def __init__(self): self.power = Power() self.L1 = Phase() self.L2 = Phase() self.L3 = Phase() self.tariff_1 = Tariff() self.tariff_2 = Tariff() self.frequency = float('nan')
def read_energy(self): values = self._from_double(self.read_input_register(801, 40)) self.tariff_1 = Tariff( Energy(values[8], values[0], values[4]), Energy(values[8], values[2], values[6]) ) self.tariff_2 = Tariff( Energy(values[9], values[1], values[5]), Energy(values[9], values[3], values[7]) )
def test_add(): e1 = Energy(1, 1, 1) e2 = Energy(1, 1, 1) t1 = Tariff(e1, e2) t2 = Tariff(e1, e2) t_total = t1 + t2 assert t_total.energy_import.apparent == t1.energy_import.apparent + t2.energy_import.apparent assert t_total.energy_import.active == t1.energy_import.active + t2.energy_import.active assert t_total.energy_import.reactive == t1.energy_import.reactive + t2.energy_import.reactive assert t_total.energy_export.apparent == t1.energy_export.apparent + t2.energy_export.apparent assert t_total.energy_export.active == t1.energy_export.active + t2.energy_export.active assert t_total.energy_export.reactive == t1.energy_export.reactive + t2.energy_export.reactive
def test_balance(): e1 = Energy(1000, 1000, 1000) e2 = Energy(1000, 1000, 1000) balance = Tariff(e1, e2).balance assert isinstance(balance, Energy) assert balance.apparent == 0 assert balance.active == 0 assert balance.reactive == 0
def test_div(): e1 = Energy(1000, 1000, 1000) e2 = Energy(1000, 1000, 1000) p_import, p_export = Tariff(e1, e2) / 7200 assert isinstance(p_import, Power) assert isinstance(p_export, Power) assert p_import.apparent == 1000 / 2 assert p_export.apparent == 1000 / 2 assert p_import.active == e1.active / 2 assert p_export.active == e1.active / 2 assert p_import.reactive == e1.reactive / 2 assert p_export.reactive == e1.reactive / 2 p_import, p_export = Tariff(e1, e2) / timedelta(minutes=30) assert isinstance(p_import, Power) assert isinstance(p_export, Power) assert p_import.apparent == 1000 * 2 assert p_export.apparent == 1000 * 2 assert p_import.active == e1.active * 2 assert p_export.active == e1.active * 2 assert p_import.reactive == e1.reactive * 2 assert p_export.reactive == e1.reactive * 2
class PAC(object): _master = None _unit = None def __init__(self): self.power = Power() self.L1 = Phase() self.L2 = Phase() self.L3 = Phase() self.tariff_1 = Tariff() self.tariff_2 = Tariff() self.frequency = float('nan') def _from_float(self, values): return [unpack(str('>f'), pack(str('>HH'), *values[i:i + 2]))[0] for i in range(0, len(values), 2)] def _from_double(self, values): return [unpack(str('>d'), pack(str('>HHHH'), *values[i:i + 4]))[0] for i in range(0, len(values), 4)] def read_input_register(self, register_start, count=1): if self._master is None or self._unit is None: raise ValueError('Connection uninitialized.') result = self._master.execute(self._unit, READ_INPUT_REGISTERS, register_start, count) if not result: raise IOError('Register read failed.') return result def read_power(self): self.power = Power(*self._from_float(self.read_input_register(63, 4))) def read_phases(self): values = self._from_float(self.read_input_register(1, 30)) # Note: PAC reports phase powers as NaN, if all phases aren't connected. # However, the total power read with PAC.read_power() is seems valid even then. self.L1 = Phase(values[0], values[6], values[9], values[12]) self.L2 = Phase(values[1], values[7], values[10], values[13]) self.L3 = Phase(values[2], values[8], values[11], values[14]) def read_frequency(self): self.frequency = self._from_float(self.read_input_register(55, 2))[0] def read_energy(self): values = self._from_double(self.read_input_register(801, 40)) self.tariff_1 = Tariff( Energy(values[8], values[0], values[4]), Energy(values[8], values[2], values[6]) ) self.tariff_2 = Tariff( Energy(values[9], values[1], values[5]), Energy(values[9], values[3], values[7]) ) def read(self): self.read_power() self.read_phases() self.read_frequency() self.read_energy() def clear_tariff(self, tariff): if self._master is None or self._unit is None: raise ValueError('Connection uninitialized.') if tariff == 1: start = 801 if tariff == 2: start = 805 registers = range(start, start + 5 * 8, 8) for x in registers: self._master.execute(self._unit, WRITE_MULTIPLE_REGISTERS, x, output_value=[0, 0, 0, 0]) # Read energy to update values... self.read_energy() def close(self): if self._master is None or self._unit is None: return self._master.close() @property def energy(self): return self.tariff_1 + self.tariff_2 @property def energy_balance(self): return self.tariff_1.energy_import + self.tariff_2.energy_import - self.tariff_1.energy_export - self.tariff_2.energy_export def as_dict(self, replace_nan=False): return { 'power': self.power.as_dict(replace_nan=replace_nan), 'phases': { 'L1': self.L1.as_dict(replace_nan=replace_nan), 'L2': self.L2.as_dict(replace_nan=replace_nan), 'L3': self.L3.as_dict(replace_nan=replace_nan), }, 'energy': self.energy.as_dict(replace_nan=replace_nan), 'balance': self.energy_balance.as_dict(replace_nan=replace_nan), 'tariffs': [ self.tariff_1.as_dict(replace_nan=replace_nan), self.tariff_2.as_dict(replace_nan=replace_nan), ], 'frequency': zero_if_nan(self.frequency, replace_nan), }