Skip to content

Commit

Permalink
maintainence release - Update to pymodbus 2.5.3, six 1.16.0, some doc…
Browse files Browse the repository at this point in the history
…umentation improvements.
  • Loading branch information
SvenBunge committed Dec 26, 2021
1 parent c5ef76e commit 7ec2280
Show file tree
Hide file tree
Showing 25 changed files with 127 additions and 91 deletions.
4 changes: 2 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,7 @@ You can replace step 4 with the `./buildRelease.sh` script. With the help of the

## Libraries

* pymodbus 2.5.0 - https://github.com/riptideio/pymodbus
* six (in pymodbus folder) 1.15.0 - https://github.com/benjaminp/six
* pymodbus 2.5.3 - https://github.com/riptideio/pymodbus
* six (in pymodbus folder) 1.16.0 - https://github.com/benjaminp/six

The shipped libraries may distributed under a different license conditions. Respect those licenses as well!
2 changes: 1 addition & 1 deletion config.xml
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
<?xml version="1.0" encoding="utf-8"?>
<config>
<modules>
<module category="Energiemanagement" context="kostalKsemModbusTCP14181" id="14181" name="kostalKsemModbusTCP" internal_name="kostalKSEM_ModbusTCP" external_name="Kostal-KSEM ModbusTCP (14181)" version="1.0">
<module category="Energiemanagement" context="kostalKsemModbusTCP14181" id="14181" name="kostalKsemModbusTCP" internal_name="kostalKSEM_ModbusTCP" external_name="Kostal-KSEM ModbusTCP (14181)" version="1.1">
<inputs>
<input type="number" const_name="switch" init_value="0">Switch on (1) / off (0)</input>
<input type="number" const_name="fetch_interval" init_value="5">Seconds of the interval to read power values (default: 5 secs)</input>
Expand Down
12 changes: 6 additions & 6 deletions doc/log14181.md
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
# Kostal KSEM ModbusTCP v1.0
# Kostal KSEM ModbusTCP v1.1

Dieser Logikbaustein liest regelmäßig Werte aus dem Smart Energy Meter des Herstellers *Kostal*, auch KSEM genannt, ein.

Expand All @@ -7,8 +7,8 @@ Dieser Logikbaustein liest regelmäßig Werte aus dem Smart Energy Meter des Her
| Nummer | Datentyp | Default | Beschreibung |
| ------ | -------- | ------- | -------------|
| 1 | Zahl | 0 | Schaltet den Baustein aus oder an. Dies funktioniert zur Laufzeit oder auch statisch, in dem der Wert entsprechend im Logikeditor geändert wird. 0 = Aus, 1 = an |
| 2 | Zahl | 5 Sekunden | Ist die Frequenz, wie oft der Baustein den Wechselrichter abfragt. Kleinere Werte erhöhen die Last auf HS und WR. |
| 3 | Text | 127.0.0.1 | Die IP-Adresse für den Wechselrichter. Hostname aktuell nicht implementiert. |
| 2 | Zahl | 5 Sekunden | Ist die Frequenz, wie oft der Baustein den KSEM abfragt. Kleinere Werte erhöhen die Last. |
| 3 | Text | 127.0.0.1 | Die IP-Adresse des Energiemeters. Hostname aktuell nicht implementiert. |

## Ausgänge

Expand Down Expand Up @@ -61,12 +61,12 @@ Es wird weder eine Haftung noch eine Gewährleistung übernommen. Für den Betri

# Sourcecode / Weiterführende Doku

* Der Sourcecode ist auf Github zu finden: [hs_kostalInverterModbusTCP](https://github.com/SvenBunge/hs_kostalKSEM_ModbusTCP)
* Der Sourcecode ist auf Github zu finden: [hs_kostalKSEM_ModbusTCP](https://github.com/SvenBunge/hs_kostalKSEM_ModbusTCP)
* Der Baustein wird im KNX-Forum diskutiert: [Thread](https://knx-user-forum.de/forum/%C3%B6ffentlicher-bereich/knx-eib-forum/1630161-logikbaustein-kostal-ksem-via-modbus-tcp-abfragen)

# Lizenz & Faire Nutzung

* Der Baustein wird unter der LGPL 2.1 frei zur Verfügung gestellt.
* Die Nutzung des Logikbausteins ist für Endverbraucher frei, wenn sie diese selbst und selbstständig in Betrieb nehmen und konfigurieren. - Integratoren haben eine angemessene Aufwandsentschädigung für die Erstellung auf das Paypal-Konto pro Installation zu zahlen, welches im [KNX-Forum-Thread](https://knx-user-forum.de/forum/%C3%B6ffentlicher-bereich/knx-eib-forum/1559910-logikbaustein-kostal-wechselrichter-via-modbus-tcp-abfragen) im obersten Post hinterlegt ist.
* Die Nutzung des Logikbausteins ist für Endverbraucher frei, wenn sie diese selbst und selbstständig in Betrieb nehmen und konfigurieren. - Integratoren haben eine angemessene Aufwandsentschädigung für die Erstellung auf das Paypal-Konto pro Installation zu zahlen, welches im [KNX-Forum-Thread](https://knx-user-forum.de/forum/%C3%B6ffentlicher-bereich/knx-eib-forum/1559910-logikbaustein-kostal-wechselrichter-via-modbus-tcp-abfragen) im obersten Post hinterlegt ist.
* Freie Software heißt nicht freie Wartung & Support und geschieht auf freiwilliger Basis
* Es wird keine Gewährleistung noch Haftung für Schäden aus der Nutzung des Bausteins übernommen
* Es wird keine Gewährleistung noch Haftung für Schäden aus der Nutzung des Bausteins übernommen
33 changes: 19 additions & 14 deletions lib/pymodbus/client/asynchronous/async_io/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -234,7 +234,7 @@ class ReconnectingAsyncioModbusTcpClient(object):
#: Maximum delay in milli seconds before reconnect is attempted.
DELAY_MAX_MS = 1000 * 60 * 5

def __init__(self, protocol_class=None, loop=None):
def __init__(self, protocol_class=None, loop=None, **kwargs):
"""
Initialize ReconnectingAsyncioModbusTcpClient
:param protocol_class: Protocol used to talk to modbus device.
Expand All @@ -251,6 +251,7 @@ def __init__(self, protocol_class=None, loop=None):
self.connected = False
#: Reconnect delay in milli seconds.
self.delay_ms = self.DELAY_MIN_MS
self._proto_args = kwargs

def reset_delay(self):
"""
Expand Down Expand Up @@ -291,7 +292,7 @@ def _create_protocol(self):
"""
Factory function to create initialized protocol instance.
"""
protocol = self.protocol_class()
protocol = self.protocol_class(**self._proto_args)
protocol.factory = self
return protocol

Expand Down Expand Up @@ -350,7 +351,7 @@ def _reconnect(self):
class AsyncioModbusTcpClient(object):
"""Client to connect to modbus device over TCP/IP."""

def __init__(self, host=None, port=502, protocol_class=None, loop=None):
def __init__(self, host=None, port=502, protocol_class=None, loop=None, **kwargs):
"""
Initializes Asyncio Modbus Tcp Client
:param host: Host IP address
Expand All @@ -369,6 +370,7 @@ def __init__(self, host=None, port=502, protocol_class=None, loop=None):
self.port = port

self.connected = False
self._proto_args = kwargs

def stop(self):
"""
Expand All @@ -384,7 +386,7 @@ def _create_protocol(self):
"""
Factory function to create initialized protocol instance.
"""
protocol = self.protocol_class()
protocol = self.protocol_class(**self._proto_args)
protocol.factory = self
return protocol

Expand Down Expand Up @@ -439,14 +441,14 @@ class ReconnectingAsyncioModbusTlsClient(ReconnectingAsyncioModbusTcpClient):
"""
Client to connect to modbus device repeatedly over TLS."
"""
def __init__(self, protocol_class=None, loop=None, framer=None):
def __init__(self, protocol_class=None, loop=None, framer=None, **kwargs):
"""
Initialize ReconnectingAsyncioModbusTcpClient
:param protocol_class: Protocol used to talk to modbus device.
:param loop: Event loop to use
"""
self.framer = framer
ReconnectingAsyncioModbusTcpClient.__init__(self, protocol_class, loop)
ReconnectingAsyncioModbusTcpClient.__init__(self, protocol_class, loop, **kwargs)

@asyncio.coroutine
def start(self, host, port=802, sslctx=None, server_hostname=None):
Expand Down Expand Up @@ -490,7 +492,7 @@ def _create_protocol(self):
"""
Factory function to create initialized protocol instance.
"""
protocol = self.protocol_class(framer=self.framer)
protocol = self.protocol_class(framer=self.framer, **self._proto_args)
protocol.transaction = FifoTransactionManager(self)
protocol.factory = self
return protocol
Expand All @@ -506,7 +508,7 @@ class ReconnectingAsyncioModbusUdpClient(object):
#: Maximum delay in milli seconds before reconnect is attempted.
DELAY_MAX_MS = 1000 * 60 * 5

def __init__(self, protocol_class=None, loop=None):
def __init__(self, protocol_class=None, loop=None, **kwargs):
"""
Initializes ReconnectingAsyncioModbusUdpClient
:param protocol_class: Protocol used to talk to modbus device.
Expand All @@ -523,6 +525,7 @@ def __init__(self, protocol_class=None, loop=None):
self.port = 0

self.connected = False
self._proto_args = kwargs
self.reset_delay()

def reset_delay(self):
Expand Down Expand Up @@ -572,7 +575,7 @@ def _create_protocol(self, host=None, port=0):
"""
Factory function to create initialized protocol instance.
"""
protocol = self.protocol_class()
protocol = self.protocol_class(**self._proto_args)
protocol.host = host
protocol.port = port
protocol.factory = self
Expand Down Expand Up @@ -637,7 +640,7 @@ class AsyncioModbusUdpClient(object):
Client to connect to modbus device over UDP.
"""

def __init__(self, host=None, port=502, protocol_class=None, loop=None):
def __init__(self, host=None, port=502, protocol_class=None, loop=None, **kwargs):
"""
Initializes Asyncio Modbus UDP Client
:param host: Host IP address
Expand All @@ -656,6 +659,7 @@ def __init__(self, host=None, port=502, protocol_class=None, loop=None):
self.port = port

self.connected = False
self._proto_args = kwargs

def stop(self):
"""
Expand All @@ -674,7 +678,7 @@ def _create_protocol(self, host=None, port=0):
"""
Factory function to create initialized protocol instance.
"""
protocol = self.protocol_class()
protocol = self.protocol_class(**self._proto_args)
protocol.host = host
protocol.port = port
protocol.factory = self
Expand Down Expand Up @@ -842,7 +846,7 @@ def init_tcp_client(proto_cls, loop, host, port, **kwargs):
:return:
"""
client = ReconnectingAsyncioModbusTcpClient(protocol_class=proto_cls,
loop=loop)
loop=loop, **kwargs)
yield from client.start(host, port)
return client

Expand All @@ -863,7 +867,8 @@ def init_tls_client(proto_cls, loop, host, port, sslctx=None,
:return:
"""
client = ReconnectingAsyncioModbusTlsClient(protocol_class=proto_cls,
loop=loop, framer=framer)
loop=loop, framer=framer,
**kwargs)
yield from client.start(host, port, sslctx, server_hostname)
return client

Expand All @@ -880,6 +885,6 @@ def init_udp_client(proto_cls, loop, host, port, **kwargs):
:return:
"""
client = ReconnectingAsyncioModbusUdpClient(protocol_class=proto_cls,
loop=loop)
loop=loop, **kwargs)
yield from client.start(host, port)
return client
11 changes: 5 additions & 6 deletions lib/pymodbus/client/asynchronous/factory/tcp.py
Original file line number Diff line number Diff line change
Expand Up @@ -77,8 +77,7 @@ def io_loop_factory(host="127.0.0.1", port=Defaults.Port, framer=None,
return protocol, future


def async_io_factory(host="127.0.0.1", port=Defaults.Port, framer=None,
source_address=None, timeout=None, **kwargs):
def async_io_factory(host="127.0.0.1", port=Defaults.Port, **kwargs):
"""
Factory to create asyncio based asynchronous tcp clients
:param host: Host IP address
Expand All @@ -91,14 +90,14 @@ def async_io_factory(host="127.0.0.1", port=Defaults.Port, framer=None,
"""
import asyncio
from pymodbus.client.asynchronous.async_io import init_tcp_client
loop = kwargs.get("loop") or asyncio.new_event_loop()
proto_cls = kwargs.get("proto_cls", None)
loop = kwargs.pop("loop", None) or asyncio.new_event_loop()
proto_cls = kwargs.pop("proto_cls", None)
if not loop.is_running():
asyncio.set_event_loop(loop)
cor = init_tcp_client(proto_cls, loop, host, port)
cor = init_tcp_client(proto_cls, loop, host, port, **kwargs)
client = loop.run_until_complete(asyncio.gather(cor))[0]
else:
cor = init_tcp_client(proto_cls, loop, host, port)
cor = init_tcp_client(proto_cls, loop, host, port, **kwargs)
future = asyncio.run_coroutine_threadsafe(cor, loop=loop)
client = future.result()

Expand Down
11 changes: 5 additions & 6 deletions lib/pymodbus/client/asynchronous/factory/tls.py
Original file line number Diff line number Diff line change
Expand Up @@ -13,8 +13,7 @@
LOGGER = logging.getLogger(__name__)

def async_io_factory(host="127.0.0.1", port=Defaults.TLSPort, sslctx=None,
server_hostname=None, framer=None, source_address=None,
timeout=None, **kwargs):
server_hostname=None, framer=None, **kwargs):
"""
Factory to create asyncio based asynchronous tls clients
:param host: Host IP address
Expand All @@ -29,16 +28,16 @@ def async_io_factory(host="127.0.0.1", port=Defaults.TLSPort, sslctx=None,
"""
import asyncio
from pymodbus.client.asynchronous.async_io import init_tls_client
loop = kwargs.get("loop") or asyncio.new_event_loop()
proto_cls = kwargs.get("proto_cls", None)
loop = kwargs.pop("loop", None) or asyncio.new_event_loop()
proto_cls = kwargs.pop("proto_cls", None)
if not loop.is_running():
asyncio.set_event_loop(loop)
cor = init_tls_client(proto_cls, loop, host, port, sslctx, server_hostname,
framer)
framer, **kwargs)
client = loop.run_until_complete(asyncio.gather(cor))[0]
else:
cor = init_tls_client(proto_cls, loop, host, port, sslctx, server_hostname,
framer)
framer, **kwargs)
future = asyncio.run_coroutine_threadsafe(cor, loop=loop)
client = future.result()

Expand Down
9 changes: 4 additions & 5 deletions lib/pymodbus/client/asynchronous/factory/udp.py
Original file line number Diff line number Diff line change
Expand Up @@ -52,8 +52,7 @@ def io_loop_factory(host="127.0.0.1", port=Defaults.Port, framer=None,
return protocol, future


def async_io_factory(host="127.0.0.1", port=Defaults.Port, framer=None,
source_address=None, timeout=None, **kwargs):
def async_io_factory(host="127.0.0.1", port=Defaults.Port, **kwargs):
"""
Factory to create asyncio based asynchronous udp clients
:param host: Host IP address
Expand All @@ -66,9 +65,9 @@ def async_io_factory(host="127.0.0.1", port=Defaults.Port, framer=None,
"""
import asyncio
from pymodbus.client.asynchronous.async_io import init_udp_client
loop = kwargs.get("loop") or asyncio.get_event_loop()
proto_cls = kwargs.get("proto_cls", None)
cor = init_udp_client(proto_cls, loop, host, port)
loop = kwargs.pop("loop", None) or asyncio.get_event_loop()
proto_cls = kwargs.pop("proto_cls", None)
cor = init_udp_client(proto_cls, loop, host, port, **kwargs)
if not loop.is_running():
client = loop.run_until_complete(asyncio.gather(cor))[0]
else:
Expand Down
2 changes: 1 addition & 1 deletion lib/pymodbus/client/asynchronous/mixins.py
Original file line number Diff line number Diff line change
Expand Up @@ -55,7 +55,7 @@ def __init__(self, host="127.0.0.1", port=Defaults.Port, framer=None,
self.host = host
self.port = port
self.source_address = source_address or ("", 0)
self.timeout = timeout if timeout is not None else Defaults.Timeout
self._timeout = timeout if timeout is not None else Defaults.Timeout


class AsyncModbusSerialClientMixin(BaseAsyncModbusClient):
Expand Down
7 changes: 3 additions & 4 deletions lib/pymodbus/client/sync.py
Original file line number Diff line number Diff line change
Expand Up @@ -231,7 +231,6 @@ def _check_read_buffer(self, recv_size=None):
time_ = time.time()
end = time_ + self.timeout
data = None
data_length = 0
ready = select.select([self.socket], [], [], end - time_)
if ready[0]:
data = self.socket.recv(1024)
Expand Down Expand Up @@ -307,7 +306,7 @@ def _recv(self, size):

# Timeout is reduced also if some data has been received in order
# to avoid infinite loops when there isn't an expected response
# size and the slave sends noisy data continuosly.
# size and the slave sends noisy data continuously.
if time_ > end:
break

Expand Down Expand Up @@ -448,7 +447,7 @@ def _recv(self, size):

# Timeout is reduced also if some data has been received in order
# to avoid infinite loops when there isn't an expected response
# size and the slave sends noisy data continuosly.
# size and the slave sends noisy data continuously.
if time_ > end:
break

Expand Down Expand Up @@ -649,7 +648,7 @@ def connect(self):
if self.socket:
return True
try:
self.socket = serial.Serial(port=self.port,
self.socket = serial.serial_for_url(self.port,
timeout=self.timeout,
bytesize=self.bytesize,
stopbits=self.stopbits,
Expand Down
2 changes: 1 addition & 1 deletion lib/pymodbus/constants.py
Original file line number Diff line number Diff line change
Expand Up @@ -224,7 +224,7 @@ class DeviceInformation(Singleton):
.. attribute:: Regular
In addition to basic data objects, the device provides additional
and optinoal identification and description data objects. All of
and optional identification and description data objects. All of
the objects of this category are defined in the standard but their
implementation is optional.
Expand Down
2 changes: 1 addition & 1 deletion lib/pymodbus/datastore/context.py
Original file line number Diff line number Diff line change
Expand Up @@ -132,7 +132,7 @@ def __iter__(self):
def __contains__(self, slave):
''' Check if the given slave is in this list
:param slave: slave The slave to check for existance
:param slave: slave The slave to check for existence
:returns: True if the slave exists, False otherwise
'''
if self.single and self._slaves:
Expand Down
2 changes: 1 addition & 1 deletion lib/pymodbus/datastore/store.py
Original file line number Diff line number Diff line change
Expand Up @@ -241,7 +241,7 @@ def create(klass, values=None):
return klass(values)

def reset(self):
''' Reset the store to the intially provided defaults'''
''' Reset the store to the initially provided defaults'''
self.values = self.default_value.copy()

def validate(self, address, count=1):
Expand Down
2 changes: 1 addition & 1 deletion lib/pymodbus/device.py
Original file line number Diff line number Diff line change
Expand Up @@ -467,7 +467,7 @@ def summary(self):
#---------------------------------------------------------------------------#
class ModbusControlBlock(Singleton):
'''
This is a global singleotn that controls all system information
This is a global singleton that controls all system information
All activity should be logged here and all diagnostic requests
should come from here.
Expand Down
2 changes: 1 addition & 1 deletion lib/pymodbus/payload.py
Original file line number Diff line number Diff line change
Expand Up @@ -273,7 +273,7 @@ def add_string(self, value):
class BinaryPayloadDecoder(object):
"""
A utility that helps decode payload messages from a modbus
reponse message. It really is just a simple wrapper around
response message. It really is just a simple wrapper around
the struct module, however it saves time looking up the format
strings. What follows is a simple example::
Expand Down
Loading

0 comments on commit 7ec2280

Please sign in to comment.