Skip to content

Commit 687c9de

Browse files
committed
Merge branch 'dev' for v3.1.1.
2 parents e3bf41c + 5de6039 commit 687c9de

17 files changed

+699
-202
lines changed

.github/workflows/docker-publish.yml

+17-49
Original file line numberDiff line numberDiff line change
@@ -1,92 +1,60 @@
11
name: Docker
22

3-
# This workflow uses actions that are not certified by GitHub.
4-
# They are provided by a third-party and are governed by
5-
# separate terms of service, privacy policy, and support
6-
# documentation.
7-
83
on:
94
push:
10-
branches: [ "dev" ]
11-
# Publish version tags as releases.
12-
tags: [ 'v*.*.*' ]
13-
14-
env:
15-
# Use docker.io for Docker Hub if empty
16-
REGISTRY: ghcr.io
17-
# github.repository as <account>/<repo>
18-
IMAGE_NAME: ${{ github.repository }}
19-
5+
branches:
6+
- dev
7+
- master
8+
tags:
9+
- v*
10+
workflow_dispatch:
2011

2112
jobs:
2213
build:
23-
2414
runs-on: ubuntu-latest
2515
permissions:
2616
contents: read
2717
packages: write
28-
# This is used to complete the identity challenge
29-
# with sigstore/fulcio when running outside of PRs.
3018
id-token: write
3119

3220
steps:
3321
- name: Checkout repository
3422
uses: actions/checkout@v3
3523

36-
# Install the cosign tool except on PR
37-
# https://github.com/sigstore/cosign-installer
3824
- name: Install cosign
39-
if: github.event_name != 'pull_request'
40-
uses: sigstore/cosign-installer@f3c664df7af409cb4873aa5068053ba9d61a57b6 #v2.6.0
41-
with:
42-
cosign-release: 'v1.11.0'
25+
uses: sigstore/cosign-installer@main
4326

27+
- name: Check cosign install
28+
run: cosign version
4429

45-
# Workaround: https://github.com/docker/build-push-action/issues/461
4630
- name: Setup Docker buildx
47-
uses: docker/setup-buildx-action@79abd3f86f79a9d68a23c75a09a9a85889262adf
31+
uses: docker/setup-buildx-action@v2
4832

49-
# Login against a Docker registry except on PR
50-
# https://github.com/docker/login-action
51-
- name: Log into registry ${{ env.REGISTRY }}
52-
if: github.event_name != 'pull_request'
53-
uses: docker/login-action@28218f9b04b4f3f62068d7b6ce6ca5b26e35336c
33+
- name: Login ghcr.io
34+
uses: docker/login-action@v2
5435
with:
55-
registry: ${{ env.REGISTRY }}
36+
registry: ghcr.io
5637
username: ${{ github.actor }}
5738
password: ${{ secrets.GITHUB_TOKEN }}
5839

59-
# Extract metadata (tags, labels) for Docker
60-
# https://github.com/docker/metadata-action
6140
- name: Extract Docker metadata
6241
id: meta
63-
uses: docker/metadata-action@98669ae865ea3cffbcbaa878cf57c20bbf1c6c38
42+
uses: docker/metadata-action@v4
6443
with:
65-
images: ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}
44+
images: ghcr.io/${{ github.repository }}
6645

67-
# Build and push Docker image with Buildx (don't push on PR)
68-
# https://github.com/docker/build-push-action
6946
- name: Build and push Docker image
7047
id: build-and-push
71-
uses: docker/build-push-action@ac9327eae2b366085ac7f6a2d02df8aa8ead720a
48+
uses: docker/build-push-action@v3
7249
with:
7350
context: .
74-
push: ${{ github.event_name != 'pull_request' }}
51+
push: true
7552
tags: ${{ steps.meta.outputs.tags }}
7653
labels: ${{ steps.meta.outputs.labels }}
7754
cache-from: type=gha
7855
cache-to: type=gha,mode=max
7956

80-
81-
# Sign the resulting Docker image digest except on PRs.
82-
# This will only write to the public Rekor transparency log when the Docker
83-
# repository is public to avoid leaking data. If you would like to publish
84-
# transparency data even for private images, pass --force to cosign below.
85-
# https://github.com/sigstore/cosign
8657
- name: Sign the published Docker image
87-
if: ${{ github.event_name != 'pull_request' }}
8858
env:
8959
COSIGN_EXPERIMENTAL: "true"
90-
# This step uses the identity token to provision an ephemeral certificate
91-
# against the sigstore community Fulcio instance.
9260
run: echo "${{ steps.meta.outputs.tags }}" | xargs -I {} cosign sign {}@${{ steps.build-and-push.outputs.digest }}

CHANGELOG.rst

+22
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,25 @@
1+
version 3.1.1
2+
----------------------------------------------------------
3+
* add missing server.start() (#1282)
4+
* small performance improvement on debug log (#1279)
5+
* Fix Unix sockets parsing (#1281)
6+
* client: Allow unix domain socket. (#1274)
7+
* transfer timeout to protocol object. (#1275)
8+
* Add ModbusUnixServer / StartAsyncUnixServer. (#1273)
9+
* Added return in AsyncModbusSerialClient.connect (#1271)
10+
* add connect() to the very first example (#1270)
11+
* Solve docker problem. (#1268)
12+
* Test stop of server task. (#1256)
13+
14+
Thanks to:
15+
16+
Alex
17+
Alexandre CUER
18+
Dries
19+
jan iversen
20+
peufeu2
21+
22+
123
version 3.1.0
224
----------------------------------------------------------
325
* Add xdist pr default. (#1253)

MAKE_RELEASE.rst

+2-2
Original file line numberDiff line numberDiff line change
@@ -13,8 +13,8 @@ Prepare/make release on dev.
1313
* Update README.rst "Supported versions"
1414
* Update CHANGELOG.rst
1515
* Add commits from last release, but selectively !
16-
git log --oneline v3.1.0..HEAD > commit.log
17-
git log v3.1.0..HEAD | grep Author > contributors.log
16+
git log --oneline v3.1.1..HEAD > commit.log
17+
git log v3.1.1..HEAD | grep Author > contributors.log
1818
* Commit, push and merge.
1919
* Checkout master locally
2020
* git merge dev

README.rst

+2-1
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,7 @@ Supported versions
2424

2525
Version `2.5.3 <https://github.com/riptideio/pymodbus/releases/tag/v2.5.3>`_ is the last 2.x release (Supports python 2.7.x - 3.7).
2626

27-
Version `3.1.0 <https://github.com/riptideio/pymodbus/releases/tag/v3.1.0>`_ is the current release (Supports Python >=3.8).
27+
Version `3.1.1 <https://github.com/riptideio/pymodbus/releases/tag/v3.1.1>`_ is the current release (Supports Python >=3.8).
2828

2929
.. important::
3030
All API changes after 3.0.0 are documented in `API_changes.rst <https://github.com/riptideio/pymodbus/blob/dev/API_changes.rst>`_
@@ -104,6 +104,7 @@ For those of you that just want to get started fast, here you go::
104104
from pymodbus.client import ModbusTcpClient
105105

106106
client = ModbusTcpClient('127.0.0.1')
107+
client.connect()
107108
client.write_coil(1, True)
108109
result = client.read_coils(1,1)
109110
print(result.bits[0])

pymodbus/client/base.py

+6-4
Original file line numberDiff line numberDiff line change
@@ -389,15 +389,17 @@ def _execute(self, request, **kwargs): # pylint: disable=unused-argument
389389
"""Start the producer to send the next request to consumer.write(Frame(request))."""
390390
request.transaction_id = self.transaction.getNextTID()
391391
packet = self.framer.buildPacket(request)
392-
txt = f"send: {hexlify_packets(packet)}"
393-
_logger.debug(txt)
392+
if _logger.isEnabledFor(logging.DEBUG):
393+
txt = f"send: {hexlify_packets(packet)}"
394+
_logger.debug(txt)
394395
self.write_transport(packet)
395396
return self._build_response(request.transaction_id)
396397

397398
def _data_received(self, data):
398399
"""Get response, check for valid message, decode result."""
399-
txt = f"recv: {hexlify_packets(data)}"
400-
_logger.debug(txt)
400+
if _logger.isEnabledFor(logging.DEBUG):
401+
txt = f"recv: {hexlify_packets(data)}"
402+
_logger.debug(txt)
401403
self.framer.processIncomingPacket(data, self._handle_response, unit=0)
402404

403405
def _handle_response(self, reply, **kwargs): # pylint: disable=unused-argument

pymodbus/client/serial.py

+4-1
Original file line numberDiff line numberDiff line change
@@ -88,7 +88,9 @@ async def close(self): # pylint: disable=invalid-overridden-method
8888

8989
def _create_protocol(self):
9090
"""Create protocol."""
91-
protocol = ModbusClientProtocol(framer=self.params.framer, xframer=self.framer)
91+
protocol = ModbusClientProtocol(
92+
framer=self.params.framer, xframer=self.framer, timeout=self.params.timeout
93+
)
9294
protocol.factory = self
9395
return protocol
9496

@@ -121,6 +123,7 @@ async def connect(self): # pylint: disable=invalid-overridden-method
121123
except Exception as exc: # pylint: disable=broad-except
122124
txt = f"Failed to connect: {exc}"
123125
_logger.warning(txt)
126+
return self.connected
124127

125128
def protocol_made_connection(self, protocol):
126129
"""Notify successful connection."""

pymodbus/client/tcp.py

+30-11
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,8 @@ class AsyncModbusTcpClient(ModbusBaseClient):
2626
:param source_address: (optional) source address of client
2727
:param kwargs: (optional) Experimental parameters
2828
29+
using unix domain socket can be achieved by setting host="unix:<path>"
30+
2931
Example::
3032
3133
from pymodbus.client import AsyncModbusTcpClient
@@ -99,12 +101,22 @@ async def _connect(self):
99101
"""Connect."""
100102
_logger.debug("Connecting.")
101103
try:
102-
transport, protocol = await asyncio.wait_for(
103-
self.loop.create_connection(
104-
self._create_protocol, host=self.params.host, port=self.params.port
105-
),
106-
timeout=self.params.timeout,
107-
)
104+
if self.params.host.startswith("unix:"):
105+
transport, protocol = await asyncio.wait_for(
106+
self.loop.create_unix_connection(
107+
self._create_protocol, path=self.params.host[5:]
108+
),
109+
timeout=self.params.timeout,
110+
)
111+
else:
112+
transport, protocol = await asyncio.wait_for(
113+
self.loop.create_connection(
114+
self._create_protocol,
115+
host=self.params.host,
116+
port=self.params.port,
117+
),
118+
timeout=self.params.timeout,
119+
)
108120
except Exception as exc: # pylint: disable=broad-except
109121
txt = f"Failed to connect: {exc}"
110122
_logger.warning(txt)
@@ -159,6 +171,8 @@ class ModbusTcpClient(ModbusBaseClient):
159171
:param source_address: (optional) source address of client
160172
:param kwargs: (optional) Experimental parameters
161173
174+
using unix domain socket can be achieved by setting host="unix:<path>"
175+
162176
Example::
163177
164178
from pymodbus.client import ModbusTcpClient
@@ -196,11 +210,16 @@ def connect(self):
196210
if self.socket:
197211
return True
198212
try:
199-
self.socket = socket.create_connection(
200-
(self.params.host, self.params.port),
201-
timeout=self.params.timeout,
202-
source_address=self.params.source_address,
203-
)
213+
if self.params.host.startswith("unix:"):
214+
self.socket = socket.socket(socket.AF_UNIX)
215+
self.socket.settimeout(self.params.timeout)
216+
self.socket.connect(self.params.host[5:])
217+
else:
218+
self.socket = socket.create_connection(
219+
(self.params.host, self.params.port),
220+
timeout=self.params.timeout,
221+
source_address=self.params.source_address,
222+
)
204223
txt = f"Connection to Modbus server established. Socket {self.socket.getsockname()}"
205224
_logger.debug(txt)
206225
except socket.error as msg:

pymodbus/datastore/context.py

+9-6
Original file line numberDiff line numberDiff line change
@@ -62,8 +62,9 @@ def validate(self, fc_as_hex, address, count=1):
6262
"""
6363
if not self.zero_mode:
6464
address = address + 1
65-
txt = f"validate: fc-[{fc_as_hex}] address-{address}: count-{count}"
66-
_logger.debug(txt)
65+
if _logger.isEnabledFor(logging.DEBUG):
66+
txt = f"validate: fc-[{fc_as_hex}] address-{address}: count-{count}"
67+
_logger.debug(txt)
6768
return self.store[self.decode(fc_as_hex)].validate(address, count)
6869

6970
def getValues(self, fc_as_hex, address, count=1):
@@ -76,8 +77,9 @@ def getValues(self, fc_as_hex, address, count=1):
7677
"""
7778
if not self.zero_mode:
7879
address = address + 1
79-
txt = f"getValues: fc-[{fc_as_hex}] address-{address}: count-{count}"
80-
_logger.debug(txt)
80+
if _logger.isEnabledFor(logging.DEBUG):
81+
txt = f"getValues: fc-[{fc_as_hex}] address-{address}: count-{count}"
82+
_logger.debug(txt)
8183
return self.store[self.decode(fc_as_hex)].getValues(address, count)
8284

8385
def setValues(self, fc_as_hex, address, values):
@@ -89,8 +91,9 @@ def setValues(self, fc_as_hex, address, values):
8991
"""
9092
if not self.zero_mode:
9193
address = address + 1
92-
txt = f"setValues[{fc_as_hex}] address-{address}: count-{len(values)}"
93-
_logger.debug(txt)
94+
if _logger.isEnabledFor(logging.DEBUG):
95+
txt = f"setValues[{fc_as_hex}] address-{address}: count-{len(values)}"
96+
_logger.debug(txt)
9497
self.store[self.decode(fc_as_hex)].setValues(address, values)
9598

9699
def register(self, function_code, fc_as_hex, datablock=None):

pymodbus/factory.py

+9-6
Original file line numberDiff line numberDiff line change
@@ -202,8 +202,9 @@ def _helper(self, data):
202202
"""
203203
function_code = int(data[0])
204204
if not (request := self.__lookup.get(function_code, lambda: None)()):
205-
txt = f"Factory Request[{function_code}]"
206-
_logger.debug(txt)
205+
if _logger.isEnabledFor(logging.DEBUG):
206+
txt = f"Factory Request[{function_code}]"
207+
_logger.debug(txt)
207208
request = IllegalFunctionRequest(function_code)
208209
else:
209210
fc_string = "%s: %s" % ( # pylint: disable=consider-using-f-string
@@ -212,8 +213,9 @@ def _helper(self, data):
212213
.rstrip('">"'),
213214
function_code,
214215
)
215-
txt = f"Factory Request[{fc_string}]"
216-
_logger.debug(txt)
216+
if _logger.isEnabledFor(logging.DEBUG):
217+
txt = f"Factory Request[{fc_string}]"
218+
_logger.debug(txt)
217219
request.decode(data[1:])
218220

219221
if hasattr(request, "sub_function_code"):
@@ -344,8 +346,9 @@ def _helper(self, data):
344346
.rstrip('">"'),
345347
function_code,
346348
)
347-
txt = f"Factory Response[{fc_string}]"
348-
_logger.debug(txt)
349+
if _logger.isEnabledFor(logging.DEBUG):
350+
txt = f"Factory Response[{fc_string}]"
351+
_logger.debug(txt)
349352
response = self.__lookup.get(function_code, lambda: None)()
350353
if function_code > 0x80:
351354
code = function_code & 0x7F # strip error portion

0 commit comments

Comments
 (0)