Compare commits

..

No commits in common. "2a794d5a5188c0757f972595838ef92412320f3a" and "418bcb59e83a0bd5c1146590bb901c77146723e4" have entirely different histories.

13 changed files with 37 additions and 122 deletions

View File

@ -12,10 +12,9 @@ exclude =
__pycache__,
build,
dist,
.conda,
.venv,
venv,
docs/source/api
.conda
.venv
venv
# Enable specific plugins or options
# Example: Enabling flake8-docstrings

View File

@ -27,13 +27,6 @@ jobs:
run: |
python -m pip install --upgrade pip
python -m pip install -e .[dev]
if [ "${{ matrix.python-version }}" = "3.13" ]; then
python -m pip install cffconvert
fi
- name: Validate CITATION.cff
if: ${{ matrix.python-version == '3.13' }}
run: cffconvert --validate
- name: Lint code with flake8
run: flake8

View File

@ -9,7 +9,7 @@ permissions:
contents: write
jobs:
build:
build-and-deploy:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
@ -29,24 +29,8 @@ jobs:
rm ./source/*.rst
make html
touch ./build/html/.nojekyll
mkdir -p ./build/html/_autogenerated
cp ./build/html/api/* ./build/html/_autogenerated/
- name: Upload artifact
uses: actions/upload-pages-artifact@v3
with:
path: docs/build/html
deploy:
needs: build
runs-on: ubuntu-latest
permissions:
contents: read
pages: write
id-token: write
environment:
name: github-pages
url: ${{ steps.deployment.outputs.page_url }}
steps:
- name: Deploy to GitHub Pages
id: deployment
uses: actions/deploy-pages@v4
uses: JamesIves/github-pages-deploy-action@v4
with:
branch: gh-pages
folder: docs/build/html

View File

@ -10,10 +10,6 @@ jobs:
name: Build and publish
runs-on: ubuntu-latest
environment:
name: pypi
url: https://pypi.org/project/${{ github.event.repository.name }}/
steps:
- uses: actions/checkout@v3

2
.gitignore vendored
View File

@ -70,7 +70,7 @@ instance/
# Sphinx documentation
docs/_build/
docs/source/api/
docs/source/_autogenerated/
# Autogenerated documentation
docs/source/modules.md

View File

@ -1,16 +1,15 @@
cff-version: 1.2.0
message: "If you use this software, please cite it as below."
title: pyhoff
abstract: The pyhoff package allows easy accessing of Beckhoff and Wago terminals with python over ModBus TCP
authors:
- family-names: Kruse
given-names: Nicolas
orcid: "https://orcid.org/0000-0001-6758-2269"
version: v1.1.2
date-released: "2025-08-04"
identifiers:
- description: This is the collection of archived snapshots of all versions of pyhoff
type: doi
value: "10.5281/zenodo.16740202"
license: MIT
version: 1.1.0
#date-released: "2025-04-01"
#identifiers:
# - description: This is the collection of archived snapshots of all versions of My Research Software
# type: doi
# value: "10.5281/"
license: MIT License
repository-code: "https://github.com/Nonannet/pyhoff"

View File

@ -1,5 +1,6 @@
# Pyhoff
## Description
The pyhoff package allows you to read and write the most common
Beckhoff and WAGO bus terminals ("Busklemmen") using the Ethernet bus
coupler ("Busskoppler") BK9000, BK9050, BK9100, or WAGO 750_352
@ -54,62 +55,6 @@ bk.select(KL4002, 0).set_voltage(1, 4.2)
```
## Adding new terminals
The package comes with automatic generated code stubs for nearly all
terminals. These stubs are not tested with hardware but for most
digital IO terminals the code should be fully functional.
Such a stub looks like this:
```python
# From ./src/pyhoff/devices.py:
class KL2442(DigitalOutputTerminal):
"""
KL2442: 2-channel digital output, 24 V DC, 2 x 4 A/1 x 8 A
(Automatic generated stub)
"""
parameters = {'output_bit_width': 2, 'input_bit_width': 0}
```
For analog IO terminals the stubs are functional as well,
but they provide only a generic `read_channel_word` and
`read_normalized` function (for inputs) without scaling the
values to voltages, currents or temperatures. For better usability
they might be extended with functions. Based on the stub the
extension could look like this:
```python
from pyhoff.devices import KL3054 as KL3054_stub
class KL3054(KL3054_stub):
def read_current(self, channel: int) -> float:
return self.read_normalized(channel) * 16.0 + 4.0
```
Or for contributing to the pyhoff package, the existing stub
code can be updated like this:
```python
# From ./src/pyhoff/devices.py:
class KL3054(AnalogInputTerminal):
"""
KL3054: 4x analog input 4...20 mA 12 Bit single-ended
"""
# Input: 4 x 16 Bit Daten (optional 4x 8 Bit Control/Status)
parameters = {'input_word_width': 4}
def read_current(self, channel: int) -> float:
"""
Read the current value from a specific channel.
Args:
channel: The channel number to read from.
Returns:
The current value in mA.
"""
return self.read_normalized(channel) * 16.0 + 4.0
```
## Contributing
Other analog and digital IO terminals are easy to complement. Contributions are welcome!
Please open an issue or submit a pull request on GitHub.
@ -117,24 +62,32 @@ Please open an issue or submit a pull request on GitHub.
## Developer Guide
To get started with developing the `pyhoff` package, follow these steps:
1. First, clone the repository to your local machine using Git:
1. **Clone the Repository**
First, clone the repository to your local machine using Git:
```bash
git clone https://github.com/Nonannet/pyhoff.git
cd pyhoff
```
2. It is recommended to use a virtual environment:
2. **Set Up a Virtual Environment**
It is recommended to use a virtual environment to manage dependencies. You can create one using `venv`:
```bash
python -m venv .venv
source .venv/bin/activate # On Windows/Powershell use `.\venv\Scripts\Activate.ps1`
python -m venv venv
source venv/bin/activate # On Windows use `venv\Scripts\activate`
```
3. Install pyhoff from source plus the development dependencies:
3. **Install Dev Dependencies**
Install pyhoff from source plus the dependencies required for development using `pip`:
```bash
pip install -e .[dev]
```
4. Ensure that everything is set up correctly by running the tests:
4. **Run Tests**
Ensure that everything is set up correctly by running the tests:
```bash
pytest
```

View File

@ -24,7 +24,7 @@ def write_classes(f: TextIOWrapper, patterns: list[str], module_name: str, title
write_dochtree(f, title, classes)
for cls in classes:
with open(f'docs/source/api/{cls}.md', 'w') as f2:
with open(f'docs/source/_autogenerated/{cls}.md', 'w') as f2:
f2.write(f'# {module_name}.{cls}\n')
f2.write('```{eval-rst}\n')
f2.write(f'.. autoclass:: {module_name}.{cls}\n')
@ -52,9 +52,9 @@ def write_dochtree(f: TextIOWrapper, title: str, items: list[str]):
if __name__ == "__main__":
# Ensure the output directory exists
os.makedirs('docs/source/api', exist_ok=True)
os.makedirs('docs/source/_autogenerated', exist_ok=True)
with open('docs/source/api/index.md', 'w') as f:
with open('docs/source/_autogenerated/index.md', 'w') as f:
f.write('# Classes and Modules\n\n')
write_classes(f, ['BK*', 'WAGO_750_352'], 'pyhoff.devices', title='Bus coupler',

View File

@ -1,8 +1,7 @@
```{toctree}
:maxdepth: 1
:hidden:
api/index
repo
_autogenerated/index
```
```{include} ../../README.md

View File

@ -1,3 +0,0 @@
# Code repository
Code repository is on GitHub: [github.com/Nonannet/pyhoff](https://github.com/Nonannet/pyhoff).

View File

@ -1,6 +1,6 @@
[project]
name = "pyhoff"
version = "1.1.2"
version = "1.1.1"
authors = [
{ name="Nicolas Kruse", email="nicolas.kruse@nonan.net" },
]
@ -25,9 +25,6 @@ build-backend = "setuptools.build_meta"
[tool.setuptools.packages.find]
where = ["src"]
[tool.setuptools.package-data]
pyhoff = ["py.typed"]
[project.optional-dependencies]
dev = [
"pytest", "flake8", "mypy"

View File

@ -137,10 +137,9 @@ class AnalogInputTerminal(BusTerminal):
Args:
channel: The channel number (1 based index) to read from.
error_value: Value that is returned in case the modbus read command fails.
Returns:
The read word value or provided error_value if read failed.
The read word value.
Raises:
Exception: If the word offset or count is out of range.
@ -175,7 +174,6 @@ class AnalogOutputTerminal(BusTerminal):
Args:
channel: The channel number (1 based index) to read from.
error_value: Value that is returned in case the modbus read command fails.
Returns:
The read word value or provided error_value if read failed.

View File