From 2e24be118958560cabfc6038a32130bc488efb3d Mon Sep 17 00:00:00 2001 From: "Thomas St.Pierre" Date: Sun, 1 Mar 2026 11:11:26 +0000 Subject: [PATCH] Add missing metadata fields --- src/sensesp/signalk/signalk_metadata.cpp | 49 +++++++++++++++++++++++- src/sensesp/signalk/signalk_metadata.h | 44 ++++++++++++++++++++- 2 files changed, 91 insertions(+), 2 deletions(-) diff --git a/src/sensesp/signalk/signalk_metadata.cpp b/src/sensesp/signalk/signalk_metadata.cpp index 5e61861a5..26db14fe7 100644 --- a/src/sensesp/signalk/signalk_metadata.cpp +++ b/src/sensesp/signalk/signalk_metadata.cpp @@ -1,5 +1,7 @@ #include "signalk_metadata.h" +#include + namespace sensesp { SKMetadata::SKMetadata(const String& units, const String& display_name, @@ -9,7 +11,10 @@ SKMetadata::SKMetadata(const String& units, const String& display_name, units_{units}, description_{description}, short_name_{short_name}, - timeout_{timeout} {} + timeout_{timeout}, + supports_put_{-1}, + display_scale_lower_{NAN}, + display_scale_upper_{NAN} {} void SKMetadata::add_entry(const String& sk_path, JsonArray& meta) { JsonObject json = meta.add(); @@ -35,6 +40,48 @@ void SKMetadata::add_entry(const String& sk_path, JsonArray& meta) { if (this->timeout_ >= 0.0) { val["timeout"] = this->timeout_; } + + if (!this->example_.isEmpty()) { + val["example"] = this->example_; + } + + if (this->supports_put_ != -1) { + val["supportsPut"] = (this->supports_put_ == 1); + } + + if (!std::isnan(this->display_scale_lower_) || + !std::isnan(this->display_scale_upper_)) { + JsonObject scale = val["displayScale"].to(); + if (!std::isnan(this->display_scale_lower_)) { + scale["lower"] = this->display_scale_lower_; + } + if (!std::isnan(this->display_scale_upper_)) { + scale["upper"] = this->display_scale_upper_; + } + } + + if (!this->zones_.empty()) { + JsonArray zones_arr = val["zones"].to(); + for (const SKZone& zone : this->zones_) { + JsonObject zone_obj = zones_arr.add(); + zone_obj["state"] = alarm_state_to_string(zone.state_); + zone_obj["message"] = zone.message_; + if (!std::isnan(zone.lower_)) zone_obj["lower"] = zone.lower_; + if (!std::isnan(zone.upper_)) zone_obj["upper"] = zone.upper_; + } + } +} + +const char* SKMetadata::alarm_state_to_string(SKAlarmState state) { + switch (state) { + case SKAlarmState::kNominal: return "nominal"; + case SKAlarmState::kNormal: return "normal"; + case SKAlarmState::kAlert: return "alert"; + case SKAlarmState::kWarn: return "warn"; + case SKAlarmState::kAlarm: return "alarm"; + case SKAlarmState::kEmergency: return "emergency"; + default: return "normal"; + } } } // namespace sensesp diff --git a/src/sensesp/signalk/signalk_metadata.h b/src/sensesp/signalk/signalk_metadata.h index c494488bd..7f394037c 100644 --- a/src/sensesp/signalk/signalk_metadata.h +++ b/src/sensesp/signalk/signalk_metadata.h @@ -2,9 +2,39 @@ #define SENSESP_SIGNALK_SIGNALK_METADATA_H_ #include +#include +#include namespace sensesp { +/** + * @brief Alarm state values for Signal K Zone metadata. + * @see https://demo.signalk.org/documentation/_signalk/server-api/ALARM_STATE.html + */ +enum class SKAlarmState { + kNominal, + kNormal, + kAlert, + kWarn, + kAlarm, + kEmergency +}; + +/** + * @brief Represents a single Signal K alarm zone within metadata. + * @see https://demo.signalk.org/documentation/_signalk/server-api/Zone.html + */ +struct SKZone { + float lower_; ///< Lower bound of the zone; NAN if not set + float upper_; ///< Upper bound of the zone; NAN if not set + String message_; + SKAlarmState state_; + + SKZone(SKAlarmState state, const String& message, + float lower = NAN, float upper = NAN) + : lower_{lower}, upper_{upper}, message_{message}, state_{state} {} +}; + /** * @brief Holds Signal K meta data that is associated with * the sk_path an SKEmitter class may optionally send to the server. @@ -28,6 +58,11 @@ class SKMetadata { String description_; String short_name_; float timeout_; + String example_; + int supports_put_; ///< -1 = not set, 0 = false, 1 = true + float display_scale_lower_; ///< NAN = not set + float display_scale_upper_; ///< NAN = not set + std::vector zones_; /** * @param units The unit of measurement the value represents. See @@ -49,7 +84,11 @@ class SKMetadata { float timeout = -1.0); /// Default constructor creates a blank Metadata structure - SKMetadata() : timeout_{-1} {} + SKMetadata() + : timeout_{-1}, + supports_put_{-1}, + display_scale_lower_{NAN}, + display_scale_upper_{NAN} {} /** * Adds an entry to the specified meta array that represents this metadata @@ -59,6 +98,9 @@ class SKMetadata { * @param[out] meta The array the metadata entry is supposed to be added to */ virtual void add_entry(const String& sk_path, JsonArray& meta); + + private: + static const char* alarm_state_to_string(SKAlarmState state); }; } // namespace sensesp