def test_add(): L1 = Phase(230, 1, 2, 1) L2 = Phase(230, 1, 2, 1) L3 = Phase(230, 1, 2, 1) L_total = L1 + L2 + L3 assert isinstance(L_total, Phase) assert L_total.voltage == 230 assert L_total.current == 3 assert isinstance(L_total.power, Power) assert L_total.power.apparent == 3 * 2 assert L_total.power.active == 3
def test_sub(): L1 = Phase(230, 1, 2, 1) L2 = Phase(230, 1, 2, 1) L3 = Phase(230, 1, 2, 1) L_total = L1 - L2 - L3 assert isinstance(L_total, Phase) assert L_total.voltage == 230 assert L_total.current == -1 assert isinstance(L_total.power, Power) assert L_total.power.apparent == -2 assert L_total.power.active == -1
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 __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')
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), }
def test_power_calc(): L1 = Phase(230, 1) assert isinstance(L1.power, Power) assert L1.power.apparent == 230 assert isnan(L1.power.active) assert isnan(L1.power.reactive)