diff --git a/.github/workflows/build-and-push-container-image.yaml b/.github/workflows/build-and-push-container-image.yaml index faba241..d636010 100644 --- a/.github/workflows/build-and-push-container-image.yaml +++ b/.github/workflows/build-and-push-container-image.yaml @@ -19,7 +19,7 @@ jobs: !contains(github.event.pull_request.labels.*.name, 'chore') steps: - name: Checkout GIT repository - uses: actions/checkout@v4 + uses: actions/checkout@v7 - name: Get the application version id: application-version run: | @@ -28,20 +28,29 @@ jobs: echo "ERROR: unable to detect version number!" >&2 exit 1 fi - echo "tag=${image_version}" >> $GITHUB_OUTPUT + echo "tag=${image_version}" >> "${GITHUB_OUTPUT}" - name: Set up QEMU - uses: docker/setup-qemu-action@v3 + uses: docker/setup-qemu-action@v4 - name: Set up Docker Buildx - uses: docker/setup-buildx-action@v3 + uses: docker/setup-buildx-action@v4 - name: Login to container registry - uses: docker/login-action@v3 + uses: docker/login-action@v4 with: username: ${{ secrets.DOCKERHUB_USERNAME }} password: ${{ secrets.DOCKERHUB_PASSWORD }} - name: Build and push - uses: docker/build-push-action@v6 + uses: docker/build-push-action@v7 with: push: true context: . platforms: linux/amd64, linux/arm64 tags: oitc/modbus-client:${{steps.application-version.outputs.tag}},oitc/modbus-client:latest + labels: | + site.local.program.version=${{ steps.application-version.outputs.tag }} + context.github.repositoryUrl=${{ github.repositoryUrl }} + context.github.actor=${{ github.actor }} + context.github.event.repository.updated_at=${{ github.event.repository.updated_at}} + context.github.ref=${{ github.ref }} + context.github.job=${{ github.job }} + context.runner.os=${{ runner.os }} + context.runner.arch=${{ runner.arch }} diff --git a/.github/workflows/container-image-build-validation.yaml b/.github/workflows/container-image-build-validation.yaml index 9a1b097..003063d 100644 --- a/.github/workflows/container-image-build-validation.yaml +++ b/.github/workflows/container-image-build-validation.yaml @@ -7,195 +7,5 @@ on: - synchronize - reopened jobs: - container-build: - name: Build - runs-on: ubuntu-latest - steps: - - name: Checkout GIT repository - uses: actions/checkout@v4 - - name: Set up QEMU - uses: docker/setup-qemu-action@v3 - - name: Set up Docker Buildx - uses: docker/setup-buildx-action@v3 - - name: Test build - uses: docker/build-push-action@v6 - with: - push: false - load: false - context: . - platforms: linux/amd64, linux/arm64 - tags: container-build:test - - name: Test build and export for further validation - uses: docker/build-push-action@v6 - with: - push: false - load: true - context: . - tags: container-build:test - outputs: type=docker,dest=/tmp/container.tar - - name: Upload container image as artifact - uses: actions/upload-artifact@v4 - with: - name: container-build - path: /tmp/container.tar - - function-test-preparation: - name: Container functionality test preparation - runs-on: ubuntu-latest - permissions: write-all - steps: - - name: Checkout GIT repository - uses: actions/checkout@v4 - - name: Log in to Github container registry - run: echo "${{ secrets.GITHUB_TOKEN }}" | docker login ghcr.io -u ${{ github.actor }} --password-stdin - - name: Build container for functionality test - uses: docker/build-push-action@v6 - with: - push: true - load: false - context: . - file: ./Dockerfile - tags: ghcr.io/cybcon/modbus-client/modbus-client:test - - function-test-execution: - name: Container functionality test execution - needs: function-test-preparation - runs-on: ubuntu-latest - services: - modbusserver: - image: oitc/modbus-server:latest - ports: - - 5020:5020 - steps: - - name: Log in to Github container registry - run: echo "${{ secrets.GITHUB_TOKEN }}" | docker login ghcr.io -u ${{ github.actor }} --password-stdin - - name: Pull Modbus Client for functionality test - run: | - docker pull ghcr.io/cybcon/modbus-client/modbus-client:test - echo "# Modbus functionality test" >> ${GITHUB_STEP_SUMMARY} - - name: Get modbus server address - id: modbus-server-address - run: | - LOCAL_MACHINE=$(ifconfig -a eth0|grep inet|grep -v 127.0.0.1|grep -v inet6|awk '{print $2}'|tr -d "addr:") - echo "DEBUG: ${LOCAL_MACHINE}" - echo "ip=${LOCAL_MACHINE}" >> $GITHUB_OUTPUT - - name: Validate server endpoint - run: | - modbusserver=${{steps. modbus-server-address.outputs.ip}} - ping -c 1 -q ${modbusserver} - RC=$? - if [ ${RC} -gt 0 ]; then - echo "ERROR: Modbus slave not reachable" >&2 - exit 1 - fi - - name: Test Discrete Output Coils - run: | - modbusserver=${{steps. modbus-server-address.outputs.ip}} - echo "## Get Discrete Output Coils" >> ${GITHUB_STEP_SUMMARY} - echo '
' >> ${GITHUB_STEP_SUMMARY} - echo ' Test output details' >> ${GITHUB_STEP_SUMMARY} - echo "" >> ${GITHUB_STEP_SUMMARY} - echo ' ```' >> ${GITHUB_STEP_SUMMARY} - echo " docker run --rm ghcr.io/cybcon/modbus-client/modbus-client:test -s ${modbusserver} -p 5020 -t 1 -r 0 -l 10" >> ${GITHUB_STEP_SUMMARY} - docker run --rm ghcr.io/cybcon/modbus-client/modbus-client:test -s ${modbusserver} -p 5020 -t 1 -r 0 -l 10 > output.tmp 2>&1 - cat output.tmp | while read line - do - echo " ${line}" >> ${GITHUB_STEP_SUMMARY} - done - echo ' ```' >> ${GITHUB_STEP_SUMMARY} - echo '
' >> ${GITHUB_STEP_SUMMARY} - echo "" >> ${GITHUB_STEP_SUMMARY} - # analyze output - RESULT=$(cat output.tmp | grep ^2 | awk '{print $3}') - if [ "${RESULT}" == "False" ]; then - echo "Test succesfull :white_check_mark:" >> ${GITHUB_STEP_SUMMARY} - else - echo "Test failed :x:" >> ${GITHUB_STEP_SUMMARY} - exit 1 - fi - - name: Test Discrete Input Contacts - run: | - modbusserver=${{steps. modbus-server-address.outputs.ip}} - echo "## Get Discrete Input Contacts" >> ${GITHUB_STEP_SUMMARY} - echo '
' >> ${GITHUB_STEP_SUMMARY} - echo ' Test output details' >> ${GITHUB_STEP_SUMMARY} - echo "" >> ${GITHUB_STEP_SUMMARY} - echo ' ```' >> ${GITHUB_STEP_SUMMARY} - echo " docker run --rm ghcr.io/cybcon/modbus-client/modbus-client:test -s ${modbusserver} -p 5020 -t 2 -r 0 -l 10" >> ${GITHUB_STEP_SUMMARY} - docker run --rm ghcr.io/cybcon/modbus-client/modbus-client:test -s ${modbusserver} -p 5020 -t 2 -r 0 -l 10 > output.tmp 2>&1 - cat output.tmp | while read line - do - echo " ${line}" >> ${GITHUB_STEP_SUMMARY} - done - echo ' ```' >> ${GITHUB_STEP_SUMMARY} - echo '
' >> ${GITHUB_STEP_SUMMARY} - echo "" >> ${GITHUB_STEP_SUMMARY} - # analyze output - RESULT=$(cat output.tmp | grep ^10002 | awk '{print $3}') - if [ "${RESULT}" == "False" ]; then - echo "Test succesfull :white_check_mark:" >> ${GITHUB_STEP_SUMMARY} - else - echo "Test failed :x:" >> ${GITHUB_STEP_SUMMARY} - exit 1 - fi - - name: Test Analog Output Holding Register - run: | - modbusserver=${{steps. modbus-server-address.outputs.ip}} - echo "## Get Analog Output Holding Register" >> ${GITHUB_STEP_SUMMARY} - echo '
' >> ${GITHUB_STEP_SUMMARY} - echo ' Test output details' >> ${GITHUB_STEP_SUMMARY} - echo "" >> ${GITHUB_STEP_SUMMARY} - echo ' ```' >> ${GITHUB_STEP_SUMMARY} - echo " docker run --rm ghcr.io/cybcon/modbus-client/modbus-client:test -s ${modbusserver} -p 5020 -t 3 -r 0 -l 10" >> ${GITHUB_STEP_SUMMARY} - docker run --rm ghcr.io/cybcon/modbus-client/modbus-client:test -s ${modbusserver} -p 5020 -t 3 -r 0 -l 10 > output.tmp 2>&1 - cat output.tmp | while read line - do - echo " ${line}" >> ${GITHUB_STEP_SUMMARY} - done - echo ' ```' >> ${GITHUB_STEP_SUMMARY} - echo '
' >> ${GITHUB_STEP_SUMMARY} - echo "" >> ${GITHUB_STEP_SUMMARY} - # analyze output - RESULT=$(cat output.tmp | grep ^40002 | awk '{print $2}') - if [ "${RESULT}" == "0x0000" ]; then - echo "Test succesfull :white_check_mark:" >> ${GITHUB_STEP_SUMMARY} - else - echo "Test failed :x:" >> ${GITHUB_STEP_SUMMARY} - exit 1 - fi - - name: Test Analog Input Register - run: | - modbusserver=${{steps. modbus-server-address.outputs.ip}} - echo "## Get Analog Input Register" >> ${GITHUB_STEP_SUMMARY} - echo '
' >> ${GITHUB_STEP_SUMMARY} - echo ' Test output details' >> ${GITHUB_STEP_SUMMARY} - echo "" >> ${GITHUB_STEP_SUMMARY} - echo ' ```' >> ${GITHUB_STEP_SUMMARY} - echo " docker run --rm ghcr.io/cybcon/modbus-client/modbus-client:test -s ${modbusserver} -p 5020 -t 4 -r 0 -l 10" >> ${GITHUB_STEP_SUMMARY} - docker run --rm ghcr.io/cybcon/modbus-client/modbus-client:test -s ${modbusserver} -p 5020 -t 4 -r 0 -l 10 > output.tmp 2>&1 - cat output.tmp | while read line - do - echo " ${line}" >> ${GITHUB_STEP_SUMMARY} - done - echo ' ```' >> ${GITHUB_STEP_SUMMARY} - echo '
' >> ${GITHUB_STEP_SUMMARY} - echo "" >> ${GITHUB_STEP_SUMMARY} - # analyze output - RESULT=$(cat output.tmp | grep ^30002 | head -1 | awk '{print $2}') - if [ "${RESULT}" == "0x0000" ]; then - echo "Test succesfull :white_check_mark:" >> ${GITHUB_STEP_SUMMARY} - else - echo "Test failed :x:" >> ${GITHUB_STEP_SUMMARY} - exit 1 - fi - - scan: - name: Container vulnerability scan - needs: container-build - uses: cybcon/github_workflows/.github/workflows/container-vulnerability-scan.yaml@v1.4.0 - with: - image_name: container-build:test - image_artifact_filename: container.tar - image_artifact_name: container-build - login_dockerhub: false - trivy_tag: latest + container-image-build-validation: + uses: cybcon/github_workflows/.github/workflows/container-image-build-validation.yaml@v2.1.0 diff --git a/.github/workflows/pre-commit.yaml b/.github/workflows/pre-commit.yaml index 101fee6..50a82f0 100644 --- a/.github/workflows/pre-commit.yaml +++ b/.github/workflows/pre-commit.yaml @@ -3,8 +3,7 @@ on: pull_request: push: branches: - - master - main jobs: pre-commit: - uses: cybcon/github_workflows/.github/workflows/pre-commit.yaml@v1.4.0 + uses: cybcon/github_workflows/.github/workflows/pre-commit.yaml@v2.1.0 diff --git a/.github/workflows/release-from-label.yaml b/.github/workflows/release-from-label.yaml index 714ed98..33bc6de 100644 --- a/.github/workflows/release-from-label.yaml +++ b/.github/workflows/release-from-label.yaml @@ -5,4 +5,4 @@ on: - closed jobs: release: - uses: cybcon/github_workflows/.github/workflows/release-from-label.yaml@v1.4.0 + uses: cybcon/github_workflows/.github/workflows/release-from-label.yaml@v2.1.0 diff --git a/.github/workflows/release-label-validation.yaml b/.github/workflows/release-label-validation.yaml index 3ad8986..7d618a2 100644 --- a/.github/workflows/release-label-validation.yaml +++ b/.github/workflows/release-label-validation.yaml @@ -10,4 +10,4 @@ on: - unlabeled jobs: release-label-validation: - uses: cybcon/github_workflows/.github/workflows/release-label-validation.yaml@v1.4.0 + uses: cybcon/github_workflows/.github/workflows/release-label-validation.yaml@v2.1.0 diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index 1a218c1..c064429 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -1,20 +1,27 @@ repos: - repo: https://github.com/pre-commit/pre-commit-hooks - rev: v5.0.0 + rev: v6.0.0 hooks: - id: fix-byte-order-marker + - id: check-ast - id: check-json - id: check-yaml + - id: debug-statements - id: end-of-file-fixer - id: trailing-whitespace + - id: requirements-txt-fixer - id: mixed-line-ending args: ['--fix=lf'] description: Forces to replace line ending by the UNIX 'lf' character - id: detect-aws-credentials args: ['--allow-missing-credentials'] - id: detect-private-key + - repo: https://github.com/asottile/pyupgrade + rev: v3.21.2 + hooks: + - id: pyupgrade - repo: https://github.com/myint/autoflake - rev: v2.3.1 + rev: v2.3.3 hooks: - id: autoflake args: @@ -22,11 +29,11 @@ repos: - --remove-unused-variables - --remove-all-unused-imports - repo: https://github.com/hadolint/hadolint - rev: v2.12.0 + rev: v2.14.0 hooks: - id: hadolint-docker - repo: https://github.com/charliermarsh/ruff-pre-commit - rev: v0.8.4 + rev: v0.15.20 hooks: - id: ruff args: @@ -34,7 +41,7 @@ repos: - '--fix' - '--exit-non-zero-on-fix' - repo: https://github.com/pycqa/isort - rev: 5.13.2 + rev: 8.0.1 hooks: - id: isort name: isort (python) @@ -43,8 +50,12 @@ repos: - black - '--filter-files' - repo: https://github.com/psf/black - rev: 24.10.0 + rev: 26.5.1 hooks: - id: black args: - '--line-length=120' + - repo: https://github.com/rhysd/actionlint + rev: v1.7.11 + hooks: + - id: actionlint diff --git a/.tool-versions b/.tool-versions index df76196..540fb7a 100644 --- a/.tool-versions +++ b/.tool-versions @@ -1 +1,2 @@ -pre-commit 4.0.1 +pre-commit 4.6.0 +python 3.14.6 diff --git a/.vscode/settings.json b/.vscode/settings.json new file mode 100644 index 0000000..2fb1fda --- /dev/null +++ b/.vscode/settings.json @@ -0,0 +1,3 @@ +{ + "python-envs.defaultEnvManager": "ms-python.python:system" +} diff --git a/CODE_OF_CONDUCT.md b/CODE_OF_CONDUCT.md new file mode 100644 index 0000000..420b548 --- /dev/null +++ b/CODE_OF_CONDUCT.md @@ -0,0 +1,128 @@ +# Contributor Covenant Code of Conduct + +## Our Pledge + +We as members, contributors, and leaders pledge to make participation in our +community a harassment-free experience for everyone, regardless of age, body +size, visible or invisible disability, ethnicity, sex characteristics, gender +identity and expression, level of experience, education, socio-economic status, +nationality, personal appearance, race, religion, or sexual identity +and orientation. + +We pledge to act and interact in ways that contribute to an open, welcoming, +diverse, inclusive, and healthy community. + +## Our Standards + +Examples of behavior that contributes to a positive environment for our +community include: + +* Demonstrating empathy and kindness toward other people +* Being respectful of differing opinions, viewpoints, and experiences +* Giving and gracefully accepting constructive feedback +* Accepting responsibility and apologizing to those affected by our mistakes, + and learning from the experience +* Focusing on what is best not just for us as individuals, but for the + overall community + +Examples of unacceptable behavior include: + +* The use of sexualized language or imagery, and sexual attention or + advances of any kind +* Trolling, insulting or derogatory comments, and personal or political attacks +* Public or private harassment +* Publishing others' private information, such as a physical or email + address, without their explicit permission +* Other conduct which could reasonably be considered inappropriate in a + professional setting + +## Enforcement Responsibilities + +Community leaders are responsible for clarifying and enforcing our standards of +acceptable behavior and will take appropriate and fair corrective action in +response to any behavior that they deem inappropriate, threatening, offensive, +or harmful. + +Community leaders have the right and responsibility to remove, edit, or reject +comments, commits, code, wiki edits, issues, and other contributions that are +not aligned to this Code of Conduct, and will communicate reasons for moderation +decisions when appropriate. + +## Scope + +This Code of Conduct applies within all community spaces, and also applies when +an individual is officially representing the community in public spaces. +Examples of representing our community include using an official e-mail address, +posting via an official social media account, or acting as an appointed +representative at an online or offline event. + +## Enforcement + +Instances of abusive, harassing, or otherwise unacceptable behavior may be +reported to the community leaders responsible for enforcement at +e-mail notification. +All complaints will be reviewed and investigated promptly and fairly. + +All community leaders are obligated to respect the privacy and security of the +reporter of any incident. + +## Enforcement Guidelines + +Community leaders will follow these Community Impact Guidelines in determining +the consequences for any action they deem in violation of this Code of Conduct: + +### 1. Correction + +**Community Impact**: Use of inappropriate language or other behavior deemed +unprofessional or unwelcome in the community. + +**Consequence**: A private, written warning from community leaders, providing +clarity around the nature of the violation and an explanation of why the +behavior was inappropriate. A public apology may be requested. + +### 2. Warning + +**Community Impact**: A violation through a single incident or series +of actions. + +**Consequence**: A warning with consequences for continued behavior. No +interaction with the people involved, including unsolicited interaction with +those enforcing the Code of Conduct, for a specified period of time. This +includes avoiding interactions in community spaces as well as external channels +like social media. Violating these terms may lead to a temporary or +permanent ban. + +### 3. Temporary Ban + +**Community Impact**: A serious violation of community standards, including +sustained inappropriate behavior. + +**Consequence**: A temporary ban from any sort of interaction or public +communication with the community for a specified period of time. No public or +private interaction with the people involved, including unsolicited interaction +with those enforcing the Code of Conduct, is allowed during this period. +Violating these terms may lead to a permanent ban. + +### 4. Permanent Ban + +**Community Impact**: Demonstrating a pattern of violation of community +standards, including sustained inappropriate behavior, harassment of an +individual, or aggression toward or disparagement of classes of individuals. + +**Consequence**: A permanent ban from any sort of public interaction within +the community. + +## Attribution + +This Code of Conduct is adapted from the [Contributor Covenant][homepage], +version 2.0, available at +[https://www.contributor-covenant.org/version/2/0/code_of_conduct.html](https://www.contributor-covenant.org/version/2/0/code_of_conduct.html). + +Community Impact Guidelines were inspired by [Mozilla's code of conduct +enforcement ladder](https://github.com/mozilla/diversity). + +[homepage]: [https://www.contributor-covenant.org](https://www.contributor-covenant.org) + +For answers to common questions about this code of conduct, see the FAQ at +[https://www.contributor-covenant.org/faq](https://www.contributor-covenant.org/faq). Translations are available at +[https://www.contributor-covenant.org/translations](https://www.contributor-covenant.org/translations). diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md new file mode 100644 index 0000000..8457b0b --- /dev/null +++ b/CONTRIBUTING.md @@ -0,0 +1,46 @@ +# How to contribute to modbus-client + +## **Did you find a bug?** + +* **Do not open up a GitHub issue if the bug is a security vulnerability + in modbus-client**, and instead write me a mail to [info@oberdorf-itc.de](mailto:info@oberdorf-itc.de). + +* **Ensure the bug was not already reported** by searching on GitHub under [Issues](https://github.com/cybcon/docker.modbus-client/issues). + +* If you're unable to find an open issue addressing the problem, [open a new one](https://github.com/cybcon/docker.modbus-client/issues/new). Be sure to include a **title and clear description**, as much relevant information as possible, and a **code sample** or an **executable test case** demonstrating the expected behavior that is not occurring. + +## **Did you write a patch that fixes a bug?** + +* Open a new GitHub pull request with the patch. + +* Ensure the PR description clearly describes the problem and solution. Include the relevant issue number if applicable. + +* All commits needs to have a valid GPG signature + +* All pull request checks have to pass successfully + +* If using 3rd party components, the licence needs to be compatible with the license of this project + +## **Did you fix whitespace, format code, or make a purely cosmetic patch?** + +Changes that are cosmetic in nature and do not add anything substantial to the stability, functionality, or testability of the application will generally not be accepted. + +## **Do you intend to add a new feature or change an existing one?** + +* Open a new GitHub pull request with the patch. + +* Ensure the PR description clearly describes the new feature or the change. Include the relevant issue number if applicable. + +* All commits needs to have a valid GPG signature + +* All pull request checks have to pass successfully + +* If using 3rd party components, the licence needs to be compatible with the license of this project + +## **Do you have questions about the source code?** + +* Write me a mail to [info@oberdorf-itc.de](mailto:info@oberdorf-itc.de). + +Thanks! :heart: :heart: :heart: + +Michael diff --git a/Dockerfile b/Dockerfile index a6cb30a..478ad7d 100644 --- a/Dockerfile +++ b/Dockerfile @@ -1,8 +1,8 @@ -FROM alpine:3.23.2 AS base +FROM alpine:3.24.1 AS base RUN apk upgrade --available --no-cache --update \ && apk add --no-cache --update \ - python3=3.12.12-r0 \ - py3-pip=25.1.1-r1 \ + python3=3.14.5-r0 \ + py3-pip=26.1.2-r0 \ # Cleanup APK && rm -rf /var/cache/apk/* /tmp/* /var/tmp/* @@ -11,14 +11,15 @@ RUN apk upgrade --available --no-cache --update \ # Compiling python modules FROM base AS builder RUN apk add --no-cache --update \ - g++=15.2.0-r2 \ - python3-dev=3.12.12-r0 \ + g++=15.2.0-r5 \ + python3-dev=3.14.5-r0 \ && ln -s /usr/include/locale.h /usr/include/xlocale.h COPY --chown=root:root FloatToHex /FloatToHex WORKDIR /FloatToHex -RUN python3 setup.py install +RUN pip3 install --no-cache-dir -r /FloatToHex/requirements.txt --break-system-packages \ + && python3 setup.py install @@ -28,12 +29,12 @@ FROM base LABEL maintainer="Michael Oberdorf IT-Consulting " LABEL site.local.program.version="1.0.17" -COPY --from=builder /usr/lib/python3.12/site-packages /usr/lib/python3.12/site-packages +COPY --from=builder /usr/lib/python3.14/site-packages /usr/lib/python3.14/site-packages RUN apk add --no-cache --update \ - libstdc++=15.2.0-r2 \ - py3-wheel=0.46.1-r0 \ - py3-pandas=2.3.3-r0 + libstdc++=15.2.0-r5 \ + py3-wheel=0.47.0-r0 \ + py3-pandas=3.0.3-r0 COPY --chown=root:root /src / diff --git a/FloatToHex/README.md b/FloatToHex/README.md index 0fcae3e..2e7389e 100644 --- a/FloatToHex/README.md +++ b/FloatToHex/README.md @@ -2,34 +2,38 @@ The software was taken from site: https://gregstoll.com/~gregstoll/floattohex/ -## Contributor: +## Contributor Gregory Stoll https://gregstoll.com/ -# Synopsis +## Synopsis ```python import FloatToHex float = 29.625 ``` -# store float in 4 byte (32 bit) single precision (IEEE 754 binary32) +### store float in 4 byte (32 bit) single precision (IEEE 754 binary32) + ```python my_32bit_int = FloatToHex.floattohex(float) ``` -# recover float from IEEE 754 binary32 +### recover float from IEEE 754 binary32 + ```python print(FloatToHex.hextofloat(my_32bit_int)) ``` -# store float in 8 byte (64 bit) double precision (IEEE 754 binary64) +### store float in 8 byte (64 bit) double precision (IEEE 754 binary64) + ```python my_64bit_int = FloatToHex.doubletohex(float) ``` -# recover float from IEEE 754 binary64 +### recover float from IEEE 754 binary64 + ```python print(FloatToHex.hextodouble(my_64bit_int)) ``` diff --git a/FloatToHex/requirements.txt b/FloatToHex/requirements.txt new file mode 100644 index 0000000..fcc1a15 --- /dev/null +++ b/FloatToHex/requirements.txt @@ -0,0 +1 @@ +Setuptools >=83 diff --git a/FloatToHex/setup.py b/FloatToHex/setup.py index 531874c..efee9ad 100644 --- a/FloatToHex/setup.py +++ b/FloatToHex/setup.py @@ -1,10 +1,10 @@ #!/usr/bin/python3 -# -*- coding: utf-8 -*- # setup.py sdist to create a package which can be uploaded to PyPi registry (but need more information) # setup.py install to install the package - needs C compiler (vcvarsall.bat on windows) -from distutils.core import Extension, setup +# from distutils.core import Extension, setup # migrate to python 3.14 +from setuptools import Extension, setup FloatToHexModule = Extension("FloatToHex", sources=["floattohexmodule.c"]) diff --git a/LICENSE b/LICENSE index 04c0049..2186675 100644 --- a/LICENSE +++ b/LICENSE @@ -1,6 +1,6 @@ MIT License -Copyright (c) 2020-2025 Michael Oberdorf IT-Consulting +Copyright (c) 2020-2026 Michael Oberdorf IT-Consulting Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal diff --git a/README.md b/README.md index de5c18c..5dccb96 100644 --- a/README.md +++ b/README.md @@ -15,16 +15,15 @@ Container Registry: [DockerHub](https://hub.docker.com/r/oitc/modbus-client) [![][github-forks-shield]][github-forks-link] [![][github-issues-shield]][github-issues-link] [![][github-license-shield]][github-license-link] - [![][docker-release-shield]][docker-release-link] [![][docker-pulls-shield]][docker-pulls-link] [![][docker-stars-shield]][docker-stars-link] [![][docker-size-shield]][docker-size-link] +## Supported tags and respective `Dockerfile` links -# Supported tags and respective `Dockerfile` links - -* [`latest`, `1.0.17`](https://github.com/cybcon/modbus-client/blob/v1.0.17/Dockerfile) +* [`latest`, `1.1.0`](https://github.com/cybcon/modbus-client/blob/v1.1.0/Dockerfile) +* [`1.0.17`](https://github.com/cybcon/modbus-client/blob/v1.0.17/Dockerfile) * [`1.0.16`](https://github.com/cybcon/modbus-client/blob/v1.0.16/Dockerfile) * [`1.0.15`](https://github.com/cybcon/modbus-client/blob/v1.0.15/Dockerfile) * [`1.0.14`](https://github.com/cybcon/modbus-client/blob/v1.0.14/Dockerfile) @@ -32,25 +31,23 @@ Container Registry: [DockerHub](https://hub.docker.com/r/oitc/modbus-client) * [`1.0.12`](https://github.com/cybcon/modbus-client/blob/v1.0.12/Dockerfile) * [`1.0.11`](https://github.com/cybcon/modbus-client/blob/v1.0.11/Dockerfile) - -# What is Modbus TCP Client? +## What is Modbus TCP Client? The Modbus TCP Client is a command line tool, written in python to read and interpret Modbus registers. The Modbus specification can be found here: [PDF](https://modbus.org/docs/Modbus_Application_Protocol_V1_1b3.pdf) - -# QuickStart with Modbus TCP Client and Docker +## QuickStart with Modbus TCP Client and Docker Step - 1 : Pull the Modbus TCP Client -``` +```bash docker pull oitc/modbus-client ``` Step - 2 : Run the Modbus TCP Client to scan your Modbus Server Registers -``` +```bash docker run --rm oitc/modbus-client:latest [options] usage: modbus_client.py [-h] [-s SLAVE] [-p PORT] [-i SLAVEID] @@ -83,10 +80,11 @@ optional arguments: -d, --debug Enable debug output ``` -# Examples -## Read Analog Input Register +## Examples -``` +### Read Analog Input Register + +```bash docker run --rm oitc/modbus-client:latest -s 192.168.58.70 -p 1503 -t 4 -r 0 -l 10 HEX16 UINT16 INT16 BIT HEX32 FLOAT32 register @@ -102,9 +100,9 @@ register 30009 0x0032 50 50 0000000000110010 0x00320074 0.000000 ``` -## Discrete Discrete Input Contacts +### Discrete Discrete Input Contacts -``` +```bash docker run --rm test:latest -s 192.168.57.10 -p 5020 -t 2 -r 0 -l 3 BIT BOOL register @@ -113,15 +111,15 @@ register 10002 1 True ``` -# Donate -I would appreciate a small donation to support the further development of my open source projects. +## Donate -Donate with PayPal +I would appreciate a small donation to support the further development of my open source projects. +[![Donate with PayPal][donate-paypal-button]][donate-paypal-link] -# License +## License -Copyright (c) 2020-2024 Michael Oberdorf IT-Consulting +Copyright (c) 2020-2026 Michael Oberdorf IT-Consulting Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal @@ -150,6 +148,8 @@ SOFTWARE. [docker-size-shield]: https://img.shields.io/docker/image-size/oitc/modbus-client?color=369eff&labelColor=black&style=flat-square [docker-stars-link]: https://hub.docker.com/r/oitc/modbus-client [docker-stars-shield]: https://img.shields.io/docker/stars/oitc/modbus-client?color=45cc11&labelColor=black&style=flat-square +[donate-paypal-button]: https://raw.githubusercontent.com/cybcon/paypal-donate-button/refs/heads/master/paypal-donate-button_200x77.png +[donate-paypal-link]: https://www.paypal.com/donate/?hosted_button_id=BHGJGGUS6RH44 [github-action-release-link]: https://github.com/cybcon/modbus-client/actions/workflows/release-from-label.yaml [github-action-release-shield]: https://img.shields.io/github/actions/workflow/status/cybcon/modbus-client/release-from-label.yaml?label=release&labelColor=black&logo=githubactions&logoColor=white&style=flat-square [github-action-test-link]: https://github.com/cybcon/modbus-client/actions/workflows/container-image-build-validation.yaml diff --git a/SECURITY.md b/SECURITY.md new file mode 100644 index 0000000..933f524 --- /dev/null +++ b/SECURITY.md @@ -0,0 +1,23 @@ +# Security Policy + +## Supported Versions + +Due to the small size of this project, only the latest version receives security updates and patches. + +| Version | Supported | +| ------- | ------------------ | +| Latest | :white_check_mark: | +| Older | :x: | + +## Reporting a Vulnerability + +**Please do not open a GitHub issue for security vulnerabilities.** + +Instead, please report security vulnerabilities by sending an email to [info@oberdorf-itc.de](mailto:info@oberdorf-itc.de) with: + +- A description of the vulnerability +- Steps to reproduce (if applicable) +- Potential impact +- Any suggested fixes (optional) + +For more details on how to contribute to this project, please refer to [CONTRIBUTING.md](CONTRIBUTING.md). diff --git a/src/app/modbus_client.py b/src/app/modbus_client.py index 6398adb..b39c059 100644 --- a/src/app/modbus_client.py +++ b/src/app/modbus_client.py @@ -1,23 +1,24 @@ -# -*- coding: utf-8 -*- """ -############################################################################### -# Modbus TCP client script for debugging -# Author: Michael Oberdorf IT-Consulting -# Datum: 2020-05-20 -# Last modified by: Michael Oberdorf -# Last modified at: 2025-12-28 -############################################################################### +Modbus TCP client script for debugging +Author: Michael Oberdorf IT-Consulting +Datum: 2020-05-20 +Last modified by: Michael Oberdorf +Last modified at: 2026-07-06 """ + import argparse import logging import sys import pandas as pd -from pymodbus.client.sync import ModbusTcpClient as ModbusClient +from pymodbus.client import ModbusTcpClient as ModbusClient import FloatToHex -VERSION = "1.0.17" +__status__ = "production" +__date__ = "2026-07-06" +__version_info__ = ("1", "1", "0") +__version__ = ".".join(__version_info__) DEBUG = False """ ############################################################################### @@ -107,7 +108,7 @@ def parse_modbus_result(registers: list, startRegister: int, readLength: int, va log.setLevel(logging.INFO) # Parsing command line arguments -parser = argparse.ArgumentParser(description="Modbus TCP Client v" + VERSION) +parser = argparse.ArgumentParser(description="Modbus TCP Client v" + __version__) group = parser.add_argument_group() group.add_argument( "-s", "--slave", help="Hostname or IP address of the Modbus TCP slave (default: 127.0.0.1)", default="127.0.0.1" @@ -181,7 +182,7 @@ def parse_modbus_result(registers: list, startRegister: int, readLength: int, va # start the master and connect to slave if DEBUG: - print("Starting Modbus TCP master client, v" + str(VERSION)) + print(f"Starting Modbus TCP master client, v{__version__}") print("Trying to connect to slave: " + str(args.slave) + ":" + str(args.port)) print( "Query with slave id: " @@ -210,13 +211,13 @@ def parse_modbus_result(registers: list, startRegister: int, readLength: int, va # read the registers, dependent on the requested type if args.registerType == 1: - rr = client.read_coils(args.register, args.length, unit=args.slaveid) + rr = client.read_coils(address=args.register, count=args.length, device_id=args.slaveid) elif args.registerType == 2: - rr = client.read_discrete_inputs(args.register, args.length, unit=args.slaveid) + rr = client.read_discrete_inputs(address=args.register, count=args.length, device_id=args.slaveid) elif args.registerType == 3: - rr = client.read_holding_registers(args.register, args.length, unit=args.slaveid) + rr = client.read_holding_registers(address=args.register, count=args.length, device_id=args.slaveid) elif args.registerType == 4: - rr = client.read_input_registers(args.register, args.length, unit=args.slaveid) + rr = client.read_input_registers(address=args.register, count=args.length, device_id=args.slaveid) if rr.isError(): log.error("Error while querying Modbus TCP slave!") client.close() diff --git a/src/requirements.txt b/src/requirements.txt index fee656c..9aa876f 100644 --- a/src/requirements.txt +++ b/src/requirements.txt @@ -1 +1 @@ -pymodbus >= 2, < 3 +pymodbus >= 3.13.1, < 4