1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
|
From 1c8594af0f8060090255c22ed13ede464b6df1b9 Mon Sep 17 00:00:00 2001
From: "M. Greyson Christoforo" <grey@christoforo.net>
Date: Mon, 18 Aug 2025 11:48:50 -0600
Subject: [PATCH 1/2] add logic to decode the total kWh counter reported by my
meter
fix scaling
parse timestamp info from meter reading message
---
python/packetize.py | 12 +++++++++++-
1 file changed, 11 insertions(+), 1 deletion(-)
diff --git a/python/packetize.py b/python/packetize.py
index 665dd5d..b99ee44 100644
--- a/python/packetize.py
+++ b/python/packetize.py
@@ -105,7 +105,7 @@ def process_packet(self, channel, pkt):
if src & 0x80000000 == 0 and len(payload) > cmd_start:
cmd_len = payload[cmd_start]
- if cmd_len == 0x33 and len(payload) >= cmd_start + 1 + cmd_len:
+ if cmd_len in (0x33, 0xab) and len(payload) >= cmd_start + 1 + cmd_len - 2:
cmd_payload = payload[cmd_start + 1:cmd_start + 1 + cmd_len]
cmd = cmd_payload[1]
if cmd == 0xce: # hourly usage data, every 6 hours
@@ -124,6 +124,16 @@ def process_packet(self, channel, pkt):
print()
+ elif cmd == 0x23: # usage message
+ print()
+
+ main_reading = struct.unpack("<i", cmd_payload[15:19])[0]/1000
+ YY, MM, DD, hh, mm, ss = struct.unpack("BBBBBB", cmd_payload[8:14])
+ ts_theirs = datetime.datetime(2000+YY, MM, DD, hh, mm, ss)
+ print(f" Reading for meter number {src} @ {ts_theirs.isoformat()} = {main_reading} kWh")
+
+ print()
+
def forecast(self, noutput_items, ninputs):
return [640] * ninputs
From 726318ae2653234d65a42e463ae51fc1eb22a171 Mon Sep 17 00:00:00 2001
From: "M. Greyson Christoforo" <grey@christoforo.net>
Date: Tue, 9 Sep 2025 15:50:40 -0600
Subject: [PATCH 2/2] add walrus
---
.gitignore | 1 +
python/packetize.py | 12 ++++++------
2 files changed, 7 insertions(+), 6 deletions(-)
diff --git a/.gitignore b/.gitignore
index 8acdcd9..4bc3e0a 100644
--- a/.gitignore
+++ b/.gitignore
@@ -1,3 +1,4 @@
/build/
/apps/elster*.py
*.pcap
+*.pdf
diff --git a/python/packetize.py b/python/packetize.py
index b99ee44..7a7e07a 100644
--- a/python/packetize.py
+++ b/python/packetize.py
@@ -125,14 +125,14 @@ def process_packet(self, channel, pkt):
print()
elif cmd == 0x23: # usage message
- print()
+ if main_reading := struct.unpack("<i", cmd_payload[15:19])[0]/1000:
+ print()
- main_reading = struct.unpack("<i", cmd_payload[15:19])[0]/1000
- YY, MM, DD, hh, mm, ss = struct.unpack("BBBBBB", cmd_payload[8:14])
- ts_theirs = datetime.datetime(2000+YY, MM, DD, hh, mm, ss)
- print(f" Reading for meter number {src} @ {ts_theirs.isoformat()} = {main_reading} kWh")
+ YY, MM, DD, hh, mm, ss = struct.unpack("BBBBBB", cmd_payload[8:14])
+ ts_theirs = datetime.datetime(2000+YY, MM, DD, hh, mm, ss)
+ print(f" Reading for meter number {src} @ {ts_theirs.isoformat()} = {main_reading} kWh")
- print()
+ print()
def forecast(self, noutput_items, ninputs):
return [640] * ninputs
|