Skip to content

Commit

Permalink
AM200 settings #573
Browse files Browse the repository at this point in the history
  • Loading branch information
MichaelDvP committed Jul 30, 2022
1 parent ec02e55 commit fb94026
Show file tree
Hide file tree
Showing 4 changed files with 338 additions and 16 deletions.
246 changes: 240 additions & 6 deletions src/devices/boiler.cpp
Expand Up @@ -31,7 +31,8 @@ Boiler::Boiler(uint8_t device_type, int8_t device_id, uint8_t product_id, const
register_telegram_type(0x54D, F("AmTemperatures"), false, MAKE_PF_CB(process_amTempMessage));
register_telegram_type(0x54E, F("AmStatus"), false, MAKE_PF_CB(process_amStatusMessage));
register_telegram_type(0x54F, F("AmCommand"), false, MAKE_PF_CB(process_amCommandMessage)); // not broadcasted, but actually not used
register_telegram_type(0x550, F("AmSettings"), false, MAKE_PF_CB(process_amSettingMessage));
register_telegram_type(0x550, F("AmExtra"), false, MAKE_PF_CB(process_amExtraMessage));
register_telegram_type(0x54C, F("AmSettings"), true, MAKE_PF_CB(process_amSettingMessage)); // not broadcasted

register_device_value(DeviceValueTAG::TAG_AHS, &curFlowTemp_, DeviceValueType::SHORT, FL_(div10), FL_(sysFlowTemp), DeviceValueUOM::DEGREES);
register_device_value(DeviceValueTAG::TAG_AHS, &retTemp_, DeviceValueType::SHORT, FL_(div10), FL_(sysRetTemp), DeviceValueUOM::DEGREES);
Expand All @@ -45,10 +46,56 @@ Boiler::Boiler(uint8_t device_type, int8_t device_id, uint8_t product_id, const
register_device_value(DeviceValueTAG::TAG_AHS, &valveReturn_, DeviceValueType::UINT, nullptr, FL_(valveReturn), DeviceValueUOM::PERCENT);
register_device_value(DeviceValueTAG::TAG_AHS, &aPumpMod_, DeviceValueType::UINT, nullptr, FL_(aPumpMod), DeviceValueUOM::PERCENT);
// register_device_value(DeviceValueTAG::TAG_AHS, &heatSource_, DeviceValueType::BOOL, nullptr, FL_(heatSource), DeviceValueUOM::NONE);
// Settings:
register_device_value(
DeviceValueTAG::TAG_AHS, &vr2Config_, DeviceValueType::ENUM, FL_(enum_vr2Config), FL_(vr2Config), DeviceValueUOM::NONE, MAKE_CF_CB(set_vr2Config));
register_device_value(
DeviceValueTAG::TAG_AHS, &ahsActivated_, DeviceValueType::BOOL, nullptr, FL_(ahsActivated), DeviceValueUOM::NONE, MAKE_CF_CB(set_ahsActivated));
register_device_value(
DeviceValueTAG::TAG_AHS, &aPumpConfig_, DeviceValueType::BOOL, nullptr, FL_(aPumpConfig), DeviceValueUOM::NONE, MAKE_CF_CB(set_aPumpConfig));
register_device_value(DeviceValueTAG::TAG_AHS,
&aPumpSignal_,
DeviceValueType::ENUM,
FL_(enum_aPumpSignal),
FL_(aPumpSignal),
DeviceValueUOM::NONE,
MAKE_CF_CB(set_aPumpSignal));
register_device_value(DeviceValueTAG::TAG_AHS, &aPumpMin_, DeviceValueType::UINT, nullptr, FL_(aPumpMin), DeviceValueUOM::PERCENT, MAKE_CF_CB(set_aPumpMin));
register_device_value(DeviceValueTAG::TAG_AHS, &tempRise_, DeviceValueType::BOOL, nullptr, FL_(tempRise), DeviceValueUOM::NONE, MAKE_CF_CB(set_tempRise));
register_device_value(DeviceValueTAG::TAG_AHS,
&setReturnTemp_,
DeviceValueType::UINT,
nullptr,
FL_(setReturnTemp),
DeviceValueUOM::DEGREES,
MAKE_CF_CB(set_setReturnTemp));
register_device_value(
DeviceValueTAG::TAG_AHS, &mixRuntime_, DeviceValueType::USHORT, nullptr, FL_(mixRuntime), DeviceValueUOM::SECONDS, MAKE_CF_CB(set_mixRuntime));
register_device_value(
DeviceValueTAG::TAG_AHS, &setFlowTemp_, DeviceValueType::UINT, nullptr, FL_(setFlowTemp), DeviceValueUOM::DEGREES, MAKE_CF_CB(set_setFlowTemp));
register_device_value(
DeviceValueTAG::TAG_AHS, &bufBypass_, DeviceValueType::ENUM, FL_(enum_bufBypass), FL_(bufBypass), DeviceValueUOM::NONE, MAKE_CF_CB(set_bufBypass));
register_device_value(DeviceValueTAG::TAG_AHS,
&bufMixRuntime_,
DeviceValueType::USHORT,
nullptr,
FL_(bufMixRuntime),
DeviceValueUOM::SECONDS,
MAKE_CF_CB(set_bufMixRuntime));
register_device_value(
DeviceValueTAG::TAG_AHS, &bufConfig_, DeviceValueType::ENUM, FL_(enum_bufConfig), FL_(bufConfig), DeviceValueUOM::NONE, MAKE_CF_CB(set_bufConfig));
register_device_value(
DeviceValueTAG::TAG_AHS, &blockMode_, DeviceValueType::ENUM, FL_(enum_blockMode), FL_(blockMode), DeviceValueUOM::NONE, MAKE_CF_CB(set_blockMode));
register_device_value(
DeviceValueTAG::TAG_AHS, &blockTerm_, DeviceValueType::ENUM, FL_(enum_blockTerm), FL_(blockTerm), DeviceValueUOM::NONE, MAKE_CF_CB(set_blockTerm));
register_device_value(
DeviceValueTAG::TAG_AHS, &blockHyst_, DeviceValueType::INT, nullptr, FL_(blockHyst), DeviceValueUOM::DEGREES_R, MAKE_CF_CB(set_blockHyst));
register_device_value(
DeviceValueTAG::TAG_AHS, &releaseWait_, DeviceValueType::UINT, nullptr, FL_(releaseWait), DeviceValueUOM::MINUTES, MAKE_CF_CB(set_releaseWait));
return;
}
// cascaded heatingsources, only some values per individual heatsource (hs)
if (device_id != EMSdevice::EMS_DEVICE_ID_BOILER) {
if (device_id >= EMSdevice::EMS_DEVICE_ID_BOILER_1) {
uint8_t hs = device_id - EMSdevice::EMS_DEVICE_ID_BOILER_1; // heating source id, count from 0
// Runtime of each heatingsource in 0x06DC, ff
register_telegram_type(0x6DC + hs, F("CascadeMessage"), false, MAKE_PF_CB(process_CascadeMessage));
Expand Down Expand Up @@ -1187,24 +1234,211 @@ void Boiler::process_amStatusMessage(std::shared_ptr<const Telegram> telegram) {
has_update(telegram, valveBuffer_, 5); // VB1, percent
}

// 0x054C AM200 not broadcasted message, 23 bytes long
// data: 00 01 01 00 01 00 41 4B 00 5A 00 5A 00 01 05 3C 00 00 5A 00 01 23 00
void Boiler::process_amSettingMessage(std::shared_ptr<const Telegram> telegram) {
has_update(telegram, vr2Config_, 12); // pos 12: off(00)/bypass(01)
has_update(telegram, ahsActivated_, 0); // pos 00: Alternate heat source activation: No(00),Yes(01)
has_update(telegram, aPumpConfig_, 4); // pos 04: Buffer primary pump->Config pump: No(00),Yes(01)
has_update(telegram, aPumpSignal_, 3); // pos 03: Output for PR1 pump: On/Off(00),PWM(01),PWM invers(02)
has_update(telegram, aPumpMin_, 21); // pos 21: Min output pump PR1 (%)
has_update(telegram, tempRise_, 1); // pos 01: AHS return temp rise: No(00),Yes(01) (mixer VR1)
has_update(telegram, setReturnTemp_, 6); // pos 06: Set temp return (°C) (VR1)
has_update(telegram, mixRuntime_, 10); // pos 10/11?: Mixer run time (s) (VR1)
has_update(telegram, setFlowTemp_, 7); // pos 07: Set flow temp AHS (°C) (Buffer)
has_update(telegram, bufBypass_, 2); // pos 02: Puffer bypass: No(00), Mischer(01), Ventil(02) (Buffer)
has_update(telegram, bufMixRuntime_, 8); // pos 8/9: Bypass mixer run time: [time] (s) (Buffer)
has_update(telegram, bufConfig_, 20); // pos 20: Konfig WW-Speicher Monovalent(01), Bivalent(02) (buffer)
has_update(telegram, blockMode_, 16); // pos 16: Config htg. blocking mode: No(00),Automatic(01),Always block02) (blocking)
has_update(telegram, blockTerm_, 17); // pos 17: Config of block terminal: NO(00), NC(01)
has_update(telegram, blockHyst_, 14); // pos 14?: Hyst. for bolier block (K)
has_update(telegram, releaseWait_, 15); // pos 15: Boiler release wait time (min)
}

#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Wunused-parameter"

// 0x054F AM200 not broadcasted message, 7 bytes long
// Boiler(0x60) -> Me(0x0B), ?(0x054F), data: 00 00 00 00 00 00 00
// Boiler(0x60) -> Me(0x0B), amCommand(0x054F), data: 00 00 00 00 00 00 00
void Boiler::process_amCommandMessage(std::shared_ptr<const Telegram> telegram) {
// has_update(telegram, setValveBuffer_, 3); // VB1 0-off, 1-open, 2-close
// has_update(telegram, setValveReturn_, 2); // VR1 0-off, 1-open, 2-close
// pos 0: return pump in percent
// pos 3: setValveBuffer VB1 0-off, 1-open, 2-close
// pos 2: setValveReturn VR1 0-off, 1-open, 2-close
// pos 6: boiler blocking 0-off, 1-on
}

// 0x0550 AM200 broadcasted message, all 27 bytes unkown
// Rx: 60 00 FF 00 04 50 00 FF 00 FF FF 00 0D 00 01 00 00 00 00 01 03 01 00 03 00 2D 19 C8 02 94 00 4A
// Rx: 60 00 FF 19 04 50 00 FF FF 39
void Boiler::process_amSettingMessage(std::shared_ptr<const Telegram> telegram) {
void Boiler::process_amExtraMessage(std::shared_ptr<const Telegram> telegram) {
}

#pragma GCC diagnostic pop

// Settings AM200

// pos 12: off(00)/Keelbypass(01)/(hc1pump(02) only standalone)
bool Boiler::set_vr2Config(const char * value, const int8_t id) {
uint8_t v;
if (!Helpers::value2enum(value, v, FL_(enum_vr2Config))) {
return false;
}
write_command(0x54C, 12, v, 0x54C);
return true;
}

// pos 00: Alternate heat source activation: No(00),Yes(01)
bool Boiler::set_ahsActivated(const char * value, const int8_t id) {
bool v;
if (!Helpers::value2bool(value, v)) {
return false;
}
write_command(0x54C, 0, v, 0x54C);
return true;
}

// pos 04: Buffer primary pump->Config pump: No(00),Yes(01)
bool Boiler::set_aPumpConfig(const char * value, const int8_t id) {
bool v;
if (!Helpers::value2bool(value, v)) {
return false;
}
write_command(0x54C, 4, v, 0x54C);
return true;
}

// pos 03: Output for PR1 pump: On/Off(00),PWM(01),PWM invers(02)
bool Boiler::set_aPumpSignal(const char * value, const int8_t id) {
uint8_t v;
if (!Helpers::value2enum(value, v, FL_(enum_aPumpSignal))) {
return false;
}
write_command(0x54C, 3, v, 0x54C);
return true;
}

// pos 21: Min output pump PR1 (%)
bool Boiler::set_aPumpMin(const char * value, const int8_t id) {
int v;
if (!Helpers::value2number(value, v)) {
return false;
}
write_command(0x54C, 21, v, 0x54C);
return true;
}

// pos 01: AHS return temp rise: No(00),Yes(01) (mixer VR1)
bool Boiler::set_tempRise(const char * value, const int8_t id) {
bool v;
if (!Helpers::value2bool(value, v)) {
return false;
}
write_command(0x54C, 1, v, 0x54C);
return true;
}

// pos 06: Set temp return (°C) (VR1)
bool Boiler::set_setReturnTemp(const char * value, const int8_t id) {
int v;
if (!Helpers::value2temperature(value, v)) {
return false;
}
write_command(0x54C, 6, v, 0x54C);
return true;
}

// pos 10/11?: Mixer run time (s) (VR1)
bool Boiler::set_mixRuntime(const char * value, const int8_t id) {
int v;
if (!Helpers::value2number(value, v)) {
return false;
}
uint8_t data[2] = {(uint8_t)(v >> 8), (uint8_t)v};
write_command(0x54C, 10, data, 2, 0x54C);
return true;
}

// pos 07: Set flow temp AHS (°C) (Buffer)
bool Boiler::set_setFlowTemp(const char * value, const int8_t id) {
int v;
if (!Helpers::value2number(value, v)) {
return false;
}
write_command(0x54C, 7, v, 0x54C);
return true;
}

// pos 02: Puffer bypass: No(00), Mischer(01), Ventil(02) (Buffer)
bool Boiler::set_bufBypass(const char * value, const int8_t id) {
uint8_t v;
if (!Helpers::value2enum(value, v, FL_(enum_bufBypass))) {
return false;
}
write_command(0x54C, 2, v, 0x54C);
return true;
}

// pos 8/9: Bypass mixer run time: [time] (s) (Buffer)
bool Boiler::set_bufMixRuntime(const char * value, const int8_t id) {
int v;
if (!Helpers::value2number(value, v)) {
return false;
}
uint8_t data[2] = {(uint8_t)(v >> 8), (uint8_t)v};
write_command(0x54C, 8, data, 2, 0x54C);
return true;
}

// pos 20: Konfig WW-Speicher Monovalent(01), Bivalent(02) (buffer)
bool Boiler::set_bufConfig(const char * value, const int8_t id) {
uint8_t v;
if (!Helpers::value2enum(value, v, FL_(enum_bufConfig))) {
return false;
}
write_command(0x54C, 20, v, 0x54C);
return true;
}

// pos 16: Config htg. blocking mode: No(00),Automatic(01),Always block02) (blocking)
bool Boiler::set_blockMode(const char * value, const int8_t id) {
uint8_t v;
if (!Helpers::value2enum(value, v, FL_(enum_blockMode))) {
return false;
}
write_command(0x54C, 16, v, 0x54C);
return true;
}

// pos 17: Config of block terminal: NO(00), NC(01)
bool Boiler::set_blockTerm(const char * value, const int8_t id) {
uint8_t v;
if (!Helpers::value2enum(value, v, FL_(enum_blockTerm))) {
return false;
}
write_command(0x54C, 17, v, 0x54C);
return true;
}

// pos 14?: Hyst. for bolier block (K)
bool Boiler::set_blockHyst(const char * value, const int8_t id) {
int v;
if (!Helpers::value2temperature(value, v, true)) {
return false;
}
write_command(0x54C, 14, v, 0x54C);
return true;
}

// pos 15: Boiler release wait time (min)
bool Boiler::set_releaseWait(const char * value, const int8_t id) {
int v;
if (!Helpers::value2number(value, v)) {
return false;
}
write_command(0x54C, 15, v, 0x54C);
return true;
}

/*
* Hybrid heatpump with telegram 0xBB is readable and writeable in boiler and thermostat
* thermostat always overwrites settings in boiler
Expand Down
58 changes: 48 additions & 10 deletions src/devices/boiler.h
Expand Up @@ -199,19 +199,38 @@ class Boiler : public EMSdevice {
int8_t poolSetTemp_;

// Alternative Heatsource AM200
int16_t cylTopTemp_; // TB1
int16_t cylCenterTemp_; // TB2
int16_t cylBottomTemp_; // TB3
int16_t aFlowTemp_; // TA1
int16_t aRetTemp_; // TR1
// uint8_t aPump_; // PR1 - on/off
uint8_t aPumpMod_; // PR1 - percent
int16_t cylTopTemp_; // TB1
int16_t cylCenterTemp_; // TB2
int16_t cylBottomTemp_; // TB3
int16_t aFlowTemp_; // TA1
int16_t aRetTemp_; // TR1
uint8_t aPumpMod_; // PR1 - percent
// uint8_t valveByPass_; // VR2
uint8_t valveBuffer_; // VB1
uint8_t valveReturn_; // VR1
uint8_t valveBuffer_; // VB1
uint8_t valveReturn_; // VR1
// uint8_t heatSource_; // OEV
// Settings:
uint8_t vr2Config_; // pos 12: off(00)/Keelbypass(01)/(hc1pump(02) only standalone)
uint8_t ahsActivated_; // pos 00: Alternate heat source activation: No(00),Yes(01)
uint8_t aPumpConfig_; // pos 04: Buffer primary pump->Config pump: No(00),Yes(01)
uint8_t aPumpSignal_; // pos 03: Output for PR1 pump: On/Off(00),PWM(01),PWM invers(02)
uint8_t aPumpMin_; // pos 21: Min output pump PR1 (%)
uint8_t tempRise_; // pos 01: AHS return temp rise: No(00),Yes(01) (mixer VR1)
uint8_t setReturnTemp_; // pos 06: Set temp return (°C) (VR1)
uint16_t mixRuntime_; // pos 10/11?: Mixer run time (s) (VR1)
// uint8_t setFlowTemp_; // pos 07: Set flow temp AHS (°C) (Buffer)
uint8_t bufBypass_; // pos 02: Puffer bypass: No(00), Mischer(01), Ventil(02) (Buffer)
uint16_t bufMixRuntime_; // pos 8/9: Bypass mixer run time: [time] (s) (Buffer)
uint8_t bufConfig_; // pos 20: Konfig WW-Speicher Monovalent(01), Bivalent(02) (buffer)
uint8_t blockMode_; // pos 16: Config htg. blocking mode: No(00),Automatic(01),Always block02) (blocking)
uint8_t blockTerm_; // pos 17: Config of block terminal: NO(00), NC(01)
int8_t blockHyst_; // pos 14?: Hyst. for bolier block (K)
uint8_t releaseWait_; // pos 15: Boiler release wait time (min)

/*



/*
* Hybrid heatpump with telegram 0xBB is readable and writeable in boiler and thermostat
* thermostat always overwrites settings in boiler
* enable settings here if no thermostat is used in system
Expand Down Expand Up @@ -259,6 +278,7 @@ class Boiler : public EMSdevice {
void process_amStatusMessage(std::shared_ptr<const Telegram> telegram);
void process_amSettingMessage(std::shared_ptr<const Telegram> telegram);
void process_amCommandMessage(std::shared_ptr<const Telegram> telegram);
void process_amExtraMessage(std::shared_ptr<const Telegram> telegram);

// commands - none of these use the additional id parameter
bool set_ww_mode(const char * value, const int8_t id);
Expand Down Expand Up @@ -298,6 +318,24 @@ class Boiler : public EMSdevice {
bool set_pool_temp(const char * value, const int8_t id);
bool set_emergency_temp(const char * value, const int8_t id);
bool set_emergency_ops(const char * value, const int8_t id);

bool set_vr2Config(const char * value, const int8_t id); // pos 12: off(00)/Keelbypass(01)/(hc1pump(02) only standalone)
bool set_ahsActivated(const char * value, const int8_t id); // pos 00: Alternate heat source activation: No(00),Yes(01)
bool set_aPumpConfig(const char * value, const int8_t id); // pos 04: Buffer primary pump->Config pump: No(00),Yes(01)
bool set_aPumpSignal(const char * value, const int8_t id); // pos 03: Output for PR1 pump: On/Off(00),PWM(01),PWM invers(02)
bool set_aPumpMin(const char * value, const int8_t id); // pos 21: Min output pump PR1 (%)
bool set_tempRise(const char * value, const int8_t id); // pos 01: AHS return temp rise: No(00),Yes(01) (mixer VR1)
bool set_setReturnTemp(const char * value, const int8_t id); // pos 06: Set temp return (°C) (VR1)
bool set_mixRuntime(const char * value, const int8_t id); // pos 10/11?: Mixer run time (s) (VR1)
bool set_setFlowTemp(const char * value, const int8_t id); // pos 07: Set flow temp AHS (°C) (Buffer)
bool set_bufBypass(const char * value, const int8_t id); // pos 02: Puffer bypass: No(00), Mischer(01), Ventil(02) (Buffer)
bool set_bufMixRuntime(const char * value, const int8_t id); // pos 8/9: Bypass mixer run time: [time] (s) (Buffer)
bool set_bufConfig(const char * value, const int8_t id); // pos 20: Konfig WW-Speicher Monovalent(01), Bivalent(02) (buffer)
bool set_blockMode(const char * value, const int8_t id); // pos 16: Config htg. blocking mode: No(00),Automatic(01),Always block02) (blocking)
bool set_blockTerm(const char * value, const int8_t id); // pos 17: Config of block terminal: NO(00), NC(01)
bool set_blockHyst(const char * value, const int8_t id); // pos 14?: Hyst. for bolier block (K)
bool set_releaseWait(const char * value, const int8_t id); // pos 15: Boiler release wait time (min)

/*
bool set_hybridStrategy(const char * value, const int8_t id);
bool set_switchOverTemp(const char * value, const int8_t id);
Expand Down

0 comments on commit fb94026

Please sign in to comment.