diff --git a/server/src/core/idobject.cpp b/server/src/core/idobject.cpp index 5a3be06c..344debe7 100644 --- a/server/src/core/idobject.cpp +++ b/server/src/core/idobject.cpp @@ -27,7 +27,11 @@ IdObject::IdObject(const std::weak_ptr& world, std::string_view _id) : Object{}, m_world{world}, - id{this, "id", std::string(_id.data(), _id.size()), PropertyFlags::ReadWrite | PropertyFlags::Store, nullptr, + id{this, "id", std::string(_id.data(), _id.size()), PropertyFlags::ReadWrite | PropertyFlags::Store, + [this](const std::string& value) + { + idChanged(value); + }, [this](std::string& value) { auto w = getWorld(this); diff --git a/server/src/core/idobject.hpp b/server/src/core/idobject.hpp index d436ce42..3087a49b 100644 --- a/server/src/core/idobject.hpp +++ b/server/src/core/idobject.hpp @@ -45,6 +45,7 @@ class IdObject : public Object IdObject(const std::weak_ptr& world, std::string_view _id); virtual void addToWorld(); void worldEvent(WorldState state, WorldEvent event) override; + virtual void idChanged(const std::string& id) {} public: Property id; diff --git a/server/src/core/session.cpp b/server/src/core/session.cpp index b7d5524e..93d0419e 100644 --- a/server/src/core/session.cpp +++ b/server/src/core/session.cpp @@ -698,7 +698,7 @@ void Session::writeAttribute(Message& message , const AbstractAttribute& attribu assert(false); } -void Session::inputMonitorInputIdChanged(InputMonitor& inputMonitor, uint32_t address, const std::string& id) +void Session::inputMonitorInputIdChanged(InputMonitor& inputMonitor, const uint32_t address, const std::string_view id) { auto event = Message::newEvent(Message::Command::InputMonitorInputIdChanged); event->write(m_handles.getHandle(inputMonitor.shared_from_this())); @@ -707,7 +707,7 @@ void Session::inputMonitorInputIdChanged(InputMonitor& inputMonitor, uint32_t ad m_client->sendMessage(std::move(event)); } -void Session::inputMonitorInputValueChanged(InputMonitor& inputMonitor, uint32_t address, TriState value) +void Session::inputMonitorInputValueChanged(InputMonitor& inputMonitor, const uint32_t address, const TriState value) { auto event = Message::newEvent(Message::Command::InputMonitorInputValueChanged); event->write(m_handles.getHandle(inputMonitor.shared_from_this())); diff --git a/server/src/core/session.hpp b/server/src/core/session.hpp index 597f12d9..4111f308 100644 --- a/server/src/core/session.hpp +++ b/server/src/core/session.hpp @@ -62,7 +62,7 @@ class Session : public std::enable_shared_from_this void objectPropertyChanged(AbstractProperty& property); void objectAttributeChanged(AbstractAttribute& attribute); - void inputMonitorInputIdChanged(InputMonitor& inputMonitor, uint32_t address, const std::string& id); + void inputMonitorInputIdChanged(InputMonitor& inputMonitor, uint32_t address, std::string_view id); void inputMonitorInputValueChanged(InputMonitor& inputMonitor, uint32_t address, TriState value); public: diff --git a/server/src/hardware/input/input.cpp b/server/src/hardware/input/input.cpp index 3199cd58..f0cbcc4d 100644 --- a/server/src/hardware/input/input.cpp +++ b/server/src/hardware/input/input.cpp @@ -28,7 +28,11 @@ Input::Input(const std::weak_ptr world, std::string_view _id) : IdObject(world, _id), name{this, "name", "", PropertyFlags::ReadWrite | PropertyFlags::Store}, - value{this, "value", TriState::Undefined, PropertyFlags::ReadOnly | PropertyFlags::StoreState} + value{this, "value", TriState::Undefined, PropertyFlags::ReadOnly | PropertyFlags::StoreState, + [this](TriState _value) + { + valueChanged(_value); + }} { auto w = world.lock(); const bool editable = w && contains(w->state.value(), WorldState::Edit); @@ -56,7 +60,7 @@ void Input::worldEvent(WorldState state, WorldEvent event) name.setAttributeEnabled(editable); } -void Input::valueChanged(TriState _value) +void Input::updateValue(TriState _value) { // todo: delay in ms for 0->1 || 1->0 value.setValueInternal(_value); diff --git a/server/src/hardware/input/input.hpp b/server/src/hardware/input/input.hpp index a51eb398..adbc8201 100644 --- a/server/src/hardware/input/input.hpp +++ b/server/src/hardware/input/input.hpp @@ -31,8 +31,9 @@ class Input : public IdObject protected: void addToWorld() override; void worldEvent(WorldState state, WorldEvent event) override; + virtual void valueChanged(TriState _value) {} - void valueChanged(TriState _value); + void updateValue(TriState _value); public: Property name; diff --git a/server/src/hardware/input/inputmonitor.hpp b/server/src/hardware/input/inputmonitor.hpp index b66a5efc..105e6f10 100644 --- a/server/src/hardware/input/inputmonitor.hpp +++ b/server/src/hardware/input/inputmonitor.hpp @@ -31,7 +31,7 @@ class InputMonitor : public Object { public: - std::function inputIdChanged; + std::function inputIdChanged; std::function inputValueChanged; struct InputInfo diff --git a/server/src/hardware/input/loconetinput.cpp b/server/src/hardware/input/loconetinput.cpp index eec7177e..efef37ef 100644 --- a/server/src/hardware/input/loconetinput.cpp +++ b/server/src/hardware/input/loconetinput.cpp @@ -66,3 +66,15 @@ void LocoNetInput::worldEvent(WorldState state, WorldEvent event) loconet.setAttributeEnabled(editable); address.setAttributeEnabled(editable); } + +void LocoNetInput::idChanged(const std::string& id) +{ + if(loconet) + loconet->inputMonitorIdChanged(address, id); +} + +void LocoNetInput::valueChanged(TriState _value) +{ + if(loconet) + loconet->inputMonitorValueChanged(address, _value); +} diff --git a/server/src/hardware/input/loconetinput.hpp b/server/src/hardware/input/loconetinput.hpp index d95c954f..e04ff134 100644 --- a/server/src/hardware/input/loconetinput.hpp +++ b/server/src/hardware/input/loconetinput.hpp @@ -33,8 +33,10 @@ class LocoNetInput : public Input protected: void worldEvent(WorldState state, WorldEvent event) final; + void idChanged(const std::string& id) final; + void valueChanged(TriState _value) final; - inline void valueChanged(TriState _value) { Input::valueChanged(_value); } + inline void updateValue(TriState _value) { Input::updateValue(_value); } public: CLASS_ID("input.loconet") diff --git a/server/src/hardware/protocol/loconet/loconet.cpp b/server/src/hardware/protocol/loconet/loconet.cpp index 6348f060..e2904832 100644 --- a/server/src/hardware/protocol/loconet/loconet.cpp +++ b/server/src/hardware/protocol/loconet/loconet.cpp @@ -223,11 +223,9 @@ void LocoNet::receive(const Message& message) const uint16_t address = 1 + inputRep.fullAddress(); auto it = m_inputs.find(address); if(it != m_inputs.end()) - it->second->valueChanged(toTriState(inputRep.value())); - - for(auto* inputMonitor : m_inputMonitors) - if(inputMonitor->inputValueChanged) - inputMonitor->inputValueChanged(*inputMonitor, address, toTriState(inputRep.value())); + it->second->updateValue(toTriState(inputRep.value())); + else + inputMonitorValueChanged(address, toTriState(inputRep.value())); }); break; @@ -408,6 +406,8 @@ bool LocoNet::changeInputAddress(const LocoNetInput& input, uint16_t newAddress) auto node = m_inputs.extract(input.address); // old address node.key() = newAddress; m_inputs.insert(std::move(node)); + inputMonitorIdChanged(input.address, {}); + inputMonitorIdChanged(newAddress, input.id.value()); return true; } @@ -418,6 +418,7 @@ bool LocoNet::addInput(const std::shared_ptr& input) if(isInputAddressAvailable(input->address)) { m_inputs.insert({input->address, input}); + inputMonitorIdChanged(input->address, input->id.value()); return true; } else @@ -427,7 +428,23 @@ bool LocoNet::addInput(const std::shared_ptr& input) void LocoNet::removeInput(const std::shared_ptr& input) { assert(input && input->loconet.value().get() == this); + const uint16_t address = input->address; m_inputs.erase(m_inputs.find(input->address)); + inputMonitorIdChanged(address, {}); +} + +void LocoNet::inputMonitorIdChanged(const uint32_t address, const std::string_view value) +{ + for(auto* inputMonitor : m_inputMonitors) + if(inputMonitor->inputIdChanged) + inputMonitor->inputIdChanged(*inputMonitor, address, value); +} + +void LocoNet::inputMonitorValueChanged(const uint32_t address, const TriState value) +{ + for(auto* inputMonitor : m_inputMonitors) + if(inputMonitor->inputValueChanged) + inputMonitor->inputValueChanged(*inputMonitor, address, value); } } diff --git a/server/src/hardware/protocol/loconet/loconet.hpp b/server/src/hardware/protocol/loconet/loconet.hpp index adf92767..0d4f9c0c 100644 --- a/server/src/hardware/protocol/loconet/loconet.hpp +++ b/server/src/hardware/protocol/loconet/loconet.hpp @@ -122,6 +122,8 @@ class LocoNet : public SubObject bool changeInputAddress(const LocoNetInput& input, uint16_t newAddress); bool addInput(const std::shared_ptr& input); void removeInput(const std::shared_ptr& input); + void inputMonitorIdChanged(uint32_t address, std::string_view value); + void inputMonitorValueChanged(uint32_t address, TriState value); public: CLASS_ID("protocol.loconet")