2025-05-22 12:51:20 +00:00
<!DOCTYPE html>
2025-06-06 14:37:53 +00:00
< html lang = "en" data-content_root = "./" >
< head >
< meta charset = "utf-8" / >
< meta name = "viewport" content = "width=device-width, initial-scale=1.0" / > < meta name = "viewport" content = "width=device-width, initial-scale=1" / >
< title > Pyhoff — pyhoff documentation< / title >
< script data-cfasync = "false" >
document.documentElement.dataset.mode = localStorage.getItem("mode") || "";
document.documentElement.dataset.theme = localStorage.getItem("theme") || "";
< / script >
<!--
this give us a css class that will be invisible only if js is disabled
-->
< noscript >
< style >
.pst-js-only { display: none !important; }
< / style >
< / noscript >
<!-- Loaded before other Sphinx assets -->
< link href = "_static/styles/theme.css?digest=8878045cc6db502f8baf" rel = "stylesheet" / >
< link href = "_static/styles/pydata-sphinx-theme.css?digest=8878045cc6db502f8baf" rel = "stylesheet" / >
< link rel = "stylesheet" type = "text/css" href = "_static/pygments.css?v=8f2a1f02" / >
<!-- So that users can add custom icons -->
< script src = "_static/scripts/fontawesome.js?digest=8878045cc6db502f8baf" > < / script >
<!-- Pre - loaded scripts that we'll load fully later -->
< link rel = "preload" as = "script" href = "_static/scripts/bootstrap.js?digest=8878045cc6db502f8baf" / >
< link rel = "preload" as = "script" href = "_static/scripts/pydata-sphinx-theme.js?digest=8878045cc6db502f8baf" / >
< script src = "_static/documentation_options.js?v=5929fcd5" > < / script >
< script src = "_static/doctools.js?v=9bcbadda" > < / script >
< script src = "_static/sphinx_highlight.js?v=dc90522c" > < / script >
< script > DOCUMENTATION _OPTIONS . pagename = 'index' ; < / script >
2025-05-22 12:51:20 +00:00
< link rel = "index" title = "Index" href = "genindex.html" / >
< link rel = "search" title = "Search" href = "search.html" / >
2025-06-06 14:37:53 +00:00
< link rel = "next" title = "Classes and Modules" href = "_autogenerated/index.html" / >
< meta name = "viewport" content = "width=device-width, initial-scale=1" / >
< meta name = "docsearch:language" content = "en" / >
< meta name = "docsearch:version" content = "" / >
< / head >
< body data-bs-spy = "scroll" data-bs-target = ".bd-toc-nav" data-offset = "180" data-bs-root-margin = "0px 0px -60%" data-default-mode = "" >
2025-05-22 12:51:20 +00:00
2025-06-06 14:37:53 +00:00
< div id = "pst-skip-link" class = "skip-link d-print-none" > < a href = "#main-content" > Skip to main content< / a > < / div >
< div id = "pst-scroll-pixel-helper" > < / div >
< button type = "button" class = "btn rounded-pill" id = "pst-back-to-top" >
< i class = "fa-solid fa-arrow-up" > < / i > Back to top< / button >
2025-05-22 12:51:20 +00:00
2025-06-06 14:37:53 +00:00
< dialog id = "pst-search-dialog" >
< form class = "bd-search d-flex align-items-center"
action="search.html"
method="get">
< i class = "fa-solid fa-magnifying-glass" > < / i >
< input type = "search"
class="form-control"
name="q"
placeholder="Search the docs ..."
aria-label="Search the docs ..."
autocomplete="off"
autocorrect="off"
autocapitalize="off"
spellcheck="false"/>
< span class = "search-button__kbd-shortcut" > < kbd class = "kbd-shortcut__modifier" > Ctrl< / kbd > +< kbd > K< / kbd > < / span >
< / form >
< / dialog >
< div class = "pst-async-banner-revealer d-none" >
< aside id = "bd-header-version-warning" class = "d-none d-print-none" aria-label = "Version warning" > < / aside >
2025-05-22 12:51:20 +00:00
< / div >
2025-06-06 14:37:53 +00:00
< header class = "bd-header navbar navbar-expand-lg bd-navbar d-print-none" >
< div class = "bd-header__inner bd-page-width" >
< button class = "pst-navbar-icon sidebar-toggle primary-toggle" aria-label = "Site navigation" >
< span class = "fa-solid fa-bars" > < / span >
< / button >
< div class = "col-lg-3 navbar-header-items__start" >
< div class = "navbar-item" >
< a class = "navbar-brand logo" href = "#" >
< p class = "title logo__title" > pyhoff documentation< / p >
< / a > < / div >
< / div >
< div class = "col-lg-9 navbar-header-items" >
< div class = "me-auto navbar-header-items__center" >
< div class = "navbar-item" >
< nav >
< ul class = "bd-navbar-elements navbar-nav" >
< li class = "nav-item " >
< a class = "nav-link nav-internal" href = "_autogenerated/index.html" >
Classes and Modules
< / a >
< / li >
2025-05-22 12:51:20 +00:00
< / ul >
2025-06-06 14:37:53 +00:00
< / nav > < / div >
< / div >
< div class = "navbar-header-items__end" >
< div class = "navbar-item navbar-persistent--container" >
< button class = "btn search-button-field search-button__button pst-js-only" title = "Search" aria-label = "Search" data-bs-placement = "bottom" data-bs-toggle = "tooltip" >
< i class = "fa-solid fa-magnifying-glass" > < / i >
< span class = "search-button__default-text" > Search< / span >
< span class = "search-button__kbd-shortcut" > < kbd class = "kbd-shortcut__modifier" > Ctrl< / kbd > +< kbd class = "kbd-shortcut__modifier" > K< / kbd > < / span >
< / button >
< / div >
< div class = "navbar-item" >
< button class = "btn btn-sm nav-link pst-navbar-icon theme-switch-button pst-js-only" aria-label = "Color mode" data-bs-title = "Color mode" data-bs-placement = "bottom" data-bs-toggle = "tooltip" >
< i class = "theme-switch fa-solid fa-sun fa-lg" data-mode = "light" title = "Light" > < / i >
< i class = "theme-switch fa-solid fa-moon fa-lg" data-mode = "dark" title = "Dark" > < / i >
< i class = "theme-switch fa-solid fa-circle-half-stroke fa-lg" data-mode = "auto" title = "System Settings" > < / i >
< / button > < / div >
< / div >
< / div >
< div class = "navbar-persistent--mobile" >
< button class = "btn search-button-field search-button__button pst-js-only" title = "Search" aria-label = "Search" data-bs-placement = "bottom" data-bs-toggle = "tooltip" >
< i class = "fa-solid fa-magnifying-glass" > < / i >
< span class = "search-button__default-text" > Search< / span >
< span class = "search-button__kbd-shortcut" > < kbd class = "kbd-shortcut__modifier" > Ctrl< / kbd > +< kbd class = "kbd-shortcut__modifier" > K< / kbd > < / span >
< / button >
< / div >
< button class = "pst-navbar-icon sidebar-toggle secondary-toggle" aria-label = "On this page" >
< span class = "fa-solid fa-outdent" > < / span >
< / button >
2025-05-22 12:51:20 +00:00
< / div >
2025-06-06 14:37:53 +00:00
< / header >
< div class = "bd-container" >
< div class = "bd-container__inner bd-page-width" >
< dialog id = "pst-primary-sidebar-modal" > < / dialog >
< div id = "pst-primary-sidebar" class = "bd-sidebar-primary bd-sidebar hide-on-wide" >
< div class = "sidebar-header-items sidebar-primary__section" >
< div class = "sidebar-header-items__center" >
< div class = "navbar-item" >
< nav >
< ul class = "bd-navbar-elements navbar-nav" >
< li class = "nav-item " >
< a class = "nav-link nav-internal" href = "_autogenerated/index.html" >
Classes and Modules
< / a >
2025-05-22 12:51:20 +00:00
< / li >
2025-06-06 14:37:53 +00:00
< / ul >
< / nav > < / div >
< / div >
< div class = "sidebar-header-items__end" >
< div class = "navbar-item" >
< button class = "btn btn-sm nav-link pst-navbar-icon theme-switch-button pst-js-only" aria-label = "Color mode" data-bs-title = "Color mode" data-bs-placement = "bottom" data-bs-toggle = "tooltip" >
< i class = "theme-switch fa-solid fa-sun fa-lg" data-mode = "light" title = "Light" > < / i >
< i class = "theme-switch fa-solid fa-moon fa-lg" data-mode = "dark" title = "Dark" > < / i >
< i class = "theme-switch fa-solid fa-circle-half-stroke fa-lg" data-mode = "auto" title = "System Settings" > < / i >
< / button > < / div >
< / div >
< / div >
< div class = "sidebar-primary-items__end sidebar-primary__section" >
< div class = "sidebar-primary-item" >
< div id = "ethical-ad-placement"
class="flat"
data-ea-publisher="readthedocs"
data-ea-type="readthedocs-sidebar"
data-ea-manual="true">
< / div > < / div >
< / div >
< / div >
< main id = "main-content" class = "bd-main" role = "main" >
< div class = "bd-content" >
< div class = "bd-article-container" >
< div class = "bd-header-article d-print-none" > < / div >
< div id = "searchbox" > < / div >
< article class = "bd-article" >
< div class = "toctree-wrapper compound" >
2025-05-22 12:51:20 +00:00
< / div >
< section id = "pyhoff" >
2025-06-06 14:37:53 +00:00
< h1 > Pyhoff< a class = "headerlink" href = "#pyhoff" title = "Link to this heading" > #< / a > < / h1 >
2025-05-22 12:51:20 +00:00
< section id = "description" >
2025-06-06 14:37:53 +00:00
< h2 > Description< a class = "headerlink" href = "#description" title = "Link to this heading" > #< / a > < / h2 >
2025-05-22 12:51:20 +00:00
< p > 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
over Ethernet TCP/IP based on ModBus TCP.< / p >
< section id = "key-features" >
2025-06-06 14:37:53 +00:00
< h3 > Key Features< a class = "headerlink" href = "#key-features" title = "Link to this heading" > #< / a > < / h3 >
2025-05-22 12:51:20 +00:00
< ul class = "simple" >
< li > < p > Supports a wide range of Beckhoff and WAGO analog and digital bus
terminals.< / p > < / li >
< li > < p > Very lightweight: no dependencies; compact code base< / p > < / li >
< li > < p > Easy to extend< / p > < / li >
< li > < p > Using standardized ModBus TCP.< / p > < / li >
< li > < p > Provides high-level abstractions for reading and writing data
from/to IO-terminals with minimal code< / p > < / li >
< / ul >
< / section >
< section id = "usage-scenarios" >
2025-06-06 14:37:53 +00:00
< h3 > Usage Scenarios< a class = "headerlink" href = "#usage-scenarios" title = "Link to this heading" > #< / a > < / h3 >
2025-05-22 12:51:20 +00:00
< ul class = "simple" >
< li > < p > Industrial test setups.< / p > < / li >
< li > < p > Research automation setups.< / p > < / li >
< li > < p > Data acquisition and monitoring.< / p > < / li >
< / ul >
< / section >
< / section >
< section id = "installation" >
2025-06-06 14:37:53 +00:00
< h2 > Installation< a class = "headerlink" href = "#installation" title = "Link to this heading" > #< / a > < / h2 >
2025-05-22 12:51:20 +00:00
< p > The package has no additional decencies. It can be installed with pip:< / p >
< div class = "highlight-bash notranslate" > < div class = "highlight" > < pre > < span > < / span > pip< span class = "w" > < / span > install< span class = "w" > < / span > pyhoff
< / pre > < / div >
< / div >
< / section >
< section id = "usage" >
2025-06-06 14:37:53 +00:00
< h2 > Usage< a class = "headerlink" href = "#usage" title = "Link to this heading" > #< / a > < / h2 >
2025-05-22 12:51:20 +00:00
< p > It is easy to use as the following example code shows:< / p >
< div class = "highlight-python notranslate" > < div class = "highlight" > < pre > < span > < / span > < span class = "kn" > from< / span > < span class = "w" > < / span > < span class = "nn" > pyhoff.devices< / span > < span class = "w" > < / span > < span class = "kn" > import< / span > < span class = "o" > *< / span >
< span class = "c1" > # connect to the BK9050 by tcp/ip on default port 502< / span >
< span class = "n" > bk< / span > < span class = "o" > =< / span > < span class = "n" > BK9050< / span > < span class = "p" > (< / span > < span class = "s2" > " 172.16.17.1" < / span > < span class = "p" > )< / span >
< span class = "c1" > # add all bus terminals connected to the bus coupler< / span >
< span class = "c1" > # in the order of the physical arrangement< / span >
< span class = "n" > bk< / span > < span class = "o" > .< / span > < span class = "n" > add_bus_terminals< / span > < span class = "p" > (< / span > < span class = "n" > KL2404< / span > < span class = "p" > ,< / span > < span class = "n" > KL2424< / span > < span class = "p" > ,< / span > < span class = "n" > KL9100< / span > < span class = "p" > ,< / span > < span class = "n" > KL1104< / span > < span class = "p" > ,< / span > < span class = "n" > KL3202< / span > < span class = "p" > ,< / span >
< span class = "n" > KL3202< / span > < span class = "p" > ,< / span > < span class = "n" > KL4002< / span > < span class = "p" > ,< / span > < span class = "n" > KL9188< / span > < span class = "p" > ,< / span > < span class = "n" > KL3054< / span > < span class = "p" > ,< / span > < span class = "n" > KL3214< / span > < span class = "p" > ,< / span >
< span class = "n" > KL4004< / span > < span class = "p" > ,< / span > < span class = "n" > KL9010< / span > < span class = "p" > )< / span >
< span class = "c1" > # Set 1. output of the first KL2404-type bus terminal to hi< / span >
< span class = "n" > bk< / span > < span class = "o" > .< / span > < span class = "n" > select< / span > < span class = "p" > (< / span > < span class = "n" > KL2404< / span > < span class = "p" > ,< / span > < span class = "mi" > 0< / span > < span class = "p" > )< / span > < span class = "o" > .< / span > < span class = "n" > write_coil< / span > < span class = "p" > (< / span > < span class = "mi" > 1< / span > < span class = "p" > ,< / span > < span class = "kc" > True< / span > < span class = "p" > )< / span >
< span class = "c1" > # read temperature from the 2. channel of the 2. KL3202-type< / span >
< span class = "c1" > # bus terminal< / span >
< span class = "n" > t< / span > < span class = "o" > =< / span > < span class = "n" > bk< / span > < span class = "o" > .< / span > < span class = "n" > select< / span > < span class = "p" > (< / span > < span class = "n" > KL3202< / span > < span class = "p" > ,< / span > < span class = "mi" > 1< / span > < span class = "p" > )< / span > < span class = "o" > .< / span > < span class = "n" > read_temperature< / span > < span class = "p" > (< / span > < span class = "mi" > 2< / span > < span class = "p" > )< / span >
< span class = "nb" > print< / span > < span class = "p" > (< / span > < span class = "sa" > f< / span > < span class = "s2" > " t = < / span > < span class = "si" > {< / span > < span class = "n" > t< / span > < span class = "si" > :< / span > < span class = "s2" > .1f< / span > < span class = "si" > }< / span > < span class = "s2" > °C" < / span > < span class = "p" > )< / span >
< span class = "c1" > # Set 1. output of the 1. KL4002-type bus terminal to 4.2 V< / span >
< span class = "n" > bk< / span > < span class = "o" > .< / span > < span class = "n" > select< / span > < span class = "p" > (< / span > < span class = "n" > KL4002< / span > < span class = "p" > ,< / span > < span class = "mi" > 0< / span > < span class = "p" > )< / span > < span class = "o" > .< / span > < span class = "n" > set_voltage< / span > < span class = "p" > (< / span > < span class = "mi" > 1< / span > < span class = "p" > ,< / span > < span class = "mf" > 4.2< / span > < span class = "p" > )< / span >
< / pre > < / div >
< / div >
< / section >
< section id = "contributing" >
2025-06-06 14:37:53 +00:00
< h2 > Contributing< a class = "headerlink" href = "#contributing" title = "Link to this heading" > #< / a > < / h2 >
2025-05-22 12:51:20 +00:00
< p > Other analog and digital IO terminals are easy to complement. Contributions are welcome!
Please open an issue or submit a pull request on GitHub.< / p >
< / section >
< section id = "developer-guide" >
2025-06-06 14:37:53 +00:00
< h2 > Developer Guide< a class = "headerlink" href = "#developer-guide" title = "Link to this heading" > #< / a > < / h2 >
2025-05-22 12:51:20 +00:00
< p > To get started with developing the < code class = "docutils literal notranslate" > < span class = "pre" > pyhoff< / span > < / code > package, follow these steps:< / p >
< ol class = "arabic" >
< li > < p > < strong > Clone the Repository< / strong >
First, clone the repository to your local machine using Git:< / p >
< div class = "highlight-bash notranslate" > < div class = "highlight" > < pre > < span > < / span > git< span class = "w" > < / span > clone< span class = "w" > < / span > https://github.com/Nonannet/pyhoff.git
< span class = "nb" > cd< / span > < span class = "w" > < / span > pyhoff
< / pre > < / div >
< / div >
< / li >
< li > < p > < strong > Set Up a Virtual Environment< / strong >
It is recommended to use a virtual environment to manage dependencies. You can create one using < code class = "docutils literal notranslate" > < span class = "pre" > venv< / span > < / code > :< / p >
< div class = "highlight-bash notranslate" > < div class = "highlight" > < pre > < span > < / span > python< span class = "w" > < / span > -m< span class = "w" > < / span > venv< span class = "w" > < / span > venv
< span class = "nb" > source< / span > < span class = "w" > < / span > venv/bin/activate< span class = "w" > < / span > < span class = "c1" > # On Windows use `venv\Scripts\activate`< / span >
< / pre > < / div >
< / div >
< / li >
< li > < p > < strong > Install Dev Dependencies< / strong >
Install pyhoff from source plus the dependencies required for development using < code class = "docutils literal notranslate" > < span class = "pre" > pip< / span > < / code > :< / p >
< div class = "highlight-bash notranslate" > < div class = "highlight" > < pre > < span > < / span > pip< span class = "w" > < / span > install< span class = "w" > < / span > -e< span class = "w" > < / span > .< span class = "o" > [< / span > dev< span class = "o" > ]< / span >
< / pre > < / div >
< / div >
< / li >
< li > < p > < strong > Run Tests< / strong >
Ensure that everything is set up correctly by running the tests:< / p >
< div class = "highlight-bash notranslate" > < div class = "highlight" > < pre > < span > < / span > pytest
< / pre > < / div >
< / div >
< / li >
< / ol >
< / section >
< section id = "license" >
2025-06-06 14:37:53 +00:00
< h2 > License< a class = "headerlink" href = "#license" title = "Link to this heading" > #< / a > < / h2 >
< p > This project is licensed under the MIT License - see the < a class = "reference internal" href = "LICENSE.html" > < span class = "doc std std-doc" > LICENSE< / span > < / a > file for details.< / p >
2025-05-22 12:51:20 +00:00
< / section >
< / section >
2025-06-06 14:37:53 +00:00
< / article >
< footer class = "prev-next-footer d-print-none" >
< div class = "prev-next-area" >
< a class = "right-next"
href="_autogenerated/index.html"
title="next page">
< div class = "prev-next-info" >
< p class = "prev-next-subtitle" > next< / p >
< p class = "prev-next-title" > Classes and Modules< / p >
< / div >
< i class = "fa-solid fa-angle-right" > < / i >
< / a >
< / div >
< / footer >
< / div >
< dialog id = "pst-secondary-sidebar-modal" > < / dialog >
< div id = "pst-secondary-sidebar" class = "bd-sidebar-secondary bd-toc" > < div class = "sidebar-secondary-items sidebar-secondary__inner" >
2025-05-22 12:51:20 +00:00
2025-06-06 14:37:53 +00:00
< div class = "sidebar-secondary-item" >
< div
id="pst-page-navigation-heading-2"
class="page-toc tocsection onthispage">
< i class = "fa-solid fa-list" > < / i > On this page
2025-05-22 12:51:20 +00:00
< / div >
2025-06-06 14:37:53 +00:00
< nav class = "bd-toc-nav page-toc" aria-labelledby = "pst-page-navigation-heading-2" >
< ul class = "visible nav section-nav flex-column" >
< li class = "toc-h2 nav-item toc-entry" > < a class = "reference internal nav-link" href = "#description" > Description< / a > < ul class = "nav section-nav flex-column" >
< li class = "toc-h3 nav-item toc-entry" > < a class = "reference internal nav-link" href = "#key-features" > Key Features< / a > < / li >
< li class = "toc-h3 nav-item toc-entry" > < a class = "reference internal nav-link" href = "#usage-scenarios" > Usage Scenarios< / a > < / li >
< / ul >
< / li >
< li class = "toc-h2 nav-item toc-entry" > < a class = "reference internal nav-link" href = "#installation" > Installation< / a > < / li >
< li class = "toc-h2 nav-item toc-entry" > < a class = "reference internal nav-link" href = "#usage" > Usage< / a > < / li >
< li class = "toc-h2 nav-item toc-entry" > < a class = "reference internal nav-link" href = "#contributing" > Contributing< / a > < / li >
< li class = "toc-h2 nav-item toc-entry" > < a class = "reference internal nav-link" href = "#developer-guide" > Developer Guide< / a > < / li >
< li class = "toc-h2 nav-item toc-entry" > < a class = "reference internal nav-link" href = "#license" > License< / a > < / li >
< / ul >
< / nav > < / div >
2025-05-22 12:51:20 +00:00
2025-06-06 14:37:53 +00:00
< div class = "sidebar-secondary-item" >
< div role = "note" aria-label = "source link" >
< h3 > This Page< / h3 >
< ul class = "this-page-menu" >
< li > < a href = "_sources/index.md.txt"
rel="nofollow">Show Source< / a > < / li >
< / ul >
< / div > < / div >
2025-05-22 12:51:20 +00:00
2025-06-06 14:37:53 +00:00
< / div > < / div >
< / div >
< footer class = "bd-footer-content" >
< / footer >
< / main >
< / div >
2025-05-22 12:51:20 +00:00
< / div >
2025-06-06 14:37:53 +00:00
<!-- Scripts loaded after <body> so the DOM is not blocked -->
< script defer src = "_static/scripts/bootstrap.js?digest=8878045cc6db502f8baf" > < / script >
< script defer src = "_static/scripts/pydata-sphinx-theme.js?digest=8878045cc6db502f8baf" > < / script >
< footer class = "bd-footer" >
< div class = "bd-footer__inner bd-page-width" >
< div class = "footer-items__start" >
< div class = "footer-item" >
< p class = "copyright" >
© Copyright 2025, Nicolas Kruse.
< br / >
< / p >
< / div >
< div class = "footer-item" >
< p class = "sphinx-version" >
Created using < a href = "https://www.sphinx-doc.org/" > Sphinx< / a > 8.2.3.
< br / >
< / p >
< / div >
< / div >
< div class = "footer-items__end" >
< div class = "footer-item" >
< p class = "theme-version" >
<!-- # L10n: Setting the PST URL as an argument as this does not need to be localized -->
Built with the < a href = "https://pydata-sphinx-theme.readthedocs.io/en/stable/index.html" > PyData Sphinx Theme< / a > 0.16.1.
< / p > < / div >
< / div >
< / div >
2025-05-22 12:51:20 +00:00
2025-06-06 14:37:53 +00:00
< / footer >
< / body >
2025-05-22 12:51:20 +00:00
< / html >