Browse Source

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

Maxime Alves LIRMM@home 3 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,11 +32,11 @@ CREATE TABLE IF NOT EXISTS var_value (
32 32
 );
33 33
 
34 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 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 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 41
 CREATE TRIGGER variable_insert BEFORE INSERT ON var_value
42 42
 FOR EACH ROW

+ 3
- 3
poetry.lock View File

@@ -273,7 +273,7 @@ description = "The lightning-fast ASGI server."
273 273
 name = "uvicorn"
274 274
 optional = false
275 275
 python-versions = "*"
276
-version = "0.11.6"
276
+version = "0.11.8"
277 277
 
278 278
 [package.dependencies]
279 279
 click = ">=7.0.0,<8.0.0"
@@ -436,8 +436,8 @@ urllib3 = [
436 436
     {file = "urllib3-1.25.10.tar.gz", hash = "sha256:91056c15fa70756691db97756772bb1eb9678fa585d9184f24534b100dc60f4a"},
437 437
 ]
438 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 442
 uvloop = [
443 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,6 +2,7 @@
2 2
 from serial import Serial
3 3
 from serial.serialutil import SerialException
4 4
 from umodbus.client.serial import rtu
5
+import umodbus
5 6
 from pprint import pprint
6 7
 
7 8
 from pyheatpump.conf import config
@@ -14,8 +15,12 @@ def connect():
14 15
     if serial_conn is None:
15 16
         print('Connecting to serial port *{}*'.format(
16 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 25
     if serial_conn.open is False:
21 26
         print('Opening serial port')
@@ -25,38 +30,54 @@ def connect():
25 30
 
26 31
 def read_coils(start, end):
27 32
     global serial_con
33
+    connect()
28 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 51
     return res
39 52
 
40 53
 
54
+
41 55
 def read_holding_registers(start, end):
42 56
     global serial_conn
57
+    connect()
43 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 75
     return res
59 76
 
60 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,8 +8,8 @@ license = "GPL-3.0-or-later"
8 8
 [tool.poetry.dependencies]
9 9
 python = "^3.7"
10 10
 starlette = "^0.13.6"
11
-umodbus = "^1.0.3"
12 11
 uvicorn = "^0.11.6"
12
+umodbus = "^1.0.3"
13 13
 
14 14
 [tool.poetry.dev-dependencies]
15 15
 pytest = "^5.4.3"

+ 1
- 1
pytest.ini View File

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

+ 44
- 12
tests/test_modbus.py View File

@@ -33,7 +33,7 @@ def set_test_db():
33 33
 
34 34
     yield
35 35
 
36
-    os.unlink(tmpdb)
36
+    #os.unlink(tmpdb)
37 37
 
38 38
 @pytest.fixture(scope='module')
39 39
 def serial_conn():
@@ -44,8 +44,8 @@ def serial_conn():
44 44
 
45 45
 @patch('umodbus.client.serial.rtu.send_message')
46 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 49
     RtuReadCoils.assert_any_call(slave_id=1, starting_address=1, quantity=2)
50 50
     RtuSendMessage.assert_called()
51 51
 
@@ -53,6 +53,18 @@ def test_rtu_call_mocked(RtuReadCoils, RtuSendMessage, serial_conn):
53 53
     RtuReadCoils.assert_any_call(slave_id=1, starting_address=1, quantity=2)
54 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 68
 def test_rtu_call_holding_registers(serial_conn):
57 69
     r = modbus.read_holding_registers(1, 1)
58 70
     assert type(r) == list
@@ -70,25 +82,45 @@ def test_rtu_call_holding_registers(serial_conn):
70 82
     assert type(r) == list
71 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 92
     res = modbus.read_holding_registers(analog.start_address, analog.end_address)
81 93
     assert type(res) == list
82 94
     assert len(res) == analog.end_address - analog.start_address
83 95
     for r in res:
84 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 101
     try:
88 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 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 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 123
     for r in res:
94 124
         assert type(r) == int
125
+        assert r in [0, 1]
126
+

Loading…
Cancel
Save