Update the docs about the V7 payload.

This commit is contained in:
Victor Chang
2023-12-09 16:28:27 -08:00
parent 39b97f15ba
commit 94773024f1
3 changed files with 67 additions and 11 deletions

View File

@@ -1,5 +1,9 @@
# Meter Response Payload # 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 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. 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. 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
<tr> <th>148</th> <td colspan=4 align="center">MeterTS</td></tr> <tr> <th>148</th> <td colspan=4 align="center">MeterTS</td></tr>
</table> </table>
## Known Fields ### Known Fields
### EnergyVal #### EnergyVal
Bytes 4 to 8, 32 bit int, unknown if signed, MSB 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. 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 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 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. 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(?) 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 This value is not currently used in the code
### PowerVal #### PowerVal
Bytes 57 to 59 (24 bit signed int, MSB) 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` "Data Missing" / "Unknown" is denoted as max negative, `0x800000`
### MeterTS #### MeterTS
Bytes 148 to 151 (32 bit unsigned int, LSB) 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. Only reported as a debugging value, not used in calculations.
### Unknown 1 #### Unknown 1
Bytes 52 and 53 Bytes 52 and 53
@@ -79,3 +83,54 @@ fbfb
3133 3133
``` ```
Random uneducated guess is that this is a bit field with flags about the meter configuration. 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).
<table style="width:80%">
<tr> <td></td>
<th align="center"><img width="50" height="1">0<img width="50" height="1"></th>
<th align="center"><img width="50" height="1">1<img width="50" height="1"></th>
<th align="center"><img width="50" height="1">2<img width="50" height="1"></th>
<th align="center"><img width="50" height="1">3<img width="50" height="1"></th>
</tr>
<tr> <th>0</th> <td colspan=1 align="center">0x18</td><td colspan=1 align="center">Incrementor</td><td colspan=1 align="center">0x01</td><td colspan=1></tr>
<tr> <th>4</th> <td colspan=2></td><td colspan=1 align="center">0x25</td><td colspan=1 align="center">ImportWh~</td></tr>
<tr> <th>8</th> <td colspan=1 align="center">~ImportWh</td><td colspan=1 align="center">0x16</td><td colspan=1 align="center">0x09</td><td colspan=1></td></tr>
<tr> <th>12</th> <td colspan=1></td><td colspan=1 align="center">0x01</td><td colspan=2></td></tr>
<tr> <th>16</th> <td colspan=1></td><td colspan=2 align="center">ExportWh</td><td colspan=1 align="center">0x97</td></tr>
<tr> <th>20</th> <td colspan=3></td><td colspan=1 align="center">0x01</td></tr>
<tr> <th>24</th> <td colspan=1 align="center">0x03</td><td colspan=1></td><td colspan=1 align="center">0x22</td><td colspan=1 align="center">0x01</td></tr>
<tr> <th>28</th> <td colspan=2></td><td colspan=1 align="center">0x02</td><td colspan=1 align="center">0x03</td></tr>
<tr> <th>32</th> <td colspan=1></td><td colspan=1 align="center">0x22</td><td colspan=1 align="center">0xE8</td><td colspan=1 align="center">0x03</td></tr>
<tr> <th>36</th> <td colspan=1></td><td colspan=1></td><td colspan=1 align="center">0x04</td><td colspan=1></td></tr>
<tr> <th>40</th> <td colspan=1></td><td colspan=3 align="center">PowerVal</td></tr>
</table>
### 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.

View File

@@ -42,5 +42,8 @@ The mac address reponse bytes are in reverse order, if the device responds with
#### Install code response payload #### Install code response payload
The install code bytes are not swapped like the mac address 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 #### 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)

View File

@@ -236,8 +236,6 @@ class EmporiaVueUtility : public Component, public UARTDevice {
return 0; return 0;
} }
// Byte-swap a 32 bit int in the proprietary format
// used by the MGS111
int32_t endian_swap(uint32_t in) { int32_t endian_swap(uint32_t in) {
uint32_t x = 0; uint32_t x = 0;
x += (in & 0x000000FF) << 24; x += (in & 0x000000FF) << 24;
@@ -315,7 +313,7 @@ class EmporiaVueUtility : public Component, public UARTDevice {
// Quick validate, look for a magic number. // Quick validate, look for a magic number.
if (input_buffer.data[44] != 0x2A) { 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; last_reading_has_error = 1;
return; return;
} }