loconet: input monitor

- implemented id change
- route input value change via input if known (for future change delay/invert)
Dieser Commit ist enthalten in:
Reinder Feenstra 2020-10-19 23:35:22 +02:00
Ursprung 7866c60f75
Commit c77c370a2a
11 geänderte Dateien mit 57 neuen und 14 gelöschten Zeilen

Datei anzeigen

@ -27,7 +27,11 @@
IdObject::IdObject(const std::weak_ptr<World>& 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);

Datei anzeigen

@ -45,6 +45,7 @@ class IdObject : public Object
IdObject(const std::weak_ptr<World>& world, std::string_view _id);
virtual void addToWorld();
void worldEvent(WorldState state, WorldEvent event) override;
virtual void idChanged(const std::string& id) {}
public:
Property<std::string> id;

Datei anzeigen

@ -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()));

Datei anzeigen

@ -62,7 +62,7 @@ class Session : public std::enable_shared_from_this<Session>
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:

Datei anzeigen

@ -28,7 +28,11 @@
Input::Input(const std::weak_ptr<World> 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);

Datei anzeigen

@ -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<std::string> name;

Datei anzeigen

@ -31,7 +31,7 @@
class InputMonitor : public Object
{
public:
std::function<void(InputMonitor&, uint32_t, const std::string&)> inputIdChanged;
std::function<void(InputMonitor&, uint32_t, std::string_view)> inputIdChanged;
std::function<void(InputMonitor&, uint32_t, TriState)> inputValueChanged;
struct InputInfo

Datei anzeigen

@ -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);
}

Datei anzeigen

@ -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")

Datei anzeigen

@ -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<LocoNetInput>& 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<LocoNetInput>& input)
void LocoNet::removeInput(const std::shared_ptr<LocoNetInput>& 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);
}
}

Datei anzeigen

@ -122,6 +122,8 @@ class LocoNet : public SubObject
bool changeInputAddress(const LocoNetInput& input, uint16_t newAddress);
bool addInput(const std::shared_ptr<LocoNetInput>& input);
void removeInput(const std::shared_ptr<LocoNetInput>& input);
void inputMonitorIdChanged(uint32_t address, std::string_view value);
void inputMonitorValueChanged(uint32_t address, TriState value);
public:
CLASS_ID("protocol.loconet")