From ccfa90efb243270c649ab3b5240779ea6323adb5 Mon Sep 17 00:00:00 2001 From: Thomas Popp Date: Mon, 4 Nov 2024 21:05:11 +0100 Subject: [PATCH] wip(protocol): doc, fixed date, add water temp target, add operation type and modes --- AquaMQTT/src/message/HMIMessage.cpp | 37 +- AquaMQTT/src/task/MQTTTask.cpp | 665 ++++++++++++++-------------- PROTOCOL_NEXT.md | 217 +++++++++ 3 files changed, 580 insertions(+), 339 deletions(-) diff --git a/AquaMQTT/src/message/HMIMessage.cpp b/AquaMQTT/src/message/HMIMessage.cpp index 888271f..3c1a476 100644 --- a/AquaMQTT/src/message/HMIMessage.cpp +++ b/AquaMQTT/src/message/HMIMessage.cpp @@ -26,8 +26,7 @@ HMIMessage::HMIMessage(uint8_t* data) } float HMIMessage::waterTempTarget() { - // TODO - return 0.0; + return mData[1]; } void HMIMessage::setWaterTempTarget(float targetTemperature) { @@ -35,17 +34,33 @@ void HMIMessage::setWaterTempTarget(float targetTemperature) } HMIOperationMode HMIMessage::operationMode() const { - // TODO + switch (mData[2] & 0x0F) + { + case 0: + return OM_AUTO; + case 1: + return OM_ECO_ACTIVE; + case 2: + return OM_ECO_INACTIVE; + case 9: + return OM_BOOST; + // TODO: implement absence + default: + return OM_UNKNOWN; + } return OM_UNKNOWN; } void HMIMessage::setOperationMode(HMIOperationMode operationMode) const { - // TODO +// TODO } HMIOperationType HMIMessage::getOperationType() const { - // TODO - return HMIOperationType::ALWAYS_ON; + if (mData[3] & 0x40) + { + return HMIOperationType::ALWAYS_ON; + } + return HMIOperationType::TIMER; } void HMIMessage::setOperationType(HMIOperationType operationType) const @@ -178,8 +193,9 @@ void HMIMessage::setDateMonthAndYear(uint8_t month, uint16_t year) const } uint8_t HMIMessage::dateMonth() const { - return (mData[17] >> 5) + ((mData[18] % 2) * 8); + return 1 + (mData[17] >> 5) + ((mData[18] % 2) * 8); } + uint8_t HMIMessage::dateDay() const { return mData[17] & 0x1F; @@ -217,6 +233,7 @@ uint8_t HMIMessage::errorRequestId() const // TODO return 0; } + uint8_t HMIMessage::errorNumberRequested() const { // TODO @@ -253,6 +270,12 @@ void HMIMessage::compareWith(uint8_t* data) switch (indiceChanged) { + case 1: + mTargetTempChanged = true; + break; + case 2: + mOperationModeChanged = true; + break; case 16: case 19: case 20: diff --git a/AquaMQTT/src/task/MQTTTask.cpp b/AquaMQTT/src/task/MQTTTask.cpp index 54d1172..fc9efdf 100644 --- a/AquaMQTT/src/task/MQTTTask.cpp +++ b/AquaMQTT/src/task/MQTTTask.cpp @@ -514,92 +514,92 @@ void MQTTTask::updateStats() } void MQTTTask::updateMainStatus(bool fullUpdate) { -// message::MainStatusMessage message(mTransferBuffer); -// -// applyTemperatureFilter(&message); -// -// message.compareWith(fullUpdate ? nullptr : mLastProcessedMainMessage); -// -// if (message.hotWaterTempChanged()) -// { -// publishFloat(MAIN_SUBTOPIC, MAIN_HOT_WATER_TEMP, message.hotWaterTemp()); -// } -// if (message.airTempChanged()) -// { -// publishFloat(MAIN_SUBTOPIC, MAIN_SUPPLY_AIR_TEMP, message.airTemp()); -// } -// if (message.evaporatorLowerAirTempChanged()) -// { -// publishFloat(MAIN_SUBTOPIC, MAIN_EVAPORATOR_AIR_TEMP_LOWER, message.evaporatorLowerAirTemp()); -// } -// if (message.evaporatorUpperAirTempChanged()) -// { -// publishFloat(MAIN_SUBTOPIC, MAIN_EVAPORATOR_AIR_TEMP_UPPER, message.evaporatorUpperAirTemp()); -// } -// if (message.fanSpeedChanged()) -// { -// publishFloat(MAIN_SUBTOPIC, MAIN_FAN_PWM, message.fanSpeedPwm()); -// } -// if (message.statesChanged()) -// { -// publishi(MAIN_SUBTOPIC, MAIN_STATE_HEAT_ELEMENT, message.stateHeatingElement()); -// publishi(MAIN_SUBTOPIC, MAIN_STATE_HEATPUMP, message.stateHeatpump()); -// publishi(MAIN_SUBTOPIC, MAIN_STATE_EXT_BOILER, message.stateBoilerBackup()); -// publishi(MAIN_SUBTOPIC, MAIN_STATE_FAN, message.stateFan()); -// publishi(MAIN_SUBTOPIC, MAIN_STATE_DEFROST, message.stateDefrost()); -// } -// -// if (message.statePVOrSolarChanged()) -// { -// publishi(MAIN_SUBTOPIC, MAIN_STATE_PV, message.statePV()); -// publishi(MAIN_SUBTOPIC, MAIN_STATE_SOLAR, message.stateSolar()); -// } -// -// if (message.settingPwmFirstChanged()) -// { -// publishi(MAIN_SUBTOPIC, MAIN_SETTING_PWM_01, message.settingPwmFirst()); -// } -// if (message.settingPwmSecondChanged()) -// { -// publishi(MAIN_SUBTOPIC, MAIN_SETTING_PWM_02, message.settingPwmSecond()); -// } -// if (message.settingPwmThirdChanged()) -// { -// publishi(MAIN_SUBTOPIC, MAIN_SETTING_PWM_03, message.settingPwmThird()); -// } -// if (message.settingMinTTargetChanged()) -// { -// publishi(MAIN_SUBTOPIC, MAIN_SETTING_MIN_TEMP_TARGET, message.settingMinTTarget()); -// } -// if (message.settingLegionellaTTargetChanged()) -// { -// publishi(MAIN_SUBTOPIC, MAIN_SETTING_MIN_TEMP_LEGIONELLA, message.settingLegionellaTTarget()); -// } -// if (message.settingWattageHeatingElementChanged()) -// { -// publishi(MAIN_SUBTOPIC, MAIN_SETTING_PWR_HEATELEM, message.settingWattageHeatingElement()); -// } -// if (message.settingBoilerCapacityChanged()) -// { -// publishi(MAIN_SUBTOPIC, MAIN_SETTING_BOILER_CAP, message.settingBoilerCapacity()); -// } -// if (message.settingBrandChanged()) -// { -// publishString(MAIN_SUBTOPIC, MAIN_SETTING_BOILER_BRAND, brandStr(message.settingBrand())); -// } -// if (message.settingCapabilitiesChanged()) -// { -// publishi(MAIN_SUBTOPIC, MAIN_CAPABILITY_HEAT_EXC, message.capabilityHasHeatExchanger()); -// publishi(MAIN_SUBTOPIC, MAIN_CAPABILITY_CIRCULATION, message.capabilityHasCirculation()); -// publishi(MAIN_SUBTOPIC, MAIN_CAPABILITY_PV_INPUT, message.capabilityHasPVInput()); -// publishi(MAIN_SUBTOPIC, MAIN_CAPABILITY_EXT_COMM, message.capabilityHasCommunication()); -// publishi(MAIN_SUBTOPIC, MAIN_CAPABILITY_DRY_HEATING, message.capabilityHasAntiDryHeating()); -// } -// -// if (message.errorCodeChanged()) -// { -// publishi(MAIN_SUBTOPIC, MAIN_ERROR_CODE, message.errorCode()); -// } + // message::MainStatusMessage message(mTransferBuffer); + // + // applyTemperatureFilter(&message); + // + // message.compareWith(fullUpdate ? nullptr : mLastProcessedMainMessage); + // + // if (message.hotWaterTempChanged()) + // { + // publishFloat(MAIN_SUBTOPIC, MAIN_HOT_WATER_TEMP, message.hotWaterTemp()); + // } + // if (message.airTempChanged()) + // { + // publishFloat(MAIN_SUBTOPIC, MAIN_SUPPLY_AIR_TEMP, message.airTemp()); + // } + // if (message.evaporatorLowerAirTempChanged()) + // { + // publishFloat(MAIN_SUBTOPIC, MAIN_EVAPORATOR_AIR_TEMP_LOWER, message.evaporatorLowerAirTemp()); + // } + // if (message.evaporatorUpperAirTempChanged()) + // { + // publishFloat(MAIN_SUBTOPIC, MAIN_EVAPORATOR_AIR_TEMP_UPPER, message.evaporatorUpperAirTemp()); + // } + // if (message.fanSpeedChanged()) + // { + // publishFloat(MAIN_SUBTOPIC, MAIN_FAN_PWM, message.fanSpeedPwm()); + // } + // if (message.statesChanged()) + // { + // publishi(MAIN_SUBTOPIC, MAIN_STATE_HEAT_ELEMENT, message.stateHeatingElement()); + // publishi(MAIN_SUBTOPIC, MAIN_STATE_HEATPUMP, message.stateHeatpump()); + // publishi(MAIN_SUBTOPIC, MAIN_STATE_EXT_BOILER, message.stateBoilerBackup()); + // publishi(MAIN_SUBTOPIC, MAIN_STATE_FAN, message.stateFan()); + // publishi(MAIN_SUBTOPIC, MAIN_STATE_DEFROST, message.stateDefrost()); + // } + // + // if (message.statePVOrSolarChanged()) + // { + // publishi(MAIN_SUBTOPIC, MAIN_STATE_PV, message.statePV()); + // publishi(MAIN_SUBTOPIC, MAIN_STATE_SOLAR, message.stateSolar()); + // } + // + // if (message.settingPwmFirstChanged()) + // { + // publishi(MAIN_SUBTOPIC, MAIN_SETTING_PWM_01, message.settingPwmFirst()); + // } + // if (message.settingPwmSecondChanged()) + // { + // publishi(MAIN_SUBTOPIC, MAIN_SETTING_PWM_02, message.settingPwmSecond()); + // } + // if (message.settingPwmThirdChanged()) + // { + // publishi(MAIN_SUBTOPIC, MAIN_SETTING_PWM_03, message.settingPwmThird()); + // } + // if (message.settingMinTTargetChanged()) + // { + // publishi(MAIN_SUBTOPIC, MAIN_SETTING_MIN_TEMP_TARGET, message.settingMinTTarget()); + // } + // if (message.settingLegionellaTTargetChanged()) + // { + // publishi(MAIN_SUBTOPIC, MAIN_SETTING_MIN_TEMP_LEGIONELLA, message.settingLegionellaTTarget()); + // } + // if (message.settingWattageHeatingElementChanged()) + // { + // publishi(MAIN_SUBTOPIC, MAIN_SETTING_PWR_HEATELEM, message.settingWattageHeatingElement()); + // } + // if (message.settingBoilerCapacityChanged()) + // { + // publishi(MAIN_SUBTOPIC, MAIN_SETTING_BOILER_CAP, message.settingBoilerCapacity()); + // } + // if (message.settingBrandChanged()) + // { + // publishString(MAIN_SUBTOPIC, MAIN_SETTING_BOILER_BRAND, brandStr(message.settingBrand())); + // } + // if (message.settingCapabilitiesChanged()) + // { + // publishi(MAIN_SUBTOPIC, MAIN_CAPABILITY_HEAT_EXC, message.capabilityHasHeatExchanger()); + // publishi(MAIN_SUBTOPIC, MAIN_CAPABILITY_CIRCULATION, message.capabilityHasCirculation()); + // publishi(MAIN_SUBTOPIC, MAIN_CAPABILITY_PV_INPUT, message.capabilityHasPVInput()); + // publishi(MAIN_SUBTOPIC, MAIN_CAPABILITY_EXT_COMM, message.capabilityHasCommunication()); + // publishi(MAIN_SUBTOPIC, MAIN_CAPABILITY_DRY_HEATING, message.capabilityHasAntiDryHeating()); + // } + // + // if (message.errorCodeChanged()) + // { + // publishi(MAIN_SUBTOPIC, MAIN_ERROR_CODE, message.errorCode()); + // } if (config::DEBUG_RAW_SERIAL_MESSAGES) { @@ -619,19 +619,19 @@ void MQTTTask::updateHMIStatus(bool fullUpdate) { message::HMIMessage message(mTransferBuffer); message.compareWith(fullUpdate ? nullptr : mLastProcessedHMIMessage); -// -// if (message.waterTempTargetChanged()) -// { -// publishFloat(HMI_SUBTOPIC, HMI_HOT_WATER_TEMP_TARGET, message.waterTempTarget()); -// } -// -// if (message.operationTypeOrModeChanged()) -// { -// publishString(HMI_SUBTOPIC, HMI_OPERATION_MODE, operationModeStr(message.operationMode())); -// -// publishString(HMI_SUBTOPIC, HMI_OPERATION_TYPE, operationTypeStr(message.getOperationType())); -// } -// + + if (message.waterTempTargetChanged()) + { + publishFloat(HMI_SUBTOPIC, HMI_HOT_WATER_TEMP_TARGET, message.waterTempTarget()); + } + + if (message.operationTypeOrModeChanged()) + { + publishString(HMI_SUBTOPIC, HMI_OPERATION_MODE, operationModeStr(message.operationMode())); + + publishString(HMI_SUBTOPIC, HMI_OPERATION_TYPE, operationTypeStr(message.getOperationType())); + } + if (config::MQTT_PUBLISH_HEATPUMP_TIME_AND_DATE && message.timeChanged()) { sprintf(reinterpret_cast(mPayloadBuffer), @@ -663,77 +663,78 @@ void MQTTTask::updateHMIStatus(bool fullUpdate) HMI_DATE); mMQTTClient.publish(reinterpret_cast(mTopicBuffer), reinterpret_cast(mPayloadBuffer)); } -// -// if (message.emergencyModeChanged()) -// { -// publishi(HMI_SUBTOPIC, HMI_EMERGENCY_MODE, message.isEmergencyModeEnabled()); -// } -// -// if (message.heatingElemOrSetupStateOrPVActiveChanged()) -// { -// publishi(HMI_SUBTOPIC, HMI_HEATING_ELEMENT_ENABLED, message.isHeatingElementEnabled()); -// publishi(HMI_SUBTOPIC, HMM_PV_INPUT_ACTIVATED, message.isPVInputActivated()); -// publishString(HMI_SUBTOPIC, HMI_SETUP_STATE, setupStr(message.setupMode())); -// } -// -// if (message.legionellaOrAirductChanged()) -// { -// publishi(HMI_SUBTOPIC, HMI_LEGIONELLA, message.antiLegionellaModePerMonth()); -// publishString(HMI_SUBTOPIC, HMI_AIR_DUCT_CONFIG, aquamqtt::message::airDuctConfigStr(message.airDuctConfig())); -// } -// -// if (message.testModeChanged()) -// { -// publishString(HMI_SUBTOPIC, HMI_TEST_MODE, testModeStr(message.testMode())); -// } -// -// if (message.installationConfigChanged()) -// { -// publishString(HMI_SUBTOPIC, HMI_INSTALLATION_CONFIG, installationModeStr(message.installationMode())); -// } -// -// if (message.exhaustFanChanged()) -// { -// publishString(HMI_SUBTOPIC, HMI_FAN_EXHAUST_CONFIG, exhaustModeStr(message.fanExhaust())); -// } -// -// if (message.timerModeOneChanged()) -// { -// sprintf(reinterpret_cast(mTopicBuffer), -// "%s%s%s%s", -// config::mqttPrefix, -// BASE_TOPIC, -// HMI_SUBTOPIC, -// HMI_TIMER_WINDOW_A); -// message.timerWindowStr(true, reinterpret_cast(mPayloadBuffer)); -// mMQTTClient.publish(reinterpret_cast(mTopicBuffer), reinterpret_cast(mPayloadBuffer)); -// } -// -// if (message.timerModeTwoChanged()) -// { -// sprintf(reinterpret_cast(mTopicBuffer), -// "%s%s%s%s", -// config::mqttPrefix, -// BASE_TOPIC, -// HMI_SUBTOPIC, -// HMI_TIMER_WINDOW_B); -// message.timerWindowStr(false, reinterpret_cast(mPayloadBuffer)); -// mMQTTClient.publish(reinterpret_cast(mTopicBuffer), reinterpret_cast(mPayloadBuffer)); -// } -// -// // publish the error number to the request id -// if (message.errorRequestChanged() && message.errorRequestId() != 0) -// { -// sprintf(reinterpret_cast(mTopicBuffer), -// "%s%s%s%u/%s", -// config::mqttPrefix, -// BASE_TOPIC, -// ERROR_SUBTOPIC, -// message.errorRequestId(), -// ERROR_ERROR_NUMBER); -// itoa(message.errorNumberRequested(), reinterpret_cast(mPayloadBuffer), 10); -// mMQTTClient.publish(reinterpret_cast(mTopicBuffer), reinterpret_cast(mPayloadBuffer)); -// } + // + // if (message.emergencyModeChanged()) + // { + // publishi(HMI_SUBTOPIC, HMI_EMERGENCY_MODE, message.isEmergencyModeEnabled()); + // } + // + // if (message.heatingElemOrSetupStateOrPVActiveChanged()) + // { + // publishi(HMI_SUBTOPIC, HMI_HEATING_ELEMENT_ENABLED, message.isHeatingElementEnabled()); + // publishi(HMI_SUBTOPIC, HMM_PV_INPUT_ACTIVATED, message.isPVInputActivated()); + // publishString(HMI_SUBTOPIC, HMI_SETUP_STATE, setupStr(message.setupMode())); + // } + // + // if (message.legionellaOrAirductChanged()) + // { + // publishi(HMI_SUBTOPIC, HMI_LEGIONELLA, message.antiLegionellaModePerMonth()); + // publishString(HMI_SUBTOPIC, HMI_AIR_DUCT_CONFIG, + // aquamqtt::message::airDuctConfigStr(message.airDuctConfig())); + // } + // + // if (message.testModeChanged()) + // { + // publishString(HMI_SUBTOPIC, HMI_TEST_MODE, testModeStr(message.testMode())); + // } + // + // if (message.installationConfigChanged()) + // { + // publishString(HMI_SUBTOPIC, HMI_INSTALLATION_CONFIG, installationModeStr(message.installationMode())); + // } + // + // if (message.exhaustFanChanged()) + // { + // publishString(HMI_SUBTOPIC, HMI_FAN_EXHAUST_CONFIG, exhaustModeStr(message.fanExhaust())); + // } + // + // if (message.timerModeOneChanged()) + // { + // sprintf(reinterpret_cast(mTopicBuffer), + // "%s%s%s%s", + // config::mqttPrefix, + // BASE_TOPIC, + // HMI_SUBTOPIC, + // HMI_TIMER_WINDOW_A); + // message.timerWindowStr(true, reinterpret_cast(mPayloadBuffer)); + // mMQTTClient.publish(reinterpret_cast(mTopicBuffer), reinterpret_cast(mPayloadBuffer)); + // } + // + // if (message.timerModeTwoChanged()) + // { + // sprintf(reinterpret_cast(mTopicBuffer), + // "%s%s%s%s", + // config::mqttPrefix, + // BASE_TOPIC, + // HMI_SUBTOPIC, + // HMI_TIMER_WINDOW_B); + // message.timerWindowStr(false, reinterpret_cast(mPayloadBuffer)); + // mMQTTClient.publish(reinterpret_cast(mTopicBuffer), reinterpret_cast(mPayloadBuffer)); + // } + // + // // publish the error number to the request id + // if (message.errorRequestChanged() && message.errorRequestId() != 0) + // { + // sprintf(reinterpret_cast(mTopicBuffer), + // "%s%s%s%u/%s", + // config::mqttPrefix, + // BASE_TOPIC, + // ERROR_SUBTOPIC, + // message.errorRequestId(), + // ERROR_ERROR_NUMBER); + // itoa(message.errorNumberRequested(), reinterpret_cast(mPayloadBuffer), 10); + // mMQTTClient.publish(reinterpret_cast(mTopicBuffer), reinterpret_cast(mPayloadBuffer)); + // } if (config::DEBUG_RAW_SERIAL_MESSAGES) { @@ -751,55 +752,55 @@ void MQTTTask::updateHMIStatus(bool fullUpdate) void MQTTTask::updateEnergyStats(bool fullUpdate) { -// message::MainEnergyMessage message(mTransferBuffer); -// message.compareWith(fullUpdate ? nullptr : mLastProcessedEnergyMessage); -// -// if (message.totalHeatpumpHoursChanged()) -// { -// publishul(ENERGY_SUBTOPIC, ENERGY_TOTAL_HEATPUMP_HOURS, message.totalHeatpumpHours(), true); -// } -// if (message.totalHeatingElemHoursChanged()) -// { -// publishul(ENERGY_SUBTOPIC, ENERGY_TOTAL_HEATING_ELEM_HOURS, message.totalHeatingElemHours(), true); -// } -// if (message.totalHoursChanged()) -// { -// publishul(ENERGY_SUBTOPIC, ENERGY_TOTAL_HOURS, message.totalHours(), true); -// } -// if (message.totalEnergyCounterChanged()) -// { -// publishul(ENERGY_SUBTOPIC, ENERGY_TOTAL_ENERGY_WH, message.totalEnergyCounter(), true); -// } -// -// if (message.powerHeatpumpChanged()) -// { -// publishul(ENERGY_SUBTOPIC, ENERGY_POWER_HEATPUMP, message.powerHeatpump()); -// if (strlen(optionalPublishTopicHeatPumpCurrentPower) != 0) -// { -// sprintf(reinterpret_cast(mTopicBuffer), "%s", optionalPublishTopicHeatPumpCurrentPower); -// mMQTTClient.publish(reinterpret_cast(mTopicBuffer), reinterpret_cast(mPayloadBuffer)); -// } -// } -// -// if (message.powerHeatElementChanged()) -// { -// publishul(ENERGY_SUBTOPIC, ENERGY_POWER_HEAT_ELEMENT, message.powerHeatElement()); -// if (strlen(optionalPublishTopicHeatElementCurrentPower) != 0) -// { -// sprintf(reinterpret_cast(mTopicBuffer), "%s", optionalPublishTopicHeatElementCurrentPower); -// mMQTTClient.publish(reinterpret_cast(mTopicBuffer), reinterpret_cast(mPayloadBuffer)); -// } -// } -// -// if (message.powerOverallChanged()) -// { -// publishul(ENERGY_SUBTOPIC, ENERGY_POWER_TOTAL, message.powerOverall()); -// } -// -// if (message.totalWaterProductionChanged()) -// { -// publishul(ENERGY_SUBTOPIC, ENERGY_TOTAL_WATER_PRODUCTION, message.totalWaterProduction()); -// } + // message::MainEnergyMessage message(mTransferBuffer); + // message.compareWith(fullUpdate ? nullptr : mLastProcessedEnergyMessage); + // + // if (message.totalHeatpumpHoursChanged()) + // { + // publishul(ENERGY_SUBTOPIC, ENERGY_TOTAL_HEATPUMP_HOURS, message.totalHeatpumpHours(), true); + // } + // if (message.totalHeatingElemHoursChanged()) + // { + // publishul(ENERGY_SUBTOPIC, ENERGY_TOTAL_HEATING_ELEM_HOURS, message.totalHeatingElemHours(), true); + // } + // if (message.totalHoursChanged()) + // { + // publishul(ENERGY_SUBTOPIC, ENERGY_TOTAL_HOURS, message.totalHours(), true); + // } + // if (message.totalEnergyCounterChanged()) + // { + // publishul(ENERGY_SUBTOPIC, ENERGY_TOTAL_ENERGY_WH, message.totalEnergyCounter(), true); + // } + // + // if (message.powerHeatpumpChanged()) + // { + // publishul(ENERGY_SUBTOPIC, ENERGY_POWER_HEATPUMP, message.powerHeatpump()); + // if (strlen(optionalPublishTopicHeatPumpCurrentPower) != 0) + // { + // sprintf(reinterpret_cast(mTopicBuffer), "%s", optionalPublishTopicHeatPumpCurrentPower); + // mMQTTClient.publish(reinterpret_cast(mTopicBuffer), reinterpret_cast(mPayloadBuffer)); + // } + // } + // + // if (message.powerHeatElementChanged()) + // { + // publishul(ENERGY_SUBTOPIC, ENERGY_POWER_HEAT_ELEMENT, message.powerHeatElement()); + // if (strlen(optionalPublishTopicHeatElementCurrentPower) != 0) + // { + // sprintf(reinterpret_cast(mTopicBuffer), "%s", optionalPublishTopicHeatElementCurrentPower); + // mMQTTClient.publish(reinterpret_cast(mTopicBuffer), reinterpret_cast(mPayloadBuffer)); + // } + // } + // + // if (message.powerOverallChanged()) + // { + // publishul(ENERGY_SUBTOPIC, ENERGY_POWER_TOTAL, message.powerOverall()); + // } + // + // if (message.totalWaterProductionChanged()) + // { + // publishul(ENERGY_SUBTOPIC, ENERGY_TOTAL_WATER_PRODUCTION, message.totalWaterProduction()); + // } if (config::DEBUG_RAW_SERIAL_MESSAGES) { @@ -817,119 +818,119 @@ void MQTTTask::updateEnergyStats(bool fullUpdate) void MQTTTask::updateErrorStatus() { -// message::ErrorMessage message(mTransferBuffer); -// -// if (message.isEmpty()) -// { -// return; -// } -// -// sprintf(reinterpret_cast(mTopicBuffer), -// "%s%s%s%u/%s", -// config::mqttPrefix, -// BASE_TOPIC, -// ERROR_SUBTOPIC, -// message.errorRequestId(), -// MAIN_ERROR_CODE); -// itoa(message.errorCode(), reinterpret_cast(mPayloadBuffer), 10); -// mMQTTClient.publish(reinterpret_cast(mTopicBuffer), reinterpret_cast(mPayloadBuffer)); -// -// if (!message.isEmpty()) -// { -// sprintf(reinterpret_cast(mPayloadBuffer), -// "%d.%d.%d", -// message.dateDay(), -// message.dateMonth(), -// message.dateYear()); -// sprintf(reinterpret_cast(mTopicBuffer), -// "%s%s%s%u/%s", -// config::mqttPrefix, -// BASE_TOPIC, -// ERROR_SUBTOPIC, -// message.errorRequestId(), -// HMI_DATE); -// mMQTTClient.publish(reinterpret_cast(mTopicBuffer), reinterpret_cast(mPayloadBuffer)); -// -// sprintf(reinterpret_cast(mPayloadBuffer), "%02d:%02d", message.timeHours(), message.timeMinutes()); -// sprintf(reinterpret_cast(mTopicBuffer), -// "%s%s%s%u/%s", -// config::mqttPrefix, -// BASE_TOPIC, -// ERROR_SUBTOPIC, -// message.errorRequestId(), -// HMI_TIME); -// mMQTTClient.publish(reinterpret_cast(mTopicBuffer), reinterpret_cast(mPayloadBuffer)); -// -// dtostrf(message.hotWaterTemp(), 3, 1, reinterpret_cast(mPayloadBuffer)); -// sprintf(reinterpret_cast(mTopicBuffer), -// "%s%s%s%u/%s", -// config::mqttPrefix, -// BASE_TOPIC, -// ERROR_SUBTOPIC, -// message.errorRequestId(), -// MAIN_HOT_WATER_TEMP); -// mMQTTClient.publish(reinterpret_cast(mTopicBuffer), reinterpret_cast(mPayloadBuffer)); -// -// dtostrf(message.airTemp(), 3, 1, reinterpret_cast(mPayloadBuffer)); -// sprintf(reinterpret_cast(mTopicBuffer), -// "%s%s%s%u/%s", -// config::mqttPrefix, -// BASE_TOPIC, -// ERROR_SUBTOPIC, -// message.errorRequestId(), -// MAIN_SUPPLY_AIR_TEMP); -// mMQTTClient.publish(reinterpret_cast(mTopicBuffer), reinterpret_cast(mPayloadBuffer)); -// -// dtostrf(message.evaporatorLowerAirTemp(), 3, 1, reinterpret_cast(mPayloadBuffer)); -// sprintf(reinterpret_cast(mTopicBuffer), -// "%s%s%s%u/%s", -// config::mqttPrefix, -// BASE_TOPIC, -// ERROR_SUBTOPIC, -// message.errorRequestId(), -// MAIN_EVAPORATOR_AIR_TEMP_LOWER); -// mMQTTClient.publish(reinterpret_cast(mTopicBuffer), reinterpret_cast(mPayloadBuffer)); -// -// dtostrf(message.evaporatorUpperAirTemp(), 3, 1, reinterpret_cast(mPayloadBuffer)); -// sprintf(reinterpret_cast(mTopicBuffer), -// "%s%s%s%u/%s", -// config::mqttPrefix, -// BASE_TOPIC, -// ERROR_SUBTOPIC, -// message.errorRequestId(), -// MAIN_EVAPORATOR_AIR_TEMP_UPPER); -// mMQTTClient.publish(reinterpret_cast(mTopicBuffer), reinterpret_cast(mPayloadBuffer)); -// -// dtostrf(message.fanSpeedPwm(), 3, 1, reinterpret_cast(mPayloadBuffer)); -// sprintf(reinterpret_cast(mTopicBuffer), -// "%s%s%s%u/%s", -// config::mqttPrefix, -// BASE_TOPIC, -// ERROR_SUBTOPIC, -// message.errorRequestId(), -// MAIN_FAN_PWM); -// mMQTTClient.publish(reinterpret_cast(mTopicBuffer), reinterpret_cast(mPayloadBuffer)); -// -// ultoa(message.totalHeatpumpHours(), reinterpret_cast(mPayloadBuffer), 10); -// sprintf(reinterpret_cast(mTopicBuffer), -// "%s%s%s%u/%s", -// config::mqttPrefix, -// BASE_TOPIC, -// ERROR_SUBTOPIC, -// message.errorRequestId(), -// ENERGY_TOTAL_HEATPUMP_HOURS); -// mMQTTClient.publish(reinterpret_cast(mTopicBuffer), reinterpret_cast(mPayloadBuffer)); -// -// ultoa(message.totalHeatingElemHours(), reinterpret_cast(mPayloadBuffer), 10); -// sprintf(reinterpret_cast(mTopicBuffer), -// "%s%s%s%u/%s", -// config::mqttPrefix, -// BASE_TOPIC, -// ERROR_SUBTOPIC, -// message.errorRequestId(), -// ENERGY_TOTAL_HEATING_ELEM_HOURS); -// mMQTTClient.publish(reinterpret_cast(mTopicBuffer), reinterpret_cast(mPayloadBuffer)); -// } + // message::ErrorMessage message(mTransferBuffer); + // + // if (message.isEmpty()) + // { + // return; + // } + // + // sprintf(reinterpret_cast(mTopicBuffer), + // "%s%s%s%u/%s", + // config::mqttPrefix, + // BASE_TOPIC, + // ERROR_SUBTOPIC, + // message.errorRequestId(), + // MAIN_ERROR_CODE); + // itoa(message.errorCode(), reinterpret_cast(mPayloadBuffer), 10); + // mMQTTClient.publish(reinterpret_cast(mTopicBuffer), reinterpret_cast(mPayloadBuffer)); + // + // if (!message.isEmpty()) + // { + // sprintf(reinterpret_cast(mPayloadBuffer), + // "%d.%d.%d", + // message.dateDay(), + // message.dateMonth(), + // message.dateYear()); + // sprintf(reinterpret_cast(mTopicBuffer), + // "%s%s%s%u/%s", + // config::mqttPrefix, + // BASE_TOPIC, + // ERROR_SUBTOPIC, + // message.errorRequestId(), + // HMI_DATE); + // mMQTTClient.publish(reinterpret_cast(mTopicBuffer), reinterpret_cast(mPayloadBuffer)); + // + // sprintf(reinterpret_cast(mPayloadBuffer), "%02d:%02d", message.timeHours(), + // message.timeMinutes()); sprintf(reinterpret_cast(mTopicBuffer), + // "%s%s%s%u/%s", + // config::mqttPrefix, + // BASE_TOPIC, + // ERROR_SUBTOPIC, + // message.errorRequestId(), + // HMI_TIME); + // mMQTTClient.publish(reinterpret_cast(mTopicBuffer), reinterpret_cast(mPayloadBuffer)); + // + // dtostrf(message.hotWaterTemp(), 3, 1, reinterpret_cast(mPayloadBuffer)); + // sprintf(reinterpret_cast(mTopicBuffer), + // "%s%s%s%u/%s", + // config::mqttPrefix, + // BASE_TOPIC, + // ERROR_SUBTOPIC, + // message.errorRequestId(), + // MAIN_HOT_WATER_TEMP); + // mMQTTClient.publish(reinterpret_cast(mTopicBuffer), reinterpret_cast(mPayloadBuffer)); + // + // dtostrf(message.airTemp(), 3, 1, reinterpret_cast(mPayloadBuffer)); + // sprintf(reinterpret_cast(mTopicBuffer), + // "%s%s%s%u/%s", + // config::mqttPrefix, + // BASE_TOPIC, + // ERROR_SUBTOPIC, + // message.errorRequestId(), + // MAIN_SUPPLY_AIR_TEMP); + // mMQTTClient.publish(reinterpret_cast(mTopicBuffer), reinterpret_cast(mPayloadBuffer)); + // + // dtostrf(message.evaporatorLowerAirTemp(), 3, 1, reinterpret_cast(mPayloadBuffer)); + // sprintf(reinterpret_cast(mTopicBuffer), + // "%s%s%s%u/%s", + // config::mqttPrefix, + // BASE_TOPIC, + // ERROR_SUBTOPIC, + // message.errorRequestId(), + // MAIN_EVAPORATOR_AIR_TEMP_LOWER); + // mMQTTClient.publish(reinterpret_cast(mTopicBuffer), reinterpret_cast(mPayloadBuffer)); + // + // dtostrf(message.evaporatorUpperAirTemp(), 3, 1, reinterpret_cast(mPayloadBuffer)); + // sprintf(reinterpret_cast(mTopicBuffer), + // "%s%s%s%u/%s", + // config::mqttPrefix, + // BASE_TOPIC, + // ERROR_SUBTOPIC, + // message.errorRequestId(), + // MAIN_EVAPORATOR_AIR_TEMP_UPPER); + // mMQTTClient.publish(reinterpret_cast(mTopicBuffer), reinterpret_cast(mPayloadBuffer)); + // + // dtostrf(message.fanSpeedPwm(), 3, 1, reinterpret_cast(mPayloadBuffer)); + // sprintf(reinterpret_cast(mTopicBuffer), + // "%s%s%s%u/%s", + // config::mqttPrefix, + // BASE_TOPIC, + // ERROR_SUBTOPIC, + // message.errorRequestId(), + // MAIN_FAN_PWM); + // mMQTTClient.publish(reinterpret_cast(mTopicBuffer), reinterpret_cast(mPayloadBuffer)); + // + // ultoa(message.totalHeatpumpHours(), reinterpret_cast(mPayloadBuffer), 10); + // sprintf(reinterpret_cast(mTopicBuffer), + // "%s%s%s%u/%s", + // config::mqttPrefix, + // BASE_TOPIC, + // ERROR_SUBTOPIC, + // message.errorRequestId(), + // ENERGY_TOTAL_HEATPUMP_HOURS); + // mMQTTClient.publish(reinterpret_cast(mTopicBuffer), reinterpret_cast(mPayloadBuffer)); + // + // ultoa(message.totalHeatingElemHours(), reinterpret_cast(mPayloadBuffer), 10); + // sprintf(reinterpret_cast(mTopicBuffer), + // "%s%s%s%u/%s", + // config::mqttPrefix, + // BASE_TOPIC, + // ERROR_SUBTOPIC, + // message.errorRequestId(), + // ENERGY_TOTAL_HEATING_ELEM_HOURS); + // mMQTTClient.publish(reinterpret_cast(mTopicBuffer), reinterpret_cast(mPayloadBuffer)); + // } if (config::DEBUG_RAW_SERIAL_MESSAGES) { diff --git a/PROTOCOL_NEXT.md b/PROTOCOL_NEXT.md index e69de29..38e2c17 100644 --- a/PROTOCOL_NEXT.md +++ b/PROTOCOL_NEXT.md @@ -0,0 +1,217 @@ +# Protocol (NEXT) + +Another heat pump protocol observed in https://github.com/tspopp/AquaMQTT/issues/45 with an _Austria Email BWWP 200 WT SMART COZY_ heat pump. + +## Message Format + +``` +ID LEN PAYLOAD CHECKSUM +C1 23 2E00230018001800150000000000000000000000008200000000454528CB000E0111 44 +C2 22 32120000001000062C01D0020000003A211E0C0C000000004E450000060422013E FA +43 2D 0000071D0000000000000000071D0000EEB2390000000000000000000B4C105AFB27FB250B1B000000000000 57 +``` + +## Identifier + +- 1 byte message identifier +- 1 byte payload length (length field and payload size) +- 1-254 bytes payload +- 1 bytes checksum + +## Checksum + +Checksum calculation is yet unknown. + +*TODO: A long time (e.g. two minutes) dump of AquaDebug is required* + +## Messages + +### HMI Message (194) + +| Byte Number | Example (dec) | Purpose/Function | Other Information | +|-------------|---------------|--------------------------------|-------------------| +| 0 | 34 | Length Field | | +| 1 | 50 | Water Target Temperature | | +| 2 | 18 | Operation Mode, Operation Type | See table below | +| 3 | 0 | ? | | +| 4 | 0 | ? | | +| 5 | 0 | ? | | +| 6 | 16 | ? | | +| 7 | 0 | ? | | +| 8 | 6 | ? | | +| 9 | 44 | ? | | +| 10 | 1 | ? | | +| 11 | 208 | ? | | +| 12 | 2 | ? | | +| 13 | 0 | ? | | +| 14 | 0 | ? | | +| 15 | 0 | ? | | +| 16 | 59 | Time Seconds | | +| 17 | 33 | Date Day, Month | | +| 18 | 30 | Date Year, Month | | +| 19 | 12 | Time Minutes | | +| 20 | 12 | Time Hours | | +| 21 | 0 | ? | | +| 22 | 0 | ? | | +| 23 | 0 | ? | | +| 24 | 0 | ? | | +| 25 | 78 | ? | | +| 26 | 69 | ? | | +| 27 | 0 | ? | | +| 28 | 0 | ? | | +| 29 | 6 | ? | | +| 30 | 4 | ? | | +| 31 | 34 | ? | | +| 32 | 1 | ? | | +| 33 | 62 | ? | | + + +##### Byte No. 2: Operation Mode + +| Bit Number | Purpose/Function | Other Information | +|------------|------------------|--------------------------------------------------------------------------| +| 0 - 3 | Operation Mode | Interpreted as integer, 0 == Auto, 1 == ECO ON, 2 == ECO OFF, 9 == BOOST | +| 4 - 7 | Operation Type | Interpreted as integer, 1 == Timer, 4 == Continious | + + + +## Help Required: + +- *TODO: OperationMode: ~~Boost, Eco On, Eco Off, Auto,~~ Absence* +- *TODO: TimerWindow A/B* +- *TODO: Anti-Legionalla Setting* +- *TODO: AirDuct Config: INT/INT, EXT/INT, EXT/EXT* +- *TODO: Installation Config: WP-Only, WP+ExtBoiler-Prio-WP,...* +- *TODO: Exhaust Fan Config: (Only in EXT/INT): STOP, LOW-SPEED, HIGH-SPEED* +- *TODO: Heating Element Enabled On/Off* +- *TODO: PV Mode allowed On/Off* + +### Main Message (193) + +| Byte Number | Example (dec) | Purpose/Function | Other Information | +|-------------|---------------|------------------|-------------------| +| 0 | 35 | Length Field | | +| 1 | 46 | ? | | +| 2 | 0 | ? | | +| 3 | 35 | ? | | +| 4 | 0 | ? | | +| 5 | 24 | ? | | +| 6 | 0 | ? | | +| 7 | 24 | ? | | +| 8 | 0 | ? | | +| 9 | 21 | ? | | +| 10 | 0 | ? | | +| 11 | 0 | ? | | +| 12 | 0 | ? | | +| 13 | 0 | ? | | +| 14 | 0 | ? | | +| 15 | 0 | ? | | +| 16 | 0 | ? | | +| 17 | 0 | ? | | +| 18 | 0 | ? | | +| 19 | 0 | ? | | +| 20 | 0 | ? | | +| 21 | 0 | ? | | +| 22 | 130 | ? | | +| 23 | 0 | ? | | +| 24 | 0 | ? | | +| 25 | 0 | ? | | +| 26 | 0 | ? | | +| 27 | 69 | ? | | +| 28 | 69 | ? | | +| 29 | 40 | ? | | +| 30 | 203 | ? | | +| 31 | 0 | ? | | +| 32 | 14 | ? | | +| 33 | 1 | ? | | +| 34 | 17 | ? | | + +## Help Required: + +_To identify this attributes within the message, try to locate the information within the HMI controller, +and provide a photo of the HMI controller together with a dump of the *main* message. We should find the values shown in the HMI controller within the message. +For determining the values from super secret menu, you change a setting in the super secret menu of the hmi controller and watch the change of main message._ + +- *TODO: Hot Water Temp* +- *TODO: Input Air Temp* +- *TODO: Lower Evaporator Temp* +- *TODO: Upper Evaporator Temp* +- *TODO: PWM Level Settings (Super Secret Menu)* +- *TODO: Status Bitmask (Fan On/Off, Defrost On/Off, PV On/Off, Solar On/Off, HeatElement On/Off, HeatPump On/Off, Boiler Backup On/Off)* +- *TODO: Current Fan PWM Level* +- *TODO: Min T Target (Super Secret Menu)* +- *TODO: Anti-Legionella T Target (Super Secret Menu)* +- *TODO: Error Codes* +- *TODO: Wattage Heat Element (Super Secret Menu)* +- *TODO: Boiler Capacity (Super Secret Menu)* +- *TODO: Brand (Super Secret Menu)* +- *TODO: Setting Bitflags (Super Secret Menu)* + +### Energy Message (67) + +| Byte Number | Example (dec) | Purpose/Function | Other Information | +|-------------|---------------|------------------|-------------------| +| 0 | 45 | Length Field | | +| 1 | 0 | ? | | +| 2 | 0 | ? | | +| 3 | 7 | ? | | +| 4 | 29 | ? | | +| 5 | 0 | ? | | +| 6 | 0 | ? | | +| 7 | 0 | ? | | +| 8 | 0 | ? | | +| 9 | 0 | ? | | +| 10 | 0 | ? | | +| 11 | 0 | ? | | +| 12 | 0 | ? | | +| 13 | 7 | ? | | +| 14 | 29 | ? | | +| 15 | 0 | ? | | +| 16 | 0 | ? | | +| 17 | 238 | ? | | +| 18 | 178 | ? | | +| 19 | 57 | ? | | +| 20 | 0 | ? | | +| 21 | 0 | ? | | +| 22 | 0 | ? | | +| 23 | 0 | ? | | +| 24 | 0 | ? | | +| 25 | 0 | ? | | +| 26 | 0 | ? | | +| 27 | 0 | ? | | +| 28 | 0 | ? | | +| 29 | 11 | ? | | +| 30 | 76 | ? | | +| 31 | 16 | ? | | +| 32 | 90 | ? | | +| 33 | 251 | ? | | +| 34 | 39 | ? | | +| 35 | 251 | ? | | +| 36 | 37 | ? | | +| 37 | 11 | ? | | +| 38 | 27 | ? | | +| 39 | 0 | ? | | +| 40 | 0 | ? | | +| 41 | 0 | ? | | +| 42 | 0 | ? | | +| 43 | 0 | ? | | +| 44 | 0 | ? | | + + +## Help Required: + +_To identify this attributes within the message, try to locate the information within the HMI controller, +and provide a photo of the HMI controller together with a dump of the *energy* message. We should find the values shown in the HMI controller within the message._ + +- *TODO: Power Consumption Heatpump* +- *TODO: Power Consumption Heating Element* +- *TODO: Power Consumption Total (Both)* +- *TODO: Total Water Production (l)* +- *TODO: Total Operation Hours (Heatpump)* +- *TODO: Total Operation Hours (Heating Element)* +- *TODO: Total Operation Hours (Both)* +- *TODO: Total Energy Counter (Wh)* + +### Error Message + +*TODO: Requires a running AquaDebug raw trace while opening the [super secret menu](https://github.com/tspopp/AquaMQTT/issues/17) in the hmi controller.*