From 5935e0dabeabf26a72fa097c7aa0ce42eb846970 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jan-Jonas=20S=C3=A4mann?= Date: Mon, 23 May 2022 07:16:56 +0200 Subject: [PATCH] Update pypackage set txpower per nrf/inverter Add config parameter `txpower` in inverters- and nrf context. This enables overriding txpower default RF24_PA_MAX, in some cases inverters require RF24_PA_LOW. For larger setups, txpower can be set per inverter to be able to query a far away (max) and a near by (low) one from within one instance. Valid values can be: * `txpower: 'max'` (corresponds to RF24_PA_MAX, default) * `txpower: 'low'` (corresponds to RF24_PA_LOW) --- tools/rpi/ahoy.yml.example | 2 ++ tools/rpi/hoymiles/__init__.py | 35 +++++++++++++++++++++++++++++----- tools/rpi/hoymiles/__main__.py | 12 ++---------- 3 files changed, 34 insertions(+), 15 deletions(-) diff --git a/tools/rpi/ahoy.yml.example b/tools/rpi/ahoy.yml.example index ef139c487..9426d1a4a 100644 --- a/tools/rpi/ahoy.yml.example +++ b/tools/rpi/ahoy.yml.example @@ -8,6 +8,7 @@ ahoy: nrf: - ce_pin: 22 cs_pin: 0 + txpower: 'low' # default txpower (low,max) mqtt: disabled: false @@ -31,6 +32,7 @@ ahoy: inverters: - name: 'balkon' serial: 114172220003 + txpower: 'low' # txpower per inverter (low,max) mqtt: send_raw_enabled: false # allow inject debug data via mqtt topic: 'hoymiles/114172221234' # defaults to 'hoymiles/{serial}' diff --git a/tools/rpi/hoymiles/__init__.py b/tools/rpi/hoymiles/__init__.py index 72c6a1987..c30105221 100644 --- a/tools/rpi/hoymiles/__init__.py +++ b/tools/rpi/hoymiles/__init__.py @@ -274,16 +274,27 @@ class HoymilesNRF: rx_channel_list = [3,23,40,61,75] rx_channel_ack = False rx_error = 0 + txpower = 'max' - def __init__(self, device): + def __init__(self, **radio_config): """ Claim radio device :param NRF24 device: instance of NRF24 """ - self.radio = device + radio = RF24( + radio_config.get('ce_pin', 22), + radio_config.get('cs_pin', 0), + radio_config.get('spispeed', 1000000)) - def transmit(self, packet): + if not radio.begin(): + raise RuntimeError('Can\'t open radio') + + self.txpower = radio_config.get('txpower', 'max') + + self.radio = radio + + def transmit(self, packet, txpower=None): """ Transmit Packet @@ -292,12 +303,14 @@ def transmit(self, packet): :rtype: bool """ + if not txpower: + txpower = self.txpower + inv_esb_addr = b'\01' + packet[1:5] dtu_esb_addr = b'\01' + packet[5:9] self.radio.stopListening() # put radio in TX mode self.radio.setDataRate(RF24_250KBPS) - #self.radio.setPALevel(RF24_PA_LOW) self.radio.openReadingPipe(1,dtu_esb_addr) self.radio.openWritingPipe(inv_esb_addr) self.radio.setChannel(self.tx_channel) @@ -306,6 +319,11 @@ def transmit(self, packet): self.radio.setCRCLength(RF24_CRC_16) self.radio.enableDynamicPayloads() + if txpower == 'low': + self.radio.setPALevel(RF24_PA_LOW) + else: + self.radio.setPALevel(RF24_PA_MAX) + return self.radio.write(packet) def receive(self, timeout=None): @@ -402,6 +420,9 @@ def rx_channel(self): """ return self.rx_channel_list[self.rx_channel_id] + def __del__(self): + self.radio.powerDown() + def frame_payload(payload): """ Prepare payload for transmission, append Modbus CRC16 @@ -490,6 +511,7 @@ class InverterTransaction: time_rx = None radio = None + txpower = None def __init__(self, request_time=None, @@ -513,6 +535,9 @@ def __init__(self, if radio: self.radio = radio + if 'txpower' in params: + self.txpower = params['txpower'] + if not request_time: request_time=datetime.now() @@ -555,7 +580,7 @@ def rxtx(self): c_datetime = datetime.now().strftime("%Y-%m-%d %H:%M:%S.%f") print(f'{c_datetime} Transmit {len(packet)} | {hexify_payload(packet)}') - self.radio.transmit(packet) + self.radio.transmit(packet, txpower=self.txpower) wait = False try: diff --git a/tools/rpi/hoymiles/__main__.py b/tools/rpi/hoymiles/__main__.py index f74828da0..c9c2ba01a 100644 --- a/tools/rpi/hoymiles/__main__.py +++ b/tools/rpi/hoymiles/__main__.py @@ -14,7 +14,6 @@ import yaml from yaml.loader import SafeLoader import paho.mqtt.client -from RF24 import RF24, RF24_PA_LOW, RF24_PA_MAX, RF24_250KBPS, RF24_CRC_DISABLED, RF24_CRC_8, RF24_CRC_16 import hoymiles def main_loop(): @@ -52,6 +51,7 @@ def poll_inverter(inverter, retries=4): payload_ttl = payload_ttl - 1 com = hoymiles.InverterTransaction( radio=hmradio, + txpower=inverter.get('txpower', None), dtu_ser=dtu_ser, inverter_ser=inverter_ser, request=next(hoymiles.compose_esb_packet( @@ -207,11 +207,7 @@ def mqtt_on_command(client, userdata, message): # Prepare for multiple transceivers, makes them configurable (currently # only one supported) for radio_config in ahoy_config.get('nrf', [{}]): - radio = RF24( - radio_config.get('ce_pin', 22), - radio_config.get('cs_pin', 0), - radio_config.get('spispeed', 1000000)) - hmradio = hoymiles.HoymilesNRF(device=radio) + hmradio = hoymiles.HoymilesNRF(**radio_config) mqtt_client = None @@ -242,9 +238,6 @@ def mqtt_on_command(client, userdata, message): bucket=influx_config.get('bucket', None), measurement=influx_config.get('measurement', 'hoymiles')) - if not radio.begin(): - raise RuntimeError('Can\'t open radio') - g_inverters = [g_inverter.get('serial') for g_inverter in ahoy_config.get('inverters', [])] for g_inverter in ahoy_config.get('inverters', []): g_inverter_ser = g_inverter.get('serial') @@ -274,5 +267,4 @@ def mqtt_on_command(client, userdata, message): time.sleep(time.time() % loop_interval) except KeyboardInterrupt: - radio.powerDown() sys.exit()