Index: CloudConnect/CloudConnectController.cpp =================================================================== diff -u -rb915ccc1a72fcca21908c35140af7ac7df1f1f37 -rcaca75be9a284ac5f98c078ec47c2e826ac5e980 --- CloudConnect/CloudConnectController.cpp (.../CloudConnectController.cpp) (revision b915ccc1a72fcca21908c35140af7ac7df1f1f37) +++ CloudConnect/CloudConnectController.cpp (.../CloudConnectController.cpp) (revision caca75be9a284ac5f98c078ec47c2e826ac5e980) @@ -37,7 +37,7 @@ _canInterface.init(_canThread); connect(&_canInterface, &Can::CanInterface::didFrameReceive, this, &CloudConnectController::onFrameReceive); connect(&_dispatcher, &Can::MessageDispatcher::didActionReceive, this, &CloudConnectController::onMessageReceive); - connect(&_agentInterface, &RtInterface::didDisconnect, this, &CloudConnectController::onAgentDisconnect); + connect(&_agentInterface, &CloudConnectClient::didDisconnect, this, &CloudConnectController::onAgentDisconnect); } /*! @@ -55,12 +55,12 @@ /*! * \brief CloudConnectController::connectToAgent - * \details Initialises the RtInterface using the socket path and reconnect + * \details Initialises the CloudConnectClient using the socket path and reconnect * interval from the settings file. */ void CloudConnectController::connectToAgent() { - const QString socketPath = _settings.value("Socket/LocalSocketName", "/tmp/leahi_rt.sock").toString(); + const QString socketPath = _settings.value("Socket/AgentSocketName", "/tmp/cloudconnect_agent.sock").toString(); const int reconnectIntervalMs = _settings.value("Socket/ReconnectIntervalMs", 5000).toInt(); _agentInterface.init(socketPath, reconnectIntervalMs, _agentThread); } @@ -73,7 +73,7 @@ */ bool CloudConnectController::listenForApp() { - const QString appSocketPath = _settings.value("Socket/AppSocketName", "/tmp/leahi_app.sock").toString(); + const QString appSocketPath = _settings.value("Socket/AppSocketName", "/tmp/cloudconnect_app.sock").toString(); return _appServer.listen(appSocketPath); } @@ -90,15 +90,15 @@ { QStringLiteral("send_delta"), MsgAction::SendDelta }, { QStringLiteral("drop"), MsgAction::Drop }, }; - static const QHash topicMap = { - { QStringLiteral("ClinicalData"), RtMessage::MsgId::ClinicalData }, - { QStringLiteral("Diagnostic"), RtMessage::MsgId::Diagnostic }, - { QStringLiteral("Ack"), RtMessage::MsgId::Ack }, - { QStringLiteral("Alarms"), RtMessage::MsgId::Alarms }, - { QStringLiteral("Audit"), RtMessage::MsgId::Audit }, - { QStringLiteral("DeviceLogFile"), RtMessage::MsgId::DeviceLogFile }, - { QStringLiteral("TreatmentLogFile"), RtMessage::MsgId::TreatmentLogFile }, - { QStringLiteral("CloudSyncLogFile"), RtMessage::MsgId::CloudSyncLogFile }, + static const QHash topicMap = { + { QStringLiteral("ClinicalData"), CloudConnectFrame::MsgId::ClinicalData }, + { QStringLiteral("Diagnostic"), CloudConnectFrame::MsgId::Diagnostic }, + { QStringLiteral("Ack"), CloudConnectFrame::MsgId::Ack }, + { QStringLiteral("Alarms"), CloudConnectFrame::MsgId::Alarms }, + { QStringLiteral("Audit"), CloudConnectFrame::MsgId::Audit }, + { QStringLiteral("DeviceLogFile"), CloudConnectFrame::MsgId::DeviceLogFile }, + { QStringLiteral("TreatmentLogFile"), CloudConnectFrame::MsgId::TreatmentLogFile }, + { QStringLiteral("CloudSyncLogFile"), CloudConnectFrame::MsgId::CloudSyncLogFile }, }; QSettings msgHandlingIni(msgHandlingPath, QSettings::IniFormat); @@ -122,7 +122,7 @@ MsgHandling msgHandling; msgHandling.action = actionMap.value(actionStr, MsgAction::Drop); - msgHandling.topic = topicMap.value(topicStr, RtMessage::MsgId::ClinicalData); + msgHandling.topic = topicMap.value(topicStr, CloudConnectFrame::MsgId::ClinicalData); if (!actionMap.contains(actionStr)) { qWarning().noquote() << QString("CloudConnect: unknown message action \"%1\" for msgId=0x%2 — defaulting to drop") @@ -150,7 +150,7 @@ * \brief CloudConnectController::onMessageReceive * \details Applies the message handling policy from LeahiMsgHandling.ini: drops, * forwards unconditionally, or forwards only on payload change. Uses the - * section's topic to set the RtMessage frame msg_id. + * section's topic to set the CloudConnectFrame frame msg_id. * \param msg - the reassembled message */ void CloudConnectController::onMessageReceive(const Can::Message &msg) Index: CloudConnect/CloudConnectController.h =================================================================== diff -u -rb915ccc1a72fcca21908c35140af7ac7df1f1f37 -rcaca75be9a284ac5f98c078ec47c2e826ac5e980 --- CloudConnect/CloudConnectController.h (.../CloudConnectController.h) (revision b915ccc1a72fcca21908c35140af7ac7df1f1f37) +++ CloudConnect/CloudConnectController.h (.../CloudConnectController.h) (revision caca75be9a284ac5f98c078ec47c2e826ac5e980) @@ -22,17 +22,17 @@ #include #include -#include "RtInterface.h" -#include "RtMessage.h" +#include "CloudConnectClient.h" +#include "CloudConnectFrame.h" #include "CanInterface.h" #include "CanMessage.h" -#include "RtServer.h" +#include "CloudConnectServer.h" #include "MessageDispatcher.h" using namespace Can; /*! - * \brief Real-time Cloud Communications controller + * \brief CloudConnect controller */ class CloudConnectController : public QObject { @@ -59,17 +59,17 @@ * \brief Send message handling policy for a CAN message. */ enum class MsgAction { - Drop, ///< Discard the message; do not forward to the Agent. - SendAlways, ///< Forward unconditionally. - SendDelta, ///< Forward only when the payload has changed since the last send. + Drop, + SendAlways, + SendDelta, }; /*! * \brief Message handling entry loaded from message handling INI. */ struct MsgHandling { MsgAction action = MsgAction::Drop; - RtMessage::MsgId topic = RtMessage::MsgId::ClinicalData; + CloudConnectFrame::MsgId topic = CloudConnectFrame::MsgId::ClinicalData; }; void loadMsgHandling(const QString &msgHandlingPath); @@ -80,9 +80,9 @@ Can::MessageDispatcher _dispatcher; QMap> _msgCache; QHash _msgHandling; - RtInterface _agentInterface; + CloudConnectClient _agentInterface; QThread _agentThread; - RtServer _appServer; ///< The Luis application connects here. + CloudConnectServer _appServer; quint16 _txSequence = 0; private Q_SLOTS: Index: CloudConnect/config/CloudConnect.ini =================================================================== diff -u -rb915ccc1a72fcca21908c35140af7ac7df1f1f37 -rcaca75be9a284ac5f98c078ec47c2e826ac5e980 --- CloudConnect/config/CloudConnect.ini (.../CloudConnect.ini) (revision b915ccc1a72fcca21908c35140af7ac7df1f1f37) +++ CloudConnect/config/CloudConnect.ini (.../CloudConnect.ini) (revision caca75be9a284ac5f98c078ec47c2e826ac5e980) @@ -1,4 +1,4 @@ [Socket] -LocalSocketName=/tmp/leahi_rt.sock -AppSocketName=/tmp/leahi_app.sock +AgentSocketName=/tmp/cloudconnect_agent.sock +AppSocketName=/tmp/cloudconnect_app.sock ReconnectIntervalMs=5000 Index: CloudConnect/config/LeahiMsgHandling.ini =================================================================== diff -u --- CloudConnect/config/LeahiMsgHandling.ini (revision 0) +++ CloudConnect/config/LeahiMsgHandling.ini (revision caca75be9a284ac5f98c078ec47c2e826ac5e980) @@ -0,0 +1,2370 @@ +[0x0000] +msg_id = MSG_ID_UNUSED +action = drop +topic = + +[0x0080] +msg_id = MSG_ID_TESTER_LOGIN_REQUEST +action = drop +topic = + +[0x00A0] +msg_id = MSG_ID_DD_TESTER_LOGIN_REQUEST +action = drop +topic = + +[0x00B0] +msg_id = MSG_ID_FP_TESTER_LOGIN_REQUEST +action = drop +topic = + +[0x0100] +msg_id = MSG_ID_ALARM_STATUS_DATA +action = drop +topic = + +[0x0180] +msg_id = MSG_ID_TD_SOFTWARE_RESET_REQUEST +action = drop +topic = + +[0x01A0] +msg_id = MSG_ID_DD_SOFTWARE_RESET_REQUEST +action = drop +topic = + +[0x01B0] +msg_id = MSG_ID_FP_SOFTWARE_RESET_REQUEST +action = drop +topic = + +[0x0200] +msg_id = MSG_ID_ALARM_TRIGGERED +action = drop +topic = + +[0x0280] +msg_id = MSG_ID_TD_SEND_TEST_CONFIGURATION +action = drop +topic = + +[0x02A0] +msg_id = MSG_ID_DD_SEND_TEST_CONFIGURATION +action = drop +topic = + +[0x02B0] +msg_id = MSG_ID_FP_SEND_TEST_CONFIGURATION +action = drop +topic = + +[0x0300] +msg_id = MSG_ID_ALARM_CLEARED +action = drop +topic = + +[0x0380] +msg_id = MSG_ID_TD_BUBBLE_OVERRIDE_REQUEST +action = drop +topic = + +[0x03A0] +msg_id = MSG_ID_DD_VALVE_PUBLISH_INTERVAL_OVERRIDE_REQUEST +action = drop +topic = + +[0x03B0] +msg_id = MSG_ID_FP_VALVE_PUBLISH_INTERVAL_OVERRIDE_REQUEST +action = drop +topic = + +[0x0400] +msg_id = MSG_ID_ALARM_CONDITION_CLEARED +action = drop +topic = + +[0x0480] +msg_id = MSG_ID_TD_VOLTAGE_PUBLISH_INTERVAL_OVERRIDE_REQUEST +action = drop +topic = + +[0x04A0] +msg_id = MSG_ID_DD_VALVE_STATE_OVERRIDE_REQUEST +action = drop +topic = + +[0x04B0] +msg_id = MSG_ID_FP_VALVE_CMD_STATE_OVERRIDE_REQUEST +action = drop +topic = + +[0x0500] +msg_id = MSG_ID_USER_ALARM_SILENCE_REQUEST +action = drop +topic = + +[0x0580] +msg_id = MSG_ID_TD_VOLTAGE_OVERRIDE_REQUEST +action = drop +topic = + +[0x05A0] +msg_id = MSG_ID_DD_VALVE_SENSED_STATE_OVERRIDE_REQUEST +action = drop +topic = + +[0x05B0] +msg_id = MSG_ID_FP_VALVE_SENSED_STATE_OVERRIDE_REQUEST +action = drop +topic = + +[0x0600] +msg_id = MSG_ID_UI_ALARM_USER_ACTION_REQUEST +action = drop +topic = + +[0x0680] +msg_id = MSG_ID_TD_BUBBLE_PUBLISH_INTERVAL_OVERRIDE_REQUEST +action = drop +topic = + +[0x06A0] +msg_id = MSG_ID_DD_PRESSURE_SENSOR_READINGS_OVERRIDE_REQUEST +action = drop +topic = + +[0x06B0] +msg_id = MSG_ID_FP_FLUID_PUMP_SET_PWM_REQUEST +action = drop +topic = + +[0x0700] +msg_id = MSG_ID_TD_ALARM_INFORMATION_DATA +action = drop +topic = + +[0x0780] +msg_id = MSG_ID_TD_PRESSURE_OVERRIDE_REQUEST +action = drop +topic = + +[0x07A0] +msg_id = MSG_ID_DD_PRESSURE_SENSOR_TEMPERATURE_OVERRIDE_REQUEST +action = drop +topic = + +[0x07B0] +msg_id = MSG_ID_FP_FLUID_PUMP_READ_PWM_OVERRIDE_REQUEST +action = drop +topic = + +[0x0800] +msg_id = MSG_ID_DD_ALARM_INFO_DATA +action = drop +topic = + +[0x0880] +msg_id = MSG_ID_TD_AIR_PUMP_SET_STATE_REQUEST +action = drop +topic = + +[0x08A0] +msg_id = MSG_ID_DD_PRESSURE_SENSOR_READ_COUNTER_OVERRIDE_REQUEST +action = drop +topic = + +[0x08B0] +msg_id = MSG_ID_FP_FLUID_PUMP_SPEED_OVERRIDE_REQUEST +action = drop +topic = + +[0x0900] +msg_id = MSG_ID_UI_ACTIVE_ALARMS_LIST_REQUEST +action = drop +topic = + +[0x0980] +msg_id = MSG_ID_TD_AIR_PUMP_PUBLISH_INTERVAL_OVERRIDE_REQUEST +action = drop +topic = + +[0x09A0] +msg_id = MSG_ID_DD_PRESSURE_SENSOR_ERROR_COUNTER_OVERRIDE_REQUEST +action = drop +topic = + +[0x09B0] +msg_id = MSG_ID_FP_RO_PUMP_PUBLISH_INTERVAL_OVERRIDE_REQUEST +action = drop +topic = + +[0x0A00] +msg_id = MSG_ID_TD_ACTIVE_ALARMS_LIST_REQUEST_RESPONSE +action = drop +topic = + +[0x0A80] +msg_id = MSG_ID_TD_SWITCHES_PUBLISH_INTERVAL_OVERRIDE_REQUEST +action = drop +topic = + +[0x0AA0] +msg_id = MSG_ID_DD_PRESSURE_SENSOR_PUBLISH_INTERVAL_OVERRIDE_REQUEST +action = drop +topic = + +[0x0AB0] +msg_id = MSG_ID_FP_PRESSURE_OVERRIDE_REQUEST +action = drop +topic = + +[0x0B00] +msg_id = MSG_ID_UI_SET_ALARM_AUDIO_VOLUME_LEVEL_CMD_REQUEST +action = drop +topic = + +[0x0B80] +msg_id = MSG_ID_TD_SWITCH_STATE_OVERRIDE_REQUEST +action = drop +topic = + +[0x0BA0] +msg_id = MSG_ID_DD_PRESSURE_SENSOR_FILTER_READINGS_OVERRIDE_REQUEST +action = drop +topic = + +[0x0BB0] +msg_id = MSG_ID_FP_PRESSURE_TEMP_OVERRIDE_REQUEST +action = drop +topic = + +[0x0C00] +msg_id = MSG_ID_TD_ALARM_AUDIO_VOLUME_SET_RESPONSE +action = drop +topic = + +[0x0C80] +msg_id = MSG_ID_TD_OFF_BUTTON_OVERRIDE_REQUEST +action = drop +topic = + +[0x0CA0] +msg_id = MSG_ID_DD_PRESSURE_SENSOR_FILTER_TEMPERATURE_OVERRIDE_REQUEST +action = drop +topic = + +[0x0CB0] +msg_id = MSG_ID_FP_PRESSURE_SENSOR_FILTER_READINGS_OVERRIDE_REQUEST +action = drop +topic = + +[0x0D00] +msg_id = MSG_ID_FW_VERSIONS_REQUEST +action = drop +topic = + +[0x0D80] +msg_id = MSG_ID_TD_STOP_BUTTON_OVERRIDE_REQUEST +action = drop +topic = + +[0x0DA0] +msg_id = MSG_ID_DD_CONDUCTIVITY_SENSOR_READINGS_OVERRIDE_REQUEST +action = drop +topic = + +[0x0DB0] +msg_id = MSG_ID_FP_PRESSURE_SENSOR_FILTER_TEMPERATURE_OVERRIDE_REQUEST +action = drop +topic = + +[0x0E00] +msg_id = MSG_ID_TD_VERSION_RESPONSE +action = drop +topic = + +[0x0E80] +msg_id = MSG_ID_TD_ALARM_LAMP_PATTERN_OVERRIDE_REQUEST +action = drop +topic = + +[0x0EA0] +msg_id = MSG_ID_DD_CONDUCTIVITY_SENSOR_TEMPERATURE_OVERRIDE_REQUEST +action = drop +topic = + +[0x0EB0] +msg_id = MSG_ID_FP_PRESSURE_PUBLISH_INTERVAL_OVERRIDE_REQUEST +action = drop +topic = + +[0x0F00] +msg_id = MSG_ID_DD_VERSION_RESPONSE +action = drop +topic = + +[0x0F80] +msg_id = MSG_ID_TD_ALARM_AUDIO_LEVEL_OVERRIDE_REQUEST +action = drop +topic = + +[0x0FA0] +msg_id = MSG_ID_DD_CONDUCTIVITY_SENSOR_CONDUCTIVITY_READ_COUNTER_OVERRIDE_REQUEST +action = drop +topic = + +[0x0FB0] +msg_id = MSG_ID_FP_LEVEL_PUBLISH_INTERVAL_OVERRIDE_REQUEST +action = drop +topic = + +[0x1000] +msg_id = MSG_ID_UI_CHECK_IN +action = drop +topic = + +[0x1080] +msg_id = MSG_ID_TD_ALARM_AUDIO_CURRENT_HG_OVERRIDE_REQUEST +action = drop +topic = + +[0x10A0] +msg_id = MSG_ID_DD_CONDUCTIVITY_SENSOR_CONDUCTIVITY_ERROR_COUNTER_OVERRIDE_REQUEST +action = drop +topic = + +[0x10B0] +msg_id = MSG_ID_FP_FLOATER_LEVEL_OVERRIDE_REQUEST +action = drop +topic = + +[0x1100] +msg_id = MSG_ID_TD_BLOOD_PUMP_DATA +action = drop +topic = + +[0x1180] +msg_id = MSG_ID_TD_ALARM_AUDIO_CURRENT_LG_OVERRIDE_REQUEST +action = drop +topic = + +[0x11A0] +msg_id = MSG_ID_DD_CONDUCTIVITY_SENSOR_PUBLISH_INTERVAL_OVERRIDE_REQUEST +action = drop +topic = + +[0x11B0] +msg_id = MSG_ID_FP_FLOWS_PUBLISH_INTERVAL_OVERRIDE_REQUEST +action = drop +topic = + +[0x1200] +msg_id = MSG_ID_TD_OP_MODE_DATA +action = drop +topic = + +[0x1280] +msg_id = MSG_ID_TD_BACKUP_ALARM_AUDIO_CURRENT_OVERRIDE_REQUEST +action = drop +topic = + +[0x12A0] +msg_id = MSG_ID_DD_CONCENTRATE_PUMP_PUBLISH_INTERVAL_OVERRIDE_REQUEST +action = drop +topic = + +[0x12B0] +msg_id = MSG_ID_FP_FLOW_RATE_OVERRIDE_REQUEST +action = drop +topic = + +[0x1300] +msg_id = MSG_ID_DD_OP_MODE_DATA +action = drop +topic = + +[0x1380] +msg_id = MSG_ID_TD_PRESSURE_PUBLISH_INTERVAL_OVERRIDE_REQUEST +action = drop +topic = + +[0x13A0] +msg_id = MSG_ID_DD_CONCENTRATE_PUMP_TARGET_SPEED_OVERRIDE_REQUEST +action = drop +topic = + +[0x13B0] +msg_id = MSG_ID_FP_FLOW_TEMP_OVERRIDE_REQUEST +action = drop +topic = + +[0x1400] +msg_id = MSG_ID_DD_COMMAND_RESPONSE +action = drop +topic = + +[0x1480] +msg_id = MSG_ID_TD_AIR_TRAP_LEVEL_OVERRIDE_REQUEST +action = drop +topic = + +[0x14A0] +msg_id = MSG_ID_DD_CONCENTRATE_PUMP_MEASURED_SPEED_OVERRIDE_REQUEST +action = drop +topic = + +[0x14B0] +msg_id = MSG_ID_FP_CONDUCTIVITY_PUBLISH_INTERVAL_OVERRIDE_REQUEST +action = drop +topic = + +[0x1500] +msg_id = MSG_ID_TD_UI_VERSION_INFO_REQUEST +action = drop +topic = + +[0x1580] +msg_id = MSG_ID_TD_AIR_TRAP_LEVEL_RAW_OVERRIDE_REQUEST +action = drop +topic = + +[0x15A0] +msg_id = MSG_ID_DD_CONCENTRATE_PUMP_PARKED_OVERRIDE_REQUEST +action = drop +topic = + +[0x15B0] +msg_id = MSG_ID_FP_CONDUCTIVITY_SENSOR_READINGS_OVERRIDE_REQUEST +action = drop +topic = + +[0x1600] +msg_id = MSG_ID_UI_VERSION_INFO_RESPONSE +action = drop +topic = + +[0x1680] +msg_id = MSG_ID_TD_AIR_TRAP_PUBLISH_INTERVAL_OVERRIDE_REQUEST +action = drop +topic = + +[0x16A0] +msg_id = MSG_ID_DD_CONCENTRATE_PUMP_PARK_FAULT_OVERRIDE_REQUEST +action = drop +topic = + +[0x16B0] +msg_id = MSG_ID_FP_CONDUCTIVITY_SENSOR_TEMPERATURE_OVERRIDE_REQUEST +action = drop +topic = + +[0x1700] +msg_id = MSG_ID_TD_EVENT +action = drop +topic = + +[0x1780] +msg_id = MSG_ID_TD_3_WAY_VALVE_SET_STATE_REQUEST +action = drop +topic = + +[0x17A0] +msg_id = MSG_ID_DD_CONCENTRATE_PUMP_PARK_REQUEST_OVERRIDE_REQUEST +action = drop +topic = + +[0x17B0] +msg_id = MSG_ID_FP_CONDUCTIVITY_SENSOR_CONDUCTIVITY_READ_COUNT_OVERRIDE_REQUEST +action = drop +topic = + +[0x1800] +msg_id = MSG_ID_DD_EVENT +action = drop +topic = + +[0x1880] +msg_id = MSG_ID_TD_ROTARY_PINCH_VALVE_SET_POS_REQUEST +action = drop +topic = + +[0x18A0] +msg_id = MSG_ID_DD_TEMPERATURE_SENSOR_PUBLISH_INTERVAL_OVERRIDE_REQUEST +action = drop +topic = + +[0x18B0] +msg_id = MSG_ID_FP_CONDUCTIVITY_SENSOR_CONDUCTIVITY_ERROR_COUNT_OVERRIDE_REQUEST +action = drop +topic = + +[0x1900] +msg_id = MSG_ID_TD_DD_ALARMS_REQUEST +action = drop +topic = + +[0x1980] +msg_id = MSG_ID_TD_ROTARY_PINCH_VALVE_STATUS_OVERRIDE_REQUEST +action = drop +topic = + +[0x19A0] +msg_id = MSG_ID_DD_TEMPERATURE_SENSOR_MEASURED_TEMPERATURE_OVERRIDE_REQUEST +action = drop +topic = + +[0x19B0] +msg_id = MSG_ID_FP_TEMPERATURE_OVERRIDE_REQUEST +action = drop +topic = + +[0x1A00] +msg_id = MSG_ID_UI_TD_RESET_IN_SERVICE_MODE_REQUEST +action = drop +topic = + +[0x1A80] +msg_id = MSG_ID_TD_ROTARY_PINCH_VALVE_POSITION_OVERRIDE_REQUEST +action = drop +topic = + +[0x1AA0] +msg_id = MSG_ID_DD_TEMPERATURE_SENSOR_READ_COUNTER_OVERRIDE_REQUEST +action = drop +topic = + +[0x1AB0] +msg_id = MSG_ID_FP_FILTERED_FLOW_RATE_OVERRIDE_REQUEST +action = drop +topic = + +[0x1B00] +msg_id = MSG_ID_DD_VALVES_STATES_DATA +action = drop +topic = + +[0x1B80] +msg_id = MSG_ID_TD_VALVES_PUBLISH_INTERVAL_OVERRIDE_REQUEST +action = drop +topic = + +[0x1BA0] +msg_id = MSG_ID_DD_TEMPERATURE_SENSOR_FILTERED_TEMP_OVERRIDE_REQUEST +action = drop +topic = + +[0x1BB0] +msg_id = MSG_ID_FP_FILTERED_FLOW_TEMP_OVERRIDE_REQUEST +action = drop +topic = + +[0x1C00] +msg_id = MSG_ID_DD_PRESSURES_DATA +action = drop +topic = + +[0x1C80] +msg_id = MSG_ID_TD_ALARM_STATUS_PUBLISH_INTERVAL_OVERRIDE_REQUEST +action = drop +topic = + +[0x1CA0] +msg_id = MSG_ID_DD_SET_OPERATION_SUB_MODE_OVERRIDE_REQUEST +action = drop +topic = + +[0x1CB0] +msg_id = MSG_ID_FP_PRE_GEN_PUBLISH_INTERVAL_OVERRIDE_REQUEST +action = drop +topic = + +[0x1D00] +msg_id = MSG_ID_TD_VOLTAGES_DATA +action = drop +topic = + +[0x1D80] +msg_id = MSG_ID_TD_ALARM_INFO_PUBLISH_INTERVAL_OVERRIDE_REQUEST +action = drop +topic = + +[0x1DA0] +msg_id = MSG_ID_DD_DIALYSATE_PUMPS_PUBLISH_INTERVAL_OVERRIDE_REQUEST +action = drop +topic = + +[0x1DB0] +msg_id = MSG_ID_FP_SET_OPERATION_MODE_REQUEST +action = drop +topic = + +[0x1E00] +msg_id = MSG_ID_TD_BUBBLES_DATA +action = drop +topic = + +[0x1E80] +msg_id = MSG_ID_TD_ALARM_START_TIME_OVERRIDE_REQUEST +action = drop +topic = + +[0x1EA0] +msg_id = MSG_ID_DD_DIALYSATE_PUMPS_TARGET_SPEED_OVERRIDE_REQUEST +action = drop +topic = + +[0x1EB0] +msg_id = MSG_ID_FP_OPERATION_MODE_PUBLISH_INTERVAL_OVERRIDE_REQUEST +action = drop +topic = + +[0x1F00] +msg_id = MSG_ID_DD_CONDUCTIVITY_DATA +action = drop +topic = + +[0x1F80] +msg_id = MSG_ID_TD_ALARM_CLEAR_ALL_ALARMS_REQUEST +action = drop +topic = + +[0x1FA0] +msg_id = MSG_ID_DD_DIALYSATE_PUMPS_MEASURED_SPEED_OVERRIDE_REQUEST +action = drop +topic = + +[0x1FB0] +msg_id = MSG_ID_FP_TEMPERATURE_SENSOR_PUBLISH_INTERVAL_OVERRIDE_REQUEST +action = drop +topic = + +[0x2000] +msg_id = MSG_ID_TD_AIR_PUMP_DATA +action = drop +topic = + +[0x2080] +msg_id = MSG_ID_TD_WATCHDOG_OVERRIDE_REQUEST +action = drop +topic = + +[0x20A0] +msg_id = MSG_ID_DD_DIALYSATE_PUMPS_TARGET_PRESSURE_OVERRIDE_REQUEST +action = drop +topic = + +[0x20B0] +msg_id = MSG_ID_FP_RO_PUMP_TARGET_PRESSURE_OVERRIDE_REQUEST +action = drop +topic = + +[0x2100] +msg_id = MSG_ID_TD_SWITCHES_DATA +action = drop +topic = + +[0x2180] +msg_id = MSG_ID_TD_ALARM_STATE_OVERRIDE_REQUEST +action = drop +topic = + +[0x21A0] +msg_id = MSG_ID_DD_DIALYSATE_PUMPS_MEASURED_CURRENT_OVERRIDE_REQUEST +action = drop +topic = + +[0x21B0] +msg_id = MSG_ID_FP_RO_PUMP_TARGET_FLOW_OVERRIDE_REQUEST +action = drop +topic = + +[0x2200] +msg_id = MSG_ID_POWER_OFF_WARNING +action = drop +topic = + +[0x2280] +msg_id = MSG_ID_TD_SAFETY_SHUTDOWN_OVERRIDE_REQUEST +action = drop +topic = + +[0x22A0] +msg_id = MSG_ID_DD_DIALYSATE_PUMPS_MEASURED_DIRECTION_OVERRIDE_REQUEST +action = drop +topic = + +[0x22B0] +msg_id = MSG_ID_FP_RO_PUMP_TARGET_PWM_OVERRIDE_REQUEST +action = drop +topic = + +[0x2300] +msg_id = MSG_ID_OFF_BUTTON_PRESS_REQUEST +action = drop +topic = + +[0x2380] +msg_id = MSG_ID_TD_PINCH_VALVE_SET_POSITION_REQUEST +action = drop +topic = + +[0x23A0] +msg_id = MSG_ID_DD_HEATERS_PUBLISH_INTERVAL_OVERRIDE_REQUEST +action = drop +topic = + +[0x23B0] +msg_id = MSG_ID_FP_BOOST_PUMP_PUBLISH_INTERVAL_OVERRIDE_REQUEST +action = drop +topic = + +[0x2400] +msg_id = MSG_ID_TD_PRESSURE_DATA +action = drop +topic = + +[0x2480] +msg_id = MSG_ID_TD_PINCH_VALVE_HOME_REQUEST +action = drop +topic = + +[0x24A0] +msg_id = MSG_ID_DD_HEATERS_DUTY_CYCLE_OVERRIDE_REQUEST +action = drop +topic = + +[0x24B0] +msg_id = MSG_ID_FP_BOOST_PUMP_TARGET_PRESSURE_OVERRIDE_REQUEST +action = drop +topic = + +[0x2500] +msg_id = MSG_ID_DD_CONCENTRATE_PUMP_DATA +action = drop +topic = + +[0x2580] +msg_id = MSG_ID_TD_BLOOD_PUMP_PUBLISH_INTERVAL_OVERRIDE_REQUEST +action = drop +topic = + +[0x25A0] +msg_id = MSG_ID_DD_LEVELS_PUBLISH_INTERVAL_OVERRIDE_REQUEST +action = drop +topic = + +[0x25B0] +msg_id = MSG_ID_FP_BOOST_PUMP_TARGET_FLOW_OVERRIDE_REQUEST +action = drop +topic = + +[0x2600] +msg_id = MSG_ID_DD_TEMPERATURE_DATA +action = drop +topic = + +[0x2680] +msg_id = MSG_ID_TD_BLOOD_PUMP_SET_FLOW_RATE_REQUEST +action = drop +topic = + +[0x26A0] +msg_id = MSG_ID_DD_LEVELS_STATUS_OVERRIDE_REQUEST +action = drop +topic = + +[0x26B0] +msg_id = MSG_ID_FP_BOOST_PUMP_TARGET_PWM_OVERRIDE_REQUEST +action = drop +topic = + +[0x2700] +msg_id = MSG_ID_DIALYSATE_PUMPS_DATA +action = drop +topic = + +[0x2780] +msg_id = MSG_ID_TD_BLOOD_PUMP_SET_SPEED_REQUEST +action = drop +topic = + +[0x27B0] +msg_id = MSG_ID_FP_BOOST_PUMP_STOP_REQUEST +action = drop +topic = + +[0x2800] +msg_id = MSG_ID_DD_HEATERS_DATA +action = drop +topic = + +[0x2880] +msg_id = MSG_ID_TD_BLOOD_PUMP_MEASURED_FLOW_RATE_OVERRIDE_REQUEST +action = drop +topic = + +[0x28A0] +msg_id = MSG_ID_DD_OP_MODE_STATUS_OVERRIDE_REQUEST +action = drop +topic = + +[0x28B0] +msg_id = MSG_ID_FP_RO_PUMP_STOP_REQUEST +action = drop +topic = + +[0x2900] +msg_id = MSG_ID_DD_LEVEL_DATA +action = drop +topic = + +[0x2980] +msg_id = MSG_ID_TD_BLOOD_PUMP_MEASURED_MOTOR_SPEED_OVERRIDE_REQUEST +action = drop +topic = + +[0x29A0] +msg_id = MSG_ID_DD_SET_OPERATION_MODE_OVERRIDE_REQUEST +action = drop +topic = + +[0x29B0] +msg_id = MSG_ID_FP_SAFETY_SHUTDOWN_OVERRIDE_REQUEST +action = drop +topic = + +[0x2A00] +msg_id = MSG_ID_TD_AIR_TRAP_DATA +action = drop +topic = + +[0x2A80] +msg_id = MSG_ID_TD_BLOOD_PUMP_MEASURED_ROTOR_SPEED_OVERRIDE_REQUEST +action = drop +topic = + +[0x2AA0] +msg_id = MSG_ID_DD_UF_DATA_PUBLISH_OVERRIDE_REQUEST +action = drop +topic = + +[0x2AB0] +msg_id = MSG_ID_FP_PERMEATE_TANK_PUBLISH_INTERVAL_OVERRIDE_REQUEST +action = drop +topic = + +[0x2B00] +msg_id = MSG_ID_TD_VALVES_DATA +action = drop +topic = + +[0x2B80] +msg_id = MSG_ID_TD_BLOOD_PUMP_ROTOR_COUNT_OVERRIDE_REQUEST +action = drop +topic = + +[0x2BA0] +msg_id = MSG_ID_DD_DIALYSATE_PUMPS_START_STOP_OVERRIDE_REQUEST +action = drop +topic = + +[0x2BB0] +msg_id = MSG_ID_FP_ALARM_STATE_OVERRIDE_REQUEST +action = drop +topic = + +[0x2C00] +msg_id = MSG_ID_FP_EVENT +action = drop +topic = + +[0x2C80] +msg_id = MSG_ID_TD_TMP_PRESSURE_OVERRIDE_REQUEST +action = drop +topic = + +[0x2CA0] +msg_id = MSG_ID_DD_GEND_MODE_DATA_PUBLISH_OVERRIDE_REQUEST +action = drop +topic = + +[0x2CB0] +msg_id = MSG_ID_FP_ALARM_CLEAR_ALL_ALARMS_REQUEST +action = drop +topic = + +[0x2D00] +msg_id = MSG_ID_FP_ALARM_INFO_DATA +action = drop +topic = + +[0x2D80] +msg_id = MSG_ID_TD_REQ_CURRENT_TREATMENT_PARAMETERS +action = drop +topic = + +[0x2DA0] +msg_id = MSG_ID_DD_CONCENTRATE_PUMPS_START_STOP_OVERRIDE_REQUEST +action = drop +topic = + +[0x2DB0] +msg_id = MSG_ID_FP_SET_TEST_CONFIGURATION +action = drop +topic = + +[0x2E00] +msg_id = MSG_ID_DD_BAL_CHAMBER_DATA +action = drop +topic = + +[0x2E80] +msg_id = MSG_ID_TD_RSP_CURRENT_TREATMENT_PARAMETERS +action = drop +topic = + +[0x2EA0] +msg_id = MSG_ID_DD_HEATERS_START_STOP_OVERRIDE_REQUEST +action = drop +topic = + +[0x2EB0] +msg_id = MSG_ID_FP_GET_TEST_CONFIGURATION +action = drop +topic = + +[0x2F00] +msg_id = MSG_ID_DD_GEN_DIALYSATE_MODE_DATA +action = drop +topic = + +[0x2F80] +msg_id = MSG_ID_TD_SET_TREATMENT_PARAMETER +action = drop +topic = + +[0x2FA0] +msg_id = MSG_ID_DD_VALVES_OPEN_CLOSE_STATE_OVERRIDE_REQUEST +action = drop +topic = + +[0x2FB0] +msg_id = MSG_ID_FP_RESET_ALL_TEST_CONFIGURATIONS +action = drop +topic = + +[0x3000] +msg_id = MSG_ID_DD_GEN_DIALYSATE_REQUEST_DATA +action = drop +topic = + +[0x3080] +msg_id = MSG_ID_TD_OP_MODE_PUBLISH_INTERVAL_OVERRIDE_REQUEST +action = drop +topic = + +[0x30B0] +msg_id = MSG_ID_FP_INLET_PRES_PUBLISH_INTERVAL_OVERRIDE_REQUEST +action = drop +topic = + +[0x3100] +msg_id = MSG_ID_FP_VALVES_STATES_DATA +action = drop +topic = + +[0x3180] +msg_id = MSG_ID_TD_OP_MODE_OVERRIDE_REQUEST +action = drop +topic = + +[0x31A0] +msg_id = MSG_ID_DD_BAL_CHAMBER_DATA_PUBLISH_OVERRIDE_REQUEST +action = drop +topic = + +[0x31B0] +msg_id = MSG_ID_FP_INLET_PRES_CHECK_TIME_OVERRIDE_REQUEST +action = drop +topic = + +[0x3200] +msg_id = MSG_ID_FP_RO_PUMP_DATA +action = drop +topic = + +[0x3280] +msg_id = MSG_ID_TD_EJECTOR_MOTOR_SET_SPEED_REQUEST +action = drop +topic = + +[0x32A0] +msg_id = MSG_ID_DD_BAL_CHAMBER_SWITCH_FREQ_OVERRIDE_REQUEST +action = drop +topic = + +[0x32B0] +msg_id = MSG_ID_FP_FILTERED_COND_SENSOR_READINGS_OVERRIDE_REQUEST +action = drop +topic = + +[0x3300] +msg_id = MSG_ID_FP_OP_MODE_DATA +action = drop +topic = + +[0x3380] +msg_id = MSG_ID_TD_EJECTOR_COMMAND +action = drop +topic = + +[0x33A0] +msg_id = MSG_ID_DD_DIAL_DELIVERY_IN_PROGRESS_OVERRIDE_REQUEST +action = drop +topic = + +[0x33B0] +msg_id = MSG_ID_FP_FILTERED_COND_SENSOR_TEMPERATURE_OVERRIDE_REQUEST +action = drop +topic = + +[0x3400] +msg_id = MSG_ID_FP_PRESSURES_DATA +action = drop +topic = + +[0x3480] +msg_id = MSG_ID_TD_EJECTOR_PUBLISH_INTERVAL_OVERRIDE_REQUEST +action = drop +topic = + +[0x34A0] +msg_id = MSG_ID_DD_DIAL_DELIVERY_GOOD_TO_DELIVER_OVERRIDE_REQUEST +action = drop +topic = + +[0x34B0] +msg_id = MSG_ID_FP_SET_START_STOP_OVERRIDE_REQUEST +action = drop +topic = + +[0x3500] +msg_id = MSG_ID_FP_LEVEL_DATA +action = drop +topic = + +[0x3580] +msg_id = MSG_ID_TD_SET_AIR_TRAP_CONTROL +action = drop +topic = + +[0x35A0] +msg_id = MSG_ID_DD_HEATERS_TARGET_TEMPERATURE_OVERRIDE_REQUEST +action = drop +topic = + +[0x35B0] +msg_id = MSG_ID_FP_RO_REJECTION_RATIO_PUBLISH_INTERVAL_OVERRIDE_REQUEST +action = drop +topic = + +[0x3600] +msg_id = MSG_ID_FP_FLOW_DATA +action = drop +topic = + +[0x3680] +msg_id = MSG_ID_TD_HOME_BLOOD_PUMP +action = drop +topic = + +[0x36A0] +msg_id = MSG_ID_DD_BC_VALVE_STATES_OVERRIDE_REQUEST +action = drop +topic = + +[0x36B0] +msg_id = MSG_ID_FP_RO_FILTERED_REJECTION_RATIO_OVERRIDE_REQUEST +action = drop +topic = + +[0x3700] +msg_id = MSG_ID_FP_CONDUCTIVITY_DATA +action = drop +topic = + +[0x3780] +msg_id = MSG_ID_TD_BLOOD_FLOW_STROKE_VOLUME_OVERRIDE_REQUEST +action = drop +topic = + +[0x37A0] +msg_id = MSG_ID_DD_BC_SWITCH_ONLY_START_STOP_OVERRIDE_REQUEST +action = drop +topic = + +[0x37B0] +msg_id = MSG_ID_FP_RO_GET_CALCULATED_DUTY_CYCLE_REQUEST +action = drop +topic = + +[0x3800] +msg_id = MSG_ID_AVAILABLE_6 +action = drop +topic = + +[0x3880] +msg_id = MSG_ID_TD_BLOOD_FLOW_WEAR_A_TERM_OVERRIDE_REQUEST +action = drop +topic = + +[0x38A0] +msg_id = MSG_ID_DD_HYD_CHAMBER_TARGET_TEMP_OVERRIDE_REQUEST +action = drop +topic = + +[0x38B0] +msg_id = MSG_ID_FP_RO_CALCULATED_DUTY_CYCLE_RESPONSE +action = drop +topic = + +[0x3900] +msg_id = MSG_ID_FP_TEMPERATURE_DATA +action = drop +topic = + +[0x3980] +msg_id = MSG_ID_TD_BLOOD_FLOW_WEAR_B_TERM_OVERRIDE_REQUEST +action = drop +topic = + +[0x39A0] +msg_id = MSG_ID_DD_ACID_DOSING_VOLUME_OVERRIDE_REQUEST +action = drop +topic = + +[0x39B0] +msg_id = MSG_ID_FP_FLUSH_FILTER_PUBLISH_INTERVAL_OVERRIDE_REQUEST +action = drop +topic = + +[0x3A00] +msg_id = MSG_ID_FP_HEATER_DATA +action = drop +topic = + +[0x3A80] +msg_id = MSG_ID_TD_SET_TEST_CONFIGURATION +action = drop +topic = + +[0x3AA0] +msg_id = MSG_ID_DD_BICARB_DOSING_VOLUME_OVERRIDE_REQUEST +action = drop +topic = + +[0x3AB0] +msg_id = MSG_ID_FP_FLUSH_FILTER_TIMER_OVERRIDE_REQUEST +action = drop +topic = + +[0x3B00] +msg_id = MSG_ID_TD_TREATMENT_TIME_DATA +action = drop +topic = + +[0x3B80] +msg_id = MSG_ID_TD_GET_TEST_CONFIGURATION +action = drop +topic = + +[0x3BA0] +msg_id = MSG_ID_DD_GEND_EXEC_STATE_OVERRIDE_REQUEST +action = drop +topic = + +[0x3BB0] +msg_id = MSG_ID_FP_FLUSH_PERMEATE_PUBLISH_INTERVAL_OVERRIDE_REQUEST +action = drop +topic = + +[0x3C00] +msg_id = MSG_ID_TD_TREATMENT_STATE_DATA +action = drop +topic = + +[0x3C80] +msg_id = MSG_ID_TD_RESET_ALL_TEST_CONFIGURATIONS +action = drop +topic = + +[0x3CA0] +msg_id = MSG_ID_DD_HEATERS_PWM_PERIOD_OVERIDE_REQUEST +action = drop +topic = + +[0x3CB0] +msg_id = MSG_ID_FP_FLUSH_PERMEATE_TIMER_OVERRIDE_REQUEST +action = drop +topic = + +[0x3D00] +msg_id = MSG_ID_TD_FLUID_BOLUS_DATA +action = drop +topic = + +[0x3D80] +msg_id = MSG_ID_TD_AIR_PUMP_POWER_RAISE_OVERRIDE_REQUEST +action = drop +topic = + +[0x3DA0] +msg_id = MSG_ID_DD_PRE_GEND_MODE_DATA_PUBLISH_OVERRIDE_REQUEST +action = drop +topic = + +[0x3DB0] +msg_id = MSG_ID_FP_FLUSH_PERMEATE_ALARM_TIMER_OVERRIDE_REQUEST +action = drop +topic = + +[0x3E00] +msg_id = MSG_ID_TD_ULTRAFILTRATION_DATA +action = drop +topic = + +[0x3E80] +msg_id = MSG_ID_TD_AIR_PUMP_POWER_LOWER_OVERRIDE_REQUEST +action = drop +topic = + +[0x3EA0] +msg_id = MSG_ID_DD_POST_GEND_MODE_DATA_PUBLISH_OVERRIDE_REQUEST +action = drop +topic = + +[0x3EB0] +msg_id = MSG_ID_FP_FLUSH_CONCENTRATE_PUBLISH_INTERVAL_OVERRIDE_REQUEST +action = drop +topic = + +[0x3F00] +msg_id = MSG_ID_UI_TREATMENT_PARAMS_TO_VALIDATE +action = drop +topic = + +[0x3F80] +msg_id = MSG_ID_TD_HARD_STOP_BLOOD_PUMP +action = drop +topic = + +[0x3FA0] +msg_id = MSG_ID_DD_SEND_BLOOD_LEAK_EMB_MODE_RESPONSE +action = drop +topic = + +[0x3FB0] +msg_id = MSG_ID_FP_FLUSH_CONCENTRATE_TIMER_OVERRIDE_REQUEST +action = drop +topic = + +[0x4000] +msg_id = MSG_ID_TD_RESP_TREATMENT_PARAMS_TO_VALIDATE +action = drop +topic = + +[0x4080] +msg_id = MSG_ID_TD_BARO_MFG_CRC_OVERRIDE +action = drop +topic = + +[0x40A0] +msg_id = MSG_ID_DD_SPENT_CHAMB_FILL_DATA_PUBLISH_OVERRIDE_REQUEST +action = drop +topic = + +[0x40B0] +msg_id = MSG_ID_FP_DEF_FLUSH_FILTER_PUBLISH_INTERVAL_OVERRIDE_REQUEST +action = drop +topic = + +[0x4100] +msg_id = MSG_ID_UI_TREATMENT_UF_VOLUME_VALIDATE_REQUEST +action = drop +topic = + +[0x4180] +msg_id = MSG_ID_TD_BARO_PRESSURE_OVERRIDE +action = drop +topic = + +[0x41A0] +msg_id = MSG_ID_DD_AVAILABLE_TO_USE_4 +action = drop +topic = + +[0x41B0] +msg_id = MSG_ID_FP_DEF_FLUSH_FILTER_TIMER_OVERRIDE_REQUEST +action = drop +topic = + +[0x4200] +msg_id = MSG_ID_TD_TREATMENT_UF_VOLUME_VALIDATE_RESPONSE +action = drop +topic = + +[0x4280] +msg_id = MSG_ID_TD_TEMPERATURE_OVERRIDE +action = drop +topic = + +[0x42A0] +msg_id = MSG_ID_DD_SAFETY_SHUTDOWN_OVERRIDE_REQUEST +action = drop +topic = + +[0x42B0] +msg_id = MSG_ID_FP_DEF_PRE_GEN_PUBLISH_INTERVAL_OVERRIDE_REQUEST +action = drop +topic = + +[0x4300] +msg_id = MSG_ID_TD_TREATMENT_PARAM_RANGES +action = drop +topic = + +[0x4380] +msg_id = MSG_ID_TD_TEMPERATURE_PUBLISH_INTERVAL_OVERRIDE_REQUEST +action = drop +topic = + +[0x43A0] +msg_id = MSG_ID_DD_SET_TEST_CONFIGURATION +action = drop +topic = + +[0x43B0] +msg_id = MSG_ID_FP_DEF_GEN_PUBLISH_INTERVAL_OVERRIDE_REQUEST +action = drop +topic = + +[0x4400] +msg_id = MSG_ID_TD_VALIDATED_TREATMENT_PARAMS +action = drop +topic = + +[0x4480] +msg_id = MSG_ID_TD_EJECTOR_OPT_SENSOR_OVERRIDE_REQUEST +action = drop +topic = + +[0x44A0] +msg_id = MSG_ID_DD_GET_TEST_CONFIGURATION +action = drop +topic = + +[0x44B0] +msg_id = MSG_ID_FP_DEF_STATUS_REQUEST +action = drop +topic = + +[0x4500] +msg_id = MSG_ID_UI_INITIATE_TREATMENT_WORKFLOW +action = drop +topic = + +[0x4580] +msg_id = MSG_ID_TD_BLOOD_PRIME_VOLUME_OVERRIDE +action = drop +topic = + +[0x45A0] +msg_id = MSG_ID_DD_RESET_ALL_TEST_CONFIGURATIONS +action = drop +topic = + +[0x45B0] +msg_id = MSG_ID_FP_DEF_STATUS_RESPONSE +action = drop +topic = + +[0x4600] +msg_id = MSG_ID_TD_RESP_INITIATE_TREATMENT_WORKFLOW +action = drop +topic = + +[0x4680] +msg_id = MSG_ID_TD_BLOOD_PRIME_PUBLISH_INTERVAL_OVERRIDE_REQUEST +action = drop +topic = + +[0x46A0] +msg_id = MSG_ID_AVAILABLE_1 +action = drop +topic = + +[0x46B0] +msg_id = MSG_ID_FP_SET_OPERATION_SUB_MODE_REQUEST +action = drop +topic = + +[0x4700] +msg_id = MSG_ID_UI_UF_PAUSE_RESUME_REQUEST +action = drop +topic = + +[0x4780] +msg_id = MSG_ID_TD_ENABLE_VENOUS_BUBBLE_ALARM +action = drop +topic = + +[0x47A0] +msg_id = MSG_ID_DD_BLOOD_LEAK_DATA_PUBLISH_INTERVAL_OVERRIDE_REQUEST +action = drop +topic = + +[0x47B0] +msg_id = MSG_ID_FP_CONDUCTIVITY_SENSOR_RESISTANCE_OVERRIDE_REQUEST +action = drop +topic = + +[0x4800] +msg_id = MSG_ID_TD_UF_PAUSE_RESUME_RESPONSE +action = drop +topic = + +[0x4880] +msg_id = MSG_ID_TD_SYRINGE_PUMP_OPERATION_REQUEST +action = drop +topic = + +[0x48A0] +msg_id = MSG_ID_DD_BLOOD_LEAK_STATUS_OVERRIDE_REQUEST +action = drop +topic = + +[0x48B0] +msg_id = MSG_ID_FP_SET_RECOVERY_VALVES_REQUEST +action = drop +topic = + +[0x4900] +msg_id = MSG_ID_FP_GEN_WATER_MODE_DATA +action = drop +topic = + +[0x4980] +msg_id = MSG_ID_HD_SYRINGE_PUMP_PUBLISH_INTERVAL_OVERRIDE +action = drop +topic = + +[0x49A0] +msg_id = MSG_ID_DD_BLOOD_LEAK_SET_TO_EMBEDDED_MODE_REQUEST +action = drop +topic = + +[0x49B0] +msg_id = MSG_ID_FP_BOOST_PUMP_INSTALL_STATUS_REQUEST +action = drop +topic = + +[0x4A00] +msg_id = MSG_ID_DD_PRE_GEN_DIALYSATE_STATE_DATA +action = drop +topic = + +[0x4AA0] +msg_id = MSG_ID_DD_BLOOD_LEAK_SET_EMBEDDED_MODE_CMD_REQUEST +action = drop +topic = + +[0x4AB0] +msg_id = MSG_ID_FP_BOOST_PUMP_INSTALL_STATUS_RESPONSE +action = drop +topic = + +[0x4B00] +msg_id = MSG_ID_DD_POST_GEN_DIALYSATE_STATE_DATA +action = drop +topic = + +[0x4BA0] +msg_id = MSG_ID_DD_BLOOD_LEAK_EMBEDDED_MODE_INFO_OVERRIDE_REQUEST +action = drop +topic = + +[0x4C00] +msg_id = MSG_ID_DD_PRE_GEN_DIALYSATE_REQUEST_DATA +action = drop +topic = + +[0x4CA0] +msg_id = MSG_ID_DD_BLOOD_LEAK_INTENSITY_MOVING_AVERAGE_OVERRIDE_REQUEST +action = drop +topic = + +[0x4CB0] +msg_id = MSG_ID_FP_CONDUCTIVITY_SENSOR_VERSION_RESPONSE +action = drop +topic = + +[0x4D00] +msg_id = MSG_ID_FP_PRE_GEN_WATER_MODE_DATA +action = drop +topic = + +[0x4DA0] +msg_id = MSG_ID_DD_BLOOD_LEAK_ZEROING_INTERVAL_IN_MS_OVERRIDE_REQUEST +action = drop +topic = + +[0x4E00] +msg_id = MSG_ID_TD_EJECTOR_DATA +action = drop +topic = + +[0x4EA0] +msg_id = MSG_ID_DD_BLOOD_LEAK_ZERO_REQUEST +action = drop +topic = + +[0x4EB0] +msg_id = MSG_ID_FP_CONDUCTIVITY_SENSOR_CAL_RESPONSE +action = drop +topic = + +[0x4F00] +msg_id = MSG_ID_TD_TREATMENT_SET_POINTS +action = drop +topic = + +[0x4FA0] +msg_id = MSG_ID_DD_FILTERED_COND_SENSOR_READINGS_OVERRIDE_REQUEST +action = drop +topic = + +[0x5000] +msg_id = MSG_ID_FP_BOOST_PUMP_DATA +action = drop +topic = + +[0x5080] +msg_id = MSG_ID_TD_SYRINGE_PUMP_RATE_OVERRIDE_REQUEST +action = drop +topic = + +[0x50A0] +msg_id = MSG_ID_DD_FILTERED_COND_SENSOR_TEMPERATURE_OVERRIDE_REQUEST +action = drop +topic = + +[0x5100] +msg_id = MSG_ID_TD_SERIAL_RESPONSE +action = drop +topic = + +[0x5180] +msg_id = MSG_ID_TD_SYRINGE_PUMP_FORCE_OVERRIDE_REQUEST +action = drop +topic = + +[0x51A0] +msg_id = MSG_ID_DD_VOLTAGE_DATA_PUBLISH_INTERVAL_OVERRIDE_REQUEST +action = drop +topic = + +[0x5200] +msg_id = MSG_ID_DD_SERIAL_RESPONSE +action = drop +topic = + +[0x5280] +msg_id = MSG_ID_TD_SYRINGE_PUMP_HOME_OVERRIDE_REQUEST +action = drop +topic = + +[0x52A0] +msg_id = MSG_ID_DD_MONITORED_VOLTAGE_OVERRIDE_REQUEST +action = drop +topic = + +[0x5300] +msg_id = MSG_ID_TD_TEMPERATURE_DATA +action = drop +topic = + +[0x5380] +msg_id = MSG_ID_TD_SYRINGE_PUMP_POSITION_OVERRIDE_REQUEST +action = drop +topic = + +[0x53A0] +msg_id = MSG_ID_DD_RINSE_PUMP_DATA_PUBLISH_INTERVAL_OVERRIDE_REQUEST +action = drop +topic = + +[0x5400] +msg_id = MSG_ID_TD_BATTERY_DATA +action = drop +topic = + +[0x5480] +msg_id = MSG_ID_TD_SYRINGE_PUMP_VOLUME_OVERRIDE_REQUEST +action = drop +topic = + +[0x54A0] +msg_id = MSG_ID_DD_RINSE_PUMP_PWM_PERCENT_OVERRIDE_REQUEST +action = drop +topic = + +[0x5500] +msg_id = MSG_ID_UI_PATIENT_DISCONNECT_CONFIRM_REQUEST +action = drop +topic = + +[0x5580] +msg_id = MSG_ID_TD_SYRINGE_PUMP_STATUS_OVERRIDE_REQUEST +action = drop +topic = + +[0x55A0] +msg_id = MSG_ID_DD_RINSE_PUMP_TURN_ON_OFF_REQUEST +action = drop +topic = + +[0x5600] +msg_id = MSG_ID_TD_PATIENT_DISCONNECT_CONFIRM_RESPONSE +action = drop +topic = + +[0x5680] +msg_id = MSG_ID_TD_SYRINGE_PUMP_ENCODER_STATUS_OVERRIDE_REQUEST +action = drop +topic = + +[0x56A0] +msg_id = MSG_ID_DD_DRY_BICART_DATA_PUBLISH_INTERVAL_OVERRIDE_REQUEST +action = drop +topic = + +[0x5700] +msg_id = MSG_ID_FP_CONCENTRATE_FLUSH_DATA +action = drop +topic = + +[0x5780] +msg_id = MSG_ID_TD_SYRINGE_PUMP_ADC_DAC_STATUS_OVERRIDE_REQUEST +action = drop +topic = + +[0x57A0] +msg_id = MSG_ID_DD_DRY_BICART_FILL_CYCLE_MAX_OVERRIDE_REQUEST +action = drop +topic = + +[0x5800] +msg_id = MSG_ID_FP_GENP_DEF_DATA +action = drop +topic = + +[0x5880] +msg_id = MSG_ID_TD_SYRINGE_PUMP_ADC_READ_COUNTER_OVERRIDE_REQUEST +action = drop +topic = + +[0x58A0] +msg_id = MSG_ID_DD_DRY_BICART_FILL_REQUEST_OVERRIDE_REQUEST +action = drop +topic = + +[0x5900] +msg_id = MSG_ID_FP_PRE_GEN_DEF_DATA +action = drop +topic = + +[0x5980] +msg_id = MSG_ID_TD_HEPARIN_BOLUS_TARGET_RATE_OVERRIDE_REQUEST +action = drop +topic = + +[0x59A0] +msg_id = MSG_ID_DD_BICARB_CHAMBER_FILL_REQUEST_OVERRIDE_REQUEST +action = drop +topic = + +[0x5A00] +msg_id = MSG_ID_FP_VERSION_RESPONSE +action = drop +topic = + +[0x5AA0] +msg_id = MSG_ID_DD_BICART_DRAIN_REQUEST_OVERRIDE_REQUEST +action = drop +topic = + +[0x5B00] +msg_id = MSG_ID_TD_TREATMENT_PAUSED_TIMER_DATA +action = drop +topic = + +[0x5BA0] +msg_id = MSG_ID_DD_BICART_CARTRIDGE_SELECT_OVERRIDE_REQUEST +action = drop +topic = + +[0x5C00] +msg_id = MSG_ID_DD_UF_DATA +action = drop +topic = + +[0x5CA0] +msg_id = MSG_ID_DD_SET_CONDUCTIVITY_MODEL_REQUEST +action = drop +topic = + +[0x5D00] +msg_id = MSG_ID_FP_PERMEATE_TANK_DATA +action = drop +topic = + +[0x5DA0] +msg_id = MSG_ID_DD_CONDUCTIVITY_SENSOR_RESISTANCE_OVERRIDE_REQUEST +action = drop +topic = + +[0x5E00] +msg_id = MSG_ID_DD_SPENT_CHAMBER_FILL_DATA +action = drop +topic = + +[0x5F00] +msg_id = MSG_ID_UI_FLUID_BOLUS_REQUEST +action = drop +topic = + +[0x5FA0] +msg_id = MSG_ID_DD_CONDUCTIVITY_SENSOR_VERSION_RESPONSE +action = drop +topic = + +[0x6000] +msg_id = MSG_ID_TD_FLUID_BOLUS_RESPONSE +action = drop +topic = + +[0x6080] +msg_id = MSG_ID_TD_SYRINGE_PUMP_FORCE_SENSOR_CALIBRATION_REQUEST +action = drop +topic = + +[0x60A0] +msg_id = MSG_ID_DD_BICARB_MIX_VOL_KP_GAIN_COEFF_OVERRIDE_REQUEST +action = drop +topic = + +[0x6100] +msg_id = MSG_ID_DD_BLOOD_LEAK_DATA +action = drop +topic = + +[0x6180] +msg_id = MSG_ID_TD_GET_ALARM_PROPERTIES_REQUEST +action = drop +topic = + +[0x61A0] +msg_id = MSG_ID_DD_BICARB_MIX_VOL_KI_GAIN_COEFF_OVERRIDE_REQUEST +action = drop +topic = + +[0x6200] +msg_id = MSG_ID_FP_INLET_PRESSURE_CHECK_DATA +action = drop +topic = + +[0x6280] +msg_id = MSG_ID_TD_ALARM_PROPERTIES_RESPONSE +action = drop +topic = + +[0x62A0] +msg_id = MSG_ID_DD_ACID_MIX_VOL_KP_GAIN_COEFF_OVERRIDE_REQUEST +action = drop +topic = + +[0x6300] +msg_id = MSG_ID_UI_BLOOD_PRESSURE_REQUEST +action = drop +topic = + +[0x63A0] +msg_id = MSG_ID_DD_ACID_MIX_VOL_KI_GAIN_COEFF_OVERRIDE_REQUEST +action = drop +topic = + +[0x6400] +msg_id = MSG_ID_TD_BLOOD_PRESSURE_READING +action = drop +topic = + +[0x64A0] +msg_id = MSG_ID_DD_ACID_MIX_VOL_OVERRIDE_REQUEST +action = drop +topic = + +[0x6500] +msg_id = MSG_ID_TD_BLOOD_PRESSURE_DATA +action = drop +topic = + +[0x65A0] +msg_id = MSG_ID_DD_BICARB_MIX_VOL_OVERRIDE_REQUEST +action = drop +topic = + +[0x6600] +msg_id = MSG_ID_UI_ULTRAFILTRATION_CHANGE_CONFIRM_REQUEST +action = drop +topic = + +[0x66A0] +msg_id = MSG_ID_DD_BICARB_TARGET_CONDUCTIVITY_OVERRIDE_REQUEST +action = drop +topic = + +[0x6700] +msg_id = MSG_ID_TD_ULTRAFILTRATION_CHANGE_CONFIRM_RESPONSE +action = drop +topic = + +[0x67A0] +msg_id = MSG_ID_DD_BICARB_DELTA_CONDUCTIVITY_OVERRIDE_REQUEST +action = drop +topic = + +[0x6800] +msg_id = MSG_ID_DD_VOLTAGES_DATA +action = drop +topic = + +[0x68A0] +msg_id = MSG_ID_DD_DIALYSATE_TARGET_CONDUCTIVITY_OVERRIDE_REQUEST +action = drop +topic = + +[0x6900] +msg_id = MSG_ID_DD_RINSE_PUMP_DATA +action = drop +topic = + +[0x69A0] +msg_id = MSG_ID_DD_DIALYSATE_DELTA_CONDUCTIVITY_OVERRIDE_REQUEST +action = drop +topic = + +[0x6A00] +msg_id = MSG_ID_TD_TREATMENT_LOG_ALARM_EVENT +action = drop +topic = + +[0x6AA0] +msg_id = MSG_ID_DD_BICART_UPPER_PRESSURE_OVERRIDE_REQUEST +action = drop +topic = + +[0x6B00] +msg_id = MSG_ID_TD_TREATMENT_LOG_EVENT +action = drop +topic = + +[0x6BA0] +msg_id = MSG_ID_DD_BICART_LOWER_PRESSURE_OVERRIDE_REQUEST +action = drop +topic = + +[0x6C00] +msg_id = MSG_ID_TD_DATE_AND_TIME_REQUEST +action = drop +topic = + +[0x6CA0] +msg_id = MSG_ID_DD_FLOATER_LEVEL_OVERRIDE_REQUEST +action = drop +topic = + +[0x6D00] +msg_id = MSG_ID_TD_DATE_AND_TIME_RESPONSE +action = drop +topic = + +[0x6DA0] +msg_id = MSG_ID_DD_SUBSTITUTION_PUMP_START_STOP_OVERRIDE_REQUEST +action = drop +topic = + +[0x6E00] +msg_id = MSG_ID_DD_DATE_AND_TIME_REQUEST +action = drop +topic = + +[0x6EA0] +msg_id = MSG_ID_DD_SUBSTITUTION_PUMP_BROADCAST_INTERVAL_OVERRIDE_REQUEST +action = drop +topic = + +[0x6F00] +msg_id = MSG_ID_DD_DATE_AND_TIME_RESPONSE +action = drop +topic = + +[0x6FA0] +msg_id = MSG_ID_DD_SUBSTITUTION_PUMP_TARGET_RATE_OVERRIDE_REQUEST +action = drop +topic = + +[0x7000] +msg_id = MSG_ID_DD_DRY_BICART_DATA +action = drop +topic = + +[0x7100] +msg_id = MSG_ID_FP_RO_REJECTION_RATIO_DATA +action = drop +topic = + +[0x71A0] +msg_id = MSG_ID_DD_CONDUCTIVITY_SENSOR_CAL_RESPONSE +action = drop +topic = + +[0x7200] +msg_id = MSG_ID_UI_PRESSURE_LIMITS_CHANGE_REQUEST +action = drop +topic = + +[0x72A0] +msg_id = MSG_ID_DD_MIXING_CONTROL_DATA +action = drop +topic = + +[0x7300] +msg_id = MSG_ID_TD_PRESSURE_LIMITS_CHANGE_RESPONSE +action = drop +topic = + +[0x73A0] +msg_id = MSG_ID_DD_MIXING_CONTROL_DATA_PUBLISH_INTERVAL_OVERRIDE_REQUEST +action = drop +topic = + +[0x7400] +msg_id = MSG_ID_UI_BOLUS_VOLUME_CHANGE_REQUEST +action = drop +topic = + +[0x74A0] +msg_id = MSG_ID_DD_BICART_DEPRESSURISE_REQUEST_OVERRIDE_REQUEST +action = drop +topic = + +[0x7500] +msg_id = MSG_ID_TD_BOLUS_VOLUME_CHANGE_RESPONSE +action = drop +topic = + +[0x75A0] +msg_id = MSG_ID_DD_TREATMENT_PARAMS_OVERRIDE_REQUEST +action = drop +topic = + +[0x7600] +msg_id = MSG_ID_UI_DURATION_VALIDATE_REQUEST +action = drop +topic = + +[0x7700] +msg_id = MSG_ID_TD_DURATION_VALIDATE_RESPONSE +action = drop +topic = + +[0x7800] +msg_id = MSG_ID_UI_DURATION_CONFIRM_REQUEST +action = drop +topic = + +[0x7900] +msg_id = MSG_ID_TD_DURATION_CONFIRM_RESPONSE +action = drop +topic = + +[0x7A00] +msg_id = MSG_ID_UI_TREATMENT_SET_POINTS_CHANGE_REQUEST +action = drop +topic = + +[0x7B00] +msg_id = MSG_ID_TD_TREATMENT_SET_POINTS_CHANGE_RESPONSE +action = drop +topic = + +[0x7C00] +msg_id = MSG_ID_UI_TREATMENT_SET_POINT_BLOOD_FLOW_CHANGE_REQUEST +action = drop +topic = + +[0x7D00] +msg_id = MSG_ID_TD_TREATMENT_SET_POINT_BLOOD_FLOW_CHANGE_RESPONSE +action = drop +topic = + +[0x7E00] +msg_id = MSG_ID_UI_TREATMENT_SET_POINT_DIALYSATE_FLOW_CHANGE_REQUEST +action = drop +topic = + +[0x7F00] +msg_id = MSG_ID_TD_TREATMENT_SET_POINT_DIALYSATE_FLOW_CHANGE_RESPONSE +action = drop +topic = + +[0x8000] +msg_id = MSG_ID_UI_TREATMENT_SET_POINT_DIALYSATE_TEMP_CHANGE_REQUEST +action = drop +topic = + +[0x8100] +msg_id = MSG_ID_TD_TREATMENT_SET_POINT_DIALYSATE_TEMP_CHANGE_RESPONSE +action = drop +topic = + +[0x8200] +msg_id = MSG_ID_TD_INSTITUTIONAL_RECORD_REQUEST +action = drop +topic = + +[0x8300] +msg_id = MSG_ID_TD_INSTITUTIONAL_RECORD_RESPONSE +action = drop +topic = + +[0x8400] +msg_id = MSG_ID_TD_ADJUST_INSTITUTIONAL_RECORD_REQUEST +action = drop +topic = + +[0x8500] +msg_id = MSG_ID_TD_ADJUST_INSTITUTIONAL_RECORD_RESPONSE +action = drop +topic = + +[0x8600] +msg_id = MSG_ID_TD_ADVANCED_INSTITUTIONAL_RECORD_REQUEST +action = drop +topic = + +[0x8700] +msg_id = MSG_ID_TD_ADVANCED_INSTITUTIONAL_RECORD_RESPONSE +action = drop +topic = + +[0x8800] +msg_id = MSG_ID_TD_ADVANCED_ADJUST_INSTITUTIONAL_RECORD_REQUEST +action = drop +topic = + +[0x8900] +msg_id = MSG_ID_TD_ADVANCED_ADJUST_INSTITUTIONAL_RECORD_RESPONSE +action = drop +topic = + +[0x8A00] +msg_id = MSG_ID_TD_HEPARIN_REQUEST +action = drop +topic = + +[0x8B00] +msg_id = MSG_ID_TD_HEPARIN_RESPONSE +action = drop +topic = + +[0x8C00] +msg_id = MSG_ID_TD_HEPARIN_DATA +action = drop +topic = + +[0x8D00] +msg_id = MSG_ID_TD_END_TREATMENT_REQUEST +action = drop +topic = + +[0x8E00] +msg_id = MSG_ID_TD_END_TREATMENT_RESPONSE +action = drop +topic = + +[0x8F00] +msg_id = MSG_ID_TD_RINSEBACK_PROGRESS +action = drop +topic = + +[0x9000] +msg_id = MSG_ID_UI_RINSEBACK_CMD_REQUEST +action = drop +topic = + +[0x9100] +msg_id = MSG_ID_TD_RINSEBACK_CMD_RESPONSE +action = drop +topic = + +[0x9200] +msg_id = MSG_ID_UI_ADJUST_DISPOSABLES_CONFIRM_REQUEST +action = drop +topic = + +[0x9300] +msg_id = MSG_ID_TD_ADJUST_DISPOSABLES_CONFIRM_RESPONSE +action = drop +topic = + +[0x9400] +msg_id = MSG_ID_UI_ADJUST_DISPOSABLES_REMOVAL_CONFIRM_REQUEST +action = drop +topic = + +[0x9500] +msg_id = MSG_ID_TD_ADJUST_DISPOSABLES_REMOVAL_CONFIRM_RESPONSE +action = drop +topic = + +[0x9600] +msg_id = MSG_ID_FP_FILTER_FLUSH_DEF_DATA +action = drop +topic = + +[0x9700] +msg_id = MSG_ID_TD_BLOOD_PRIME_PROGRESS_DATA +action = drop +topic = + +[0x9800] +msg_id = MSG_ID_UI_BLOOD_PRIME_CMD_REQUEST +action = drop +topic = + +[0x9900] +msg_id = MSG_ID_TD_BLOOD_PRIME_CMD_RESPONSE +action = drop +topic = + +[0x9A00] +msg_id = MSG_ID_TD_ISOLATED_UF_DATA +action = drop +topic = + +[0x9B00] +msg_id = MSG_ID_UI_ISOLATED_UF_DURATION_CHANGE_REQUEST +action = drop +topic = + +[0x9C00] +msg_id = MSG_ID_TD_ISOLATED_UF_DURATION_CHANGE_RESPONSE +action = drop +topic = + +[0x9D00] +msg_id = MSG_ID_UI_ISOLATED_UF_VOLUME_GOAL_CHANGE_REQUEST +action = drop +topic = + +[0x9E00] +msg_id = MSG_ID_TD_ISOLATED_UF_VOLUME_GOAL_CHANGE_RESPONSE +action = drop +topic = + +[0x9F00] +msg_id = MSG_ID_UI_ISOLATED_UF_CONFIRM_REQUEST +action = drop +topic = + +[0xA000] +msg_id = MSG_ID_TD_ISOLATED_UF_CONFIRM_RESPONSE +action = drop +topic = + +[0xA100] +msg_id = MSG_ID_UI_ADJUST_START_TREATMENT_REQUEST +action = drop +topic = + +[0xA200] +msg_id = MSG_ID_TD_ADJUST_START_TREATMENT_RESPONSE +action = drop +topic = + +[0xA300] +msg_id = MSG_ID_UI_WATER_SAMPLE_RESULT_REQUEST +action = drop +topic = + +[0xA400] +msg_id = MSG_ID_UI_PRESSURE_LIMIT_WIDEN_REQUEST +action = drop +topic = + +[0xA500] +msg_id = MSG_ID_TD_PRESSURE_LIMIT_WIDEN_RESPONSE +action = drop +topic = + +[0xA600] +msg_id = MSG_ID_UI_RECIRCULATE_REQUEST +action = drop +topic = + +[0xA700] +msg_id = MSG_ID_TD_RECIRCULATE_RESPONSE +action = drop +topic = + +[0xA800] +msg_id = MSG_ID_TD_RECIRCULATE_DATA +action = drop +topic = + +[0xA900] +msg_id = MSG_ID_UI_ADJUST_TREATMENT_LOGS_REQUEST +action = drop +topic = + +[0xAA00] +msg_id = MSG_ID_TD_ADJUST_TREATMENT_LOGS_RESPONSE +action = drop +topic = + +[0xAB00] +msg_id = MSG_ID_TD_WATER_SAMPLE_RESULT_RESPONSE +action = drop +topic = + +[0xAC00] +msg_id = MSG_ID_TD_WATER_SAMPLE_DATA +action = drop +topic = + +[0xAD00] +msg_id = MSG_ID_TD_TREATMENT_LOG_AVERAGE_DATA +action = drop +topic = + +[0xAE00] +msg_id = MSG_ID_TD_DRY_SELF_TEST_PROGRESS_DATA +action = drop +topic = + +[0xAF00] +msg_id = MSG_ID_TD_TUBE_SET_AUTHENTICATION_REQUEST +action = drop +topic = + +[0xB000] +msg_id = MSG_ID_TD_TUBE_SET_AUTHENTICATION_ACK_RESPONSE +action = drop +topic = + +[0xB100] +msg_id = MSG_ID_TD_SYRINGE_PUMP_DATA +action = drop +topic = + +[0xB200] +msg_id = MSG_ID_TD_HEPARIN_PAUSE_RESUME_RESPONSE +action = drop +topic = + +[0xB300] +msg_id = MSG_ID_FFU_SIGNAL_TD_UPDATE_AVAILABLE +action = drop +topic = + +[0xB400] +msg_id = MSG_ID_FFU_SIGNAL_DD_UPDATE_AVAILABLE +action = drop +topic = + +[0xB500] +msg_id = MSG_ID_TD_UI_GENERIC_CONFIRMATION_REQUEST +action = drop +topic = + +[0xB600] +msg_id = MSG_ID_UI_GENERIC_CONFIRMATION_RESULT_RESPONSE +action = drop +topic = + +[0xB700] +msg_id = MSG_ID_AVAILABLE_B7 +action = drop +topic = + +[0xB800] +msg_id = MSG_ID_UI_VITALS_ADJUSTMENT_REQUEST +action = drop +topic = + +[0xB900] +msg_id = MSG_ID_TD_VITALS_ADJUSTMENT_RESPONSE +action = drop +topic = + +[0xD600] +msg_id = MSG_ID_UI_SETUP_TUBING_SET_CONNECTIONS_CONFIRM_REQUEST +action = drop +topic = + +[0xD700] +msg_id = MSG_ID_TD_SETUP_TUBING_SET_CONNECTIONS_CONFIRM_RESPONSE +action = drop +topic = + +[0xDB00] +msg_id = MSG_ID_DD_SUBSTITUTION_PUMP_DATA +action = drop +topic = + +[0xDC00] +msg_id = MSG_ID_DD_CONDUCTIVITY_SENSOR_RESISTANCE_DATA +action = drop +topic = + +[0xDD00] +msg_id = MSG_ID_FP_FILTER_FLUSH_DATA +action = drop +topic = + +[0xDE00] +msg_id = MSG_ID_FP_PERMEATE_FLUSH_DATA +action = drop +topic = + +[0xF1FF] +msg_id = MSG_ID_TD_DEBUG_EVENT +action = drop +topic = + +[0xF2FF] +msg_id = MSG_ID_DD_DEBUG_EVENT +action = drop +topic = + +[0xF3FF] +msg_id = MSG_ID_FP_DEBUG_EVENT +action = drop +topic = + +[0xFFFF] +msg_id = MSG_ID_ACK_MESSAGE_THAT_REQUIRES_ACK +action = drop +topic = + Index: docs/SDD/Class_Overview.puml =================================================================== diff -u -rb915ccc1a72fcca21908c35140af7ac7df1f1f37 -rcaca75be9a284ac5f98c078ec47c2e826ac5e980 --- docs/SDD/Class_Overview.puml (.../Class_Overview.puml) (revision b915ccc1a72fcca21908c35140af7ac7df1f1f37) +++ docs/SDD/Class_Overview.puml (.../Class_Overview.puml) (revision caca75be9a284ac5f98c078ec47c2e826ac5e980) @@ -16,7 +16,7 @@ -_dispatcher: Can::MessageDispatcher -_msgHandling: QHash -_msgCache: QMap> - -_agentInterface: RtInterface + -_agentInterface: CloudConnectClient -_agentThread: QThread -_txSequence: quint16 __ @@ -53,12 +53,12 @@ -onFrameWritten(qint64) <> } - class RtInterface { + class CloudConnectClient { -_socket: QLocalSocket -_reconnectTimer: QTimer -_socketPath: QString -_rxBuf: QByteArray - -_rxMsg: RtMessage + -_rxMsg: CloudConnectFrame __ +init(socketPath, reconnectIntervalMs, thread): bool +send(msgId, sequence, payload): bool @@ -94,7 +94,7 @@ +enableConsoleOut(bool) } - class RtMessage { + class CloudConnectFrame { -_headerBuf: QByteArray -_rxMsgId: MsgId -_rxSequence: quint16 @@ -109,7 +109,7 @@ +reset() } - enum "RtMessage::MsgId" as AgentMsgId { + enum "CloudConnectFrame::MsgId" as AgentMsgId { ClinicalData = 0x0001 Diagnostic = 0x0002 Ack = 0x0003 @@ -120,7 +120,7 @@ CloudSyncLogFile = 0x0008 } - enum "RtMessage::FeedResult" as FeedResult { + enum "CloudConnectFrame::FeedResult" as FeedResult { Incomplete Complete HeaderError @@ -134,10 +134,10 @@ -_server: QLocalServer -_client: QLocalSocket* -_rxBuf: QByteArray - -_rxMsg: RtMessage + -_rxMsg: CloudConnectFrame __ +listen(): bool - -handleMessage(RtMessage) + -handleMessage(CloudConnectFrame) -logMessage(MsgId, seq, payload) __ -onNewConnection() <> @@ -159,21 +159,21 @@ ' --- composition --- CloudConnectController *-- CanInterface -CloudConnectController *-- RtInterface +CloudConnectController *-- CloudConnectClient CloudConnectController *-- MessageDispatcher ' --- internal composition --- MessageDispatcher *-- MessageBuilder ' --- usage --- -RtInterface ..> RtMessage : uses -AgentSimController ..> RtMessage : uses +CloudConnectClient ..> CloudConnectFrame : uses +AgentSimController ..> CloudConnectFrame : uses ' --- enum nesting --- -RtMessage +-- AgentMsgId -RtMessage +-- FeedResult +CloudConnectFrame +-- AgentMsgId +CloudConnectFrame +-- FeedResult ' --- layout hints --- -CanInterface -[hidden]- RtInterface +CanInterface -[hidden]- CloudConnectClient @enduml Index: docs/SDD/Comms_Overview.puml =================================================================== diff -u -rb915ccc1a72fcca21908c35140af7ac7df1f1f37 -rcaca75be9a284ac5f98c078ec47c2e826ac5e980 --- docs/SDD/Comms_Overview.puml (.../Comms_Overview.puml) (revision b915ccc1a72fcca21908c35140af7ac7df1f1f37) +++ docs/SDD/Comms_Overview.puml (.../Comms_Overview.puml) (revision caca75be9a284ac5f98c078ec47c2e826ac5e980) @@ -5,7 +5,7 @@ participant "Can::CanInterface" as CANI participant "CloudConnectController" as LRC participant "Can::MessageDispatcher" as MDISP -participant "RtInterface" as AI +participant "CloudConnectClient" as AI participant "Unix Domain\nSocket" as UDS participant "AgentSimController" as ASC @@ -19,7 +19,7 @@ LRC -> LRC : look up policy in _msgHandling\n(drop / send_always / send_delta) LRC -> AI : send(topic, sequence, protobuf payload) -AI -> UDS : write(RtMessage frame) +AI -> UDS : write(CloudConnectFrame frame) == AgentSim receives == Index: docs/SDD/Seq_RealtimeDataTransfer.puml =================================================================== diff -u -rb915ccc1a72fcca21908c35140af7ac7df1f1f37 -rcaca75be9a284ac5f98c078ec47c2e826ac5e980 --- docs/SDD/Seq_RealtimeDataTransfer.puml (.../Seq_RealtimeDataTransfer.puml) (revision b915ccc1a72fcca21908c35140af7ac7df1f1f37) +++ docs/SDD/Seq_RealtimeDataTransfer.puml (.../Seq_RealtimeDataTransfer.puml) (revision caca75be9a284ac5f98c078ec47c2e826ac5e980) @@ -25,9 +25,9 @@ LRC -> LRC : discard (no change) else action == send_always OR send_delta with new payload LRC -> LRC : canMessageToProtobufByteArray()\n→ serialised protobuf bytes - LRC -> UDS : RtMessage frame\n(msgId=topic, seq++, protobuf payload) + LRC -> UDS : CloudConnectFrame frame\n(msgId=topic, seq++, protobuf payload) UDS -> ASC : readyRead - ASC -> ASC : RtMessage::feed() → Complete\nlogMessage() + Envelope parse\n(see Seq_AgentSim for detail) + ASC -> ASC : CloudConnectFrame::feed() → Complete\nlogMessage() + Envelope parse\n(see Seq_AgentSim for detail) end @enduml Index: docs/SDD/SoftwareArchitecture.puml =================================================================== diff -u -rb915ccc1a72fcca21908c35140af7ac7df1f1f37 -rcaca75be9a284ac5f98c078ec47c2e826ac5e980 --- docs/SDD/SoftwareArchitecture.puml (.../SoftwareArchitecture.puml) (revision b915ccc1a72fcca21908c35140af7ac7df1f1f37) +++ docs/SDD/SoftwareArchitecture.puml (.../SoftwareArchitecture.puml) (revision caca75be9a284ac5f98c078ec47c2e826ac5e980) @@ -14,23 +14,23 @@ node "CloudConnect (process)" { component "CloudConnectController" as LRC component "Can::CanInterface" as CAN - component "RtInterface" as AI + component "CloudConnectClient" as AI } node "Comms (lib)" { - component "RtInterface\nimpl" as AI_IMPL - component "RtServer\n(local-socket server)" as RS + component "CloudConnectClient\nimpl" as AI_IMPL + component "CloudConnectServer\n(local-socket server)" as RS component "Can::MessageDispatcher\n(per-CAN-id reassembly)" as MDISP component "Can::MessageBuilder\n(frame ↔ message)" as MB - component "RtMessage\n(framing + CRC)" as AM + component "CloudConnectFrame\n(framing + CRC)" as AM } node "MsgUtils (lib)" { component "LeahiMsgDefs\n(generated C++)" as MD <> } interface "CAN Bus\n(SocketCAN)" as CANBUS - interface "Unix Domain Socket\n(/tmp/leahi_rt.sock)" as UDS + interface "Unix Domain Socket\n(/tmp/cloudconnect_agent.sock)" as UDS } node "CANDumpPlayer (tool)" { @@ -39,7 +39,7 @@ node "AgentSim (tool / future Agent)" { component "AgentSimController" as ASC - component "RtMessage\n(framing + CRC)" as AM2 + component "CloudConnectFrame\n(framing + CRC)" as AM2 } cloud "Cloud Service\n(out of scope)" as CLOUD <> Index: lib/Comms/CMakeLists.txt =================================================================== diff -u -ra5781739bcbe58c754aff8861561495624bc5b67 -rcaca75be9a284ac5f98c078ec47c2e826ac5e980 --- lib/Comms/CMakeLists.txt (.../CMakeLists.txt) (revision a5781739bcbe58c754aff8861561495624bc5b67) +++ lib/Comms/CMakeLists.txt (.../CMakeLists.txt) (revision caca75be9a284ac5f98c078ec47c2e826ac5e980) @@ -11,28 +11,28 @@ set(INCLUDES include/CanInterface.h include/CanMessage.h + include/CloudConnectClient.h + include/CloudConnectFrame.h + include/CloudConnectServer.h include/crc.h include/format.h include/FrameInterface.h include/main.h include/MessageBuilder.h include/MessageDispatcher.h - include/RtInterface.h - include/RtMessage.h - include/RtServer.h include/types.h ) set(SRCS src/CanInterface.cpp + src/CloudConnectClient.cpp + src/CloudConnectFrame.cpp + src/CloudConnectServer.cpp src/crc.cpp src/format.cpp src/FrameInterface.cpp src/MessageBuilder.cpp src/MessageDispatcher.cpp - src/RtInterface.cpp - src/RtMessage.cpp - src/RtServer.cpp src/types.cpp ) Index: lib/Comms/Comms.pro =================================================================== diff -u -ra5781739bcbe58c754aff8861561495624bc5b67 -rcaca75be9a284ac5f98c078ec47c2e826ac5e980 --- lib/Comms/Comms.pro (.../Comms.pro) (revision a5781739bcbe58c754aff8861561495624bc5b67) +++ lib/Comms/Comms.pro (.../Comms.pro) (revision caca75be9a284ac5f98c078ec47c2e826ac5e980) @@ -12,27 +12,27 @@ HEADERS = \ include/CanInterface.h \ include/CanMessage.h \ + include/CloudConnectClient.h \ + include/CloudConnectFrame.h \ + include/CloudConnectServer.h \ include/crc.h \ include/format.h \ include/FrameInterface.h \ include/main.h \ include/MessageBuilder.h \ include/MessageDispatcher.h \ - include/RtInterface.h \ - include/RtMessage.h \ - include/RtServer.h \ include/types.h SOURCES = \ src/CanInterface.cpp \ + src/CloudConnectClient.cpp \ + src/CloudConnectFrame.cpp \ + src/CloudConnectServer.cpp \ src/crc.cpp \ src/format.cpp \ src/FrameInterface.cpp \ src/MessageBuilder.cpp \ src/MessageDispatcher.cpp \ - src/RtInterface.cpp \ - src/RtMessage.cpp \ - src/RtServer.cpp \ src/types.cpp INCLUDEPATH += $$PWD/include Index: lib/Comms/include/CloudConnectClient.h =================================================================== diff -u --- lib/Comms/include/CloudConnectClient.h (revision 0) +++ lib/Comms/include/CloudConnectClient.h (revision caca75be9a284ac5f98c078ec47c2e826ac5e980) @@ -0,0 +1,85 @@ +/*! + * + * Copyright (c) 2024-2026 Diality Inc. - All Rights Reserved. + * \copyright + * THIS CODE MAY NOT BE COPIED OR REPRODUCED IN ANY FORM, IN PART OR IN + * WHOLE, WITHOUT THE EXPLICIT PERMISSION OF THE COPYRIGHT OWNER. + * + * \file CloudConnectClient.h + * \author (original) Stephen Quong + * \date (original) 24-May-2026 + * + */ +#pragma once + +#include +#include +#include +#include +#include +#include + +#include "CloudConnectFrame.h" + +/*! + * \brief UDS interface to the Connectivity Agent + * \details Manages the QLocalSocket connection to the Connectivity Agent + * including automatic reconnection on disconnect or error. + * Outbound: call send() to write a CloudConnectFrame to the socket. + * Inbound: emits didMessageReceive() for each complete parsed frame. + */ +class CloudConnectClient : public QObject +{ + Q_OBJECT + +public: + CloudConnectClient(QObject *parent = nullptr); + + bool init(const QString &socketPath, int reconnectIntervalMs); + bool init(const QString &socketPath, int reconnectIntervalMs, QThread &thread); + bool send(CloudConnectFrame::MsgId msgId, quint16 sequence, const QByteArray &payload = {}); + +public Q_SLOTS: + void quit(); + +Q_SIGNALS: + /*! + * \brief didMessageReceive + * \details Emitted when a complete inbound CloudConnectFrame has been parsed. + * \param msgId - message identifier from the frame header + * \param sequence - sequence number from the frame header + * \param payload - decoded payload bytes, empty for zero-length frames + */ + void didMessageReceive(CloudConnectFrame::MsgId msgId, quint16 sequence, QByteArray payload); + + /*! + * \brief didConnect + * \details Emitted when the socket connects successfully. + */ + void didConnect(); + + /*! + * \brief didDisconnect + * \details Emitted when the socket disconnects. + */ + void didDisconnect(); + +private Q_SLOTS: + void onConnected(); + void onDisconnected(); + void onError(QLocalSocket::LocalSocketError error); + void onReadyRead(); + void onReconnectTimer(); + +private: + void connectToServer(); + void initThread(QThread &thread); + void quitThread(); + + QLocalSocket _socket; + QTimer _reconnectTimer; + QString _socketPath; + QByteArray _rxBuf; + CloudConnectFrame _rxMsg; + bool _init = false; +}; Index: lib/Comms/include/CloudConnectFrame.h =================================================================== diff -u --- lib/Comms/include/CloudConnectFrame.h (revision 0) +++ lib/Comms/include/CloudConnectFrame.h (revision caca75be9a284ac5f98c078ec47c2e826ac5e980) @@ -0,0 +1,95 @@ +/*! + * + * Copyright (c) 2024-2026 Diality Inc. - All Rights Reserved. + * \copyright + * THIS CODE MAY NOT BE COPIED OR REPRODUCED IN ANY FORM, IN PART OR IN + * WHOLE, WITHOUT THE EXPLICIT PERMISSION OF THE COPYRIGHT OWNER. + * + * \file CloudConnectFrame.h + * \author (original) Stephen Quong + * \date (original) 24-May-2026 + * + */ +#pragma once + +#include + +/*! + * \brief CloudConnect to Connectivity Agent message framing + * \details Transport-agnostic binary framing. build() makes a wire-ready frame; + * feed() parses inbound bytes (see FeedResult). On Complete, read + * msgId()/sequence()/payload(), then reset(). + * + * Frame layout — header only (payload_length == 0): + * + * Byte: 0 1 2 3 4 5 6-9 10 11 + * ┌─────────┬────────┬────────┬───────────┬────────┐ + * │ AA 55 │ msg_id │ seq_num│ pay_length│hdr_crc │ + * │ sync │uint16BE│uint16BE│ uint32 BE │uint16BE│ + * └─────────┴────────┴────────┴───────────┴────────┘ + * + * Frame layout — with payload (payload_length > 0): + * + * ┌── 12-byte header ──┬── N bytes payload ──┬── pay_crc (4 B) ──┐ + * │ (see above) │ uint8[] │ CRC-32/ISO-HDLC │ + * └────────────────────┴─────────────────────┴───────────────────┘ + * + * Header CRC: CRC-16/CCITT (poly 0x1021, init 0xFFFF, no reflection). + * Payload CRC: CRC-32/ISO-HDLC (IEEE 802.3, reflected poly 0xEDB88320). + */ +class CloudConnectFrame +{ +public: + /*! + * \brief MQTT topic identifier carried in every frame header + * \details The Connectivity Agent uses this value to determine the MQTT topic. + */ + enum class MsgId : quint16 { + ClinicalData = 0x0001, + Diagnostic = 0x0002, + Ack = 0x0003, + Alarms = 0x0004, + Audit = 0x0005, + DeviceLogFile = 0x0006, + TreatmentLogFile = 0x0007, + CloudSyncLogFile = 0x0008, + }; + + /*! + * \brief Result returned by feed() after processing each byte chunk + */ + enum class FeedResult { + Incomplete, ///< More bytes needed — continue feeding. + Complete, ///< Full valid frame assembled — read accessors, then call reset(). + HeaderError, ///< Header CRC mismatch — frame dropped, state reset automatically. + PayloadError, ///< Payload CRC mismatch or oversized payload — frame dropped, state reset automatically. + }; + + static QByteArray build(MsgId msgId, quint16 sequence, const QByteArray &payload = {}); + FeedResult feed(QByteArray &bytes); + + MsgId msgId() const; + quint16 sequence() const; + QByteArray payload() const; + + void reset(); + +private: + static quint16 crc16ccitt(const quint8 *data, int len); + static quint32 crc32isohdlc(const quint8 *data, int len); + + static constexpr int SYNC_SIZE = 2; + static constexpr quint8 SYNC[SYNC_SIZE] = {0xAA, 0x55}; + static constexpr int HEADER_SIZE = 12; + static constexpr int MSGID_SIZE = 2; + static constexpr int SEQUENCE_SIZE = 2; + static constexpr int HEADER_CRC_SIZE = 2; + static constexpr int PAYLOAD_CRC_SIZE = 4; + static constexpr quint32 MAX_PAYLOAD_LEN = 64 * 1024; + + QByteArray _headerBuf; + MsgId _rxMsgId = MsgId::ClinicalData; + quint16 _rxSequence = 0; + quint32 _rxPayloadLen = 0; + QByteArray _rxPayload; +}; Index: lib/Comms/include/CloudConnectServer.h =================================================================== diff -u --- lib/Comms/include/CloudConnectServer.h (revision 0) +++ lib/Comms/include/CloudConnectServer.h (revision caca75be9a284ac5f98c078ec47c2e826ac5e980) @@ -0,0 +1,69 @@ +/*! + * + * Copyright (c) 2024-2026 Diality Inc. - All Rights Reserved. + * \copyright + * THIS CODE MAY NOT BE COPIED OR REPRODUCED IN ANY FORM, IN PART OR IN + * WHOLE, WITHOUT THE EXPLICIT PERMISSION OF THE COPYRIGHT OWNER. + * + * \file CloudConnectServer.h + * \author (original) Stephen Quong + * \date (original) 15-Jul-2026 + * + */ +#pragma once + +#include +#include +#include +#include +#include + +#include "CloudConnectFrame.h" + +/*! + * \brief Server to handle incoming local socket connections to the CloudConnect agent. + */ +class CloudConnectServer : public QObject +{ + Q_OBJECT + +public: + explicit CloudConnectServer(QObject *parent = nullptr); + + bool listen(const QString &socketPath); + bool send(CloudConnectFrame::MsgId msgId, quint16 sequence, const QByteArray &payload = {}); + bool isConnected() const; + +Q_SIGNALS: + /*! + * \brief didMessageReceive + * \details Emitted when a complete inbound CloudConnectFrame has been parsed. + * \param msgId - message identifier from the frame header + * \param sequence - sequence number from the frame header + * \param payload - decoded payload bytes, empty for zero-length frames + */ + void didMessageReceive(CloudConnectFrame::MsgId msgId, quint16 sequence, QByteArray payload); + + /*! + * \brief didConnect + * \details Emitted when a client connects. + */ + void didConnect(); + + /*! + * \brief didDisconnect + * \details Emitted when the connected client disconnects. + */ + void didDisconnect(); + +private Q_SLOTS: + void onNewConnection(); + void onDisconnected(); + void onReadyRead(); + +private: + QLocalServer _server; + QLocalSocket *_client = nullptr; + QByteArray _rxBuf; + CloudConnectFrame _rxMsg; +}; Fisheye: Tag caca75be9a284ac5f98c078ec47c2e826ac5e980 refers to a dead (removed) revision in file `lib/Comms/include/RtInterface.h'. Fisheye: No comparison available. Pass `N' to diff? Fisheye: Tag caca75be9a284ac5f98c078ec47c2e826ac5e980 refers to a dead (removed) revision in file `lib/Comms/include/RtMessage.h'. Fisheye: No comparison available. Pass `N' to diff? Fisheye: Tag caca75be9a284ac5f98c078ec47c2e826ac5e980 refers to a dead (removed) revision in file `lib/Comms/include/RtServer.h'. Fisheye: No comparison available. Pass `N' to diff? Index: lib/Comms/src/CloudConnectClient.cpp =================================================================== diff -u --- lib/Comms/src/CloudConnectClient.cpp (revision 0) +++ lib/Comms/src/CloudConnectClient.cpp (revision caca75be9a284ac5f98c078ec47c2e826ac5e980) @@ -0,0 +1,202 @@ +/*! + * + * Copyright (c) 2024-2026 Diality Inc. - All Rights Reserved. + * \copyright + * THIS CODE MAY NOT BE COPIED OR REPRODUCED IN ANY FORM, IN PART OR IN + * WHOLE, WITHOUT THE EXPLICIT PERMISSION OF THE COPYRIGHT OWNER. + * + * \file CloudConnectClient.cpp + * \author (original) Stephen Quong + * \date (original) 24-May-2026 + * + */ +#include "CloudConnectClient.h" + +#include +#include +#include + +static void qRegister() { qRegisterMetaType("CloudConnectFrame::MsgId"); } +Q_COREAPP_STARTUP_FUNCTION(qRegister) + +/*! + * \brief CloudConnectClient::CloudConnectClient + * \details Constructor + * \param parent - optional QObject parent + */ +CloudConnectClient::CloudConnectClient(QObject *parent) : QObject(parent) +{ + connect(&_socket, &QLocalSocket::connected, this, &CloudConnectClient::onConnected); + connect(&_socket, &QLocalSocket::disconnected, this, &CloudConnectClient::onDisconnected); + connect(&_socket, &QLocalSocket::errorOccurred, this, &CloudConnectClient::onError); + connect(&_socket, &QLocalSocket::readyRead, this, &CloudConnectClient::onReadyRead); + + _reconnectTimer.setSingleShot(false); + connect(&_reconnectTimer, &QTimer::timeout, this, &CloudConnectClient::onReconnectTimer); +} + +/*! + * \brief CloudConnectClient::init + * \details Stores the socket path and reconnect interval and initiates the + * first connection attempt. Guards against double-initialisation. + * \param socketPath - path to the Unix domain socket + * \param reconnectIntervalMs - milliseconds between reconnect attempts + * \return true on success, false if already initialised + */ +bool CloudConnectClient::init(const QString &socketPath, int reconnectIntervalMs) +{ + if (_init) { + return false; + } + _init = true; + + _socketPath = socketPath; + _reconnectTimer.setInterval(reconnectIntervalMs); + connectToServer(); + return true; +} + +/*! + * \brief CloudConnectClient::init + * \details Calls init() then moves this object onto vThread. + * Must be called from the main thread. + * \param socketPath - path to the Unix domain socket + * \param reconnectIntervalMs - milliseconds between reconnect attempts + * \param thread - the thread to move this object onto + * \return true on success, false if already initialised + */ +bool CloudConnectClient::init(const QString &socketPath, int reconnectIntervalMs, QThread &thread) +{ + if (!init(socketPath, reconnectIntervalMs)) { + return false; + } + initThread(thread); + return true; +} + +/*! + * \brief CloudConnectClient::send + * \details Builds a CloudConnectFrame and writes it to the socket. + * \param msgId - message identifier for Agent MQTT topic + * \param sequence - caller-managed sequence number + * \param payload - message payload; pass empty for zero-length frames + * \return true if written to the socket, false if not connected + */ +bool CloudConnectClient::send(CloudConnectFrame::MsgId msgId, quint16 sequence, const QByteArray &payload) +{ + if (_socket.state() != QLocalSocket::ConnectedState) { + return false; + } + const QByteArray frame = CloudConnectFrame::build(msgId, sequence, payload); + _socket.write(frame); + _socket.flush(); + return true; +} + +/*! + * \brief CloudConnectClient::quit + * \details Moves this object back to the main thread for safe destruction. + */ +void CloudConnectClient::quit() { quitThread(); } + +/*! + * \brief CloudConnectClient::connectToServer + * \details Initiates a connection to the stored socket path. + */ +void CloudConnectClient::connectToServer() { _socket.connectToServer(_socketPath, QLocalSocket::ReadWrite); } + +/*! + * \brief CloudConnectClient::initThread + * \details Moves this object onto vThread and starts it. + * Must be called from the main thread. + * \param thread - the thread to move this object onto + */ +void CloudConnectClient::initThread(QThread &thread) +{ + Q_ASSERT_X(QThread::currentThread() == qApp->thread(), __func__, + "CloudConnectClient::init must be called from the main thread"); + thread.setObjectName(QString("%1_Thread").arg(metaObject()->className())); + connect(qApp, &QCoreApplication::aboutToQuit, this, &CloudConnectClient::quit); + moveToThread(&thread); + thread.start(); +} + +/*! + * \brief CloudConnectClient::quitThread + * \details Moves this object back to the main thread. + */ +void CloudConnectClient::quitThread() +{ + if (QThread::currentThread() != qApp->thread()) { + moveToThread(qApp->thread()); + } +} + +/*! + * \brief CloudConnectClient::onConnected + * \details Stops the reconnect timer and emits didConnect(). + */ +void CloudConnectClient::onConnected() +{ + qDebug().noquote() << "Agent socket connected to" << _socketPath; + _reconnectTimer.stop(); + emit didConnect(); +} + +/*! + * \brief CloudConnectClient::onDisconnected + * \details Clears inbound parser state, starts the reconnect timer, and emits didDisconnect(). + */ +void CloudConnectClient::onDisconnected() +{ + qDebug().noquote() << "Agent socket disconnected — retrying in" << _reconnectTimer.interval() / 1000 << "s"; + _rxBuf.clear(); + _rxMsg.reset(); + _reconnectTimer.start(); + emit didDisconnect(); +} + +/*! + * \brief CloudConnectClient::onError + * \details Logs the socket error and starts the reconnect timer if not already running. + * \param error - the socket error code + */ +void CloudConnectClient::onError(QLocalSocket::LocalSocketError error) +{ + qDebug().noquote() << "Agent socket error:" << _socket.errorString() << QString("(%1)").arg(error); + if (!_reconnectTimer.isActive()) { + _reconnectTimer.start(); + } +} + +/*! + * \brief CloudConnectClient::onReadyRead + * \details Drains incoming bytes through the CloudConnectFrame parser and emits + * didMessageReceive() for each complete frame. + */ +void CloudConnectClient::onReadyRead() +{ + _rxBuf.append(_socket.readAll()); + + CloudConnectFrame::FeedResult result; + do { + result = _rxMsg.feed(_rxBuf); + if (result == CloudConnectFrame::FeedResult::Complete) { + emit didMessageReceive(_rxMsg.msgId(), _rxMsg.sequence(), _rxMsg.payload()); + _rxMsg.reset(); + } + } while (result == CloudConnectFrame::FeedResult::Complete && !_rxBuf.isEmpty()); +} + +/*! + * \brief CloudConnectClient::onReconnectTimer + * \details Attempts to reconnect if the socket is in the unconnected state. + */ +void CloudConnectClient::onReconnectTimer() +{ + if (_socket.state() != QLocalSocket::UnconnectedState) { + return; + } + qDebug().noquote() << "Agent socket reconnecting to" << _socketPath; + connectToServer(); +} Index: lib/Comms/src/CloudConnectFrame.cpp =================================================================== diff -u --- lib/Comms/src/CloudConnectFrame.cpp (revision 0) +++ lib/Comms/src/CloudConnectFrame.cpp (revision caca75be9a284ac5f98c078ec47c2e826ac5e980) @@ -0,0 +1,233 @@ +/*! + * + * Copyright (c) 2024-2026 Diality Inc. - All Rights Reserved. + * \copyright + * THIS CODE MAY NOT BE COPIED OR REPRODUCED IN ANY FORM, IN PART OR IN + * WHOLE, WITHOUT THE EXPLICIT PERMISSION OF THE COPYRIGHT OWNER. + * + * \file CloudConnectFrame.cpp + * \author (original) Stephen Quong + * \date (original) 24-May-2026 + * + */ +#include "CloudConnectFrame.h" + +#include + +// --------------------------------------------------------------------------- +// Outbound +// --------------------------------------------------------------------------- + +/*! + * \brief CloudConnectFrame::build + * \details Builds a complete wire-ready frame with header and optional payload CRCs. + * \param msgId - message identifier for Agent MQTT topic + * \param sequence - caller-managed sequence number + * \param payload - optional payload; pass empty for zero-length frames (e.g. Ack) + * \return complete frame ready to write to the transport + */ +QByteArray CloudConnectFrame::build(MsgId msgId, quint16 sequence, const QByteArray &payload) +{ + const quint32 payloadLen = static_cast(payload.size()); + + // Header: sync(2) + msg_id(2) + sequence(2) + payload_length(4) + header_crc(2) = 12 bytes + QByteArray msg(HEADER_SIZE, Qt::Uninitialized); + quint8 *header = reinterpret_cast(msg.data()); + + header[0] = SYNC[0]; + header[1] = SYNC[1]; + qToBigEndian(static_cast(msgId), header + SYNC_SIZE); + qToBigEndian(sequence, header + SYNC_SIZE + MSGID_SIZE); + qToBigEndian(payloadLen, header + SYNC_SIZE + MSGID_SIZE + SEQUENCE_SIZE); + + const quint16 hCrc = crc16ccitt(header, HEADER_SIZE - HEADER_CRC_SIZE); + qToBigEndian(hCrc, header + HEADER_SIZE - HEADER_CRC_SIZE); + + if (payloadLen > 0) { + msg.append(payload); + const quint32 crc = crc32isohdlc(reinterpret_cast(payload.constData()), payload.size()); + QByteArray crcBytes(PAYLOAD_CRC_SIZE, Qt::Uninitialized); + qToBigEndian(crc, reinterpret_cast(crcBytes.data())); + msg.append(crcBytes); + } + + return msg; +} + +// --------------------------------------------------------------------------- +// Inbound +// --------------------------------------------------------------------------- + +/*! + * \brief CloudConnectFrame::feed + * \details Feeds raw bytes into the inbound parser state machine. + * Consumed bytes are removed from the front of the buffer. + * On HeaderError or PayloadError the caller may call feed() again + * immediately if the buffer is non-empty. + * \param bytes - raw bytes from the transport; modified in-place + * \return FeedResult indicating the parser outcome + */ +CloudConnectFrame::FeedResult CloudConnectFrame::feed(QByteArray &bytes) +{ + int pos = 0; + FeedResult result = FeedResult::Incomplete; + + // scan for a valid header — skipped when _headerBuf is already populated from a prior feed() call + while (_headerBuf.size() == 0 && bytes.size() - pos >= HEADER_SIZE && result != FeedResult::HeaderError) { + if (static_cast(bytes.at(pos)) == SYNC[0] && static_cast(bytes.at(pos + 1)) == SYNC[1]) { + _headerBuf.append(bytes.constData() + pos, HEADER_SIZE); + if (crc16ccitt(reinterpret_cast(_headerBuf.constData()), HEADER_SIZE - HEADER_CRC_SIZE) == + qFromBigEndian(reinterpret_cast(_headerBuf.constData() + HEADER_SIZE - + HEADER_CRC_SIZE))) + { + const quint8 *header = reinterpret_cast(_headerBuf.constData()); + int header_pos = SYNC_SIZE; + _rxMsgId = static_cast(qFromBigEndian(header + header_pos)); + header_pos += MSGID_SIZE; + _rxSequence = qFromBigEndian(header + header_pos); + header_pos += SEQUENCE_SIZE; + _rxPayloadLen = qFromBigEndian(header + header_pos); + pos += HEADER_SIZE; + } + else { + // TODO: log the header CRC failure + _headerBuf.clear(); + pos += SYNC_SIZE; + result = FeedResult::HeaderError; + } + } + else { + ++pos; + } + } + + // process payload if a valid header has been accumulated + if (result != FeedResult::HeaderError && _headerBuf.size() == HEADER_SIZE) { + if (_rxPayloadLen == 0) { + result = FeedResult::Complete; + } + else if (_rxPayloadLen > MAX_PAYLOAD_LEN) { + // TODO: log the oversized payload + _headerBuf.clear(); + result = FeedResult::PayloadError; + } + else if (bytes.size() - pos >= static_cast(_rxPayloadLen) + PAYLOAD_CRC_SIZE) { + const quint8 *payload = reinterpret_cast(bytes.constData() + pos); + if (crc32isohdlc(payload, static_cast(_rxPayloadLen)) == + qFromBigEndian(payload + _rxPayloadLen)) + { + _rxPayload = QByteArray(reinterpret_cast(payload), static_cast(_rxPayloadLen)); + pos += static_cast(_rxPayloadLen) + PAYLOAD_CRC_SIZE; + result = FeedResult::Complete; + } + else { + // TODO: log the payload CRC failure + _headerBuf.clear(); + result = FeedResult::PayloadError; + } + } + } + + // remove the consumed bytes from the input buffer + bytes.remove(0, pos); + + return result; +} + +/*! + * \brief CloudConnectFrame::msgId + * \details Message identifier of the last complete frame. + * Valid only after feed() returns FeedResult::Complete. + * \return MsgId of the last complete frame + */ +CloudConnectFrame::MsgId CloudConnectFrame::msgId() const +{ + return _rxMsgId; +} + +/*! + * \brief CloudConnectFrame::sequence + * \details Sequence number of the last complete frame. + * Valid only after feed() returns FeedResult::Complete. + * \return sequence number of the last complete frame + */ +quint16 CloudConnectFrame::sequence() const +{ + return _rxSequence; +} + +/*! + * \brief CloudConnectFrame::payload + * \details Payload bytes of the last complete frame. Empty for zero-length frames. + * Valid only after feed() returns FeedResult::Complete. + * \return payload of the last complete frame + */ +QByteArray CloudConnectFrame::payload() const +{ + return _rxPayload; +} + +/*! + * \brief CloudConnectFrame::reset + * \details Resets the inbound parser to its initial sync-scanning state. + * Must be called after consuming a Complete frame. + */ +void CloudConnectFrame::reset() +{ + _headerBuf.clear(); + _rxMsgId = MsgId::ClinicalData; + _rxSequence = 0; + _rxPayloadLen = 0; + _rxPayload.clear(); +} + +/*! + * \brief CloudConnectFrame::crc16ccitt + * \details CRC-16/CCITT: poly 0x1021, init 0xFFFF, no reflection, no final XOR. + * Check value: crc16ccitt("123456789", 9) == 0x29B1. + * \param data - input data bytes + * \param len - number of bytes to process + * \return 16-bit CRC value + */ +quint16 CloudConnectFrame::crc16ccitt(const quint8 *data, int len) +{ + quint16 crc = 0xFFFF; + for (int i = 0; i < len; ++i) { + crc ^= static_cast(data[i]) << 8; + for (int bit = 0; bit < 8; ++bit) { + if (crc & 0x8000) { + crc = (crc << 1) ^ 0x1021; + } + else { + crc <<= 1; + } + } + } + return crc; +} + +/*! + * \brief CloudConnectFrame::crc32isohdlc + * \details CRC-32/ISO-HDLC: reflected poly 0xEDB88320 (IEEE 802.3), init 0xFFFFFFFF, + * input and output reflected, final XOR 0xFFFFFFFF. + * Check value: crc32isohdlc("123456789", 9) == 0xCBF43926. + * \param data - input data bytes + * \param len - number of bytes to process + * \return 32-bit CRC value + */ +quint32 CloudConnectFrame::crc32isohdlc(const quint8 *data, int len) +{ + quint32 crc = 0xFFFFFFFF; + for (int i = 0; i < len; ++i) { + crc ^= data[i]; + for (int bit = 0; bit < 8; ++bit) { + if (crc & 1) { + crc = (crc >> 1) ^ 0xEDB88320; + } + else { + crc >>= 1; + } + } + } + return crc ^ 0xFFFFFFFF; +} Index: lib/Comms/src/CloudConnectServer.cpp =================================================================== diff -u --- lib/Comms/src/CloudConnectServer.cpp (revision 0) +++ lib/Comms/src/CloudConnectServer.cpp (revision caca75be9a284ac5f98c078ec47c2e826ac5e980) @@ -0,0 +1,140 @@ +/*! + * + * Copyright (c) 2024-2026 Diality Inc. - All Rights Reserved. + * \copyright + * THIS CODE MAY NOT BE COPIED OR REPRODUCED IN ANY FORM, IN PART OR IN + * WHOLE, WITHOUT THE EXPLICIT PERMISSION OF THE COPYRIGHT OWNER. + * + * \file CloudConnectServer.cpp + * \author (original) Stephen Quong + * \date (original) 15-Jul-2026 + * + */ +#include "CloudConnectServer.h" + +#include + +/*! + * \brief CloudConnectServer::CloudConnectServer + * \details Constructor. Wires the server newConnection signal. + * \param parent Optional QObject parent. + */ +CloudConnectServer::CloudConnectServer(QObject *parent) : QObject(parent) +{ + connect(&_server, &QLocalServer::newConnection, this, &CloudConnectServer::onNewConnection); +} + +/*! + * \brief CloudConnectServer::listen + * \details Removes any stale socket file, then starts the server. + * \param socketPath Path to the Unix domain socket. + * \return true on success, false if the server could not bind. + */ +bool CloudConnectServer::listen(const QString &socketPath) +{ + QLocalServer::removeServer(socketPath); + if (!_server.listen(socketPath)) { + qCritical().noquote() << metaObject()->className() << ": failed to listen on" << socketPath + << "—" << _server.errorString(); + return false; + } + qInfo().noquote() << metaObject()->className() << ": listening on" << socketPath; + return true; +} + +/*! + * \brief CloudConnectServer::send + * \details Builds a CloudConnectFrame and writes it to the connected client. + * \param msgId Message identifier for the frame header. + * \param sequence Caller-managed sequence number. + * \param payload Message payload; pass empty for zero-length frames. + * \return true if written to the socket, false if no client is connected. + */ +bool CloudConnectServer::send(CloudConnectFrame::MsgId msgId, quint16 sequence, const QByteArray &payload) +{ + if (_client == nullptr || _client->state() != QLocalSocket::ConnectedState) { + return false; + } + const QByteArray frame = CloudConnectFrame::build(msgId, sequence, payload); + _client->write(frame); + _client->flush(); + return true; +} + +/*! + * \brief CloudConnectServer::isConnected + * \details Reports whether a client is currently attached to the server. + * \return true if a client is currently connected. + */ +bool CloudConnectServer::isConnected() const +{ + return _client != nullptr; +} + +/*! + * \brief CloudConnectServer::onNewConnection + * \details Accepts the pending connection. If a client is already connected the + * new socket is discarded with a warning. + */ +void CloudConnectServer::onNewConnection() +{ + if (_client) { + qWarning().noquote() << metaObject()->className() + << ": second connection attempt rejected — already connected"; + _server.nextPendingConnection()->deleteLater(); + return; + } + + _client = _server.nextPendingConnection(); + qInfo().noquote() << metaObject()->className() << ": client connected"; + + connect(_client, &QLocalSocket::readyRead, this, &CloudConnectServer::onReadyRead); + connect(_client, &QLocalSocket::disconnected, this, &CloudConnectServer::onDisconnected); + + emit didConnect(); +} + +/*! + * \brief CloudConnectServer::onDisconnected + * \details Releases the client socket and resets inbound parser state. + */ +void CloudConnectServer::onDisconnected() +{ + qInfo().noquote() << metaObject()->className() << ": client disconnected"; + _client->deleteLater(); + _client = nullptr; + _rxBuf.clear(); + _rxMsg.reset(); + + emit didDisconnect(); +} + +/*! + * \brief CloudConnectServer::onReadyRead + * \details Appends incoming bytes to the receive buffer and drains it through + * the CloudConnectFrame parser, emitting didMessageReceive() for each + * complete frame. + */ +void CloudConnectServer::onReadyRead() +{ + _rxBuf.append(_client->readAll()); + + CloudConnectFrame::FeedResult result; + do { + result = _rxMsg.feed(_rxBuf); + switch (result) { + case CloudConnectFrame::FeedResult::Complete: + emit didMessageReceive(_rxMsg.msgId(), _rxMsg.sequence(), _rxMsg.payload()); + _rxMsg.reset(); + break; + case CloudConnectFrame::FeedResult::HeaderError: + qWarning().noquote() << metaObject()->className() << ": header CRC error — frame dropped"; + break; + case CloudConnectFrame::FeedResult::PayloadError: + qWarning().noquote() << metaObject()->className() << ": payload CRC error — frame dropped"; + break; + case CloudConnectFrame::FeedResult::Incomplete: + break; + } + } while (result == CloudConnectFrame::FeedResult::Complete && !_rxBuf.isEmpty()); +} Fisheye: Tag caca75be9a284ac5f98c078ec47c2e826ac5e980 refers to a dead (removed) revision in file `lib/Comms/src/RtInterface.cpp'. Fisheye: No comparison available. Pass `N' to diff? Fisheye: Tag caca75be9a284ac5f98c078ec47c2e826ac5e980 refers to a dead (removed) revision in file `lib/Comms/src/RtMessage.cpp'. Fisheye: No comparison available. Pass `N' to diff? Fisheye: Tag caca75be9a284ac5f98c078ec47c2e826ac5e980 refers to a dead (removed) revision in file `lib/Comms/src/RtServer.cpp'. Fisheye: No comparison available. Pass `N' to diff? Index: tools/AgentSim/AgentSimController.cpp =================================================================== diff -u -ra5781739bcbe58c754aff8861561495624bc5b67 -rcaca75be9a284ac5f98c078ec47c2e826ac5e980 --- tools/AgentSim/AgentSimController.cpp (.../AgentSimController.cpp) (revision a5781739bcbe58c754aff8861561495624bc5b67) +++ tools/AgentSim/AgentSimController.cpp (.../AgentSimController.cpp) (revision caca75be9a284ac5f98c078ec47c2e826ac5e980) @@ -39,7 +39,7 @@ */ bool AgentSimController::listen() { - const QString socketPath = _settings.value("Socket/LocalSocketName", "/tmp/leahi_rt.sock").toString(); + const QString socketPath = _settings.value("Socket/AgentSocketName", "/tmp/cloudconnect_agent.sock").toString(); QLocalServer::removeServer(socketPath); if (!_server.listen(socketPath)) { qCritical().noquote() << "AgentSim: failed to listen on" << socketPath << "—" << _server.errorString(); @@ -85,39 +85,39 @@ /*! * \brief AgentSimController::onReadyRead * \details Appends incoming bytes to the receive buffer and drains it through - * the RtMessage parser. Logs each complete frame and sends an Ack. + * the CloudConnectFrame parser. Logs each complete frame and sends an Ack. */ void AgentSimController::onReadyRead() { _rxBuf.append(_client->readAll()); - RtMessage::FeedResult result; + CloudConnectFrame::FeedResult result; do { result = _rxMsg.feed(_rxBuf); switch (result) { - case RtMessage::FeedResult::Complete: + case CloudConnectFrame::FeedResult::Complete: handleMessage(_rxMsg); _rxMsg.reset(); break; - case RtMessage::FeedResult::HeaderError: + case CloudConnectFrame::FeedResult::HeaderError: qWarning().noquote() << "AgentSim: header CRC error — frame dropped"; break; - case RtMessage::FeedResult::PayloadError: + case CloudConnectFrame::FeedResult::PayloadError: qWarning().noquote() << "AgentSim: payload CRC error — frame dropped"; break; - case RtMessage::FeedResult::Incomplete: + case CloudConnectFrame::FeedResult::Incomplete: break; } - } while (result == RtMessage::FeedResult::Complete && !_rxBuf.isEmpty()); + } while (result == CloudConnectFrame::FeedResult::Complete && !_rxBuf.isEmpty()); } /*! * \brief AgentSimController::handleMessage * \details Decodes a received frame and prints its typed body as JSON, generically * via the protobuf descriptor pool (msgId -> message name -> dynamic parse). - * \param msg The complete RtMessage frame. + * \param msg The complete CloudConnectFrame frame. */ -void AgentSimController::handleMessage(const RtMessage &msg) +void AgentSimController::handleMessage(const CloudConnectFrame &msg) { const QByteArray payload = msg.payload(); logMessage(msg.msgId(), msg.sequence(), payload); @@ -173,7 +173,7 @@ * \param sequence Sequence number from the parsed frame. * \param payload Payload bytes of the parsed frame. */ -void AgentSimController::logMessage(RtMessage::MsgId msgId, quint16 sequence, const QByteArray &payload) +void AgentSimController::logMessage(CloudConnectFrame::MsgId msgId, quint16 sequence, const QByteArray &payload) { qInfo().noquote() << QString("AgentSim: rx MsgId=0x%1 seq=%2 payloadLen=%3") .arg(static_cast(msgId), 4, 16, QChar('0')) Index: tools/AgentSim/AgentSimController.h =================================================================== diff -u -ra5781739bcbe58c754aff8861561495624bc5b67 -rcaca75be9a284ac5f98c078ec47c2e826ac5e980 --- tools/AgentSim/AgentSimController.h (.../AgentSimController.h) (revision a5781739bcbe58c754aff8861561495624bc5b67) +++ tools/AgentSim/AgentSimController.h (.../AgentSimController.h) (revision caca75be9a284ac5f98c078ec47c2e826ac5e980) @@ -19,7 +19,7 @@ #include #include -#include "RtMessage.h" +#include "CloudConnectFrame.h" /*! * \brief Simulates the Agent app that connects the Leahi device to the Cloud System @@ -39,12 +39,12 @@ void onReadyRead(); private: - void handleMessage(const RtMessage &msg); - void logMessage(RtMessage::MsgId msgId, quint16 sequence, const QByteArray &payload); + void handleMessage(const CloudConnectFrame &msg); + void logMessage(CloudConnectFrame::MsgId msgId, quint16 sequence, const QByteArray &payload); QSettings _settings; QLocalServer _server; QLocalSocket *_client = nullptr; QByteArray _rxBuf; - RtMessage _rxMsg; + CloudConnectFrame _rxMsg; }; Index: tools/AgentSim/config/AgentSim.ini =================================================================== diff -u -rb8c2474ae637b7757b673d332a7b578636f232b6 -rcaca75be9a284ac5f98c078ec47c2e826ac5e980 --- tools/AgentSim/config/AgentSim.ini (.../AgentSim.ini) (revision b8c2474ae637b7757b673d332a7b578636f232b6) +++ tools/AgentSim/config/AgentSim.ini (.../AgentSim.ini) (revision caca75be9a284ac5f98c078ec47c2e826ac5e980) @@ -1,2 +1,2 @@ [Socket] -LocalSocketName=/tmp/leahi_rt.sock +AgentSocketName=/tmp/cloudconnect_agent.sock