@@ -1,7 +1,7 @@
/*
/*
* EMS-ESP - https://github.com/proddy/EMS-ESP
* EMS-ESP - https://github.com/proddy/EMS-ESP
* Copyright 2019 Paul Derbyshire
* Copyright 2019 Paul Derbyshire
*
*
* This program is free software: you can redistribute it and/or modify
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* the Free Software Foundation, either version 3 of the License, or
@@ -61,11 +61,13 @@ void Solar::add_context_menu() {
// print to web
// print to web
void Solar : : device_info ( JsonArray & root ) {
void Solar : : device_info ( JsonArray & root ) {
render_value_json ( root , " " , F ( " Collector temperature (TS1) " ) , collectorTemp_ , F_ ( degrees ) , 10 ) ;
render_value_json ( root , " " , F ( " Collector temperature (TS1) " ) , collectorTemp_ , F_ ( degrees ) , 10 ) ;
render_value_json ( root , " " , F ( " B ottom temperature (TS2)" ) , b ottomTemp_, F_ ( degrees ) , 10 ) ;
render_value_json ( root , " " , F ( " Tank b ottom temperature (TS2)" ) , tankB ottomTemp_, F_ ( degrees ) , 10 ) ;
render_value_json ( root , " " , F ( " B ottom temperature (TS5)" ) , b ottomTemp2_, F_ ( degrees ) , 10 ) ;
render_value_json ( root , " " , F ( " Tank b ottom temperature (TS5)" ) , tankB ottomTemp2_, F_ ( degrees ) , 10 ) ;
render_value_json ( root , " " , F ( " Pump modulation " ) , pumpModulation_ , F_ ( percent ) ) ;
render_value_json ( root , " " , F ( " Heat exchanger temperature (TS6) " ) , heatExchangerTemp_ , F_ ( degrees ) , 10 ) ;
render_value_json ( root , " " , F ( " Solar pump modulation (PS1) " ) , solarPumpModulation_ , F_ ( percent ) ) ;
render_value_json ( root , " " , F ( " Cylinder pump modulation (PS5) " ) , cylinderPumpModulation_ , F_ ( percent ) ) ;
render_value_json ( root , " " , F ( " Valve (VS2) status " ) , valveStatus_ , nullptr , EMS_VALUE_BOOL ) ;
render_value_json ( root , " " , F ( " Valve (VS2) status " ) , valveStatus_ , nullptr , EMS_VALUE_BOOL ) ;
render_value_json ( root , " " , F ( " Pump (PS1) active " ) , p ump_, nullptr , EMS_VALUE_BOOL ) ;
render_value_json ( root , " " , F ( " Solar Pump (PS1) active" ) , solarP ump_, nullptr , EMS_VALUE_BOOL ) ;
if ( Helpers : : hasValue ( pumpWorkMin_ ) ) {
if ( Helpers : : hasValue ( pumpWorkMin_ ) ) {
JsonObject dataElement ;
JsonObject dataElement ;
@@ -77,7 +79,7 @@ void Solar::device_info(JsonArray & root) {
}
}
render_value_json ( root , " " , F ( " Tank Heated " ) , tankHeated_ , nullptr , EMS_VALUE_BOOL ) ;
render_value_json ( root , " " , F ( " Tank Heated " ) , tankHeated_ , nullptr , EMS_VALUE_BOOL ) ;
render_value_json ( root , " " , F ( " Collector shutdown " ) , collectorOnOff _ , nullptr , EMS_VALUE_BOOL ) ;
render_value_json ( root , " " , F ( " Collector shutdown " ) , collectorShutdown _ , nullptr , EMS_VALUE_BOOL ) ;
render_value_json ( root , " " , F ( " Energy last hour " ) , energyLastHour_ , F_ ( wh ) , 10 ) ;
render_value_json ( root , " " , F ( " Energy last hour " ) , energyLastHour_ , F_ ( wh ) , 10 ) ;
render_value_json ( root , " " , F ( " Energy today " ) , energyToday_ , F_ ( wh ) ) ;
render_value_json ( root , " " , F ( " Energy today " ) , energyToday_ , F_ ( wh ) ) ;
@@ -89,18 +91,20 @@ void Solar::show_values(uuid::console::Shell & shell) {
EMSdevice : : show_values ( shell ) ; // always call this to show header
EMSdevice : : show_values ( shell ) ; // always call this to show header
print_value ( shell , 2 , F ( " Collector temperature (TS1) " ) , collectorTemp_ , F_ ( degrees ) , 10 ) ;
print_value ( shell , 2 , F ( " Collector temperature (TS1) " ) , collectorTemp_ , F_ ( degrees ) , 10 ) ;
print_value ( shell , 2 , F ( " Bottom temperature (TS2) " ) , b ottomTemp_, F_ ( degrees ) , 10 ) ;
print_value ( shell , 2 , F ( " Bottom temperature (TS2) " ) , tankB ottomTemp_, F_ ( degrees ) , 10 ) ;
print_value ( shell , 2 , F ( " Bottom temperature (TS5) " ) , b ottomTemp2_, F_ ( degrees ) , 10 ) ;
print_value ( shell , 2 , F ( " Bottom temperature (TS5) " ) , tankB ottomTemp2_, F_ ( degrees ) , 10 ) ;
print_value ( shell , 2 , F ( " Pump modulation " ) , pumpModulation_ , F_ ( percent ) ) ;
print_value ( shell , 2 , F ( " Heat exchanger temperature (TS6) " ) , heatExchangerTemp_ , F_ ( degrees ) , 10 ) ;
print_value ( shell , 2 , F ( " Solar pump modulation (PS1) " ) , solarPumpModulation_ , F_ ( percent ) ) ;
print_value ( shell , 2 , F ( " Cylinder pump modulation (PS5) " ) , cylinderPumpModulation_ , F_ ( percent ) ) ;
print_value ( shell , 2 , F ( " Valve (VS2) status " ) , valveStatus_ , nullptr , EMS_VALUE_BOOL ) ;
print_value ( shell , 2 , F ( " Valve (VS2) status " ) , valveStatus_ , nullptr , EMS_VALUE_BOOL ) ;
print_value ( shell , 2 , F ( " Pump (PS1) active " ) , p ump_, nullptr , EMS_VALUE_BOOL ) ;
print_value ( shell , 2 , F ( " Solar Pump (PS1) active" ) , solarP ump_, nullptr , EMS_VALUE_BOOL ) ;
if ( Helpers : : hasValue ( pumpWorkMin_ ) ) {
if ( Helpers : : hasValue ( pumpWorkMin_ ) ) {
shell . printfln ( F ( " Pump working time: %d days %d hours %d minutes " ) , pumpWorkMin_ / 1440 , ( pumpWorkMin_ % 1440 ) / 60 , pumpWorkMin_ % 60 ) ;
shell . printfln ( F ( " Pump working time: %d days %d hours %d minutes " ) , pumpWorkMin_ / 1440 , ( pumpWorkMin_ % 1440 ) / 60 , pumpWorkMin_ % 60 ) ;
}
}
print_value ( shell , 2 , F ( " Tank Heated " ) , tankHeated_ , nullptr , EMS_VALUE_BOOL ) ;
print_value ( shell , 2 , F ( " Tank Heated " ) , tankHeated_ , nullptr , EMS_VALUE_BOOL ) ;
print_value ( shell , 2 , F ( " Collector shutdown " ) , collectorOnOff _ , nullptr , EMS_VALUE_BOOL ) ;
print_value ( shell , 2 , F ( " Collector shutdown " ) , collectorShutdown _ , nullptr , EMS_VALUE_BOOL ) ;
print_value ( shell , 2 , F ( " Energy last hour " ) , energyLastHour_ , F_ ( wh ) , 10 ) ;
print_value ( shell , 2 , F ( " Energy last hour " ) , energyLastHour_ , F_ ( wh ) , 10 ) ;
print_value ( shell , 2 , F ( " Energy today " ) , energyToday_ , F_ ( wh ) ) ;
print_value ( shell , 2 , F ( " Energy today " ) , energyToday_ , F_ ( wh ) ) ;
@@ -114,27 +118,35 @@ void Solar::publish_values() {
char s [ 10 ] ; // for formatting strings
char s [ 10 ] ; // for formatting strings
if ( Helpers : : hasValue ( collectorTemp_ ) ) {
if ( Helpers : : hasValue ( collectorTemp_ ) ) {
doc [ " collectort emp " ] = ( float ) collectorTemp_ / 10 ;
doc [ " collectorT emp " ] = ( float ) collectorTemp_ / 10 ;
}
}
if ( Helpers : : hasValue ( b ottomTemp_) ) {
if ( Helpers : : hasValue ( tankB ottomTemp_) ) {
doc [ " b ottomt emp" ] = ( float ) b ottomTemp_ / 10 ;
doc [ " tankB ottomT emp" ] = ( float ) tankB ottomTemp_ / 10 ;
}
}
if ( Helpers : : hasValue ( b ottomTemp2_) ) {
if ( Helpers : : hasValue ( tankB ottomTemp2_) ) {
doc [ " b ottomt emp2" ] = ( float ) b ottomTemp2_ / 10 ;
doc [ " tankB ottomT emp2" ] = ( float ) tankB ottomTemp2_ / 10 ;
}
}
if ( Helpers : : hasValue ( pumpModulation _) ) {
if ( Helpers : : hasValue ( heatExchangerTemp _) ) {
doc [ " pumpmodulation " ] = pumpModulation_ ;
doc [ " heatExchangerTemp " ] = ( float ) heatExchangerTemp_ / 10 ;
}
}
if ( Helpers : : hasValue ( pump_ , VALUE_BOOL ) ) {
if ( Helpers : : hasValue ( solarPumpModulation_ ) ) {
doc [ " pump " ] = Helpers : : render_value ( s , pump_ , EMS_VALUE_BOOL ) ;
doc [ " solarPumpModulation " ] = solarPumpModulation_ ;
}
if ( Helpers : : hasValue ( cylinderPumpModulation_ ) ) {
doc [ " cylinderPumpModulation " ] = cylinderPumpModulation_ ;
}
if ( Helpers : : hasValue ( solarPump_ , VALUE_BOOL ) ) {
doc [ " solarPump " ] = Helpers : : render_value ( s , solarPump_ , EMS_VALUE_BOOL ) ;
}
}
if ( Helpers : : hasValue ( valveStatus_ , VALUE_BOOL ) ) {
if ( Helpers : : hasValue ( valveStatus_ , VALUE_BOOL ) ) {
doc [ " valves tatus " ] = Helpers : : render_value ( s , valveStatus_ , EMS_VALUE_BOOL ) ;
doc [ " valveS tatus " ] = Helpers : : render_value ( s , valveStatus_ , EMS_VALUE_BOOL ) ;
}
}
if ( Helpers : : hasValue ( pumpWorkMin_ ) ) {
if ( Helpers : : hasValue ( pumpWorkMin_ ) ) {
@@ -145,20 +157,20 @@ void Solar::publish_values() {
doc [ " tankHeated " ] = Helpers : : render_value ( s , tankHeated_ , EMS_VALUE_BOOL ) ;
doc [ " tankHeated " ] = Helpers : : render_value ( s , tankHeated_ , EMS_VALUE_BOOL ) ;
}
}
if ( Helpers : : hasValue ( collectorOnOff _ , VALUE_BOOL ) ) {
if ( Helpers : : hasValue ( collectorShutdown _ , VALUE_BOOL ) ) {
doc [ " collectorOnOff " ] = Helpers : : render_value ( s , collectorOnOff _ , EMS_VALUE_BOOL ) ;
doc [ " collectorShutdown " ] = Helpers : : render_value ( s , collectorShutdown _ , EMS_VALUE_BOOL ) ;
}
}
if ( Helpers : : hasValue ( energyLastHour_ ) ) {
if ( Helpers : : hasValue ( energyLastHour_ ) ) {
doc [ " energyl asth our " ] = ( float ) energyLastHour_ / 10 ;
doc [ " energyL astH our " ] = ( float ) energyLastHour_ / 10 ;
}
}
if ( Helpers : : hasValue ( energyToday_ ) ) {
if ( Helpers : : hasValue ( energyToday_ ) ) {
doc [ " energyt oday " ] = energyToday_ ;
doc [ " energyT oday " ] = energyToday_ ;
}
}
if ( Helpers : : hasValue ( energyTotal_ ) ) {
if ( Helpers : : hasValue ( energyTotal_ ) ) {
doc [ " energyt otal " ] = ( float ) energyTotal_ / 10 ;
doc [ " energyT otal " ] = ( float ) energyTotal_ / 10 ;
}
}
Mqtt : : publish ( " sm_data " , doc ) ;
Mqtt : : publish ( " sm_data " , doc ) ;
@@ -176,26 +188,29 @@ void Solar::console_commands() {
// SM10Monitor - type 0x97
// SM10Monitor - type 0x97
void Solar : : process_SM10Monitor ( std : : shared_ptr < const Telegram > telegram ) {
void Solar : : process_SM10Monitor ( std : : shared_ptr < const Telegram > telegram ) {
telegram - > read_value ( collectorTemp_ , 2 ) ; // collector temp from SM10, is *10
telegram - > read_value ( collectorTemp_ , 2 ) ; // collector temp from SM10, is *10
telegram - > read_value ( b ottomTemp_, 5 ) ; // bottom temp from SM10, is *10
telegram - > read_value ( tankB ottomTemp_, 5 ) ; // bottom temp from SM10, is *10
telegram - > read_value ( p umpModulation_, 4 ) ; // modulation solar pump
telegram - > read_value ( solarP umpModulation_, 4 ) ; // modulation solar pump
telegram - > read_bitvalue ( p ump_, 7 , 1 ) ;
telegram - > read_bitvalue ( solarP ump_, 7 , 1 ) ;
telegram - > read_value ( pumpWorkMin_ , 8 ) ;
telegram - > read_value ( pumpWorkMin_ , 8 ) ;
}
}
/*
/*
* SM100Monitor - type 0x0362 EMS+ - for SM100 and SM200
* SM100Monitor - type 0x0362 EMS+ - for MS/ SM100 and MS/ SM200
* e.g. B0 0B FF 00 02 62 00 44 02 7A 80 00 80 00 80 00 80 00 80 00 80 00 00 7C 80 00 80 00 80 00 80
* e.g. B0 0B FF 00 02 62 00 44 02 7A 80 00 80 00 80 00 80 00 80 00 80 00 00 7C 80 00 80 00 80 00 80
* e.g. B0 0B FF 00 02 62 00 77 01 D4 80 00 80 00 80 00 80 00 80 00 80 00 80 00 80 00 00 F9 80 00 80 9E - for heat exchanger temp
* e.g, 30 00 FF 00 02 62 01 AC
* e.g, 30 00 FF 00 02 62 01 AC
* 30 00 FF 18 02 62 80 00
* 30 00 FF 18 02 62 80 00
* 30 00 FF 00 02 62 01 A1 - for bottom temps
* 30 00 FF 00 02 62 01 A1 - for bottom temps
* bytes 0+1 = TS1 Temperature sensor for collector
* bytes 0+1 = TS1 Temperature sensor for collector
* bytes 2+3 = TS2 Temperature sensor bottom cylinder 1
* bytes 2+3 = TS2 Temperature sensor 1 cylinder, bottom
* bytes 16+17 = TS5 Temperature sensor bottom cylinder 2
* bytes 16+17 = TS5 Temperature sensor 2 cylinder, bottom, or swimming pool
* bytes 20+21 = TS6 Temperature sensor external heat exchanger
*/
*/
void Solar : : process_SM100Monitor ( std : : shared_ptr < const Telegram > telegram ) {
void Solar : : process_SM100Monitor ( std : : shared_ptr < const Telegram > telegram ) {
telegram - > read_value ( collectorTemp_ , 0 ) ; // is *10
telegram - > read_value ( collectorTemp_ , 0 ) ; // is *10 - TS1: Temperature sensor for collector array 1
telegram - > read_value ( b ottomTemp_, 2 ) ; // is *10
telegram - > read_value ( tankB ottomTemp_, 2 ) ; // is *10 - TS2: Temperature sensor 1 cylinder, bottom
telegram - > read_value ( b ottomTemp2_, 16 ) ; // is *10
telegram - > read_value ( tankB ottomTemp2_, 16 ) ; // is *10 - TS5: Temperature sensor 2 cylinder, bottom, or swimming pool
telegram - > read_value ( heatExchangerTemp_ , 20 ) ; // is *10 - TS6: Heat exchanger temperature sensor
}
}
# pragma GCC diagnostic push
# pragma GCC diagnostic push
@@ -218,30 +233,37 @@ void Solar::process_SM100Config(std::shared_ptr<const Telegram> telegram) {
}
}
/*
/*
* SM100Status - type 0x0364 EMS+ for pump modulation - for SM100 and SM200
* SM100Status - type 0x0364 EMS+ for pump modulations - for MS/ SM100 and MS/ SM200
- PS1: Solar circuit pump for collector array 1
- PS5: Cylinder primary pump when using an external heat exchanger
* e.g. 30 00 FF 09 02 64 64 = 100%
* e.g. 30 00 FF 09 02 64 64 = 100%
* 30 00 FF 09 02 64 1E = 30%
* 30 00 FF 09 02 64 1E = 30%
*/
*/
void Solar : : process_SM100Status ( std : : shared_ptr < const Telegram > telegram ) {
void Solar : : process_SM100Status ( std : : shared_ptr < const Telegram > telegram ) {
uint8_t pumpmod = p umpModulation_;
uint8_t solar pumpmod = solarP umpModulation_;
telegram - > read_value ( p umpModulation_, 9 ) ;
uint8_t cylinderpumpmod = cylinderP umpModulation_;
if ( pumpmod = = 0 & & pumpModulation_ = = 100 ) { // mask out boosts
telegram - > read_value ( cylinderPumpModulation_ , 8 ) ;
pumpModulation_ = 15 ; // set to minimum
telegram - > read_value ( solarPumpModulation_ , 9 ) ;
if ( solarpumpmod = = 0 & & solarPumpModulation_ = = 100 ) { // mask out boosts
solarPumpModulation_ = 15 ; // set to minimum
}
if ( cylinderpumpmod = = 0 & & cylinderPumpModulation_ = = 100 ) { // mask out boosts
cylinderPumpModulation_ = 15 ; // set to minimum
}
}
telegram - > read_bitvalue ( tankHeated_ , 3 , 1 ) ; // issue #422
telegram - > read_bitvalue ( tankHeated_ , 3 , 1 ) ; // issue #422
telegram - > read_bitvalue ( collectorOnOff _ , 3 , 0 ) ; // collector shutdown
telegram - > read_bitvalue ( collectorShutdown _ , 3 , 0 ) ; // collector shutdown
}
}
/*
/*
* SM100Status2 - type 0x036A EMS+ for pump on/off at offset 0x0A - for SM100 and SM200
* SM100Status2 - type 0x036A EMS+ for pump on/off at offset 0x0A - for SM100 and SM200
* e.g. B0 00 FF 00 02 6A 03 03 03 03 01 03 03 03 03 03 01 03
* e.g. B0 00 FF 00 02 6A 03 03 03 03 01 03 03 03 03 03 01 03
* byte 4 = VS2 3-way valve for cylinder 2 : test=01, on=04 and off=03
* byte 4 = VS2 3-way valve for cylinder 2 : test=01, on=04 and off=03
* byte 10 = PS1 Solar circuit pump for collector array 1: test=b0001(1), on=b0100(4) and off=b0011(3)
* byte 10 = PS1 Solar circuit pump for collector array 1: test=b0001(1), on=b0100(4) and off=b0011(3)
*/
*/
void Solar : : process_SM100Status2 ( std : : shared_ptr < const Telegram > telegram ) {
void Solar : : process_SM100Status2 ( std : : shared_ptr < const Telegram > telegram ) {
telegram - > read_bitvalue ( valveStatus_ , 4 , 2 ) ; // on if bit 2 set
telegram - > read_bitvalue ( valveStatus_ , 4 , 2 ) ; // on if bit 2 set
telegram - > read_bitvalue ( p ump_, 10 , 2 ) ; // on if bit 2 set
telegram - > read_bitvalue ( solarP ump_, 10 , 2 ) ; // on if bit 2 set
}
}
/*
/*
@@ -250,8 +272,8 @@ void Solar::process_SM100Status2(std::shared_ptr<const Telegram> telegram) {
*/
*/
void Solar : : process_SM100Energy ( std : : shared_ptr < const Telegram > telegram ) {
void Solar : : process_SM100Energy ( std : : shared_ptr < const Telegram > telegram ) {
telegram - > read_value ( energyLastHour_ , 0 ) ; // last hour / 10 in Wh
telegram - > read_value ( energyLastHour_ , 0 ) ; // last hour / 10 in Wh
telegram - > read_value ( energyToday_ , 4 ) ; // todays in Wh
telegram - > read_value ( energyToday_ , 4 ) ; // todays in Wh
telegram - > read_value ( energyTotal_ , 8 ) ; // total / 10 in kWh
telegram - > read_value ( energyTotal_ , 8 ) ; // total / 10 in kWh
}
}
/*
/*
@@ -259,17 +281,17 @@ void Solar::process_SM100Energy(std::shared_ptr<const Telegram> telegram) {
* e.g. B0 00 FF 00 00 03 32 00 00 00 00 13 00 D6 00 00 00 FB D0 F0
* e.g. B0 00 FF 00 00 03 32 00 00 00 00 13 00 D6 00 00 00 FB D0 F0
*/
*/
void Solar : : process_ISM1StatusMessage ( std : : shared_ptr < const Telegram > telegram ) {
void Solar : : process_ISM1StatusMessage ( std : : shared_ptr < const Telegram > telegram ) {
telegram - > read_value ( collectorTemp_ , 4 ) ; // Collector Temperature
telegram - > read_value ( collectorTemp_ , 4 ) ; // Collector Temperature
telegram - > read_value ( b ottomTemp_, 6 ) ; // Temperature Bottom of Solar Boiler
telegram - > read_value ( tankB ottomTemp_, 6 ) ; // Temperature Bottom of Solar Boiler
uint16_t Wh = 0xFFFF ;
uint16_t Wh = 0xFFFF ;
telegram - > read_value ( Wh , 2 ) ; // Solar Energy produced in last hour only ushort, is not * 10
telegram - > read_value ( Wh , 2 ) ; // Solar Energy produced in last hour only ushort, is not * 10
if ( Wh ! = 0xFFFF ) {
if ( Wh ! = 0xFFFF ) {
energyLastHour_ = Wh * 10 ; // set to *10
energyLastHour_ = Wh * 10 ; // set to *10
}
}
telegram - > read_bitvalue ( p ump_, 8 , 0 ) ; // Solar pump on (1) or off (0)
telegram - > read_bitvalue ( solarP ump_, 8 , 0 ) ; // PS1 Solar pump on (1) or off (0)
telegram - > read_value ( pumpWorkMin_ , 10 , 3 ) ; // force to 3 bytes
telegram - > read_value ( pumpWorkMin_ , 10 , 3 ) ; // force to 3 bytes
telegram - > read_bitvalue ( collectorOnOff _ , 9 , 0 ) ; // collector shutdown on/off
telegram - > read_bitvalue ( collectorShutdown _ , 9 , 0 ) ; // collector shutdown on/off
telegram - > read_bitvalue ( tankHeated_ , 9 , 2 ) ; // tank full
telegram - > read_bitvalue ( tankHeated_ , 9 , 2 ) ; // tank full
}
}
/*
/*