Skip to content

Commit a630118

Browse files
committed
modbus_tcp: added modBusDirection: write
1 parent 1463731 commit a630118

File tree

3 files changed

+63
-44
lines changed

3 files changed

+63
-44
lines changed

modbus_tcp/__init__.py

Lines changed: 47 additions & 38 deletions
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,8 @@
3737
from pymodbus.client.tcp import ModbusTcpClient
3838
from pymodbus import ModbusException
3939

40+
import struct
41+
4042
import logging
4143

4244
AttrAddress = 'modBusAddress'
@@ -63,7 +65,7 @@ class modbus_tcp(SmartPlugin):
6365
devices.
6466
"""
6567

66-
PLUGIN_VERSION = '1.0.14'
68+
PLUGIN_VERSION = '1.0.15'
6769

6870
def __init__(self, sh, *args, **kwargs):
6971
"""
@@ -210,6 +212,10 @@ def parse_item(self, item):
210212
self._regToWrite.update({reg: regPara})
211213
self.logger.info(f"parse item: {item} Attributes {regPara}")
212214
return self.update_item
215+
elif dataDirection == 'write':
216+
self._regToWrite.update({reg: regPara})
217+
self.logger.info(f"parse item: {item} Attributes {regPara}")
218+
return self.update_item
213219
else:
214220
self.logger.warning("Invalid data direction -> default(read) is used")
215221
self._regToRead.update({reg: regPara})
@@ -338,7 +344,7 @@ def update_item(self, item, caller=None, source=None, dest=None):
338344

339345
if self.has_iattr(item.conf, AttrDirection):
340346
dataDirection = self.get_iattr_value(item.conf, AttrDirection)
341-
if not dataDirection == 'read_write':
347+
if not (dataDirection == 'read_write' or dataDirection == 'write'):
342348
self.logger.debug(f'update_item: {item} Writing is not allowed - selected dataDirection:{dataDirection}')
343349
return
344350
# else:
@@ -554,44 +560,47 @@ def __read_Registers(self, regPara: dict):
554560

555561
self.logger.debug(f"read {objectType}.{address}.{slaveUnit} (address.slaveUnit) regCount:{registerCount} result:{result}")
556562

557-
if dataType.lower() == 'uint':
558-
if bits == 16:
559-
return decoder.decode_16bit_uint()
560-
elif bits == 32:
561-
return decoder.decode_32bit_uint()
562-
elif bits == 64:
563-
return decoder.decode_64bit_uint()
564-
else:
565-
self.logger.error(f"Number of bits or datatype not supported : {dataTypeStr}")
566-
elif dataType.lower() == 'int':
567-
if bits == 16:
568-
return decoder.decode_16bit_int()
569-
elif bits == 32:
570-
return decoder.decode_32bit_int()
571-
elif bits == 64:
572-
return decoder.decode_64bit_int()
573-
else:
574-
self.logger.error(f"Number of bits or datatype not supported : {dataTypeStr}")
575-
elif dataType.lower() == 'float':
576-
if bits == 32:
577-
return decoder.decode_32bit_float()
578-
elif bits == 64:
579-
return decoder.decode_64bit_float()
563+
try:
564+
if dataType.lower() == 'uint':
565+
if bits == 16:
566+
return decoder.decode_16bit_uint()
567+
elif bits == 32:
568+
return decoder.decode_32bit_uint()
569+
elif bits == 64:
570+
return decoder.decode_64bit_uint()
571+
else:
572+
self.logger.error(f"Number of bits or datatype not supported : {dataTypeStr}")
573+
elif dataType.lower() == 'int':
574+
if bits == 16:
575+
return decoder.decode_16bit_int()
576+
elif bits == 32:
577+
return decoder.decode_32bit_int()
578+
elif bits == 64:
579+
return decoder.decode_64bit_int()
580+
else:
581+
self.logger.error(f"Number of bits or datatype not supported : {dataTypeStr}")
582+
elif dataType.lower() == 'float':
583+
if bits == 32:
584+
return decoder.decode_32bit_float()
585+
elif bits == 64:
586+
return decoder.decode_64bit_float()
587+
else:
588+
self.logger.error(f"Number of bits or datatype not supported : {dataTypeStr}")
589+
elif dataType.lower() == 'string':
590+
# bei string: bits = bytes !! string16 -> 16Byte
591+
ret = decoder.decode_string(bits)
592+
return str(ret, 'ASCII')
593+
elif dataType.lower() == 'bit':
594+
if objectType == 'Coil' or objectType == 'DiscreteInput':
595+
# self.logger.debug(f"read bit value: {value}")
596+
return value
597+
else:
598+
self.logger.debug(f"read bits values: {value.decode_bits()}")
599+
return decoder.decode_bits()
580600
else:
581601
self.logger.error(f"Number of bits or datatype not supported : {dataTypeStr}")
582-
elif dataType.lower() == 'string':
583-
# bei string: bits = bytes !! string16 -> 16Byte
584-
ret = decoder.decode_string(bits)
585-
return str(ret, 'ASCII')
586-
elif dataType.lower() == 'bit':
587-
if objectType == 'Coil' or objectType == 'DiscreteInput':
588-
# self.logger.debug(f"read bit value: {value}")
589-
return value
590-
else:
591-
self.logger.debug(f"read bits values: {value.decode_bits()}")
592-
return decoder.decode_bits()
593-
else:
594-
self.logger.error(f"Number of bits or datatype not supported : {dataTypeStr}")
602+
except struct.error as e:
603+
self.logger.error(f"unable to unpack data for datatype={dataType.lower()} for read {objectType}.{address}.{slaveUnit} (address.slaveUnit) regCount:{registerCount}")
595604

596605
@staticmethod
597606
def is_NaN( value, dataType: str) -> bool:

modbus_tcp/plugin.yaml

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -8,11 +8,11 @@ plugin:
88
maintainer: ivande, Cannon
99
tester: NONE # Who tests this plugin?
1010
state: ready
11-
keywords: modbus_tcp modbus smartmeter inverter heatpump
11+
keywords: modbus_tcp modbus tcp smartmeter inverter heatpump
1212
#documentation: http://smarthomeng.de/user/plugins/modbus_tcp/user_doc.html
1313
support: https://knx-user-forum.de/forum/supportforen/smarthome-py/1154368-einbindung-von-modbus-tcp
1414
version: 1.0.14 # Plugin version
15-
sh_minversion: '1.10' # minimum shNG version to use this plugin
15+
sh_minversion: '1.10' # minimum shNG version to use this plugin
1616
#sh_maxversion: # maximum shNG version to use this plugin (leave empty if latest)
1717
py_minversion: '3.8'
1818
# py_maxversion: # maximum Python version to use for this plugin (leave empty if latest)

modbus_tcp/user_doc.rst

Lines changed: 14 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -18,9 +18,9 @@ SmarthomeNG plugin, zum Lesen von Register über ModBusTCP
1818
Anforderungen
1919
=============
2020

21-
* Python > 3.6
22-
* pymodbus >= 2.5.3
23-
* SmarthomeNG >= 1.8.0
21+
* Python > 3.8
22+
* pymodbus < 3.10
23+
* SmarthomeNG >= 1.10
2424

2525
pymodbus
2626
--------
@@ -164,6 +164,16 @@ siehe auch example.yaml
164164
165165
Changelog
166166
---------
167+
V1.0.15 Item Attribut modBusDirection erweitert: 'write' hinzugefügt für Register
168+
die nicht gelesen werden können aber beschrieben werden dürfen
169+
170+
pymodbus auf Version < 3.10 beschränkt
171+
172+
V1.0.14 Fehlerwerte hinzugefügt, Exception Handling verbessert, an aktuelle Pymodbus Version
173+
angepasst und minimal notwendige Python Version auf 3.8 gesetzt
174+
175+
V1.0.13 pause_item wird nun unterstützt
176+
167177
V1.0.12 Problem beim Schreiben ohne modBusObjectTyp behoben
168178
bei wiederholten Verbindungsproblemen Ausgabe vom Logger reduziert
169179
Verbindungstop mit supend/resume steuerbar
@@ -173,7 +183,7 @@ V1.0.11 Verbesserung Umwandlung Byte/Wordorder in Endian-Konstante
173183

174184
V1.0.10 Mindestversion für pymodbus ist nun 3.5.2
175185

176-
V1.0.9
186+
V1.0.9 Zusätzlich zu cycle für Geräteabfrage 'crontab' Einträge erlaubt, Logeinträge abgeändert in Python f-strings
177187

178188
V1.0.8 Neuere Pymodbus Versionen können nun verwendet werden.
179189
Di minimale Version für Pymodbus ist jetzt 2.5.3

0 commit comments

Comments
 (0)