summaryrefslogtreecommitdiff
path: root/src/home/mqtt/module/inverter.py
diff options
context:
space:
mode:
Diffstat (limited to 'src/home/mqtt/module/inverter.py')
-rw-r--r--src/home/mqtt/module/inverter.py195
1 files changed, 0 insertions, 195 deletions
diff --git a/src/home/mqtt/module/inverter.py b/src/home/mqtt/module/inverter.py
deleted file mode 100644
index d927a06..0000000
--- a/src/home/mqtt/module/inverter.py
+++ /dev/null
@@ -1,195 +0,0 @@
-import time
-import json
-import datetime
-try:
- import inverterd
-except:
- pass
-
-from typing import Optional
-from .._module import MqttModule
-from .._node import MqttNode
-from .._payload import MqttPayload, bit_field
-try:
- from home.database import InverterDatabase
-except:
- pass
-
-_mult_10 = lambda n: int(n*10)
-_div_10 = lambda n: n/10
-
-
-MODULE_NAME = 'MqttInverterModule'
-
-STATUS_TOPIC = 'status'
-GENERATION_TOPIC = 'generation'
-
-
-class MqttInverterStatusPayload(MqttPayload):
- # 46 bytes
- FORMAT = 'IHHHHHHBHHHHHBHHHHHHHH'
-
- PACKER = {
- 'grid_voltage': _mult_10,
- 'grid_freq': _mult_10,
- 'ac_output_voltage': _mult_10,
- 'ac_output_freq': _mult_10,
- 'battery_voltage': _mult_10,
- 'battery_voltage_scc': _mult_10,
- 'battery_voltage_scc2': _mult_10,
- 'pv1_input_voltage': _mult_10,
- 'pv2_input_voltage': _mult_10
- }
- UNPACKER = {
- 'grid_voltage': _div_10,
- 'grid_freq': _div_10,
- 'ac_output_voltage': _div_10,
- 'ac_output_freq': _div_10,
- 'battery_voltage': _div_10,
- 'battery_voltage_scc': _div_10,
- 'battery_voltage_scc2': _div_10,
- 'pv1_input_voltage': _div_10,
- 'pv2_input_voltage': _div_10
- }
-
- time: int
- grid_voltage: float
- grid_freq: float
- ac_output_voltage: float
- ac_output_freq: float
- ac_output_apparent_power: int
- ac_output_active_power: int
- output_load_percent: int
- battery_voltage: float
- battery_voltage_scc: float
- battery_voltage_scc2: float
- battery_discharge_current: int
- battery_charge_current: int
- battery_capacity: int
- inverter_heat_sink_temp: int
- mppt1_charger_temp: int
- mppt2_charger_temp: int
- pv1_input_power: int
- pv2_input_power: int
- pv1_input_voltage: float
- pv2_input_voltage: float
-
- # H
- mppt1_charger_status: bit_field(0, 16, 2)
- mppt2_charger_status: bit_field(0, 16, 2)
- battery_power_direction: bit_field(0, 16, 2)
- dc_ac_power_direction: bit_field(0, 16, 2)
- line_power_direction: bit_field(0, 16, 2)
- load_connected: bit_field(0, 16, 1)
-
-
-class MqttInverterGenerationPayload(MqttPayload):
- # 8 bytes
- FORMAT = 'II'
-
- time: int
- wh: int
-
-
-class MqttInverterModule(MqttModule):
- _status_poll_freq: int
- _generation_poll_freq: int
- _inverter: Optional[inverterd.Client]
- _database: Optional[InverterDatabase]
- _gen_prev: float
-
- def __init__(self, status_poll_freq=0, generation_poll_freq=0):
- super().__init__(tick_interval=status_poll_freq)
- self._status_poll_freq = status_poll_freq
- self._generation_poll_freq = generation_poll_freq
-
- # this defines whether this is a publisher or a subscriber
- if status_poll_freq > 0:
- self._inverter = inverterd.Client()
- self._inverter.connect()
- self._inverter.format(inverterd.Format.SIMPLE_JSON)
- self._database = None
- else:
- self._inverter = None
- self._database = InverterDatabase()
-
- self._gen_prev = 0
-
- def on_connect(self, mqtt: MqttNode):
- super().on_connect(mqtt)
- if not self._inverter:
- mqtt.subscribe_module(STATUS_TOPIC, self)
- mqtt.subscribe_module(GENERATION_TOPIC, self)
-
- def tick(self):
- if not self._inverter:
- return
-
- # read status
- now = time.time()
- try:
- raw = self._inverter.exec('get-status')
- except inverterd.InverterError as e:
- self._logger.error(f'inverter error: {str(e)}')
- # TODO send to server
- return
-
- data = json.loads(raw)['data']
- status = MqttInverterStatusPayload(time=round(now), **data)
- self._mqtt_node_ref.publish(STATUS_TOPIC, status.pack())
-
- # read today's generation stat
- now = time.time()
- if self._gen_prev == 0 or now - self._gen_prev >= self._generation_poll_freq:
- self._gen_prev = now
- today = datetime.date.today()
- try:
- raw = self._inverter.exec('get-day-generated', (today.year, today.month, today.day))
- except inverterd.InverterError as e:
- self._logger.error(f'inverter error: {str(e)}')
- # TODO send to server
- return
-
- data = json.loads(raw)['data']
- gen = MqttInverterGenerationPayload(time=round(now), wh=data['wh'])
- self._mqtt_node_ref.publish(GENERATION_TOPIC, gen.pack())
-
- def handle_payload(self, mqtt: MqttNode, topic: str, payload: bytes) -> Optional[MqttPayload]:
- home_id = 1 # legacy compat
-
- if topic == STATUS_TOPIC:
- s = MqttInverterStatusPayload.unpack(payload)
- self._database.add_status(home_id=home_id,
- client_time=s.time,
- grid_voltage=int(s.grid_voltage*10),
- grid_freq=int(s.grid_freq * 10),
- ac_output_voltage=int(s.ac_output_voltage * 10),
- ac_output_freq=int(s.ac_output_freq * 10),
- ac_output_apparent_power=s.ac_output_apparent_power,
- ac_output_active_power=s.ac_output_active_power,
- output_load_percent=s.output_load_percent,
- battery_voltage=int(s.battery_voltage * 10),
- battery_voltage_scc=int(s.battery_voltage_scc * 10),
- battery_voltage_scc2=int(s.battery_voltage_scc2 * 10),
- battery_discharge_current=s.battery_discharge_current,
- battery_charge_current=s.battery_charge_current,
- battery_capacity=s.battery_capacity,
- inverter_heat_sink_temp=s.inverter_heat_sink_temp,
- mppt1_charger_temp=s.mppt1_charger_temp,
- mppt2_charger_temp=s.mppt2_charger_temp,
- pv1_input_power=s.pv1_input_power,
- pv2_input_power=s.pv2_input_power,
- pv1_input_voltage=int(s.pv1_input_voltage * 10),
- pv2_input_voltage=int(s.pv2_input_voltage * 10),
- mppt1_charger_status=s.mppt1_charger_status,
- mppt2_charger_status=s.mppt2_charger_status,
- battery_power_direction=s.battery_power_direction,
- dc_ac_power_direction=s.dc_ac_power_direction,
- line_power_direction=s.line_power_direction,
- load_connected=s.load_connected)
- return s
-
- elif topic == GENERATION_TOPIC:
- gen = MqttInverterGenerationPayload.unpack(payload)
- self._database.add_generation(home_id, gen.time, gen.wh)
- return gen