server: Z21 add LanXExtAccessoryInfo message

- Support querying and obtaining DCCExt accessory status
Dieser Commit ist enthalten in:
Filippo Gentile 2024-05-20 14:47:50 +02:00
Ursprung 09c86cb1cc
Commit d11c40a30f
4 geänderte Dateien mit 158 neuen und 0 gelöschten Zeilen

Datei anzeigen

@ -89,6 +89,21 @@ void ClientKernel::receive(const Message& message)
}
break;
case LAN_X_EXT_ACCESSORY_INFO:
if(message.dataLen() == sizeof(LanXExtAccessoryInfo))
{
const auto& reply = static_cast<const LanXExtAccessoryInfo&>(message);
if(reply.isDataValid())
{
EventLoop::call(
[this, address=reply.address(), value=reply.aspect()]()
{
m_outputController->updateOutputValue(OutputChannel::DCCext, address, value);
});
}
}
break;
case LAN_X_BC:
if(message == LanXBCTrackPowerOff() || message == LanXBCTrackShortCircuit())
{

Datei anzeigen

@ -151,6 +151,29 @@ bool SimulationIOHandler::send(const Message& message)
}
break;
}
case LAN_X_SET_EXT_ACCESSORY:
{
if(message.dataLen() == sizeof(LanXSetExtAccessory))
{
const auto& setAccessory = static_cast<const LanXSetExtAccessory&>(message);
if((m_broadcastFlags & BroadcastFlags::PowerLocoTurnoutChanges) == BroadcastFlags::PowerLocoTurnoutChanges)
{
// Client has subscribed to turnout changes
reply(LanXExtAccessoryInfo(setAccessory.address(), setAccessory.aspect(), false));
}
}
break;
}
case LAN_X_EXT_ACCESSORY_INFO:
{
if(message.dataLen() == sizeof(LanXGetExtAccessoryInfo))
{
const auto& getAccessory = static_cast<const LanXGetExtAccessoryInfo&>(message);
//We do not keep a record of accessory states so send "Unknown Position"
reply(LanXExtAccessoryInfo(getAccessory.address(), 0, true));
}
break;
}
}
break;
}

Datei anzeigen

@ -120,6 +120,24 @@ std::string toString(const Message& message, bool raw)
s.append(" queue=").append(setTurnout.queue() ? "yes" : "no");
break;
}
case LAN_X_EXT_ACCESSORY_INFO:
{
if(message.dataLen() == sizeof(LanXExtAccessoryInfo))
{
const auto& reply = static_cast<const LanXExtAccessoryInfo&>(message);
s = "LAN_X_EXT_ACCESSORY_INFO";
s.append(" address=").append(std::to_string(reply.address()));
s.append(" aspect=").append(std::to_string(reply.aspect()));
s.append(" unknown=").append(std::to_string(!reply.isDataValid()));
}
else
{
const auto& getAccessoryInfo = static_cast<const LanXGetExtAccessoryInfo&>(message);
s = "LAN_X_GET_EXT_ACCESSORY_INFO";
s.append(" address=").append(std::to_string(getAccessoryInfo.address()));
}
break;
}
case LAN_X_SET_EXT_ACCESSORY:
{
const auto& setExtAccessory = static_cast<const LanXSetExtAccessory&>(message);

Datei anzeigen

@ -145,6 +145,8 @@ enum LocoMode : uint8_t
static constexpr uint8_t LAN_X_TURNOUT_INFO = 0x43;
static constexpr uint8_t LAN_X_SET_TURNOUT = 0x53;
static constexpr uint8_t LAN_X_EXT_ACCESSORY_INFO = 0x44;
static constexpr uint8_t LAN_X_SET_EXT_ACCESSORY = 0x54;
static constexpr uint8_t LAN_X_BC = 0x61;
@ -549,9 +551,109 @@ struct LanXSetExtAccessory : LanX
{
return rawAddress() + 3;
}
inline uint8_t aspect() const
{
return db2;
}
} ATTRIBUTE_PACKED;
static_assert(sizeof(LanXSetExtAccessory) == 10);
// LAN_X_GET_EXT_ACCESSORY_INFO
struct LanXGetExtAccessoryInfo : LanX
{
uint8_t addressMSB;
uint8_t addressLSB;
uint8_t db2 = 0x00; // Reserved for future extension, must be 0x00
uint8_t checksum;
LanXGetExtAccessoryInfo(uint16_t address)
: LanX(sizeof(LanXGetExtAccessoryInfo), LAN_X_EXT_ACCESSORY_INFO)
, addressMSB(high8(address + 3))
, addressLSB(low8(address + 3))
{
}
inline uint16_t rawAddress() const
{
return to16(addressLSB, addressMSB);
}
inline uint16_t address() const
{
return rawAddress() + 3;
}
} ATTRIBUTE_PACKED;
static_assert(sizeof(LanXGetExtAccessoryInfo) == 9);
// LAN_X_EXT_ACCESSORY_INFO
struct LanXExtAccessoryInfo : LanX
{
uint8_t addressMSB;
uint8_t addressLSB;
uint8_t db2;
uint8_t db3 = 0x00;
uint8_t checksum;
LanXExtAccessoryInfo(uint16_t address)
: LanX(sizeof(LanXExtAccessoryInfo), LAN_X_EXT_ACCESSORY_INFO)
, addressMSB(high8(address + 3))
, addressLSB(low8(address + 3))
{
}
LanXExtAccessoryInfo(uint16_t address, uint8_t aspect, bool isUnknown)
: LanXExtAccessoryInfo(address)
{
db2 = aspect;
db3 = isUnknown ? 0xFF : 0x00; // 0xFF represent Unknown Data
updateChecksum();
}
LanXExtAccessoryInfo(uint16_t address, bool dir, uint8_t powerOnTime)
: LanXExtAccessoryInfo(address)
{
assert(powerOnTime <= 127);
db2 = powerOnTime & 0x7F;
if(dir)
{
db2 |= 0x80;
}
updateChecksum();
}
inline uint16_t rawAddress() const
{
return to16(addressLSB, addressMSB);
}
inline uint16_t address() const
{
return rawAddress() + 3;
}
inline bool isDataValid() const
{
return db3 == 0x00;
}
inline uint8_t aspect() const
{
return db2;
}
inline bool direction() const
{
return db2 & 0x80;
}
inline bool powerOnTime() const
{
return db2 & 0x7F;
}
} ATTRIBUTE_PACKED;
static_assert(sizeof(LanXExtAccessoryInfo) == 10);
// LAN_X_SET_STOP
struct LanXSetStop : LanX
{