Esempio n. 1
0
 def testPayloadDecoderReset(self):
     """ Test the payload decoder reset functionality """
     decoder = BinaryPayloadDecoder(b'\x12\x34')
     self.assertEqual(0x12, decoder.decode_8bit_uint())
     self.assertEqual(0x34, decoder.decode_8bit_uint())
     decoder.reset()   
     self.assertEqual(0x3412, decoder.decode_16bit_uint())
Esempio n. 2
0
def bytes_to_status(bytes_, status_type):
    """Convert bytes to trip and digital input statuses

    """
    # The 4 bits for a state is contained i 4 bytes, gather them up into one list
    all_states = []
    for byte_ in bytes_:
        pay = BinaryPayloadDecoder(byte_)
        bits_ = pay.decode_bits()  # 8 booleans
        all_states.extend([bits_[:4], bits_[4:]])

    # The 3 bit indicates whether status is used, sort out the rest
    all_states = [state for state in all_states if state[3]]

    states = {}
    for state_num, state_bits in enumerate(all_states,
                                           start=1):  # Enumeration starts at 1
        # The first 3 bits has 3 different meanings: on, inhibit and override
        # First make sure only one is set
        if sum(state_bits[:3]) > 1:
            raise ValueError('Bad state: {}'.format(state_bits))

        # Then translate, if none is set, default to off
        for bit_num, bit_meaning in enumerate(['on', 'inhibit', 'override']):
            if state_bits[bit_num]:
                states[status_type + str(state_num)] = bit_meaning
                break
        else:
            states[status_type + str(state_num)] = 'off'

    return states
Esempio n. 3
0
    def fromCoils(coils, endian=Endian.Little):
        """ Initialize a payload decoder with the result of
        reading a collection of coils from a modbus device.

        The coils are treated as a list of bit(boolean) values.

        :param coils: The coil results to initialize with
        :param endian: The endianess of the payload
        :returns: An initialized PayloadDecoder
        """
        if isinstance(coils, list):
            payload = pack_bitstring(coils)
            return BinaryPayloadDecoder(payload, endian)
        raise ParameterException('Invalid collection of coils supplied')
Esempio n. 4
0
 def testBigEndianPayloadDecoder(self):
     ''' Test basic bit message encoding/decoding '''
     decoder = BinaryPayloadDecoder(self.big_endian_payload, endian=Endian.Big)
     self.assertEqual(1,      decoder.decode_8bit_uint())
     self.assertEqual(2,      decoder.decode_16bit_uint())
     self.assertEqual(3,      decoder.decode_32bit_uint())
     self.assertEqual(4,      decoder.decode_64bit_uint())
     self.assertEqual(-1,     decoder.decode_8bit_int())
     self.assertEqual(-2,     decoder.decode_16bit_int())
     self.assertEqual(-3,     decoder.decode_32bit_int())
     self.assertEqual(-4,     decoder.decode_64bit_int())
     self.assertEqual(1.25,   decoder.decode_32bit_float())
     self.assertEqual(6.25,   decoder.decode_64bit_float())
     self.assertEqual(b'test', decoder.decode_string(4))
     self.assertEqual(self.bitstring, decoder.decode_bits())
Esempio n. 5
0
    def fromRegisters(registers, endian=Endian.Little):
        """ Initialize a payload decoder with the result of
        reading a collection of registers from a modbus device.

        The registers are treated as a list of 2 byte values.
        We have to do this because of how the data has already
        been decoded by the rest of the library.

        :param registers: The register results to initialize with
        :param endian: The endianess of the payload
        :returns: An initialized PayloadDecoder
        """
        if isinstance(registers, list):  # repack into flat binary
            payload = ''.join(pack('>H', x) for x in registers)
            return BinaryPayloadDecoder(payload, endian)
        raise ParameterException('Invalid collection of registers supplied')
Esempio n. 6
0
 def testLittleEndianPayloadDecoder(self):
     ''' Test basic bit message encoding/decoding '''
     decoder = BinaryPayloadDecoder(self.little_endian_payload,
                                    endian=Endian.Little)
     self.assertEqual(1, decoder.decode_8bit_uint())
     self.assertEqual(2, decoder.decode_16bit_uint())
     self.assertEqual(3, decoder.decode_32bit_uint())
     self.assertEqual(4, decoder.decode_64bit_uint())
     self.assertEqual(-1, decoder.decode_8bit_int())
     self.assertEqual(-2, decoder.decode_16bit_int())
     self.assertEqual(-3, decoder.decode_32bit_int())
     self.assertEqual(-4, decoder.decode_64bit_int())
     self.assertEqual(1.25, decoder.decode_32bit_float())
     self.assertEqual(6.25, decoder.decode_64bit_float())
     self.assertEqual(None, decoder.skip_bytes(2))
     self.assertEqual('test', decoder.decode_string(4).decode())
     self.assertEqual(self.bitstring, decoder.decode_bits())
    def decode(self, raw, size, mb_type, mb_funcall=3):
        log.debug('decode param (raw=%s, size=%s, mb_type=%s, mb_funcall=%s)' %
                  (raw, size, mb_type, mb_funcall))
        if mb_funcall == 1:
            # Read Coil Status (FC=01)
            log.debug("decoder FC1 (raw: %s)" % raw)
            decoder = BinaryPayloadDecoder.fromCoils(raw, endian=self.endian)
        elif mb_funcall == 2:
            # Read Discrete Input (FC=02)
            log.debug("decoder FC2 (raw: %s)" % raw)
            decoder = BinaryPayloadDecoder(raw, endian=self.endian)
        elif mb_funcall == 3:
            # Read Holding Registers (FC=03)
            log.debug("decoder FC3 (raw: %s)" % raw)
            decoder = BinaryPayloadDecoder.fromRegisters(raw,
                                                         endian=self.endian)
        elif mb_funcall == 4:
            # Read Input Registers (FC=04)
            log.debug("decoder stub FC4 (raw: %s)" % raw)
            decoder = BinaryPayloadDecoder(raw, endian=self.endian)
        else:
            log.debug("Function call not supported: %s" % mb_funcall)
            decoder = None

        result = ""
        if mb_type == 'bitmap':
            if size == 1:
                mb_type = 'int8'
            elif size == 2:
                mb_type = 'int16'
            elif size == 2:
                mb_type = 'int32'
            elif size == 4:
                mb_type = 'int64'

        if decoder is None:
            log.debug("decode none")
            result = raw
        else:
            try:
                if mb_type == 'string' or mb_type == 'utf8':
                    result = decoder.decode_string(size)
                #elif mb_type == 'bitmap':
                #	result = decoder.decode_string(size)
                elif mb_type == 'datetime':
                    result = decoder.decode_string(size)
                elif mb_type == 'uint8':
                    result = int(decoder.decode_8bit_uint())
                elif mb_type == 'int8':
                    result = int(decoder.decode_8bit_int())
                elif mb_type == 'uint16':
                    result = int(decoder.decode_16bit_uint())
                elif mb_type == 'int16':
                    result = int(decoder.decode_16bit_int())
                elif mb_type == 'uint32':
                    result = int(decoder.decode_32bit_uint())
                elif mb_type == 'int32':
                    result = int(decoder.decode_32bit_int())
                elif mb_type == 'uint64':
                    result = int(decoder.decode_64bit_uint())
                elif mb_type == 'int64':
                    result = int(decoder.decode_64bit_int())
                elif mb_type == 'float32' or mb_type == 'float':
                    result = float(decoder.decode_32bit_float())
                elif mb_type == 'float64':
                    result = float(decoder.decode_64bit_float())
                elif mb_type == 'bit':
                    result = int(decoder.decode_bits())
                elif mb_type == 'bool':
                    result = bool(raw[0])
                elif mb_type == 'raw':
                    result = raw[0]
                else:
                    result = raw
            except ValueError as e:
                log.exception(e)
                result = raw
        return result
Esempio n. 8
0
    def start(self, host, port, update_period):
        self.modbus_client = ModbusClient(host, port=port)
        self.iterate_blocks()
        while not self.closed:
            try:
                if not self.connected:
                    self.connect()
                for method, starting_address, size, slave_id, points in self.executions:
                    result = method(starting_address, size, unit=slave_id)
                    if result:
                        for point in points:
                            value = None
                            if isinstance(
                                    result, ReadCoilsResponse) or isinstance(
                                        result, ReadDiscreteInputsResponse):
                                value = result.bits[point.address -
                                                    starting_address]
                            elif isinstance(result,
                                            ReadHoldingRegistersResponse):
                                start = point.address - starting_address
                                value = result.registers[start:start +
                                                         point.count]
                                if not point.encoding == 'none' and not point.encoding == 'custom':
                                    endian = Endian.Auto
                                    if point.endian == 'Little':
                                        endian = Endian.Little
                                    elif point.endian == 'Big':
                                        endian = Endian.Big
                                    payload = ''.join(
                                        pack(endian + 'H', x) for x in value)
                                    decoder = BinaryPayloadDecoder(
                                        payload, endian)
                                    encoding_map = {
                                        'bits': decoder.decode_bits,
                                        '8unit': decoder.decode_8bit_uint,
                                        '16unit': decoder.decode_16bit_uint,
                                        '32unit': decoder.decode_32bit_uint,
                                        '64unit': decoder.decode_64bit_uint,
                                        '8int': decoder.decode_8bit_int,
                                        '16int': decoder.decode_16bit_int,
                                        '32int': decoder.decode_32bit_int,
                                        '64int': decoder.decode_64bit_int,
                                        '32float': decoder.decode_32bit_float,
                                        '64float': decoder.decode_64bit_float,
                                        'string': decoder.decode_string
                                    }
                                    value = encoding_map[point.encoding]()
                                elif point.encoding == 'custom' and point.custom_decoder:
                                    decode = eval("lambda value: " +
                                                  point.custom_decoder)
                                    value = decode(value)

                            if point.condition:
                                if point.condition[0] == '=':
                                    if str(value) == point.condition[1:]:
                                        conpot_core.get_databus().set_value(
                                            'r ' + point.point_id,
                                            point.get_read_value(value),
                                            index=point.index)
                                elif point.condition[0] == '!':
                                    if not str(value) == point.condition[1:]:
                                        conpot_core.get_databus().set_value(
                                            'r ' + point.point_id,
                                            point.get_read_value(value),
                                            index=point.index)
                                elif point.condition[0] == '>':
                                    if str(value) > point.condition[1:]:
                                        conpot_core.get_databus().set_value(
                                            'r ' + point.point_id,
                                            point.get_read_value(value),
                                            index=point.index)
                                elif point.condition[0] == '<':
                                    if str(value) < point.condition[1:]:
                                        conpot_core.get_databus().set_value(
                                            'r ' + point.point_id,
                                            point.get_read_value(value),
                                            index=point.index)
                            else:
                                conpot_core.get_databus().set_value(
                                    'r ' + point.point_id,
                                    point.get_read_value(value),
                                    index=point.index)
            except ConnectionException, e:
                logger.error('Error because: %s' % e)
                self.connected = False
            time.sleep(update_period)
Esempio n. 9
0
def byte_to_bits(byte):
    """Convert a byte to a list of bits"""
    return list(reversed(BinaryPayloadDecoder(byte).decode_bits()))
Esempio n. 10
0
 def read_remaining_time(self):
     res = self.client.read_holding_registers(address=128, count=2) 
     decoder = BinaryPayloadDecoder(res.registers, byteorder=Endian.Little, wordorder=Ending.Little)
     time = decoder.decode_32bit_int # value in minutes
     return time