z21: implemented input simulation

Dieser Commit ist enthalten in:
Reinder Feenstra 2022-05-01 13:35:44 +02:00
Ursprung 71920a5a72
Commit 14c41bf540
7 geänderte Dateien mit 75 neuen und 4 gelöschten Zeilen

Datei anzeigen

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

Datei anzeigen

@ -86,6 +86,7 @@ class Z21Interface final
std::pair<uint32_t, uint32_t> 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<uint32_t, uint32_t> outputAddressMinMax(uint32_t /*channel*/) const final { return {Z21::ClientKernel::outputAddressMin, Z21::ClientKernel::outputAddressMax}; }

Datei anzeigen

@ -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<uint32_t>(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

Datei anzeigen

@ -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<ClientKernel> create(const ClientConfig& config, Args... args)
{
static_assert(std::is_base_of_v<IOHandler, IOHandlerType>);
std::unique_ptr<ClientKernel> kernel{new ClientKernel(config)};
std::unique_ptr<ClientKernel> kernel{new ClientKernel(config, isSimulation<IOHandlerType>())};
kernel->setIOHandler(std::make_unique<IOHandlerType>(*kernel, std::forward<Args>(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);
};
}

Datei anzeigen

@ -58,6 +58,12 @@ class IOHandler
virtual void purgeClient(ClientId /*id*/) {}
};
template<class T>
constexpr bool isSimulation()
{
return false;
}
}
#endif

Datei anzeigen

@ -54,6 +54,12 @@ class SimulationIOHandler final : public IOHandler
bool send(const Message& message) final;
};
template<>
constexpr bool isSimulation<SimulationIOHandler>()
{
return true;
}
}
#endif

Datei anzeigen

@ -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<uint8_t>(1 << (index & 0x7));
}
};
static_assert(sizeof(LanRMBusDataChanged) == 15);