diff --git a/frames/Kamstup-Encrypted.raw b/frames/Kamstup-Encrypted.raw new file mode 100644 index 00000000..92704f72 --- /dev/null +++ b/frames/Kamstup-Encrypted.raw @@ -0,0 +1,40 @@ +# After decode: +7E A1 E9 41 03 13 C6 37 E6 E7 00 DB 08 4B 41 4D 45 01 AC 4D 6E 82 01 D0 30 00 00 A3 2F 0F 00 00 00 00 +0C 07 E4 05 0C 02 0A 19 00 FF 80 00 80 + +02 41 +0A 0E 4B 61 6D 73 74 72 75 70 5F 56 30 30 30 31 - List ID +09 06 01 01 01 08 00 FF 06 00 11 94 CA - Active+ Energy +09 06 01 01 02 08 00 FF 06 00 00 00 00 - Active- Energy +09 06 01 01 03 08 00 FF 06 00 00 12 7E - Reactive+ Energy +09 06 01 01 04 08 00 FF 06 00 09 55 0E - Reactive- Energy +09 06 01 01 00 00 01 FF 06 01 44 AD E1 - Electricity ID? +09 06 01 01 01 07 00 FF 06 00 00 05 CC - Active+ Instantaneous value +09 06 01 01 02 07 00 FF 06 00 00 00 00 - Active- Instantaneous value +09 06 01 01 03 07 00 FF 06 00 00 00 00 - Reactive+ Instantaneous value +09 06 01 01 04 07 00 FF 06 00 00 00 17 - Reactive- Instantaneous value +09 06 00 01 01 00 00 FF 09 0C 07 E4 05 0C 02 0A 19 00 FF 80 00 80 - Current date/time +09 06 01 01 20 07 00 FF 12 00 E5 - L1 Voltage Instantaneous value +09 06 01 01 34 07 00 FF 12 00 E5 - L2 Voltage Instantaneous value +09 06 01 01 48 07 00 FF 12 00 E3 - L3 Voltage Instantaneous value +09 06 01 01 1F 07 00 FF 06 00 00 00 4B - L1 Current Instantaneous value +09 06 01 01 33 07 00 FF 06 00 00 00 AA - L2 Current Instantaneous value +09 06 01 01 47 07 00 FF 06 00 00 01 E4 - L3 Current Instantaneous value +09 06 01 01 15 07 00 FF 06 00 00 00 71 - L1 Active+ Instantaneous value +09 06 01 01 29 07 00 FF 06 00 00 01 54 - L2 Active+ Instantaneous value +09 06 01 01 3D 07 00 FF 06 00 00 04 07 - L3 Active+ Instantaneous value +09 06 01 01 21 07 00 FF 12 00 4D - L1 (cos.phi) (PF) Instantaneous value +09 06 01 01 35 07 00 FF 12 00 5F - L2 (cos.phi) (PF) Instantaneous value +09 06 01 01 49 07 00 FF 12 00 62 - L3 (cos.phi) (PF) Instantaneous value +09 06 01 01 0D 07 00 FF 12 00 63 - Avegage (cos.phi) (PF) Inst. value +09 06 01 01 16 07 00 FF 06 00 00 00 00 - L1 Active- Instantaneous value +09 06 01 01 2A 07 00 FF 06 00 00 00 00 - L2 Active- Instantaneous value +09 06 01 01 3E 07 00 FF 06 00 00 00 00 - L3 Active- Instantaneous value +09 06 01 01 16 08 00 FF 06 00 00 00 00 - L1 Active- Energy +09 06 01 01 2A 08 00 FF 06 00 00 00 00 - L2 Active- Energy +09 06 01 01 3E 08 00 FF 06 00 00 00 00 - L3 Active- Energy +09 06 01 01 15 08 00 FF 06 00 0A 8F 97 - L1 Active+ Energy +09 06 01 01 29 08 00 FF 06 00 04 C1 53 - L2 Active+ Energy +09 06 01 01 3D 08 00 FF 06 00 02 43 E0 - L3 Active+ Energy + +5B C3 CD 5E 79 18 18 DA 9F 97 85 FF 5A 84 7E \ No newline at end of file diff --git a/frames/Kamstup-TN-3p.raw b/frames/Kamstup-TN-3p.raw index 033e3e2f..a6606523 100644 --- a/frames/Kamstup-TN-3p.raw +++ b/frames/Kamstup-TN-3p.raw @@ -1,8 +1,8 @@ -7E A0 E2 2B 21 13 23 9A E6 E7 00 0F 00 00 00 00 0C -07 E5 0B 11 03 0B 32 00 FF 80 00 00 +7E A0 E2 2B 21 13 23 9A E6 E7 00 0F 00 00 00 00 +0C 07 E5 0B 11 03 0B 32 00 FF 80 00 00 02 19 -0A 0E 4B 61 6D 73 74 72 75 70 5F 56 30 30 30 31 - +0A 0E 4B 61 6D 73 74 72 75 70 5F 56 30 30 30 31 - List ID 09 06 01 01 00 00 05 FF 0A 10 XX XX XX XX XX XX XX XX XX XX XX XX XX XX XX XX - Meter ID 09 06 01 01 60 01 01 FF 0A 12 36 38 34 31 31 33 31 42 4E 32 34 33 31 30 31 30 34 30 - Meter model 09 06 01 01 01 07 00 FF 06 00 00 05 E6 - Active+ diff --git a/src/AmsData.cpp b/src/AmsData.cpp index c89604d1..45838843 100644 --- a/src/AmsData.cpp +++ b/src/AmsData.cpp @@ -28,6 +28,10 @@ void AmsData::apply(AmsData& other) { this->listType = other.getListType(); switch(other.getListType()) { case 3: + this->powerFactor = other.getPowerFactor(); + this->l1PowerFactor = other.getL1PowerFactor(); + this->l2PowerFactor = other.getL2PowerFactor(); + this->l3PowerFactor = other.getL3PowerFactor(); this->meterTimestamp = other.getMeterTimestamp(); this->activeImportCounter = other.getActiveImportCounter(); this->activeExportCounter = other.getActiveExportCounter(); @@ -127,6 +131,22 @@ float AmsData::getL3Current() { return this->l3current; } +float AmsData::getPowerFactor() { + return this->powerFactor; +} + +float AmsData::getL1PowerFactor() { + return this->l1PowerFactor; +} + +float AmsData::getL2PowerFactor() { + return this->l2PowerFactor; +} + +float AmsData::getL3PowerFactor() { + return this->l3PowerFactor; +} + float AmsData::getActiveImportCounter() { return this->activeImportCounter; } diff --git a/src/AmsData.h b/src/AmsData.h index c55d315d..e428e0b2 100644 --- a/src/AmsData.h +++ b/src/AmsData.h @@ -46,6 +46,11 @@ public: float getL2Current(); float getL3Current(); + float getPowerFactor(); + float getL1PowerFactor(); + float getL2PowerFactor(); + float getL3PowerFactor(); + float getActiveImportCounter(); float getReactiveImportCounter(); float getActiveExportCounter(); @@ -62,6 +67,7 @@ protected: time_t meterTimestamp = 0; uint16_t activeImportPower = 0, reactiveImportPower = 0, activeExportPower = 0, reactiveExportPower = 0; float l1voltage = 0, l2voltage = 0, l3voltage = 0, l1current = 0, l2current = 0, l3current = 0; + float powerFactor = 0, l1PowerFactor = 0, l2PowerFactor = 0, l3PowerFactor = 0; float activeImportCounter = 0, reactiveImportCounter = 0, activeExportCounter = 0, reactiveExportCounter = 0; bool threePhase = false, twoPhase = false, counterEstimated = false; }; diff --git a/src/IEC6205675.cpp b/src/IEC6205675.cpp index 99f1e2e6..c3bf06fa 100644 --- a/src/IEC6205675.cpp +++ b/src/IEC6205675.cpp @@ -266,6 +266,23 @@ IEC6205675::IEC6205675(const char* d, uint8_t useMeterType, CosemDateTime packag meterTimestamp = ts; } + u32 = getUnsignedNumber(AMS_OBIS_POWER_FACTOR, sizeof(AMS_OBIS_POWER_FACTOR), ((char *) (d))); + if(u32 != 0xFFFFFFFF) { + powerFactor = u32 / 100.0; + } + u32 = getUnsignedNumber(AMS_OBIS_POWER_FACTOR_L1, sizeof(AMS_OBIS_POWER_FACTOR_L1), ((char *) (d))); + if(u32 != 0xFFFFFFFF) { + l1PowerFactor = u32 / 100.0; + } + u32 = getUnsignedNumber(AMS_OBIS_POWER_FACTOR_L2, sizeof(AMS_OBIS_POWER_FACTOR_L2), ((char *) (d))); + if(u32 != 0xFFFFFFFF) { + l2PowerFactor = u32 / 100.0; + } + u32 = getUnsignedNumber(AMS_OBIS_POWER_FACTOR_L3, sizeof(AMS_OBIS_POWER_FACTOR_L3), ((char *) (d))); + if(u32 != 0xFFFFFFFF) { + l3PowerFactor = u32 / 100.0; + } + lastUpdateMillis = millis(); } diff --git a/src/IEC6205675.h b/src/IEC6205675.h index 7bfde259..3367b1da 100644 --- a/src/IEC6205675.h +++ b/src/IEC6205675.h @@ -56,6 +56,10 @@ private: uint8_t AMS_OBIS_ACTIVE_EXPORT_COUNT[4] = { 2, 8, 0, 255 }; uint8_t AMS_OBIS_REACTIVE_IMPORT_COUNT[4] = { 3, 8, 0, 255 }; uint8_t AMS_OBIS_REACTIVE_EXPORT_COUNT[4] = { 4, 8, 0, 255 }; + uint8_t AMS_OBIS_POWER_FACTOR[4] = { 13, 7, 0, 255 }; + uint8_t AMS_OBIS_POWER_FACTOR_L1[4] = { 33, 7, 0, 255 }; + uint8_t AMS_OBIS_POWER_FACTOR_L2[4] = { 53, 7, 0, 255 }; + uint8_t AMS_OBIS_POWER_FACTOR_L3[4] = { 73, 7, 0, 255 }; }; #endif diff --git a/src/mqtt/RawMqttHandler.cpp b/src/mqtt/RawMqttHandler.cpp index fe878164..f11a243f 100644 --- a/src/mqtt/RawMqttHandler.cpp +++ b/src/mqtt/RawMqttHandler.cpp @@ -19,6 +19,18 @@ bool RawMqttHandler::publish(AmsData* data, AmsData* meterState) { mqtt->publish(topic + "/meter/import/active/accumulated", String(data->getActiveImportCounter(), 2), true, 0); mqtt->publish(topic + "/meter/export/reactive/accumulated", String(data->getReactiveExportCounter(), 2), true, 0); mqtt->publish(topic + "/meter/export/active/accumulated", String(data->getActiveExportCounter(), 2), true, 0); + if(full || meterState->getPowerFactor() != data->getPowerFactor()) { + mqtt->publish(topic + "/meter/powerfactor", String(data->getPowerFactor(), 2)); + } + if(full || meterState->getL1PowerFactor() != data->getL1PowerFactor()) { + mqtt->publish(topic + "/meter/l1/powerfactor", String(data->getL1PowerFactor(), 2)); + } + if(full || meterState->getL2PowerFactor() != data->getL2PowerFactor()) { + mqtt->publish(topic + "/meter/l1/powerfactor", String(data->getL1PowerFactor(), 2)); + } + if(full || meterState->getL3PowerFactor() != data->getL3PowerFactor()) { + mqtt->publish(topic + "/meter/l1/powerfactor", String(data->getL1PowerFactor(), 2)); + } case 2: // Only send data if changed. ID and Type is sent on the 10s interval only if changed if(full || meterState->getMeterId() != data->getMeterId()) { diff --git a/src/web/AmsWebServer.cpp b/src/web/AmsWebServer.cpp index 5aebeff1..56ae2c13 100644 --- a/src/web/AmsWebServer.cpp +++ b/src/web/AmsWebServer.cpp @@ -730,7 +730,7 @@ void AmsWebServer::dataJson() { mqttStatus = 3; } - char json[300]; + char json[340]; snprintf_P(json, sizeof(json), DATA_JSON, maxPwr == 0 ? meterState->isThreePhase() ? 20000 : 10000 : maxPwr, meterConfig->productionCapacity, @@ -749,6 +749,10 @@ void AmsWebServer::dataJson() { meterState->getL1Current(), meterState->getL2Current(), meterState->getL3Current(), + meterState->getPowerFactor(), + meterState->getL1PowerFactor(), + meterState->getL2PowerFactor(), + meterState->getL3PowerFactor(), vcc, rssi, hw->getTemperature(), diff --git a/web/data.json b/web/data.json index 8322d217..3995443b 100644 --- a/web/data.json +++ b/web/data.json @@ -16,6 +16,10 @@ "i1" : %.2f, "i2" : %.2f, "i3" : %.2f, + "f" : %.2f, + "f1" : %.2f, + "f2" : %.2f, + "f3" : %.2f, "v" : %.3f, "r" : %d, "t" : %.2f,