예제 #1
0
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
예제 #2
0
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
예제 #3
0
    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])
예제 #4
0
 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')
예제 #5
0
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),
        }
예제 #6
0
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)