예제 #1
0
 def __new__(cls, addr, *args, **kwargs):
     """ Overridden __new__ for setting the size. """
     return ModbusRegister.__new__(cls, addr, size=3, *args, **kwargs)
예제 #2
0
 def __new__(cls, addr, *args, **kwargs):
     """ Overridden __new__ for setting the signed option. """
     return ModbusRegister.__new__(cls, addr, signed=True, *args, **kwargs)
예제 #3
0
 def __new__(cls, addr, *args, **kwargs):
     """ Overridden __new__ for fixing the register size and
     forcing unsigned values since 2's complement is used here.
     """
     return ModbusRegister.__new__(cls, addr, size=2, signed=False, *args, **kwargs)
예제 #4
0
 def __new__(cls, addr, *args, **kwargs):
     """ Overridden __new__ for fixing the register size. """
     return ModbusRegister.__new__(cls, addr, *args, **kwargs)
예제 #5
0
class DigiRail_2A(RTUModbusHWDevice):
    """ DigiRail-2A A/D converter HW device

    The supported model is the RTU RS485 one, the RS485 bus being connected
    via a USB.RS485 interface.
    """

    DEFAULT_BAUDRATE = 19200

    # registers
    # - configuration
    REG_MODBUS_ADDR = ModbusRegister(3)
    REG_INPUT_TYPE_1 = ModbusRegister(21)
    REG_INPUT_TYPE_2 = ModbusRegister(22)
    REG_MEAS_UNIT_1 = ModbusRegister(26)
    REG_MEAS_UNIT_2 = ModbusRegister(27)

    # - data
    REG_PV_ENG_1 = ModbusRegister(14)
    REG_PV_ENG_2 = ModbusRegister(15)

    #: the compiled sequence of collected registers
    COLLECTED_REGS = [REG_PV_ENG_1, REG_PV_ENG_2]

    _TOTAL_INPUT_SIZE = reduce(lambda accum, size: accum + size,
                               [r.size for r in COLLECTED_REGS])

    # Definition of the type of the poll() method result

    # VERY IMPORTANT :
    # The name of its items MUST match the name of the outputs described
    # in the metadata stored in devcfg.d directory, since the notification
    # events generation process is based on this.
    # (see pycstbox.hyal.device.PolledDevice.poll() method for details)
    OutputValues = namedtuple(
        'OutputValues',
        [
            'in1',  # input 1
            'in2',  # input 2
        ])

    def __init__(self, port, unit_id):
        """
        :param str port: serial port on which the RS485 interface is connected
        :param int unit_id: the address of the device
        """
        super(DigiRail_2A, self).__init__(port=port,
                                          unit_id=int(unit_id),
                                          logname='dr2a')

        self._logger.info('reading inputs configuration from device...')
        input_types = self.unpack_registers(
            start_register=self.REG_INPUT_TYPE_1,
            reg_count=2,
            unpack_format='>hh')
        input_units = self.unpack_registers(
            start_register=self.REG_MEAS_UNIT_1,
            reg_count=2,
            unpack_format='>hh')

        self._logger.info('creating corresponding model instances...')
        self.inputs = [
            DRInput(input_type, input_unit)
            for input_type, input_unit in zip(input_types, input_units)
        ]
        for n, input in enumerate(self.inputs):
            self._logger.info('... [%d] %s', n + 1, input)

    @property
    def unit_id(self):
        """ The id of the device """
        return self.address

    def poll(self):
        """ Reads the registers data and returns the
        values as a named tuple.

        """
        # since the input registers are contiguous, optimise the operation by reading them in a single request
        return self.OutputValues(**dict(
            zip(self.OutputValues._fields, [
                inp.physical_value(rv) for inp, rv in zip(
                    self.inputs,
                    self.unpack_registers(
                        self.REG_PV_ENG_1, reg_count=2, unpack_format=">hh"))
            ])))

    def input_unit(self, channel_num):
        try:
            return self.inputs[channel_num - 1].unit
        except KeyError:
            raise ValueError('invalid channel number (%s)' % channel_num)

    def is_enabled(self, channel_num):
        try:
            return self.inputs[channel_num - 1].enabled
        except KeyError:
            raise ValueError('invalid channel number (%s)' % channel_num)