|
@ -8,10 +8,20 @@ import argparse |
|
|
import time |
|
|
import time |
|
|
import struct |
|
|
import struct |
|
|
import crcmod |
|
|
import crcmod |
|
|
|
|
|
import json |
|
|
from datetime import datetime |
|
|
from datetime import datetime |
|
|
from RF24 import RF24, RF24_PA_LOW, RF24_PA_MAX, RF24_250KBPS |
|
|
from RF24 import RF24, RF24_PA_LOW, RF24_PA_MAX, RF24_250KBPS |
|
|
|
|
|
import paho.mqtt.client |
|
|
|
|
|
from configparser import ConfigParser |
|
|
|
|
|
|
|
|
|
|
|
cfg = ConfigParser() |
|
|
|
|
|
cfg.read('ahoy.conf') |
|
|
|
|
|
mqtt_host = cfg.get('mqtt', 'host', fallback='192.168.1.1') |
|
|
|
|
|
mqtt_port = cfg.getint('mqtt', 'port', fallback=1883) |
|
|
|
|
|
|
|
|
radio = RF24(22, 0, 1000000) |
|
|
radio = RF24(22, 0, 1000000) |
|
|
|
|
|
mqtt_client = paho.mqtt.client.Client() |
|
|
|
|
|
mqtt_client.connect(mqtt_host, mqtt_port) |
|
|
|
|
|
|
|
|
# Master Address ('DTU') |
|
|
# Master Address ('DTU') |
|
|
dtu_ser = 99978563412 # identical to fc22's |
|
|
dtu_ser = 99978563412 # identical to fc22's |
|
@ -105,18 +115,37 @@ def on_receive(p): |
|
|
print(ts.isoformat(), end='Z ') |
|
|
print(ts.isoformat(), end='Z ') |
|
|
|
|
|
|
|
|
# interpret content |
|
|
# interpret content |
|
|
if p[0] == 0x95: |
|
|
mid = p[0] |
|
|
|
|
|
d['mid'] = mid |
|
|
|
|
|
name = 'unknowndata' |
|
|
|
|
|
|
|
|
|
|
|
if mid == 0x95: |
|
|
src, dst, cmd = struct.unpack('>LLB', p[1:10]) |
|
|
src, dst, cmd = struct.unpack('>LLB', p[1:10]) |
|
|
src_s = f'{src:08x}' |
|
|
src_s = f'{src:08x}' |
|
|
dst_s = f'{dst:08x}' |
|
|
dst_s = f'{dst:08x}' |
|
|
|
|
|
d['src'] = src_s |
|
|
|
|
|
d['dst'] = dst_s |
|
|
|
|
|
d['cmd'] = cmd |
|
|
print(f'MSG src={src_s}, dst={dst_s}, cmd={cmd}, ', end=' ') |
|
|
print(f'MSG src={src_s}, dst={dst_s}, cmd={cmd}, ', end=' ') |
|
|
|
|
|
|
|
|
if cmd==1: |
|
|
if cmd==1: |
|
|
|
|
|
name = 'dcdata' |
|
|
unknown1, u1, i1, p1, u2, i2, p2, unknown2 = struct.unpack( |
|
|
unknown1, u1, i1, p1, u2, i2, p2, unknown2 = struct.unpack( |
|
|
'>HHHHHHHH', p[10:26]) |
|
|
'>HHHHHHHH', p[10:26]) |
|
|
print(f'u1={u1/10}V, i1={i1/100}A, p1={p1/10}W, ', end='') |
|
|
print(f'u1={u1/10}V, i1={i1/100}A, p1={p1/10}W, ', end='') |
|
|
print(f'u2={u2/10}V, i2={i2/100}A, p2={p2/10}W, ', end='') |
|
|
print(f'u2={u2/10}V, i2={i2/100}A, p2={p2/10}W, ', end='') |
|
|
print(f'unknown1={unknown1}, unknown2={unknown2}') |
|
|
print(f'unknown1={unknown1}, unknown2={unknown2}') |
|
|
|
|
|
d['u1_V'] = u1/10 |
|
|
|
|
|
d['i1_A'] = i1/100 |
|
|
|
|
|
d['p1_W'] = p1/10 |
|
|
|
|
|
d['u2_V'] = u2/10 |
|
|
|
|
|
d['i2_A'] = i2/100 |
|
|
|
|
|
d['p2_W'] = p2/10 |
|
|
|
|
|
d['unknown1'] = unknown1 |
|
|
|
|
|
d['unknown2'] = unknown2 |
|
|
|
|
|
|
|
|
elif cmd==2: |
|
|
elif cmd==2: |
|
|
|
|
|
name = 'acdata' |
|
|
uk1, uk2, uk3, uk4, uk5, u, f, p = struct.unpack( |
|
|
uk1, uk2, uk3, uk4, uk5, u, f, p = struct.unpack( |
|
|
'>HHHHHHHH', p[10:26]) |
|
|
'>HHHHHHHH', p[10:26]) |
|
|
print(f'u={u/10:.1f}V, f={f/100:.2f}Hz, p={p/10:.1f}W, ', end='') |
|
|
print(f'u={u/10:.1f}V, f={f/100:.2f}Hz, p={p/10:.1f}W, ', end='') |
|
@ -125,11 +154,31 @@ def on_receive(p): |
|
|
print(f'uk3={uk3}, ', end='') |
|
|
print(f'uk3={uk3}, ', end='') |
|
|
print(f'uk4={uk4}, ', end='') |
|
|
print(f'uk4={uk4}, ', end='') |
|
|
print(f'uk5={uk5}') |
|
|
print(f'uk5={uk5}') |
|
|
|
|
|
d['u_V'] = u/10 |
|
|
|
|
|
d['f_Hz'] = f/100 |
|
|
|
|
|
d['p_W'] = p/10 |
|
|
|
|
|
d['wtot1_Wh'] = uk1 |
|
|
|
|
|
d['wtot2_Wh'] = uk3 |
|
|
|
|
|
d['wday1_Wh'] = uk4 |
|
|
|
|
|
d['wday2_Wh'] = uk5 |
|
|
|
|
|
d['uk2'] = uk2 |
|
|
|
|
|
|
|
|
else: |
|
|
else: |
|
|
print(f'unknown cmd {cmd}') |
|
|
print(f'unknown cmd {cmd}') |
|
|
else: |
|
|
else: |
|
|
print(f'unknown frame id {p[0]}') |
|
|
print(f'unknown frame id {p[0]}') |
|
|
|
|
|
|
|
|
|
|
|
# output to MQTT |
|
|
|
|
|
if d: |
|
|
|
|
|
j = json.dumps(d) |
|
|
|
|
|
mqtt_client.publish(f'ahoy/{src}/{name}', j) |
|
|
|
|
|
if d['cmd']==2: |
|
|
|
|
|
mqtt_client.publish(f'ahoy/{src}/{name}/p_W', d['p_W']) |
|
|
|
|
|
if d['cmd']==1: |
|
|
|
|
|
mqtt_client.publish(f'ahoy/{src}/{name}/p1_W', d['p1_W']) |
|
|
|
|
|
mqtt_client.publish(f'ahoy/{src}/{name}/p2_W', d['p2_W']) |
|
|
|
|
|
mqtt_client.publish(f'ahoy/{src}/{name}/p_W', d['p1_W']+d['p2_W']) |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
def main_loop(): |
|
|
def main_loop(): |
|
|
""" |
|
|
""" |
|
@ -141,6 +190,9 @@ def main_loop(): |
|
|
print_addr(dtu_ser) |
|
|
print_addr(dtu_ser) |
|
|
|
|
|
|
|
|
ctr = 1 |
|
|
ctr = 1 |
|
|
|
|
|
|
|
|
|
|
|
ts = int(time.time()) # see what happens if we always send one and the same (constant) time! |
|
|
|
|
|
|
|
|
while True: |
|
|
while True: |
|
|
radio.setChannel(3) |
|
|
radio.setChannel(3) |
|
|
radio.enableDynamicPayloads() |
|
|
radio.enableDynamicPayloads() |
|
@ -167,6 +219,8 @@ def main_loop(): |
|
|
print(f"Received {size} bytes on pipe {pipe_number}: " + |
|
|
print(f"Received {size} bytes on pipe {pipe_number}: " + |
|
|
" ".join([f"{b:02x}" for b in payload])) |
|
|
" ".join([f"{b:02x}" for b in payload])) |
|
|
on_receive(payload) |
|
|
on_receive(payload) |
|
|
|
|
|
else: |
|
|
|
|
|
time.sleep(0.01) |
|
|
|
|
|
|
|
|
radio.stopListening() # put radio in TX mode |
|
|
radio.stopListening() # put radio in TX mode |
|
|
radio.setChannel(40) |
|
|
radio.setChannel(40) |
|
@ -176,7 +230,7 @@ def main_loop(): |
|
|
pass |
|
|
pass |
|
|
# radio.printPrettyDetails() |
|
|
# radio.printPrettyDetails() |
|
|
|
|
|
|
|
|
ts = int(time.time()) |
|
|
# ts = int(time.time()) |
|
|
payload = compose_0x80_msg(src_ser_no=dtu_ser, dst_ser_no=inv_ser, ts=ts) |
|
|
payload = compose_0x80_msg(src_ser_no=dtu_ser, dst_ser_no=inv_ser, ts=ts) |
|
|
print(f"{ctr:5d}: len={len(payload)} | " + " ".join([f"{b:02x}" for b in payload]), |
|
|
print(f"{ctr:5d}: len={len(payload)} | " + " ".join([f"{b:02x}" for b in payload]), |
|
|
flush=True) |
|
|
flush=True) |
|
|