From 14c41bf540e9b83aca91847c82dd6551171f7cb1 Mon Sep 17 00:00:00 2001 From: Reinder Feenstra Date: Sun, 1 May 2022 13:35:44 +0200 Subject: [PATCH] z21: implemented input simulation --- .../src/hardware/interface/z21interface.cpp | 6 +++ .../src/hardware/interface/z21interface.hpp | 1 + .../hardware/protocol/z21/clientkernel.cpp | 44 ++++++++++++++++++- .../hardware/protocol/z21/clientkernel.hpp | 7 ++- .../protocol/z21/iohandler/iohandler.hpp | 6 +++ .../z21/iohandler/simulationiohandler.hpp | 6 +++ server/src/hardware/protocol/z21/messages.hpp | 9 ++++ 7 files changed, 75 insertions(+), 4 deletions(-) diff --git a/server/src/hardware/interface/z21interface.cpp b/server/src/hardware/interface/z21interface.cpp index e116e08c..f7e7c10b 100644 --- a/server/src/hardware/interface/z21interface.cpp +++ b/server/src/hardware/interface/z21interface.cpp @@ -140,6 +140,12 @@ bool Z21Interface::removeInput(Input& input) return success; } +void Z21Interface::inputSimulateChange(uint32_t channel, uint32_t address) +{ + if(m_kernel && inRange(address, outputAddressMinMax(channel))) + m_kernel->simulateInputChange(channel, address); +} + bool Z21Interface::addOutput(Output& output) { const bool success = OutputController::addOutput(output); diff --git a/server/src/hardware/interface/z21interface.hpp b/server/src/hardware/interface/z21interface.hpp index 1e3aef94..83eda85a 100644 --- a/server/src/hardware/interface/z21interface.hpp +++ b/server/src/hardware/interface/z21interface.hpp @@ -86,6 +86,7 @@ class Z21Interface final std::pair inputAddressMinMax(uint32_t channel) const final; [[nodiscard]] bool addInput(Input& input) final; [[nodiscard]] bool removeInput(Input& input) final; + void inputSimulateChange(uint32_t channel, uint32_t address) final; // OutputController: std::pair outputAddressMinMax(uint32_t /*channel*/) const final { return {Z21::ClientKernel::outputAddressMin, Z21::ClientKernel::outputAddressMax}; } diff --git a/server/src/hardware/protocol/z21/clientkernel.cpp b/server/src/hardware/protocol/z21/clientkernel.cpp index 103786be..51127b55 100644 --- a/server/src/hardware/protocol/z21/clientkernel.cpp +++ b/server/src/hardware/protocol/z21/clientkernel.cpp @@ -32,8 +32,9 @@ namespace Z21 { -ClientKernel::ClientKernel(const ClientConfig& config) - : m_keepAliveTimer(m_ioContext) +ClientKernel::ClientKernel(const ClientConfig& config, bool simulation) + : m_simulation{simulation} + , m_keepAliveTimer(m_ioContext) , m_config{config} { } @@ -349,6 +350,45 @@ bool ClientKernel::setOutput(uint16_t address, bool value) return true; } +void ClientKernel::simulateInputChange(uint32_t channel, uint32_t address) +{ + if(!m_simulation) + return; + + m_ioContext.post( + [this, channel, address]() + { + (void)address; + switch(channel) + { + case InputChannel::rbus: + { + LanRMBusDataChanged message; + message.groupIndex = (address - rbusAddressMin) / LanRMBusDataChanged::feedbackStatusCount; + + for(uint8_t i = 0; i < LanRMBusDataChanged::feedbackStatusCount; i++) + { + const uint32_t n = static_cast(message.groupIndex) * LanRMBusDataChanged::feedbackStatusCount + i; + if(address == rbusAddressMin + n) + message.setFeedbackStatus(i, m_rbusFeedbackStatus[n] != TriState::True); + else + message.setFeedbackStatus(i, m_rbusFeedbackStatus[n] == TriState::True); + } + + receive(message); + + break; + } + case InputChannel::loconet: + { + const uint16_t feedbackAddress = address - loconetAddressMin; + receive(LanLocoNetDetectorOccupancyDetector(feedbackAddress, m_loconetFeedbackStatus[feedbackAddress] != TriState::True)); + break; + } + } + }); +} + void ClientKernel::onStart() { // reset all state values diff --git a/server/src/hardware/protocol/z21/clientkernel.hpp b/server/src/hardware/protocol/z21/clientkernel.hpp index 0b9db659..59f8a27f 100644 --- a/server/src/hardware/protocol/z21/clientkernel.hpp +++ b/server/src/hardware/protocol/z21/clientkernel.hpp @@ -59,6 +59,7 @@ class ClientKernel final : public Kernel }; private: + const bool m_simulation; boost::asio::steady_timer m_keepAliveTimer; uint32_t m_serialNumber; @@ -84,7 +85,7 @@ class ClientKernel final : public Kernel ClientConfig m_config; - ClientKernel(const ClientConfig& config); + ClientKernel(const ClientConfig& config, bool simulation); void onStart() final; void onStop() final; @@ -115,7 +116,7 @@ class ClientKernel final : public Kernel static std::unique_ptr create(const ClientConfig& config, Args... args) { static_assert(std::is_base_of_v); - std::unique_ptr kernel{new ClientKernel(config)}; + std::unique_ptr kernel{new ClientKernel(config, isSimulation())}; kernel->setIOHandler(std::make_unique(*kernel, std::forward(args)...)); return kernel; } @@ -236,6 +237,8 @@ class ClientKernel final : public Kernel * @return \c true if send successful, \c false otherwise. */ bool setOutput(uint16_t address, bool value); + + void simulateInputChange(uint32_t channel, uint32_t address); }; } diff --git a/server/src/hardware/protocol/z21/iohandler/iohandler.hpp b/server/src/hardware/protocol/z21/iohandler/iohandler.hpp index eccf1617..8f747a1c 100644 --- a/server/src/hardware/protocol/z21/iohandler/iohandler.hpp +++ b/server/src/hardware/protocol/z21/iohandler/iohandler.hpp @@ -58,6 +58,12 @@ class IOHandler virtual void purgeClient(ClientId /*id*/) {} }; +template +constexpr bool isSimulation() +{ + return false; +} + } #endif diff --git a/server/src/hardware/protocol/z21/iohandler/simulationiohandler.hpp b/server/src/hardware/protocol/z21/iohandler/simulationiohandler.hpp index 26690473..1c4f6862 100644 --- a/server/src/hardware/protocol/z21/iohandler/simulationiohandler.hpp +++ b/server/src/hardware/protocol/z21/iohandler/simulationiohandler.hpp @@ -54,6 +54,12 @@ class SimulationIOHandler final : public IOHandler bool send(const Message& message) final; }; +template<> +constexpr bool isSimulation() +{ + return true; +} + } #endif diff --git a/server/src/hardware/protocol/z21/messages.hpp b/server/src/hardware/protocol/z21/messages.hpp index 07278f55..67cc4ddd 100644 --- a/server/src/hardware/protocol/z21/messages.hpp +++ b/server/src/hardware/protocol/z21/messages.hpp @@ -1274,6 +1274,15 @@ struct LanRMBusDataChanged : Message assert(index < feedbackStatusCount); return feedbackStatus[index >> 3] & (1 << (index & 0x7)); } + + inline void setFeedbackStatus(uint8_t index, bool value) + { + assert(index < feedbackStatusCount); + if(value) + feedbackStatus[index >> 3] |= (1 << (index & 0x7)); + else + feedbackStatus[index >> 3] &= ~static_cast(1 << (index & 0x7)); + } }; static_assert(sizeof(LanRMBusDataChanged) == 15);