mirror of https://github.com/Nonannet/pyhoff.git
Compare commits
No commits in common. "main" and "v1.1.1" have entirely different histories.
7
.flake8
7
.flake8
|
@ -12,10 +12,9 @@ exclude =
|
||||||
__pycache__,
|
__pycache__,
|
||||||
build,
|
build,
|
||||||
dist,
|
dist,
|
||||||
.conda,
|
.conda
|
||||||
.venv,
|
.venv
|
||||||
venv,
|
venv
|
||||||
docs/source/api
|
|
||||||
|
|
||||||
# Enable specific plugins or options
|
# Enable specific plugins or options
|
||||||
# Example: Enabling flake8-docstrings
|
# Example: Enabling flake8-docstrings
|
||||||
|
|
|
@ -27,13 +27,6 @@ jobs:
|
||||||
run: |
|
run: |
|
||||||
python -m pip install --upgrade pip
|
python -m pip install --upgrade pip
|
||||||
python -m pip install -e .[dev]
|
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
|
- name: Lint code with flake8
|
||||||
run: flake8
|
run: flake8
|
||||||
|
|
|
@ -9,7 +9,7 @@ permissions:
|
||||||
contents: write
|
contents: write
|
||||||
|
|
||||||
jobs:
|
jobs:
|
||||||
build:
|
build-and-deploy:
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@v4
|
- uses: actions/checkout@v4
|
||||||
|
@ -17,36 +17,21 @@ jobs:
|
||||||
uses: actions/setup-python@v3
|
uses: actions/setup-python@v3
|
||||||
with:
|
with:
|
||||||
python-version: "3.x"
|
python-version: "3.x"
|
||||||
- name: Install package and dependencies
|
- name: Install dependencies
|
||||||
run: pip install .[doc_build]
|
run: pip install sphinx sphinx_rtd_theme sphinx-autodoc-typehints myst-parser
|
||||||
- name: Generate Class List
|
- name: Generate Class List
|
||||||
run: python ./docs/source/generate_class_list.py
|
run: |
|
||||||
|
pip install .
|
||||||
|
python ./docs/source/generate_class_list.py
|
||||||
- name: Build Docs
|
- name: Build Docs
|
||||||
run: |
|
run: |
|
||||||
cp LICENSE docs/source/LICENSE.md
|
|
||||||
cd docs
|
cd docs
|
||||||
sphinx-apidoc -o ./source/ ../src/ -M --no-toc
|
sphinx-apidoc -o ./source/ ../src/ -M --no-toc
|
||||||
rm ./source/*.rst
|
rm ./source/*.rst
|
||||||
make html
|
make html
|
||||||
touch ./build/html/.nojekyll
|
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
|
- name: Deploy to GitHub Pages
|
||||||
id: deployment
|
uses: JamesIves/github-pages-deploy-action@v4
|
||||||
uses: actions/deploy-pages@v4
|
with:
|
||||||
|
branch: gh-pages
|
||||||
|
folder: docs/build/html
|
||||||
|
|
|
@ -10,10 +10,6 @@ jobs:
|
||||||
name: Build and publish
|
name: Build and publish
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
|
|
||||||
environment:
|
|
||||||
name: pypi
|
|
||||||
url: https://pypi.org/project/${{ github.event.repository.name }}/
|
|
||||||
|
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@v3
|
- uses: actions/checkout@v3
|
||||||
|
|
||||||
|
|
|
@ -70,7 +70,6 @@ instance/
|
||||||
|
|
||||||
# Sphinx documentation
|
# Sphinx documentation
|
||||||
docs/_build/
|
docs/_build/
|
||||||
docs/source/api/
|
|
||||||
|
|
||||||
# Autogenerated documentation
|
# Autogenerated documentation
|
||||||
docs/source/modules.md
|
docs/source/modules.md
|
||||||
|
|
15
CITATION.cff
15
CITATION.cff
|
@ -1,16 +1,15 @@
|
||||||
cff-version: 1.2.0
|
cff-version: 1.2.0
|
||||||
message: "If you use this software, please cite it as below."
|
|
||||||
title: pyhoff
|
title: pyhoff
|
||||||
abstract: The pyhoff package allows easy accessing of Beckhoff and Wago terminals with python over ModBus TCP
|
abstract: The pyhoff package allows easy accessing of Beckhoff and Wago terminals with python over ModBus TCP
|
||||||
authors:
|
authors:
|
||||||
- family-names: Kruse
|
- family-names: Kruse
|
||||||
given-names: Nicolas
|
given-names: Nicolas
|
||||||
orcid: "https://orcid.org/0000-0001-6758-2269"
|
orcid: "https://orcid.org/0000-0001-6758-2269"
|
||||||
version: v1.1.2
|
version: 1.1.0
|
||||||
date-released: "2025-08-04"
|
#date-released: "2025-04-01"
|
||||||
identifiers:
|
#identifiers:
|
||||||
- description: This is the collection of archived snapshots of all versions of pyhoff
|
# - description: This is the collection of archived snapshots of all versions of My Research Software
|
||||||
type: doi
|
# type: doi
|
||||||
value: "10.5281/zenodo.16740202"
|
# value: "10.5281/"
|
||||||
license: MIT
|
license: MIT License
|
||||||
repository-code: "https://github.com/Nonannet/pyhoff"
|
repository-code: "https://github.com/Nonannet/pyhoff"
|
77
README.md
77
README.md
|
@ -1,5 +1,6 @@
|
||||||
# Pyhoff
|
# Pyhoff
|
||||||
|
|
||||||
|
## Description
|
||||||
The pyhoff package allows you to read and write the most common
|
The pyhoff package allows you to read and write the most common
|
||||||
Beckhoff and WAGO bus terminals ("Busklemmen") using the Ethernet bus
|
Beckhoff and WAGO bus terminals ("Busklemmen") using the Ethernet bus
|
||||||
coupler ("Busskoppler") BK9000, BK9050, BK9100, or WAGO 750_352
|
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
|
## Contributing
|
||||||
Other analog and digital IO terminals are easy to complement. Contributions are welcome!
|
Other analog and digital IO terminals are easy to complement. Contributions are welcome!
|
||||||
Please open an issue or submit a pull request on GitHub.
|
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
|
## Developer Guide
|
||||||
To get started with developing the `pyhoff` package, follow these steps:
|
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
|
```bash
|
||||||
git clone https://github.com/Nonannet/pyhoff.git
|
git clone https://github.com/Nonannet/pyhoff.git
|
||||||
cd pyhoff
|
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
|
```bash
|
||||||
python -m venv .venv
|
python -m venv venv
|
||||||
source .venv/bin/activate # On Windows/Powershell use `.\venv\Scripts\Activate.ps1`
|
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
|
```bash
|
||||||
pip install -e .[dev]
|
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
|
```bash
|
||||||
pytest
|
pytest
|
||||||
```
|
```
|
||||||
|
|
|
@ -26,8 +26,7 @@ exclude_patterns = []
|
||||||
# https://www.sphinx-doc.org/en/master/usage/configuration.html#options-for-html-output
|
# https://www.sphinx-doc.org/en/master/usage/configuration.html#options-for-html-output
|
||||||
|
|
||||||
# html_theme = 'alabaster'
|
# html_theme = 'alabaster'
|
||||||
html_theme = 'pydata_sphinx_theme'
|
html_theme = 'sphinx_rtd_theme'
|
||||||
html_static_path = ['_static']
|
html_static_path = ['_static']
|
||||||
|
|
||||||
autodoc_inherit_docstrings = True
|
autodoc_inherit_docstrings = True
|
||||||
autoclass_content = 'both'
|
|
||||||
|
|
|
@ -2,66 +2,42 @@ import importlib
|
||||||
import inspect
|
import inspect
|
||||||
import fnmatch
|
import fnmatch
|
||||||
from io import TextIOWrapper
|
from io import TextIOWrapper
|
||||||
import os
|
|
||||||
|
|
||||||
|
|
||||||
def write_classes(f: TextIOWrapper, patterns: list[str], module_name: str, title: str, description: str = '', exclude: list[str] = []) -> None:
|
def write_classes(f: TextIOWrapper, patterns: list[str], module_name: str, title: str, description: str = '', exclude: list[str] = []) -> None:
|
||||||
"""Write the classes to the file."""
|
|
||||||
module = importlib.import_module(module_name)
|
module = importlib.import_module(module_name)
|
||||||
|
|
||||||
classes = [
|
classes = [
|
||||||
name for name, obj in inspect.getmembers(module, inspect.isclass)
|
name for name, obj in inspect.getmembers(module, inspect.isclass)
|
||||||
if (obj.__module__ == module_name and
|
if (obj.__module__ == module_name and
|
||||||
any(fnmatch.fnmatch(name, pat) for pat in patterns if pat not in exclude) and
|
any(fnmatch.fnmatch(name, pat) for pat in patterns if pat not in exclude) and
|
||||||
(obj.__doc__ and ('(Automatic generated stub)' not in obj.__doc__ or ' digital ' in obj.__doc__)) and
|
obj.__doc__ and '(Automatic generated stub)' not in obj.__doc__)
|
||||||
obj.__doc__ and '(no I/O function)' not in obj.__doc__
|
|
||||||
)
|
|
||||||
]
|
]
|
||||||
|
|
||||||
|
"""Write the classes to the file."""
|
||||||
|
f.write(f'## {title}\n\n')
|
||||||
if description:
|
if description:
|
||||||
f.write(f'{description}\n\n')
|
f.write(f'{description}\n\n')
|
||||||
|
|
||||||
write_dochtree(f, title, classes)
|
|
||||||
|
|
||||||
for cls in classes:
|
for cls in classes:
|
||||||
with open(f'docs/source/api/{cls}.md', 'w') as f2:
|
f.write('```{eval-rst}\n')
|
||||||
f2.write(f'# {module_name}.{cls}\n')
|
f.write(f'.. autoclass:: {module_name}.{cls}\n')
|
||||||
f2.write('```{eval-rst}\n')
|
f.write(' :members:\n')
|
||||||
f2.write(f'.. autoclass:: {module_name}.{cls}\n')
|
f.write(' :undoc-members:\n')
|
||||||
f2.write(' :members:\n')
|
f.write(' :show-inheritance:\n')
|
||||||
f2.write(' :show-inheritance:\n')
|
f.write(' :inherited-members:\n')
|
||||||
f2.write(' :inherited-members:\n')
|
if title != 'Base classes':
|
||||||
if title not in ['Base classes', 'Bus coupler']:
|
f.write(' :exclude-members: select\n')
|
||||||
f2.write(' :exclude-members: select, parameters\n')
|
|
||||||
if 'bus terminals' in title:
|
|
||||||
f2.write(' :class-doc-from: class\n')
|
|
||||||
|
|
||||||
f2.write('```\n\n')
|
|
||||||
|
|
||||||
|
|
||||||
def write_dochtree(f: TextIOWrapper, title: str, items: list[str]):
|
|
||||||
f.write('```{toctree}\n')
|
|
||||||
f.write(':maxdepth: 1\n')
|
|
||||||
f.write(f':caption: {title}:\n')
|
|
||||||
# f.write(':hidden:\n')
|
|
||||||
for text in items:
|
|
||||||
if not text.startswith('_'):
|
|
||||||
f.write(f"{text}\n")
|
|
||||||
f.write('```\n\n')
|
f.write('```\n\n')
|
||||||
|
|
||||||
|
|
||||||
if __name__ == "__main__":
|
with open('docs/source/modules.md', 'w') as f:
|
||||||
# Ensure the output directory exists
|
f.write('# Classes\n\n')
|
||||||
os.makedirs('docs/source/api', exist_ok=True)
|
|
||||||
|
|
||||||
with open('docs/source/api/index.md', 'w') as f:
|
|
||||||
f.write('# Classes and Modules\n\n')
|
|
||||||
|
|
||||||
write_classes(f, ['BK*', 'WAGO_750_352'], 'pyhoff.devices', title='Bus coupler',
|
write_classes(f, ['BK*', 'WAGO_750_352'], 'pyhoff.devices', title='Bus coupler',
|
||||||
description='These classes are bus couplers and are used to connect the IO bus terminals to a Ethernet interface.')
|
description='These classes are bus couplers and are used to connect the IO bus terminals to a Ethernet interface.')
|
||||||
write_classes(f, ['KL*'], 'pyhoff.devices', title='Beckhoff bus terminals')
|
write_classes(f, ['KL*'], 'pyhoff.devices', title='Beckhoff bus terminals')
|
||||||
write_classes(f, ['WAGO*'], 'pyhoff.devices', title='WAGO bus terminals', exclude=['WAGO_750_352'])
|
write_classes(f, ['WAGO*'], 'pyhoff.devices', title='WAGO bus terminals', exclude=['WAGO_750_352'])
|
||||||
write_classes(f, ['*Terminal*'], 'pyhoff.devices', title='Generic bus terminals')
|
|
||||||
write_classes(f, ['*'], 'pyhoff', title='Base classes',
|
write_classes(f, ['*'], 'pyhoff', title='Base classes',
|
||||||
description='These classes are base classes for devices and are typically not used directly.')
|
description='These classes are base classes for devices and are typically not used directly.')
|
||||||
write_classes(f, ['*'], 'pyhoff.modbus', title='Modbus',
|
write_classes(f, ['*'], 'pyhoff.modbus', title='Modbus',
|
||||||
|
|
|
@ -1,8 +1,9 @@
|
||||||
```{toctree}
|
```{toctree}
|
||||||
:maxdepth: 1
|
:maxdepth: 2
|
||||||
:hidden:
|
:caption: Contents:
|
||||||
api/index
|
|
||||||
repo
|
readme
|
||||||
|
modules
|
||||||
```
|
```
|
||||||
|
|
||||||
```{include} ../../README.md
|
```{include} ../../README.md
|
||||||
|
|
|
@ -0,0 +1,2 @@
|
||||||
|
```{include} ../../README.md
|
||||||
|
```
|
|
@ -1,3 +0,0 @@
|
||||||
# Code repository
|
|
||||||
|
|
||||||
Code repository is on GitHub: [github.com/Nonannet/pyhoff](https://github.com/Nonannet/pyhoff).
|
|
|
@ -1,6 +1,6 @@
|
||||||
[project]
|
[project]
|
||||||
name = "pyhoff"
|
name = "pyhoff"
|
||||||
version = "1.1.2"
|
version = "1.1.1"
|
||||||
authors = [
|
authors = [
|
||||||
{ name="Nicolas Kruse", email="nicolas.kruse@nonan.net" },
|
{ name="Nicolas Kruse", email="nicolas.kruse@nonan.net" },
|
||||||
]
|
]
|
||||||
|
@ -25,19 +25,10 @@ build-backend = "setuptools.build_meta"
|
||||||
[tool.setuptools.packages.find]
|
[tool.setuptools.packages.find]
|
||||||
where = ["src"]
|
where = ["src"]
|
||||||
|
|
||||||
[tool.setuptools.package-data]
|
|
||||||
pyhoff = ["py.typed"]
|
|
||||||
|
|
||||||
[project.optional-dependencies]
|
[project.optional-dependencies]
|
||||||
dev = [
|
dev = [
|
||||||
"pytest", "flake8", "mypy"
|
"pytest", "flake8", "mypy"
|
||||||
]
|
]
|
||||||
doc_build = [
|
|
||||||
"sphinx",
|
|
||||||
"pydata_sphinx_theme",
|
|
||||||
"sphinx-autodoc-typehints",
|
|
||||||
"myst-parser"
|
|
||||||
]
|
|
||||||
|
|
||||||
[tool.mypy]
|
[tool.mypy]
|
||||||
files = ["src"]
|
files = ["src"]
|
||||||
|
|
|
@ -137,10 +137,9 @@ class AnalogInputTerminal(BusTerminal):
|
||||||
|
|
||||||
Args:
|
Args:
|
||||||
channel: The channel number (1 based index) to read from.
|
channel: The channel number (1 based index) to read from.
|
||||||
error_value: Value that is returned in case the modbus read command fails.
|
|
||||||
|
|
||||||
Returns:
|
Returns:
|
||||||
The read word value or provided error_value if read failed.
|
The read word value.
|
||||||
|
|
||||||
Raises:
|
Raises:
|
||||||
Exception: If the word offset or count is out of range.
|
Exception: If the word offset or count is out of range.
|
||||||
|
@ -175,7 +174,6 @@ class AnalogOutputTerminal(BusTerminal):
|
||||||
|
|
||||||
Args:
|
Args:
|
||||||
channel: The channel number (1 based index) to read from.
|
channel: The channel number (1 based index) to read from.
|
||||||
error_value: Value that is returned in case the modbus read command fails.
|
|
||||||
|
|
||||||
Returns:
|
Returns:
|
||||||
The read word value or provided error_value if read failed.
|
The read word value or provided error_value if read failed.
|
||||||
|
@ -227,10 +225,19 @@ class BusCoupler():
|
||||||
"""
|
"""
|
||||||
Base class for ModBus TCP bus coupler
|
Base class for ModBus TCP bus coupler
|
||||||
|
|
||||||
|
Args:
|
||||||
|
host: ip or hostname of the bus coupler
|
||||||
|
port: port of the modbus host
|
||||||
|
debug: outputs modbus debug information
|
||||||
|
timeout: timeout for waiting for the device response
|
||||||
|
watchdog: time in seconds after the device sets all outputs to
|
||||||
|
default state. A value of 0 deactivates the watchdog.
|
||||||
|
debug: If True, debug information is printed.
|
||||||
|
|
||||||
Attributes:
|
Attributes:
|
||||||
bus_terminals (list[BusTerminal]): A list of bus terminal classes according to the
|
bus_terminals: A list of bus terminal classes according to the
|
||||||
connected terminals.
|
connected terminals.
|
||||||
modbus (SimpleModbusClient): The underlying modbus client used for the connection.
|
modbus: The underlying modbus client used for the connection.
|
||||||
"""
|
"""
|
||||||
|
|
||||||
def __init__(self, host: str, port: int = 502, bus_terminals: Iterable[type[BusTerminal]] = [],
|
def __init__(self, host: str, port: int = 502, bus_terminals: Iterable[type[BusTerminal]] = [],
|
||||||
|
@ -241,8 +248,6 @@ class BusCoupler():
|
||||||
Args:
|
Args:
|
||||||
host: ip or hostname of the bus coupler
|
host: ip or hostname of the bus coupler
|
||||||
port: port of the modbus host
|
port: port of the modbus host
|
||||||
bus_terminals: list of bus terminal classes for the
|
|
||||||
connected terminals
|
|
||||||
debug: outputs modbus debug information
|
debug: outputs modbus debug information
|
||||||
timeout: timeout for waiting for the device response
|
timeout: timeout for waiting for the device response
|
||||||
watchdog: time in seconds after the device sets all outputs to
|
watchdog: time in seconds after the device sets all outputs to
|
||||||
|
|
|
@ -224,7 +224,7 @@ class KL3054(AnalogInputTerminal):
|
||||||
channel: The channel number to read from.
|
channel: The channel number to read from.
|
||||||
|
|
||||||
Returns:
|
Returns:
|
||||||
The current value in mA.
|
The current value.
|
||||||
"""
|
"""
|
||||||
return self.read_normalized(channel) * 16.0 + 4.0
|
return self.read_normalized(channel) * 16.0 + 4.0
|
||||||
|
|
||||||
|
@ -244,7 +244,7 @@ class KL3042(AnalogInputTerminal):
|
||||||
channel: The channel number to read from.
|
channel: The channel number to read from.
|
||||||
|
|
||||||
Returns:
|
Returns:
|
||||||
The current value in mA.
|
The current value.
|
||||||
"""
|
"""
|
||||||
return self.read_normalized(channel) * 20.0
|
return self.read_normalized(channel) * 20.0
|
||||||
|
|
||||||
|
@ -311,7 +311,7 @@ class KL4002(AnalogOutputTerminal):
|
||||||
|
|
||||||
Args:
|
Args:
|
||||||
channel: The channel number to set.
|
channel: The channel number to set.
|
||||||
value: The voltage value to set in V.
|
value: The voltage value to set.
|
||||||
|
|
||||||
Returns:
|
Returns:
|
||||||
True if the write operation succeeded.
|
True if the write operation succeeded.
|
||||||
|
@ -348,7 +348,7 @@ class KL4132(AnalogOutputTerminal):
|
||||||
|
|
||||||
Args:
|
Args:
|
||||||
channel: The channel number to set.
|
channel: The channel number to set.
|
||||||
value: The voltage value to set in V.
|
value: The voltage value to set.
|
||||||
|
|
||||||
Returns:
|
Returns:
|
||||||
True if the write operation succeeded.
|
True if the write operation succeeded.
|
||||||
|
@ -369,7 +369,7 @@ class KL4004(AnalogOutputTerminal):
|
||||||
|
|
||||||
Args:
|
Args:
|
||||||
channel: The channel number to set.
|
channel: The channel number to set.
|
||||||
value: The voltage value to set in V.
|
value: The voltage value to set.
|
||||||
|
|
||||||
Returns:
|
Returns:
|
||||||
True if the write operation succeeded.
|
True if the write operation succeeded.
|
||||||
|
|
|
@ -48,13 +48,20 @@ class SimpleModbusClient:
|
||||||
"""
|
"""
|
||||||
A simple Modbus TCP client
|
A simple Modbus TCP client
|
||||||
|
|
||||||
|
Args:
|
||||||
|
host: hostname or IP address
|
||||||
|
port: server port
|
||||||
|
unit_id: ModBus id
|
||||||
|
timeout: socket timeout in seconds
|
||||||
|
debug: if True prints out transmitted and received bytes in hex
|
||||||
|
|
||||||
Attributes:
|
Attributes:
|
||||||
host (str): hostname or IP address
|
host: hostname or IP address
|
||||||
port (int): server port
|
port: server port
|
||||||
unit_id (int): ModBus id
|
unit_id: ModBus id
|
||||||
timeout (float): socket timeout in seconds
|
timeout: socket timeout in seconds
|
||||||
last_error (str): contains last error message or empty string if no error occurred
|
last_error: contains last error message or empty string if no error occurred
|
||||||
debug (bool): if True prints out transmitted and received bytes in hex
|
debug: if True prints out transmitted and received bytes in hex
|
||||||
|
|
||||||
"""
|
"""
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue