From 94773024f17edee8182c9053f8522b9224d834a9 Mon Sep 17 00:00:00 2001 From: Victor Chang Date: Sat, 9 Dec 2023 16:28:27 -0800 Subject: [PATCH] Update the docs about the V7 payload. --- docs/protocol-meter-reading.md | 69 ++++++++++++++++++++++++++++++---- docs/protocol.md | 5 ++- src/emporia_vue_utility.h | 4 +- 3 files changed, 67 insertions(+), 11 deletions(-) diff --git a/docs/protocol-meter-reading.md b/docs/protocol-meter-reading.md index 4786c32..0627eb1 100644 --- a/docs/protocol-meter-reading.md +++ b/docs/protocol-meter-reading.md @@ -1,5 +1,9 @@ # Meter Response Payload +There are at least two known response payloads sent by the MGM111 chip. MGM Firmware version 2 sends a 152 byte payload while version 7 sends a 45 byte payload. Check the section below relevant to your version. + +## Payload for Version 2 + The meter reading response contains 152 bytes of payload, most of which seem to always be zeros. The fields in the payload have a mix of sizes and just to make things more confusing, the use of LSB / MSB byte ordering is inconsistent. The below table details the payload format that's been reversed engineered so far. @@ -23,9 +27,9 @@ Blank cells have never been seen to be anything other than zero. Note the table 148 MeterTS -## Known Fields +### Known Fields -### EnergyVal +#### EnergyVal Bytes 4 to 8, 32 bit int, unknown if signed, MSB @@ -34,14 +38,14 @@ might reset monthly or on start of new billing cycle. Sometimes, an invalid number greater than `0x00400000` is returned, it is not understood when or why this happens. -### MeterDiv +#### MeterDiv At least byte 47, maybe as large as bytes 44 to 47 Some meters report values not in watts and watt hours but in a multiple of those values. `EnergyVal` and `PowerVal` should be divided by `MeterDiv` to determine the real value. Usually this is 1, but have also seen a value of 3. -### EnergyCostUnit +#### EnergyCostUnit Bytes 50 and 51 MSB(?) @@ -50,7 +54,7 @@ Since people are typically charged per kWh, this value is typically 1000. This value is not currently used in the code -### PowerVal +#### PowerVal Bytes 57 to 59 (24 bit signed int, MSB) @@ -59,7 +63,7 @@ Negative values are returned in 1's complement notation (if left most bit is 1, "Data Missing" / "Unknown" is denoted as max negative, `0x800000` -### MeterTS +#### MeterTS Bytes 148 to 151 (32 bit unsigned int, LSB) @@ -68,7 +72,7 @@ Will roll over every 49 days. Only reported as a debugging value, not used in calculations. -### Unknown 1 +#### Unknown 1 Bytes 52 and 53 @@ -79,3 +83,54 @@ fbfb 3133 ``` Random uneducated guess is that this is a bit field with flags about the meter configuration. + +## Payload for Version 7 + +The meter reading response contains 45 bytes of payload, most of which seem to always be zeros. The table below details the payload format that's been reversed engineered so far. +Blank cells have never been seen to be anything other than zero. Some cells have hex codes that I have never seen change, but might differ for you. Note the table is zero-indexed (starts at byte zero, not byte 1). + + + + + + + + + + + + + + + + + + + +
0123
0 0x18Incrementor0x01
4 0x25ImportWh~
8 ~ImportWh0x160x09
12 0x01
16 ExportWh0x97
20 0x01
24 0x030x220x01
28 0x020x03
32 0x220xE80x03
36 0x04
40 PowerVal
+ +### Known Fields + +#### ImportWh + +Bytes 7 to 8, (16 bit int, probably unsigned, LSB) + +Cumulative watt-hours consumed from the grid. Unknown when the value resets, but probably never resets since ESP32 never sends a clock sync to the MGM111 so it likely just rolls over. + +#### ExportWh + +Bytes 17 to 18, (16 bit int, probably unsigned, LSB) + +Cumulative watt-hours sent to the grid. Unknown when the value resets, but probably never resets since ESP32 never sends a clock sync to the MGM111 so it likely just rolls over. + +#### PowerVal + +Bytes 41 and 43 (24 bit signed int, LSB) + +The power being sent or consumed at this moment. This is in watts for me but I know in the V2 payload that there is a `MeterDiv`, which means `PowerVal` might be a multiplication of the real wattage. If V7 also has this behavior then `MeterDiv` must have a value of 1 in my readings. So, `MeterDiv` might be byte 2, 13, 23, or 27. + +#### Incrementor + +Byte 1 (8 bit unsigned int) + +This just increments by 1 on each reading and rolls over. \ No newline at end of file diff --git a/docs/protocol.md b/docs/protocol.md index 7dc26e2..12cba59 100644 --- a/docs/protocol.md +++ b/docs/protocol.md @@ -42,5 +42,8 @@ The mac address reponse bytes are in reverse order, if the device responds with #### Install code response payload The install code bytes are not swapped like the mac address payload. +#### Meter join response payload +This always returns a 0x01 value even if the Vue is not in range of the meter. + #### Meter reading response payload -The meter response payload has it's own page [protocol-meter-reading.md](protocol-meter-reading.md) +The meter response payload has its own page [protocol-meter-reading.md](protocol-meter-reading.md) diff --git a/src/emporia_vue_utility.h b/src/emporia_vue_utility.h index b9dbdec..60f3889 100644 --- a/src/emporia_vue_utility.h +++ b/src/emporia_vue_utility.h @@ -236,8 +236,6 @@ class EmporiaVueUtility : public Component, public UARTDevice { return 0; } - // Byte-swap a 32 bit int in the proprietary format - // used by the MGS111 int32_t endian_swap(uint32_t in) { uint32_t x = 0; x += (in & 0x000000FF) << 24; @@ -315,7 +313,7 @@ class EmporiaVueUtility : public Component, public UARTDevice { // Quick validate, look for a magic number. if (input_buffer.data[44] != 0x2A) { - ESP_LOGE(TAG, "Byte 44 was %d instead of %d", input_buffer.data[44], 0x2A); + ESP_LOGE(TAG, "Byte 44 was %02x instead of %02x", input_buffer.data[44], 0x2A); last_reading_has_error = 1; return; }