Ejemplo n.º 1
0
    def test_scan_batching_bad_value(self):
        with patch(
                'modbus4mqtt.modbus_interface.ModbusTcpClient') as mock_modbus:
            with self.assertLogs() as mock_logger:
                mock_modbus().connect.side_effect = self.connect_success
                mock_modbus(
                ).read_input_registers.side_effect = self.read_input_registers
                mock_modbus(
                ).read_holding_registers.side_effect = self.read_holding_registers

                bad_scan_batching = modbus_interface.MAX_SCAN_BATCHING + 1
                modbus_interface.modbus_interface(
                    '1.1.1.1', 111, 2, scan_batching=bad_scan_batching)
                self.assertIn(
                    "Bad value for scan_batching: {}. Enforcing maximum value of {}"
                    .format(bad_scan_batching,
                            modbus_interface.MAX_SCAN_BATCHING),
                    mock_logger.output[-1])

                bad_scan_batching = modbus_interface.MIN_SCAN_BATCHING - 1
                modbus_interface.modbus_interface(
                    '1.1.1.1', 111, 2, scan_batching=bad_scan_batching)
                self.assertIn(
                    "Bad value for scan_batching: {}. Enforcing minimum value of {}"
                    .format(bad_scan_batching,
                            modbus_interface.MIN_SCAN_BATCHING),
                    mock_logger.output[-1])
Ejemplo n.º 2
0
    def test_masked_writes(self):
        with patch(
                'modbus4mqtt.modbus_interface.ModbusTcpClient') as mock_modbus:
            mock_modbus().connect.side_effect = self.connect_success
            mock_modbus(
            ).read_input_registers.side_effect = self.read_input_registers
            mock_modbus(
            ).read_holding_registers.side_effect = self.read_holding_registers
            mock_modbus(
            ).write_register.side_effect = self.write_holding_register

            m = modbus_interface.modbus_interface('1.1.1.1', 111, 2)
            m.connect()

            self.holding_registers.registers[1] = 0
            m.add_monitor_register('holding', 1)

            m.set_value('holding', 1, 0x00FF, 0x00F0)
            self.assertEqual(self.holding_registers.registers[1], 0x00F0)

            m.set_value('holding', 1, 0x00FF, 0x000F)
            self.assertEqual(self.holding_registers.registers[1], 0x00FF)

            m.set_value('holding', 1, 0xFFFF, 0xFF00)
            self.assertEqual(self.holding_registers.registers[1], 0xFFFF)

            m.set_value('holding', 1, 0x0000, 0x0F00)
            self.assertEqual(self.holding_registers.registers[1], 0xF0FF)
Ejemplo n.º 3
0
    def test_multi_byte_write_counts_LowHigh_order(self):
        with patch(
                'modbus4mqtt.modbus_interface.ModbusTcpClient') as mock_modbus:
            mock_modbus().connect.side_effect = self.connect_success

            m = modbus_interface.modbus_interface(
                '1.1.1.1',
                111,
                2,
                word_order=modbus_interface.WordOrder.LowHigh)
            m.connect()
            mock_modbus.assert_called_with(
                '1.1.1.1',
                111,
                RetryOnEmpty=True,
                framer=modbus_interface.ModbusSocketFramer,
                retries=1,
                timeout=1)

            for i in range(1, 11):
                m.add_monitor_register('holding', i)
            m.set_value('holding', 1, 689876135, 0xFFFF, 'uint32')
            m.poll()

            mock_modbus().write_register.assert_any_call(1,
                                                         int.from_bytes(
                                                             b'\xAC\xA7',
                                                             'big'),
                                                         unit=1)
            mock_modbus().write_register.assert_any_call(2,
                                                         int.from_bytes(
                                                             b'\x29\x1E',
                                                             'big'),
                                                         unit=1)
            mock_modbus().reset_mock()

            m.set_value('holding', 1, 5464681683516384647, 0xFFFF, 'uint64')
            m.poll()

            mock_modbus().write_register.assert_any_call(1,
                                                         int.from_bytes(
                                                             b'\xE5\x87',
                                                             'big'),
                                                         unit=1)
            mock_modbus().write_register.assert_any_call(2,
                                                         int.from_bytes(
                                                             b'\xBC\x93',
                                                             'big'),
                                                         unit=1)
            mock_modbus().write_register.assert_any_call(3,
                                                         int.from_bytes(
                                                             b'\x73\x09',
                                                             'big'),
                                                         unit=1)
            mock_modbus().write_register.assert_any_call(4,
                                                         int.from_bytes(
                                                             b'\x4B\xD6',
                                                             'big'),
                                                         unit=1)
            mock_modbus().reset_mock()
Ejemplo n.º 4
0
    def test_invalid_tables_and_addresses(self):
        with patch(
                'modbus4mqtt.modbus_interface.ModbusTcpClient') as mock_modbus:
            mock_modbus().connect.side_effect = self.connect_success
            m = modbus_interface.modbus_interface('1.1.1.1', 111, 2)
            m.connect()

            m.add_monitor_register('holding', 5)
            m.add_monitor_register('input', 6)
            self.assertRaises(ValueError, m.get_value, 'beupe', 5)
            self.assertRaises(ValueError, m.add_monitor_register, 'beupe', 5)
            self.assertRaises(ValueError, m.get_value, 'holding', 1000)
Ejemplo n.º 5
0
    def test_multi_byte_read_write_values_LowHigh(self):
        with patch(
                'modbus4mqtt.modbus_interface.ModbusTcpClient') as mock_modbus:
            mock_modbus().connect.side_effect = self.connect_success
            mock_modbus(
            ).read_holding_registers.side_effect = self.read_holding_registers
            mock_modbus(
            ).write_register.side_effect = self.write_holding_register

            m = modbus_interface.modbus_interface(
                '1.1.1.1',
                111,
                2,
                scan_batching=1,
                word_order=modbus_interface.WordOrder.LowHigh)
            m.connect()
            mock_modbus.assert_called_with(
                '1.1.1.1',
                111,
                RetryOnEmpty=True,
                framer=modbus_interface.ModbusSocketFramer,
                retries=1,
                timeout=1)

            for i in range(1, 11):
                m.add_monitor_register('holding', i)

            m.poll()
            # Write a value in.
            m.set_value('holding', 1, 65535, 0xFFFF, 'uint16')
            m.poll()
            # Read the value out.
            self.assertEqual(m.get_value('holding', 1, 'uint16'), 65535)
            # Read the value out as a different type.
            self.assertEqual(m.get_value('holding', 1, 'int16'), -1)
            m.poll()

            m.set_value('holding', 1, 4294927687, 0xFFFF, 'uint32')
            m.poll()
            # Read the value out.
            self.assertEqual(m.get_value('holding', 1, 'uint32'), 4294927687)
            # Read the value out as a different type.
            self.assertEqual(m.get_value('holding', 1, 'int32'), -39609)

            m.set_value('holding', 1, 18446573203856197441, 0xFFFF, 'uint64')
            m.poll()
            # Read the value out.
            self.assertEqual(m.get_value('holding', 1, 'uint64'),
                             18446573203856197441)
            # Read the value out as a different type.
            self.assertEqual(m.get_value('holding', 1, 'int64'),
                             -170869853354175)
Ejemplo n.º 6
0
    def test_exception_on_write(self):
        with patch(
                'modbus4mqtt.modbus_interface.ModbusTcpClient') as mock_modbus:
            mock_modbus().connect.side_effect = self.connect_success
            with self.assertLogs() as mock_logger:
                m = modbus_interface.modbus_interface('1.1.1.1', 111, 2)
                m.connect()

                m.add_monitor_register('holding', 5)
                # Have the write_register throw an exception
                mock_modbus().write_register.side_effect = self.throw_exception
                m.set_value('holding', 5, 7)
                self.assertIn(
                    "ERROR:root:Failed to write to modbus device: Oh noooo!",
                    mock_logger.output[-1])
Ejemplo n.º 7
0
    def test_write_queuing(self):
        with patch(
                'modbus4mqtt.modbus_interface.ModbusTcpClient') as mock_modbus:
            mock_modbus().connect.side_effect = self.connect_success
            m = modbus_interface.modbus_interface('1.1.1.1', 111, 2)
            m.connect()

            m.add_monitor_register('holding', 5)
            m.add_monitor_register('input', 6)

            # Check that the write queuing works properly.
            mock_modbus().write_register.reset_mock()
            m._writing = True
            m.set_value('holding', 5, 7)
            m.poll()
            mock_modbus().write_register.assert_not_called()
            m._writing = False
            m.set_value('holding', 6, 8)
            mock_modbus().write_register.assert_any_call(5, 7, unit=1)
            mock_modbus().write_register.assert_any_call(6, 8, unit=1)
Ejemplo n.º 8
0
    def test_scan_batching_of_one(self):
        with patch(
                'modbus4mqtt.modbus_interface.ModbusTcpClient') as mock_modbus:
            mock_modbus().connect.side_effect = self.connect_success
            mock_modbus(
            ).read_input_registers.side_effect = self.read_input_registers
            mock_modbus(
            ).read_holding_registers.side_effect = self.read_holding_registers

            m = modbus_interface.modbus_interface('1.1.1.1',
                                                  111,
                                                  2,
                                                  scan_batching=1)
            m.connect()
            mock_modbus.assert_called_with(
                '1.1.1.1',
                111,
                RetryOnEmpty=True,
                framer=modbus_interface.ModbusSocketFramer,
                retries=1,
                timeout=1)

            # Confirm registers are added to the correct tables.
            m.add_monitor_register('holding', 5)
            m.add_monitor_register('holding', 6)
            m.add_monitor_register('input', 6)
            m.add_monitor_register('input', 7)

            m.poll()

            self.assertEqual(m.get_value('holding', 5), 5)
            self.assertEqual(m.get_value('holding', 6), 6)
            self.assertEqual(m.get_value('input', 6), 6)
            self.assertEqual(m.get_value('input', 7), 7)

            # Ensure each register is scanned with a separate read call.
            mock_modbus().read_holding_registers.assert_any_call(5, 1, unit=1)
            mock_modbus().read_holding_registers.assert_any_call(6, 1, unit=1)
            mock_modbus().read_input_registers.assert_any_call(6, 1, unit=1)
            mock_modbus().read_input_registers.assert_any_call(7, 1, unit=1)
Ejemplo n.º 9
0
    def test_connect(self):
        with patch(
                'modbus4mqtt.modbus_interface.ModbusTcpClient') as mock_modbus:
            mock_modbus().connect.side_effect = self.connect_success
            mock_modbus(
            ).read_input_registers.side_effect = self.read_input_registers
            mock_modbus(
            ).read_holding_registers.side_effect = self.read_holding_registers

            m = modbus_interface.modbus_interface('1.1.1.1', 111, 2)
            m.connect()
            mock_modbus.assert_called_with(
                '1.1.1.1',
                111,
                RetryOnEmpty=True,
                framer=modbus_interface.ModbusSocketFramer,
                retries=1,
                timeout=1)

            # Confirm registers are added to the correct tables.
            m.add_monitor_register('holding', 5)
            m.add_monitor_register('input', 6)
            self.assertIn(5, m._tables['holding'])
            self.assertNotIn(5, m._tables['input'])
            self.assertIn(6, m._tables['input'])
            self.assertNotIn(6, m._tables['holding'])

            m.poll()

            self.assertEqual(m.get_value('holding', 5), 5)
            self.assertEqual(m.get_value('input', 6), 6)

            # Ensure we read a batch of DEFAULT_SCAN_BATCHING registers even though we only
            # added one register in each table as interesting
            mock_modbus().read_holding_registers.assert_any_call(0, 10, unit=1)
            mock_modbus().read_input_registers.assert_any_call(0, 10, unit=1)

            m.set_value('holding', 5, 7)
            m.poll()
            mock_modbus().write_register.assert_any_call(5, 7, unit=1)

            self.assertRaises(ValueError, m.set_value, 'input', 5, 7)

            mock_modbus().read_holding_registers.reset_mock()
            mock_modbus().read_input_registers.reset_mock()

            # Ensure this causes two batched reads per table, one from 0-9 and one from 10-19.
            m.add_monitor_register('holding', 15)
            m.add_monitor_register('input', 16)

            self.assertIn(15, m._tables['holding'])
            self.assertIn(16, m._tables['input'])

            m.poll()

            mock_modbus().read_holding_registers.assert_any_call(0, 10, unit=1)
            mock_modbus().read_holding_registers.assert_any_call(10,
                                                                 10,
                                                                 unit=1)
            mock_modbus().read_input_registers.assert_any_call(0, 10, unit=1)
            mock_modbus().read_input_registers.assert_any_call(10, 10, unit=1)