|  | @ -7,19 +7,26 @@ | 
			
		
	
		
		
			
				
					|  |  | #define __POWERMETER_H__ |  |  | #define __POWERMETER_H__ | 
			
		
	
		
		
			
				
					|  |  | 
 |  |  | 
 | 
			
		
	
		
		
			
				
					|  |  | #include <AsyncJson.h> |  |  | #include <AsyncJson.h> | 
			
		
	
		
		
			
				
					|  |  | #include <base64.h> |  |  |  | 
			
		
	
		
		
			
				
					|  |  | #include <HTTPClient.h> |  |  | #include <HTTPClient.h> | 
			
		
	
		
		
			
				
					|  |  |  |  |  | #if defined(ZEROEXPORT_POWERMETER_TIBBER) | 
			
		
	
		
		
			
				
					|  |  |  |  |  | #include <base64.h> | 
			
		
	
		
		
			
				
					|  |  | #include <string.h> |  |  | #include <string.h> | 
			
		
	
		
		
			
				
					|  |  |  |  |  | 
 | 
			
		
	
		
		
			
				
					|  |  | #include <list> |  |  | #include <list> | 
			
		
	
		
		
			
				
					|  |  |  |  |  | #endif | 
			
		
	
		
		
			
				
					|  |  | 
 |  |  | 
 | 
			
		
	
		
		
			
				
					|  |  | #include "config/settings.h" |  |  | #include "config/settings.h" | 
			
		
	
		
		
			
				
					|  |  |  |  |  | #if defined(ZEROEXPORT_POWERMETER_TIBBER) | 
			
		
	
		
		
			
				
					|  |  | #include "plugins/zeroExport/lib/sml.h" |  |  | #include "plugins/zeroExport/lib/sml.h" | 
			
		
	
		
		
			
				
					|  |  |  |  |  | #endif | 
			
		
	
		
		
			
				
					|  |  | 
 |  |  | 
 | 
			
		
	
		
		
			
				
					|  |  |  |  |  | #if defined(ZEROEXPORT_POWERMETER_TIBBER) | 
			
		
	
		
		
			
				
					|  |  | typedef struct { |  |  | typedef struct { | 
			
		
	
		
		
			
				
					|  |  |     const unsigned char OBIS[6]; |  |  |     const unsigned char OBIS[6]; | 
			
		
	
		
		
			
				
					|  |  |     void (*Fn)(double &); |  |  |     void (*Fn)(double &); | 
			
		
	
		
		
			
				
					|  |  |     float *Arg; |  |  |     float *Arg; | 
			
		
	
		
		
			
				
					|  |  | } OBISHandler; |  |  | } OBISHandler; | 
			
		
	
		
		
			
				
					|  |  |  |  |  | #endif | 
			
		
	
		
		
			
				
					|  |  | 
 |  |  | 
 | 
			
		
	
		
		
			
				
					|  |  | typedef struct { |  |  | typedef struct { | 
			
		
	
		
		
			
				
					|  |  |     float P; |  |  |     float P; | 
			
		
	
	
		
		
			
				
					|  | @ -45,32 +52,40 @@ class powermeter { | 
			
		
	
		
		
			
				
					|  |  |     /** loop
 |  |  |     /** loop
 | 
			
		
	
		
		
			
				
					|  |  |      * abfrage der gruppen um die aktuellen Werte (Zähler) zu ermitteln. |  |  |      * abfrage der gruppen um die aktuellen Werte (Zähler) zu ermitteln. | 
			
		
	
		
		
			
				
					|  |  |      */ |  |  |      */ | 
			
		
	
		
		
			
				
					
					|  |  |     void loop(void) |  |  |     void loop(void) { | 
			
				
				
			
		
	
		
		
			
				
					|  |  |     { |  |  |  | 
			
		
	
		
		
	
		
		
			
				
					|  |  |         unsigned long Tsp = millis(); |  |  |         unsigned long Tsp = millis(); | 
			
		
	
		
		
			
				
					
					|  |  |         if(Tsp - mPreviousTsp <= 1000) return; // skip when it is to fast
 |  |  |         if (Tsp - mPreviousTsp <= 1000) return;  // skip when it is to fast
 | 
			
				
				
			
		
	
		
		
	
		
		
			
				
					|  |  |         mPreviousTsp = Tsp; |  |  |         mPreviousTsp = Tsp; | 
			
		
	
		
		
			
				
					|  |  | 
 |  |  | 
 | 
			
		
	
		
		
			
				
					|  |  |         PowermeterBuffer_t power; |  |  |         PowermeterBuffer_t power; | 
			
		
	
		
		
			
				
					|  |  | 
 |  |  | 
 | 
			
		
	
		
		
			
				
					
					|  |  |         for (u_short group = 0; group < ZEROEXPORT_MAX_GROUPS; group++) |  |  |         for (u_short group = 0; group < ZEROEXPORT_MAX_GROUPS; group++) { | 
			
				
				
			
		
	
		
		
			
				
					|  |  |         { |  |  |  | 
			
		
	
		
		
	
		
		
			
				
					|  |  |             switch (mCfg->groups[group].pm_type) { |  |  |             switch (mCfg->groups[group].pm_type) { | 
			
		
	
		
		
			
				
					|  |  |  |  |  | #if defined(ZEROEXPORT_POWERMETER_SHELLY) | 
			
		
	
		
		
			
				
					|  |  |                 case zeroExportPowermeterType_t::Shelly: |  |  |                 case zeroExportPowermeterType_t::Shelly: | 
			
		
	
		
		
			
				
					|  |  |                     power = getPowermeterWattsShelly(*mLog, group); |  |  |                     power = getPowermeterWattsShelly(*mLog, group); | 
			
		
	
		
		
			
				
					|  |  |                     break; |  |  |                     break; | 
			
		
	
		
		
			
				
					|  |  |  |  |  | #endif | 
			
		
	
		
		
			
				
					|  |  |  |  |  | #if defined(ZEROEXPORT_POWERMETER_TASMOTA) | 
			
		
	
		
		
			
				
					|  |  |                 case zeroExportPowermeterType_t::Tasmota: |  |  |                 case zeroExportPowermeterType_t::Tasmota: | 
			
		
	
		
		
			
				
					|  |  |                     power = getPowermeterWattsTasmota(*mLog, group); |  |  |                     power = getPowermeterWattsTasmota(*mLog, group); | 
			
		
	
		
		
			
				
					|  |  |                     break; |  |  |                     break; | 
			
		
	
		
		
			
				
					|  |  |  |  |  | #endif | 
			
		
	
		
		
			
				
					|  |  |  |  |  | #if defined(ZEROEXPORT_POWERMETER_MQTT) | 
			
		
	
		
		
			
				
					|  |  |                 case zeroExportPowermeterType_t::Mqtt: |  |  |                 case zeroExportPowermeterType_t::Mqtt: | 
			
		
	
		
		
			
				
					|  |  |                     power = getPowermeterWattsMqtt(*mLog, group); |  |  |                     power = getPowermeterWattsMqtt(*mLog, group); | 
			
		
	
		
		
			
				
					|  |  |                     break; |  |  |                     break; | 
			
		
	
		
		
			
				
					|  |  |  |  |  | #endif | 
			
		
	
		
		
			
				
					|  |  |  |  |  | #if defined(ZEROEXPORT_POWERMETER_HICHI) | 
			
		
	
		
		
			
				
					|  |  |                 case zeroExportPowermeterType_t::Hichi: |  |  |                 case zeroExportPowermeterType_t::Hichi: | 
			
		
	
		
		
			
				
					|  |  |                     power = getPowermeterWattsHichi(*mLog, group); |  |  |                     power = getPowermeterWattsHichi(*mLog, group); | 
			
		
	
		
		
			
				
					|  |  |                     break; |  |  |                     break; | 
			
		
	
		
		
			
				
					|  |  |  |  |  | #endif | 
			
		
	
		
		
			
				
					|  |  |  |  |  | #if defined(ZEROEXPORT_POWERMETER_TIBBER) | 
			
		
	
		
		
			
				
					|  |  |                 case zeroExportPowermeterType_t::Tibber: |  |  |                 case zeroExportPowermeterType_t::Tibber: | 
			
		
	
		
		
			
				
					|  |  |                     power = getPowermeterWattsTibber(*mLog, group); |  |  |                     power = getPowermeterWattsTibber(*mLog, group); | 
			
		
	
		
		
			
				
					|  |  |                     break; |  |  |                     break; | 
			
		
	
		
		
			
				
					|  |  |  |  |  | #endif | 
			
		
	
		
		
			
				
					|  |  |             } |  |  |             } | 
			
		
	
		
		
			
				
					|  |  | 
 |  |  | 
 | 
			
		
	
		
		
			
				
					|  |  |             bufferWrite(power, group); |  |  |             bufferWrite(power, group); | 
			
		
	
	
		
		
			
				
					|  | @ -86,8 +101,7 @@ class powermeter { | 
			
		
	
		
		
			
				
					|  |  |         PowermeterBuffer_t avg; |  |  |         PowermeterBuffer_t avg; | 
			
		
	
		
		
			
				
					|  |  |         avg.P = avg.P1 = avg.P2 = avg.P2 = avg.P3 = 0; |  |  |         avg.P = avg.P1 = avg.P2 = avg.P2 = avg.P3 = 0; | 
			
		
	
		
		
			
				
					|  |  | 
 |  |  | 
 | 
			
		
	
		
		
			
				
					
					|  |  |         for (int i = 0; i < 5; i++) |  |  |         for (int i = 0; i < 5; i++) { | 
			
				
				
			
		
	
		
		
			
				
					|  |  |         { |  |  |  | 
			
		
	
		
		
	
		
		
			
				
					|  |  |             avg.P += mPowermeterBuffer[group][i].P; |  |  |             avg.P += mPowermeterBuffer[group][i].P; | 
			
		
	
		
		
			
				
					|  |  |             avg.P1 += mPowermeterBuffer[group][i].P1; |  |  |             avg.P1 += mPowermeterBuffer[group][i].P1; | 
			
		
	
		
		
			
				
					|  |  |             avg.P2 += mPowermeterBuffer[group][i].P2; |  |  |             avg.P2 += mPowermeterBuffer[group][i].P2; | 
			
		
	
	
		
		
			
				
					|  | @ -102,6 +116,7 @@ class powermeter { | 
			
		
	
		
		
			
				
					|  |  |     } |  |  |     } | 
			
		
	
		
		
			
				
					|  |  | 
 |  |  | 
 | 
			
		
	
		
		
			
				
					|  |  |    private: |  |  |    private: | 
			
		
	
		
		
			
				
					|  |  |  |  |  | #if defined(ZEROEXPORT_POWERMETER_SHELLY) | 
			
		
	
		
		
			
				
					|  |  |     /** getPowermeterWattsShelly
 |  |  |     /** getPowermeterWattsShelly
 | 
			
		
	
		
		
			
				
					|  |  |      * ... |  |  |      * ... | 
			
		
	
		
		
			
				
					|  |  |      * @param logObj |  |  |      * @param logObj | 
			
		
	
	
		
		
			
				
					|  | @ -210,7 +225,9 @@ class powermeter { | 
			
		
	
		
		
			
				
					|  |  |         http.end(); |  |  |         http.end(); | 
			
		
	
		
		
			
				
					|  |  |         return result; |  |  |         return result; | 
			
		
	
		
		
			
				
					|  |  |     } |  |  |     } | 
			
		
	
		
		
			
				
					|  |  |  |  |  | #endif | 
			
		
	
		
		
			
				
					|  |  | 
 |  |  | 
 | 
			
		
	
		
		
			
				
					|  |  |  |  |  | #if defined(ZEROEXPORT_POWERMETER_TASMOTA) | 
			
		
	
		
		
			
				
					|  |  |     /** getPowermeterWattsTasmota
 |  |  |     /** getPowermeterWattsTasmota
 | 
			
		
	
		
		
			
				
					|  |  |      * ... |  |  |      * ... | 
			
		
	
		
		
			
				
					|  |  |      * @param logObj |  |  |      * @param logObj | 
			
		
	
	
		
		
			
				
					|  | @ -325,7 +342,9 @@ class powermeter { | 
			
		
	
		
		
			
				
					|  |  |         */ |  |  |         */ | 
			
		
	
		
		
			
				
					|  |  |         return result; |  |  |         return result; | 
			
		
	
		
		
			
				
					|  |  |     } |  |  |     } | 
			
		
	
		
		
			
				
					|  |  |  |  |  | #endif | 
			
		
	
		
		
			
				
					|  |  | 
 |  |  | 
 | 
			
		
	
		
		
			
				
					|  |  |  |  |  | #if defined(ZEROEXPORT_POWERMETER_MQTT) | 
			
		
	
		
		
			
				
					|  |  |     /** getPowermeterWattsMqtt
 |  |  |     /** getPowermeterWattsMqtt
 | 
			
		
	
		
		
			
				
					|  |  |      * ... |  |  |      * ... | 
			
		
	
		
		
			
				
					|  |  |      * @param logObj |  |  |      * @param logObj | 
			
		
	
	
		
		
			
				
					|  | @ -346,7 +365,9 @@ class powermeter { | 
			
		
	
		
		
			
				
					|  |  | 
 |  |  | 
 | 
			
		
	
		
		
			
				
					|  |  |         return result; |  |  |         return result; | 
			
		
	
		
		
			
				
					|  |  |     } |  |  |     } | 
			
		
	
		
		
			
				
					|  |  |  |  |  | #endif | 
			
		
	
		
		
			
				
					|  |  | 
 |  |  | 
 | 
			
		
	
		
		
			
				
					|  |  |  |  |  | #if defined(ZEROEXPORT_POWERMETER_HICHI) | 
			
		
	
		
		
			
				
					|  |  |     /** getPowermeterWattsHichi
 |  |  |     /** getPowermeterWattsHichi
 | 
			
		
	
		
		
			
				
					|  |  |      * ... |  |  |      * ... | 
			
		
	
		
		
			
				
					|  |  |      * @param logObj |  |  |      * @param logObj | 
			
		
	
	
		
		
			
				
					|  | @ -367,7 +388,9 @@ class powermeter { | 
			
		
	
		
		
			
				
					|  |  | 
 |  |  | 
 | 
			
		
	
		
		
			
				
					|  |  |         return result; |  |  |         return result; | 
			
		
	
		
		
			
				
					|  |  |     } |  |  |     } | 
			
		
	
		
		
			
				
					|  |  |  |  |  | #endif | 
			
		
	
		
		
			
				
					|  |  | 
 |  |  | 
 | 
			
		
	
		
		
			
				
					|  |  |  |  |  | #if defined(ZEROEXPORT_POWERMETER_TIBBER) | 
			
		
	
		
		
			
				
					|  |  |     /** getPowermeterWattsTibber
 |  |  |     /** getPowermeterWattsTibber
 | 
			
		
	
		
		
			
				
					|  |  |      * ... |  |  |      * ... | 
			
		
	
		
		
			
				
					|  |  |      * @param logObj |  |  |      * @param logObj | 
			
		
	
	
		
		
			
				
					|  | @ -379,7 +402,6 @@ class powermeter { | 
			
		
	
		
		
			
				
					|  |  | 
 |  |  | 
 | 
			
		
	
		
		
			
				
					|  |  |     sml_states_t currentState; |  |  |     sml_states_t currentState; | 
			
		
	
		
		
			
				
					|  |  | 
 |  |  | 
 | 
			
		
	
		
		
			
				
					|  |  | 
 |  |  |  | 
			
		
	
		
		
			
				
					|  |  |     float _powerMeterTotal = 0.0; |  |  |     float _powerMeterTotal = 0.0; | 
			
		
	
		
		
			
				
					|  |  | 
 |  |  | 
 | 
			
		
	
		
		
			
				
					|  |  |     float _powerMeter1Power = 0.0; |  |  |     float _powerMeter1Power = 0.0; | 
			
		
	
	
		
		
			
				
					|  | @ -389,8 +411,7 @@ class powermeter { | 
			
		
	
		
		
			
				
					|  |  |     float _powerMeterImport = 0.0; |  |  |     float _powerMeterImport = 0.0; | 
			
		
	
		
		
			
				
					|  |  |     float _powerMeterExport = 0.0; |  |  |     float _powerMeterExport = 0.0; | 
			
		
	
		
		
			
				
					|  |  | 
 |  |  | 
 | 
			
		
	
		
		
			
				
					
					|  |  | 
 |  |  |     /*
 | 
			
				
				
			
		
	
		
		
			
				
					|  |  | /*
 |  |  |  | 
			
		
	
		
		
	
		
		
			
				
					|  |  |      07 81 81 c7 82 03 ff		#objName: OBIS Kennzahl für den Hersteller |  |  |      07 81 81 c7 82 03 ff		#objName: OBIS Kennzahl für den Hersteller | 
			
		
	
		
		
			
				
					|  |  |      07 01 00 01 08 00 ff		#objName: OBIS Kennzahl für Wirkenergie Bezug gesamt tariflos |  |  |      07 01 00 01 08 00 ff		#objName: OBIS Kennzahl für Wirkenergie Bezug gesamt tariflos | 
			
		
	
		
		
			
				
					|  |  |      07 01 00 01 08 01 ff 		#objName: OBIS-Kennzahl für Wirkenergie Bezug Tarif1 |  |  |      07 01 00 01 08 01 ff 		#objName: OBIS-Kennzahl für Wirkenergie Bezug Tarif1 | 
			
		
	
	
		
		
			
				
					|  | @ -398,7 +419,7 @@ class powermeter { | 
			
		
	
		
		
			
				
					|  |  |      07 01 00 02 08 00 ff		#objName: OBIS-Kennzahl für Wirkenergie Einspeisung gesamt tariflos |  |  |      07 01 00 02 08 00 ff		#objName: OBIS-Kennzahl für Wirkenergie Einspeisung gesamt tariflos | 
			
		
	
		
		
			
				
					|  |  |      07 01 00 02 08 01 ff		#objName: OBIS-Kennzahl für Wirkenergie Einspeisung Tarif1 |  |  |      07 01 00 02 08 01 ff		#objName: OBIS-Kennzahl für Wirkenergie Einspeisung Tarif1 | 
			
		
	
		
		
			
				
					|  |  |      07 01 00 02 08 02 ff		#objName: OBIS-Kennzahl für Wirkenergie Einspeisung Tarif2 |  |  |      07 01 00 02 08 02 ff		#objName: OBIS-Kennzahl für Wirkenergie Einspeisung Tarif2 | 
			
		
	
		
		
			
				
					
					|  |  | */ |  |  |     */ | 
			
				
				
			
		
	
		
		
	
		
		
			
				
					|  |  |     const std::list<OBISHandler> smlHandlerList{ |  |  |     const std::list<OBISHandler> smlHandlerList{ | 
			
		
	
		
		
			
				
					|  |  |         {{0x01, 0x00, 0x10, 0x07, 0x00, 0xff}, &smlOBISW, &_powerMeterTotal},  // total - OBIS-Kennzahl für momentane Gesamtwirkleistung
 |  |  |         {{0x01, 0x00, 0x10, 0x07, 0x00, 0xff}, &smlOBISW, &_powerMeterTotal},  // total - OBIS-Kennzahl für momentane Gesamtwirkleistung
 | 
			
		
	
		
		
			
				
					|  |  | 
 |  |  | 
 | 
			
		
	
	
		
		
			
				
					|  | @ -448,7 +469,7 @@ class powermeter { | 
			
		
	
		
		
			
				
					|  |  |                         result.P2 = _powerMeter2Power; |  |  |                         result.P2 = _powerMeter2Power; | 
			
		
	
		
		
			
				
					|  |  |                         result.P3 = _powerMeter3Power; |  |  |                         result.P3 = _powerMeter3Power; | 
			
		
	
		
		
			
				
					|  |  | 
 |  |  | 
 | 
			
		
	
		
		
			
				
					
					|  |  |                         if(! (_powerMeter1Power && _powerMeter2Power && _powerMeter3Power)) { |  |  |                         if (!(_powerMeter1Power && _powerMeter2Power && _powerMeter3Power)) { | 
			
				
				
			
		
	
		
		
	
		
		
			
				
					|  |  |                             result.P1 = result.P2 = result.P3 = _powerMeterTotal / 3; |  |  |                             result.P1 = result.P2 = result.P3 = _powerMeterTotal / 3; | 
			
		
	
		
		
			
				
					|  |  |                         } |  |  |                         } | 
			
		
	
		
		
			
				
					|  |  |                         break; |  |  |                         break; | 
			
		
	
	
		
		
			
				
					|  | @ -468,12 +489,12 @@ class powermeter { | 
			
		
	
		
		
			
				
					|  |  |         http.end(); |  |  |         http.end(); | 
			
		
	
		
		
			
				
					|  |  |         return result; |  |  |         return result; | 
			
		
	
		
		
			
				
					|  |  |     } |  |  |     } | 
			
		
	
		
		
			
				
					|  |  |  |  |  | #endif | 
			
		
	
		
		
			
				
					|  |  | 
 |  |  | 
 | 
			
		
	
		
		
			
				
					
					|  |  |     void bufferWrite(PowermeterBuffer_t raw, short group) |  |  |     void bufferWrite(PowermeterBuffer_t raw, short group) { | 
			
				
				
			
		
	
		
		
			
				
					|  |  |     { |  |  |  | 
			
		
	
		
		
	
		
		
			
				
					|  |  |         mPowermeterBuffer[group][mPowermeterBufferPos[group]] = raw; |  |  |         mPowermeterBuffer[group][mPowermeterBufferPos[group]] = raw; | 
			
		
	
		
		
			
				
					|  |  |         mPowermeterBufferPos[group]++; |  |  |         mPowermeterBufferPos[group]++; | 
			
		
	
		
		
			
				
					
					|  |  |         if(mPowermeterBufferPos[group] >= 5) mPowermeterBufferPos[group] = 0; |  |  |         if (mPowermeterBufferPos[group] >= 5) mPowermeterBufferPos[group] = 0; | 
			
				
				
			
		
	
		
		
	
		
		
			
				
					|  |  |     } |  |  |     } | 
			
		
	
		
		
			
				
					|  |  | 
 |  |  | 
 | 
			
		
	
		
		
			
				
					|  |  |     zeroExport_t *mCfg; |  |  |     zeroExport_t *mCfg; | 
			
		
	
	
		
		
			
				
					|  | @ -481,8 +502,8 @@ class powermeter { | 
			
		
	
		
		
			
				
					|  |  | 
 |  |  | 
 | 
			
		
	
		
		
			
				
					|  |  |     unsigned long mPreviousTsp = 0; |  |  |     unsigned long mPreviousTsp = 0; | 
			
		
	
		
		
			
				
					|  |  | 
 |  |  | 
 | 
			
		
	
		
		
			
				
					
					|  |  |     PowermeterBuffer_t mPowermeterBuffer[ZEROEXPORT_MAX_GROUPS][5] = { 0 }; |  |  |     PowermeterBuffer_t mPowermeterBuffer[ZEROEXPORT_MAX_GROUPS][5] = {0}; | 
			
				
				
			
		
	
		
		
			
				
					
					|  |  |     short mPowermeterBufferPos[ZEROEXPORT_MAX_GROUPS] = { 0 }; |  |  |     short mPowermeterBufferPos[ZEROEXPORT_MAX_GROUPS] = {0}; | 
			
				
				
			
		
	
		
		
	
		
		
	
		
		
			
				
					|  |  | }; |  |  | }; | 
			
		
	
		
		
			
				
					|  |  | 
 |  |  | 
 | 
			
		
	
		
		
			
				
					|  |  | // TODO: Vorlagen für Powermeter-Analyse
 |  |  | // TODO: Vorlagen für Powermeter-Analyse
 | 
			
		
	
	
		
		
			
				
					|  | 
 |