#pragma once #include #include #include #include #include "secsgem/secs2/item.hpp" // E30 ยง6.21 Limits Monitoring. // // A limit definition attaches an upper/lower deadband pair to a VID under // some limit id. Multiple definitions per VID are allowed (different // LIMITIDs can monitor different ranges). Store is pure data; the actual // "value crossed limit" detection and CEID emission is the application's // job (typically wired into the SVID/DVID set_value path). namespace secsgem::gem { namespace s2 = secsgem::secs2; // Defined here (not in the generated messages.hpp) so the data model can // own the type and the codegen can reference it as external_struct. struct LimitDefinition { uint8_t limitid; s2::Item upper; s2::Item lower; }; enum class LimitMonitorAck : uint8_t { // S2F46 VLAACK Accept = 0, LimitsNotEqualToExisting = 1, CannotChangeAttributes = 2, LimitValueError = 3, VidNotExist = 4, VidNoLimitSupport = 5, }; class LimitMonitorStore { public: void set_for_vid(uint32_t vid, std::vector defs) { by_vid_.insert_or_assign(vid, std::move(defs)); } void clear() { by_vid_.clear(); } std::vector get_for_vid(uint32_t vid) const { auto it = by_vid_.find(vid); if (it == by_vid_.end()) return {}; return it->second; } std::vector all_vids() const { std::vector out; out.reserve(by_vid_.size()); for (const auto& [vid, _] : by_vid_) out.push_back(vid); return out; } bool has(uint32_t vid) const { return by_vid_.count(vid) > 0; } std::size_t size() const { return by_vid_.size(); } private: std::map> by_vid_; }; } // namespace secsgem::gem