summaryrefslogtreecommitdiff
path: root/src/home/database/inverter.py
diff options
context:
space:
mode:
Diffstat (limited to 'src/home/database/inverter.py')
-rw-r--r--src/home/database/inverter.py212
1 files changed, 0 insertions, 212 deletions
diff --git a/src/home/database/inverter.py b/src/home/database/inverter.py
deleted file mode 100644
index fc3f74f..0000000
--- a/src/home/database/inverter.py
+++ /dev/null
@@ -1,212 +0,0 @@
-from time import time
-from datetime import datetime, timedelta
-from typing import Optional
-from collections import namedtuple
-
-from .clickhouse import ClickhouseDatabase
-
-
-IntervalList = list[list[Optional[datetime]]]
-
-
-class InverterDatabase(ClickhouseDatabase):
- def __init__(self):
- super().__init__('solarmon')
-
- def add_generation(self, home_id: int, client_time: int, watts: int) -> None:
- self.db.execute(
- 'INSERT INTO generation (ClientTime, ReceivedTime, HomeID, Watts) VALUES',
- [[client_time, round(time()), home_id, watts]]
- )
-
- def add_status(self, home_id: int,
- client_time: int,
- grid_voltage: int,
- grid_freq: int,
- ac_output_voltage: int,
- ac_output_freq: int,
- ac_output_apparent_power: int,
- ac_output_active_power: int,
- output_load_percent: int,
- battery_voltage: int,
- battery_voltage_scc: int,
- battery_voltage_scc2: int,
- 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: int,
- pv2_input_voltage: int,
- mppt1_charger_status: int,
- mppt2_charger_status: int,
- battery_power_direction: int,
- dc_ac_power_direction: int,
- line_power_direction: int,
- load_connected: int) -> None:
- self.db.execute("""INSERT INTO status (
- ClientTime,
- ReceivedTime,
- HomeID,
- GridVoltage,
- GridFrequency,
- ACOutputVoltage,
- ACOutputFrequency,
- ACOutputApparentPower,
- ACOutputActivePower,
- OutputLoadPercent,
- BatteryVoltage,
- BatteryVoltageSCC,
- BatteryVoltageSCC2,
- BatteryDischargingCurrent,
- BatteryChargingCurrent,
- BatteryCapacity,
- HeatSinkTemp,
- MPPT1ChargerTemp,
- MPPT2ChargerTemp,
- PV1InputPower,
- PV2InputPower,
- PV1InputVoltage,
- PV2InputVoltage,
- MPPT1ChargerStatus,
- MPPT2ChargerStatus,
- BatteryPowerDirection,
- DCACPowerDirection,
- LinePowerDirection,
- LoadConnected) VALUES""", [[
- client_time,
- round(time()),
- home_id,
- grid_voltage,
- grid_freq,
- ac_output_voltage,
- ac_output_freq,
- ac_output_apparent_power,
- ac_output_active_power,
- output_load_percent,
- battery_voltage,
- battery_voltage_scc,
- battery_voltage_scc2,
- battery_discharge_current,
- battery_charge_current,
- battery_capacity,
- inverter_heat_sink_temp,
- mppt1_charger_temp,
- mppt2_charger_temp,
- pv1_input_power,
- pv2_input_power,
- pv1_input_voltage,
- pv2_input_voltage,
- mppt1_charger_status,
- mppt2_charger_status,
- battery_power_direction,
- dc_ac_power_direction,
- line_power_direction,
- load_connected
- ]])
-
- def get_consumed_energy(self, dt_from: datetime, dt_to: datetime) -> float:
- rows = self.query('SELECT ClientTime, ACOutputActivePower FROM status'
- ' WHERE ClientTime >= %(from)s AND ClientTime <= %(to)s'
- ' ORDER BY ClientTime', {'from': dt_from, 'to': dt_to})
- prev_time = None
- prev_wh = 0
-
- ws = 0 # watt-seconds
- for t, wh in rows:
- if prev_time is not None:
- n = (t - prev_time).total_seconds()
- ws += prev_wh * n
-
- prev_time = t
- prev_wh = wh
-
- return ws / 3600 # convert to watt-hours
-
- def get_intervals_by_condition(self,
- dt_from: datetime,
- dt_to: datetime,
- cond_start: str,
- cond_end: str) -> IntervalList:
- rows = None
- ranges = [[None, None]]
-
- while rows is None or len(rows) > 0:
- if ranges[len(ranges)-1][0] is None:
- condition = cond_start
- range_idx = 0
- else:
- condition = cond_end
- range_idx = 1
-
- rows = self.query('SELECT ClientTime FROM status '
- f'WHERE ClientTime > %(from)s AND ClientTime <= %(to)s AND {condition}'
- ' ORDER BY ClientTime LIMIT 1',
- {'from': dt_from, 'to': dt_to})
- if not rows:
- break
-
- row = rows[0]
-
- ranges[len(ranges) - 1][range_idx] = row[0]
- if range_idx == 1:
- ranges.append([None, None])
-
- dt_from = row[0]
-
- if ranges[len(ranges)-1][0] is None:
- ranges.pop()
- elif ranges[len(ranges)-1][1] is None:
- ranges[len(ranges)-1][1] = dt_to - timedelta(seconds=1)
-
- return ranges
-
- def get_grid_connected_intervals(self, dt_from: datetime, dt_to: datetime) -> IntervalList:
- return self.get_intervals_by_condition(dt_from, dt_to, 'GridFrequency > 0', 'GridFrequency = 0')
-
- def get_grid_used_intervals(self, dt_from: datetime, dt_to: datetime) -> IntervalList:
- return self.get_intervals_by_condition(dt_from,
- dt_to,
- "LinePowerDirection = 'Input'",
- "LinePowerDirection != 'Input'")
-
- def get_grid_consumed_energy(self, dt_from: datetime, dt_to: datetime) -> float:
- PrevData = namedtuple('PrevData', 'time, pd, bat_chg, bat_dis, wh')
-
- ws = 0 # watt-seconds
- amps = 0 # amper-seconds
-
- intervals = self.get_grid_used_intervals(dt_from, dt_to)
- for dt_start, dt_end in intervals:
- fields = ', '.join([
- 'ClientTime',
- 'DCACPowerDirection',
- 'BatteryChargingCurrent',
- 'BatteryDischargingCurrent',
- 'ACOutputActivePower'
- ])
- rows = self.query(f'SELECT {fields} FROM status'
- ' WHERE ClientTime >= %(from)s AND ClientTime < %(to)s ORDER BY ClientTime',
- {'from': dt_start, 'to': dt_end})
-
- prev = PrevData(time=None, pd=None, bat_chg=None, bat_dis=None, wh=None)
- for ct, pd, bat_chg, bat_dis, wh in rows:
- if prev.time is not None:
- n = (ct-prev.time).total_seconds()
- ws += prev.wh * n
-
- if pd == 'DC/AC':
- amps -= prev.bat_dis * n
- elif pd == 'AC/DC':
- amps += prev.bat_chg * n
-
- prev = PrevData(time=ct, pd=pd, bat_chg=bat_chg, bat_dis=bat_dis, wh=wh)
-
- amps /= 3600
- wh = ws / 3600
- wh += amps*48
-
- return wh