Browse Source

[variables][db] fixed variable addresses and modbus functions

Maxime Alves LIRMM@home 4 years ago
parent
commit
0aa2af892a
6 changed files with 98 additions and 45 deletions
  1. 3
    3
      db/pyheatpump.sql
  2. 3
    3
      poetry.lock
  3. 46
    25
      pyheatpump/modbus.py
  4. 1
    1
      pyproject.toml
  5. 1
    1
      pytest.ini
  6. 44
    12
      tests/test_modbus.py

+ 3
- 3
db/pyheatpump.sql View File

32
 );
32
 );
33
 
33
 
34
 INSERT INTO var_type (slabel, label, type, start_address, end_address) VALUES (
34
 INSERT INTO var_type (slabel, label, type, start_address, end_address) VALUES (
35
-	'A', 'Analog', 'float', 1, (1 + 500));
35
+	'A', 'Analog', 'float', 1, 5000);
36
 INSERT INTO var_type (slabel, label, type, start_address, end_address) VALUES (
36
 INSERT INTO var_type (slabel, label, type, start_address, end_address) VALUES (
37
-	'I', 'Integer', 'int', 5002, (5002 + 500));
37
+	'I', 'Integer', 'int', 5002, 10002);
38
 INSERT INTO var_type (slabel, label, type, start_address, end_address) VALUES (
38
 INSERT INTO var_type (slabel, label, type, start_address, end_address) VALUES (
39
-	'D', 'Digital', 'boolean', 1, (1 + 1000));
39
+	'D', 'Digital', 'bool', 1, 2048);
40
 
40
 
41
 CREATE TRIGGER variable_insert BEFORE INSERT ON var_value
41
 CREATE TRIGGER variable_insert BEFORE INSERT ON var_value
42
 FOR EACH ROW
42
 FOR EACH ROW

+ 3
- 3
poetry.lock View File

273
 name = "uvicorn"
273
 name = "uvicorn"
274
 optional = false
274
 optional = false
275
 python-versions = "*"
275
 python-versions = "*"
276
-version = "0.11.6"
276
+version = "0.11.8"
277
 
277
 
278
 [package.dependencies]
278
 [package.dependencies]
279
 click = ">=7.0.0,<8.0.0"
279
 click = ">=7.0.0,<8.0.0"
436
     {file = "urllib3-1.25.10.tar.gz", hash = "sha256:91056c15fa70756691db97756772bb1eb9678fa585d9184f24534b100dc60f4a"},
436
     {file = "urllib3-1.25.10.tar.gz", hash = "sha256:91056c15fa70756691db97756772bb1eb9678fa585d9184f24534b100dc60f4a"},
437
 ]
437
 ]
438
 uvicorn = [
438
 uvicorn = [
439
-    {file = "uvicorn-0.11.6-py3-none-any.whl", hash = "sha256:d19a20b17445708fd222e5a7cfc3eacfb31ac269bc8fefa4920833334e199782"},
440
-    {file = "uvicorn-0.11.6.tar.gz", hash = "sha256:467c333c743ec6a3eb545517a0e3cac603becfa40c73c65ed46c3a4bf1c8e2d0"},
439
+    {file = "uvicorn-0.11.8-py3-none-any.whl", hash = "sha256:4b70ddb4c1946e39db9f3082d53e323dfd50634b95fd83625d778729ef1730ef"},
440
+    {file = "uvicorn-0.11.8.tar.gz", hash = "sha256:46a83e371f37ea7ff29577d00015f02c942410288fb57def6440f2653fff1d26"},
441
 ]
441
 ]
442
 uvloop = [
442
 uvloop = [
443
     {file = "uvloop-0.14.0-cp35-cp35m-macosx_10_11_x86_64.whl", hash = "sha256:08b109f0213af392150e2fe6f81d33261bb5ce968a288eb698aad4f46eb711bd"},
443
     {file = "uvloop-0.14.0-cp35-cp35m-macosx_10_11_x86_64.whl", hash = "sha256:08b109f0213af392150e2fe6f81d33261bb5ce968a288eb698aad4f46eb711bd"},

+ 46
- 25
pyheatpump/modbus.py View File

2
 from serial import Serial
2
 from serial import Serial
3
 from serial.serialutil import SerialException
3
 from serial.serialutil import SerialException
4
 from umodbus.client.serial import rtu
4
 from umodbus.client.serial import rtu
5
+import umodbus
5
 from pprint import pprint
6
 from pprint import pprint
6
 
7
 
7
 from pyheatpump.conf import config
8
 from pyheatpump.conf import config
14
     if serial_conn is None:
15
     if serial_conn is None:
15
         print('Connecting to serial port *{}*'.format(
16
         print('Connecting to serial port *{}*'.format(
16
             config.get('heatpump', 'serial_port')))
17
             config.get('heatpump', 'serial_port')))
17
-        serial_conn = Serial(config.get('heatpump', 'serial_port'),
18
-            config.get('heatpump', 'baudrate'))
18
+        serial_conn = Serial(
19
+            port=config.get('heatpump', 'serial_port'),
20
+            baudrate=config.get('heatpump', 'baudrate'),
21
+            bytesize=8,
22
+            parity='N',
23
+            stopbits=1)
19
 
24
 
20
     if serial_conn.open is False:
25
     if serial_conn.open is False:
21
         print('Opening serial port')
26
         print('Opening serial port')
25
 
30
 
26
 def read_coils(start, end):
31
 def read_coils(start, end):
27
     global serial_con
32
     global serial_con
33
+    connect()
28
     res = []
34
     res = []
29
 
35
 
30
-    # digital - boolean
31
-    req_adu = rtu.read_coils(
32
-        slave_id=1,
33
-        starting_address=start,
34
-        quantity=end - start)
35
-
36
-    resp = rtu.send_message(req_adu, serial_conn)
37
-
36
+    try:
37
+        for address in range(start, end + 1, 125):
38
+            qty = 125 if (end - address) >= 125 else (end - address)
39
+            if not qty:
40
+                break
41
+            print(start, end, address, qty)
42
+            req_adu = rtu.read_coils(
43
+                slave_id=1,
44
+                starting_address=address,
45
+                quantity=qty)
46
+
47
+            resp = rtu.send_message(req_adu, serial_conn)
48
+            res.extend(resp)
49
+    except umodbus.exceptions.IllegalDataAddressError as e:
50
+        print(e)
38
     return res
51
     return res
39
 
52
 
40
 
53
 
54
+
41
 def read_holding_registers(start, end):
55
 def read_holding_registers(start, end):
42
     global serial_conn
56
     global serial_conn
57
+    connect()
43
     res = []
58
     res = []
44
 
59
 
45
-
46
-    for address in range(start, end + 1, 125):
47
-        qty = 125 if (end - address) >= 125 else (end - address)
48
-        if not qty:
49
-            break
50
-        print(start, end, address, qty)
51
-        req_adu = rtu.read_coils(
52
-            slave_id=1,
53
-            starting_address=address,
54
-            quantity=qty)
55
-
56
-        resp = rtu.send_message(req_adu, serial_conn)
57
-        res.extend(resp)
60
+    try:
61
+        for address in range(start, end + 1, 125):
62
+            qty = 125 if (end - address) >= 125 else (end - address)
63
+            if not qty:
64
+                break
65
+            print(start, end, address, qty)
66
+            req_adu = rtu.read_holding_registers(
67
+                slave_id=1,
68
+                starting_address=address,
69
+                quantity=qty)
70
+
71
+            resp = rtu.send_message(req_adu, serial_conn)
72
+            res.extend(resp)
73
+    except umodbus.exceptions.IllegalDataAddressError as e:
74
+        print(e)
58
     return res
75
     return res
59
 
76
 
60
 if __name__ == '__main__':
77
 if __name__ == '__main__':
61
-    connect()
62
-    read_holding_registers(1, 10)
78
+    resp = read_holding_registers(1, 5000)
79
+    #pprint(resp)
80
+    print(len(resp))
81
+    resp = read_coils(1, 2000)
82
+    #pprint(resp)
83
+    print(len(resp))

+ 1
- 1
pyproject.toml View File

8
 [tool.poetry.dependencies]
8
 [tool.poetry.dependencies]
9
 python = "^3.7"
9
 python = "^3.7"
10
 starlette = "^0.13.6"
10
 starlette = "^0.13.6"
11
-umodbus = "^1.0.3"
12
 uvicorn = "^0.11.6"
11
 uvicorn = "^0.11.6"
12
+umodbus = "^1.0.3"
13
 
13
 
14
 [tool.poetry.dev-dependencies]
14
 [tool.poetry.dev-dependencies]
15
 pytest = "^5.4.3"
15
 pytest = "^5.4.3"

+ 1
- 1
pytest.ini View File

1
 [pytest]
1
 [pytest]
2
 testpaths = tests
2
 testpaths = tests
3
-addopts = -rP
3
+#addopts = -r

+ 44
- 12
tests/test_modbus.py View File

33
 
33
 
34
     yield
34
     yield
35
 
35
 
36
-    os.unlink(tmpdb)
36
+    #os.unlink(tmpdb)
37
 
37
 
38
 @pytest.fixture(scope='module')
38
 @pytest.fixture(scope='module')
39
 def serial_conn():
39
 def serial_conn():
44
 
44
 
45
 @patch('umodbus.client.serial.rtu.send_message')
45
 @patch('umodbus.client.serial.rtu.send_message')
46
 @patch('umodbus.client.serial.rtu.read_coils')
46
 @patch('umodbus.client.serial.rtu.read_coils')
47
-def test_rtu_call_mocked(RtuReadCoils, RtuSendMessage, serial_conn):
48
-    modbus.read_holding_registers(1, 3)
47
+def test_rtu__coils_call_mocked(RtuReadCoils, RtuSendMessage, serial_conn):
48
+    modbus.read_coils(1, 3)
49
     RtuReadCoils.assert_any_call(slave_id=1, starting_address=1, quantity=2)
49
     RtuReadCoils.assert_any_call(slave_id=1, starting_address=1, quantity=2)
50
     RtuSendMessage.assert_called()
50
     RtuSendMessage.assert_called()
51
 
51
 
53
     RtuReadCoils.assert_any_call(slave_id=1, starting_address=1, quantity=2)
53
     RtuReadCoils.assert_any_call(slave_id=1, starting_address=1, quantity=2)
54
     RtuSendMessage.assert_called()
54
     RtuSendMessage.assert_called()
55
 
55
 
56
+
57
+@patch('umodbus.client.serial.rtu.send_message')
58
+@patch('umodbus.client.serial.rtu.read_holding_registers')
59
+def test_rtu_registers_call_mocked(RtuReadHoldingRegisters, RtuSendMessage, serial_conn):
60
+    modbus.read_holding_registers(1, 3)
61
+    RtuReadHoldingRegisters.assert_any_call(slave_id=1, starting_address=1, quantity=2)
62
+    RtuSendMessage.assert_called()
63
+
64
+    modbus.read_holding_registers(1, 500)
65
+    RtuReadHoldingRegisters.assert_any_call(slave_id=1, starting_address=1, quantity=125)
66
+    RtuSendMessage.assert_called()
67
+
56
 def test_rtu_call_holding_registers(serial_conn):
68
 def test_rtu_call_holding_registers(serial_conn):
57
     r = modbus.read_holding_registers(1, 1)
69
     r = modbus.read_holding_registers(1, 1)
58
     assert type(r) == list
70
     assert type(r) == list
70
     assert type(r) == list
82
     assert type(r) == list
71
     assert len(r) == 150
83
     assert len(r) == 150
72
 
84
 
85
+@pytest.fixture
86
+def var_types():
87
+    return VariableType.getall()
73
 
88
 
74
-
75
-
76
-def test_get_var(set_test_db, serial_conn):
77
-    d_var_types = VariableType.getall()
78
-
79
-    analog = d_var_types['Analog']
89
+def test_get_analog(set_test_db, serial_conn, var_types):
90
+    analog = var_types['Analog']
91
+    print(analog.__dict__)
80
     res = modbus.read_holding_registers(analog.start_address, analog.end_address)
92
     res = modbus.read_holding_registers(analog.start_address, analog.end_address)
81
     assert type(res) == list
93
     assert type(res) == list
82
     assert len(res) == analog.end_address - analog.start_address
94
     assert len(res) == analog.end_address - analog.start_address
83
     for r in res:
95
     for r in res:
84
         assert type(r) == int
96
         assert type(r) == int
85
 
97
 
86
-    integer = d_var_types['Integer']
98
+def test_get_integer(set_test_db, serial_conn, var_types):
99
+    integer = var_types['Integer']
100
+    print(integer.__dict__)
87
     try:
101
     try:
88
         res = modbus.read_holding_registers(integer.start_address, integer.end_address)
102
         res = modbus.read_holding_registers(integer.start_address, integer.end_address)
89
-    except umodbus.exceptions.IllegalDataAddressError:
103
+        assert type(res) == list
104
+        assert len(res) == integer.end_address - integer.start_address
105
+        for r in res:
106
+            assert type(r) == int
107
+
108
+    except umodbus.exceptions.IllegalDataAddressError as e:
109
+        print(e)
90
         print(f'The start and end addresses are not available [{integer.start_address}, {integer.end_address}]')
110
         print(f'The start and end addresses are not available [{integer.start_address}, {integer.end_address}]')
111
+        assert False
112
+
113
+
114
+def test_get_digital(set_test_db, serial_conn, var_types):
115
+    digital = var_types['Digital']
116
+    print(digital.__dict__)
117
+    try:
118
+        res = modbus.read_coils(digital.start_address, digital.end_address)
119
+    except umodbus.exceptions.IllegalDataAddressError:
120
+        print(f'The start and end addresses are not available [{digital.start_address}, {digital.end_address}]')
91
     assert type(res) == list
121
     assert type(res) == list
92
-    assert len(res) == integer.end_address - integer.start_address
122
+    assert len(res) == digital.end_address - digital.start_address
93
     for r in res:
123
     for r in res:
94
         assert type(r) == int
124
         assert type(r) == int
125
+        assert r in [0, 1]
126
+

Loading…
Cancel
Save