diff --git a/.github/workflows/github-actions-python.yml b/.github/workflows/github-actions-python.yml index e942a8e893..8fb5304588 100644 --- a/.github/workflows/github-actions-python.yml +++ b/.github/workflows/github-actions-python.yml @@ -5,15 +5,19 @@ on: pull_request jobs: build: runs-on: ubuntu-latest + strategy: + matrix: + python-version: ["3.11", "3.12", "3.13"] steps: - uses: actions/checkout@v4 - - name: Set up Python 3.9 + - name: Set up Python ${{ matrix.python-version }} uses: actions/setup-python@v5 with: - python-version: "3.9.12" + python-version: ${{ matrix.python-version }} - name: Install dependencies run: | pip3 install -r "/home/runner/work/core/core/requirements.txt" + pip3 install -r "/home/runner/work/core/core/requirements-dev.txt" - name: Flake8 with annotations in packages folder uses: TrueBrain/actions-flake8@v2.1 with: diff --git a/.gitignore b/.gitignore index 57189a06cb..5e006c7f24 100644 --- a/.gitignore +++ b/.gitignore @@ -21,4 +21,5 @@ data/restore/*.tar.gz data/data_migration/*.tar.gz ramdisk/* web/lastcommit -!.gitignore +.stack-version +!.gitignore diff --git a/.htaccess b/.htaccess deleted file mode 100644 index 6b43667dee..0000000000 --- a/.htaccess +++ /dev/null @@ -1,11 +0,0 @@ - - Header set Cache-Control "no-cache, no-store, must-revalidate" - Header set Pragma "no-cache" - Header set Expires 0 - - -RedirectMatch 404 \.conf$ -RedirectMatch 404 \.ini$ -RedirectMatch 404 \.py$ -RedirectMatch 404 \.sh$ -ErrorDocument 404 /openWB/web/error.html diff --git a/README.md b/README.md index 14b32635c5..4db6999995 100644 --- a/README.md +++ b/README.md @@ -33,11 +33,10 @@ Bei fertig erworbenen openWB ist die Software bereits vorinstalliert. Software: - Installiertes Raspberry Pi OS auf einem Raspberry Pi 3b oder besser. -- Raspberry Pi OS Lite installieren. Aktuell wird in der Version 2.1 nur **Debian 11 "Bullseye"** (derzeit "oldstable") unterstützt. - -- alternativ kann auch ein x86_64 System (Hardware oder als VM) mit installiertem **Debian 11 "Bullseye"** als Basis verwendet werden. -- Eine Installation unter **Debian 12 "Bookworm"** wird noch nicht unterstützt! -- Bitte beachten das **Debian 11 "Bullseye"** nur mit erheblichem Aufwand mit einem Raspberry Pi 5 kompatibel ist. Wir empfehlen die Nutzung von einem Raspberry Pi 3b. +- Raspberry Pi OS Lite installieren. Unterstützt werden **Debian 12 "Bookworm"** und **Debian 13 "Trixie"**. +- alternativ kann auch ein x86_64 System (Hardware oder als VM) mit installiertem **Debian 12 "Bookworm"** oder **Debian 13 "Trixie"** als Basis verwendet werden. +- **Python 3.10 oder neuer** wird benötigt (Python 3.13 empfohlen). +- Die Installation richtet automatisch ein Python Virtual Environment unter `/opt/openwb-venv` ein. In der Shell folgendes eingeben: diff --git a/data/config/apache/000-default.conf b/data/config/apache/000-default.conf deleted file mode 100644 index 4a16b41bec..0000000000 --- a/data/config/apache/000-default.conf +++ /dev/null @@ -1,45 +0,0 @@ -# openwb-version:6 - - # The ServerName directive sets the request scheme, hostname and port that - # the server uses to identify itself. This is used when creating - # redirection URLs. In the context of virtual hosts, the ServerName - # specifies what hostname must appear in the request's Host: header to - # match this virtual host. For the default virtual host (this file) this - # value is not decisive as it is used as a last resort host regardless. - # However, you must set it for any further virtual host explicitly. - #ServerName www.example.com - - ServerAdmin webmaster@localhost - DocumentRoot /var/www/html - # Available loglevels: trace8, ..., trace1, debug, info, notice, warn, - # error, crit, alert, emerg. - # It is also possible to configure the loglevel for particular - # modules, e.g. - #LogLevel info ssl:warn - - ErrorLog ${APACHE_LOG_DIR}/error.log - #CustomLog ${APACHE_LOG_DIR}/access.log combined - - AllowOverride All - Require all granted - Options -Indexes - - - Options +Indexes - - - Options +Indexes - - # For most configuration files from conf-available/, which are - # enabled or disabled at a global level, it is possible to - # include a line for only one particular virtual host. For example the - # following line enables the CGI configuration for this host only - # after it has been globally disabled with "a2disconf". - #Include conf-available/serve-cgi-bin.conf - - # Proxy WebSocket and MQTT connections to Mosquitto - # ToDo: remove /mqtt target once all clients use /ws - ProxyPassMatch "^/(ws|mqtt)(/|$)" "ws://127.0.0.1:9003/" - - -# vim: syntax=apache ts=4 sw=4 sts=4 sr noet diff --git a/data/config/apache/apache-openwb-ssl.conf b/data/config/apache/apache-openwb-ssl.conf deleted file mode 100644 index ddd95d2a1f..0000000000 --- a/data/config/apache/apache-openwb-ssl.conf +++ /dev/null @@ -1,149 +0,0 @@ -# openwb-version:8 - - - ServerAdmin webmaster@localhost - - DocumentRoot /var/www/html - - # Available loglevels: trace8, ..., trace1, debug, info, notice, warn, - # error, crit, alert, emerg. - # It is also possible to configure the loglevel for particular - # modules, e.g. - #LogLevel info ssl:warn - - ErrorLog ${APACHE_LOG_DIR}/error.log - CustomLog ${APACHE_LOG_DIR}/access.log combined - - # For most configuration files from conf-available/, which are - # enabled or disabled at a global level, it is possible to - # include a line for only one particular virtual host. For example the - # following line enables the CGI configuration for this host only - # after it has been globally disabled with "a2disconf". - #Include conf-available/serve-cgi-bin.conf - - # SSL Engine Switch: - # Enable/Disable SSL for this virtual host. - SSLEngine on - - # A self-signed (snakeoil) certificate can be created by installing - # the ssl-cert package. See - # /usr/share/doc/apache2/README.Debian.gz for more info. - # If both key and certificate are stored in the same file, only the - # SSLCertificateFile directive is needed. - SSLCertificateFile /etc/ssl/certs/ssl-cert-snakeoil.pem - SSLCertificateKeyFile /etc/ssl/private/ssl-cert-snakeoil.key - - # Server Certificate Chain: - # Point SSLCertificateChainFile at a file containing the - # concatenation of PEM encoded CA certificates which form the - # certificate chain for the server certificate. Alternatively - # the referenced file can be the same as SSLCertificateFile - # when the CA certificates are directly appended to the server - # certificate for convinience. - #SSLCertificateChainFile /etc/apache2/ssl.crt/server-ca.crt - - # Certificate Authority (CA): - # Set the CA certificate verification path where to find CA - # certificates for client authentication or alternatively one - # huge file containing all of them (file must be PEM encoded) - # Note: Inside SSLCACertificatePath you need hash symlinks - # to point to the certificate files. Use the provided - # Makefile to update the hash symlinks after changes. - #SSLCACertificatePath /etc/ssl/certs/ - #SSLCACertificateFile /etc/apache2/ssl.crt/ca-bundle.crt - - # Certificate Revocation Lists (CRL): - # Set the CA revocation path where to find CA CRLs for client - # authentication or alternatively one huge file containing all - # of them (file must be PEM encoded) - # Note: Inside SSLCARevocationPath you need hash symlinks - # to point to the certificate files. Use the provided - # Makefile to update the hash symlinks after changes. - #SSLCARevocationPath /etc/apache2/ssl.crl/ - #SSLCARevocationFile /etc/apache2/ssl.crl/ca-bundle.crl - - # Client Authentication (Type): - # Client certificate verification type and depth. Types are - # none, optional, require and optional_no_ca. Depth is a - # number which specifies how deeply to verify the certificate - # issuer chain before deciding the certificate is not valid. - #SSLVerifyClient require - #SSLVerifyDepth 10 - - # SSL Engine Options: - # Set various options for the SSL engine. - # o FakeBasicAuth: - # Translate the client X.509 into a Basic Authorisation. This means that - # the standard Auth/DBMAuth methods can be used for access control. The - # user name is the `one line' version of the client's X.509 certificate. - # Note that no password is obtained from the user. Every entry in the user - # file needs this password: `xxj31ZMTZzkVA'. - # o ExportCertData: - # This exports two additional environment variables: SSL_CLIENT_CERT and - # SSL_SERVER_CERT. These contain the PEM-encoded certificates of the - # server (always existing) and the client (only existing when client - # authentication is used). This can be used to import the certificates - # into CGI scripts. - # o StdEnvVars: - # This exports the standard SSL/TLS related `SSL_*' environment variables. - # Per default this exportation is switched off for performance reasons, - # because the extraction step is an expensive operation and is usually - # useless for serving static content. So one usually enables the - # exportation for CGI and SSI requests only. - # o OptRenegotiate: - # This enables optimized SSL connection renegotiation handling when SSL - # directives are used in per-directory context. - #SSLOptions +FakeBasicAuth +ExportCertData +StrictRequire - - SSLOptions +StdEnvVars - - - SSLOptions +StdEnvVars - - - AllowOverride All - Require all granted - Options -Indexes - - - Options +Indexes - - - Options +Indexes - - # SSL Protocol Adjustments: - # The safe and default but still SSL/TLS standard compliant shutdown - # approach is that mod_ssl sends the close notify alert but doesn't wait for - # the close notify alert from client. When you need a different shutdown - # approach you can use one of the following variables: - # o ssl-unclean-shutdown: - # This forces an unclean shutdown when the connection is closed, i.e. no - # SSL close notify alert is send or allowed to received. This violates - # the SSL/TLS standard but is needed for some brain-dead browsers. Use - # this when you receive I/O errors because of the standard approach where - # mod_ssl sends the close notify alert. - # o ssl-accurate-shutdown: - # This forces an accurate shutdown when the connection is closed, i.e. a - # SSL close notify alert is send and mod_ssl waits for the close notify - # alert of the client. This is 100% SSL/TLS standard compliant, but in - # practice often causes hanging connections with brain-dead browsers. Use - # this only for browsers where you know that their SSL implementation - # works correctly. - # Notice: Most problems of broken clients are also related to the HTTP - # keep-alive facility, so you usually additionally want to disable - # keep-alive for those clients, too. Use variable "nokeepalive" for this. - # Similarly, one has to force some clients to use HTTP/1.0 to workaround - # their broken HTTP/1.1 implementation. Use variables "downgrade-1.0" and - # "force-response-1.0" for this. - # BrowserMatch "MSIE [2-6]" \ - # nokeepalive ssl-unclean-shutdown \ - # downgrade-1.0 force-response-1.0 - - # Proxy WebSocket and MQTT connections to Mosquitto - # ToDo: remove /mqtt target once all clients use /ws - ProxyPassMatch "^/(ws|mqtt)(/|$)" "ws://127.0.0.1:9003/" - - - - -# vim: syntax=apache ts=4 sw=4 sts=4 sr noet diff --git a/data/config/apache/apache-proplus.conf b/data/config/apache/apache-proplus.conf deleted file mode 100644 index c20f2b6a35..0000000000 --- a/data/config/apache/apache-proplus.conf +++ /dev/null @@ -1,12 +0,0 @@ -# openwb-version:1 -Listen 8080 - - - ProxyPreserveHost On - - # Proxy for Pro: - ProxyPass / http://192.168.192.50:80/ - ProxyPassReverse / http://192.168.192.50:80/ - - ServerName localhost - diff --git a/data/config/apache/apache-redirect-ssl.conf b/data/config/apache/apache-redirect-ssl.conf deleted file mode 100644 index 8ee4d9c539..0000000000 --- a/data/config/apache/apache-redirect-ssl.conf +++ /dev/null @@ -1,29 +0,0 @@ -# openwb-version:1 - - # The ServerName directive sets the request scheme, hostname and port that - # the server uses to identify itself. This is used when creating - # redirection URLs. In the context of virtual hosts, the ServerName - # specifies what hostname must appear in the request's Host: header to - # match this virtual host. For the default virtual host (this file) this - # value is not decisive as it is used as a last resort host regardless. - # However, you must set it for any further virtual host explicitly. - #ServerName www.example.com - - ServerAdmin webmaster@localhost - DocumentRoot /var/www/html - # Available loglevels: trace8, ..., trace1, debug, info, notice, warn, - # error, crit, alert, emerg. - # It is also possible to configure the loglevel for particular - # modules, e.g. - #LogLevel info ssl:warn - - ErrorLog ${APACHE_LOG_DIR}/error.log - #CustomLog ${APACHE_LOG_DIR}/access.log combined - - # redirect all HTTP traffic to HTTPS - RewriteEngine On - RewriteCond %{HTTPS} off - RewriteRule ^/?(.*)$ https://%{HTTP_HOST}/$1 [R=301,L] - - -# vim: syntax=apache ts=4 sw=4 sts=4 sr noet diff --git a/data/config/apache/http-api-ssl.conf b/data/config/apache/http-api-ssl.conf deleted file mode 100644 index 2a2546da76..0000000000 --- a/data/config/apache/http-api-ssl.conf +++ /dev/null @@ -1,141 +0,0 @@ -# openwb-version:1 - - Listen 8443 - - - ServerAdmin webmaster@localhost - - DocumentRoot /var/www/html/openWB/runs/http-api - - # Available loglevels: trace8, ..., trace1, debug, info, notice, warn, - # error, crit, alert, emerg. - # It is also possible to configure the loglevel for particular - # modules, e.g. - #LogLevel info ssl:warn - - ErrorLog ${APACHE_LOG_DIR}/api-ssl-error.log - CustomLog ${APACHE_LOG_DIR}/api-ssl-access.log combined - - # For most configuration files from conf-available/, which are - # enabled or disabled at a global level, it is possible to - # include a line for only one particular virtual host. For example the - # following line enables the CGI configuration for this host only - # after it has been globally disabled with "a2disconf". - #Include conf-available/serve-cgi-bin.conf - - # SSL Engine Switch: - # Enable/Disable SSL for this virtual host. - SSLEngine on - - # A self-signed (snakeoil) certificate can be created by installing - # the ssl-cert package. See - # /usr/share/doc/apache2/README.Debian.gz for more info. - # If both key and certificate are stored in the same file, only the - # SSLCertificateFile directive is needed. - SSLCertificateFile /etc/ssl/certs/ssl-cert-snakeoil.pem - SSLCertificateKeyFile /etc/ssl/private/ssl-cert-snakeoil.key - - # Server Certificate Chain: - # Point SSLCertificateChainFile at a file containing the - # concatenation of PEM encoded CA certificates which form the - # certificate chain for the server certificate. Alternatively - # the referenced file can be the same as SSLCertificateFile - # when the CA certificates are directly appended to the server - # certificate for convinience. - #SSLCertificateChainFile /etc/apache2/ssl.crt/server-ca.crt - - # Certificate Authority (CA): - # Set the CA certificate verification path where to find CA - # certificates for client authentication or alternatively one - # huge file containing all of them (file must be PEM encoded) - # Note: Inside SSLCACertificatePath you need hash symlinks - # to point to the certificate files. Use the provided - # Makefile to update the hash symlinks after changes. - #SSLCACertificatePath /etc/ssl/certs/ - #SSLCACertificateFile /etc/apache2/ssl.crt/ca-bundle.crt - - # Certificate Revocation Lists (CRL): - # Set the CA revocation path where to find CA CRLs for client - # authentication or alternatively one huge file containing all - # of them (file must be PEM encoded) - # Note: Inside SSLCARevocationPath you need hash symlinks - # to point to the certificate files. Use the provided - # Makefile to update the hash symlinks after changes. - #SSLCARevocationPath /etc/apache2/ssl.crl/ - #SSLCARevocationFile /etc/apache2/ssl.crl/ca-bundle.crl - - # Client Authentication (Type): - # Client certificate verification type and depth. Types are - # none, optional, require and optional_no_ca. Depth is a - # number which specifies how deeply to verify the certificate - # issuer chain before deciding the certificate is not valid. - #SSLVerifyClient require - #SSLVerifyDepth 10 - - # SSL Engine Options: - # Set various options for the SSL engine. - # o FakeBasicAuth: - # Translate the client X.509 into a Basic Authorisation. This means that - # the standard Auth/DBMAuth methods can be used for access control. The - # user name is the `one line' version of the client's X.509 certificate. - # Note that no password is obtained from the user. Every entry in the user - # file needs this password: `xxj31ZMTZzkVA'. - # o ExportCertData: - # This exports two additional environment variables: SSL_CLIENT_CERT and - # SSL_SERVER_CERT. These contain the PEM-encoded certificates of the - # server (always existing) and the client (only existing when client - # authentication is used). This can be used to import the certificates - # into CGI scripts. - # o StdEnvVars: - # This exports the standard SSL/TLS related `SSL_*' environment variables. - # Per default this exportation is switched off for performance reasons, - # because the extraction step is an expensive operation and is usually - # useless for serving static content. So one usually enables the - # exportation for CGI and SSI requests only. - # o OptRenegotiate: - # This enables optimized SSL connection renegotiation handling when SSL - # directives are used in per-directory context. - #SSLOptions +FakeBasicAuth +ExportCertData +StrictRequire - - SSLOptions +StdEnvVars - - - SSLOptions +StdEnvVars - - - AllowOverride All - Require all granted - Options -Indexes - - # SSL Protocol Adjustments: - # The safe and default but still SSL/TLS standard compliant shutdown - # approach is that mod_ssl sends the close notify alert but doesn't wait for - # the close notify alert from client. When you need a different shutdown - # approach you can use one of the following variables: - # o ssl-unclean-shutdown: - # This forces an unclean shutdown when the connection is closed, i.e. no - # SSL close notify alert is send or allowed to received. This violates - # the SSL/TLS standard but is needed for some brain-dead browsers. Use - # this when you receive I/O errors because of the standard approach where - # mod_ssl sends the close notify alert. - # o ssl-accurate-shutdown: - # This forces an accurate shutdown when the connection is closed, i.e. a - # SSL close notify alert is send and mod_ssl waits for the close notify - # alert of the client. This is 100% SSL/TLS standard compliant, but in - # practice often causes hanging connections with brain-dead browsers. Use - # this only for browsers where you know that their SSL implementation - # works correctly. - # Notice: Most problems of broken clients are also related to the HTTP - # keep-alive facility, so you usually additionally want to disable - # keep-alive for those clients, too. Use variable "nokeepalive" for this. - # Similarly, one has to force some clients to use HTTP/1.0 to workaround - # their broken HTTP/1.1 implementation. Use variables "downgrade-1.0" and - # "force-response-1.0" for this. - # BrowserMatch "MSIE [2-6]" \ - # nokeepalive ssl-unclean-shutdown \ - # downgrade-1.0 force-response-1.0 - - - - -# vim: syntax=apache ts=4 sw=4 sts=4 sr noet diff --git a/data/config/apache/localhost.conf b/data/config/apache/localhost.conf deleted file mode 100644 index 4d809119de..0000000000 --- a/data/config/apache/localhost.conf +++ /dev/null @@ -1,47 +0,0 @@ -# openwb-version:2 -Listen 127.0.0.1:81 - - - # The ServerName directive sets the request scheme, hostname and port that - # the server uses to identify itself. This is used when creating - # redirection URLs. In the context of virtual hosts, the ServerName - # specifies what hostname must appear in the request's Host: header to - # match this virtual host. For the default virtual host (this file) this - # value is not decisive as it is used as a last resort host regardless. - # However, you must set it for any further virtual host explicitly. - #ServerName www.example.com - - ServerAdmin webmaster@localhost - DocumentRoot /var/www/html - # Available loglevels: trace8, ..., trace1, debug, info, notice, warn, - # error, crit, alert, emerg. - # It is also possible to configure the loglevel for particular - # modules, e.g. - #LogLevel info ssl:warn - - ErrorLog ${APACHE_LOG_DIR}/error.log - #CustomLog ${APACHE_LOG_DIR}/access.log combined - - AllowOverride All - Require all granted - Options -Indexes - - - Options +Indexes - - - Options +Indexes - - # For most configuration files from conf-available/, which are - # enabled or disabled at a global level, it is possible to - # include a line for only one particular virtual host. For example the - # following line enables the CGI configuration for this host only - # after it has been globally disabled with "a2disconf". - #Include conf-available/serve-cgi-bin.conf - - # Proxy WebSocket and MQTT connections to Mosquitto - # ToDo: remove /mqtt target once all clients use /ws - ProxyPassMatch "^/(ws|mqtt)(/|$)" "ws://127.0.0.1:9003/" - - -# vim: syntax=apache ts=4 sw=4 sts=4 sr noet diff --git a/data/config/caddy/Caddyfile b/data/config/caddy/Caddyfile new file mode 100644 index 0000000000..adacf01e27 --- /dev/null +++ b/data/config/caddy/Caddyfile @@ -0,0 +1,212 @@ +# openwb-version:1 +# openWB Caddy configuration +# Replaces all Apache vhosts + .htaccess files + +# Global options +{ + # Use snakeoil certs for HTTPS (LAN device, no public domain) + # Caddy auto-HTTPS needs to be disabled for internal IPs + auto_https off +} + +# PHP-FPM upstream +# Detect PHP version dynamically via php-fpm socket symlink +{$PHP_FPM_SOCK:unix//run/php/php-fpm.sock} + +# --- Main site: HTTP (:80) --- +# openwb-version:http-unencrypted:1 +:80 { + root * /var/www/html + + php_fastcgi {$PHP_FPM_SOCK:unix//run/php/php-fpm.sock} + + file_server { + index index.php index.html + } + + # ramdisk and backup allow directory listing + @ramdisk path /openWB/ramdisk/* + handle_path @ramdisk { + root * /var/www/html/openWB/ramdisk + file_server browse + } + @backup path /openWB/data/backup/* + handle_path @backup { + root * /var/www/html/openWB/data/backup + file_server browse + } + + # WebSocket/MQTT proxy to mosquitto + # TODO: remove /mqtt target once all clients use /ws + handle_path /ws/* { + reverse_proxy 127.0.0.1:9003 + } + handle_path /mqtt/* { + reverse_proxy 127.0.0.1:9003 + } + + # .htaccess: no-cache headers + header { + Cache-Control "no-cache, no-store, must-revalidate" + Pragma "no-cache" + Expires 0 + } + + # .htaccess: block sensitive file types + @blocked { + path *.conf + path *.ini + path *.py + path *.sh + } + respond @blocked 404 + + # Custom 404 + handle_errors { + @404 expression {http.error.status_code} == 404 + handle @404 { + rewrite * /openWB/web/error.html + file_server + } + } + + log { + output file /var/log/caddy/access.log + } +} + +# --- Main site: HTTPS (:443) --- +# openwb-version:https-main:1 +:443 { + root * /var/www/html + + tls /etc/ssl/certs/ssl-cert-snakeoil.pem /etc/ssl/private/ssl-cert-snakeoil.key + + php_fastcgi {$PHP_FPM_SOCK:unix//run/php/php-fpm.sock} + + file_server { + index index.php index.html + } + + @ramdisk path /openWB/ramdisk/* + handle_path @ramdisk { + root * /var/www/html/openWB/ramdisk + file_server browse + } + @backup path /openWB/data/backup/* + handle_path @backup { + root * /var/www/html/openWB/data/backup + file_server browse + } + + handle_path /ws/* { + reverse_proxy 127.0.0.1:9003 + } + handle_path /mqtt/* { + reverse_proxy 127.0.0.1:9003 + } + + header { + Cache-Control "no-cache, no-store, must-revalidate" + Pragma "no-cache" + Expires 0 + } + + @blocked { + path *.conf + path *.ini + path *.py + path *.sh + } + respond @blocked 404 + + handle_errors { + @404 expression {http.error.status_code} == 404 + handle @404 { + rewrite * /openWB/web/error.html + file_server + } + } + + log { + output file /var/log/caddy/ssl-access.log + } +} + +# --- HTTP redirect to HTTPS (enabled when unencrypted access is disabled) --- +# This block is only activated by setup_caddy.sh based on MQTT config +# When active, :80 is replaced by the redirect block above +# openwb-version:http-redirect:1 +# Uncommented by setup_caddy.sh when allow_unencrypted_access != "true" +#:80 { +# redir https://{host}{uri} permanent +#} + +# --- Localhost internal (:81) --- +# openwb-version:localhost:1 +127.0.0.1:81 { + root * /var/www/html + + php_fastcgi {$PHP_FPM_SOCK:unix//run/php/php-fpm.sock} + + file_server { + index index.php index.html + } + + @ramdisk path /openWB/ramdisk/* + handle_path @ramdisk { + root * /var/www/html/openWB/ramdisk + file_server browse + } + @backup path /openWB/data/backup/* + handle_path @backup { + root * /var/www/html/openWB/data/backup + file_server browse + } + + handle_path /ws/* { + reverse_proxy 127.0.0.1:9003 + } + handle_path /mqtt/* { + reverse_proxy 127.0.0.1:9003 + } + + header { + Cache-Control "no-cache, no-store, must-revalidate" + Pragma "no-cache" + Expires 0 + } + + @blocked { + path *.conf + path *.ini + path *.py + path *.sh + } + respond @blocked 404 +} + +# --- HTTP API over HTTPS (:8443) --- +# openwb-version:http-api:1 +:8443 { + root * /var/www/html/openWB/runs/http-api + + tls /etc/ssl/certs/ssl-cert-snakeoil.pem /etc/ssl/private/ssl-cert-snakeoil.key + + php_fastcgi {$PHP_FPM_SOCK:unix//run/php/php-fpm.sock} + + file_server { + index index.php index.html + } + + log { + output file /var/log/caddy/api-access.log + } +} + +# --- Pro+ reverse proxy (:8080) --- +# Enabled only when USB network adapter is detected +# openwb-version:proplus:1 +#:8080 { +# reverse_proxy 192.168.192.50:80 +#} diff --git a/data/config/chrony/chrony.conf b/data/config/chrony/chrony.conf new file mode 100644 index 0000000000..508e6f6622 --- /dev/null +++ b/data/config/chrony/chrony.conf @@ -0,0 +1,32 @@ +# openwb-version:1 +# Chrony NTP configuration for openWB +# PTB Braunschweig (primary, Germany's national metrology institute) +server ptbtime1.ptb.de iburst prefer +server ptbtime2.ptb.de iburst + +# NTP Pool (Germany) +pool 0.de.pool.ntp.org iburst + +# Ubuntu NTP pools (reliable fallback) +pool ntp.ubuntu.com iburst maxsources 4 +pool 0.ubuntu.pool.ntp.org iburst maxsources 1 +pool 1.ubuntu.pool.ntp.org iburst maxsources 1 +pool 2.ubuntu.pool.ntp.org iburst maxsources 2 + +# Allow local network to query this server (useful for LAN charge points) +allow 192.168.0.0/16 +allow 10.0.0.0/8 +allow 172.16.0.0/12 + +# Drift file +driftfile /var/lib/chrony/chrony.drift + +# Log +logdir /var/log/chrony +maxupdateskew 100.0 + +# Allow step on first sync +makestep 1 -1 + +# RTC sync +rtconutc diff --git a/data/config/mosquitto/public/openwb-default-acl.conf b/data/config/mosquitto/public/openwb-default-acl.conf index 75503da260..f11ee93f71 100644 --- a/data/config/mosquitto/public/openwb-default-acl.conf +++ b/data/config/mosquitto/public/openwb-default-acl.conf @@ -1,7 +1,7 @@ # openwb-version:1 # localhost websocket listener -# used for internal connections only (apache2 reverse proxy) +# used for internal connections only (caddy reverse proxy) listener 9003 127.0.0.1 protocol websockets allow_anonymous true diff --git a/data/config/mosquitto/public/openwb-user-management.conf b/data/config/mosquitto/public/openwb-user-management.conf index eceb6fc774..43f71bf078 100644 --- a/data/config/mosquitto/public/openwb-user-management.conf +++ b/data/config/mosquitto/public/openwb-user-management.conf @@ -1,7 +1,7 @@ # openwb-version:1 # localhost websocket listener -# used for internal connections only (apache2 reverse proxy) +# used for internal connections only (caddy reverse proxy) listener 9003 127.0.0.1 protocol websockets allow_anonymous true diff --git a/data/config/openwb-simpleAPI.service b/data/config/openwb-simpleAPI.service index b549c9223b..54f1668dc5 100644 --- a/data/config/openwb-simpleAPI.service +++ b/data/config/openwb-simpleAPI.service @@ -1,4 +1,4 @@ -# openwb-version:1 +# openwb-version:2 [Unit] Description="openWB mqtt simpleAPI" After=mosquitto.service @@ -6,7 +6,7 @@ After=mosquitto.service [Service] User=openwb WorkingDirectory=/var/www/html/openWB -ExecStart=/var/www/html/openWB/simpleAPI/simpleAPI_mqtt.py +ExecStart=/opt/openwb-venv/bin/python3 /var/www/html/openWB/simpleAPI/simpleAPI_mqtt.py Restart=always # extend timeout to 15min for long running atreboot TimeoutStartSec=900 diff --git a/data/config/openwb2.service b/data/config/openwb2.service index 6b0c007a7b..e31239e887 100644 --- a/data/config/openwb2.service +++ b/data/config/openwb2.service @@ -1,4 +1,4 @@ -# openwb-version:4 +# openwb-version:5 [Unit] Description="Regelung openWB 2.0" After=mosquitto_local.service @@ -7,7 +7,7 @@ After=mosquitto_local.service User=openwb WorkingDirectory=/var/www/html/openWB ExecStartPre=-/var/www/html/openWB/runs/atreboot.sh -ExecStart=/var/www/html/openWB/packages/main.py +ExecStart=/opt/openwb-venv/bin/python3 /var/www/html/openWB/packages/main.py Restart=always # extend timeout to 15min for long running atreboot TimeoutStartSec=900 diff --git a/data/config/openwbRemoteSupport.service b/data/config/openwbRemoteSupport.service index 0b49f1f0fc..8dec8bf320 100644 --- a/data/config/openwbRemoteSupport.service +++ b/data/config/openwbRemoteSupport.service @@ -1,4 +1,4 @@ -# openwb-version:3 +# openwb-version:4 [Unit] Description="Remote Support Handler openWB 2.0" After=mosquitto_local.service @@ -6,7 +6,7 @@ After=mosquitto_local.service [Service] User=openwb WorkingDirectory=/var/www/html/openWB -ExecStart=/var/www/html/openWB/runs/remoteSupport/remoteSupport.py +ExecStart=/opt/openwb-venv/bin/python3 /var/www/html/openWB/runs/remoteSupport/remoteSupport.py Restart=always [Install] diff --git a/data/config/php/fpm/20-uploadlimit.ini b/data/config/php/fpm/20-uploadlimit.ini new file mode 100644 index 0000000000..c604d90e76 --- /dev/null +++ b/data/config/php/fpm/20-uploadlimit.ini @@ -0,0 +1,2 @@ +upload_max_filesize = 300M +post_max_size = 300M diff --git a/data/config/profile.d/99-openwb-motd.sh b/data/config/profile.d/99-openwb-motd.sh new file mode 100644 index 0000000000..cb8a0e9b3c --- /dev/null +++ b/data/config/profile.d/99-openwb-motd.sh @@ -0,0 +1,45 @@ +#!/bin/bash +OPENWBBASEDIR="/var/www/html/openWB" + +IP=$(hostname -I 2>/dev/null | awk '{print $1}') +if [ -z "$IP" ]; then + IP="unknown" +fi + +# Get openWB version +OWB_VERSION="unknown" +OWB_GIT="unknown" +if [ -d "$OPENWBBASEDIR/.git" ]; then + OWB_GIT=$(cd "$OPENWBBASEDIR" && git rev-parse --short HEAD 2>/dev/null || echo "unknown") + OWB_BRANCH=$(cd "$OPENWBBASEDIR" && git rev-parse --abbrev-ref HEAD 2>/dev/null || echo "unknown") +fi + +# Check service status +OWB_STATUS=$(systemctl is-active openwb2.service 2>/dev/null || echo "unknown") + +# Get Debian version +. /etc/os-release 2>/dev/null +DEBIAN_VER="${PRETTY_NAME:-unknown}" + +# Get uptime +UPTIME=$(uptime -p 2>/dev/null || echo "unknown") + +# Get memory +MEM=$(free -h 2>/dev/null | awk '/^Mem:/{print $3 "/" $2}' || echo "unknown") + +# Get load +LOAD=$(cat /proc/loadavg 2>/dev/null | awk '{print $1 " " $2 " " $3}' || echo "unknown") + +printf "${GREEN}╔══════════════════════════════════════════════════════════╗ +║ openWB 2.0 ║ +╚══════════════════════════════════════════════════════════╝${RESET} + Web UI: ${BOLD}http://${IP}/openWB/${RESET} + Status: $([ "$OWB_STATUS" = "active" ] && echo "$GREEN" || echo "$RED")${OWB_STATUS}${RESET} + Git: ${OWB_BRANCH} @ ${OWB_GIT} + OS: ${DEBIAN_VER} + Uptime: ${UPTIME} + Load: ${LOAD} + Memory: ${MEM} + + ${DIM}Logs: journalctl -u openwb2 -f${RESET} +" diff --git a/data/config/sudoers/apache2 b/data/config/sudoers/apache2 deleted file mode 100644 index 7d077feec1..0000000000 --- a/data/config/sudoers/apache2 +++ /dev/null @@ -1,2 +0,0 @@ -# openwb-version:1 -www-data ALL=NOPASSWD: /bin/systemctl restart openwb2.service, /bin/systemctl restart openwbRemoteSupport.service, /bin/systemctl restart mosquitto.service, /bin/systemctl restart mosquitto_local.service diff --git a/data/config/sudoers/caddy b/data/config/sudoers/caddy new file mode 100644 index 0000000000..5364ab7885 --- /dev/null +++ b/data/config/sudoers/caddy @@ -0,0 +1,2 @@ +# openwb-version:1 +caddy ALL=NOPASSWD: /bin/systemctl restart openwb2.service, /bin/systemctl restart openwbRemoteSupport.service, /bin/systemctl restart mosquitto.service, /bin/systemctl restart mosquitto_local.service diff --git a/docs/samples/sample_modbus/sample_modbus/bat.py b/docs/samples/sample_modbus/sample_modbus/bat.py index e13e03bfab..9c52d26f69 100644 --- a/docs/samples/sample_modbus/sample_modbus/bat.py +++ b/docs/samples/sample_modbus/sample_modbus/bat.py @@ -53,7 +53,7 @@ def update(self) -> None: # read_input_registers_bulk benötigit als Parameter das Startregister, die Anzahl der Register, # Register-Mapping und die Modbus-ID resp = self.client.read_input_registers_bulk( - Register.CURRENT_L1, 70, mapping=self.REG_MAPPING, unit=self.id) + Register.CURRENT_L1, 70, mapping=self.REG_MAPPING, device_id=self.id) imported, exported = self.peak_filter.check_values(resp[Register.POWER], resp[Register.IMPORTED], resp[Register.EXPORTED]) @@ -66,8 +66,8 @@ def update(self) -> None: self.store.set(bat_state) # Einzelregister lesen (dauert länger, bei sehr weit >100 auseinanderliegenden Registern sinnvoll) - power = self.client.read_holding_registers(reg, ModbusDataType.INT_32, unit=unit) - soc = self.client.read_holding_registers(reg, ModbusDataType.INT_32, unit=unit) + power = self.client.read_holding_registers(reg, ModbusDataType.INT_32, device_id=unit) + soc = self.client.read_holding_registers(reg, ModbusDataType.INT_32, device_id=unit) self.peak_filter.check_values(power) imported, exported = self.sim_counter.sim_count(power) diff --git a/docs/samples/sample_modbus/sample_modbus/counter.py b/docs/samples/sample_modbus/sample_modbus/counter.py index 8bf7d3b8b1..2e8f45de32 100644 --- a/docs/samples/sample_modbus/sample_modbus/counter.py +++ b/docs/samples/sample_modbus/sample_modbus/counter.py @@ -57,7 +57,7 @@ def update(self): # read_input_registers_bulk benötigit als Parameter das Startregister, die Anzahl der Register, # Register-Mapping und die Modbus-ID resp = self.client.read_input_registers_bulk( - Register.VOLTAGE_L1, 76, mapping=self.REG_MAPPING, unit=self.id) + Register.VOLTAGE_L1, 76, mapping=self.REG_MAPPING, device_id=self.id) imported, exported = self.peak_filter.check_values(sum(resp[Register.POWER_L1]), resp[Register.IMPORTED], resp[Register.EXPORTED]) @@ -74,7 +74,7 @@ def update(self): self.store.set(counter_state) # Einzelregister lesen (dauert länger, bei sehr weit >100 auseinanderliegenden Registern sinnvoll) - power = self.client.read_holding_registers(reg, ModbusDataType.INT_32, unit=unit) + power = self.client.read_holding_registers(reg, ModbusDataType.INT_32, device_id=unit) self.peak_filter.check_values(power) imported, exported = self.sim_counter.sim_count(power) diff --git a/docs/samples/sample_modbus/sample_modbus/inverter.py b/docs/samples/sample_modbus/sample_modbus/inverter.py index a46530a18c..cde8eee54a 100644 --- a/docs/samples/sample_modbus/sample_modbus/inverter.py +++ b/docs/samples/sample_modbus/sample_modbus/inverter.py @@ -51,7 +51,7 @@ def update(self) -> None: # read_input_registers_bulk benötigit als Parameter das Startregister, die Anzahl der Register, # Register-Mapping und die Modbus-ID resp = self.client.read_input_registers_bulk( - Register.CURRENT_L1, 70, mapping=self.REG_MAPPING, unit=self.id) + Register.CURRENT_L1, 70, mapping=self.REG_MAPPING, device_id=self.id) _, exported = self.peak_filter.check_values(resp[Register.POWER], None, resp[Register.EXPORTED]) inverter_state = InverterState( power=resp[Register.POWER], @@ -62,7 +62,7 @@ def update(self) -> None: self.store.set(inverter_state) # Einzelregister lesen (dauert länger, bei sehr weit >100 auseinanderliegenden Registern sinnvoll) - power = self.client.read_holding_registers(reg, ModbusDataType.INT_32, unit=unit) + power = self.client.read_holding_registers(reg, ModbusDataType.INT_32, device_id=unit) self.peak_filter.check_values(power) exported = self.sim_counter.sim_count(power)[1] diff --git a/openwb-install.sh b/openwb-install.sh index 5665357839..5bcb4c4a32 100755 --- a/openwb-install.sh +++ b/openwb-install.sh @@ -92,34 +92,50 @@ cp -a "${SRC}/openwb_local.conf" /etc/mosquitto/conf_local.d/ systemctl start mosquitto_local echo "mosquitto done" -# apache -echo -n "replacing apache default page..." -cp "${OPENWBBASEDIR}/data/config/apache/000-default.conf" "/etc/apache2/sites-available/" +# caddy + php-fpm +echo -n "configuring caddy web server..." cp "${OPENWBBASEDIR}/index.html" /var/www/html/index.html -echo "done" -echo -n "fix upload limit..." -if [ -d "/etc/php/7.3/" ]; then - echo "upload_max_filesize = 300M" > /etc/php/7.3/apache2/conf.d/20-uploadlimit.ini - echo "post_max_size = 300M" >> /etc/php/7.3/apache2/conf.d/20-uploadlimit.ini - echo "done (OS Buster)" -elif [ -d "/etc/php/7.4/" ]; then - echo "upload_max_filesize = 300M" > /etc/php/7.4/apache2/conf.d/20-uploadlimit.ini - echo "post_max_size = 300M" >> /etc/php/7.4/apache2/conf.d/20-uploadlimit.ini - echo "done (OS Bullseye)" +# ensure caddy can read webroot without changing file ownership +chmod -R a+rX /var/www/html +# fix php-fpm upload limit +php_dir="" +for dir in /etc/php/*/fpm/conf.d; do + if [ -d "$dir" ]; then + php_dir="$dir" + break + fi +done +if [ -n "$php_dir" ]; then + cp "${OPENWBBASEDIR}/data/config/php/fpm/20-uploadlimit.ini" "${php_dir}/20-uploadlimit.ini" + echo "PHP upload limit set ($(basename $(dirname $(dirname "$php_dir"))))" +else + echo "no PHP-FPM config directory found, skipping upload limit" fi -echo -n "enabling apache ssl module..." -a2enmod ssl -a2enmod proxy_wstunnel -sudo a2dissite default-ssl -sudo cp "${OPENWBBASEDIR}/data/config/apache/apache-openwb-ssl.conf" /etc/apache2/sites-available/ -sudo a2ensite apache-openwb-ssl +# start php-fpm +systemctl enable php*-fpm 2>/dev/null +systemctl start php*-fpm 2>/dev/null +# generate and install caddyfile +"${OPENWBBASEDIR}/runs/setup_caddy.sh" echo "done" -echo -n "restarting apache..." -systemctl restart apache2 + +echo "installing python requirements into venv..." +python3 -m venv /opt/openwb-venv +chown -R "$OPENWB_USER:$OPENWB_GROUP" /opt/openwb-venv +sudo -u "$OPENWB_USER" /opt/openwb-venv/bin/python3 -m pip install --upgrade pip +sudo -u "$OPENWB_USER" /opt/openwb-venv/bin/python3 -m pip install -r "${OPENWBBASEDIR}/requirements.txt" + +echo "configuring chrony NTP..." +systemctl stop systemd-timesyncd 2>/dev/null || true +systemctl disable systemd-timesyncd 2>/dev/null || true +cp "${OPENWBBASEDIR}/data/config/chrony/chrony.conf" /etc/chrony/chrony.conf +systemctl enable chrony +systemctl restart chrony echo "done" -echo "installing python requirements..." -sudo -u "$OPENWB_USER" pip install -r "${OPENWBBASEDIR}/requirements.txt" +echo "installing MOTD..." +cp "${OPENWBBASEDIR}/data/config/profile.d/99-openwb-motd.sh" /etc/profile.d/99-openwb-motd.sh +chmod 755 /etc/profile.d/99-openwb-motd.sh +echo "done" echo "installing openwb2 system service..." ln -s "${OPENWBBASEDIR}/data/config/openwb2.service" /etc/systemd/system/openwb2.service diff --git a/packages/control/ocpp.py b/packages/control/ocpp.py index 352357cffd..1a5f5f3b2c 100644 --- a/packages/control/ocpp.py +++ b/packages/control/ocpp.py @@ -1,5 +1,4 @@ from datetime import datetime, timezone -import json import logging from helpermodules.utils.error_handling import ImportErrorContext @@ -25,22 +24,22 @@ def _get_formatted_time(self: OptionalProtocol) -> str: def _process_call(self: OptionalProtocol, chargebox_id: str, fault_state: FaultState, - func: Callable) -> Optional[websockets.WebSocketClientProtocol]: - async def make_call() -> websockets.WebSocketClientProtocol: + func: Callable) -> Optional[tuple]: + async def make_call(): url = self.data.ocpp.config.url async with websockets.connect(f"{url}{'' if url.endswith('/') else '/'}{chargebox_id}", subprotocols=[self.data.ocpp.config.version]) as ws: + response = None try: cp = OcppChargepoint(chargebox_id, ws, 2) - await cp.call(func) + response = await cp.call(func) except asyncio.exceptions.TimeoutError: - # log.exception("Erwarteter TimeOut StartTransaction") pass - return ws + return ws, response try: if self.data.ocpp.config.active and chargebox_id: return asyncio.run(make_call()) - except websockets.exceptions.InvalidStatusCode: + except websockets.exceptions.InvalidStatus: fault_state.warning(f"Chargebox ID {chargebox_id} konnte nicht im OCPP-Backend gefunden werden oder " "URL des Backends ist falsch.") return None @@ -68,14 +67,17 @@ def start_transaction(self: OptionalProtocol, id_tag: str, imported: int) -> Optional[int]: try: - ws = self._process_call(chargebox_id, fault_state, call.StartTransaction( + result = self._process_call(chargebox_id, fault_state, call.StartTransaction( connector_id=connector_id, id_tag=id_tag if id_tag else "", meter_start=int(imported), timestamp=self._get_formatted_time() )) - if ws: - transaction_id = json.loads(ws.messages[0])[2]["transactionId"] + if result: + _ws, response = result + if response is None: + return None + transaction_id = response.transaction_id log.debug(f"Transaction ID: {transaction_id} für Chargebox ID: {chargebox_id} mit Tag: {id_tag} " f"und Zählerstand: {imported} erhalten.") return transaction_id diff --git a/packages/helpermodules/broker.py b/packages/helpermodules/broker.py index c9b6940c6f..d41cf45606 100644 --- a/packages/helpermodules/broker.py +++ b/packages/helpermodules/broker.py @@ -25,7 +25,7 @@ def __init__(self, port: int = 1886) -> None: try: self.name = f"openWB-{name}-{get_name_suffix()}" - self.client = mqtt.Client(self.name) + self.client = mqtt.Client(mqtt.CallbackAPIVersion.VERSION1, client_id=self.name) self.client.on_connect = on_connect self.client.on_message = on_message self.client.connect(host, port) @@ -48,7 +48,7 @@ def disconnect(self) -> None: class InternalBrokerPublisher: def __init__(self) -> None: try: - self.client = mqtt.Client(f"openWB-python-bulk-publisher-{get_name_suffix()}") + self.client = mqtt.Client(mqtt.CallbackAPIVersion.VERSION1, client_id=f"openWB-python-bulk-publisher-{get_name_suffix()}") self.client.connect("localhost", 1886) except Exception: log.exception("Fehler beim Verbindungsaufbau zum Bulk-Publisher") diff --git a/packages/helpermodules/create_debug.py b/packages/helpermodules/create_debug.py index 28f82085d0..69f8bbbc96 100644 --- a/packages/helpermodules/create_debug.py +++ b/packages/helpermodules/create_debug.py @@ -63,8 +63,11 @@ def get_common_data(): def get_hardware_data(): parsed_data = "" - temp = run_shell_command(["vcgencmd measure_temp"]).removeprefix("temp=").removesuffix("\n") - throttled = int(run_shell_command("vcgencmd get_throttled").removeprefix("throttled="), 16) + try: + temp = run_shell_command(["vcgencmd", "measure_temp"]).removeprefix("temp=").removesuffix("\n") + throttled = int(run_shell_command(["vcgencmd", "get_throttled"]).removeprefix("throttled="), 16) + except Exception: + return "Hardware data not available (vcgencmd not found or not a Raspberry Pi)\n" parsed_data += f"Temperature_C: {temp}" mask_undervoltage = 0b0001 mask_temp_limit = 0b1000 diff --git a/packages/modbus_control_tester.py b/packages/modbus_control_tester.py index f11ccbba5e..9588005d26 100755 --- a/packages/modbus_control_tester.py +++ b/packages/modbus_control_tester.py @@ -4,7 +4,7 @@ import logging import struct from typing import Optional -from pymodbus.client.sync import ModbusTcpClient +from pymodbus.client import ModbusTcpClient import time from modules.common import modbus from modules.common.modbus import ModbusDataType @@ -54,7 +54,7 @@ class ReadMode(Enum): def heartbeat_read(): - read_client.read_input_registers(10104, modbus.ModbusDataType.INT_16, unit=slave_id) + read_client.read_input_registers(10104, modbus.ModbusDataType.INT_16, device_id=slave_id) def read_reg(register: int, @@ -66,28 +66,28 @@ def read_reg(register: int, if action == Actions.READ_NUMBER: if read_mode == ReadMode.READ_INPUT_REG: if length > 1: - resp = read_client.read_input_registers(register, [data_type]*length, unit=slave_id) + resp = read_client.read_input_registers(register, [data_type]*length, device_id=slave_id) else: - resp = read_client.read_input_registers(register, data_type, unit=slave_id) + resp = read_client.read_input_registers(register, data_type, device_id=slave_id) elif read_mode == ReadMode.READ_HOLDING_REG: if length > 1: - resp = read_client.read_holding_registers(register, [data_type]*length, unit=slave_id) + resp = read_client.read_holding_registers(register, [data_type]*length, device_id=slave_id) else: - resp = read_client.read_holding_registers(register, data_type, unit=slave_id) + resp = read_client.read_holding_registers(register, data_type, device_id=slave_id) return resp elif action == Actions.READ_STR: if read_mode == ReadMode.READ_INPUT_REG: - resp = read_client.read_input_registers(register, [modbus.ModbusDataType.INT_16]*length, unit=slave_id) + resp = read_client.read_input_registers(register, [modbus.ModbusDataType.INT_16]*length, device_id=slave_id) elif read_mode == ReadMode.READ_HOLDING_REG: resp = read_client.read_holding_registers( - register, [modbus.ModbusDataType.INT_16]*length, unit=slave_id) + register, [modbus.ModbusDataType.INT_16]*length, device_id=slave_id) string = "" for word in resp: string += struct.pack(">h", word).decode("utf-8") return resp elif action == Actions.WRITE_VALUE: client = ModbusTcpClient(host, port=port) - client.write_registers(register, write_value, unit=slave_id) + client.write_registers(register, write_value, device_id=slave_id) return None except Exception: log.exception("Fehler") diff --git a/packages/modules/chargepoints/openwb_series2_satellit/chargepoint_module.py b/packages/modules/chargepoints/openwb_series2_satellit/chargepoint_module.py index 3a6b63979d..1272fb8660 100644 --- a/packages/modules/chargepoints/openwb_series2_satellit/chargepoint_module.py +++ b/packages/modules/chargepoints/openwb_series2_satellit/chargepoint_module.py @@ -148,16 +148,16 @@ def switch_phases(self, phases_to_use: int) -> None: time.sleep(5) if phases_to_use == 1: self._client.client.delegate.write_register( - 0x0001, 256, unit=self.ID_PHASE_SWITCH_UNIT) + 0x0001, 256, device_id=self.ID_PHASE_SWITCH_UNIT) time.sleep(1) self._client.client.delegate.write_register( - 0x0001, 512, unit=self.ID_PHASE_SWITCH_UNIT) + 0x0001, 512, device_id=self.ID_PHASE_SWITCH_UNIT) else: self._client.client.delegate.write_register( - 0x0002, 512, unit=self.ID_PHASE_SWITCH_UNIT) + 0x0002, 512, device_id=self.ID_PHASE_SWITCH_UNIT) time.sleep(1) self._client.client.delegate.write_register( - 0x0002, 256, unit=self.ID_PHASE_SWITCH_UNIT) + 0x0002, 256, device_id=self.ID_PHASE_SWITCH_UNIT) except AttributeError: self._create_client() self._validate_version() diff --git a/packages/modules/common/b23.py b/packages/modules/common/b23.py index affebbd9d0..b123c52e2e 100644 --- a/packages/modules/common/b23.py +++ b/packages/modules/common/b23.py @@ -46,7 +46,7 @@ def get_serial_number(self) -> str: # Modbus mapping version: 0x8910, 1 Register, only 2 bytes data_type = ModbusDataType.UINT_32 time.sleep(0.1) - value = self.client.read_holding_registers(0x8900, data_type, unit=self.id) + value = self.client.read_holding_registers(0x8900, data_type, device_id=self.id) return str(self.check_nan(value, value, data_type)) def get_currents(self) -> List[float]: @@ -55,14 +55,14 @@ def get_currents(self) -> List[float]: data_type = ModbusDataType.UINT_32 time.sleep(0.1) return [self.check_nan(val, val / 100, data_type) - for val in self.client.read_holding_registers(0x5B0C, [data_type]*3, unit=self.id)] + for val in self.client.read_holding_registers(0x5B0C, [data_type]*3, device_id=self.id)] def get_frequency(self) -> float: """Returns frequency in Hz. """ data_type = ModbusDataType.UINT_16 time.sleep(0.1) - raw_value = self.client.read_holding_registers(0x5B2C, data_type, unit=self.id) + raw_value = self.client.read_holding_registers(0x5B2C, data_type, device_id=self.id) return self.check_nan(raw_value, raw_value / 100, data_type) def get_imported(self) -> float: @@ -70,12 +70,12 @@ def get_imported(self) -> float: """ data_type = ModbusDataType.UINT_64 time.sleep(0.1) - raw_value = self.client.read_holding_registers(0x5000, data_type, unit=self.id) + raw_value = self.client.read_holding_registers(0x5000, data_type, device_id=self.id) return self.check_nan(raw_value, raw_value * 10, data_type) def get_exported(self) -> float: time.sleep(0.1) - return self.client.read_holding_registers(0x5004, ModbusDataType.UINT_64, unit=self.id) * 10 + return self.client.read_holding_registers(0x5004, ModbusDataType.UINT_64, device_id=self.id) * 10 def get_power(self) -> Tuple[List[float], float]: """Returns power per phase and total power. @@ -84,7 +84,7 @@ def get_power(self) -> Tuple[List[float], float]: time.sleep(0.1) # reading of total power and power per phase in one call powers = [self.check_nan(val, val / 100, data_type) - for val in self.client.read_holding_registers(0x5B14, [data_type]*4, unit=self.id)] + for val in self.client.read_holding_registers(0x5B14, [data_type]*4, device_id=self.id)] return powers[1:4], powers[0] def get_power_factors(self) -> List[float]: @@ -95,7 +95,7 @@ def get_power_factors(self) -> List[float]: data_type = ModbusDataType.INT_16 time.sleep(0.1) return [self.check_nan(val, val / 1000, data_type) - for val in self.client.read_holding_registers(0x5B3B, [data_type]*3, unit=self.id)] + for val in self.client.read_holding_registers(0x5B3B, [data_type]*3, device_id=self.id)] def get_voltages(self) -> List[float]: """Returns voltages for all 3 phases. @@ -103,7 +103,7 @@ def get_voltages(self) -> List[float]: data_type = ModbusDataType.UINT_32 time.sleep(0.1) values = [self.check_nan(val, val / 10, data_type) - for val in self.client.read_holding_registers(0x5B00, [data_type]*3, unit=self.id)] + for val in self.client.read_holding_registers(0x5B00, [data_type]*3, device_id=self.id)] return values def get_counter_state(self) -> CounterState: diff --git a/packages/modules/common/evse.py b/packages/modules/common/evse.py index dba788746b..d8642f05a9 100644 --- a/packages/modules/common/evse.py +++ b/packages/modules/common/evse.py @@ -35,9 +35,9 @@ def __init__(self, modbus_id: int, client: modbus.ModbusSerialClient_) -> None: self.id = modbus_id with client: time.sleep(0.1) - self.version = self.client.read_holding_registers(1005, ModbusDataType.UINT_16, unit=self.id) + self.version = self.client.read_holding_registers(1005, ModbusDataType.UINT_16, device_id=self.id) time.sleep(0.1) - self.max_current = self.client.read_holding_registers(2007, ModbusDataType.UINT_16, unit=self.id) + self.max_current = self.client.read_holding_registers(2007, ModbusDataType.UINT_16, device_id=self.id) with ModifyLoglevelContext(log, logging.DEBUG): log.debug(f"Firmware-Version der EVSE: {self.version}") if self.version < 17: @@ -50,7 +50,7 @@ def __init__(self, modbus_id: int, client: modbus.ModbusSerialClient_) -> None: def get_plug_charge_state(self) -> Tuple[bool, bool, float]: time.sleep(0.1) raw_set_current, _, state_number = self.client.read_holding_registers( - 1000, [ModbusDataType.UINT_16]*3, unit=self.id) + 1000, [ModbusDataType.UINT_16]*3, device_id=self.id) # remove leading zeros self.evse_current = int(raw_set_current) log.debug("Gesetzte Stromstärke EVSE: "+str(self.evse_current) + @@ -78,7 +78,7 @@ def get_evse_state(self) -> EvseState: def is_precise_current_active(self) -> bool: time.sleep(0.1) - value = self.client.read_holding_registers(2005, ModbusDataType.UINT_16, unit=self.id) + value = self.client.read_holding_registers(2005, ModbusDataType.UINT_16, device_id=self.id) with ModifyLoglevelContext(log, logging.DEBUG): if value & self.PRECISE_CURRENT_BIT: log.debug("Angabe der Ströme in 0,01A-Schritten ist aktiviert.") @@ -89,23 +89,23 @@ def is_precise_current_active(self) -> bool: def activate_precise_current(self) -> None: time.sleep(0.1) - value = self.client.read_holding_registers(2005, ModbusDataType.UINT_16, unit=self.id) + value = self.client.read_holding_registers(2005, ModbusDataType.UINT_16, device_id=self.id) if value & self.PRECISE_CURRENT_BIT: return else: with ModifyLoglevelContext(log, logging.DEBUG): log.debug("Bit zur Angabe der Ströme in 0,1A-Schritten wird gesetzt.") - self.client.write_register(2005, value ^ self.PRECISE_CURRENT_BIT, unit=self.id) + self.client.write_register(2005, value ^ self.PRECISE_CURRENT_BIT, device_id=self.id) # Zeit zum Verarbeiten geben time.sleep(1) def deactivate_precise_current(self) -> None: time.sleep(0.1) - value = self.client.read_holding_registers(2005, ModbusDataType.UINT_16, unit=self.id) + value = self.client.read_holding_registers(2005, ModbusDataType.UINT_16, device_id=self.id) if value & self.PRECISE_CURRENT_BIT: with ModifyLoglevelContext(log, logging.DEBUG): log.debug("Bit zur Angabe der Ströme in 0,1A-Schritten wird zurueckgesetzt.") - self.client.write_register(2005, value ^ self.PRECISE_CURRENT_BIT, unit=self.id) + self.client.write_register(2005, value ^ self.PRECISE_CURRENT_BIT, device_id=self.id) else: return @@ -118,4 +118,4 @@ def set_current(self, current: int, phases_in_use: Optional[int] = None) -> None current = 16 formatted_current = round(current*100) if self._precise_current else round(current) if self.evse_current != formatted_current: - self.client.write_register(1000, formatted_current, unit=self.id) + self.client.write_register(1000, formatted_current, device_id=self.id) diff --git a/packages/modules/common/lovato.py b/packages/modules/common/lovato.py index cb8a0b596e..3c7375cb5b 100644 --- a/packages/modules/common/lovato.py +++ b/packages/modules/common/lovato.py @@ -17,21 +17,21 @@ def __init__(self, modbus_id: int, client: modbus.ModbusTcpClient_, fault_state: def get_voltages(self) -> List[float]: return [val / 100 for val in self.client.read_input_registers( - 0x0001, [ModbusDataType.INT_32]*3, unit=self.id)] + 0x0001, [ModbusDataType.INT_32]*3, device_id=self.id)] def get_power(self) -> Tuple[List[float], float]: powers = [val / 100 for val in self.client.read_input_registers( - 0x0013, [ModbusDataType.INT_32]*3, unit=self.id + 0x0013, [ModbusDataType.INT_32]*3, device_id=self.id )] power = sum(powers) return powers, power def get_power_factors(self) -> List[float]: return [val / 10000 for val in self.client.read_input_registers( - 0x0025, [ModbusDataType.INT_32]*3, unit=self.id)] + 0x0025, [ModbusDataType.INT_32]*3, device_id=self.id)] def get_frequency(self) -> float: - frequency = self.client.read_input_registers(0x0031, ModbusDataType.INT_32, unit=self.id) / 100 + frequency = self.client.read_input_registers(0x0031, ModbusDataType.INT_32, device_id=self.id) / 100 if frequency > 100: # needed if external measurement clamps connected frequency = frequency / 10 @@ -39,7 +39,7 @@ def get_frequency(self) -> float: def get_currents(self) -> List[float]: return [val / 10000 for val in self.client.read_input_registers( - 0x0007, [ModbusDataType.INT_32]*3, unit=self.id)] + 0x0007, [ModbusDataType.INT_32]*3, device_id=self.id)] def get_counter_state(self) -> CounterState: powers, power = self.get_power() diff --git a/packages/modules/common/modbus.py b/packages/modules/common/modbus.py index 9f5fc13e50..65cec6db4f 100644 --- a/packages/modules/common/modbus.py +++ b/packages/modules/common/modbus.py @@ -11,10 +11,10 @@ from typing import Any, Callable, Iterable, Optional, Union, overload, List import pymodbus -from pymodbus.client.sync import ModbusTcpClient, ModbusUdpClient, ModbusSerialClient -from pymodbus.constants import Endian -from pymodbus.payload import BinaryPayloadBuilder, BinaryPayloadDecoder -from pymodbus.transaction import ModbusSocketFramer +from pymodbus.client import ModbusTcpClient, ModbusUdpClient, ModbusSerialClient +from modules.common.pymodbus_compat import Endian +from modules.common.pymodbus_compat import BinaryPayloadBuilder, BinaryPayloadDecoder +from pymodbus.framer import FramerType from urllib3.util import parse_url log = logging.getLogger(__name__) @@ -103,7 +103,7 @@ def divide_rounding_up(numerator: int, denominator: int): number_of_addresses = sum(divide_rounding_up( t.bits, _MODBUS_HOLDING_REGISTER_SIZE) for t in types) response = read_register_method( - address, number_of_addresses, **kwargs) + address, count=number_of_addresses, **kwargs) if response.isError(): raise Exception(__name__+" "+str(response)) decoder = BinaryPayloadDecoder.fromRegisters(response.registers, byteorder, wordorder) @@ -176,7 +176,7 @@ def read_coils(self, address: int, count: int, **kwargs) -> bool: def read_coils(self, address: int, count: int, **kwargs): try: - response = self._delegate.read_coils(address, count, **kwargs) + response = self._delegate.read_coils(address, count=count, **kwargs) if response.isError(): raise Exception(__name__+" "+str(response)) return response.bits[0] if count == 1 else response.bits[:count] @@ -235,7 +235,7 @@ def __read_bulk(self, if self.is_socket_open() is False: self.connect() try: - response = read_register_method(start_address, count, **kwargs) + response = read_register_method(start_address, count=count, **kwargs) if response.isError(): raise Exception(__name__+" "+str(response)) decoder = BinaryPayloadDecoder.fromRegisters(response.registers, byteorder, wordorder) @@ -299,13 +299,13 @@ def __init__(self, address: str, port: int = 502, sleep_after_connect: Optional[int] = 0, - framer: type[ModbusSocketFramer] = ModbusSocketFramer, + framer=FramerType.SOCKET, **kwargs): parsed_url = parse_url(address) host = parsed_url.host if parsed_url.port is not None: port = parsed_url.port - super().__init__(ModbusTcpClient(host, port, framer, **kwargs), address, port, sleep_after_connect) + super().__init__(ModbusTcpClient(host, port=port, framer=framer, **kwargs), address, port, sleep_after_connect) class ModbusUdpClient_(ModbusClient): @@ -318,7 +318,7 @@ def __init__(self, host = parsed_url.host if parsed_url.port is not None: port = parsed_url.port - super().__init__(ModbusUdpClient(host, port, **kwargs), address, port, sleep_after_connect) + super().__init__(ModbusUdpClient(host, port=port, **kwargs), address, port, sleep_after_connect) class ModbusSerialClient_(ModbusClient): @@ -326,8 +326,8 @@ def __init__(self, port: int, sleep_after_connect: Optional[int] = 0, **kwargs): - super().__init__(ModbusSerialClient(method="rtu", - port=port, + super().__init__(ModbusSerialClient(port, + framer=FramerType.RTU, baudrate=9600, stopbits=1, bytesize=8, diff --git a/packages/modules/common/mpm3pm.py b/packages/modules/common/mpm3pm.py index 4791398dc7..59844a00f7 100644 --- a/packages/modules/common/mpm3pm.py +++ b/packages/modules/common/mpm3pm.py @@ -17,40 +17,40 @@ def __init__(self, modbus_id: int, client: modbus.ModbusTcpClient_, fault_state: def get_voltages(self) -> List[float]: return [val / 10 for val in self.client.read_input_registers( - 0x08, [ModbusDataType.UINT_32]*3, unit=self.id)] + 0x08, [ModbusDataType.UINT_32]*3, device_id=self.id)] def get_imported(self) -> float: # Faktorisierung anders als in der Dokumentation angegeben - return self.client.read_input_registers(0x0002, ModbusDataType.UINT_32, unit=self.id) * 10 + return self.client.read_input_registers(0x0002, ModbusDataType.UINT_32, device_id=self.id) * 10 def get_power(self) -> Tuple[List[float], float]: powers = [val / 100 for val in self.client.read_input_registers( - 0x14, [ModbusDataType.INT_32]*3, unit=self.id)] - power = self.client.read_input_registers(0x26, ModbusDataType.INT_32, unit=self.id) / 100 + 0x14, [ModbusDataType.INT_32]*3, device_id=self.id)] + power = self.client.read_input_registers(0x26, ModbusDataType.INT_32, device_id=self.id) / 100 return powers, power def get_exported(self) -> float: # Faktorisierung anders als in der Dokumentation angegeben - return self.client.read_input_registers(0x0004, ModbusDataType.UINT_32, unit=self.id) * 10 + return self.client.read_input_registers(0x0004, ModbusDataType.UINT_32, device_id=self.id) * 10 def get_power_factors(self) -> List[float]: # Faktorisierung anders als in der Dokumentation angegeben? factors = [val / 10 for val in self.client.read_input_registers( - 0x20, [ModbusDataType.UINT_32]*3, unit=self.id)] + 0x20, [ModbusDataType.UINT_32]*3, device_id=self.id)] # check if the absolute value of an entry in factors is greater 1 if any([abs(factor) > 1 for factor in factors]): factors = [factor / 100 for factor in factors] return factors def get_frequency(self) -> float: - return self.client.read_input_registers(0x2c, ModbusDataType.UINT_32, unit=self.id) / 100 + return self.client.read_input_registers(0x2c, ModbusDataType.UINT_32, device_id=self.id) / 100 def get_currents(self) -> List[float]: return [val / 100 for val in self.client.read_input_registers( - 0x0E, [ModbusDataType.UINT_32]*3, unit=self.id)] + 0x0E, [ModbusDataType.UINT_32]*3, device_id=self.id)] def get_serial_number(self) -> str: - return str(self.client.read_input_registers(0x33, ModbusDataType.UINT_32, unit=self.id)) + return str(self.client.read_input_registers(0x33, ModbusDataType.UINT_32, device_id=self.id)) def get_counter_state(self) -> CounterState: powers, power = self.get_power() diff --git a/packages/modules/common/pymodbus_compat.py b/packages/modules/common/pymodbus_compat.py new file mode 100644 index 0000000000..910fef810a --- /dev/null +++ b/packages/modules/common/pymodbus_compat.py @@ -0,0 +1,118 @@ +import struct + + +class Endian: + Big = "big" + Little = "little" + + +class BinaryPayloadDecoder: + def __init__(self, payload, byteorder="big", wordorder="big"): + self._payload = payload + self._bo = byteorder + self._wo = wordorder + self._ptr = 0 + + @classmethod + def fromRegisters(cls, registers, byteorder="big", wordorder="big"): + if wordorder == "little": + registers = list(reversed(registers)) + raw = b"" + for r in registers: + raw += struct.pack(">H", r) + return cls(raw, byteorder, wordorder) + + def reset(self): + self._ptr = 0 + + def skip_bytes(self, n): + self._ptr += n + + def _decode(self, fmt): + sz = struct.calcsize(fmt) + data = self._payload[self._ptr:self._ptr + sz] + self._ptr += sz + if ">" not in fmt and "<" not in fmt: + fmt = ">" + fmt + return struct.unpack(fmt, data)[0] + + def decode_8bit_uint(self): + return self._decode("B") + + def decode_16bit_uint(self): + return self._decode(">H") + + def decode_16bit_int(self): + return self._decode(">h") + + def decode_32bit_uint(self): + return self._decode(">I") + + def decode_32bit_int(self): + return self._decode(">i") + + def decode_64bit_uint(self): + return self._decode(">Q") + + def decode_64bit_int(self): + return self._decode(">q") + + def decode_32bit_float(self): + return self._decode(">f") + + def decode_64bit_float(self): + return self._decode(">d") + + +class BinaryPayloadBuilder: + def __init__(self, byteorder="big", wordorder="big"): + self._bo = byteorder + self._wo = wordorder + self._regs = [] + + def reset(self): + self._regs = [] + + def _add(self, value, fmt): + if ">" not in fmt and "<" not in fmt: + fmt = ">" + fmt + data = struct.pack(fmt, value) + regs = [] + for i in range(0, len(data), 2): + chunk = data[i:i+2] + if len(chunk) == 1: + chunk = b"\x00" + chunk + regs.append(struct.unpack(">H", chunk)[0]) + if self._wo == "little": + regs.reverse() + self._regs.extend(regs) + + def add_8bit_uint(self, v): + self._add(v, "B") + + def add_16bit_uint(self, v): + self._add(v, ">H") + + def add_16bit_int(self, v): + self._add(v, ">h") + + def add_32bit_uint(self, v): + self._add(v, ">I") + + def add_32bit_int(self, v): + self._add(v, ">i") + + def add_64bit_uint(self, v): + self._add(v, ">Q") + + def add_64bit_int(self, v): + self._add(v, ">q") + + def add_32bit_float(self, v): + self._add(v, ">f") + + def add_64bit_float(self, v): + self._add(v, ">d") + + def to_registers(self): + return list(self._regs) diff --git a/packages/modules/common/sdm.py b/packages/modules/common/sdm.py index 6fe1cd62ed..0d6d53d321 100644 --- a/packages/modules/common/sdm.py +++ b/packages/modules/common/sdm.py @@ -20,12 +20,12 @@ def __init__(self, modbus_id: int, client: modbus.ModbusTcpClient_) -> None: self.id = modbus_id self.fast_mode = True with client: - self.serial_number = str(self.client.read_holding_registers(0xFC00, ModbusDataType.UINT_32, unit=self.id)) + self.serial_number = str(self.client.read_holding_registers(0xFC00, ModbusDataType.UINT_32, device_id=self.id)) def get_imported(self) -> float: # smarthome legacy time.sleep(0.1) - return self.client.read_input_registers(0x0048, ModbusDataType.FLOAT_32, unit=self.id) * 1000 + return self.client.read_input_registers(0x0048, ModbusDataType.FLOAT_32, device_id=self.id) * 1000 class SdmRegister(IntEnum): @@ -57,14 +57,14 @@ def __init__(self, modbus_id: int, client: modbus.ModbusTcpClient_, fault_state: def get_power(self) -> Tuple[List[float], float]: # smarthome legacy time.sleep(0.1) - powers = self.client.read_input_registers(0x0C, [ModbusDataType.FLOAT_32]*3, unit=self.id) + powers = self.client.read_input_registers(0x0C, [ModbusDataType.FLOAT_32]*3, device_id=self.id) power = sum(powers) return powers, power def get_voltages(self) -> Tuple[List[float], float]: # client handler time.sleep(0.1) - return self.client.read_input_registers(0x00, [ModbusDataType.FLOAT_32]*3, unit=self.id) + return self.client.read_input_registers(0x00, [ModbusDataType.FLOAT_32]*3, device_id=self.id) def get_counter_state(self) -> CounterState: # entgegen der Doku können nicht bei allen SDM72 80 Register auf einmal gelesen werden, @@ -73,18 +73,18 @@ def get_counter_state(self) -> CounterState: try: time.sleep(0.1) bulk_1 = self.client.read_input_registers_bulk( - SdmRegister.VOLTAGE_L1, 18, mapping=self.REG_MAPPING_BULK_1, unit=self.id) + SdmRegister.VOLTAGE_L1, 18, mapping=self.REG_MAPPING_BULK_1, device_id=self.id) time.sleep(0.1) power_factors = self.client.read_input_registers( - SdmRegister.POWER_FACTOR_L1, [ModbusDataType.FLOAT_32]*3, unit=self.id) + SdmRegister.POWER_FACTOR_L1, [ModbusDataType.FLOAT_32]*3, device_id=self.id) time.sleep(0.1) bulk_2 = self.client.read_input_registers_bulk( - SdmRegister.FREQUENCY, 6, mapping=self.REG_MAPPING_BULK_2, unit=self.id) + SdmRegister.FREQUENCY, 6, mapping=self.REG_MAPPING_BULK_2, device_id=self.id) resp = {**bulk_1, **bulk_2} except Exception: log.exception("Fehler beim Auslesen des Zählers") self.client.read_input_registers( - SdmRegister.VOLTAGE_L1, [ModbusDataType.FLOAT_32]*3, unit=self.id) + SdmRegister.VOLTAGE_L1, [ModbusDataType.FLOAT_32]*3, device_id=self.id) self.fast_mode = False if self.fast_mode is False: # im gleichen Durchlauf noch im slow mode versuchen, sonst schlägt der Hardware-Check fehl @@ -92,23 +92,23 @@ def get_counter_state(self) -> CounterState: resp = {} time.sleep(0.1) resp[SdmRegister.VOLTAGE_L1] = self.client.read_input_registers( - SdmRegister.VOLTAGE_L1, [ModbusDataType.FLOAT_32]*3, unit=self.id) + SdmRegister.VOLTAGE_L1, [ModbusDataType.FLOAT_32]*3, device_id=self.id) time.sleep(0.1) resp[SdmRegister.CURRENT_L1] = self.client.read_input_registers( - SdmRegister.CURRENT_L1, [ModbusDataType.FLOAT_32]*3, unit=self.id) + SdmRegister.CURRENT_L1, [ModbusDataType.FLOAT_32]*3, device_id=self.id) time.sleep(0.1) resp[SdmRegister.POWER_L1] = self.client.read_input_registers( - SdmRegister.POWER_L1, [ModbusDataType.FLOAT_32]*3, unit=self.id) + SdmRegister.POWER_L1, [ModbusDataType.FLOAT_32]*3, device_id=self.id) time.sleep(0.1) power_factors = self.client.read_input_registers( - SdmRegister.POWER_FACTOR_L1, [ModbusDataType.FLOAT_32]*3, unit=self.id) + SdmRegister.POWER_FACTOR_L1, [ModbusDataType.FLOAT_32]*3, device_id=self.id) time.sleep(0.1) # frequency noch mit auslesen klappt nicht resp[SdmRegister.IMPORTED], resp[SdmRegister.EXPORTED] = self.client.read_input_registers( - SdmRegister.IMPORTED, [ModbusDataType.FLOAT_32]*2, unit=self.id) + SdmRegister.IMPORTED, [ModbusDataType.FLOAT_32]*2, device_id=self.id) time.sleep(0.1) resp[SdmRegister.FREQUENCY] = self.client.read_input_registers( - SdmRegister.FREQUENCY, ModbusDataType.FLOAT_32, unit=self.id) + SdmRegister.FREQUENCY, ModbusDataType.FLOAT_32, device_id=self.id) frequency = resp[SdmRegister.FREQUENCY] if frequency > 100: @@ -147,19 +147,19 @@ def __init__(self, modbus_id: int, client: modbus.ModbusTcpClient_, fault_state: def get_power(self) -> Tuple[List[float], float]: # smarthome legacy time.sleep(0.1) - power = self.client.read_input_registers(0x0C, ModbusDataType.FLOAT_32, unit=self.id) + power = self.client.read_input_registers(0x0C, ModbusDataType.FLOAT_32, device_id=self.id) return [power, 0, 0], power def get_counter_state(self) -> CounterState: # beim SDM120 steht nichts von Bulk-Reads in der Doku, daher auch auf 20 Register limitiert time.sleep(0.1) bulk_1 = self.client.read_input_registers_bulk( - SdmRegister.VOLTAGE_L1, 14, mapping=self.REG_MAPPING_BULK_1, unit=self.id) + SdmRegister.VOLTAGE_L1, 14, mapping=self.REG_MAPPING_BULK_1, device_id=self.id) time.sleep(0.1) - power_factor = self.client.read_input_registers(0x1E, ModbusDataType.FLOAT_32, unit=self.id) + power_factor = self.client.read_input_registers(0x1E, ModbusDataType.FLOAT_32, device_id=self.id) time.sleep(0.1) bulk_2 = self.client.read_input_registers_bulk( - SdmRegister.FREQUENCY, 6, mapping=self.REG_MAPPING_BULK_2, unit=self.id) + SdmRegister.FREQUENCY, 6, mapping=self.REG_MAPPING_BULK_2, device_id=self.id) resp = {**bulk_1, **bulk_2} frequency = resp[SdmRegister.FREQUENCY] if frequency > 100: diff --git a/packages/modules/conftest.py b/packages/modules/conftest.py index 9733696c81..e88978c896 100644 --- a/packages/modules/conftest.py +++ b/packages/modules/conftest.py @@ -20,11 +20,17 @@ # sys.modules['telnetlib3'] = type(sys)('telnetlib3') -module = type(sys)('pymodbus.client.sync') +module = type(sys)('pymodbus.client') module.ModbusSerialClient = Mock() module.ModbusTcpClient = Mock() module.ModbusUdpClient = Mock() -sys.modules['pymodbus.client.sync'] = module +sys.modules['pymodbus.client'] = module + +module = type(sys)('pymodbus.framer') +module.FramerType = Mock() +module.FramerType.SOCKET = 'socket' +module.FramerType.RTU = 'rtu' +sys.modules['pymodbus.framer'] = module module = type(sys)('pymodbus.constants') module.Endian = Mock() @@ -35,8 +41,6 @@ sys.modules['pymodbus.payload'] = module module = type(sys)('pymodbus.transaction') -module.ModbusSocketFramer = Mock() -module.ModbusRtuFramer = Mock() sys.modules['pymodbus.transaction'] = module module = type(sys)('socketserver') diff --git a/packages/modules/devices/algodue/algodue/bat.py b/packages/modules/devices/algodue/algodue/bat.py index 5ceee007e5..70c1478aa1 100644 --- a/packages/modules/devices/algodue/algodue/bat.py +++ b/packages/modules/devices/algodue/algodue/bat.py @@ -36,8 +36,8 @@ def initialize(self) -> None: def update(self): currents = self.__tcp_client.read_input_registers( - 0x100E, [ModbusDataType.FLOAT_32]*3, unit=self.__modbus_id) - powers = self.__tcp_client.read_input_registers(0x1020, [ModbusDataType.FLOAT_32]*3, unit=self.__modbus_id) + 0x100E, [ModbusDataType.FLOAT_32]*3, device_id=self.__modbus_id) + powers = self.__tcp_client.read_input_registers(0x1020, [ModbusDataType.FLOAT_32]*3, device_id=self.__modbus_id) power = sum(powers) self.peak_filter.check_values(power) diff --git a/packages/modules/devices/algodue/algodue/counter.py b/packages/modules/devices/algodue/algodue/counter.py index 805410400f..7d46d7bba0 100644 --- a/packages/modules/devices/algodue/algodue/counter.py +++ b/packages/modules/devices/algodue/algodue/counter.py @@ -35,15 +35,15 @@ def initialize(self) -> None: self.peak_filter = PeakFilter(ComponentType.COUNTER, self.component_config.id, self.fault_state) def update(self): - frequency = self.__tcp_client.read_input_registers(0x1038, ModbusDataType.FLOAT_32, unit=self.__modbus_id) + frequency = self.__tcp_client.read_input_registers(0x1038, ModbusDataType.FLOAT_32, device_id=self.__modbus_id) currents = self.__tcp_client.read_input_registers( - 0x100E, [ModbusDataType.FLOAT_32]*3, unit=self.__modbus_id) - powers = self.__tcp_client.read_input_registers(0x1020, [ModbusDataType.FLOAT_32]*3, unit=self.__modbus_id) + 0x100E, [ModbusDataType.FLOAT_32]*3, device_id=self.__modbus_id) + powers = self.__tcp_client.read_input_registers(0x1020, [ModbusDataType.FLOAT_32]*3, device_id=self.__modbus_id) power = sum(powers) voltages = self.__tcp_client.read_input_registers( - 0x1000, [ModbusDataType.FLOAT_32]*3, unit=self.__modbus_id) + 0x1000, [ModbusDataType.FLOAT_32]*3, device_id=self.__modbus_id) power_factors = self.__tcp_client.read_input_registers( - 0x1018, [ModbusDataType.FLOAT_32]*3, unit=self.__modbus_id) + 0x1018, [ModbusDataType.FLOAT_32]*3, device_id=self.__modbus_id) self.peak_filter.check_values(power) imported, exported = self.sim_counter.sim_count(power) @@ -63,8 +63,8 @@ def update(self): component_descriptor = ComponentDescriptor(configuration_factory=AlgodueCounterSetup) -# serial_chars = self.client.read_holding_registers(0x500, [ModbusDataType.UINT_8]*10, unit=self.id) -# model_id = self.client.read_holding_registers(0x505, ModbusDataType.UINT_16, unit=self.id) +# serial_chars = self.client.read_holding_registers(0x500, [ModbusDataType.UINT_8]*10, device_id=self.id) +# model_id = self.client.read_holding_registers(0x505, ModbusDataType.UINT_16, device_id=self.id) # model_string = "unknown" # if model_id == 0x03: # model_string = "6 A, 3 phases, 4 wires" @@ -77,7 +77,7 @@ def update(self): # elif model_id == 0x12: # model_string = "63 A, 3 phases, 4 wires" -# type_id = self.client.read_holding_registers(0x506, ModbusDataType.UINT_16, unit=self.id) +# type_id = self.client.read_holding_registers(0x506, ModbusDataType.UINT_16, device_id=self.id) # type_string = "unknown" # if type_id == 0x00: # type_string = "NO MID, RESET" diff --git a/packages/modules/devices/algodue/algodue/inverter.py b/packages/modules/devices/algodue/algodue/inverter.py index b8cd036822..2d30d731d5 100644 --- a/packages/modules/devices/algodue/algodue/inverter.py +++ b/packages/modules/devices/algodue/algodue/inverter.py @@ -36,8 +36,8 @@ def initialize(self) -> None: def update(self): currents = self.__tcp_client.read_input_registers( - 0x100E, [ModbusDataType.FLOAT_32]*3, unit=self.__modbus_id) - powers = self.__tcp_client.read_input_registers(0x1020, [ModbusDataType.FLOAT_32]*3, unit=self.__modbus_id) + 0x100E, [ModbusDataType.FLOAT_32]*3, device_id=self.__modbus_id) + powers = self.__tcp_client.read_input_registers(0x1020, [ModbusDataType.FLOAT_32]*3, device_id=self.__modbus_id) power = sum(powers) self.peak_filter.check_values(power) diff --git a/packages/modules/devices/alpha_ess/alpha_ess/bat.py b/packages/modules/devices/alpha_ess/alpha_ess/bat.py index 8663913cc5..c72c0228ba 100644 --- a/packages/modules/devices/alpha_ess/alpha_ess/bat.py +++ b/packages/modules/devices/alpha_ess/alpha_ess/bat.py @@ -39,9 +39,9 @@ def update(self) -> None: # keine Unterschiede zwischen den Versionen time.sleep(0.1) - voltage = self.__tcp_client.read_holding_registers(0x0100, ModbusDataType.INT_16, unit=self.__modbus_id) + voltage = self.__tcp_client.read_holding_registers(0x0100, ModbusDataType.INT_16, device_id=self.__modbus_id) time.sleep(0.1) - current = self.__tcp_client.read_holding_registers(0x0101, ModbusDataType.INT_16, unit=self.__modbus_id) + current = self.__tcp_client.read_holding_registers(0x0101, ModbusDataType.INT_16, device_id=self.__modbus_id) power = voltage * current * -1 / 100 log.debug( @@ -49,7 +49,7 @@ def update(self) -> None: (power, voltage, current) ) time.sleep(0.1) - soc_reg = self.__tcp_client.read_holding_registers(0x0102, ModbusDataType.INT_16, unit=self.__modbus_id) + soc_reg = self.__tcp_client.read_holding_registers(0x0102, ModbusDataType.INT_16, device_id=self.__modbus_id) soc = int(soc_reg * 0.1) self.peak_filter.check_values(power) @@ -69,7 +69,7 @@ def set_power_limit(self, power_limit: Optional[int]) -> None: # Kein Powerlimit gefordert, externe Steuerung deaktivieren log.debug("Keine Batteriesteuerung gefordert, deaktiviere externe Steuerung.") if self.last_mode is not None: - self.__tcp_client.write_register(2127, 0, data_type=ModbusDataType.UINT_16, unit=unit) + self.__tcp_client.write_register(2127, 0, data_type=ModbusDataType.UINT_16, device_id=unit) self.last_mode = None elif power_limit <= 0: # AlphaESS kann die Entladung nur über den SoC verhindern (komplette Entladesperre) @@ -77,15 +77,15 @@ def set_power_limit(self, power_limit: Optional[int]) -> None: # Zeiten für Netzladung müssen im Wechselrichter aktiviert werden log.debug("Aktive Batteriesteuerung angestoßen. Setze Entladesperre.") if self.last_mode != 'stop': - self.__tcp_client.write_register(2127, 1, data_type=ModbusDataType.UINT_16, unit=unit) - self.__tcp_client.write_register(2133, 10, data_type=ModbusDataType.UINT_16, unit=unit) + self.__tcp_client.write_register(2127, 1, data_type=ModbusDataType.UINT_16, device_id=unit) + self.__tcp_client.write_register(2133, 10, data_type=ModbusDataType.UINT_16, device_id=unit) self.last_mode = 'stop' else: # Aktive Ladung log.debug("Aktive Batteriesteuerung angestoßen. Setze aktive Ladung.") if self.last_mode != 'charge': - self.__tcp_client.write_register(2127, 1, data_type=ModbusDataType.UINT_16, unit=unit) - self.__tcp_client.write_register(2133, 100, data_type=ModbusDataType.UINT_16, unit=unit) + self.__tcp_client.write_register(2127, 1, data_type=ModbusDataType.UINT_16, device_id=unit) + self.__tcp_client.write_register(2133, 100, data_type=ModbusDataType.UINT_16, device_id=unit) self.last_mode = 'charge' def power_limit_controllable(self) -> bool: diff --git a/packages/modules/devices/alpha_ess/alpha_ess/counter.py b/packages/modules/devices/alpha_ess/alpha_ess/counter.py index ea184ee888..11cec1561c 100644 --- a/packages/modules/devices/alpha_ess/alpha_ess/counter.py +++ b/packages/modules/devices/alpha_ess/alpha_ess/counter.py @@ -37,12 +37,12 @@ def update(self): time.sleep(0.1) if self.__device_config.source == 0 and self.__device_config.version == 0: power, exported, imported = self.__tcp_client.read_holding_registers( - 0x6, [modbus.ModbusDataType.INT_32] * 3, unit=self.__modbus_id) + 0x6, [modbus.ModbusDataType.INT_32] * 3, device_id=self.__modbus_id) exported *= 10 imported *= 10 imported, exported = self.peak_filter.check_values(power, imported, exported) currents = [val / 230 for val in self.__tcp_client.read_holding_registers( - 0x0000, [ModbusDataType.INT_32]*3, unit=self.__modbus_id)] + 0x0000, [ModbusDataType.INT_32]*3, device_id=self.__modbus_id)] counter_state = CounterState( currents=currents, imported=imported, @@ -50,18 +50,18 @@ def update(self): power=power ) else: - power = self.__tcp_client.read_holding_registers(0x0021, ModbusDataType.INT_32, unit=self.__modbus_id) + power = self.__tcp_client.read_holding_registers(0x0021, ModbusDataType.INT_32, device_id=self.__modbus_id) exported, imported = [ val * 10 for val in self.__tcp_client.read_holding_registers( - 0x0010, [ModbusDataType.INT_32] * 2, unit=self.__modbus_id + 0x0010, [ModbusDataType.INT_32] * 2, device_id=self.__modbus_id )] imported, exported = self.peak_filter.check_values(power, imported, exported) frequency = self.__tcp_client.read_holding_registers( - 0x001A, ModbusDataType.UINT_16, unit=self.__modbus_id) / 100 + 0x001A, ModbusDataType.UINT_16, device_id=self.__modbus_id) / 100 currents = self.__tcp_client.read_holding_registers( - 0x0017, [ModbusDataType.INT_16]*3, unit=self.__modbus_id) + 0x0017, [ModbusDataType.INT_16]*3, device_id=self.__modbus_id) powers = self.__tcp_client.read_holding_registers( - 0x001b, [ModbusDataType.INT_32]*3, unit=self.__modbus_id) + 0x001b, [ModbusDataType.INT_32]*3, device_id=self.__modbus_id) currents = scale_currents(currents, powers) counter_state = CounterState( currents=currents, diff --git a/packages/modules/devices/alpha_ess/alpha_ess/inverter.py b/packages/modules/devices/alpha_ess/alpha_ess/inverter.py index d38a28bdda..512d234918 100644 --- a/packages/modules/devices/alpha_ess/alpha_ess/inverter.py +++ b/packages/modules/devices/alpha_ess/alpha_ess/inverter.py @@ -56,7 +56,7 @@ def __version_factory(self) -> int: def __get_power(self, reg_p: int) -> Number: powers = [ - self.__tcp_client.read_holding_registers(address, ModbusDataType.INT_32, unit=self.__modbus_id) + self.__tcp_client.read_holding_registers(address, ModbusDataType.INT_32, device_id=self.__modbus_id) for address in [reg_p, 0x041F, 0x0423, 0x0427] ] powers[0] = abs(powers[0]) diff --git a/packages/modules/devices/ampere/ampere/bat.py b/packages/modules/devices/ampere/ampere/bat.py index 1ee8a9269c..8cf0c878fb 100644 --- a/packages/modules/devices/ampere/ampere/bat.py +++ b/packages/modules/devices/ampere/ampere/bat.py @@ -36,8 +36,8 @@ def initialize(self) -> None: self.client = self.kwargs['client'] def update(self) -> None: - power = self.client.read_input_registers(535, ModbusDataType.INT_16, unit=self.modbus_id) * -1 - soc = self.client.read_input_registers(1339, ModbusDataType.UINT_16, unit=self.modbus_id) + power = self.client.read_input_registers(535, ModbusDataType.INT_16, device_id=self.modbus_id) * -1 + soc = self.client.read_input_registers(1339, ModbusDataType.UINT_16, device_id=self.modbus_id) self.peak_filter.check_values(power) imported, exported = self.sim_counter.sim_count(power) diff --git a/packages/modules/devices/ampere/ampere/counter.py b/packages/modules/devices/ampere/ampere/counter.py index 5ecc06f901..ec377b593b 100644 --- a/packages/modules/devices/ampere/ampere/counter.py +++ b/packages/modules/devices/ampere/ampere/counter.py @@ -36,8 +36,8 @@ def initialize(self) -> None: self.peak_filter = PeakFilter(ComponentType.COUNTER, self.component_config.id, self.fault_state) def update(self): - powers = self.client.read_input_registers(1349, [ModbusDataType.INT_16]*3, unit=self.modbus_id) - power = self.client.read_input_registers(1348, ModbusDataType.INT_16, unit=self.modbus_id) + powers = self.client.read_input_registers(1349, [ModbusDataType.INT_16]*3, device_id=self.modbus_id) + power = self.client.read_input_registers(1348, ModbusDataType.INT_16, device_id=self.modbus_id) self.peak_filter.check_values(power) imported, exported = self.sim_counter.sim_count(power) diff --git a/packages/modules/devices/ampere/ampere/inverter.py b/packages/modules/devices/ampere/ampere/inverter.py index 8fcbc47ed0..daed698483 100644 --- a/packages/modules/devices/ampere/ampere/inverter.py +++ b/packages/modules/devices/ampere/ampere/inverter.py @@ -36,8 +36,8 @@ def initialize(self) -> None: self.peak_filter = PeakFilter(ComponentType.INVERTER, self.component_config.id, self.fault_state) def update(self) -> None: - pv1_power = self.client.read_holding_registers(519, ModbusDataType.INT_16, unit=self.modbus_id) * -1 - pv2_power = self.client.read_holding_registers(522, ModbusDataType.INT_16, unit=self.modbus_id) * -1 + pv1_power = self.client.read_holding_registers(519, ModbusDataType.INT_16, device_id=self.modbus_id) * -1 + pv2_power = self.client.read_holding_registers(522, ModbusDataType.INT_16, device_id=self.modbus_id) * -1 power = pv1_power + pv2_power diff --git a/packages/modules/devices/azzurro_zcs/azzurro_zcs/bat.py b/packages/modules/devices/azzurro_zcs/azzurro_zcs/bat.py index f13cd5b59a..d595bd90ec 100644 --- a/packages/modules/devices/azzurro_zcs/azzurro_zcs/bat.py +++ b/packages/modules/devices/azzurro_zcs/azzurro_zcs/bat.py @@ -33,15 +33,15 @@ def update(self) -> None: # 0x020D Battery charge-discharge power Int16 -10-10 kW accuracy 0,01 kW pos charge, neg discharge # 0x020E Battery voltage Cell UInt16 0-100 V accuracy 0,1 V # 0x020F Battery charge-discharge current Int -100-100 A accuracy 0,01A - power = self.client.read_input_registers(0x020D, ModbusDataType.INT_16, unit=self.__modbus_id) + power = self.client.read_input_registers(0x020D, ModbusDataType.INT_16, device_id=self.__modbus_id) # 0x0210 SoC UInt16 0-100 % - soc = self.client.read_input_registers(0x0210, ModbusDataType.UINT_16, unit=self.__modbus_id) + soc = self.client.read_input_registers(0x0210, ModbusDataType.UINT_16, device_id=self.__modbus_id) # 0x0227 Total energy charging battery low UInt16 in kWh LSB imported = self.client.read_input_registers( - 0x0227, ModbusDataType.UINT_16, unit=self.__modbus_id) * 100 + 0x0227, ModbusDataType.UINT_16, device_id=self.__modbus_id) * 100 # 0x0229 Total energy discharging battery low UInt16 in kWh LSB exported = self.client.read_input_registers( - 0x0229, ModbusDataType.UINT_16, unit=self.__modbus_id) * 100 + 0x0229, ModbusDataType.UINT_16, device_id=self.__modbus_id) * 100 imported, exported = self.peak_filter.check_values(power, imported, exported) bat_state = BatState( diff --git a/packages/modules/devices/azzurro_zcs/azzurro_zcs/counter.py b/packages/modules/devices/azzurro_zcs/azzurro_zcs/counter.py index 25ab9f48e8..10e6672d01 100644 --- a/packages/modules/devices/azzurro_zcs/azzurro_zcs/counter.py +++ b/packages/modules/devices/azzurro_zcs/azzurro_zcs/counter.py @@ -1,6 +1,6 @@ #!/usr/bin/env python3 from typing import TypedDict, Any -from pymodbus.constants import Endian +from modules.common.pymodbus_compat import Endian from modules.common.abstract_device import AbstractCounter from modules.common.component_state import CounterState @@ -36,22 +36,22 @@ def update(self) -> None: # 0x0212 Grid Power Int16 -10-10 kW Unit 0,01kW Feed in/out power # 0x0214 Input/Output power Int16 -10-10kW 0,01kW Energy storage power inverter power = self.client.read_input_registers(0x0212, ModbusDataType.INT_16, wordorder=Endian.Little, - unit=self.__modbus_id) * -1 + device_id=self.__modbus_id) * -1 # 0x020C Grid frequency UInt 0-100 Hz Unit 0,01 Hz frequency = self.client.read_input_registers( - 0x020C, ModbusDataType.UINT_16, unit=self.__modbus_id) / 100 + 0x020C, ModbusDataType.UINT_16, device_id=self.__modbus_id) / 100 exported = [value * 10 for value in self.client.read_input_registers( # 0x021E Total energy injected into the grid UInt16 Unit 1kWh high # 0x021F Total energy injected into the grid UInt16 Unit 1kWh low 0x021E, [ModbusDataType.UINT_16] * 10, - wordorder=Endian.Little, unit=self.__modbus_id)] + wordorder=Endian.Little, device_id=self.__modbus_id)] imported = [value * 10 for value in self.client.read_input_registers( # 0x0220 Total energy taken from the grid UInt16 Unit 1kWh high # 0x0221 Total energy taken from the grid UInt16 Unit 1kWh low 0x0220, [ModbusDataType.UINT_16] * 10, - wordorder=Endian.Little, unit=self.__modbus_id)] + wordorder=Endian.Little, device_id=self.__modbus_id)] imported, exported = self.peak_filter.check_values(power, imported, exported) counter_state = CounterState( diff --git a/packages/modules/devices/azzurro_zcs/azzurro_zcs/inverter.py b/packages/modules/devices/azzurro_zcs/azzurro_zcs/inverter.py index 2d7b7de42d..4c80155db4 100644 --- a/packages/modules/devices/azzurro_zcs/azzurro_zcs/inverter.py +++ b/packages/modules/devices/azzurro_zcs/azzurro_zcs/inverter.py @@ -1,6 +1,6 @@ #!/usr/bin/env python3 from typing import TypedDict, Any -from pymodbus.constants import Endian +from modules.common.pymodbus_compat import Endian from modules.common.abstract_device import AbstractInverter from modules.common.component_state import InverterState @@ -35,18 +35,18 @@ def update(self) -> None: # 0x0250 PV1 Voltage UInt16 0-1000V Unit 0,1V # 0x0251 PV1 current Int16 0-100A Unit 0,01A power_string1 = (self.client.read_input_registers( - 0x0250, ModbusDataType.UINT_16, unit=self.__modbus_id) / 10) * \ - (self.client.read_input_registers(0x0251, ModbusDataType.INT_16, unit=self.__modbus_id) / 10) + 0x0250, ModbusDataType.UINT_16, device_id=self.__modbus_id) / 10) * \ + (self.client.read_input_registers(0x0251, ModbusDataType.INT_16, device_id=self.__modbus_id) / 10) # 0x0255 PV2 Power UInt16 0-100 kW Unit 0,01kW # 0x0253 PV2 Voltage UInt16 0-1000V Unit 0,1V # 0x0254 PV2 current Int16 0-100A Unit 0,01A power_string2 = (self.client.read_input_registers( - 0x0253, ModbusDataType.INT_16, unit=self.__modbus_id) / 10) * \ - (self.client.read_input_registers(0x0254, ModbusDataType.INT_16, unit=self.__modbus_id) / 10) + 0x0253, ModbusDataType.INT_16, device_id=self.__modbus_id) / 10) * \ + (self.client.read_input_registers(0x0254, ModbusDataType.INT_16, device_id=self.__modbus_id) / 10) power = (power_string1 + power_string2) * -1 # 0x0215 PV Power generation UInt16 0 -10 kW Unit 0,01kW exported = self.client.read_input_registers(0x0215, ModbusDataType.UINT_16, wordorder=Endian.Little, - unit=self.__modbus_id) * 100 + device_id=self.__modbus_id) * 100 _, exported = self.peak_filter.check_values(power, None, exported) inverter_state = InverterState( diff --git a/packages/modules/devices/azzurro_zcs/azzurro_zcs_3p/pv_inverter.py b/packages/modules/devices/azzurro_zcs/azzurro_zcs_3p/pv_inverter.py index cb792c7dc4..d74e7a6c24 100644 --- a/packages/modules/devices/azzurro_zcs/azzurro_zcs_3p/pv_inverter.py +++ b/packages/modules/devices/azzurro_zcs/azzurro_zcs_3p/pv_inverter.py @@ -35,12 +35,12 @@ def update(self) -> None: power = exported = 0 currents = None try: - power = self.client.read_holding_registers(0x0485, ModbusDataType.INT_16, unit=self.__modbus_id)*10 - exported = self.client.read_holding_registers(0x0684, ModbusDataType.UINT_32, unit=self.__modbus_id)*10 + power = self.client.read_holding_registers(0x0485, ModbusDataType.INT_16, device_id=self.__modbus_id)*10 + exported = self.client.read_holding_registers(0x0684, ModbusDataType.UINT_32, device_id=self.__modbus_id)*10 currents = [ - self.client.read_holding_registers(0x48E, ModbusDataType.INT_16, unit=self.__modbus_id)*0.01, - self.client.read_holding_registers(0x499, ModbusDataType.INT_16, unit=self.__modbus_id)*0.01, - self.client.read_holding_registers(0x4A4, ModbusDataType.INT_16, unit=self.__modbus_id)*0.01 + self.client.read_holding_registers(0x48E, ModbusDataType.INT_16, device_id=self.__modbus_id)*0.01, + self.client.read_holding_registers(0x499, ModbusDataType.INT_16, device_id=self.__modbus_id)*0.01, + self.client.read_holding_registers(0x4A4, ModbusDataType.INT_16, device_id=self.__modbus_id)*0.01 ] except Exception: log.debug("Modbus could not be read.") diff --git a/packages/modules/devices/carlo_gavazzi/carlo_gavazzi/counter.py b/packages/modules/devices/carlo_gavazzi/carlo_gavazzi/counter.py index 18ff88a5f4..fecec94504 100644 --- a/packages/modules/devices/carlo_gavazzi/carlo_gavazzi/counter.py +++ b/packages/modules/devices/carlo_gavazzi/carlo_gavazzi/counter.py @@ -1,7 +1,7 @@ #!/usr/bin/env python3 from typing import Any, TypedDict -from pymodbus.constants import Endian +from modules.common.pymodbus_compat import Endian from modules.devices.carlo_gavazzi.carlo_gavazzi.config import CarloGavazziCounterSetup from modules.common import modbus @@ -39,13 +39,13 @@ def initialize(self) -> None: def update(self): with self.__tcp_client: voltages = [val / 10 for val in self.__tcp_client.read_input_registers( - 0x00, [ModbusDataType.INT_32] * 3, wordorder=Endian.Little, unit=self.__modbus_id)] + 0x00, [ModbusDataType.INT_32] * 3, wordorder=Endian.Little, device_id=self.__modbus_id)] powers = [val / 10 for val in self.__tcp_client.read_input_registers( - 0x12, [ModbusDataType.INT_32] * 3, wordorder=Endian.Little, unit=self.__modbus_id)] + 0x12, [ModbusDataType.INT_32] * 3, wordorder=Endian.Little, device_id=self.__modbus_id)] power = sum(powers) currents = [(val / 1000) for val in self.__tcp_client.read_input_registers( - 0x0C, [ModbusDataType.INT_32] * 3, wordorder=Endian.Little, unit=self.__modbus_id)] - frequency = self.__tcp_client.read_input_registers(0x33, ModbusDataType.INT_16, unit=self.__modbus_id) / 10 + 0x0C, [ModbusDataType.INT_32] * 3, wordorder=Endian.Little, device_id=self.__modbus_id)] + frequency = self.__tcp_client.read_input_registers(0x33, ModbusDataType.INT_16, device_id=self.__modbus_id) / 10 if frequency > 100: frequency = frequency / 10 diff --git a/packages/modules/devices/chint/chint/counter.py b/packages/modules/devices/chint/chint/counter.py index 9654cdfb2a..a9708834d9 100644 --- a/packages/modules/devices/chint/chint/counter.py +++ b/packages/modules/devices/chint/chint/counter.py @@ -33,30 +33,30 @@ def initialize(self) -> None: def update(self): powers = voltages = currents = power_factors = None imported_ep = exported_ep = power = frequency = 0 - irat = self.client.read_holding_registers(0x0006, ModbusDataType.INT_16, unit=self.__modbus_id) - urat = self.client.read_holding_registers(0x0007, ModbusDataType.INT_16, unit=self.__modbus_id) + irat = self.client.read_holding_registers(0x0006, ModbusDataType.INT_16, device_id=self.__modbus_id) + urat = self.client.read_holding_registers(0x0007, ModbusDataType.INT_16, device_id=self.__modbus_id) power_ratio = urat*0.1*irat*0.1 - frequency = self.client.read_holding_registers(0x2044, ModbusDataType.FLOAT_32, unit=self.__modbus_id)/100 + frequency = self.client.read_holding_registers(0x2044, ModbusDataType.FLOAT_32, device_id=self.__modbus_id)/100 power = self.client.read_holding_registers(0x2012, - ModbusDataType.FLOAT_32, unit=self.__modbus_id) * power_ratio - powers = [self.client.read_holding_registers(reg, ModbusDataType.FLOAT_32, unit=self.__modbus_id) * power_ratio + ModbusDataType.FLOAT_32, device_id=self.__modbus_id) * power_ratio + powers = [self.client.read_holding_registers(reg, ModbusDataType.FLOAT_32, device_id=self.__modbus_id) * power_ratio for reg in [0x2014, 0x2016, 0x2018]] voltage_ratio = urat*0.1*0.1 voltages = [self.client.read_holding_registers( - reg, ModbusDataType.FLOAT_32, unit=self.__modbus_id) * voltage_ratio + reg, ModbusDataType.FLOAT_32, device_id=self.__modbus_id) * voltage_ratio for reg in [0x2006, 0x2008, 0x200A]] current_ratio = irat*0.001 currents = [self.client.read_holding_registers( - reg, ModbusDataType.FLOAT_32, unit=self.__modbus_id) * current_ratio + reg, ModbusDataType.FLOAT_32, device_id=self.__modbus_id) * current_ratio for reg in [0x200C, 0x200E, 0x2010]] - power_factors = [self.client.read_holding_registers(reg, ModbusDataType.FLOAT_32, unit=self.__modbus_id) * 0.001 + power_factors = [self.client.read_holding_registers(reg, ModbusDataType.FLOAT_32, device_id=self.__modbus_id) * 0.001 for reg in [0x202C, 0x202E, 0x2030]] ep_ratio = irat * urat * 100 imported_ep = self.client.read_holding_registers(0x401E, - ModbusDataType.FLOAT_32, unit=self.__modbus_id) * ep_ratio + ModbusDataType.FLOAT_32, device_id=self.__modbus_id) * ep_ratio exported_ep = self.client.read_holding_registers(0x4028, - ModbusDataType.FLOAT_32, unit=self.__modbus_id) * ep_ratio + ModbusDataType.FLOAT_32, device_id=self.__modbus_id) * ep_ratio imported_ep, exported_ep = self.peak_filter.check_values(power, imported_ep, exported_ep) diff --git a/packages/modules/devices/deye/deye/bat.py b/packages/modules/devices/deye/deye/bat.py index f6677ce765..920f33a876 100644 --- a/packages/modules/devices/deye/deye/bat.py +++ b/packages/modules/devices/deye/deye/bat.py @@ -33,18 +33,18 @@ def initialize(self) -> None: self.peak_filter = PeakFilter(ComponentType.BAT, self.component_config.id, self.fault_state) self.sim_counter = SimCounter(self.__device_id, self.component_config.id, prefix="speicher") self.device_type = DeviceType(self.client.read_holding_registers( - 0, ModbusDataType.INT_16, unit=self.component_config.configuration.modbus_id)) + 0, ModbusDataType.INT_16, device_id=self.component_config.configuration.modbus_id)) def update(self) -> None: unit = self.component_config.configuration.modbus_id if self.device_type == DeviceType.SINGLE_PHASE_STRING or self.device_type == DeviceType.SINGLE_PHASE_HYBRID: - power = self.client.read_holding_registers(190, ModbusDataType.INT_16, unit=unit) * -1 - soc = self.client.read_holding_registers(184, ModbusDataType.INT_16, unit=unit) + power = self.client.read_holding_registers(190, ModbusDataType.INT_16, device_id=unit) * -1 + soc = self.client.read_holding_registers(184, ModbusDataType.INT_16, device_id=unit) if self.device_type == DeviceType.SINGLE_PHASE_HYBRID: - imported = self.client.read_holding_registers(72, ModbusDataType.UINT_16, unit=unit) * 100 - exported = self.client.read_holding_registers(74, ModbusDataType.UINT_16, unit=unit) * 100 + imported = self.client.read_holding_registers(72, ModbusDataType.UINT_16, device_id=unit) * 100 + exported = self.client.read_holding_registers(74, ModbusDataType.UINT_16, device_id=unit) * 100 imported, exported = self.peak_filter.check_values(power, imported, exported) elif self.device_type == DeviceType.SINGLE_PHASE_STRING: @@ -52,11 +52,11 @@ def update(self) -> None: imported, exported = self.sim_counter.sim_count(power) else: # THREE_PHASE_LV (0x0500, 0x0005), THREE_PHASE_HV (0x0006) - power = self.client.read_holding_registers(590, ModbusDataType.INT_16, unit=unit) * -1 + power = self.client.read_holding_registers(590, ModbusDataType.INT_16, device_id=unit) * -1 if self.device_type == DeviceType.THREE_PHASE_HV: power = power * 10 - soc = self.client.read_holding_registers(588, ModbusDataType.INT_16, unit=unit) + soc = self.client.read_holding_registers(588, ModbusDataType.INT_16, device_id=unit) self.peak_filter.check_values(power) imported, exported = self.sim_counter.sim_count(power) diff --git a/packages/modules/devices/deye/deye/counter.py b/packages/modules/devices/deye/deye/counter.py index cc9c002dc9..1d2be5ea52 100644 --- a/packages/modules/devices/deye/deye/counter.py +++ b/packages/modules/devices/deye/deye/counter.py @@ -32,13 +32,13 @@ def initialize(self) -> None: self.peak_filter = PeakFilter(ComponentType.COUNTER, self.component_config.id, self.fault_state) self.sim_counter = SimCounter(self.__device_id, self.component_config.id, prefix="bezug") self.device_type = DeviceType(self.client.read_holding_registers( - 0, ModbusDataType.INT_16, unit=self.component_config.configuration.modbus_id)) + 0, ModbusDataType.INT_16, device_id=self.component_config.configuration.modbus_id)) def update(self): unit = self.component_config.configuration.modbus_id if self.device_type == DeviceType.SINGLE_PHASE_STRING or self.device_type == DeviceType.SINGLE_PHASE_HYBRID: - frequency = self.client.read_holding_registers(79, ModbusDataType.INT_16, unit=unit) / 100 + frequency = self.client.read_holding_registers(79, ModbusDataType.INT_16, device_id=unit) / 100 if self.device_type == DeviceType.SINGLE_PHASE_HYBRID: powers = [0]*3 @@ -48,18 +48,18 @@ def update(self): elif self.device_type == DeviceType.SINGLE_PHASE_STRING: currents = [ - c / 100 for c in self.client.read_holding_registers(76, [ModbusDataType.INT_16]*3, unit=unit)] + c / 100 for c in self.client.read_holding_registers(76, [ModbusDataType.INT_16]*3, device_id=unit)] voltages = [ - v / 10 for v in self.client.read_holding_registers(70, [ModbusDataType.INT_16]*3, unit=unit)] + v / 10 for v in self.client.read_holding_registers(70, [ModbusDataType.INT_16]*3, device_id=unit)] powers = [currents[i] * voltages[i] for i in range(0, 3)] power = sum(powers) else: # THREE_PHASE_LV (0x0500, 0x0005), THREE_PHASE_HV (0x0006) - currents = [c / 100 for c in self.client.read_holding_registers(613, [ModbusDataType.INT_16]*3, unit=unit)] - voltages = [v / 10 for v in self.client.read_holding_registers(644, [ModbusDataType.INT_16]*3, unit=unit)] - powers = self.client.read_holding_registers(616, [ModbusDataType.INT_16]*3, unit=unit) + currents = [c / 100 for c in self.client.read_holding_registers(613, [ModbusDataType.INT_16]*3, device_id=unit)] + voltages = [v / 10 for v in self.client.read_holding_registers(644, [ModbusDataType.INT_16]*3, device_id=unit)] + powers = self.client.read_holding_registers(616, [ModbusDataType.INT_16]*3, device_id=unit) power = sum(powers) - frequency = self.client.read_holding_registers(609, ModbusDataType.INT_16, unit=unit) / 100 + frequency = self.client.read_holding_registers(609, ModbusDataType.INT_16, device_id=unit) / 100 self.peak_filter.check_values(power) imported, exported = self.sim_counter.sim_count(power) diff --git a/packages/modules/devices/deye/deye/inverter.py b/packages/modules/devices/deye/deye/inverter.py index 13eeb467be..e9dee5b5e3 100644 --- a/packages/modules/devices/deye/deye/inverter.py +++ b/packages/modules/devices/deye/deye/inverter.py @@ -32,16 +32,16 @@ def initialize(self) -> None: self.peak_filter = PeakFilter(ComponentType.INVERTER, self.component_config.id, self.fault_state) self.sim_counter = SimCounter(self.__device_id, self.component_config.id, prefix="pv") self.device_type = DeviceType(self.client.read_holding_registers( - 0, ModbusDataType.INT_16, unit=self.component_config.configuration.modbus_id)) + 0, ModbusDataType.INT_16, device_id=self.component_config.configuration.modbus_id)) def update(self) -> None: unit = self.component_config.configuration.modbus_id if self.device_type == DeviceType.SINGLE_PHASE_STRING or self.device_type == DeviceType.SINGLE_PHASE_HYBRID: - power = sum(self.client.read_holding_registers(186, [ModbusDataType.INT_16]*4, unit=unit)) * -1 + power = sum(self.client.read_holding_registers(186, [ModbusDataType.INT_16]*4, device_id=unit)) * -1 else: # THREE_PHASE_LV (0x0500, 0x0005), THREE_PHASE_HV (0x0006) - power = sum(self.client.read_holding_registers(672, [ModbusDataType.INT_16]*2, unit=unit)) * -1 + power = sum(self.client.read_holding_registers(672, [ModbusDataType.INT_16]*2, device_id=unit)) * -1 if self.device_type == DeviceType.THREE_PHASE_HV: power = power * 10 diff --git a/packages/modules/devices/e3dc/e3dc/bat.py b/packages/modules/devices/e3dc/e3dc/bat.py index 18d290671c..86e5497e2e 100644 --- a/packages/modules/devices/e3dc/e3dc/bat.py +++ b/packages/modules/devices/e3dc/e3dc/bat.py @@ -18,9 +18,9 @@ def read_bat(client: modbus.ModbusTcpClient_, modbus_id: int) -> Tuple[int, int]: # 40082 SoC - soc = client.read_holding_registers(40082, ModbusDataType.INT_16, unit=modbus_id) + soc = client.read_holding_registers(40082, ModbusDataType.INT_16, device_id=modbus_id) # 40069 Speicherleistung - power = client.read_holding_registers(40069, ModbusDataType.INT_32, wordorder=Endian.Little, unit=modbus_id) + power = client.read_holding_registers(40069, ModbusDataType.INT_32, wordorder=Endian.Little, device_id=modbus_id) return soc, power diff --git a/packages/modules/devices/e3dc/e3dc/counter.py b/packages/modules/devices/e3dc/e3dc/counter.py index f58ff196dd..4744c301a1 100644 --- a/packages/modules/devices/e3dc/e3dc/counter.py +++ b/packages/modules/devices/e3dc/e3dc/counter.py @@ -29,7 +29,7 @@ def read_counter(client: modbus.ModbusTcpClient_, modbus_id: int) -> Tuple[int, # bei den meisten e3dc auf 40128 # farm haben typ 5, normale e3dc haben nur typ 1 und keinen typ 5 # bei farm ist typ 1 vorhanden aber liefert immer 0 - meters = list(map(int, client.read_holding_registers(40104, [ModbusDataType.INT_16] * 28, unit=modbus_id))) + meters = list(map(int, client.read_holding_registers(40104, [ModbusDataType.INT_16] * 28, device_id=modbus_id))) log.debug("meters: %s", meters) try: powers = get_meter_phases(5, meters) diff --git a/packages/modules/devices/e3dc/e3dc/external_inverter.py b/packages/modules/devices/e3dc/e3dc/external_inverter.py index 93c8955271..49c1205c46 100644 --- a/packages/modules/devices/e3dc/e3dc/external_inverter.py +++ b/packages/modules/devices/e3dc/e3dc/external_inverter.py @@ -19,7 +19,7 @@ def read_external_inverter(client: modbus.ModbusTcpClient_, modbus_id: int) -> int: pv_external = int(client.read_holding_registers( - 40075, ModbusDataType.INT_32, wordorder=Endian.Little, unit=modbus_id)) + 40075, ModbusDataType.INT_32, wordorder=Endian.Little, device_id=modbus_id)) return pv_external diff --git a/packages/modules/devices/e3dc/e3dc/inverter.py b/packages/modules/devices/e3dc/e3dc/inverter.py index 25249f49ca..f88b373a07 100644 --- a/packages/modules/devices/e3dc/e3dc/inverter.py +++ b/packages/modules/devices/e3dc/e3dc/inverter.py @@ -18,7 +18,7 @@ def read_inverter(client: modbus.ModbusTcpClient_, modbus_id: int) -> int: - pv = int(client.read_holding_registers(40067, ModbusDataType.INT_32, wordorder=Endian.Little, unit=modbus_id) * -1) + pv = int(client.read_holding_registers(40067, ModbusDataType.INT_32, wordorder=Endian.Little, device_id=modbus_id) * -1) return pv diff --git a/packages/modules/devices/fox_ess/fox_ess/bat.py b/packages/modules/devices/fox_ess/fox_ess/bat.py index 408fa44e44..9cd186e146 100644 --- a/packages/modules/devices/fox_ess/fox_ess/bat.py +++ b/packages/modules/devices/fox_ess/fox_ess/bat.py @@ -32,12 +32,12 @@ def initialize(self) -> None: def update(self) -> None: unit = self.component_config.configuration.modbus_id - power = self.client.read_holding_registers(31036, ModbusDataType.INT_16, unit=unit) * -1 - soc = self.client.read_holding_registers(31038, ModbusDataType.UINT_16, unit=unit) + power = self.client.read_holding_registers(31036, ModbusDataType.INT_16, device_id=unit) * -1 + soc = self.client.read_holding_registers(31038, ModbusDataType.UINT_16, device_id=unit) # Geladen in kWh * 0,1 - imported = self.client.read_holding_registers(32003, ModbusDataType.UINT_32, unit=unit) * 100 + imported = self.client.read_holding_registers(32003, ModbusDataType.UINT_32, device_id=unit) * 100 # Entladen in kWh * 0,1 - exported = self.client.read_holding_registers(32006, ModbusDataType.UINT_32, unit=unit) * 100 + exported = self.client.read_holding_registers(32006, ModbusDataType.UINT_32, device_id=unit) * 100 imported, exported = self.peak_filter.check_values(power, imported, exported) bat_state = BatState( diff --git a/packages/modules/devices/fox_ess/fox_ess/counter.py b/packages/modules/devices/fox_ess/fox_ess/counter.py index e600ce8f13..3c2da2c6a5 100644 --- a/packages/modules/devices/fox_ess/fox_ess/counter.py +++ b/packages/modules/devices/fox_ess/fox_ess/counter.py @@ -29,11 +29,11 @@ def update(self) -> None: unit = self.component_config.configuration.modbus_id powers = [val * -1 for val in - self.client.read_holding_registers(31026, [ModbusDataType.INT_16]*3, unit=unit)] + self.client.read_holding_registers(31026, [ModbusDataType.INT_16]*3, device_id=unit)] power = sum(powers) - frequency = self.client.read_holding_registers(31015, ModbusDataType.UINT_16, unit=unit) / 100 - imported = self.client.read_holding_registers(32018, ModbusDataType.UINT_32, unit=unit) * 100 - exported = self.client.read_holding_registers(32015, ModbusDataType.UINT_32, unit=unit) * 100 + frequency = self.client.read_holding_registers(31015, ModbusDataType.UINT_16, device_id=unit) / 100 + imported = self.client.read_holding_registers(32018, ModbusDataType.UINT_32, device_id=unit) * 100 + exported = self.client.read_holding_registers(32015, ModbusDataType.UINT_32, device_id=unit) * 100 imported, exported = self.peak_filter.check_values(power, imported, exported) counter_state = CounterState( diff --git a/packages/modules/devices/fox_ess/fox_ess/inverter.py b/packages/modules/devices/fox_ess/fox_ess/inverter.py index d64265aed4..862b6568fd 100644 --- a/packages/modules/devices/fox_ess/fox_ess/inverter.py +++ b/packages/modules/devices/fox_ess/fox_ess/inverter.py @@ -31,10 +31,10 @@ def update(self) -> None: unit = self.component_config.configuration.modbus_id # PV1 + PV2 Power power = sum([self.client.read_holding_registers( - reg, ModbusDataType.INT_16, unit=unit) + reg, ModbusDataType.INT_16, device_id=unit) for reg in [31002, 31005]]) * -1 # Gesamt Produktion Wechselrichter unsigned integer in kWh * 0,1 - exported = self.client.read_holding_registers(32000, ModbusDataType.UINT_32, unit=unit) * 100 + exported = self.client.read_holding_registers(32000, ModbusDataType.UINT_32, device_id=unit) * 100 _, exported = self.peak_filter.check_values(power, None, exported) inverter_state = InverterState( diff --git a/packages/modules/devices/good_we/good_we/bat.py b/packages/modules/devices/good_we/good_we/bat.py index de31002305..19ec9b7da9 100644 --- a/packages/modules/devices/good_we/good_we/bat.py +++ b/packages/modules/devices/good_we/good_we/bat.py @@ -49,19 +49,19 @@ def update(self) -> None: if battery_index == 1: if self.version == GoodWeVersion.V_1_7: power = self.__tcp_client.read_holding_registers( - 35183, ModbusDataType.INT_16, unit=self.__modbus_id)*-1 + 35183, ModbusDataType.INT_16, device_id=self.__modbus_id)*-1 else: power = self.__tcp_client.read_holding_registers( - 35182, ModbusDataType.INT_32, unit=self.__modbus_id)*-1 - soc = self.__tcp_client.read_holding_registers(37007, ModbusDataType.UINT_16, unit=self.__modbus_id) + 35182, ModbusDataType.INT_32, device_id=self.__modbus_id)*-1 + soc = self.__tcp_client.read_holding_registers(37007, ModbusDataType.UINT_16, device_id=self.__modbus_id) imported = self.__tcp_client.read_holding_registers( - 35206, ModbusDataType.UINT_32, unit=self.__modbus_id) * 100 + 35206, ModbusDataType.UINT_32, device_id=self.__modbus_id) * 100 exported = self.__tcp_client.read_holding_registers( - 35209, ModbusDataType.UINT_32, unit=self.__modbus_id) * 100 + 35209, ModbusDataType.UINT_32, device_id=self.__modbus_id) * 100 imported, exported = self.peak_filter.check_values(power, imported, exported) else: - power = self.__tcp_client.read_holding_registers(35264, ModbusDataType.INT_32, unit=self.__modbus_id)*-1 - soc = self.__tcp_client.read_holding_registers(39005, ModbusDataType.UINT_16, unit=self.__modbus_id) + power = self.__tcp_client.read_holding_registers(35264, ModbusDataType.INT_32, device_id=self.__modbus_id)*-1 + soc = self.__tcp_client.read_holding_registers(39005, ModbusDataType.UINT_16, device_id=self.__modbus_id) self.peak_filter.check_values(power) imported, exported = self.sim_counter.sim_count(power) @@ -80,31 +80,31 @@ def set_power_limit(self, power_limit: Optional[int]) -> None: if power_limit is None: log.debug("Keine Batteriesteuerung, Selbstregelung durch Wechselrichter") if self.last_mode is not None: - self.__tcp_client.write_register(47511, 1, data_type=ModbusDataType.UINT_16, unit=unit) - self.__tcp_client.write_register(47512, 0, data_type=ModbusDataType.UINT_16, unit=unit) + self.__tcp_client.write_register(47511, 1, data_type=ModbusDataType.UINT_16, device_id=unit) + self.__tcp_client.write_register(47512, 0, data_type=ModbusDataType.UINT_16, device_id=unit) self.last_mode = None elif power_limit == 0: log.debug("Aktive Batteriesteuerung. Batterie wird auf Stop gesetzt und nicht entladen") if self.last_mode != 'stop': - self.__tcp_client.write_register(47511, 2, data_type=ModbusDataType.UINT_16, unit=unit) - self.__tcp_client.write_register(47512, 0, data_type=ModbusDataType.UINT_16, unit=unit) + self.__tcp_client.write_register(47511, 2, data_type=ModbusDataType.UINT_16, device_id=unit) + self.__tcp_client.write_register(47512, 0, data_type=ModbusDataType.UINT_16, device_id=unit) self.last_mode = 'stop' elif power_limit < 0: log.debug(f"Aktive Batteriesteuerung. Batterie wird mit {power_limit} W entladen für den Hausverbrauch") if self.last_mode != 'discharge': - self.__tcp_client.write_register(47511, 3, data_type=ModbusDataType.UINT_16, unit=unit) + self.__tcp_client.write_register(47511, 3, data_type=ModbusDataType.UINT_16, device_id=unit) self.last_mode = 'discharge' # Die maximale Entladeleistung begrenzen auf 5000W, maximaler Wertebereich Modbusregister. power_value = int(min(abs(power_limit), 10000)) log.debug(f"Aktive Batteriesteuerung. Batterie wird mit {power_value} W entladen für den Hausverbrauch") - self.__tcp_client.write_register(47512, power_value, data_type=ModbusDataType.UINT_16, unit=unit) + self.__tcp_client.write_register(47512, power_value, data_type=ModbusDataType.UINT_16, device_id=unit) elif power_limit > 0: if self.last_mode != 'charge': - self.__tcp_client.write_register(47511, 2, data_type=ModbusDataType.UINT_16, unit=unit) + self.__tcp_client.write_register(47511, 2, data_type=ModbusDataType.UINT_16, device_id=unit) self.last_mode = 'charge' power_value = int(min(abs(power_limit), 10000)) log.debug(f"Aktive Batteriesteuerung. Batterie wird mit {power_value} W entladen für den Hausverbrauch") - self.__tcp_client.write_register(47512, power_value, data_type=ModbusDataType.UINT_16, unit=unit) + self.__tcp_client.write_register(47512, power_value, data_type=ModbusDataType.UINT_16, device_id=unit) def power_limit_controllable(self) -> bool: return True diff --git a/packages/modules/devices/good_we/good_we/counter.py b/packages/modules/devices/good_we/good_we/counter.py index f8fa2f4691..15cff34bf3 100644 --- a/packages/modules/devices/good_we/good_we/counter.py +++ b/packages/modules/devices/good_we/good_we/counter.py @@ -42,28 +42,28 @@ def update(self) -> None: with self.__tcp_client: if self.firmware < 9: power = self.__tcp_client.read_holding_registers( - 36008, ModbusDataType.INT_16, unit=self.__modbus_id) * -1 + 36008, ModbusDataType.INT_16, device_id=self.__modbus_id) * -1 powers = [ val * -1 for val in self.__tcp_client.read_holding_registers( - 36005, [ModbusDataType.INT_16]*3, unit=self.__modbus_id)] + 36005, [ModbusDataType.INT_16]*3, device_id=self.__modbus_id)] else: power = self.__tcp_client.read_holding_registers( - 36025, ModbusDataType.INT_32, unit=self.__modbus_id) * -1 + 36025, ModbusDataType.INT_32, device_id=self.__modbus_id) * -1 powers = [ val * -1 for val in self.__tcp_client.read_holding_registers( - 36019, [ModbusDataType.INT_32]*3, unit=self.__modbus_id)] + 36019, [ModbusDataType.INT_32]*3, device_id=self.__modbus_id)] power_factors = [ val / 1000 for val in self.__tcp_client.read_holding_registers( - 36010, [ModbusDataType.INT_16]*3, unit=self.__modbus_id)] + 36010, [ModbusDataType.INT_16]*3, device_id=self.__modbus_id)] frequency = self.__tcp_client.read_holding_registers( - 36014, ModbusDataType.UINT_16, unit=self.__modbus_id) / 100 + 36014, ModbusDataType.UINT_16, device_id=self.__modbus_id) / 100 if self.version == GoodWeVersion.V_1_7: exported = self.__tcp_client.read_holding_registers( - 36015, ModbusDataType.FLOAT_32, unit=self.__modbus_id) + 36015, ModbusDataType.FLOAT_32, device_id=self.__modbus_id) imported = self.__tcp_client.read_holding_registers( - 36017, ModbusDataType.FLOAT_32, unit=self.__modbus_id) + 36017, ModbusDataType.FLOAT_32, device_id=self.__modbus_id) imported, exported = self.peak_filter.check_values(power, imported, exported) else: # v1.0 und v1.1 liefern keine Werte zurueck obwohl Register laut Doku gleich diff --git a/packages/modules/devices/good_we/good_we/inverter.py b/packages/modules/devices/good_we/good_we/inverter.py index 2f77bc943c..b5b008502d 100644 --- a/packages/modules/devices/good_we/good_we/inverter.py +++ b/packages/modules/devices/good_we/good_we/inverter.py @@ -38,10 +38,10 @@ def initialize(self) -> None: def update(self) -> None: with self.__tcp_client: power = sum([self.__tcp_client.read_holding_registers( - reg, ModbusDataType.INT_32, unit=self.__modbus_id) + reg, ModbusDataType.INT_32, device_id=self.__modbus_id) for reg in [35105, 35109, 35113, 35117]]) * -1 exported = self.__tcp_client.read_holding_registers( - 35191, ModbusDataType.UINT_32, unit=self.__modbus_id) * 100 + 35191, ModbusDataType.UINT_32, device_id=self.__modbus_id) * 100 _, exported = self.peak_filter.check_values(power, None, exported) inverter_state = InverterState( diff --git a/packages/modules/devices/growatt/growatt/bat.py b/packages/modules/devices/growatt/growatt/bat.py index 6bbf5530ac..ac60df7fb8 100644 --- a/packages/modules/devices/growatt/growatt/bat.py +++ b/packages/modules/devices/growatt/growatt/bat.py @@ -35,28 +35,28 @@ def initialize(self) -> None: def update(self) -> None: if self.version == GrowattVersion.max_series: power_in = self.client.read_input_registers( - 1011, ModbusDataType.UINT_32, unit=self.__modbus_id) * 0.1 + 1011, ModbusDataType.UINT_32, device_id=self.__modbus_id) * 0.1 power_out = self.client.read_input_registers( - 1009, ModbusDataType.UINT_32, unit=self.__modbus_id) * -0.1 + 1009, ModbusDataType.UINT_32, device_id=self.__modbus_id) * -0.1 power = power_in + power_out - soc = self.client.read_input_registers(1014, ModbusDataType.UINT_16, unit=self.__modbus_id) + soc = self.client.read_input_registers(1014, ModbusDataType.UINT_16, device_id=self.__modbus_id) imported = self.client.read_input_registers( - 1058, ModbusDataType.UINT_32, unit=self.__modbus_id) * 100 + 1058, ModbusDataType.UINT_32, device_id=self.__modbus_id) * 100 exported = self.client.read_input_registers( - 1054, ModbusDataType.UINT_32, unit=self.__modbus_id) * 100 + 1054, ModbusDataType.UINT_32, device_id=self.__modbus_id) * 100 else: power_in = self.client.read_input_registers( - 3180, ModbusDataType.UINT_32, unit=self.__modbus_id) * -0.1 + 3180, ModbusDataType.UINT_32, device_id=self.__modbus_id) * -0.1 power_out = self.client.read_input_registers( - 3178, ModbusDataType.UINT_32, unit=self.__modbus_id) * 0.1 + 3178, ModbusDataType.UINT_32, device_id=self.__modbus_id) * 0.1 power = power_in + power_out - soc = self.client.read_input_registers(3171, ModbusDataType.UINT_16, unit=self.__modbus_id) + soc = self.client.read_input_registers(3171, ModbusDataType.UINT_16, device_id=self.__modbus_id) imported = self.client.read_input_registers( - 3131, ModbusDataType.UINT_32, unit=self.__modbus_id) * 100 + 3131, ModbusDataType.UINT_32, device_id=self.__modbus_id) * 100 exported = self.client.read_input_registers( - 3127, ModbusDataType.UINT_32, unit=self.__modbus_id) * 100 + 3127, ModbusDataType.UINT_32, device_id=self.__modbus_id) * 100 imported, exported = self.peak_filter.check_values(power, imported, exported) bat_state = BatState( diff --git a/packages/modules/devices/growatt/growatt/counter.py b/packages/modules/devices/growatt/growatt/counter.py index ea18aef915..2f0a0d7506 100644 --- a/packages/modules/devices/growatt/growatt/counter.py +++ b/packages/modules/devices/growatt/growatt/counter.py @@ -34,40 +34,40 @@ def initialize(self) -> None: def update(self) -> None: if self.version == GrowattVersion.max_series: - power_in = self.client.read_input_registers(1021, ModbusDataType.UINT_32, unit=self.__modbus_id) * 0.1 - power_out = self.client.read_input_registers(1029, ModbusDataType.UINT_32, unit=self.__modbus_id) * -0.1 + power_in = self.client.read_input_registers(1021, ModbusDataType.UINT_32, device_id=self.__modbus_id) * 0.1 + power_out = self.client.read_input_registers(1029, ModbusDataType.UINT_32, device_id=self.__modbus_id) * -0.1 power = power_in + power_out powers = [ self.client.read_input_registers( - 40, ModbusDataType.INT_32, unit=self.__modbus_id) / 10, + 40, ModbusDataType.INT_32, device_id=self.__modbus_id) / 10, self.client.read_input_registers( - 44, ModbusDataType.INT_32, unit=self.__modbus_id) / 10, + 44, ModbusDataType.INT_32, device_id=self.__modbus_id) / 10, self.client.read_input_registers( - 48, ModbusDataType.INT_32, unit=self.__modbus_id) / 10] + 48, ModbusDataType.INT_32, device_id=self.__modbus_id) / 10] # Einheit 0.1 kWh - exported = self.client.read_input_registers(1050, ModbusDataType.UINT_32, unit=self.__modbus_id) * 100 - imported = self.client.read_input_registers(1046, ModbusDataType.UINT_32, unit=self.__modbus_id) * 100 + exported = self.client.read_input_registers(1050, ModbusDataType.UINT_32, device_id=self.__modbus_id) * 100 + imported = self.client.read_input_registers(1046, ModbusDataType.UINT_32, device_id=self.__modbus_id) * 100 # TL-X Dokumentation hat die gleichen Register wie die MAX Serie, # zusätzlich sind aber auch unten abweichende enthalten else: - power_in = self.client.read_input_registers(3041, ModbusDataType.UINT_32, unit=self.__modbus_id) * 0.1 - power_out = self.client.read_input_registers(3043, ModbusDataType.UINT_32, unit=self.__modbus_id) * -0.1 + power_in = self.client.read_input_registers(3041, ModbusDataType.UINT_32, device_id=self.__modbus_id) * 0.1 + power_out = self.client.read_input_registers(3043, ModbusDataType.UINT_32, device_id=self.__modbus_id) * -0.1 power = power_in + power_out powers = [ self.client.read_input_registers( - 3028, ModbusDataType.INT_32, unit=self.__modbus_id) / 10, + 3028, ModbusDataType.INT_32, device_id=self.__modbus_id) / 10, self.client.read_input_registers( - 3032, ModbusDataType.INT_32, unit=self.__modbus_id) / 10, + 3032, ModbusDataType.INT_32, device_id=self.__modbus_id) / 10, self.client.read_input_registers( - 3036, ModbusDataType.INT_32, unit=self.__modbus_id) / 10] + 3036, ModbusDataType.INT_32, device_id=self.__modbus_id) / 10] # Einheit 0.1 kWh - exported = self.client.read_input_registers(3073, ModbusDataType.UINT_32, unit=self.__modbus_id) * 100 - imported = self.client.read_input_registers(3069, ModbusDataType.UINT_32, unit=self.__modbus_id) * 100 + exported = self.client.read_input_registers(3073, ModbusDataType.UINT_32, device_id=self.__modbus_id) * 100 + imported = self.client.read_input_registers(3069, ModbusDataType.UINT_32, device_id=self.__modbus_id) * 100 imported, exported = self.peak_filter.check_values(power, imported, exported) counter_state = CounterState( diff --git a/packages/modules/devices/growatt/growatt/inverter.py b/packages/modules/devices/growatt/growatt/inverter.py index bc6da22ace..ec05fe9990 100644 --- a/packages/modules/devices/growatt/growatt/inverter.py +++ b/packages/modules/devices/growatt/growatt/inverter.py @@ -35,14 +35,14 @@ def initialize(self) -> None: def update(self) -> None: if self.version == GrowattVersion.max_series: power = self.client.read_input_registers( - 1, ModbusDataType.UINT_32, unit=self.__modbus_id) / -10 + 1, ModbusDataType.UINT_32, device_id=self.__modbus_id) / -10 exported = self.client.read_input_registers( - 91, ModbusDataType.UINT_32, unit=self.__modbus_id) * 100 + 91, ModbusDataType.UINT_32, device_id=self.__modbus_id) * 100 else: power = self.client.read_input_registers( - 3001, ModbusDataType.UINT_32, unit=self.__modbus_id) / -10 + 3001, ModbusDataType.UINT_32, device_id=self.__modbus_id) / -10 exported = self.client.read_input_registers( - 3053, ModbusDataType.UINT_32, unit=self.__modbus_id) * 100 + 3053, ModbusDataType.UINT_32, device_id=self.__modbus_id) * 100 _, exported = self.peak_filter.check_values(power, None, exported) inverter_state = InverterState( diff --git a/packages/modules/devices/huawei/huawei/bat.py b/packages/modules/devices/huawei/huawei/bat.py index 9de263ec72..f3e29f1337 100644 --- a/packages/modules/devices/huawei/huawei/bat.py +++ b/packages/modules/devices/huawei/huawei/bat.py @@ -40,10 +40,10 @@ def initialize(self) -> None: def update(self) -> None: if self.type == HuaweiType.SDongle: time.sleep(1) - power = self.client.read_holding_registers(37765, ModbusDataType.INT_32, unit=self.modbus_id) + power = self.client.read_holding_registers(37765, ModbusDataType.INT_32, device_id=self.modbus_id) if self.type == HuaweiType.SDongle: time.sleep(1) - soc = self.client.read_holding_registers(37760, ModbusDataType.INT_16, unit=self.modbus_id) / 10 + soc = self.client.read_holding_registers(37760, ModbusDataType.INT_16, device_id=self.modbus_id) / 10 self.peak_filter.check_values(power) imported, exported = self.sim_counter.sim_count(power) diff --git a/packages/modules/devices/huawei/huawei/counter.py b/packages/modules/devices/huawei/huawei/counter.py index 6b6196c9bf..a4a4821052 100644 --- a/packages/modules/devices/huawei/huawei/counter.py +++ b/packages/modules/devices/huawei/huawei/counter.py @@ -40,11 +40,11 @@ def initialize(self) -> None: def update(self) -> None: if self.type == HuaweiType.SDongle: time.sleep(1) - currents = self.client.read_holding_registers(37107, [ModbusDataType.INT_32]*3, unit=self.modbus_id) + currents = self.client.read_holding_registers(37107, [ModbusDataType.INT_32]*3, device_id=self.modbus_id) currents = [val / -100 for val in currents] if self.type == HuaweiType.SDongle: time.sleep(1) - power = self.client.read_holding_registers(37113, ModbusDataType.INT_32, unit=self.modbus_id) * -1 + power = self.client.read_holding_registers(37113, ModbusDataType.INT_32, device_id=self.modbus_id) * -1 self.peak_filter.check_values(power) imported, exported = self.sim_counter.sim_count(power) diff --git a/packages/modules/devices/huawei/huawei/inverter.py b/packages/modules/devices/huawei/huawei/inverter.py index d788b50397..16eef04eb7 100644 --- a/packages/modules/devices/huawei/huawei/inverter.py +++ b/packages/modules/devices/huawei/huawei/inverter.py @@ -40,7 +40,7 @@ def initialize(self) -> None: def update(self) -> None: if self.type == HuaweiType.SDongle: time.sleep(1) - power = self.client.read_holding_registers(32064, ModbusDataType.INT_32, unit=self.modbus_id) * -1 + power = self.client.read_holding_registers(32064, ModbusDataType.INT_32, device_id=self.modbus_id) * -1 self.peak_filter.check_values(power) _, exported = self.sim_counter.sim_count(power) diff --git a/packages/modules/devices/huawei/huawei_emma/bat.py b/packages/modules/devices/huawei/huawei_emma/bat.py index 9f98c8e6bd..fd5d78ae15 100644 --- a/packages/modules/devices/huawei/huawei_emma/bat.py +++ b/packages/modules/devices/huawei/huawei_emma/bat.py @@ -34,8 +34,8 @@ def initialize(self) -> None: self.peak_filter = PeakFilter(ComponentType.BAT, self.component_config.id, self.fault_state) def update(self) -> None: - power = self.client.read_holding_registers(30360, ModbusDataType.INT_32, unit=self.modbus_id) - soc = self.client.read_holding_registers(30368, ModbusDataType.UINT_16, unit=self.modbus_id) * 0.01 + power = self.client.read_holding_registers(30360, ModbusDataType.INT_32, device_id=self.modbus_id) + soc = self.client.read_holding_registers(30368, ModbusDataType.UINT_16, device_id=self.modbus_id) * 0.01 self.peak_filter.check_values(power) imported, exported = self.sim_counter.sim_count(power) diff --git a/packages/modules/devices/huawei/huawei_emma/counter.py b/packages/modules/devices/huawei/huawei_emma/counter.py index f7f3e6bd40..3aaa1fef6c 100644 --- a/packages/modules/devices/huawei/huawei_emma/counter.py +++ b/packages/modules/devices/huawei/huawei_emma/counter.py @@ -34,9 +34,9 @@ def initialize(self) -> None: self.peak_filter = PeakFilter(ComponentType.COUNTER, self.component_config.id, self.fault_state) def update(self) -> None: - currents = self.client.read_holding_registers(31651, [ModbusDataType.INT_32]*3, unit=self.modbus_id) + currents = self.client.read_holding_registers(31651, [ModbusDataType.INT_32]*3, device_id=self.modbus_id) currents = [val * 0.1 for val in currents] - power = self.client.read_holding_registers(31657, ModbusDataType.INT_32, unit=self.modbus_id) + power = self.client.read_holding_registers(31657, ModbusDataType.INT_32, device_id=self.modbus_id) self.peak_filter.check_values(power) imported, exported = self.sim_counter.sim_count(power) diff --git a/packages/modules/devices/huawei/huawei_emma/inverter.py b/packages/modules/devices/huawei/huawei_emma/inverter.py index 11324f7dc5..6e3b3c2424 100644 --- a/packages/modules/devices/huawei/huawei_emma/inverter.py +++ b/packages/modules/devices/huawei/huawei_emma/inverter.py @@ -32,8 +32,8 @@ def initialize(self) -> None: self.peak_filter = PeakFilter(ComponentType.INVERTER, self.component_config.id, self.fault_state) def update(self) -> None: - power = self.client.read_holding_registers(30354, ModbusDataType.INT_32, unit=self.modbus_id) * -1 - exported = self.client.read_holding_registers(30348, ModbusDataType.UINT_64, unit=self.modbus_id) * 10 + power = self.client.read_holding_registers(30354, ModbusDataType.INT_32, device_id=self.modbus_id) * -1 + exported = self.client.read_holding_registers(30348, ModbusDataType.UINT_64, device_id=self.modbus_id) * 10 _, exported = self.peak_filter.check_values(power, None, exported) inverter_state = InverterState( power=power, diff --git a/packages/modules/devices/huawei/huawei_smartlogger/bat.py b/packages/modules/devices/huawei/huawei_smartlogger/bat.py index 4d82b598cf..6585e9a16e 100644 --- a/packages/modules/devices/huawei/huawei_smartlogger/bat.py +++ b/packages/modules/devices/huawei/huawei_smartlogger/bat.py @@ -34,8 +34,8 @@ def initialize(self) -> None: def update(self) -> None: modbus_id = self.component_config.configuration.modbus_id - power = self.__tcp_client.read_holding_registers(37765, ModbusDataType.INT_32, unit=modbus_id) - soc = self.__tcp_client.read_holding_registers(37760, ModbusDataType.INT_16, unit=modbus_id) / 10 + power = self.__tcp_client.read_holding_registers(37765, ModbusDataType.INT_32, device_id=modbus_id) + soc = self.__tcp_client.read_holding_registers(37760, ModbusDataType.INT_16, device_id=modbus_id) / 10 self.peak_filter.check_values(power) imported, exported = self.sim_counter.sim_count(power) diff --git a/packages/modules/devices/huawei/huawei_smartlogger/counter.py b/packages/modules/devices/huawei/huawei_smartlogger/counter.py index 80b7ae5a53..161a64394f 100644 --- a/packages/modules/devices/huawei/huawei_smartlogger/counter.py +++ b/packages/modules/devices/huawei/huawei_smartlogger/counter.py @@ -33,12 +33,12 @@ def initialize(self) -> None: def update(self) -> None: modbus_id = self.component_config.configuration.modbus_id - power = self.client.read_holding_registers(32278, ModbusDataType.INT_32, unit=modbus_id) + power = self.client.read_holding_registers(32278, ModbusDataType.INT_32, device_id=modbus_id) currents = [val / 10 for val in self.client.read_holding_registers( - 32272, [ModbusDataType.INT_32] * 3, unit=modbus_id)] + 32272, [ModbusDataType.INT_32] * 3, device_id=modbus_id)] voltages = [val / 100 for val in self.client.read_holding_registers( - 32260, [ModbusDataType.INT_32] * 3, unit=modbus_id)] - powers = self.client.read_holding_registers(32335, [ModbusDataType.INT_32] * 3, unit=modbus_id) + 32260, [ModbusDataType.INT_32] * 3, device_id=modbus_id)] + powers = self.client.read_holding_registers(32335, [ModbusDataType.INT_32] * 3, device_id=modbus_id) self.peak_filter.check_values(power) imported, exported = self.sim_counter.sim_count(power) diff --git a/packages/modules/devices/huawei/huawei_smartlogger/inverter.py b/packages/modules/devices/huawei/huawei_smartlogger/inverter.py index efe5604051..500a7208ab 100644 --- a/packages/modules/devices/huawei/huawei_smartlogger/inverter.py +++ b/packages/modules/devices/huawei/huawei_smartlogger/inverter.py @@ -37,8 +37,8 @@ def initialize(self) -> None: def update(self) -> None: modbus_id = self.component_config.configuration.modbus_id - power = self.client.read_holding_registers(32080, ModbusDataType.INT_32, unit=modbus_id) * -1 - exported = self.client.read_holding_registers(32106, ModbusDataType.INT_32, unit=modbus_id) * 10 + power = self.client.read_holding_registers(32080, ModbusDataType.INT_32, device_id=modbus_id) * -1 + exported = self.client.read_holding_registers(32106, ModbusDataType.INT_32, device_id=modbus_id) * 10 _, exported = self.peak_filter.check_values(power, None, exported) inverter_state = InverterState( diff --git a/packages/modules/devices/idm/idm/counter.py b/packages/modules/devices/idm/idm/counter.py index 6712dc1580..b7899b43fb 100644 --- a/packages/modules/devices/idm/idm/counter.py +++ b/packages/modules/devices/idm/idm/counter.py @@ -1,6 +1,6 @@ #!/usr/bin/env python3 from typing import TypedDict, Any -from pymodbus.constants import Endian +from modules.common.pymodbus_compat import Endian from modules.common.abstract_device import AbstractCounter from modules.common.component_state import CounterState @@ -37,7 +37,7 @@ def initialize(self) -> None: def update(self): unit = self.modbus_id power = self.client.read_input_registers(4122, ModbusDataType.FLOAT_32, - wordorder=Endian.Little, unit=unit) * 1000 + wordorder=Endian.Little, device_id=unit) * 1000 self.peak_filter.check_values(power) imported, exported = self.sim_counter.sim_count(power) diff --git a/packages/modules/devices/janitza/janitza/bat.py b/packages/modules/devices/janitza/janitza/bat.py index 73d927a81d..4b3a06c8a5 100644 --- a/packages/modules/devices/janitza/janitza/bat.py +++ b/packages/modules/devices/janitza/janitza/bat.py @@ -34,7 +34,7 @@ def initialize(self) -> None: self.peak_filter = PeakFilter(ComponentType.BAT, self.component_config.id, self.fault_state) def update(self): - power = self.__tcp_client.read_holding_registers(19026, ModbusDataType.FLOAT_32, unit=self.__modbus_id) * -1 + power = self.__tcp_client.read_holding_registers(19026, ModbusDataType.FLOAT_32, device_id=self.__modbus_id) * -1 self.peak_filter.check_values(power) imported, exported = self.sim_counter.sim_count(power) diff --git a/packages/modules/devices/janitza/janitza/counter.py b/packages/modules/devices/janitza/janitza/counter.py index 72e054cd23..3d8ea1e6ec 100644 --- a/packages/modules/devices/janitza/janitza/counter.py +++ b/packages/modules/devices/janitza/janitza/counter.py @@ -36,16 +36,16 @@ def initialize(self) -> None: def update(self) -> None: with self.__tcp_client: - power = self.__tcp_client.read_holding_registers(19026, ModbusDataType.FLOAT_32, unit=self.__modbus_id) + power = self.__tcp_client.read_holding_registers(19026, ModbusDataType.FLOAT_32, device_id=self.__modbus_id) powers = self.__tcp_client.read_holding_registers( - 19020, [ModbusDataType.FLOAT_32] * 3, unit=self.__modbus_id) + 19020, [ModbusDataType.FLOAT_32] * 3, device_id=self.__modbus_id) currents = self.__tcp_client.read_holding_registers( - 19012, [ModbusDataType.FLOAT_32] * 3, unit=self.__modbus_id) + 19012, [ModbusDataType.FLOAT_32] * 3, device_id=self.__modbus_id) voltages = self.__tcp_client.read_holding_registers( - 19000, [ModbusDataType.FLOAT_32] * 3, unit=self.__modbus_id) + 19000, [ModbusDataType.FLOAT_32] * 3, device_id=self.__modbus_id) power_factors = self.__tcp_client.read_holding_registers( - 19044, [ModbusDataType.FLOAT_32] * 3, unit=self.__modbus_id) - frequency = self.__tcp_client.read_holding_registers(19050, ModbusDataType.FLOAT_32, unit=self.__modbus_id) + 19044, [ModbusDataType.FLOAT_32] * 3, device_id=self.__modbus_id) + frequency = self.__tcp_client.read_holding_registers(19050, ModbusDataType.FLOAT_32, device_id=self.__modbus_id) self.peak_filter.check_values(power) imported, exported = self.sim_counter.sim_count(power) diff --git a/packages/modules/devices/janitza/janitza/inverter.py b/packages/modules/devices/janitza/janitza/inverter.py index d3637eaed7..598e45166f 100644 --- a/packages/modules/devices/janitza/janitza/inverter.py +++ b/packages/modules/devices/janitza/janitza/inverter.py @@ -34,7 +34,7 @@ def initialize(self) -> None: self.peak_filter = PeakFilter(ComponentType.INVERTER, self.component_config.id, self.fault_state) def update(self): - power = self.__tcp_client.read_holding_registers(19026, ModbusDataType.FLOAT_32, unit=self.__modbus_id) * -1 + power = self.__tcp_client.read_holding_registers(19026, ModbusDataType.FLOAT_32, device_id=self.__modbus_id) * -1 self.peak_filter.check_values(power) _, exported = self.sim_counter.sim_count(power) diff --git a/packages/modules/devices/kaco/kaco_tx/scale.py b/packages/modules/devices/kaco/kaco_tx/scale.py index bfe78d2ddd..b54d14385c 100644 --- a/packages/modules/devices/kaco/kaco_tx/scale.py +++ b/packages/modules/devices/kaco/kaco_tx/scale.py @@ -21,7 +21,7 @@ def scale_registers(registers: List[Number]) -> List[float]: def create_scaled_reader(client: ModbusTcpClient_, modbus_id: int, type: ModbusDataType): def scaled_reader(address: int, count: int): return scale_registers( - client.read_holding_registers(address, [type] * count + [ModbusDataType.INT_16], unit=modbus_id) + client.read_holding_registers(address, [type] * count + [ModbusDataType.INT_16], device_id=modbus_id) ) return scaled_reader diff --git a/packages/modules/devices/kostal/kostal_piko_ci/counter.py b/packages/modules/devices/kostal/kostal_piko_ci/counter.py index d8003c2c29..1b5343da82 100644 --- a/packages/modules/devices/kostal/kostal_piko_ci/counter.py +++ b/packages/modules/devices/kostal/kostal_piko_ci/counter.py @@ -34,10 +34,10 @@ def initialize(self) -> None: def update(self) -> None: unit = self.component_config.configuration.modbus_id - power = self.client.read_holding_registers(252, ModbusDataType.FLOAT_32, unit=unit) + power = self.client.read_holding_registers(252, ModbusDataType.FLOAT_32, device_id=unit) powers = [self.client.read_holding_registers( - reg, ModbusDataType.FLOAT_32, unit=unit) for reg in [224, 234, 244]] - frequency = self.client.read_holding_registers(220, ModbusDataType.FLOAT_32, unit=unit) + reg, ModbusDataType.FLOAT_32, device_id=unit) for reg in [224, 234, 244]] + frequency = self.client.read_holding_registers(220, ModbusDataType.FLOAT_32, device_id=unit) self.peak_filter.check_values(power) imported, exported = self.sim_counter.sim_count(power) diff --git a/packages/modules/devices/kostal/kostal_piko_ci/inverter.py b/packages/modules/devices/kostal/kostal_piko_ci/inverter.py index a9851ac454..34a40d9088 100644 --- a/packages/modules/devices/kostal/kostal_piko_ci/inverter.py +++ b/packages/modules/devices/kostal/kostal_piko_ci/inverter.py @@ -32,10 +32,10 @@ def initialize(self) -> None: def update(self) -> None: unit = self.component_config.configuration.modbus_id - power = self.client.read_holding_registers(172, ModbusDataType.FLOAT_32, unit=unit) * -1 + power = self.client.read_holding_registers(172, ModbusDataType.FLOAT_32, device_id=unit) * -1 currents = [self.client.read_holding_registers( - reg, ModbusDataType.FLOAT_32, unit=unit) for reg in [154, 160, 166]] - exported = self.client.read_holding_registers(320, ModbusDataType.FLOAT_32, unit=unit) + reg, ModbusDataType.FLOAT_32, device_id=unit) for reg in [154, 160, 166]] + exported = self.client.read_holding_registers(320, ModbusDataType.FLOAT_32, device_id=unit) _, exported = self.peak_filter.check_values(power, None, exported) inverter_state = InverterState( power=power, diff --git a/packages/modules/devices/kostal/kostal_plenticore/bat.py b/packages/modules/devices/kostal/kostal_plenticore/bat.py index 4c10ce66cc..d787e315bf 100644 --- a/packages/modules/devices/kostal/kostal_plenticore/bat.py +++ b/packages/modules/devices/kostal/kostal_plenticore/bat.py @@ -1,7 +1,7 @@ #!/usr/bin/env python3 import logging from typing import TypedDict, Any, Optional -from pymodbus.constants import Endian +from modules.common.pymodbus_compat import Endian from modules.common.abstract_device import AbstractBat from modules.common.component_state import BatState @@ -41,12 +41,12 @@ def initialize(self) -> None: def update(self) -> None: power = self.client.read_holding_registers( - 582, ModbusDataType.INT_16, unit=self.modbus_id, wordorder=self.endianess) * -1 + 582, ModbusDataType.INT_16, device_id=self.modbus_id, wordorder=self.endianess) * -1 soc = self.client.read_holding_registers( - 514, ModbusDataType.INT_16, unit=self.modbus_id, wordorder=self.endianess) + 514, ModbusDataType.INT_16, device_id=self.modbus_id, wordorder=self.endianess) if power < 0: power = self.client.read_holding_registers( - 106, ModbusDataType.FLOAT_32, unit=self.modbus_id, wordorder=self.endianess) * -1 + 106, ModbusDataType.FLOAT_32, device_id=self.modbus_id, wordorder=self.endianess) * -1 self.peak_filter.check_values(power) imported, exported = self.sim_counter.sim_count(power) @@ -73,21 +73,21 @@ def set_power_limit(self, power_limit: Optional[int]) -> None: # wiederholt auf Stop setzen damit sich Register nicht zurücksetzt log.debug("Aktive Batteriesteuerung. Batterie wird auf Stop gesetzt und nicht entladen") self.client.write_register(1034, 0.0, data_type=ModbusDataType.FLOAT_32, - wordorder=self.endianess, unit=unit) + wordorder=self.endianess, device_id=unit) elif power_limit < 0: log.debug(f"Aktive Batteriesteuerung. Batterie wird mit {power_limit} W entladen für den Hausverbrauch") # Die maximale Entladeleistung begrenzen auf 7000W power_value = float(min(abs(power_limit), 7000)) log.debug(f"Aktive Batteriesteuerung. Batterie wird mit {power_value} W entladen für den Hausverbrauch") self.client.write_register(1034, power_value, data_type=ModbusDataType.FLOAT_32, - wordorder=self.endianess, unit=unit) + wordorder=self.endianess, device_id=unit) elif power_limit > 0: log.debug(f"Aktive Batteriesteuerung. Batterie wird mit {power_limit} W geladen") # Die maximale Ladeleistung begrenzen auf 7000W power_value = float(min(abs(power_limit), 7000)) * -1 log.debug(f"Aktive Batteriesteuerung. Batterie wird mit {power_value} W geladen") self.client.write_register(1034, power_value, data_type=ModbusDataType.FLOAT_32, - wordorder=self.endianess, unit=unit) + wordorder=self.endianess, device_id=unit) def power_limit_controllable(self) -> bool: return True diff --git a/packages/modules/devices/kostal/kostal_plenticore/counter.py b/packages/modules/devices/kostal/kostal_plenticore/counter.py index d12db3eecf..9652da6995 100644 --- a/packages/modules/devices/kostal/kostal_plenticore/counter.py +++ b/packages/modules/devices/kostal/kostal_plenticore/counter.py @@ -1,6 +1,6 @@ #!/usr/bin/env python3 from typing import TypedDict, Any -from pymodbus.constants import Endian +from modules.common.pymodbus_compat import Endian from modules.common.abstract_device import AbstractCounter from modules.common.component_state import CounterState @@ -38,17 +38,17 @@ def initialize(self) -> None: def update(self) -> None: power = self.client.read_holding_registers( - 252, ModbusDataType.FLOAT_32, unit=self.modbus_id, wordorder=self.endianess) + 252, ModbusDataType.FLOAT_32, device_id=self.modbus_id, wordorder=self.endianess) power_factor = self.client.read_holding_registers( - 150, ModbusDataType.FLOAT_32, unit=self.modbus_id, wordorder=self.endianess) + 150, ModbusDataType.FLOAT_32, device_id=self.modbus_id, wordorder=self.endianess) currents = [self.client.read_holding_registers( - reg, ModbusDataType.FLOAT_32, unit=self.modbus_id, wordorder=self.endianess) for reg in [222, 232, 242]] + reg, ModbusDataType.FLOAT_32, device_id=self.modbus_id, wordorder=self.endianess) for reg in [222, 232, 242]] voltages = [self.client.read_holding_registers( - reg, ModbusDataType.FLOAT_32, unit=self.modbus_id, wordorder=self.endianess) for reg in [230, 240, 250]] + reg, ModbusDataType.FLOAT_32, device_id=self.modbus_id, wordorder=self.endianess) for reg in [230, 240, 250]] powers = [self.client.read_holding_registers( - reg, ModbusDataType.FLOAT_32, unit=self.modbus_id, wordorder=self.endianess) for reg in [224, 234, 244]] + reg, ModbusDataType.FLOAT_32, device_id=self.modbus_id, wordorder=self.endianess) for reg in [224, 234, 244]] frequency = self.client.read_holding_registers( - 220, ModbusDataType.FLOAT_32, unit=self.modbus_id, wordorder=self.endianess) + 220, ModbusDataType.FLOAT_32, device_id=self.modbus_id, wordorder=self.endianess) self.peak_filter.check_values(power) imported, exported = self.sim_counter.sim_count(power) diff --git a/packages/modules/devices/kostal/kostal_plenticore/device.py b/packages/modules/devices/kostal/kostal_plenticore/device.py index e911c90a4d..120364091f 100644 --- a/packages/modules/devices/kostal/kostal_plenticore/device.py +++ b/packages/modules/devices/kostal/kostal_plenticore/device.py @@ -1,7 +1,7 @@ #!/usr/bin/env python3 import logging from typing import Iterable, Union -from pymodbus.constants import Endian +from modules.common.pymodbus_compat import Endian from modules.common.abstract_device import DeviceDescriptor from modules.common.configurable_device import ConfigurableDevice, ComponentFactoryByType, MultiComponentUpdater @@ -54,7 +54,7 @@ def initializer(): nonlocal client, endianess client = ModbusTcpClient_(device_config.configuration.ip_address, device_config.configuration.port) endianess = Endian.Big if client.read_holding_registers( - 5, ModbusDataType.UINT_16, unit=device_config.configuration.modbus_id) else Endian.Little + 5, ModbusDataType.UINT_16, device_id=device_config.configuration.modbus_id) else Endian.Little return ConfigurableDevice( device_config=device_config, diff --git a/packages/modules/devices/kostal/kostal_plenticore/inverter.py b/packages/modules/devices/kostal/kostal_plenticore/inverter.py index 8712ba8ba2..6f51c226ca 100644 --- a/packages/modules/devices/kostal/kostal_plenticore/inverter.py +++ b/packages/modules/devices/kostal/kostal_plenticore/inverter.py @@ -1,6 +1,6 @@ #!/usr/bin/env python3 from typing import TypedDict, Any -from pymodbus.constants import Endian +from modules.common.pymodbus_compat import Endian from modules.common.abstract_device import AbstractInverter from modules.common.component_state import InverterState @@ -42,13 +42,13 @@ def initialize(self) -> None: def update(self) -> None: power = self.client.read_holding_registers( - 575, ModbusDataType.INT_16, unit=self.modbus_id, wordorder=self.endianess) * -1 + 575, ModbusDataType.INT_16, device_id=self.modbus_id, wordorder=self.endianess) * -1 exported = self.client.read_holding_registers( - 320, ModbusDataType.FLOAT_32, unit=self.modbus_id, wordorder=self.endianess) + 320, ModbusDataType.FLOAT_32, device_id=self.modbus_id, wordorder=self.endianess) # Try to read dc_power, if it fails just skip it and set to None try: dc_power = self.client.read_holding_registers( - 1066, ModbusDataType.FLOAT_32, unit=self.modbus_id, wordorder=self.endianess) * -1 + 1066, ModbusDataType.FLOAT_32, device_id=self.modbus_id, wordorder=self.endianess) * -1 self.fault_state.no_error() except Exception: dc_power = None diff --git a/packages/modules/devices/kostal/kostal_sem/counter.py b/packages/modules/devices/kostal/kostal_sem/counter.py index a14fa66820..db2f061429 100644 --- a/packages/modules/devices/kostal/kostal_sem/counter.py +++ b/packages/modules/devices/kostal/kostal_sem/counter.py @@ -32,23 +32,23 @@ def initialize(self) -> None: def update(self): with self.__tcp_client: voltages = [self.__tcp_client.read_holding_registers( - reg, ModbusDataType.UINT_32, unit=self.__modbus_id) * 0.001 for reg in [62, 102, 142]] + reg, ModbusDataType.UINT_32, device_id=self.__modbus_id) * 0.001 for reg in [62, 102, 142]] currents = [self.__tcp_client.read_holding_registers( - reg, ModbusDataType.UINT_32, unit=self.__modbus_id) * 0.001 for reg in [60, 100, 140]] + reg, ModbusDataType.UINT_32, device_id=self.__modbus_id) * 0.001 for reg in [60, 100, 140]] power_factors = [self.__tcp_client.read_holding_registers( - reg, ModbusDataType.INT_32, unit=self.__modbus_id) * 0.001 for reg in [64, 104, 144]] + reg, ModbusDataType.INT_32, device_id=self.__modbus_id) * 0.001 for reg in [64, 104, 144]] imported, exported = [val * 0.1 for val in self.__tcp_client.read_holding_registers( - 512, [ModbusDataType.UINT_64]*2, unit=self.__modbus_id)] + 512, [ModbusDataType.UINT_64]*2, device_id=self.__modbus_id)] frequency = self.__tcp_client.read_holding_registers( - 26, ModbusDataType.UINT_32, unit=self.__modbus_id) * 0.001 + 26, ModbusDataType.UINT_32, device_id=self.__modbus_id) * 0.001 powers = [] for reg in [40, 80, 120]: powers_temp = self.__tcp_client.read_holding_registers( - reg, [ModbusDataType.UINT_32]*2, unit=self.__modbus_id) + reg, [ModbusDataType.UINT_32]*2, device_id=self.__modbus_id) powers.append((powers_temp[0] if powers_temp[0] >= powers_temp[1] else -powers_temp[1]) * 0.1) - power_temp = self.__tcp_client.read_holding_registers(0, [ModbusDataType.UINT_32]*2, unit=self.__modbus_id) + power_temp = self.__tcp_client.read_holding_registers(0, [ModbusDataType.UINT_32]*2, device_id=self.__modbus_id) power = (power_temp[0] if power_temp[0] >= power_temp[1] else -power_temp[1]) * 0.1 imported, exported = self.peak_filter.check_values(power, imported, exported) counter_state = CounterState( diff --git a/packages/modules/devices/marstek/venus_c_e/bat.py b/packages/modules/devices/marstek/venus_c_e/bat.py index 2c848e23a1..f2c3f13c54 100644 --- a/packages/modules/devices/marstek/venus_c_e/bat.py +++ b/packages/modules/devices/marstek/venus_c_e/bat.py @@ -31,11 +31,11 @@ def initialize(self) -> None: self.peak_filter = PeakFilter(ComponentType.BAT, self.component_config.id, self.fault_state) def _read_reg(self, addr: int, type_: ModbusDataType) -> Union[int, float]: - return self.client.read_holding_registers(addr, type_, unit=self.component_config.configuration.modbus_id) + return self.client.read_holding_registers(addr, type_, device_id=self.component_config.configuration.modbus_id) def _write_reg(self, addr: int, val: int) -> None: # Marstek Venus does not work with write_registers! - self.client._delegate.write_register(addr, val, unit=self.component_config.configuration.modbus_id) + self.client._delegate.write_register(addr, val, device_id=self.component_config.configuration.modbus_id) def update(self) -> None: power = -self._read_reg(32202, ModbusDataType.INT_32) diff --git a/packages/modules/devices/mtec/mtec/bat.py b/packages/modules/devices/mtec/mtec/bat.py index ffe652a905..bfbcd0e9fb 100644 --- a/packages/modules/devices/mtec/mtec/bat.py +++ b/packages/modules/devices/mtec/mtec/bat.py @@ -39,12 +39,12 @@ def update(self) -> None: generation = self.component_config.configuration.generation if generation == 2: - power = self.client.read_holding_registers(40258, ModbusDataType.INT_32, unit=unit) * -1 + power = self.client.read_holding_registers(40258, ModbusDataType.INT_32, device_id=unit) * -1 # soc unit 0.01% - soc = self.client.read_holding_registers(43000, ModbusDataType.UINT_16, unit=unit) / 100 + soc = self.client.read_holding_registers(43000, ModbusDataType.UINT_16, device_id=unit) / 100 else: - power = self.client.read_holding_registers(30258, ModbusDataType.INT_32, unit=unit) * -1 - soc = self.client.read_holding_registers(33000, ModbusDataType.UINT_16, unit=unit) / 100 + power = self.client.read_holding_registers(30258, ModbusDataType.INT_32, device_id=unit) * -1 + soc = self.client.read_holding_registers(33000, ModbusDataType.UINT_16, device_id=unit) / 100 self.peak_filter.check_values(power) imported, exported = self.sim_counter.sim_count(power) diff --git a/packages/modules/devices/mtec/mtec/counter.py b/packages/modules/devices/mtec/mtec/counter.py index cdbec9fb68..7a499f5460 100644 --- a/packages/modules/devices/mtec/mtec/counter.py +++ b/packages/modules/devices/mtec/mtec/counter.py @@ -34,8 +34,8 @@ def initialize(self) -> None: def update(self) -> None: unit = self.component_config.configuration.modbus_id - power = self.client.read_holding_registers(11000, ModbusDataType.INT_32, unit=unit) * -1 - powers = self.client.read_holding_registers(10994, [ModbusDataType.INT_32]*3, unit=unit) + power = self.client.read_holding_registers(11000, ModbusDataType.INT_32, device_id=unit) * -1 + powers = self.client.read_holding_registers(10994, [ModbusDataType.INT_32]*3, device_id=unit) powers = [value * -1 for value in powers] self.peak_filter.check_values(power) diff --git a/packages/modules/devices/mtec/mtec/inverter.py b/packages/modules/devices/mtec/mtec/inverter.py index fbd5975359..139cff48e7 100644 --- a/packages/modules/devices/mtec/mtec/inverter.py +++ b/packages/modules/devices/mtec/mtec/inverter.py @@ -34,7 +34,7 @@ def initialize(self) -> None: def update(self) -> None: unit = self.component_config.configuration.modbus_id - power = self.client.read_holding_registers(11028, ModbusDataType.UINT_32, unit=unit) * -1 + power = self.client.read_holding_registers(11028, ModbusDataType.UINT_32, device_id=unit) * -1 self.peak_filter.check_values(power) _, exported = self.sim_counter.sim_count(power) diff --git a/packages/modules/devices/nibe/nibe/counter.py b/packages/modules/devices/nibe/nibe/counter.py index b20830a29c..389df061a7 100644 --- a/packages/modules/devices/nibe/nibe/counter.py +++ b/packages/modules/devices/nibe/nibe/counter.py @@ -1,6 +1,6 @@ #!/usr/bin/env python3 from typing import TypedDict, Any -from pymodbus.constants import Endian +from modules.common.pymodbus_compat import Endian from modules.common.abstract_device import AbstractCounter from modules.common.component_state import CounterState @@ -34,7 +34,7 @@ def initialize(self) -> None: def update(self): unit = self.component_config.configuration.modbus_id - power = self.client.read_input_registers(2166, ModbusDataType.UINT_32, wordorder=Endian.Little, unit=unit) + power = self.client.read_input_registers(2166, ModbusDataType.UINT_32, wordorder=Endian.Little, device_id=unit) self.peak_filter.check_values(power) imported, exported = self.sim_counter.sim_count(power) diff --git a/packages/modules/devices/orno/orno/counter.py b/packages/modules/devices/orno/orno/counter.py index 2b5c19ed62..71c7f651be 100644 --- a/packages/modules/devices/orno/orno/counter.py +++ b/packages/modules/devices/orno/orno/counter.py @@ -29,9 +29,9 @@ def initialize(self) -> None: def update(self): power = self.client.read_holding_registers( - 0x141, ModbusDataType.INT_32, unit=self.component_config.configuration.modbus_id) + 0x141, ModbusDataType.INT_32, device_id=self.component_config.configuration.modbus_id) imported = self.client.read_holding_registers( - 0xA001, ModbusDataType.INT_32, unit=self.component_config.configuration.modbus_id) * 10 + 0xA001, ModbusDataType.INT_32, device_id=self.component_config.configuration.modbus_id) * 10 imported, _ = self.peak_filter.check_values(power, imported, None) counter_state = CounterState( imported=imported, diff --git a/packages/modules/devices/orno/orno/device.py b/packages/modules/devices/orno/orno/device.py index 169bc971fd..232073123d 100644 --- a/packages/modules/devices/orno/orno/device.py +++ b/packages/modules/devices/orno/orno/device.py @@ -1,6 +1,6 @@ #!/usr/bin/env python3 import logging -from pymodbus.transaction import ModbusRtuFramer +from pymodbus.framer import FramerType from typing import Iterable from modules.common.abstract_device import DeviceDescriptor @@ -29,7 +29,7 @@ def update_components(components: Iterable[OrnoCounter]): def initializer(): nonlocal client client = ModbusTcpClient_(device_config.configuration.ip_address, - device_config.configuration.port, framer=ModbusRtuFramer) + device_config.configuration.port, framer=FramerType.RTU) return ConfigurableDevice( device_config=device_config, diff --git a/packages/modules/devices/powerdog/powerdog/counter.py b/packages/modules/devices/powerdog/powerdog/counter.py index 9319da99e3..7e45fc42e0 100644 --- a/packages/modules/devices/powerdog/powerdog/counter.py +++ b/packages/modules/devices/powerdog/powerdog/counter.py @@ -41,13 +41,13 @@ def update(self, inverter_power: float) -> None: with self.__tcp_client: if self.component_config.configuration.position_evu: export_power = self.__tcp_client.read_input_registers( - 40000, ModbusDataType.INT_32, unit=self.__modbus_id) * -1 + 40000, ModbusDataType.INT_32, device_id=self.__modbus_id) * -1 import_power = self.__tcp_client.read_input_registers( - 40024, ModbusDataType.INT_32, unit=self.__modbus_id) + 40024, ModbusDataType.INT_32, device_id=self.__modbus_id) power = export_power + import_power else: home_consumption = self.__tcp_client.read_input_registers( - 40026, ModbusDataType.INT_32, unit=self.__modbus_id) + 40026, ModbusDataType.INT_32, device_id=self.__modbus_id) power = home_consumption + inverter_power log.debug("Powerdog Hausverbrauch[W]: " + str(home_consumption)) diff --git a/packages/modules/devices/powerdog/powerdog/inverter.py b/packages/modules/devices/powerdog/powerdog/inverter.py index 241cdf01ae..5c98042028 100644 --- a/packages/modules/devices/powerdog/powerdog/inverter.py +++ b/packages/modules/devices/powerdog/powerdog/inverter.py @@ -39,7 +39,7 @@ def initialize(self) -> None: def update(self) -> float: with self.__tcp_client: - power = self.__tcp_client.read_input_registers(40002, ModbusDataType.INT_32, unit=self.__modbus_id) * -1 + power = self.__tcp_client.read_input_registers(40002, ModbusDataType.INT_32, device_id=self.__modbus_id) * -1 self.peak_filter.check_values(power) _, exported = self.sim_counter.sim_count(power) diff --git a/packages/modules/devices/qcells/qcells/bat.py b/packages/modules/devices/qcells/qcells/bat.py index 3a68bd58cd..b4e2b5d164 100644 --- a/packages/modules/devices/qcells/qcells/bat.py +++ b/packages/modules/devices/qcells/qcells/bat.py @@ -30,12 +30,12 @@ def initialize(self) -> None: self.peak_filter = PeakFilter(ComponentType.BAT, self.component_config.id, self.fault_state) def update(self) -> None: - power = self.client.read_input_registers(0x0016, ModbusDataType.INT_16, unit=self.__modbus_id) - soc = self.client.read_input_registers(0x001C, ModbusDataType.UINT_16, unit=self.__modbus_id) + power = self.client.read_input_registers(0x0016, ModbusDataType.INT_16, device_id=self.__modbus_id) + soc = self.client.read_input_registers(0x001C, ModbusDataType.UINT_16, device_id=self.__modbus_id) imported = self.client.read_input_registers( - 0x0021, ModbusDataType.UINT_16, unit=self.__modbus_id) * 100 + 0x0021, ModbusDataType.UINT_16, device_id=self.__modbus_id) * 100 exported = self.client.read_input_registers( - 0x001D, ModbusDataType.UINT_16, unit=self.__modbus_id) * 100 + 0x001D, ModbusDataType.UINT_16, device_id=self.__modbus_id) * 100 imported, exported = self.peak_filter.check_values(power, imported, exported) bat_state = BatState( diff --git a/packages/modules/devices/qcells/qcells/counter.py b/packages/modules/devices/qcells/qcells/counter.py index 3102cf7f45..d00abe27c0 100644 --- a/packages/modules/devices/qcells/qcells/counter.py +++ b/packages/modules/devices/qcells/qcells/counter.py @@ -1,6 +1,6 @@ #!/usr/bin/env python3 from typing import TypedDict, Any -from pymodbus.constants import Endian +from modules.common.pymodbus_compat import Endian from modules.common.abstract_device import AbstractCounter from modules.common.component_state import CounterState @@ -32,22 +32,22 @@ def initialize(self) -> None: def update(self) -> None: power = self.client.read_input_registers(0x0046, ModbusDataType.INT_32, wordorder=Endian.Little, - unit=self.__modbus_id) * -1 + device_id=self.__modbus_id) * -1 frequency = self.client.read_input_registers( - 0x0007, ModbusDataType.UINT_16, unit=self.__modbus_id) / 100 + 0x0007, ModbusDataType.UINT_16, device_id=self.__modbus_id) / 100 try: powers = [-value for value in self.client.read_input_registers( - 0x0082, [ModbusDataType.INT_32] * 3, wordorder=Endian.Little, unit=self.__modbus_id + 0x0082, [ModbusDataType.INT_32] * 3, wordorder=Endian.Little, device_id=self.__modbus_id )] except Exception: powers = None try: voltages = [self.client.read_input_registers( - 0x006A, ModbusDataType.UINT_16, unit=self.__modbus_id + 0x006A, ModbusDataType.UINT_16, device_id=self.__modbus_id ) / 10, self.client.read_input_registers( - 0x006E, ModbusDataType.UINT_16, unit=self.__modbus_id + 0x006E, ModbusDataType.UINT_16, device_id=self.__modbus_id ) / 10, self.client.read_input_registers( - 0x0072, ModbusDataType.UINT_16, unit=self.__modbus_id + 0x0072, ModbusDataType.UINT_16, device_id=self.__modbus_id ) / 10] if voltages[0] < 1: voltages[0] = 230 @@ -60,7 +60,7 @@ def update(self) -> None: exported, imported = [value * 10 for value in self.client.read_input_registers( 0x0048, [ModbusDataType.UINT_32] * 2, - wordorder=Endian.Little, unit=self.__modbus_id + wordorder=Endian.Little, device_id=self.__modbus_id )] imported, exported = self.peak_filter.check_values(power, imported, exported) diff --git a/packages/modules/devices/qcells/qcells/inverter.py b/packages/modules/devices/qcells/qcells/inverter.py index 4f147027d4..71ad8a0398 100644 --- a/packages/modules/devices/qcells/qcells/inverter.py +++ b/packages/modules/devices/qcells/qcells/inverter.py @@ -1,6 +1,6 @@ #!/usr/bin/env python3 from typing import TypedDict, Any -from pymodbus.constants import Endian +from modules.common.pymodbus_compat import Endian from modules.common.abstract_device import AbstractInverter from modules.common.component_state import InverterState @@ -32,14 +32,14 @@ def initialize(self) -> None: def update(self) -> None: power_string1 = (self.client.read_input_registers( - 0x0003, ModbusDataType.INT_16, unit=self.__modbus_id) / 10) * \ - (self.client.read_input_registers(0x0005, ModbusDataType.INT_16, unit=self.__modbus_id) / 10) + 0x0003, ModbusDataType.INT_16, device_id=self.__modbus_id) / 10) * \ + (self.client.read_input_registers(0x0005, ModbusDataType.INT_16, device_id=self.__modbus_id) / 10) power_string2 = (self.client.read_input_registers( - 0x0004, ModbusDataType.INT_16, unit=self.__modbus_id) / 10) * \ - (self.client.read_input_registers(0x0006, ModbusDataType.INT_16, unit=self.__modbus_id) / 10) + 0x0004, ModbusDataType.INT_16, device_id=self.__modbus_id) / 10) * \ + (self.client.read_input_registers(0x0006, ModbusDataType.INT_16, device_id=self.__modbus_id) / 10) power = (power_string1 + power_string2) * -1 exported = self.client.read_input_registers(0x0094, ModbusDataType.UINT_32, wordorder=Endian.Little, - unit=self.__modbus_id) * 100 + device_id=self.__modbus_id) * 100 _, exported = self.peak_filter.check_values(power, None, exported) inverter_state = InverterState( diff --git a/packages/modules/devices/saxpower/saxpower/bat.py b/packages/modules/devices/saxpower/saxpower/bat.py index 6149d2b52a..41070665d7 100644 --- a/packages/modules/devices/saxpower/saxpower/bat.py +++ b/packages/modules/devices/saxpower/saxpower/bat.py @@ -37,7 +37,7 @@ def initialize(self) -> None: def update(self) -> None: with self.__tcp_client: # Die beiden Register müssen zwingend zusammen ausgelesen werden, sonst scheitert die zweite Abfrage. - soc, power = self.__tcp_client.read_holding_registers(46, [ModbusDataType.INT_16]*2, unit=self.__modbus_id) + soc, power = self.__tcp_client.read_holding_registers(46, [ModbusDataType.INT_16]*2, device_id=self.__modbus_id) power = power * -1 + 16384 self.peak_filter.check_values(power) imported, exported = self.sim_counter.sim_count(power) diff --git a/packages/modules/devices/saxpower/saxpower/counter.py b/packages/modules/devices/saxpower/saxpower/counter.py index bc6ace7263..a8a4272b4f 100644 --- a/packages/modules/devices/saxpower/saxpower/counter.py +++ b/packages/modules/devices/saxpower/saxpower/counter.py @@ -34,7 +34,7 @@ def initialize(self) -> None: self.peak_filter = PeakFilter(ComponentType.COUNTER, self.component_config.id, self.fault_state) def update(self) -> None: - power = self.client.read_holding_registers(48, ModbusDataType.INT_16, unit=self.__modbus_id) + power = self.client.read_holding_registers(48, ModbusDataType.INT_16, device_id=self.__modbus_id) power = power - 16384 self.peak_filter.check_values(power) imported, exported = self.sim_counter.sim_count(power) diff --git a/packages/modules/devices/siemens/siemens/bat.py b/packages/modules/devices/siemens/siemens/bat.py index 3200fffb58..da7a74eb6f 100644 --- a/packages/modules/devices/siemens/siemens/bat.py +++ b/packages/modules/devices/siemens/siemens/bat.py @@ -36,8 +36,8 @@ def initialize(self) -> None: def update(self) -> None: with self.__tcp_client: - power = self.__tcp_client.read_holding_registers(6, ModbusDataType.INT_32, unit=self.__modbus_id) * -1 - soc = int(self.__tcp_client.read_holding_registers(8, ModbusDataType.INT_32, unit=self.__modbus_id)) + power = self.__tcp_client.read_holding_registers(6, ModbusDataType.INT_32, device_id=self.__modbus_id) * -1 + soc = int(self.__tcp_client.read_holding_registers(8, ModbusDataType.INT_32, device_id=self.__modbus_id)) self.peak_filter.check_values(power) imported, exported = self.sim_counter.sim_count(power) diff --git a/packages/modules/devices/siemens/siemens/counter.py b/packages/modules/devices/siemens/siemens/counter.py index 6f694febdb..2ef16010d9 100644 --- a/packages/modules/devices/siemens/siemens/counter.py +++ b/packages/modules/devices/siemens/siemens/counter.py @@ -36,7 +36,7 @@ def initialize(self) -> None: def update(self) -> None: with self.__tcp_client: - power = self.__tcp_client.read_holding_registers(14, ModbusDataType.INT_32, unit=self.__modbus_id) + power = self.__tcp_client.read_holding_registers(14, ModbusDataType.INT_32, device_id=self.__modbus_id) self.peak_filter.check_values(power) imported, exported = self.sim_counter.sim_count(power) diff --git a/packages/modules/devices/siemens/siemens/inverter.py b/packages/modules/devices/siemens/siemens/inverter.py index c190ee7230..4c452b3177 100644 --- a/packages/modules/devices/siemens/siemens/inverter.py +++ b/packages/modules/devices/siemens/siemens/inverter.py @@ -36,7 +36,7 @@ def initialize(self) -> None: def update(self) -> None: with self.__tcp_client: - power = self.__tcp_client.read_holding_registers(16, ModbusDataType.INT_32, unit=self.__modbus_id) * -1 + power = self.__tcp_client.read_holding_registers(16, ModbusDataType.INT_32, device_id=self.__modbus_id) * -1 self.peak_filter.check_values(power) _, exported = self.sim_counter.sim_count(power) diff --git a/packages/modules/devices/siemens/siemens_sentron/bat.py b/packages/modules/devices/siemens/siemens_sentron/bat.py index fa25f09b03..5c143a0758 100644 --- a/packages/modules/devices/siemens/siemens_sentron/bat.py +++ b/packages/modules/devices/siemens/siemens_sentron/bat.py @@ -32,9 +32,9 @@ def initialize(self) -> None: def update(self) -> None: with self.__tcp_client: - power = self.__tcp_client.read_holding_registers(65, ModbusDataType.FLOAT_32, unit=self.__modbus_id) * -1 - imported = self.__tcp_client.read_holding_registers(801, ModbusDataType.FLOAT_64, unit=self.__modbus_id) - exported = self.__tcp_client.read_holding_registers(809, ModbusDataType.FLOAT_64, unit=self.__modbus_id) + power = self.__tcp_client.read_holding_registers(65, ModbusDataType.FLOAT_32, device_id=self.__modbus_id) * -1 + imported = self.__tcp_client.read_holding_registers(801, ModbusDataType.FLOAT_64, device_id=self.__modbus_id) + exported = self.__tcp_client.read_holding_registers(809, ModbusDataType.FLOAT_64, device_id=self.__modbus_id) imported, exported = self.peak_filter.check_values(power, imported, exported) bat_state = BatState( diff --git a/packages/modules/devices/siemens/siemens_sentron/counter.py b/packages/modules/devices/siemens/siemens_sentron/counter.py index b3e2e25f52..313cf151e0 100644 --- a/packages/modules/devices/siemens/siemens_sentron/counter.py +++ b/packages/modules/devices/siemens/siemens_sentron/counter.py @@ -32,16 +32,16 @@ def initialize(self) -> None: def update(self) -> None: with self.__tcp_client: - imported = self.__tcp_client.read_holding_registers(801, ModbusDataType.FLOAT_64, unit=self.__modbus_id) - exported = self.__tcp_client.read_holding_registers(809, ModbusDataType.FLOAT_64, unit=self.__modbus_id) - power = self.__tcp_client.read_holding_registers(65, ModbusDataType.FLOAT_32, unit=self.__modbus_id) - powers = self.__tcp_client.read_holding_registers(25, [ModbusDataType.FLOAT_32] * 3, unit=self.__modbus_id) - frequency = self.__tcp_client.read_holding_registers(55, ModbusDataType.FLOAT_32, unit=self.__modbus_id) + imported = self.__tcp_client.read_holding_registers(801, ModbusDataType.FLOAT_64, device_id=self.__modbus_id) + exported = self.__tcp_client.read_holding_registers(809, ModbusDataType.FLOAT_64, device_id=self.__modbus_id) + power = self.__tcp_client.read_holding_registers(65, ModbusDataType.FLOAT_32, device_id=self.__modbus_id) + powers = self.__tcp_client.read_holding_registers(25, [ModbusDataType.FLOAT_32] * 3, device_id=self.__modbus_id) + frequency = self.__tcp_client.read_holding_registers(55, ModbusDataType.FLOAT_32, device_id=self.__modbus_id) currents = self.__tcp_client.read_holding_registers( - 13, [ModbusDataType.FLOAT_32] * 3, unit=self.__modbus_id) - voltages = self.__tcp_client.read_holding_registers(1, [ModbusDataType.FLOAT_32] * 3, unit=self.__modbus_id) + 13, [ModbusDataType.FLOAT_32] * 3, device_id=self.__modbus_id) + voltages = self.__tcp_client.read_holding_registers(1, [ModbusDataType.FLOAT_32] * 3, device_id=self.__modbus_id) power_factors = self.__tcp_client.read_holding_registers( - 37, [ModbusDataType.FLOAT_32] * 3, unit=self.__modbus_id) + 37, [ModbusDataType.FLOAT_32] * 3, device_id=self.__modbus_id) imported, exported = self.peak_filter.check_values(power, imported, exported) counter_state = CounterState( diff --git a/packages/modules/devices/siemens/siemens_sentron/inverter.py b/packages/modules/devices/siemens/siemens_sentron/inverter.py index 6a54107a25..626a51cff3 100644 --- a/packages/modules/devices/siemens/siemens_sentron/inverter.py +++ b/packages/modules/devices/siemens/siemens_sentron/inverter.py @@ -32,8 +32,8 @@ def initialize(self) -> None: def update(self) -> None: with self.__tcp_client: - power = self.__tcp_client.read_holding_registers(65, ModbusDataType.FLOAT_32, unit=self.__modbus_id) * -1 - exported = self.__tcp_client.read_holding_registers(809, ModbusDataType.FLOAT_64, unit=self.__modbus_id) + power = self.__tcp_client.read_holding_registers(65, ModbusDataType.FLOAT_32, device_id=self.__modbus_id) * -1 + exported = self.__tcp_client.read_holding_registers(809, ModbusDataType.FLOAT_64, device_id=self.__modbus_id) _, exported = self.peak_filter.check_values(power, None, exported) inverter_state = InverterState( diff --git a/packages/modules/devices/sigenergy/sigenergy/bat.py b/packages/modules/devices/sigenergy/sigenergy/bat.py index 26cb612de7..0abf6015b6 100644 --- a/packages/modules/devices/sigenergy/sigenergy/bat.py +++ b/packages/modules/devices/sigenergy/sigenergy/bat.py @@ -37,9 +37,9 @@ def initialize(self) -> None: def update(self) -> None: unit = self.component_config.configuration.modbus_id - power = self.client.read_holding_registers(30037, ModbusDataType.INT_32, unit=unit) + power = self.client.read_holding_registers(30037, ModbusDataType.INT_32, device_id=unit) # soc unit 0.1% - soc = self.client.read_holding_registers(30014, ModbusDataType.UINT_16, unit=unit) / 10 + soc = self.client.read_holding_registers(30014, ModbusDataType.UINT_16, device_id=unit) / 10 self.peak_filter.check_values(power) imported, exported = self.sim_counter.sim_count(power) @@ -59,13 +59,13 @@ def set_power_limit(self, power_limit: Optional[int]) -> None: log.debug("Keine Batteriesteuerung, Selbstregelung durch Wechselrichter") if self.last_mode is not None: # Entladesperre ab 5%, Ansonsten Eigenregelung - self.client.write_register(40048, 50, data_type=ModbusDataType.UINT_16, unit=unit) + self.client.write_register(40048, 50, data_type=ModbusDataType.UINT_16, device_id=unit) self.last_mode = None else: log.debug("Aktive Batteriesteuerung. Batterie wird auf Stop gesetzt und nicht entladen") if self.last_mode != 'stop': # Entladesperre auch bei 100% SoC - self.client.write_register(40048, 1000, data_type=ModbusDataType.UINT_16, unit=unit) + self.client.write_register(40048, 1000, data_type=ModbusDataType.UINT_16, device_id=unit) self.last_mode = 'stop' def power_limit_controllable(self) -> bool: diff --git a/packages/modules/devices/sigenergy/sigenergy/counter.py b/packages/modules/devices/sigenergy/sigenergy/counter.py index f8d4e2b7c7..a861b31774 100644 --- a/packages/modules/devices/sigenergy/sigenergy/counter.py +++ b/packages/modules/devices/sigenergy/sigenergy/counter.py @@ -32,8 +32,8 @@ def initialize(self) -> None: def update(self): unit = self.component_config.configuration.modbus_id - powers = self.client.read_holding_registers(30052, [ModbusDataType.INT_32]*3, unit=unit) - power = self.client.read_holding_registers(30005, ModbusDataType.INT_32, unit=unit) + powers = self.client.read_holding_registers(30052, [ModbusDataType.INT_32]*3, device_id=unit) + power = self.client.read_holding_registers(30005, ModbusDataType.INT_32, device_id=unit) self.peak_filter.check_values(power) imported, exported = self.sim_counter.sim_count(power) diff --git a/packages/modules/devices/sigenergy/sigenergy/inverter.py b/packages/modules/devices/sigenergy/sigenergy/inverter.py index 06c1d824d4..3bdb9d0ccc 100644 --- a/packages/modules/devices/sigenergy/sigenergy/inverter.py +++ b/packages/modules/devices/sigenergy/sigenergy/inverter.py @@ -33,7 +33,7 @@ def initialize(self) -> None: def update(self) -> None: unit = self.component_config.configuration.modbus_id - power = self.client.read_holding_registers(30035, ModbusDataType.INT_32, unit=unit) * -1 + power = self.client.read_holding_registers(30035, ModbusDataType.INT_32, device_id=unit) * -1 self.peak_filter.check_values(power) _, exported = self.sim_counter.sim_count(power) diff --git a/packages/modules/devices/sma/sma_sunny_boy/bat.py b/packages/modules/devices/sma/sma_sunny_boy/bat.py index b405760df1..debf53f961 100644 --- a/packages/modules/devices/sma/sma_sunny_boy/bat.py +++ b/packages/modules/devices/sma/sma_sunny_boy/bat.py @@ -35,16 +35,16 @@ def initialize(self) -> None: def read(self) -> BatState: unit = self.component_config.configuration.modbus_id - soc = self.__tcp_client.read_holding_registers(30845, ModbusDataType.UINT_32, unit=unit) - imp = self.__tcp_client.read_holding_registers(31393, ModbusDataType.INT_32, unit=unit) - exp = self.__tcp_client.read_holding_registers(31395, ModbusDataType.INT_32, unit=unit) + soc = self.__tcp_client.read_holding_registers(30845, ModbusDataType.UINT_32, device_id=unit) + imp = self.__tcp_client.read_holding_registers(31393, ModbusDataType.INT_32, device_id=unit) + exp = self.__tcp_client.read_holding_registers(31395, ModbusDataType.INT_32, device_id=unit) if imp > 5: power = imp else: power = exp * -1 - exported = self.__tcp_client.read_holding_registers(31401, ModbusDataType.UINT_64, unit=unit) - imported = self.__tcp_client.read_holding_registers(31397, ModbusDataType.UINT_64, unit=unit) + exported = self.__tcp_client.read_holding_registers(31401, ModbusDataType.UINT_64, device_id=unit) + imported = self.__tcp_client.read_holding_registers(31397, ModbusDataType.UINT_64, device_id=unit) if exported == self.SMA_UINT_64_NAN or imported == self.SMA_UINT_64_NAN: raise ValueError(f'Batterie lieferte nicht plausible Werte. Export: {exported}, Import: {imported}. ', diff --git a/packages/modules/devices/sma/sma_sunny_boy/bat_smart_energy.py b/packages/modules/devices/sma/sma_sunny_boy/bat_smart_energy.py index 8e320ea5be..554d9eb44c 100644 --- a/packages/modules/devices/sma/sma_sunny_boy/bat_smart_energy.py +++ b/packages/modules/devices/sma/sma_sunny_boy/bat_smart_energy.py @@ -128,14 +128,14 @@ def _read_registers(self, register_names: list, unit: int) -> Dict[str, Union[in values = {} for key in register_names: address, data_type = self.REGISTERS[key] - values[key] = self.__tcp_client.read_holding_registers(address, data_type, unit=unit) + values[key] = self.__tcp_client.read_holding_registers(address, data_type, device_id=unit) log.debug(f"Bat raw values {self.__tcp_client.address}: {values}") return values def _write_registers(self, values_to_write: Dict[str, Union[int, float]], unit: int) -> None: for key, value in values_to_write.items(): address, data_type = self.REGISTERS[key] - self.__tcp_client.write_register(address, value, data_type, unit=unit) + self.__tcp_client.write_register(address, value, data_type, device_id=unit) log.debug(f"Neuer Wert {value} in Register {address} geschrieben.") def power_limit_controllable(self) -> bool: diff --git a/packages/modules/devices/sma/sma_sunny_boy/bat_tesvolt.py b/packages/modules/devices/sma/sma_sunny_boy/bat_tesvolt.py index 166898839e..d5d5b30eb7 100644 --- a/packages/modules/devices/sma/sma_sunny_boy/bat_tesvolt.py +++ b/packages/modules/devices/sma/sma_sunny_boy/bat_tesvolt.py @@ -35,8 +35,8 @@ def initialize(self) -> None: self.peak_filter = PeakFilter(ComponentType.BAT, self.component_config.id, self.fault_state) def update(self) -> None: - soc = self.__tcp_client.read_input_registers(1056, ModbusDataType.INT_32, unit=25) / 10 - power = self.__tcp_client.read_input_registers(1012, ModbusDataType.INT_32, unit=25) * -1 + soc = self.__tcp_client.read_input_registers(1056, ModbusDataType.INT_32, device_id=25) / 10 + power = self.__tcp_client.read_input_registers(1012, ModbusDataType.INT_32, device_id=25) * -1 self.peak_filter.check_values(power) imported, exported = self.sim_counter.sim_count(power) diff --git a/packages/modules/devices/sma/sma_sunny_boy/counter.py b/packages/modules/devices/sma/sma_sunny_boy/counter.py index 5f14524d63..ffbd31fcba 100644 --- a/packages/modules/devices/sma/sma_sunny_boy/counter.py +++ b/packages/modules/devices/sma/sma_sunny_boy/counter.py @@ -35,8 +35,8 @@ def initialize(self) -> None: def update(self): unit = self.component_config.configuration.modbus_id - imp = self.__tcp_client.read_holding_registers(30865, ModbusDataType.UINT_32, unit=unit) - exp = self.__tcp_client.read_holding_registers(30867, ModbusDataType.UINT_32, unit=unit) + imp = self.__tcp_client.read_holding_registers(30865, ModbusDataType.UINT_32, device_id=unit) + exp = self.__tcp_client.read_holding_registers(30867, ModbusDataType.UINT_32, device_id=unit) if imp > 5: power = imp else: diff --git a/packages/modules/devices/sma/sma_sunny_boy/inverter.py b/packages/modules/devices/sma/sma_sunny_boy/inverter.py index 39db80d84a..45a23ef581 100644 --- a/packages/modules/devices/sma/sma_sunny_boy/inverter.py +++ b/packages/modules/devices/sma/sma_sunny_boy/inverter.py @@ -50,39 +50,39 @@ def read(self) -> InverterState: if self.component_config.configuration.version == SmaInverterVersion.default: # AC Wirkleistung über alle Phasen (W) [Pac] - power_total = self.tcp_client.read_holding_registers(30775, ModbusDataType.INT_32, unit=unit) + power_total = self.tcp_client.read_holding_registers(30775, ModbusDataType.INT_32, device_id=unit) # Gesamtertrag (Wh) [E-Total] - energy = self.tcp_client.read_holding_registers(30529, ModbusDataType.UINT_32, unit=unit) + energy = self.tcp_client.read_holding_registers(30529, ModbusDataType.UINT_32, device_id=unit) # Bei Hybrid Wechselrichtern treten Abweichungen auf, die in der Nacht # immer wieder Generatorleistung anzeigen (0-50 Watt). Um dies zu verhindern, schauen wir uns # zunächst an, ob vom DC Teil überhaupt Leistung kommt. Ist dies nicht der Fall, können wir power # gleich auf 0 setzen. # Leistung DC an Eingang 1 und 2 - dc_power = (self.tcp_client.read_holding_registers(30773, ModbusDataType.INT_32, unit=unit) + - self.tcp_client.read_holding_registers(30961, ModbusDataType.INT_32, unit=unit)) + dc_power = (self.tcp_client.read_holding_registers(30773, ModbusDataType.INT_32, device_id=unit) + + self.tcp_client.read_holding_registers(30961, ModbusDataType.INT_32, device_id=unit)) - currents = self.tcp_client.read_holding_registers(30977, [ModbusDataType.INT_32]*3, unit=unit) + currents = self.tcp_client.read_holding_registers(30977, [ModbusDataType.INT_32]*3, device_id=unit) if all(c == self.SMA_INT32_NAN for c in currents): currents = None else: currents = [current / -1000 if current != self.SMA_INT32_NAN else 0 for current in currents] elif self.component_config.configuration.version == SmaInverterVersion.core2: # AC Wirkleistung über alle Phasen (W) [Pac] - power_total = self.tcp_client.read_holding_registers(40084, ModbusDataType.INT_16, unit=unit) * 10 + power_total = self.tcp_client.read_holding_registers(40084, ModbusDataType.INT_16, device_id=unit) * 10 # Gesamtertrag (Wh) [E-Total] SF=2! - energy = self.tcp_client.read_holding_registers(40094, ModbusDataType.UINT_32, unit=unit) * 100 + energy = self.tcp_client.read_holding_registers(40094, ModbusDataType.UINT_32, device_id=unit) * 100 # Power - dc_power = self.tcp_client.read_holding_registers(40101, ModbusDataType.UINT_32, unit=unit) * 100 + dc_power = self.tcp_client.read_holding_registers(40101, ModbusDataType.UINT_32, device_id=unit) * 100 # Phasenstöme - current_L1 = self.tcp_client.read_holding_registers(30977, ModbusDataType.INT_32, unit=unit) * -1 - current_L2 = self.tcp_client.read_holding_registers(30979, ModbusDataType.INT_32, unit=unit) * -1 - current_L3 = self.tcp_client.read_holding_registers(30981, ModbusDataType.INT_32, unit=unit) * -1 + current_L1 = self.tcp_client.read_holding_registers(30977, ModbusDataType.INT_32, device_id=unit) * -1 + current_L2 = self.tcp_client.read_holding_registers(30979, ModbusDataType.INT_32, device_id=unit) * -1 + current_L3 = self.tcp_client.read_holding_registers(30981, ModbusDataType.INT_32, device_id=unit) * -1 currents = [current_L1 / 1000, current_L2 / 1000, current_L3 / 1000] elif self.component_config.configuration.version == SmaInverterVersion.datamanager: # AC Wirkleistung über alle Phasen (W) [Pac] - power_total = self.tcp_client.read_holding_registers(30775, ModbusDataType.INT_32, unit=unit) + power_total = self.tcp_client.read_holding_registers(30775, ModbusDataType.INT_32, device_id=unit) # Total eingespeiste Energie auf allen Außenleitern (Wh) [E-Total] - energy = self.tcp_client.read_holding_registers(30513, ModbusDataType.UINT_64, unit=unit) + energy = self.tcp_client.read_holding_registers(30513, ModbusDataType.UINT_64, device_id=unit) # DC-Power = power_total - Cluster-Controller gibt in Register 30775 immer korrekte Werte aus, # daher ist wie bei SmaInverterVersion.default keine Prüfung auf DC-Leistung notwendig. # Aus kompatibilitätsgründen wird dc_power auf den Wert der AC-Wirkleistung gesetzt. diff --git a/packages/modules/devices/sma/sma_sunny_island/bat.py b/packages/modules/devices/sma/sma_sunny_island/bat.py index 7d866b303d..834565129e 100644 --- a/packages/modules/devices/sma/sma_sunny_island/bat.py +++ b/packages/modules/devices/sma/sma_sunny_island/bat.py @@ -32,10 +32,10 @@ def read(self) -> BatState: unit = self.component_config.configuration.modbus_id with self.__tcp_client: - soc = self.__tcp_client.read_holding_registers(30845, ModbusDataType.INT_32, unit=unit) + soc = self.__tcp_client.read_holding_registers(30845, ModbusDataType.INT_32, device_id=unit) - power = self.__tcp_client.read_holding_registers(30775, ModbusDataType.INT_32, unit=unit) * -1 - imported, exported = self.__tcp_client.read_holding_registers(30595, [ModbusDataType.INT_32]*2, unit=unit) + power = self.__tcp_client.read_holding_registers(30775, ModbusDataType.INT_32, device_id=unit) * -1 + imported, exported = self.__tcp_client.read_holding_registers(30595, [ModbusDataType.INT_32]*2, device_id=unit) imported, exported = self.peak_filter.check_values(power, imported, exported) return BatState( diff --git a/packages/modules/devices/sofar/sofar/bat.py b/packages/modules/devices/sofar/sofar/bat.py index c06c9ec0be..13b02f6924 100644 --- a/packages/modules/devices/sofar/sofar/bat.py +++ b/packages/modules/devices/sofar/sofar/bat.py @@ -32,21 +32,21 @@ def initialize(self) -> None: def update(self) -> None: # 0x900D High 8 bits: the number of battery packs in parallel # Lower 8 bits: the number of battery strings in the battery pack - battery_packs = self.client.read_holding_registers(0x900D, ModbusDataType.UINT_16, unit=self.__modbus_id) >> 8 + battery_packs = self.client.read_holding_registers(0x900D, ModbusDataType.UINT_16, device_id=self.__modbus_id) >> 8 # Power bat1 - bat12: INT_16 in kW accuracy 0,01 power_regs = [0x0606, 0x060D, 0x0614, 0x061B, 0x0622, 0x0629, 0x0630, 0x0637, 0x0646, 0x064D, 0x0654, 0x065B] - power = sum(self.client.read_holding_registers(power_regs[idx], ModbusDataType.INT_16, unit=self.__modbus_id) + power = sum(self.client.read_holding_registers(power_regs[idx], ModbusDataType.INT_16, device_id=self.__modbus_id) for idx in range(battery_packs)) * 10 - soc = self.client.read_holding_registers(0x9012, ModbusDataType.UINT_16, unit=self.__modbus_id) + soc = self.client.read_holding_registers(0x9012, ModbusDataType.UINT_16, device_id=self.__modbus_id) # 0x0696 Bat_charge_total LSB UInt32 0,1 kWh # 0x0697 Bat_charge_total UInt32 0,1 kWh imported = self.client.read_holding_registers( - 0x0696, ModbusDataType.UINT_32, unit=self.__modbus_id) * 100 + 0x0696, ModbusDataType.UINT_32, device_id=self.__modbus_id) * 100 # 0x069A Bat_discharge_total LSB UInt32 0,1 kWh # 0x069B Bat:discharge_total UInt32 0,1 kWh exported = self.client.read_holding_registers( - 0x069A, ModbusDataType.UINT_32, unit=self.__modbus_id) * 100 + 0x069A, ModbusDataType.UINT_32, device_id=self.__modbus_id) * 100 imported, exported = self.peak_filter.check_values(power, imported, exported) bat_state = BatState( diff --git a/packages/modules/devices/sofar/sofar/counter.py b/packages/modules/devices/sofar/sofar/counter.py index bed82dc32c..8ba5810ee6 100644 --- a/packages/modules/devices/sofar/sofar/counter.py +++ b/packages/modules/devices/sofar/sofar/counter.py @@ -32,23 +32,23 @@ def initialize(self) -> None: def update(self): # 0x0485 ActivePower_output_total Int16 in kW accuracy 0,01 discharge + charge - # 0x0488 ActivePower_PCC_total Int16 0,01 kW - power = self.client.read_holding_registers(0x0488, ModbusDataType.INT_16, unit=self.__modbus_id) * -10 + power = self.client.read_holding_registers(0x0488, ModbusDataType.INT_16, device_id=self.__modbus_id) * -10 # 0x0484 Frequency_Grid UInt16 in Hz accuracy 0,01 frequency = self.client.read_holding_registers( - 0x0484, ModbusDataType.UINT_16, unit=self.__modbus_id) / 100 + 0x0484, ModbusDataType.UINT_16, device_id=self.__modbus_id) / 100 try: powers = [ - self.client.read_holding_registers(0x0493, ModbusDataType.INT_16, unit=self.__modbus_id) * -10, - self.client.read_holding_registers(0x049E, ModbusDataType.INT_16, unit=self.__modbus_id) * -10, - self.client.read_holding_registers(0x04A9, ModbusDataType.INT_16, unit=self.__modbus_id) * -10] + self.client.read_holding_registers(0x0493, ModbusDataType.INT_16, device_id=self.__modbus_id) * -10, + self.client.read_holding_registers(0x049E, ModbusDataType.INT_16, device_id=self.__modbus_id) * -10, + self.client.read_holding_registers(0x04A9, ModbusDataType.INT_16, device_id=self.__modbus_id) * -10] except Exception: powers = None # 0x0692 Energy_Selling_Total UInt32 in kwH accuracy 0,01 LSB # 0x0693 Energy_Selling_Total UInt32 in kwH accuracy 0,01 - exported = self.client.read_holding_registers(0x0692, ModbusDataType.UINT_32, unit=self.__modbus_id) * 100 + exported = self.client.read_holding_registers(0x0692, ModbusDataType.UINT_32, device_id=self.__modbus_id) * 100 # 0x068E Energy_Purchase_Total UInt32 in kwH accuracy 0,01 LSB # 0x068F Energy_Purchase_Total UInt32 in kwH accuracy 0,01 - imported = self.client.read_holding_registers(0x068E, ModbusDataType.UINT_32, unit=self.__modbus_id) * 100 + imported = self.client.read_holding_registers(0x068E, ModbusDataType.UINT_32, device_id=self.__modbus_id) * 100 imported, exported = self.peak_filter.check_values(power, imported, exported) counter_state = CounterState( diff --git a/packages/modules/devices/sofar/sofar/inverter.py b/packages/modules/devices/sofar/sofar/inverter.py index 253c066349..9c557be4d4 100644 --- a/packages/modules/devices/sofar/sofar/inverter.py +++ b/packages/modules/devices/sofar/sofar/inverter.py @@ -31,8 +31,8 @@ def initialize(self) -> None: def update(self) -> None: # 0x05C4 Power_PV_Total UINT16 in kW accuracy 0,1 - power = self.client.read_holding_registers(0x05C4, ModbusDataType.UINT_16, unit=self.__modbus_id) * -100 - exported = self.client.read_holding_registers(0x0686, ModbusDataType.UINT_32, unit=self.__modbus_id) * 100 + power = self.client.read_holding_registers(0x05C4, ModbusDataType.UINT_16, device_id=self.__modbus_id) * -100 + exported = self.client.read_holding_registers(0x0686, ModbusDataType.UINT_32, device_id=self.__modbus_id) * 100 _, exported = self.peak_filter.check_values(power, None, exported) inverter_state = InverterState( diff --git a/packages/modules/devices/solakon/solakon_one/bat.py b/packages/modules/devices/solakon/solakon_one/bat.py index 933c0bd339..6a3a52c834 100644 --- a/packages/modules/devices/solakon/solakon_one/bat.py +++ b/packages/modules/devices/solakon/solakon_one/bat.py @@ -34,13 +34,13 @@ def update(self) -> None: # AC Leistung am Stecker, Batterie aus dem Netz aufladen hat positive Werte, # Leistung aus der Batterie und/oder aus PV ins Netz abgeben hat negative Werte - power = self.client.read_holding_registers(39134, ModbusDataType.INT_32, unit=unit) * -1 + power = self.client.read_holding_registers(39134, ModbusDataType.INT_32, device_id=unit) * -1 # SoC Ladezustand der Batterie in % - soc = self.client.read_holding_registers(39424, ModbusDataType.INT_16, unit=unit) + soc = self.client.read_holding_registers(39424, ModbusDataType.INT_16, device_id=unit) # gesamte DC Ladung der Batterie in Wh - imported = self.client.read_holding_registers(39605, ModbusDataType.UINT_32, unit=unit) * 10 + imported = self.client.read_holding_registers(39605, ModbusDataType.UINT_32, device_id=unit) * 10 # gesamte DC Entladung der Batterie in Wh - exported = self.client.read_holding_registers(39609, ModbusDataType.UINT_32, unit=unit) * 10 + exported = self.client.read_holding_registers(39609, ModbusDataType.UINT_32, device_id=unit) * 10 imported, exported = self.peak_filter.check_values(power, imported, exported) bat_state = BatState( diff --git a/packages/modules/devices/solakon/solakon_one/inverter.py b/packages/modules/devices/solakon/solakon_one/inverter.py index 035fc35e52..0a9c66fdf2 100644 --- a/packages/modules/devices/solakon/solakon_one/inverter.py +++ b/packages/modules/devices/solakon/solakon_one/inverter.py @@ -30,9 +30,9 @@ def initialize(self) -> None: def update(self) -> None: unit = self.component_config.configuration.modbus_id # Gesamte DC PV Leistung aller vier MPPT in W - power = self.client.read_holding_registers(39118, ModbusDataType.INT_32, unit=unit) * -1 + power = self.client.read_holding_registers(39118, ModbusDataType.INT_32, device_id=unit) * -1 # Gesamte DC PV Produktion in Wh - exported = self.client.read_holding_registers(39601, ModbusDataType.UINT_32, unit=unit) * 10 + exported = self.client.read_holding_registers(39601, ModbusDataType.UINT_32, device_id=unit) * 10 _, exported = self.peak_filter.check_values(power, None, exported) inverter_state = InverterState( diff --git a/packages/modules/devices/solaredge/solaredge/bat.py b/packages/modules/devices/solaredge/solaredge/bat.py index ec88b4fe96..42db08439e 100644 --- a/packages/modules/devices/solaredge/solaredge/bat.py +++ b/packages/modules/devices/solaredge/solaredge/bat.py @@ -4,7 +4,7 @@ from typing import Any, TypedDict, Dict, Union, Optional, Tuple -from pymodbus.constants import Endian +from modules.common.pymodbus_compat import Endian import pymodbus @@ -99,10 +99,10 @@ def get_values(self) -> Tuple[float, float]: # Read SoC and Power from the appropriate registers soc = self.__tcp_client.read_holding_registers( - soc_reg, ModbusDataType.FLOAT_32, wordorder=Endian.Little, unit=unit + soc_reg, ModbusDataType.FLOAT_32, wordorder=Endian.Little, device_id=unit ) power = self.__tcp_client.read_holding_registers( - power_reg, ModbusDataType.FLOAT_32, wordorder=Endian.Little, unit=unit + power_reg, ModbusDataType.FLOAT_32, wordorder=Endian.Little, device_id=unit ) # Handle unsupported case @@ -203,7 +203,7 @@ def _read_registers(self, register_names: list, unit: int) -> Dict[str, Union[in address, data_type = self.REGISTERS[key] try: values[key] = self.__tcp_client.read_holding_registers( - address, data_type, wordorder=Endian.Little, unit=unit + address, data_type, wordorder=Endian.Little, device_id=unit ) except pymodbus.exceptions.ModbusException as e: log.error(f"Failed to read register {key} at address {address}: {e}") @@ -217,7 +217,7 @@ def _write_registers(self, values_to_write: Dict[str, Union[int, float]], unit: for key, value in values_to_write.items(): address, data_type = self.REGISTERS[key] try: - self.__tcp_client.write_register(address, value, data_type, wordorder=Endian.Little, unit=unit) + self.__tcp_client.write_register(address, value, data_type, wordorder=Endian.Little, device_id=unit) log.debug(f"Neuer Wert {value} in Register {address} geschrieben.") except pymodbus.exceptions.ModbusException as e: log.error(f"Failed to write register {key} at address {address}: {e}") diff --git a/packages/modules/devices/solaredge/solaredge/counter.py b/packages/modules/devices/solaredge/solaredge/counter.py index 8ae83e2e33..5a6061199e 100644 --- a/packages/modules/devices/solaredge/solaredge/counter.py +++ b/packages/modules/devices/solaredge/solaredge/counter.py @@ -57,7 +57,7 @@ def update(self): (self.registers.imp_exp_scale, ModbusDataType.INT_16), ) resp = self.__tcp_client.read_holding_registers_bulk( - self.registers.currents, 52, mapping=reg_mapping, unit=self.component_config.configuration.modbus_id) + self.registers.currents, 52, mapping=reg_mapping, device_id=self.component_config.configuration.modbus_id) imported = scale_registers(resp[self.registers.imported], resp[self.registers.imp_exp_scale]) exported = scale_registers(resp[self.registers.exported], resp[self.registers.imp_exp_scale]) diff --git a/packages/modules/devices/solaredge/solaredge/external_inverter.py b/packages/modules/devices/solaredge/solaredge/external_inverter.py index 3fd7deafc9..69394b1f2d 100644 --- a/packages/modules/devices/solaredge/solaredge/external_inverter.py +++ b/packages/modules/devices/solaredge/solaredge/external_inverter.py @@ -54,7 +54,7 @@ def read_state(self) -> InverterState: (self.registers.imp_exp_scale, ModbusDataType.INT_16), ) resp = self.__tcp_client.read_holding_registers_bulk( - self.registers.currents, 52, mapping=reg_mapping, unit=self.component_config.configuration.modbus_id) + self.registers.currents, 52, mapping=reg_mapping, device_id=self.component_config.configuration.modbus_id) factor = self.component_config.configuration.factor diff --git a/packages/modules/devices/solaredge/solaredge/inverter.py b/packages/modules/devices/solaredge/solaredge/inverter.py index 45170cbc70..acb586cc98 100644 --- a/packages/modules/devices/solaredge/solaredge/inverter.py +++ b/packages/modules/devices/solaredge/solaredge/inverter.py @@ -62,7 +62,7 @@ def update(self) -> None: def read_state(self): resp = self.__tcp_client.read_holding_registers_bulk( - Register.CURRENTS, 30, mapping=self.REG_MAPPING, unit=self.component_config.configuration.modbus_id) + Register.CURRENTS, 30, mapping=self.REG_MAPPING, device_id=self.component_config.configuration.modbus_id) power = scale_registers(resp[Register.POWER], resp[Register.POWER_SCALE]) * -1 self.peak_filter.check_values(power) diff --git a/packages/modules/devices/solaredge/solaredge/meter.py b/packages/modules/devices/solaredge/solaredge/meter.py index cd127ddce0..26fdb50dad 100644 --- a/packages/modules/devices/solaredge/solaredge/meter.py +++ b/packages/modules/devices/solaredge/solaredge/meter.py @@ -31,7 +31,7 @@ def __init__(self, internal_meter_id: int = 1, synergy_units: int = 1): # 40205: AC Frequency Scale Factor self.frequency = 40204 self.frequency_scale = 40205 - # 40222/40223/40224: Power factor by phase (unit=%) + # 40222/40223/40224: Power factor by phase (device_id=%) # 40225: AC Power Factor Scale Factor self.power_factors = 40222 self.power_factors_scale = 40225 @@ -96,14 +96,14 @@ def _get_synergy_units(component_config: Union[SolaredgeBatSetup, SolaredgeExternalInverterSetup], client) -> int: if client.read_holding_registers(40121, ModbusDataType.UINT_16, - unit=component_config.configuration.modbus_id + device_id=component_config.configuration.modbus_id ) == synergy_unit_identifier: # Snyergy-Units vom Haupt-WR des angeschlossenen Meters ermitteln. Es kann mehrere Haupt-WR mit # unterschiedlichen Modbus-IDs im Verbund geben. log.debug("Synergy Units supported") synergy_units = int(client.read_holding_registers( 40129, ModbusDataType.UINT_16, - unit=component_config.configuration.modbus_id)) or 1 + device_id=component_config.configuration.modbus_id)) or 1 log.debug( f"Synergy Units detected for Modbus ID {component_config.configuration.modbus_id}: {synergy_units}") else: diff --git a/packages/modules/devices/solarmax/solarmax/bat.py b/packages/modules/devices/solarmax/solarmax/bat.py index 0e39869f40..f15b8ddeda 100644 --- a/packages/modules/devices/solarmax/solarmax/bat.py +++ b/packages/modules/devices/solarmax/solarmax/bat.py @@ -2,7 +2,7 @@ import logging from typing import TypedDict, Any, Optional -from pymodbus.constants import Endian +from modules.common.pymodbus_compat import Endian from modules.common.abstract_device import AbstractBat from modules.common.component_state import BatState from modules.common.component_type import ComponentDescriptor @@ -37,8 +37,8 @@ def initialize(self) -> None: def update(self) -> None: unit = self.component_config.configuration.modbus_id - power = self.client.read_input_registers(114, ModbusDataType.INT_32, unit=unit, wordorder=Endian.Little) - soc = self.client.read_input_registers(122, ModbusDataType.INT_16, unit=unit) + power = self.client.read_input_registers(114, ModbusDataType.INT_32, device_id=unit, wordorder=Endian.Little) + soc = self.client.read_input_registers(122, ModbusDataType.INT_16, device_id=unit) self.peak_filter.check_values(power) imported, exported = self.sim_counter.sim_count(power) @@ -57,24 +57,24 @@ def set_power_limit(self, power_limit: Optional[int]) -> None: if power_limit is None: log.debug("Keine Batteriesteuerung, Selbstregelung durch Wechselrichter") if self.last_mode is not None: - self.client.write_register(142, 0, data_type=ModbusDataType.INT_16, unit=unit) + self.client.write_register(142, 0, data_type=ModbusDataType.INT_16, device_id=unit) self.last_mode = None elif power_limit >= 0: # Solarmax kann nicht aktiv laden log.debug("Aktive Batteriesteuerung. Batterie wird auf Stop gesetzt und nicht entladen") - self.client.write_register(140, 0, data_type=ModbusDataType.INT_16, unit=unit) - self.client.write_register(141, 0, data_type=ModbusDataType.INT_16, unit=unit) - self.client.write_register(142, 1, data_type=ModbusDataType.INT_16, unit=unit) + self.client.write_register(140, 0, data_type=ModbusDataType.INT_16, device_id=unit) + self.client.write_register(141, 0, data_type=ModbusDataType.INT_16, device_id=unit) + self.client.write_register(142, 1, data_type=ModbusDataType.INT_16, device_id=unit) self.last_mode = 'stop' elif power_limit < 0: log.debug(f"Aktive Batteriesteuerung. Batterie wird mit {power_limit} W entladen für den Hausverbrauch") - self.client.write_register(142, 1, data_type=ModbusDataType.INT_16, unit=unit) + self.client.write_register(142, 1, data_type=ModbusDataType.INT_16, device_id=unit) self.last_mode = 'discharge' # Die maximale Entladeleistung begrenzen auf 5000W, maximaler Wertebereich Modbusregister. power_value = int(min(abs(power_limit), 7000)) log.debug(f"Aktive Batteriesteuerung. Batterie wird mit {power_value} W entladen für den Hausverbrauch") - self.client.write_register(140, power_value, data_type=ModbusDataType.INT_16, unit=unit) - self.client.write_register(141, power_value, data_type=ModbusDataType.INT_16, unit=unit) + self.client.write_register(140, power_value, data_type=ModbusDataType.INT_16, device_id=unit) + self.client.write_register(141, power_value, data_type=ModbusDataType.INT_16, device_id=unit) def power_limit_controllable(self) -> bool: return self.component_config.configuration.power_limit_controllable diff --git a/packages/modules/devices/solarmax/solarmax/counter_maxstorage.py b/packages/modules/devices/solarmax/solarmax/counter_maxstorage.py index 58805fef26..063d844f56 100644 --- a/packages/modules/devices/solarmax/solarmax/counter_maxstorage.py +++ b/packages/modules/devices/solarmax/solarmax/counter_maxstorage.py @@ -1,7 +1,7 @@ #!/usr/bin/env python3 from typing import TypedDict, Any -from pymodbus.constants import Endian +from modules.common.pymodbus_compat import Endian from modules.common.abstract_device import AbstractCounter from modules.common.component_state import CounterState from modules.common.component_type import ComponentDescriptor @@ -36,7 +36,7 @@ def initialize(self) -> None: def update(self) -> None: unit = self.component_config.configuration.modbus_id - power = self.client.read_input_registers(118, ModbusDataType.INT_32, unit=unit, wordorder=Endian.Little) * -1 + power = self.client.read_input_registers(118, ModbusDataType.INT_32, device_id=unit, wordorder=Endian.Little) * -1 self.peak_filter.check_values(power) imported, exported = self.sim_counter.sim_count(power) diff --git a/packages/modules/devices/solarmax/solarmax/inverter.py b/packages/modules/devices/solarmax/solarmax/inverter.py index a77c2766fe..d7567521d9 100644 --- a/packages/modules/devices/solarmax/solarmax/inverter.py +++ b/packages/modules/devices/solarmax/solarmax/inverter.py @@ -35,7 +35,7 @@ def initialize(self) -> None: def update(self) -> None: power = self.client.read_holding_registers(4151, ModbusDataType.UINT_32, - unit=self.component_config.configuration.modbus_id) * -1 + device_id=self.component_config.configuration.modbus_id) * -1 power = power / 10 self.peak_filter.check_values(power) _, exported = self.sim_counter.sim_count(power) diff --git a/packages/modules/devices/solarmax/solarmax/inverter_maxstorage.py b/packages/modules/devices/solarmax/solarmax/inverter_maxstorage.py index d380ade120..b38cf26c2c 100644 --- a/packages/modules/devices/solarmax/solarmax/inverter_maxstorage.py +++ b/packages/modules/devices/solarmax/solarmax/inverter_maxstorage.py @@ -1,7 +1,7 @@ #!/usr/bin/env python3 from typing import TypedDict, Any -from pymodbus.constants import Endian +from modules.common.pymodbus_compat import Endian from modules.common.abstract_device import AbstractInverter from modules.common.component_state import InverterState from modules.common.component_type import ComponentDescriptor @@ -36,7 +36,7 @@ def initialize(self) -> None: def update(self) -> None: unit = self.component_config.configuration.modbus_id - power = self.client.read_input_registers(120, ModbusDataType.INT_32, unit=unit, wordorder=Endian.Little) * -1 + power = self.client.read_input_registers(120, ModbusDataType.INT_32, device_id=unit, wordorder=Endian.Little) * -1 self.peak_filter.check_values(power) _, exported = self.sim_counter.sim_count(power) diff --git a/packages/modules/devices/solax/solax/bat.py b/packages/modules/devices/solax/solax/bat.py index c1cd62a371..100465aaf4 100644 --- a/packages/modules/devices/solax/solax/bat.py +++ b/packages/modules/devices/solax/solax/bat.py @@ -36,8 +36,8 @@ def update(self) -> None: unit = self.device_config.configuration.modbus_id # kein Speicher für Versionen G2 und G4 - power = self.__tcp_client.read_input_registers(0x0016, ModbusDataType.INT_16, unit=unit) - soc = self.__tcp_client.read_input_registers(0x001C, ModbusDataType.UINT_16, unit=unit) + power = self.__tcp_client.read_input_registers(0x0016, ModbusDataType.INT_16, device_id=unit) + soc = self.__tcp_client.read_input_registers(0x001C, ModbusDataType.UINT_16, device_id=unit) self.peak_filter.check_values(power) imported, exported = self.sim_counter.sim_count(power) bat_state = BatState( diff --git a/packages/modules/devices/solax/solax/counter.py b/packages/modules/devices/solax/solax/counter.py index f42f6d2fc5..7ce3d1c163 100644 --- a/packages/modules/devices/solax/solax/counter.py +++ b/packages/modules/devices/solax/solax/counter.py @@ -1,6 +1,6 @@ #!/usr/bin/env python3 from typing import Any, TypedDict -from pymodbus.constants import Endian +from modules.common.pymodbus_compat import Endian from modules.common import modbus from modules.common.abstract_device import AbstractCounter @@ -37,32 +37,32 @@ def update(self): if SolaxVersion(self.device_config.configuration.version) == SolaxVersion.G2: power = self.__tcp_client.read_input_registers( - 0x043B, ModbusDataType.INT_32, wordorder=Endian.Little, unit=unit) * -1 - frequency = self.__tcp_client.read_input_registers(0x0407, ModbusDataType.UINT_16, unit=unit) / 100 + 0x043B, ModbusDataType.INT_32, wordorder=Endian.Little, device_id=unit) * -1 + frequency = self.__tcp_client.read_input_registers(0x0407, ModbusDataType.UINT_16, device_id=unit) / 100 powers = [-value for value in self.__tcp_client.read_input_registers( - 0x0704, [ModbusDataType.INT_32] * 3, wordorder=Endian.Little, unit=unit)] + 0x0704, [ModbusDataType.INT_32] * 3, wordorder=Endian.Little, device_id=unit)] exported, imported = [value * 10 for value in self.__tcp_client.read_input_registers( - 0x043D, [ModbusDataType.UINT_32] * 2, wordorder=Endian.Little, unit=unit)] + 0x043D, [ModbusDataType.UINT_32] * 2, wordorder=Endian.Little, device_id=unit)] elif SolaxVersion(self.device_config.configuration.version) == SolaxVersion.G3: power = self.__tcp_client.read_input_registers( - 0x0046, ModbusDataType.INT_32, wordorder=Endian.Little, unit=unit) * -1 - frequency = self.__tcp_client.read_input_registers(0x0007, ModbusDataType.UINT_16, unit=unit) / 100 + 0x0046, ModbusDataType.INT_32, wordorder=Endian.Little, device_id=unit) * -1 + frequency = self.__tcp_client.read_input_registers(0x0007, ModbusDataType.UINT_16, device_id=unit) / 100 try: powers = [-value for value in self.__tcp_client.read_input_registers( - 0x0082, [ModbusDataType.INT_32] * 3, wordorder=Endian.Little, unit=unit)] + 0x0082, [ModbusDataType.INT_32] * 3, wordorder=Endian.Little, device_id=unit)] except Exception: powers = None exported, imported = [value * 10 for value in self.__tcp_client.read_input_registers( - 0x0048, [ModbusDataType.UINT_32] * 2, wordorder=Endian.Little, unit=unit)] + 0x0048, [ModbusDataType.UINT_32] * 2, wordorder=Endian.Little, device_id=unit)] else: power = self.__tcp_client.read_input_registers( - 0x0409, ModbusDataType.INT_32, wordorder=Endian.Little, unit=unit) * -1 - frequency = self.__tcp_client.read_input_registers(0x0406, ModbusDataType.UINT_16, unit=unit) / 100 + 0x0409, ModbusDataType.INT_32, wordorder=Endian.Little, device_id=unit) * -1 + frequency = self.__tcp_client.read_input_registers(0x0406, ModbusDataType.UINT_16, device_id=unit) / 100 powers = None exported, imported = [value * 100 for value in self.__tcp_client.read_input_registers( - 0x042F, [ModbusDataType.UINT_32] * 2, wordorder=Endian.Little, unit=unit)] + 0x042F, [ModbusDataType.UINT_32] * 2, wordorder=Endian.Little, device_id=unit)] imported, exported = self.peak_filter.check_values(power, imported, exported) counter_state = CounterState( imported=imported, diff --git a/packages/modules/devices/solax/solax/inverter.py b/packages/modules/devices/solax/solax/inverter.py index b84abce03c..5b08e0a56c 100644 --- a/packages/modules/devices/solax/solax/inverter.py +++ b/packages/modules/devices/solax/solax/inverter.py @@ -1,6 +1,6 @@ #!/usr/bin/env python3 from typing import Any, TypedDict -from pymodbus.constants import Endian +from modules.common.pymodbus_compat import Endian from modules.common import modbus from modules.common.abstract_device import AbstractInverter @@ -36,19 +36,19 @@ def update(self) -> None: unit = self.device_config.configuration.modbus_id if SolaxVersion(self.device_config.configuration.version) == SolaxVersion.G2: - power = self.__tcp_client.read_input_registers(0x0413, ModbusDataType.UINT_16, unit=unit) * -1 + power = self.__tcp_client.read_input_registers(0x0413, ModbusDataType.UINT_16, device_id=unit) * -1 exported = self.__tcp_client.read_input_registers( - 0x0423, ModbusDataType.UINT_32, wordorder=Endian.Little, unit=unit) * 100 + 0x0423, ModbusDataType.UINT_32, wordorder=Endian.Little, device_id=unit) * 100 elif SolaxVersion(self.device_config.configuration.version) == SolaxVersion.G3: - power_temp = self.__tcp_client.read_input_registers(0x000A, [ModbusDataType.UINT_16] * 2, unit=unit) + power_temp = self.__tcp_client.read_input_registers(0x000A, [ModbusDataType.UINT_16] * 2, device_id=unit) power = sum(power_temp) * -1 exported = self.__tcp_client.read_input_registers( - 0x0052, ModbusDataType.UINT_32, wordorder=Endian.Little, unit=unit) * 100 + 0x0052, ModbusDataType.UINT_32, wordorder=Endian.Little, device_id=unit) * 100 else: - power_temp = self.__tcp_client.read_input_registers(0x0410, [ModbusDataType.UINT_16] * 2, unit=unit) + power_temp = self.__tcp_client.read_input_registers(0x0410, [ModbusDataType.UINT_16] * 2, device_id=unit) power = sum(power_temp) * -1 exported = self.__tcp_client.read_input_registers( - 0x042B, ModbusDataType.UINT_32, wordorder=Endian.Little, unit=unit) * 100 + 0x042B, ModbusDataType.UINT_32, wordorder=Endian.Little, device_id=unit) * 100 _, exported = self.peak_filter.check_values(power, None, exported) inverter_state = InverterState( diff --git a/packages/modules/devices/solis/solis/bat.py b/packages/modules/devices/solis/solis/bat.py index 490fc6a8f5..5229a634dd 100644 --- a/packages/modules/devices/solis/solis/bat.py +++ b/packages/modules/devices/solis/solis/bat.py @@ -33,12 +33,12 @@ def initialize(self) -> None: def update(self) -> None: unit = self.component_config.configuration.modbus_id - power = self.client.read_input_registers(33149, ModbusDataType.INT_32, unit=unit) - soc = self.client.read_input_registers(33139, ModbusDataType.UINT_16, unit=unit) + power = self.client.read_input_registers(33149, ModbusDataType.INT_32, device_id=unit) + soc = self.client.read_input_registers(33139, ModbusDataType.UINT_16, device_id=unit) # Geladen in kWh - imported = self.client.read_input_registers(33161, ModbusDataType.UINT_32, unit=unit) * 1000 + imported = self.client.read_input_registers(33161, ModbusDataType.UINT_32, device_id=unit) * 1000 # Entladen in kWh - exported = self.client.read_input_registers(33165, ModbusDataType.UINT_32, unit=unit) * 1000 + exported = self.client.read_input_registers(33165, ModbusDataType.UINT_32, device_id=unit) * 1000 imported, exported = self.peak_filter.check_values(power, imported, exported) bat_state = BatState( diff --git a/packages/modules/devices/solis/solis/counter.py b/packages/modules/devices/solis/solis/counter.py index e5a17bf559..cce9b6942c 100644 --- a/packages/modules/devices/solis/solis/counter.py +++ b/packages/modules/devices/solis/solis/counter.py @@ -37,11 +37,11 @@ def update(self): if self.version == SolisVersion.inverter: register_offset = -1 - power = self.client.read_input_registers(3263 + register_offset, ModbusDataType.INT_32, unit=unit) * -1 - powers = self.client.read_input_registers(3257 + register_offset, [ModbusDataType.INT_32]*3, unit=unit) - frequency = self.client.read_input_registers(3282 + register_offset, ModbusDataType.UINT_16, unit=unit) / 100 - imported = self.client.read_input_registers(3283 + register_offset, ModbusDataType.UINT_32, unit=unit) * 10 - exported = self.client.read_input_registers(3285 + register_offset, ModbusDataType.UINT_32, unit=unit) * 10 + power = self.client.read_input_registers(3263 + register_offset, ModbusDataType.INT_32, device_id=unit) * -1 + powers = self.client.read_input_registers(3257 + register_offset, [ModbusDataType.INT_32]*3, device_id=unit) + frequency = self.client.read_input_registers(3282 + register_offset, ModbusDataType.UINT_16, device_id=unit) / 100 + imported = self.client.read_input_registers(3283 + register_offset, ModbusDataType.UINT_32, device_id=unit) * 10 + exported = self.client.read_input_registers(3285 + register_offset, ModbusDataType.UINT_32, device_id=unit) * 10 imported, exported = self.peak_filter.check_values(power, imported, exported) counter_state = CounterState( diff --git a/packages/modules/devices/solis/solis/inverter.py b/packages/modules/devices/solis/solis/inverter.py index 749829a57f..0d95234353 100644 --- a/packages/modules/devices/solis/solis/inverter.py +++ b/packages/modules/devices/solis/solis/inverter.py @@ -33,11 +33,11 @@ def update(self) -> None: unit = self.component_config.configuration.modbus_id if self.version == SolisVersion.inverter: - power = self.client.read_input_registers(3004, ModbusDataType.UINT_32, unit=unit) * -1 - exported = self.client.read_input_registers(3008, ModbusDataType.UINT_32, unit=unit) * 1000 + power = self.client.read_input_registers(3004, ModbusDataType.UINT_32, device_id=unit) * -1 + exported = self.client.read_input_registers(3008, ModbusDataType.UINT_32, device_id=unit) * 1000 elif self.version == SolisVersion.hybrid: - power = self.client.read_input_registers(33057, ModbusDataType.UINT_32, unit=unit) * -1 - exported = self.client.read_input_registers(33029, ModbusDataType.UINT_32, unit=unit) * 1000 + power = self.client.read_input_registers(33057, ModbusDataType.UINT_32, device_id=unit) * -1 + exported = self.client.read_input_registers(33029, ModbusDataType.UINT_32, device_id=unit) * 1000 _, exported = self.peak_filter.check_values(power, None, exported) inverter_state = InverterState( diff --git a/packages/modules/devices/studer/studer/bat.py b/packages/modules/devices/studer/studer/bat.py index a49cf4e1a9..0bf9f5ccce 100644 --- a/packages/modules/devices/studer/studer/bat.py +++ b/packages/modules/devices/studer/studer/bat.py @@ -32,10 +32,10 @@ def update(self) -> None: unit = self.component_config.configuration.modbus_id with self.__tcp_client: - power = self.__tcp_client.read_input_registers(6, ModbusDataType.FLOAT_32, unit=unit) - imported = self.__tcp_client.read_input_registers(14, ModbusDataType.FLOAT_32, unit=unit) * 48 - exported = self.__tcp_client.read_input_registers(16, ModbusDataType.FLOAT_32, unit=unit) * 48 - soc = self.__tcp_client.read_input_registers(4, ModbusDataType.FLOAT_32, unit=unit) + power = self.__tcp_client.read_input_registers(6, ModbusDataType.FLOAT_32, device_id=unit) + imported = self.__tcp_client.read_input_registers(14, ModbusDataType.FLOAT_32, device_id=unit) * 48 + exported = self.__tcp_client.read_input_registers(16, ModbusDataType.FLOAT_32, device_id=unit) * 48 + soc = self.__tcp_client.read_input_registers(4, ModbusDataType.FLOAT_32, device_id=unit) imported, exported = self.peak_filter.check_values(power, imported, exported) bat_state = BatState( diff --git a/packages/modules/devices/studer/studer/inverter.py b/packages/modules/devices/studer/studer/inverter.py index 131b9f0a97..fa0699ff45 100644 --- a/packages/modules/devices/studer/studer/inverter.py +++ b/packages/modules/devices/studer/studer/inverter.py @@ -43,7 +43,7 @@ def update(self) -> None: power = 0 for i in range(1, vc_count+1): mb_unit_dev = mb_unit+i - power += self.__tcp_client.read_input_registers(mb_register, ModbusDataType.FLOAT_32, unit=mb_unit_dev) + power += self.__tcp_client.read_input_registers(mb_register, ModbusDataType.FLOAT_32, device_id=mb_unit_dev) power = power * -1000 if vc_type == 'VS': @@ -54,7 +54,7 @@ def update(self) -> None: for i in range(1, vc_count + 1): mb_unit_dev = mb_unit + i exported += self.__tcp_client.read_input_registers(mb_register, ModbusDataType.FLOAT_32, - unit=mb_unit_dev) + device_id=mb_unit_dev) exported = exported * 1000000 _, exported = self.peak_filter.check_values(power, None, exported) diff --git a/packages/modules/devices/sungrow/sungrow_ihm/bat.py b/packages/modules/devices/sungrow/sungrow_ihm/bat.py index 2aa86da15b..85f9196efa 100644 --- a/packages/modules/devices/sungrow/sungrow_ihm/bat.py +++ b/packages/modules/devices/sungrow/sungrow_ihm/bat.py @@ -37,10 +37,10 @@ def initialize(self) -> None: def update(self) -> None: unit = self.device_config.configuration.modbus_id - soc = int(self.__tcp_client.read_input_registers(8162, ModbusDataType.UINT_16, unit=unit) / 10) + soc = int(self.__tcp_client.read_input_registers(8162, ModbusDataType.UINT_16, device_id=unit) / 10) bat_power = self.__tcp_client.read_input_registers(8160, ModbusDataType.INT_32, - wordorder=Endian.Little, unit=unit) * -10 + wordorder=Endian.Little, device_id=unit) * -10 self.peak_filter.check_values(bat_power) imported, exported = self.sim_counter.sim_count(bat_power) @@ -59,35 +59,35 @@ def set_power_limit(self, power_limit: Optional[int]) -> None: if power_limit is None: log.debug("Keine Batteriesteuerung, Selbstregelung durch Wechselrichter") if self.last_mode is not None: - self.__tcp_client.write_register(8023, 1, data_type=ModbusDataType.UINT_16, unit=unit) - self.__tcp_client.write_register(8024, 0xCC, data_type=ModbusDataType.UINT_16, unit=unit) + self.__tcp_client.write_register(8023, 1, data_type=ModbusDataType.UINT_16, device_id=unit) + self.__tcp_client.write_register(8024, 0xCC, data_type=ModbusDataType.UINT_16, device_id=unit) self.last_mode = None elif power_limit == 0: log.debug("Aktive Batteriesteuerung. Batterie wird auf Stop gesetzt und nicht entladen") if self.last_mode != 'stop': - self.__tcp_client.write_register(8023, 5, data_type=ModbusDataType.UINT_16, unit=unit) - self.__tcp_client.write_register(8024, 0xCC, data_type=ModbusDataType.UINT_16, unit=unit) + self.__tcp_client.write_register(8023, 5, data_type=ModbusDataType.UINT_16, device_id=unit) + self.__tcp_client.write_register(8024, 0xCC, data_type=ModbusDataType.UINT_16, device_id=unit) self.last_mode = 'stop' elif power_limit < 0: log.debug(f"Aktive Batteriesteuerung. Batterie wird mit {power_limit} W entladen für den Hausverbrauch") if self.last_mode != 'discharge': - self.__tcp_client.write_register(8023, 5, data_type=ModbusDataType.UINT_16, unit=unit) - self.__tcp_client.write_register(8024, 0xBB, data_type=ModbusDataType.UINT_16, unit=unit) + self.__tcp_client.write_register(8023, 5, data_type=ModbusDataType.UINT_16, device_id=unit) + self.__tcp_client.write_register(8024, 0xBB, data_type=ModbusDataType.UINT_16, device_id=unit) self.last_mode = 'discharge' power_value = int(power_limit / 100) log.debug(f"Aktive Batteriesteuerung. Batterie wird mit {power_limit} W entladen für den Hausverbrauch") self.__tcp_client.write_register(8025, power_value, data_type=ModbusDataType.UINT_32, - wordorder=Endian.Little, unit=unit) + wordorder=Endian.Little, device_id=unit) elif power_limit > 0: log.debug(f"Aktive Batteriesteuerung. Batterie wird mit {power_limit} W geladen") if self.last_mode != 'charge': - self.__tcp_client.write_register(8023, 5, data_type=ModbusDataType.UINT_16, unit=unit) - self.__tcp_client.write_register(8025, 0xAA, data_type=ModbusDataType.UINT_16, unit=unit) + self.__tcp_client.write_register(8023, 5, data_type=ModbusDataType.UINT_16, device_id=unit) + self.__tcp_client.write_register(8025, 0xAA, data_type=ModbusDataType.UINT_16, device_id=unit) self.last_mode = 'charge' power_value = int(power_limit / 100) log.debug(f"Aktive Batteriesteuerung. Batterie wird mit {power_limit} W geladen") self.__tcp_client.write_register(8025, power_value, data_type=ModbusDataType.UINT_32, - wordorder=Endian.Little, unit=unit) + wordorder=Endian.Little, device_id=unit) def power_limit_controllable(self) -> bool: return True diff --git a/packages/modules/devices/sungrow/sungrow_ihm/counter.py b/packages/modules/devices/sungrow/sungrow_ihm/counter.py index 7a2289dade..2d5e747559 100644 --- a/packages/modules/devices/sungrow/sungrow_ihm/counter.py +++ b/packages/modules/devices/sungrow/sungrow_ihm/counter.py @@ -34,15 +34,15 @@ def initialize(self) -> None: def update(self): unit = self.device_config.configuration.modbus_id power = self.__tcp_client.read_input_registers(8156, ModbusDataType.INT_32, - wordorder=Endian.Little, unit=unit) * -10 + wordorder=Endian.Little, device_id=unit) * -10 powers = self.__tcp_client.read_input_registers(8558, [ModbusDataType.UINT_32] * 3, - wordorder=Endian.Little, unit=unit) + wordorder=Endian.Little, device_id=unit) - frequency = self.__tcp_client.read_input_registers(8557, ModbusDataType.UINT_16, unit=unit) / 10 + frequency = self.__tcp_client.read_input_registers(8557, ModbusDataType.UINT_16, device_id=unit) / 10 voltages = self.__tcp_client.read_input_registers(8554, [ModbusDataType.UINT_16] * 3, - wordorder=Endian.Little, unit=unit) + wordorder=Endian.Little, device_id=unit) voltages = [value / 10 for value in voltages] diff --git a/packages/modules/devices/sungrow/sungrow_ihm/inverter.py b/packages/modules/devices/sungrow/sungrow_ihm/inverter.py index 2b12ad5cd3..c898b4507d 100644 --- a/packages/modules/devices/sungrow/sungrow_ihm/inverter.py +++ b/packages/modules/devices/sungrow/sungrow_ihm/inverter.py @@ -35,7 +35,7 @@ def update(self) -> float: unit = self.device_config.configuration.modbus_id power = self.__tcp_client.read_input_registers(8154, ModbusDataType.INT_32, - wordorder=Endian.Little, unit=unit) * -10 + wordorder=Endian.Little, device_id=unit) * -10 self.peak_filter.check_values(power) imported, exported = self.sim_counter.sim_count(power) diff --git a/packages/modules/devices/sungrow/sungrow_micro/inverter.py b/packages/modules/devices/sungrow/sungrow_micro/inverter.py index b189c73f7a..363b40e704 100644 --- a/packages/modules/devices/sungrow/sungrow_micro/inverter.py +++ b/packages/modules/devices/sungrow/sungrow_micro/inverter.py @@ -35,7 +35,7 @@ def update(self) -> float: unit = self.device_config.configuration.modbus_id power = self.__tcp_client.read_input_registers(32213, ModbusDataType.UINT_32, - wordorder=Endian.Little, unit=unit) * -1 + wordorder=Endian.Little, device_id=unit) * -1 self.peak_filter.check_values(power) imported, exported = self.sim_counter.sim_count(power) diff --git a/packages/modules/devices/sungrow/sungrow_sg/counter.py b/packages/modules/devices/sungrow/sungrow_sg/counter.py index e03c581109..4dc838d50a 100644 --- a/packages/modules/devices/sungrow/sungrow_sg/counter.py +++ b/packages/modules/devices/sungrow/sungrow_sg/counter.py @@ -37,21 +37,21 @@ def initialize(self) -> None: def update(self): unit = self.device_config.configuration.modbus_id power = self.__tcp_client.read_input_registers(5082, ModbusDataType.INT_32, - wordorder=Endian.Little, unit=unit) + wordorder=Endian.Little, device_id=unit) try: powers = self.__tcp_client.read_input_registers(5084, [ModbusDataType.INT_32] * 3, - wordorder=Endian.Little, unit=unit) + wordorder=Endian.Little, device_id=unit) except Exception: powers = None self.fault_state.no_error(self.fault_text) - frequency = self.__tcp_client.read_input_registers(5035, ModbusDataType.UINT_16, unit=unit) / 10 + frequency = self.__tcp_client.read_input_registers(5035, ModbusDataType.UINT_16, device_id=unit) / 10 - power_factor = self.__tcp_client.read_input_registers(5034, ModbusDataType.INT_16, unit=unit) / 1000 + power_factor = self.__tcp_client.read_input_registers(5034, ModbusDataType.INT_16, device_id=unit) / 1000 voltages = self.__tcp_client.read_input_registers(5018, [ModbusDataType.UINT_16] * 3, - wordorder=Endian.Little, unit=unit) + wordorder=Endian.Little, device_id=unit) voltages = [value / 10 for value in voltages] diff --git a/packages/modules/devices/sungrow/sungrow_sg/inverter.py b/packages/modules/devices/sungrow/sungrow_sg/inverter.py index 33e479f9df..d52ef8f6e8 100644 --- a/packages/modules/devices/sungrow/sungrow_sg/inverter.py +++ b/packages/modules/devices/sungrow/sungrow_sg/inverter.py @@ -35,11 +35,11 @@ def update(self) -> float: unit = self.device_config.configuration.modbus_id power = self.__tcp_client.read_input_registers(5030, ModbusDataType.INT_32, - wordorder=Endian.Little, unit=unit) * -1 + wordorder=Endian.Little, device_id=unit) * -1 dc_power = self.__tcp_client.read_input_registers(5016, ModbusDataType.UINT_32, - wordorder=Endian.Little, unit=unit) * -1 + wordorder=Endian.Little, device_id=unit) * -1 - currents = self.__tcp_client.read_input_registers(5021, [ModbusDataType.INT_16]*3, unit=unit) + currents = self.__tcp_client.read_input_registers(5021, [ModbusDataType.INT_16]*3, device_id=unit) currents = [value * -0.1 for value in currents] diff --git a/packages/modules/devices/sungrow/sungrow_sh/bat.py b/packages/modules/devices/sungrow/sungrow_sh/bat.py index c04eaefdde..737fed9be1 100644 --- a/packages/modules/devices/sungrow/sungrow_sh/bat.py +++ b/packages/modules/devices/sungrow/sungrow_sh/bat.py @@ -43,19 +43,19 @@ def detect_register_check(self) -> RegMode: try: self.__tcp_client.read_input_registers(5213, ModbusDataType.INT_32, - wordorder=Endian.Little, unit=unit) - self.__tcp_client.read_input_registers(5630, ModbusDataType.INT_16, unit=unit) + wordorder=Endian.Little, device_id=unit) + self.__tcp_client.read_input_registers(5630, ModbusDataType.INT_16, device_id=unit) log.debug("Battery register check: using new_registers (5213/5630).") return RegMode.NEW_REGISTERS except Exception: pass # register 13000 is always available, if unused it contains zero # register type can only be determined if battery power is not zero - if self.__tcp_client.read_input_registers(13021, ModbusDataType.UINT_16, unit=unit) == 0: + if self.__tcp_client.read_input_registers(13021, ModbusDataType.UINT_16, device_id=unit) == 0: raise ValueError("Speicherleistung aktuell 0kW. Registertyp wird gesetzt sobald " "Speicher Leistungswerte liefert.") try: - if self.__tcp_client.read_input_registers(13000, ModbusDataType.UINT_16, unit=unit) != 0: + if self.__tcp_client.read_input_registers(13000, ModbusDataType.UINT_16, device_id=unit) != 0: # if battery power is not zero and register 13000 shows status bits, old registers are used log.debug("Battery register check: using old_registers (13021 + 13000 bits for sign).") return RegMode.OLD_REGISTERS @@ -67,20 +67,20 @@ def detect_register_check(self) -> RegMode: def update(self) -> None: unit = self.device_config.configuration.modbus_id - soc = int(self.__tcp_client.read_input_registers(13022, ModbusDataType.UINT_16, unit=unit) / 10) + soc = int(self.__tcp_client.read_input_registers(13022, ModbusDataType.UINT_16, device_id=unit) / 10) # === Mode 1: new_registers === if self.register_check == RegMode.NEW_REGISTERS: - bat_current = self.__tcp_client.read_input_registers(5630, ModbusDataType.INT_16, unit=unit) * -0.1 + bat_current = self.__tcp_client.read_input_registers(5630, ModbusDataType.INT_16, device_id=unit) * -0.1 bat_power = self.__tcp_client.read_input_registers(5213, ModbusDataType.INT_32, - wordorder=Endian.Little, unit=unit) * -1 + wordorder=Endian.Little, device_id=unit) * -1 # === Mode 2: old_registers === elif self.register_check == RegMode.OLD_REGISTERS: - bat_current = self.__tcp_client.read_input_registers(13020, ModbusDataType.INT_16, unit=unit) * -0.1 - bat_power = self.__tcp_client.read_input_registers(13021, ModbusDataType.UINT_16, unit=unit) + bat_current = self.__tcp_client.read_input_registers(13020, ModbusDataType.INT_16, device_id=unit) * -0.1 + bat_power = self.__tcp_client.read_input_registers(13021, ModbusDataType.UINT_16, device_id=unit) - resp = self.__tcp_client._delegate.read_input_registers(13000, 1, unit=unit) + resp = self.__tcp_client._delegate.read_input_registers(13000, 1, device_id=unit) running_state = resp.registers[0] is_charging = (running_state & 0x02) != 0 is_discharging = (running_state & 0x04) != 0 @@ -92,13 +92,13 @@ def update(self) -> None: # === Mode 3: fallback === else: - bat_current = self.__tcp_client.read_input_registers(13020, ModbusDataType.INT_16, unit=unit) * -0.1 - bat_power = self.__tcp_client.read_input_registers(13021, ModbusDataType.UINT_16, unit=unit) + bat_current = self.__tcp_client.read_input_registers(13020, ModbusDataType.INT_16, device_id=unit) * -0.1 + bat_power = self.__tcp_client.read_input_registers(13021, ModbusDataType.UINT_16, device_id=unit) total_power = self.__tcp_client.read_input_registers(13033, ModbusDataType.INT_32, - wordorder=Endian.Little, unit=unit) + wordorder=Endian.Little, device_id=unit) pv_power = self.__tcp_client.read_input_registers(5016, ModbusDataType.UINT_32, - wordorder=Endian.Little, unit=unit) + wordorder=Endian.Little, device_id=unit) if total_power > pv_power: bat_power = -abs(bat_power) @@ -125,35 +125,35 @@ def set_power_limit(self, power_limit: Optional[int]) -> None: if power_limit is None: log.debug("Keine Batteriesteuerung, Selbstregelung durch Wechselrichter") if self.last_mode is not None: - self.__tcp_client.write_register(13049, 0, data_type=ModbusDataType.UINT_16, unit=unit) - self.__tcp_client.write_register(13050, 0xCC, data_type=ModbusDataType.UINT_16, unit=unit) + self.__tcp_client.write_register(13049, 0, data_type=ModbusDataType.UINT_16, device_id=unit) + self.__tcp_client.write_register(13050, 0xCC, data_type=ModbusDataType.UINT_16, device_id=unit) self.last_mode = None elif power_limit == 0: log.debug("Aktive Batteriesteuerung. Batterie wird auf Stop gesetzt und nicht entladen") if self.last_mode != 'stop': - self.__tcp_client.write_register(13049, 2, data_type=ModbusDataType.UINT_16, unit=unit) - self.__tcp_client.write_register(13050, 0xCC, data_type=ModbusDataType.UINT_16, unit=unit) + self.__tcp_client.write_register(13049, 2, data_type=ModbusDataType.UINT_16, device_id=unit) + self.__tcp_client.write_register(13050, 0xCC, data_type=ModbusDataType.UINT_16, device_id=unit) self.last_mode = 'stop' elif power_limit < 0: log.debug(f"Aktive Batteriesteuerung. Batterie wird mit {power_limit} W entladen für den Hausverbrauch") if self.last_mode != 'discharge': - self.__tcp_client.write_register(13049, 2, data_type=ModbusDataType.UINT_16, unit=unit) - self.__tcp_client.write_register(13050, 0xBB, data_type=ModbusDataType.UINT_16, unit=unit) + self.__tcp_client.write_register(13049, 2, data_type=ModbusDataType.UINT_16, device_id=unit) + self.__tcp_client.write_register(13050, 0xBB, data_type=ModbusDataType.UINT_16, device_id=unit) self.last_mode = 'discharge' # Die maximale Entladeleistung begrenzen auf 5000W, maximaler Wertebereich Modbusregister. power_value = int(min(abs(power_limit), 5000)) log.debug(f"Aktive Batteriesteuerung. Batterie wird mit {power_value} W entladen für den Hausverbrauch") - self.__tcp_client.write_register(13051, power_value, data_type=ModbusDataType.UINT_16, unit=unit) + self.__tcp_client.write_register(13051, power_value, data_type=ModbusDataType.UINT_16, device_id=unit) elif power_limit > 0: log.debug(f"Aktive Batteriesteuerung. Batterie wird mit {power_limit} W geladen") if self.last_mode != 'charge': - self.__tcp_client.write_register(13049, 2, data_type=ModbusDataType.UINT_16, unit=unit) - self.__tcp_client.write_register(13050, 0xAA, data_type=ModbusDataType.UINT_16, unit=unit) + self.__tcp_client.write_register(13049, 2, data_type=ModbusDataType.UINT_16, device_id=unit) + self.__tcp_client.write_register(13050, 0xAA, data_type=ModbusDataType.UINT_16, device_id=unit) self.last_mode = 'charge' # Die maximale Entladeleistung begrenzen auf 5000W, maximaler Wertebereich Modbusregister. power_value = int(min(power_limit, 5000)) log.debug(f"Aktive Batteriesteuerung. Batterie wird mit {power_value} W geladen") - self.__tcp_client.write_register(13051, power_value, data_type=ModbusDataType.UINT_16, unit=unit) + self.__tcp_client.write_register(13051, power_value, data_type=ModbusDataType.UINT_16, device_id=unit) def power_limit_controllable(self) -> bool: return True diff --git a/packages/modules/devices/sungrow/sungrow_sh/counter.py b/packages/modules/devices/sungrow/sungrow_sh/counter.py index f7b37254a3..871a54ea6f 100644 --- a/packages/modules/devices/sungrow/sungrow_sh/counter.py +++ b/packages/modules/devices/sungrow/sungrow_sh/counter.py @@ -38,29 +38,29 @@ def initialize(self) -> None: def update(self): unit = self.device_config.configuration.modbus_id power = self.__tcp_client.read_input_registers(13009, ModbusDataType.INT_32, - wordorder=Endian.Little, unit=unit) * -1 + wordorder=Endian.Little, device_id=unit) * -1 try: powers = self.__tcp_client.read_input_registers(5602, [ModbusDataType.INT_32] * 3, - wordorder=Endian.Little, unit=unit) + wordorder=Endian.Little, device_id=unit) except Exception: powers = None self.fault_state.no_error(self.fault_text) - frequency = self.__tcp_client.read_input_registers(5035, ModbusDataType.UINT_16, unit=unit) / 10 + frequency = self.__tcp_client.read_input_registers(5035, ModbusDataType.UINT_16, device_id=unit) / 10 if self.device_config.configuration.version == Version.SH_winet_dongle: # On WiNet-S, the frequency accuracy is higher by one place frequency /= 10 - power_factor = self.__tcp_client.read_input_registers(5034, ModbusDataType.INT_16, unit=unit) / 1000 + power_factor = self.__tcp_client.read_input_registers(5034, ModbusDataType.INT_16, device_id=unit) / 1000 if self.device_config.configuration.version == Version.SH: # SH (LAN) provides accurate values from meter voltages = self.__tcp_client.read_input_registers(5740, [ModbusDataType.UINT_16] * 3, - wordorder=Endian.Little, unit=unit) + wordorder=Endian.Little, device_id=unit) else: # These are actually output voltages of the inverter: voltages = self.__tcp_client.read_input_registers(5018, [ModbusDataType.UINT_16] * 3, - wordorder=Endian.Little, unit=unit) + wordorder=Endian.Little, device_id=unit) voltages = [value / 10 for value in voltages] diff --git a/packages/modules/devices/sungrow/sungrow_sh/inverter.py b/packages/modules/devices/sungrow/sungrow_sh/inverter.py index fcb56c56ad..7004361bc2 100644 --- a/packages/modules/devices/sungrow/sungrow_sh/inverter.py +++ b/packages/modules/devices/sungrow/sungrow_sh/inverter.py @@ -35,11 +35,11 @@ def update(self) -> float: unit = self.device_config.configuration.modbus_id power = self.__tcp_client.read_input_registers(13033, ModbusDataType.INT_32, - wordorder=Endian.Little, unit=unit) * -1 + wordorder=Endian.Little, device_id=unit) * -1 dc_power = self.__tcp_client.read_input_registers(5016, ModbusDataType.UINT_32, - wordorder=Endian.Little, unit=unit) * -1 + wordorder=Endian.Little, device_id=unit) * -1 - currents = self.__tcp_client.read_input_registers(13030, [ModbusDataType.INT_16]*3, unit=unit) + currents = self.__tcp_client.read_input_registers(13030, [ModbusDataType.INT_16]*3, device_id=unit) currents = [value * -0.1 for value in currents] diff --git a/packages/modules/devices/thermia/thermia/counter.py b/packages/modules/devices/thermia/thermia/counter.py index 47dbf6cc56..3488502eea 100644 --- a/packages/modules/devices/thermia/thermia/counter.py +++ b/packages/modules/devices/thermia/thermia/counter.py @@ -8,7 +8,7 @@ from modules.common.simcount import SimCounter from modules.common.store import get_counter_value_store from modules.devices.thermia.thermia.config import ThermiaCounterSetup -from pymodbus.constants import Endian +from modules.common.pymodbus_compat import Endian from modules.common.utils.peak_filter import PeakFilter from modules.common.component_type import ComponentType @@ -36,15 +36,15 @@ def initialize(self) -> None: def update(self): with self.client: voltages = [val / 100 for val in self.client.read_input_registers( - 72, [ModbusDataType.INT_16] * 3, unit=self.modbus_id)] + 72, [ModbusDataType.INT_16] * 3, device_id=self.modbus_id)] powers = [val / 1 for val in self.client.read_input_registers( - 78, [ModbusDataType.INT_16] * 3, unit=self.modbus_id)] + 78, [ModbusDataType.INT_16] * 3, device_id=self.modbus_id)] power = sum(powers) currents = [(val / 100) for val in self.client.read_input_registers( - 69, [ModbusDataType.INT_16] * 3, unit=self.modbus_id)] + 69, [ModbusDataType.INT_16] * 3, device_id=self.modbus_id)] imported = self.client.read_input_registers( 83, ModbusDataType.INT_32, wordorder=Endian.Little, - unit=self.modbus_id) * 100 + device_id=self.modbus_id) * 100 exported = 0 imported, _ = self.peak_filter.check_values(power, imported, None) diff --git a/packages/modules/devices/upower/upower/bat.py b/packages/modules/devices/upower/upower/bat.py index 304cbf7bd9..1af2ee4c1c 100644 --- a/packages/modules/devices/upower/upower/bat.py +++ b/packages/modules/devices/upower/upower/bat.py @@ -33,19 +33,19 @@ def __init__(self, def update(self) -> None: if self.version == UPowerVersion.GEN_1: - power = self.client.read_input_registers(30258, ModbusDataType.INT_32, unit=self.__modbus_id) * -1 - soc = self.client.read_input_registers(33000, ModbusDataType.UINT_16, unit=self.__modbus_id) + power = self.client.read_input_registers(30258, ModbusDataType.INT_32, device_id=self.__modbus_id) * -1 + soc = self.client.read_input_registers(33000, ModbusDataType.UINT_16, device_id=self.__modbus_id) imported = self.client.read_input_registers( - 31108, ModbusDataType.UINT_32, unit=self.__modbus_id) * 100 + 31108, ModbusDataType.UINT_32, device_id=self.__modbus_id) * 100 exported = self.client.read_input_registers( - 31110, ModbusDataType.UINT_32, unit=self.__modbus_id) * 100 + 31110, ModbusDataType.UINT_32, device_id=self.__modbus_id) * 100 imported, exported = self.peak_filter.check_values(power, imported, exported) else: # 1221 Total Bat Power # 1427 Battery 1 current power # Bat 1 (additional batteries offset by 50) - power = self.client.read_input_registers(1427, ModbusDataType.INT_16, unit=self.__modbus_id) - soc = self.client.read_input_registers(1402, ModbusDataType.UINT_16, unit=self.__modbus_id) / 10 + power = self.client.read_input_registers(1427, ModbusDataType.INT_16, device_id=self.__modbus_id) + soc = self.client.read_input_registers(1402, ModbusDataType.UINT_16, device_id=self.__modbus_id) / 10 self.peak_filter.check_values(power) imported, exported = self.sim_counter.sim_count(power) diff --git a/packages/modules/devices/upower/upower/counter.py b/packages/modules/devices/upower/upower/counter.py index 818b62f50a..de4ad21b80 100644 --- a/packages/modules/devices/upower/upower/counter.py +++ b/packages/modules/devices/upower/upower/counter.py @@ -33,21 +33,21 @@ def __init__(self, def update(self): if self.version == UPowerVersion.GEN_1: - power = self.client.read_holding_registers(1000, ModbusDataType.INT_32, unit=self.__modbus_id) * -1 - frequency = self.client.read_holding_registers(11015, ModbusDataType.UINT_16, unit=self.__modbus_id) + power = self.client.read_holding_registers(1000, ModbusDataType.INT_32, device_id=self.__modbus_id) * -1 + frequency = self.client.read_holding_registers(11015, ModbusDataType.UINT_16, device_id=self.__modbus_id) powers = [-value for value in self.client.read_holding_registers( - 10994, [ModbusDataType.INT_32] * 3, unit=self.__modbus_id)] - exported = self.client.read_holding_registers(31102, ModbusDataType.UINT_32, unit=self.__modbus_id) * 100 - imported = self.client.read_holding_registers(31104, ModbusDataType.UINT_32, unit=self.__modbus_id) * 100 + 10994, [ModbusDataType.INT_32] * 3, device_id=self.__modbus_id)] + exported = self.client.read_holding_registers(31102, ModbusDataType.UINT_32, device_id=self.__modbus_id) * 100 + imported = self.client.read_holding_registers(31104, ModbusDataType.UINT_32, device_id=self.__modbus_id) * 100 imported, exported = self.peak_filter.check_values(power, imported, exported) else: - power = self.client.read_holding_registers(1219, ModbusDataType.INT_16, unit=self.__modbus_id) * -10 + power = self.client.read_holding_registers(1219, ModbusDataType.INT_16, device_id=self.__modbus_id) * -10 frequency = self.client.read_holding_registers( - 1759, ModbusDataType.UINT_16, unit=self.__modbus_id) / 100 + 1759, ModbusDataType.UINT_16, device_id=self.__modbus_id) / 100 powers = [-10 * value for value in self.client.read_holding_registers( - 1750, [ModbusDataType.INT_16] * 3, unit=self.__modbus_id + 1750, [ModbusDataType.INT_16] * 3, device_id=self.__modbus_id )] self.peak_filter.check_values(power) imported, exported = self.sim_counter.sim_count(power) diff --git a/packages/modules/devices/upower/upower/inverter.py b/packages/modules/devices/upower/upower/inverter.py index d09ef2fa92..99797c29c6 100644 --- a/packages/modules/devices/upower/upower/inverter.py +++ b/packages/modules/devices/upower/upower/inverter.py @@ -30,11 +30,11 @@ def __init__(self, def update(self) -> None: if self.version == UPowerVersion.GEN_1: - power = self.client.read_holding_registers(11028, ModbusDataType.UINT_32, unit=self.__modbus_id) * -1 - exported = self.client.read_holding_registers(11020, ModbusDataType.UINT_32, unit=self.__modbus_id) * 100 + power = self.client.read_holding_registers(11028, ModbusDataType.UINT_32, device_id=self.__modbus_id) * -1 + exported = self.client.read_holding_registers(11020, ModbusDataType.UINT_32, device_id=self.__modbus_id) * 100 else: - power = self.client.read_holding_registers(1220, ModbusDataType.UINT_16, unit=self.__modbus_id) * -1 - exported = self.client.read_holding_registers(1006, ModbusDataType.UINT_32, unit=self.__modbus_id) * 10 + power = self.client.read_holding_registers(1220, ModbusDataType.UINT_16, device_id=self.__modbus_id) * -1 + exported = self.client.read_holding_registers(1006, ModbusDataType.UINT_32, device_id=self.__modbus_id) * 10 _, exported = self.peak_filter.check_values(power, None, exported) inverter_state = InverterState( diff --git a/packages/modules/devices/varta/varta/bat_modbus.py b/packages/modules/devices/varta/varta/bat_modbus.py index 2ac4cab323..e0cd063f00 100644 --- a/packages/modules/devices/varta/varta/bat_modbus.py +++ b/packages/modules/devices/varta/varta/bat_modbus.py @@ -37,8 +37,8 @@ def update(self) -> None: self.set_state(self.get_state()) def get_state(self) -> BatState: - soc = self.client.read_holding_registers(1068, ModbusDataType.INT_16, unit=self.__modbus_id) - power = self.client.read_holding_registers(1066, ModbusDataType.INT_16, unit=self.__modbus_id) + soc = self.client.read_holding_registers(1068, ModbusDataType.INT_16, device_id=self.__modbus_id) + power = self.client.read_holding_registers(1066, ModbusDataType.INT_16, device_id=self.__modbus_id) self.peak_filter.check_values(power) return BatState( power=power, diff --git a/packages/modules/devices/varta/varta/counter.py b/packages/modules/devices/varta/varta/counter.py index 3dd321010a..68e801a303 100644 --- a/packages/modules/devices/varta/varta/counter.py +++ b/packages/modules/devices/varta/varta/counter.py @@ -34,7 +34,7 @@ def initialize(self) -> None: self.peak_filter = PeakFilter(ComponentType.COUNTER, self.component_config.id, self.fault_state) def update(self): - power = self.client.read_holding_registers(1078, ModbusDataType.INT_16, unit=self.__modbus_id) * -1 + power = self.client.read_holding_registers(1078, ModbusDataType.INT_16, device_id=self.__modbus_id) * -1 self.peak_filter.check_values(power) imported, exported = self.sim_counter.sim_count(power) diff --git a/packages/modules/devices/varta/varta/inverter.py b/packages/modules/devices/varta/varta/inverter.py index 5bba140ea2..adeb54b673 100644 --- a/packages/modules/devices/varta/varta/inverter.py +++ b/packages/modules/devices/varta/varta/inverter.py @@ -33,7 +33,7 @@ def initialize(self) -> None: self.peak_filter = PeakFilter(ComponentType.INVERTER, self.component_config.id, self.fault_state) def update(self): - power = self.client.read_holding_registers(1102, ModbusDataType.UINT_16, unit=self.__modbus_id) * -1 + power = self.client.read_holding_registers(1102, ModbusDataType.UINT_16, device_id=self.__modbus_id) * -1 self.peak_filter.check_values(power) _, exported = self.sim_counter.sim_count(power) diff --git a/packages/modules/devices/victron/victron/bat.py b/packages/modules/devices/victron/victron/bat.py index f49dfc4f40..1304b3cab9 100644 --- a/packages/modules/devices/victron/victron/bat.py +++ b/packages/modules/devices/victron/victron/bat.py @@ -41,8 +41,8 @@ def initialize(self) -> None: def update(self) -> None: modbus_id = self.component_config.configuration.modbus_id with self.__tcp_client: - power = self.__tcp_client.read_holding_registers(842, ModbusDataType.INT_16, unit=modbus_id) - soc = self.__tcp_client.read_holding_registers(843, ModbusDataType.UINT_16, unit=modbus_id) + power = self.__tcp_client.read_holding_registers(842, ModbusDataType.INT_16, device_id=modbus_id) + soc = self.__tcp_client.read_holding_registers(843, ModbusDataType.UINT_16, device_id=modbus_id) self.peak_filter.check_values(power) imported, exported = self.sim_counter.sim_count(power) bat_state = BatState( @@ -57,7 +57,7 @@ def update(self) -> None: def set_power_limit(self, power_limit: Optional[int]) -> None: modbus_id = self.component_config.configuration.modbus_id # Wenn Victron Dynamic ESS aktiv, erfolgt keine weitere Regelung in openWB - dynamic_ess_mode = self.__tcp_client.read_holding_registers(5400, ModbusDataType.UINT_16, unit=modbus_id) + dynamic_ess_mode = self.__tcp_client.read_holding_registers(5400, ModbusDataType.UINT_16, device_id=modbus_id) if dynamic_ess_mode == 1: log.debug("Dynamic ESS Mode ist aktiv, daher erfolgt keine Regelung des Speichers durch openWB") return @@ -66,18 +66,18 @@ def set_power_limit(self, power_limit: Optional[int]) -> None: log.debug("Keine Batteriesteuerung, Selbstregelung durch Wechselrichter") if self.last_mode is not None: # ESS Mode 2 und Leistung EVU auf 0kW setzen für Selbstregelung - self.__tcp_client.write_register(2902, 2, data_type=ModbusDataType.UINT_16, unit=modbus_id) - self.__tcp_client.write_register(2702, 100, data_type=ModbusDataType.UINT_16, unit=modbus_id) - self.__tcp_client.write_register(2716, 0, data_type=ModbusDataType.INT_32, unit=modbus_id) + self.__tcp_client.write_register(2902, 2, data_type=ModbusDataType.UINT_16, device_id=modbus_id) + self.__tcp_client.write_register(2702, 100, data_type=ModbusDataType.UINT_16, device_id=modbus_id) + self.__tcp_client.write_register(2716, 0, data_type=ModbusDataType.INT_32, device_id=modbus_id) self.last_mode = None elif power_limit == 0: log.debug("Aktive Batteriesteuerung. Batterie wird auf Stop gesetzt und nicht entladen") if self.last_mode != 'stop': # ESS Mode 2 und Discharge Power 0% für externe Steuerung und keine Entladung # Leistung an EVU-Punkt auf 0kW setzen -> Eigenregelung bei laden und Entladen verhindern - self.__tcp_client.write_register(2902, 2, data_type=ModbusDataType.UINT_16, unit=modbus_id) - self.__tcp_client.write_register(2702, 0, data_type=ModbusDataType.UINT_16, unit=modbus_id) - self.__tcp_client.write_register(2716, 0, data_type=ModbusDataType.INT_32, unit=modbus_id) + self.__tcp_client.write_register(2902, 2, data_type=ModbusDataType.UINT_16, device_id=modbus_id) + self.__tcp_client.write_register(2702, 0, data_type=ModbusDataType.UINT_16, device_id=modbus_id) + self.__tcp_client.write_register(2716, 0, data_type=ModbusDataType.INT_32, device_id=modbus_id) self.last_mode = 'stop' elif power_limit < 0: evu_power = data.data.counter_all_data.get_evu_counter().data.get.power @@ -87,14 +87,14 @@ def set_power_limit(self, power_limit: Optional[int]) -> None: f"Aktuelle Speicherleistung: {self.current_power} W, EVU-Leistung: {evu_power} W " f"EVU-Leistung um {power_limit - self.current_power} W anpassen auf {set_power} W") if self.last_mode != 'discharge': - self.__tcp_client.write_register(2902, 2, data_type=ModbusDataType.UINT_16, unit=modbus_id) - self.__tcp_client.write_register(2702, 100, data_type=ModbusDataType.UINT_16, unit=modbus_id) + self.__tcp_client.write_register(2902, 2, data_type=ModbusDataType.UINT_16, device_id=modbus_id) + self.__tcp_client.write_register(2702, 100, data_type=ModbusDataType.UINT_16, device_id=modbus_id) self.last_mode = 'discharge' # Setzen der angestrebten EVU-Leistung, Speicher versucht seine Leistung # anzupassen um den Zielwert zu erreichen self.__tcp_client.write_register( - 2716, set_power, data_type=ModbusDataType.INT_32, unit=modbus_id) + 2716, set_power, data_type=ModbusDataType.INT_32, device_id=modbus_id) elif power_limit > 0: evu_power = data.data.counter_all_data.get_evu_counter().data.get.power set_power = (power_limit - self.current_power) + evu_power @@ -103,11 +103,11 @@ def set_power_limit(self, power_limit: Optional[int]) -> None: f"Aktuelle Speicherleistung: {self.current_power} W, EVU-Leistung: {evu_power} W " f"EVU-Leistung um {power_limit - self.current_power} W anpassen auf {set_power} W") if self.last_mode != 'charge': - self.__tcp_client.write_register(2902, 2, data_type=ModbusDataType.UINT_16, unit=modbus_id) - self.__tcp_client.write_register(2702, 100, data_type=ModbusDataType.UINT_16, unit=modbus_id) + self.__tcp_client.write_register(2902, 2, data_type=ModbusDataType.UINT_16, device_id=modbus_id) + self.__tcp_client.write_register(2702, 100, data_type=ModbusDataType.UINT_16, device_id=modbus_id) self.last_mode = 'charge' self.__tcp_client.write_register( - 2716, set_power, data_type=ModbusDataType.INT_32, unit=modbus_id) + 2716, set_power, data_type=ModbusDataType.INT_32, device_id=modbus_id) def power_limit_controllable(self) -> bool: return True diff --git a/packages/modules/devices/victron/victron/counter.py b/packages/modules/devices/victron/victron/counter.py index 11da27e6ce..f67b647437 100644 --- a/packages/modules/devices/victron/victron/counter.py +++ b/packages/modules/devices/victron/victron/counter.py @@ -37,16 +37,16 @@ def update(self): energy_meter = self.component_config.configuration.energy_meter with self.__tcp_client: if energy_meter: - powers = self.__tcp_client.read_holding_registers(2600, [ModbusDataType.INT_16]*3, unit=unit) + powers = self.__tcp_client.read_holding_registers(2600, [ModbusDataType.INT_16]*3, device_id=unit) currents = [ - self.__tcp_client.read_holding_registers(reg, ModbusDataType.INT_16, unit=unit) / 10 + self.__tcp_client.read_holding_registers(reg, ModbusDataType.INT_16, device_id=unit) / 10 for reg in [2617, 2619, 2621]] voltages = [ - self.__tcp_client.read_holding_registers(reg, ModbusDataType.UINT_16, unit=unit) / 10 + self.__tcp_client.read_holding_registers(reg, ModbusDataType.UINT_16, device_id=unit) / 10 for reg in [2616, 2618, 2620]] power = sum(powers) else: - powers = self.__tcp_client.read_holding_registers(820, [ModbusDataType.INT_16]*3, unit=unit) + powers = self.__tcp_client.read_holding_registers(820, [ModbusDataType.INT_16]*3, device_id=unit) power = sum(powers) self.peak_filter.check_values(power) diff --git a/packages/modules/devices/victron/victron/inverter.py b/packages/modules/devices/victron/victron/inverter.py index 2b11b17f81..778b2211e1 100644 --- a/packages/modules/devices/victron/victron/inverter.py +++ b/packages/modules/devices/victron/victron/inverter.py @@ -40,7 +40,7 @@ def update(self) -> None: with self.__tcp_client: if self.component_config.configuration.mppt: try: - power = self.__tcp_client.read_holding_registers(789, ModbusDataType.UINT_16, unit=modbus_id) / -10 + power = self.__tcp_client.read_holding_registers(789, ModbusDataType.UINT_16, device_id=modbus_id) / -10 except Exception as e: if "GatewayPathUnavailable" in str(e): power = 0 @@ -52,8 +52,8 @@ def update(self) -> None: # Adresse 808-810 ac output connected pv # Adresse 811-813 ac input connected pv # Adresse 850 mppt Leistung - power_temp1 = self.__tcp_client.read_holding_registers(808, [ModbusDataType.UINT_16]*6, unit=100) - power_temp2 = self.__tcp_client.read_holding_registers(850, ModbusDataType.UINT_16, unit=100) + power_temp1 = self.__tcp_client.read_holding_registers(808, [ModbusDataType.UINT_16]*6, device_id=100) + power_temp2 = self.__tcp_client.read_holding_registers(850, ModbusDataType.UINT_16, device_id=100) power = (sum(power_temp1)+power_temp2) * -1 self.peak_filter.check_values(power) diff --git a/packages/modules/devices/victron/victron_3p75ct/counter.py b/packages/modules/devices/victron/victron_3p75ct/counter.py index fb7e074022..1c63b0339c 100644 --- a/packages/modules/devices/victron/victron_3p75ct/counter.py +++ b/packages/modules/devices/victron/victron_3p75ct/counter.py @@ -33,22 +33,22 @@ def update(self): unit = 1 # Modbus ID ist immer 1 da Standalone Produkt with self.__udp_client: powers = [ - self.__udp_client.read_holding_registers(reg, ModbusDataType.INT_32, unit=unit) / 1 + self.__udp_client.read_holding_registers(reg, ModbusDataType.INT_32, device_id=unit) / 1 for reg in [0x3082, 0x3086, 0x308A]] currents = [ - self.__udp_client.read_holding_registers(reg, ModbusDataType.INT_16, unit=unit) / 100 + self.__udp_client.read_holding_registers(reg, ModbusDataType.INT_16, device_id=unit) / 100 for reg in [0x3041, 0x3049, 0x3051]] voltages = [ - self.__udp_client.read_holding_registers(reg, ModbusDataType.INT_16, unit=unit) / 100 + self.__udp_client.read_holding_registers(reg, ModbusDataType.INT_16, device_id=unit) / 100 for reg in [0x3040, 0x3048, 0x3050]] power_factors = [ - self.__udp_client.read_holding_registers(reg, ModbusDataType.INT_16, unit=unit) / 1000 + self.__udp_client.read_holding_registers(reg, ModbusDataType.INT_16, device_id=unit) / 1000 for reg in [0x3047, 0x304F, 0x3057]] power = sum(powers) - frequency = self.__udp_client.read_holding_registers(0x3032, ModbusDataType.UINT_16, unit=unit) / 100 - imported = self.__udp_client.read_holding_registers(0x3034, ModbusDataType.UINT_32, unit=unit) * 10 - exported = self.__udp_client.read_holding_registers(0x3036, ModbusDataType.UINT_32, unit=unit) * 10 + frequency = self.__udp_client.read_holding_registers(0x3032, ModbusDataType.UINT_16, device_id=unit) / 100 + imported = self.__udp_client.read_holding_registers(0x3034, ModbusDataType.UINT_32, device_id=unit) * 10 + exported = self.__udp_client.read_holding_registers(0x3036, ModbusDataType.UINT_32, device_id=unit) * 10 imported, exported = self.peak_filter.check_values(power, imported, exported) counter_state = CounterState( diff --git a/packages/modules/internal_chargepoint_handler/internal_chargepoint_handler.py b/packages/modules/internal_chargepoint_handler/internal_chargepoint_handler.py index 30fcf6b12b..c4628b0a58 100644 --- a/packages/modules/internal_chargepoint_handler/internal_chargepoint_handler.py +++ b/packages/modules/internal_chargepoint_handler/internal_chargepoint_handler.py @@ -1,4 +1,4 @@ -#!/usr/bin/python +#!/usr/bin/env python3 import copy import logging from threading import Event, Thread diff --git a/packages/modules/internal_chargepoint_handler/internal_chargepoint_handler_config.py b/packages/modules/internal_chargepoint_handler/internal_chargepoint_handler_config.py index 736bf8ec01..2b80baf109 100644 --- a/packages/modules/internal_chargepoint_handler/internal_chargepoint_handler_config.py +++ b/packages/modules/internal_chargepoint_handler/internal_chargepoint_handler_config.py @@ -1,4 +1,4 @@ -#!/usr/bin/python +#!/usr/bin/env python3 from dataclasses import dataclass, field from typing import List, Optional diff --git a/packages/modules/internal_chargepoint_handler/rfid.py b/packages/modules/internal_chargepoint_handler/rfid.py index 46878c99e7..6664dd437f 100644 --- a/packages/modules/internal_chargepoint_handler/rfid.py +++ b/packages/modules/internal_chargepoint_handler/rfid.py @@ -1,145 +1,140 @@ import asyncio import logging -from evdev import InputDevice, ecodes, list_devices, categorize from helpermodules.pub import Pub log = logging.getLogger(__name__) +try: + from evdev import InputDevice, ecodes, list_devices, categorize + EVDEV_AVAILABLE = True +except ImportError: + EVDEV_AVAILABLE = False + log.info("evdev not available - RFID reader disabled") -class RfidReader: - SCAN_CODE_MAP = { - # function keys - # 0: None, - # ecodes.KEY_ESC: u'ESC', - # ecodes.KEY_BACKSPACE: u'BKSP', - # ecodes.KEY_TAB: u'TAB', - # ecodes.KEY_LEFTBRACE: u'[', - # ecodes.KEY_RIGHTBRACE: u']', - # ecodes.KEY_ENTER: u'CRLF', - # ecodes.KEY_LEFTCTRL: u'LCTRL', - # ecodes.KEY_LEFTSHIFT: u'LSHFT', - # ecodes.KEY_RIGHTSHIFT: u'RSHFT', - # ecodes.KEY_LEFTALT: u'LALT', - # ecodes.KEY_KPENTER: u'CRLF', - # ecodes.KEY_RIGHTCTRL: u'RCTRL, - # ecodes.KEY_RIGHTALT: u'RALT' - # number keys - ecodes.KEY_1: u'1', - ecodes.KEY_2: u'2', - ecodes.KEY_3: u'3', - ecodes.KEY_4: u'4', - ecodes.KEY_5: u'5', - ecodes.KEY_6: u'6', - ecodes.KEY_7: u'7', - ecodes.KEY_8: u'8', - ecodes.KEY_9: u'9', - ecodes.KEY_0: u'0', - ecodes.KEY_KP1: u'1', - ecodes.KEY_KP2: u'2', - ecodes.KEY_KP3: u'3', - ecodes.KEY_KP4: u'4', - ecodes.KEY_KP5: u'5', - ecodes.KEY_KP6: u'6', - ecodes.KEY_KP7: u'7', - ecodes.KEY_KP8: u'8', - ecodes.KEY_KP9: u'9', - ecodes.KEY_KP0: u'0', +if EVDEV_AVAILABLE: - # latin letters - ecodes.KEY_A: u'A', - ecodes.KEY_B: u'B', - ecodes.KEY_C: u'C', - ecodes.KEY_D: u'D', - ecodes.KEY_E: u'E', - ecodes.KEY_F: u'F', - ecodes.KEY_G: u'G', - ecodes.KEY_H: u'H', - ecodes.KEY_I: u'I', - ecodes.KEY_J: u'J', - ecodes.KEY_K: u'K', - ecodes.KEY_L: u'L', - ecodes.KEY_M: u'M', - ecodes.KEY_N: u'N', - ecodes.KEY_O: u'O', - ecodes.KEY_P: u'P', - ecodes.KEY_Q: u'Q', - ecodes.KEY_R: u'R', - ecodes.KEY_S: u'S', - ecodes.KEY_T: u'T', - ecodes.KEY_U: u'U', - ecodes.KEY_V: u'V', - ecodes.KEY_W: u'W', - ecodes.KEY_X: u'X', - ecodes.KEY_Y: u'Y', - ecodes.KEY_Z: u'Z', + class RfidReader: + SCAN_CODE_MAP = { + ecodes.KEY_1: u'1', + ecodes.KEY_2: u'2', + ecodes.KEY_3: u'3', + ecodes.KEY_4: u'4', + ecodes.KEY_5: u'5', + ecodes.KEY_6: u'6', + ecodes.KEY_7: u'7', + ecodes.KEY_8: u'8', + ecodes.KEY_9: u'9', + ecodes.KEY_0: u'0', + ecodes.KEY_KP1: u'1', + ecodes.KEY_KP2: u'2', + ecodes.KEY_KP3: u'3', + ecodes.KEY_KP4: u'4', + ecodes.KEY_KP5: u'5', + ecodes.KEY_KP6: u'6', + ecodes.KEY_KP7: u'7', + ecodes.KEY_KP8: u'8', + ecodes.KEY_KP9: u'9', + ecodes.KEY_KP0: u'0', + ecodes.KEY_A: u'A', + ecodes.KEY_B: u'B', + ecodes.KEY_C: u'C', + ecodes.KEY_D: u'D', + ecodes.KEY_E: u'E', + ecodes.KEY_F: u'F', + ecodes.KEY_G: u'G', + ecodes.KEY_H: u'H', + ecodes.KEY_I: u'I', + ecodes.KEY_J: u'J', + ecodes.KEY_K: u'K', + ecodes.KEY_L: u'L', + ecodes.KEY_M: u'M', + ecodes.KEY_N: u'N', + ecodes.KEY_O: u'O', + ecodes.KEY_P: u'P', + ecodes.KEY_Q: u'Q', + ecodes.KEY_R: u'R', + ecodes.KEY_S: u'S', + ecodes.KEY_T: u'T', + ecodes.KEY_U: u'U', + ecodes.KEY_V: u'V', + ecodes.KEY_W: u'W', + ecodes.KEY_X: u'X', + ecodes.KEY_Y: u'Y', + ecodes.KEY_Z: u'Z', + ecodes.KEY_MINUS: u'-', + ecodes.KEY_EQUAL: u'=', + ecodes.KEY_SEMICOLON: u';', + ecodes.KEY_COMMA: u',', + ecodes.KEY_DOT: u'.', + ecodes.KEY_SLASH: u'/', + ecodes.KEY_KPASTERISK: u'*', + ecodes.KEY_KPMINUS: u'-', + ecodes.KEY_KPPLUS: u'+', + ecodes.KEY_KPDOT: u'.', + ecodes.KEY_KPSLASH: u'/', + } + _detected_keyboards: list[InputDevice] = [] - # punctuation marks and other characters - ecodes.KEY_MINUS: u'-', - ecodes.KEY_EQUAL: u'=', - ecodes.KEY_SEMICOLON: u';', - ecodes.KEY_COMMA: u',', - ecodes.KEY_DOT: u'.', - ecodes.KEY_SLASH: u'/', - ecodes.KEY_KPASTERISK: u'*', - ecodes.KEY_KPMINUS: u'-', - ecodes.KEY_KPPLUS: u'+', - ecodes.KEY_KPDOT: u'.', - ecodes.KEY_KPSLASH: u'/', - # ecodes.KEY_APOSTROPHE: u'"', - # ecodes.KEY_GRAVE: u'`', - # ecodes.KEY_BACKSLASH: u'\\', - } - _detected_keyboards: list[InputDevice] = [] - - def __init__(self) -> None: - try: - devices = [InputDevice(path) for path in list_devices()] - for device in devices: - log.debug(f"**** {device.path} {device.name} {device.phys} ****") - # log.debug(device.capabilities(verbose=True)) - device_capabilities = device.capabilities() - if ecodes.EV_KEY in device_capabilities: - log.debug("device emits keyboard events") - if ecodes.KEY_ENTER in device_capabilities[1]: - log.debug("detected 'enter' key, device seems to be a keyboard") - self._detected_keyboards.append(device) + def __init__(self) -> None: + try: + devices = [InputDevice(path) for path in list_devices()] + for device in devices: + log.debug(f"**** {device.path} {device.name} {device.phys} ****") + device_capabilities = device.capabilities() + if ecodes.EV_KEY in device_capabilities: + log.debug("device emits keyboard events") + if ecodes.KEY_ENTER in device_capabilities[1]: + log.debug("detected 'enter' key, device seems to be a keyboard") + self._detected_keyboards.append(device) + else: + log.debug("no 'enter' key detected, skipping device") else: - log.debug("no 'enter' key detected, skipping device") - else: - log.debug("device does not emit keyboard events, skipping") - log.info("detected keyboard devices:") + log.debug("device does not emit keyboard events, skipping") + log.info("detected keyboard devices:") + for device in self._detected_keyboards: + log.info(f"{device.path} {device.name}") + except Exception: + log.exception("Fehler im Rfid-Modul") + + def keyboards_detected(self) -> bool: + return len(self._detected_keyboards) > 0 + + async def _read_events(self, device: InputDevice): + log.debug(f"reading events from: {device.path}") + try: + key_string = "" + async for event in device.async_read_loop(): + if event.type == ecodes.EV_KEY: + data = categorize(event) + if data.keystate == 1: + if data.scancode in (ecodes.KEY_ENTER, ecodes.KEY_KPENTER): + if len(key_string) > 0: + log.debug(f"RFID-String: {key_string}") + Pub().pub("openWB/set/internal_chargepoint/last_tag", key_string) + key_string = "" + else: + log.debug(f"new key: {data.scancode} - {ecodes.KEY[data.scancode]}") + key_lookup = self.SCAN_CODE_MAP.get(data.scancode) or u'' + key_string += str(format(key_lookup)) + except Exception: + log.exception("Fehler im Rfid-Modul") + + def run(self): + loop = asyncio.new_event_loop() + asyncio.set_event_loop(loop) for device in self._detected_keyboards: - log.info(f"{device.path} {device.name}") - except Exception: - log.exception("Fehler im Rfid-Modul") + asyncio.ensure_future(self._read_events(device)) + loop.run_forever() - def keyboards_detected(self) -> bool: - return len(self._detected_keyboards) > 0 +else: - async def _read_events(self, device: InputDevice): - log.debug(f"reading events from: {device.path}") - try: - key_string = "" - async for event in device.async_read_loop(): - if event.type == ecodes.EV_KEY: - data = categorize(event) - if data.keystate == 1: - if data.scancode in (ecodes.KEY_ENTER, ecodes.KEY_KPENTER): - if len(key_string) > 0: - log.debug(f"RFID-String: {key_string}") - Pub().pub("openWB/set/internal_chargepoint/last_tag", key_string) - key_string = "" - else: - log.debug(f"new key: {data.scancode} - {ecodes.KEY[data.scancode]}") - key_lookup = self.SCAN_CODE_MAP.get(data.scancode) or u'' - key_string += str(format(key_lookup)) - except Exception: - log.exception("Fehler im Rfid-Modul") + class RfidReader: + def __init__(self) -> None: + pass + + def keyboards_detected(self) -> bool: + return False - def run(self): - loop = asyncio.new_event_loop() - asyncio.set_event_loop(loop) - for device in self._detected_keyboards: - asyncio.ensure_future(self._read_events(device)) - loop.run_forever() + def run(self): + pass diff --git a/packages/modules/io_devices/dimm_kit/api.py b/packages/modules/io_devices/dimm_kit/api.py index 76ed494b4d..ce59b950c9 100644 --- a/packages/modules/io_devices/dimm_kit/api.py +++ b/packages/modules/io_devices/dimm_kit/api.py @@ -44,13 +44,13 @@ def read(): # analog inputs are configured as 0-5V (AI1-AI4) and 0-25mA (AI5-AI8) as default # the values are reported as integers in range of 0-1024 time.sleep(0.1) - analog_read = client.read_input_registers(0x00, [ModbusDataType.UINT_16]*8, unit=config.configuration.modbus_id) + analog_read = client.read_input_registers(0x00, [ModbusDataType.UINT_16]*8, device_id=config.configuration.modbus_id) analog_input = {getattr(AnalogInputMapping, f'AI{pin+1}').name: analog_read[pin] * 5 for pin in range(8)} time.sleep(0.1) - digital_input_read = client.read_coils(0x00, 8, unit=config.configuration.modbus_id) + digital_input_read = client.read_coils(0x00, 8, device_id=config.configuration.modbus_id) digital_input = {getattr(DigitalInputMapping, f'DI{pin+1}').name: digital_input_read[pin] for pin in range(8)} time.sleep(0.1) - digital_output_read = client.read_coils(0x10, 8, unit=config.configuration.modbus_id) + digital_output_read = client.read_coils(0x10, 8, device_id=config.configuration.modbus_id) digital_output = { getattr(DigitalOutputMapping, f'DO{pin+1}').name: digital_output_read[pin] for pin in range(8)} return IoState( @@ -63,13 +63,13 @@ def write(analog_output: Optional[Dict[str, int]], digital_output: Optional[Dict nonlocal client for i, value in digital_output.items(): client.write_single_coil(DigitalOutputMapping[i].value, 1 if value is True else 0, - unit=config.configuration.modbus_id) + device_id=config.configuration.modbus_id) def initializer(): nonlocal client client = ModbusTcpClient_(config.configuration.host, config.configuration.port) for output, value in config.output["digital"].items(): - client.write_single_coil(DigitalOutputMapping[output].value, value, unit=config.configuration.modbus_id) + client.write_single_coil(DigitalOutputMapping[output].value, value, device_id=config.configuration.modbus_id) return ConfigurableIo(config=config, component_reader=read, component_writer=write, initializer=initializer) diff --git a/packages/modules/smarthome/acthor/watt.py b/packages/modules/smarthome/acthor/watt.py index ec32becc8d..418763649e 100644 --- a/packages/modules/smarthome/acthor/watt.py +++ b/packages/modules/smarthome/acthor/watt.py @@ -4,7 +4,7 @@ import struct import codecs import logging -from pymodbus.client.sync import ModbusTcpClient +from pymodbus.client import ModbusTcpClient from smarthome.smartret import writeret log = logging.getLogger("acthor") @@ -72,10 +72,10 @@ client = ModbusTcpClient(ipadr, port=502) # start = 1000 -resp = client.read_holding_registers(start, 35, unit=1) +resp = client.read_holding_registers(start, count=35, device_id=1) # Test only # start = 3524 -# resp = client.read_input_registers(start, 35, unit=1) +# resp = client.read_input_registers(start, count=35, device_id=1) value1 = resp.registers[0] all = format(value1, '04x') aktpower = int(struct.unpack('>h', codecs.decode(all, 'hex'))[0]) @@ -163,7 +163,7 @@ (devicenumber, ipadr, atype, instpower, faktor)) # modbus write if modbuswrite == 1: - rq = client.write_register(1000, neupower, unit=1) + rq = client.write_register(1000, neupower, device_id=1) if count1 < 3: log.info("watt devicenr %d ipadr %s device written by modbus " % (devicenumber, ipadr)) diff --git a/packages/modules/smarthome/askoheat/watt.py b/packages/modules/smarthome/askoheat/watt.py index 6733ae8976..576c9d4984 100644 --- a/packages/modules/smarthome/askoheat/watt.py +++ b/packages/modules/smarthome/askoheat/watt.py @@ -3,7 +3,7 @@ import os import struct import codecs -from pymodbus.client.sync import ModbusTcpClient +from pymodbus.client import ModbusTcpClient import logging from smarthome.smartlog import initlog from smarthome.smartret import writeret @@ -32,7 +32,7 @@ start = 110 # test # start = 3522 -resp = client.read_input_registers(start, 1, unit=1) +resp = client.read_input_registers(start, count=1, device_id=1) value1 = resp.registers[0] all = format(value1, '04x') aktpower = int(struct.unpack('>h', codecs.decode(all, 'hex'))[0]) @@ -40,7 +40,7 @@ start = 638 # test # start = 3522 -resp = client.read_input_registers(start, 1, unit=1) +resp = client.read_input_registers(start, count=1, device_id=1) value1 = resp.registers[0] all = format(value1, '04x') temp0 = int(struct.unpack('>h', codecs.decode(all, 'hex'))[0]) @@ -95,7 +95,7 @@ (devicenumber, ipadr, neupower, pvmodus, modbuswrite)) # modbus write if modbuswrite == 1: - rq = client.write_register(201, neupower, unit=1) + rq = client.write_register(201, neupower, device_id=1) if count1 < 3: log.info("watt devicenr %d ipadr %s device written by modbus " % (devicenumber, ipadr)) diff --git a/packages/modules/smarthome/elwa/watt.py b/packages/modules/smarthome/elwa/watt.py index 4bfcc40418..7b5d413c85 100644 --- a/packages/modules/smarthome/elwa/watt.py +++ b/packages/modules/smarthome/elwa/watt.py @@ -3,7 +3,7 @@ import os import struct import codecs -from pymodbus.client.sync import ModbusTcpClient +from pymodbus.client import ModbusTcpClient import logging from smarthome.smartret import writeret @@ -31,9 +31,9 @@ client = ModbusTcpClient(ipadr, port=502) # Test only # # start = 3524 -# resp=client.read_input_registers(start,20,unit=1) +# resp=client.read_input_registers(start, count=20, device_id=1) start = 1000 -resp = client.read_holding_registers(start, 20, unit=1) +resp = client.read_holding_registers(start, count=20, device_id=1) value1 = resp.registers[0] all = format(value1, '04x') aktpower = int(struct.unpack('>h', codecs.decode(all, 'hex'))[0]) @@ -127,7 +127,7 @@ (devicenumber, ipadr, neupower, pvmodus, modbuswrite)) # modbus write if modbuswrite == 1: - rq = client.write_register(1000, neupower, unit=1) + rq = client.write_register(1000, neupower, device_id=1) if count1 < 3: log.info("watt devicenr %d ipadr %s device written by modbus " % (devicenumber, ipadr)) diff --git a/packages/modules/smarthome/idm/watt.py b/packages/modules/smarthome/idm/watt.py index bb4a1c8a01..b61d4fe2e3 100644 --- a/packages/modules/smarthome/idm/watt.py +++ b/packages/modules/smarthome/idm/watt.py @@ -3,9 +3,9 @@ import os import struct import logging -from pymodbus.constants import Endian -from pymodbus.payload import BinaryPayloadBuilder -from pymodbus.client.sync import ModbusTcpClient +from modules.common.pymodbus_compat import Endian +from modules.common.pymodbus_compat import BinaryPayloadBuilder +from pymodbus.client import ModbusTcpClient from smarthome.smartlog import initlog from smarthome.smartret import writeret devicenumber = int(sys.argv[1]) @@ -47,10 +47,10 @@ # prod start = 4122 if navvers == "2": - rr = client.read_input_registers(start, 2, unit=1) + rr = client.read_input_registers(start, count=2, device_id=1) else: - rr = client.read_holding_registers(start, 2, unit=1) -raw = struct.pack('>HH', rr.getRegister(1), rr.getRegister(0)) + rr = client.read_holding_registers(start, count=2, device_id=1) +raw = struct.pack('>HH', rr.registers[1], rr.registers[0]) lkw = float(struct.unpack('>f', raw)[0]) aktpower = int(lkw*1000) modbuswrite = 0 @@ -124,11 +124,11 @@ % (devicenumber, ipadr, neupower, pvmodus, modbuswrite)) # modbus write if modbuswrite == 1: - client.write_registers(74, regnew, unit=1) + client.write_registers(74, regnew, device_id=1) if count1 < 3: log.info("devicenr %d ipadr %s device written by modbus " % (devicenumber, ipadr)) - client.write_registers(78, pvwnew, unit=1) + client.write_registers(78, pvwnew, device_id=1) else: if pvmodus == 99: pvmodus = 0 diff --git a/packages/modules/smarthome/lambda_/off.py b/packages/modules/smarthome/lambda_/off.py index 526317742f..fe3bf75e74 100644 --- a/packages/modules/smarthome/lambda_/off.py +++ b/packages/modules/smarthome/lambda_/off.py @@ -5,7 +5,7 @@ import codecs import logging from smarthome.smartlog import initlog -from pymodbus.client.sync import ModbusTcpClient +from pymodbus.client import ModbusTcpClient bp = '/var/www/html/openWB/ramdisk/smarthome_device_' devicenumber = int(sys.argv[1]) ipadr = str(sys.argv[2]) @@ -22,7 +22,7 @@ % (devicenumber, ipadr, uberschuss)) client = ModbusTcpClient(ipadr, port=502) start = 103 -resp = client.read_holding_registers(start, 2, unit=1) +resp = client.read_holding_registers(start, count=2, device_id=1) value1 = resp.registers[0] all = format(value1, '04x') aktpower = int(struct.unpack('>h', codecs.decode(all, 'hex'))[0]) diff --git a/packages/modules/smarthome/lambda_/on.py b/packages/modules/smarthome/lambda_/on.py index d74abad74a..c50d9e0985 100644 --- a/packages/modules/smarthome/lambda_/on.py +++ b/packages/modules/smarthome/lambda_/on.py @@ -4,7 +4,7 @@ import codecs import logging from smarthome.smartlog import initlog -from pymodbus.client.sync import ModbusTcpClient +from pymodbus.client import ModbusTcpClient bp = '/var/www/html/openWB/ramdisk/smarthome_device_' devicenumber = int(sys.argv[1]) ipadr = str(sys.argv[2]) @@ -23,7 +23,7 @@ % (devicenumber, ipadr, uberschuss)) client = ModbusTcpClient(ipadr, port=502) start = 103 -resp = client.read_holding_registers(start, 2, unit=1) +resp = client.read_holding_registers(start, count=2, device_id=1) value1 = resp.registers[0] all = format(value1, '04x') aktpower = int(struct.unpack('>h', codecs.decode(all, 'hex'))[0]) diff --git a/packages/modules/smarthome/lambda_/watt.py b/packages/modules/smarthome/lambda_/watt.py index a6ad5c641b..9ecd92f431 100644 --- a/packages/modules/smarthome/lambda_/watt.py +++ b/packages/modules/smarthome/lambda_/watt.py @@ -5,9 +5,9 @@ import struct import codecs import logging -from pymodbus.payload import Endian -from pymodbus.payload import BinaryPayloadBuilder -from pymodbus.client.sync import ModbusTcpClient +from modules.common.pymodbus_compat import Endian +from modules.common.pymodbus_compat import BinaryPayloadBuilder +from pymodbus.client import ModbusTcpClient from smarthome.smartlog import initlog from smarthome.smartret import writeret named_tuple = time.localtime() # getstruct_time @@ -53,7 +53,7 @@ # aktuelle Leistung lesen with ModbusTcpClient(ipadr, port=502) as client: start = 103 - resp = client.read_holding_registers(start, 2, unit=1) + resp = client.read_holding_registers(start, count=2, device_id=1) # value1 = resp.registers[0] all = format(value1, '04x') @@ -104,7 +104,7 @@ builder = BinaryPayloadBuilder(byteorder=Endian.Big, wordorder=Endian.Little) builder.add_16bit_int(neupower) pay = builder.to_registers() - client.write_registers(102, [pay[0]], unit=1) + client.write_registers(102, [pay[0]], device_id=1) if count1 < 3: log.info(' %d ipadr %s written %6d %#4X' % (devicenumber, ipadr, pay[0], pay[0])) diff --git a/packages/modules/smarthome/mqtt/off.py b/packages/modules/smarthome/mqtt/off.py index edb8cc3953..4faf96844d 100644 --- a/packages/modules/smarthome/mqtt/off.py +++ b/packages/modules/smarthome/mqtt/off.py @@ -16,7 +16,7 @@ def on_message(client, userdata, msg) -> None: devicenumber = str(sys.argv[1]) ipadr = str(sys.argv[2]) uberschuss = int(sys.argv[3]) -client = mqtt.Client("openWB-mqttsmarthomecust") +client = mqtt.Client(mqtt.CallbackAPIVersion.VERSION1, client_id="openWB-mqttsmarthomecust") client.on_connect = on_connect client.on_message = on_message startTime = time.time() diff --git a/packages/modules/smarthome/mqtt/on.py b/packages/modules/smarthome/mqtt/on.py index aabd8d2299..7794498fbb 100644 --- a/packages/modules/smarthome/mqtt/on.py +++ b/packages/modules/smarthome/mqtt/on.py @@ -16,7 +16,7 @@ def on_message(client, userdata, msg) -> None: devicenumber = str(sys.argv[1]) ipadr = str(sys.argv[2]) uberschuss = int(sys.argv[3]) -client = mqtt.Client("openWB-mqttsmarthomecust") +client = mqtt.Client(mqtt.CallbackAPIVersion.VERSION1, client_id="openWB-mqttsmarthomecust") client.on_connect = on_connect client.on_message = on_message startTime = time.time() diff --git a/packages/modules/smarthome/mqtt/watt.py b/packages/modules/smarthome/mqtt/watt.py index 304b000423..44fd4eed70 100644 --- a/packages/modules/smarthome/mqtt/watt.py +++ b/packages/modules/smarthome/mqtt/watt.py @@ -50,7 +50,7 @@ def on_message(client, userdata, msg) -> None: devicenumber = int(sys.argv[1]) ipadr = str(sys.argv[2]) uberschuss = int(sys.argv[3]) -client = mqtt.Client("openWB-mqttsmarthomecust" + str(devicenumber)) +client = mqtt.Client(mqtt.CallbackAPIVersion.VERSION1, client_id="openWB-mqttsmarthomecust" + str(devicenumber)) client.on_connect = on_connect client.on_message = on_message startTime = time.time() diff --git a/packages/modules/smarthome/nibe/watt.py b/packages/modules/smarthome/nibe/watt.py index d723965d22..75fcff6731 100644 --- a/packages/modules/smarthome/nibe/watt.py +++ b/packages/modules/smarthome/nibe/watt.py @@ -1,7 +1,7 @@ #!/usr/bin/python3 import sys import json -from pymodbus.client.sync import ModbusTcpClient +from pymodbus.client import ModbusTcpClient # get variables from arguments devicenumber = str(sys.argv[1]) # SmartHome device number @@ -18,10 +18,10 @@ CurrentPowerRegisterAddress = 2166 # register for current power reading # need to specify framer to enable RTUoverTCP -client = ModbusTcpClient(SERVER_HOST, SERVER_PORT) +client = ModbusTcpClient(SERVER_HOST, port=SERVER_PORT) # Aktueller Verbrauch -resp = client.read_input_registers(CurrentPowerRegisterAddress, 1, unit=1) +resp = client.read_input_registers(CurrentPowerRegisterAddress, count=1, device_id=1) if resp and hasattr(resp, "registers"): CurrentPower = resp.registers[0] # Get the first register value diff --git a/packages/modules/smarthome/nxdacxx/off.py b/packages/modules/smarthome/nxdacxx/off.py index e2ef124ac9..dc3b23cffd 100644 --- a/packages/modules/smarthome/nxdacxx/off.py +++ b/packages/modules/smarthome/nxdacxx/off.py @@ -2,7 +2,7 @@ import sys import os import logging -from pymodbus.client.sync import ModbusTcpClient +from pymodbus.client import ModbusTcpClient log = logging.getLogger("DAC") bp = '/var/www/html/openWB/ramdisk/smarthome_device_' @@ -19,7 +19,7 @@ if dactyp == 2: client = ModbusTcpClient(ipadr, port=port) # DO1 ausschalten um SGready zu sperren - rq = client.write_coil(0, False, unit=1) + rq = client.write_coil(0, False, device_id=1) pvmodus = 0 if os.path.isfile(file_stringpv): with open(file_stringpv, 'r') as f: diff --git a/packages/modules/smarthome/nxdacxx/on.py b/packages/modules/smarthome/nxdacxx/on.py index 2d9318c690..531945040b 100644 --- a/packages/modules/smarthome/nxdacxx/on.py +++ b/packages/modules/smarthome/nxdacxx/on.py @@ -1,7 +1,7 @@ #!/usr/bin/python3 import sys import logging -from pymodbus.client.sync import ModbusTcpClient +from pymodbus.client import ModbusTcpClient log = logging.getLogger("DAC") bp = '/var/www/html/openWB/ramdisk/smarthome_device_' @@ -18,7 +18,7 @@ if dactyp == 2: client = ModbusTcpClient(ipadr, port=port) # DO1 einschalten um SGready zu aktivieren - rq = client.write_coil(0, True, unit=1) + rq = client.write_coil(0, True, device_id=1) pvmodus = 1 with open(file_stringpv, 'w') as f: f.write(str(pvmodus)) diff --git a/packages/modules/smarthome/nxdacxx/watt.py b/packages/modules/smarthome/nxdacxx/watt.py index d4fadbb9c7..62a695bbf5 100644 --- a/packages/modules/smarthome/nxdacxx/watt.py +++ b/packages/modules/smarthome/nxdacxx/watt.py @@ -1,7 +1,7 @@ #!/usr/bin/python3 import sys import os -from pymodbus.client.sync import ModbusTcpClient +from pymodbus.client import ModbusTcpClient import logging from smarthome.smartret import writeret @@ -86,23 +86,23 @@ if dactyp == 0: # 10 Volts are 1000 ausgabe = int((neupower * 1000) / maxpower) - rq = client.write_register(1, ausgabe, unit=1) + rq = client.write_register(1, ausgabe, device_id=1) elif dactyp == 1: # 10 Volts are 4000 ausgabe = int((neupower * 4000) / maxpower) - rq = client.write_register(0x01f4, ausgabe, unit=1) + rq = client.write_register(0x01f4, ausgabe, device_id=1) elif dactyp == 2: ausgabe = int((neupower * 4095) / maxpower) if ausgabe < 370: ausgabe = 370 # ausgabe nicht kleiner 0,9V sonst Leistungsregelung der WP aus - rq = client.write_register(0, ausgabe, unit=1) + rq = client.write_register(0, ausgabe, device_id=1) elif dactyp == 3: ausgabe = int(((neupower * (4095-820)) / maxpower)+820) if ausgabe <= 820: ausgabe = 0 # ausgabe nicht kleiner 4ma sonst Leistungsregelung der WP aus - rq = client.write_register(0x01f4, ausgabe, unit=1) + rq = client.write_register(0x01f4, ausgabe, device_id=1) else: pass if count1 < 3: diff --git a/packages/modules/smarthome/ratiotherm/watt.py b/packages/modules/smarthome/ratiotherm/watt.py index e993f7d7bd..018af396a1 100644 --- a/packages/modules/smarthome/ratiotherm/watt.py +++ b/packages/modules/smarthome/ratiotherm/watt.py @@ -1,8 +1,8 @@ #!/usr/bin/python3 import sys import os -from pymodbus.payload import BinaryPayloadBuilder, Endian -from pymodbus.client.sync import ModbusTcpClient +from modules.common.pymodbus_compat import BinaryPayloadBuilder, Endian +from pymodbus.client import ModbusTcpClient import logging from smarthome.smartret import writeret @@ -82,7 +82,7 @@ builder.add_16bit_int(neupower) pay = builder.to_registers() client = ModbusTcpClient(ipadr, port=502) - client.write_register(100, pay[0], unit=1) + client.write_register(100, pay[0], device_id=1) if count1 < 3: log.info(" watt devicenr %d ipadr %s written %6d %#4X" % (devicenumber, ipadr, pay[0], pay[0])) diff --git a/packages/modules/smarthome/stiebel/off.py b/packages/modules/smarthome/stiebel/off.py index 2c726b1dec..067b491cf2 100644 --- a/packages/modules/smarthome/stiebel/off.py +++ b/packages/modules/smarthome/stiebel/off.py @@ -1,6 +1,6 @@ #!/usr/bin/python3 import sys -from pymodbus.client.sync import ModbusTcpClient +from pymodbus.client import ModbusTcpClient import logging log = logging.getLogger("stiebel") @@ -12,7 +12,7 @@ log.info('off devicenr %d ipadr %s ueberschuss %6d try to connect (modbus)' % (devicenumber, ipadr, uberschuss)) client = ModbusTcpClient(ipadr, port=502) # deactivate switch one (manual 4002) -rq = client.write_register(4001, 0, unit=1) +rq = client.write_register(4001, 0, device_id=1) log.info('off devicenr %d ipadr %s ' % (devicenumber, ipadr)) pvmodus = 0 with open(file_stringpv, 'w') as f: diff --git a/packages/modules/smarthome/stiebel/on.py b/packages/modules/smarthome/stiebel/on.py index 82c9a9d6d0..65af4d6b75 100644 --- a/packages/modules/smarthome/stiebel/on.py +++ b/packages/modules/smarthome/stiebel/on.py @@ -1,6 +1,6 @@ #!/usr/bin/python3 import sys -from pymodbus.client.sync import ModbusTcpClient +from pymodbus.client import ModbusTcpClient import logging log = logging.getLogger("stiebel") @@ -12,7 +12,7 @@ log.info('on devicenr %d ipadr %s ueberschuss %6d try to connect (modbus)' % (devicenumber, ipadr, uberschuss)) client = ModbusTcpClient(ipadr, port=502) # activate switch one (manual 4002) -rq = client.write_register(4001, 1, unit=1) +rq = client.write_register(4001, 1, device_id=1) log.info('on devicenr %d ipadr %s ' % (devicenumber, ipadr)) with open(file_stringpv, 'w') as f: f.write(str(1)) diff --git a/packages/modules/smarthome/vampair/off.py b/packages/modules/smarthome/vampair/off.py index 3b05b8b520..341b496cce 100644 --- a/packages/modules/smarthome/vampair/off.py +++ b/packages/modules/smarthome/vampair/off.py @@ -4,7 +4,7 @@ import time import struct import codecs -from pymodbus.client.sync import ModbusTcpClient +from pymodbus.client import ModbusTcpClient import logging log = logging.getLogger(__name__) @@ -29,7 +29,7 @@ % (time_string, devicenumber, ipadr, uberschuss), file=f) client = ModbusTcpClient(ipadr, port=502) start = 2322 -resp = client.read_input_registers(start, 2, unit=1) +resp = client.read_input_registers(start, count=2, device_id=1) value1 = resp.registers[0] all = format(value1, '04x') aktpower = int(struct.unpack('>h', codecs.decode(all, 'hex'))[0]) diff --git a/packages/modules/smarthome/vampair/on.py b/packages/modules/smarthome/vampair/on.py index b9b851342c..f3625c7a6b 100644 --- a/packages/modules/smarthome/vampair/on.py +++ b/packages/modules/smarthome/vampair/on.py @@ -4,7 +4,7 @@ import time import struct import codecs -from pymodbus.client.sync import ModbusTcpClient +from pymodbus.client import ModbusTcpClient import logging log = logging.getLogger(__name__) @@ -31,7 +31,7 @@ % (time_string, devicenumber, ipadr, uberschuss), file=f) client = ModbusTcpClient(ipadr, port=502) start = 2322 -resp = client.read_input_registers(start, 2, unit=1) +resp = client.read_input_registers(start, count=2, device_id=1) value1 = resp.registers[0] all = format(value1, '04x') aktpower = int(struct.unpack('>h', codecs.decode(all, 'hex'))[0]) diff --git a/packages/modules/smarthome/vampair/watt.py b/packages/modules/smarthome/vampair/watt.py index 9607ec18d8..d2b9effe8d 100644 --- a/packages/modules/smarthome/vampair/watt.py +++ b/packages/modules/smarthome/vampair/watt.py @@ -5,7 +5,7 @@ import json import struct import codecs -from pymodbus.client.sync import ModbusTcpClient +from pymodbus.client import ModbusTcpClient import logging log = logging.getLogger(__name__) @@ -48,7 +48,7 @@ # aktuelle Leistung lesen client = ModbusTcpClient(ipadr, port=502) start = 2322 - resp = client.read_input_registers(start, 2, unit=1) + resp = client.read_input_registers(start, count=2, device_id=1) value1 = resp.registers[0] all = format(value1, '04x') aktpower = int(struct.unpack('>h', codecs.decode(all, 'hex'))[0]) @@ -91,7 +91,7 @@ modbuswrite), file=f) # modbus write if modbuswrite == 1: - client.write_registers(33409, [neupower], unit=1) + client.write_registers(33409, [neupower], device_id=1) if count1 < 3: with open(file_string, 'a') as f: log.debug('%s devicenr %s ipadr %s device written by modbus ' % diff --git a/packages/modules/smarthome/viessmann/off.py b/packages/modules/smarthome/viessmann/off.py index 5714df4c39..4f1c447479 100644 --- a/packages/modules/smarthome/viessmann/off.py +++ b/packages/modules/smarthome/viessmann/off.py @@ -1,6 +1,6 @@ #!/usr/bin/python3 import sys -from pymodbus.client.sync import ModbusTcpClient +from pymodbus.client import ModbusTcpClient import logging log = logging.getLogger(__name__) @@ -21,7 +21,7 @@ log.debug(f"[Viessmann {devicenumber}] devicenr {devicenumber} ipadr {ipadr} " f"ueberschuss {uberschuss:6d} try to connect (modbus)") client = ModbusTcpClient(ipadr, port=502) -rq = client.write_coil(16, False, unit=1) +rq = client.write_coil(16, False, device_id=1) log.debug(f"[Viessmann {devicenumber}] Modbus write_coil response: {rq}") client.close() log.debug( diff --git a/packages/modules/smarthome/viessmann/on.py b/packages/modules/smarthome/viessmann/on.py index e44ac8692a..c404333666 100644 --- a/packages/modules/smarthome/viessmann/on.py +++ b/packages/modules/smarthome/viessmann/on.py @@ -1,6 +1,6 @@ #!/usr/bin/python3 import sys -from pymodbus.client.sync import ModbusTcpClient +from pymodbus.client import ModbusTcpClient import logging log = logging.getLogger(__name__) @@ -24,7 +24,7 @@ f"[Viessmann {devicenumber}] devicenr {devicenumber} ipadr {ipadr} " f"ueberschuss {uberschuss:6d} try to connect (modbus)") client = ModbusTcpClient(ipadr, port=502) -rq = client.write_coil(16, True, unit=1) +rq = client.write_coil(16, True, device_id=1) log.debug(f"[Viessmann {devicenumber}] Modbus write_coil response: {rq}") client.close() log.debug( diff --git a/packages/modules/smarthome/we514/watt.py b/packages/modules/smarthome/we514/watt.py index f9d3afe00e..833a8b5005 100644 --- a/packages/modules/smarthome/we514/watt.py +++ b/packages/modules/smarthome/we514/watt.py @@ -1,8 +1,8 @@ #!/usr/bin/python3 import sys import json -from pymodbus.transaction import ModbusRtuFramer -from pymodbus.client.sync import ModbusTcpClient +from pymodbus.framer import FramerType +from pymodbus.client import ModbusTcpClient # get variables from arguments devicenumber = str(sys.argv[1]) # SmartHome device number @@ -23,14 +23,14 @@ # need to specify framer to enable RTUoverTCP -client = ModbusTcpClient(SERVER_HOST, SERVER_PORT, framer=ModbusRtuFramer) +client = ModbusTcpClient(SERVER_HOST, port=SERVER_PORT, framer=FramerType.RTU) # KWH Total Import -resp = client.read_holding_registers(TotalEnergyRegisterAddress, 1, unit=MODBUS_DEVICEID) +resp = client.read_holding_registers(TotalEnergyRegisterAddress, count=1, device_id=MODBUS_DEVICEID) TotalEnergy = int(resp.registers[0]) * 10 # Value is in 0.01kWh, need to convert to Wh # Aktueller Verbrauch -resp = client.read_holding_registers(CurrentPowerRegisterAddress, 1, unit=MODBUS_DEVICEID) +resp = client.read_holding_registers(CurrentPowerRegisterAddress, count=1, device_id=MODBUS_DEVICEID) CurrentPower = int(resp.registers[0]) answer = {"power": CurrentPower, "powerc": TotalEnergy} diff --git a/packages/modules/vehicles/ovms/api.py b/packages/modules/vehicles/ovms/api.py index cdd530d5c0..ac2c1a80a6 100755 --- a/packages/modules/vehicles/ovms/api.py +++ b/packages/modules/vehicles/ovms/api.py @@ -4,7 +4,7 @@ from typing import Union from asyncio import new_event_loop, set_event_loop from time import mktime -from datetime import datetime +from datetime import datetime, timezone from json import loads, dumps from modules.vehicles.ovms.config import OVMS from helpermodules.pub import Pub @@ -34,7 +34,7 @@ def write_config(topic: str, config: dict): def utc2local(utc): epoch = mktime(utc.timetuple()) - offset = datetime.fromtimestamp(epoch) - datetime.utcfromtimestamp(epoch) + offset = datetime.fromtimestamp(epoch) - datetime.fromtimestamp(epoch, tz=timezone.utc).replace(tzinfo=None) return utc + offset diff --git a/packages/modules/vehicles/tronity/api.py b/packages/modules/vehicles/tronity/api.py index 8696a12a05..590bbe478e 100644 --- a/packages/modules/vehicles/tronity/api.py +++ b/packages/modules/vehicles/tronity/api.py @@ -8,7 +8,7 @@ from modules.common.abstract_vehicle import VehicleUpdateData from modules.vehicles.tronity.config import TronityVehicleSocConfiguration, TronityVehicleSoc from modules.common.component_state import CarState -from datetime import datetime +from datetime import datetime, timezone log = logging.getLogger(__name__) @@ -29,7 +29,7 @@ def is_token_valid(access_token: str) -> bool: log.debug("Found Token: %s", access_token) decoded_data = jwt.decode(jwt=access_token, verify=False, algorithms=['HS256'], options={"verify_signature": False}) - if datetime.utcfromtimestamp(decoded_data['exp']) < datetime.utcnow(): + if datetime.fromtimestamp(decoded_data['exp'], tz=timezone.utc) < datetime.now(timezone.utc): log.debug("Token expired: %s", decoded_data) return False else: diff --git a/packages/modules/vehicles/vwgroup/vwgroup.py b/packages/modules/vehicles/vwgroup/vwgroup.py index 35a92d0d94..d857bceddf 100644 --- a/packages/modules/vehicles/vwgroup/vwgroup.py +++ b/packages/modules/vehicles/vwgroup/vwgroup.py @@ -1,6 +1,6 @@ #!/usr/bin/env python3 -from datetime import datetime +from datetime import datetime, timezone from json import dumps import logging from time import mktime, time @@ -32,7 +32,7 @@ def __init__(self, conf, vehicle): # convert utc timestamp to local time def utc2local(self, utc): epoch = mktime(utc.timetuple()) - offset = datetime.fromtimestamp(epoch) - datetime.utcfromtimestamp(epoch) + offset = datetime.fromtimestamp(epoch) - datetime.fromtimestamp(epoch, tz=timezone.utc).replace(tzinfo=None) return utc + offset # async method, called from sync fetch_soc, required because libvwid/libskoda expect async environment diff --git a/packages/smarthome/smartcommon.py b/packages/smarthome/smartcommon.py index 7b6d958a41..397e99ac49 100644 --- a/packages/smarthome/smartcommon.py +++ b/packages/smarthome/smartcommon.py @@ -205,7 +205,7 @@ def pub(client: mqtt.Client, key: str, value: str) -> None: def sendmq(mqtt_input: Dict[str, str]) -> None: global mqtt_cache - client = mqtt.Client("openWB-SmartHome-bulkpublisher-" + str(os.getpid())) + client = mqtt.Client(mqtt.CallbackAPIVersion.VERSION1, client_id="openWB-SmartHome-bulkpublisher-" + str(os.getpid())) client.connect("localhost", mqttport) for key, value in mqtt_input.items(): valueold = mqtt_cache.get(key, 'not in cache') @@ -233,7 +233,7 @@ def update_devices() -> None: global parammqtt global mydevices global mqtt_cache - client = mqtt.Client("openWB-SmartHome-bulkpublisher-" + str(os.getpid())) + client = mqtt.Client(mqtt.CallbackAPIVersion.VERSION1, client_id="openWB-SmartHome-bulkpublisher-" + str(os.getpid())) client.connect("localhost", mqttport) # statische daten einschaltgruppe Sbase.ausdevices = 0 @@ -347,7 +347,7 @@ def readmq() -> None: with open(bp+'/ramdisk/smartparam.sh', 'w') as f: print('%s' % ('#!/bin/bash'), file=f) parammqtt = [] - client = mqtt.Client("openWB-mqttsmarthome") + client = mqtt.Client(mqtt.CallbackAPIVersion.VERSION1, client_id="openWB-mqttsmarthome") client.on_connect = on_connect client.on_message = on_message startTime = time.time() diff --git a/packages/tools/modbus_finder.py b/packages/tools/modbus_finder.py index a2de5e2016..d167f5634b 100644 --- a/packages/tools/modbus_finder.py +++ b/packages/tools/modbus_finder.py @@ -3,7 +3,7 @@ from typing import Callable import pymodbus -from pymodbus.constants import Endian +from modules.common.pymodbus_compat import Endian import sys sys.path.append("/var/www/html/openWB/packages") @@ -53,12 +53,12 @@ def try_read(function: Callable, **kwargs) -> str: print("Address;INT_16;UINT_16;INT_32;UINT_32") for address in range(start, end): - resp_INT_16 = try_read(function, address=address, types=modbus.ModbusDataType.INT_16, unit=slave_id) - resp_UINT_16 = try_read(function, address=address, types=modbus.ModbusDataType.UINT_16, unit=slave_id) + resp_INT_16 = try_read(function, address=address, types=modbus.ModbusDataType.INT_16, device_id=slave_id) + resp_UINT_16 = try_read(function, address=address, types=modbus.ModbusDataType.UINT_16, device_id=slave_id) resp_INT_32 = try_read(function, address=address, types=modbus.ModbusDataType.INT_32, wordorder=Endian.Little, - unit=slave_id) + device_id=slave_id) resp_UINT_32 = try_read(function, address=address, types=modbus.ModbusDataType.UINT_32, wordorder=Endian.Little, - unit=slave_id) + device_id=slave_id) print(f"{address};{resp_INT_16};{resp_UINT_16};{resp_INT_32};{resp_UINT_32}") except Exception as e: print("Exception " + str(e)) diff --git a/packages/tools/modbus_tester.py b/packages/tools/modbus_tester.py index f32a993cc2..4cb85e6ef7 100644 --- a/packages/tools/modbus_tester.py +++ b/packages/tools/modbus_tester.py @@ -30,14 +30,14 @@ client = modbus.ModbusTcpClient_(host, port=port) if func == 4: if length > 1: - resp = client.read_input_registers(start, [modbus.ModbusDataType[data_type]]*length, unit=slave_id) + resp = client.read_input_registers(start, [modbus.ModbusDataType[data_type]]*length, device_id=slave_id) else: - resp = client.read_input_registers(start, modbus.ModbusDataType[data_type], unit=slave_id) + resp = client.read_input_registers(start, modbus.ModbusDataType[data_type], device_id=slave_id) elif func == 3: if length > 1: - resp = client.read_holding_registers(start, [modbus.ModbusDataType[data_type]]*length, unit=slave_id) + resp = client.read_holding_registers(start, [modbus.ModbusDataType[data_type]]*length, device_id=slave_id) else: - resp = client.read_holding_registers(start, modbus.ModbusDataType[data_type], unit=slave_id) + resp = client.read_holding_registers(start, modbus.ModbusDataType[data_type], device_id=slave_id) else: print("unsupported function code: " + str(func)) exit(1) diff --git a/requirements-dev.txt b/requirements-dev.txt new file mode 100644 index 0000000000..68aa87452a --- /dev/null +++ b/requirements-dev.txt @@ -0,0 +1,2 @@ +pytest>=9.0.3 +requests-mock>=1.12.1 diff --git a/requirements.txt b/requirements.txt index d3f1163050..dd1619fd4d 100644 --- a/requirements.txt +++ b/requirements.txt @@ -1,27 +1,23 @@ -# don't update python distribution packages in here -typing-extensions==4.13.2 -jq==1.1.3 -paho_mqtt==1.6.1 -pymodbus==2.5.2 -pytest==6.2.5 -requests_mock==1.9.3 -lxml==4.9.1 -aiohttp==3.13.4 -schedule==1.1.0 -PyJWT==2.12.0 -bs4==0.0.1 -pkce==1.0.3 -evdev==1.5.0 -cryptography==46.0.6 -msal==1.33.0 -python-dateutil==2.8.2 -umodbus==1.0.4 -pysmb==1.2.9.1 -pytz==2023.3.post1 -grpcio==1.60.1 -protobuf==5.29.6 -ocpp==1.0.0 -websockets==12.0 -pycarwings3==0.7.14 -asyncio==3.4.3 -passlib==1.7.4 +typing-extensions>=4.15.0 +jq>=1.11.0 +paho-mqtt>=2.1.0 +pymodbus>=3.13.0 +lxml>=6.1.0 +aiohttp>=3.13.5 +schedule>=1.2.2 +PyJWT>=2.12.1 +bs4>=0.0.2 +pkce>=1.0.3 +cryptography>=47.0.0 +msal>=1.36.0 +python-dateutil>=2.9.0 +umodbus>=1.0.4 +pysmb>=1.2.13 +pytz>=2026.1 +grpcio>=1.80.0 +protobuf>=7.34.1 +ocpp>=2.1.0 +websockets>=16.0 +pycarwings3>=0.7.14 +passlib>=1.7.4 +evdev>=1.9.3 diff --git a/runs/atreboot.sh b/runs/atreboot.sh index 8166249e82..dd878c10ef 100755 --- a/runs/atreboot.sh +++ b/runs/atreboot.sh @@ -1,5 +1,7 @@ #!/bin/bash OPENWBBASEDIR=$(cd "$(dirname "${BASH_SOURCE[0]}")/.." && pwd) +source "${OPENWBBASEDIR}/runs/platform_detect.sh" +detect_platform hasInet=0 # setup log file @@ -8,19 +10,6 @@ touch "$LOGFILE" chmod 666 "$LOGFILE" { - versionMatch() { - file=$1 - target=$2 - currentVersion=$(grep -o "openwb-version:[0-9]\+" "$file" | grep -o "[0-9]\+$") - installedVersion=$(sudo grep -o "openwb-version:[0-9]\+" "$target" | grep -o "[0-9]\+$") - # echo "$currentVersion == $installedVersion ?" - if ((currentVersion == installedVersion)); then - return 0 - else - return 1 - fi - } - if ! id -u openwb >/dev/null 2>&1; then echo "user 'openwb' missing" echo "starting upgrade script..." @@ -72,18 +61,22 @@ chmod 666 "$LOGFILE" boot_config_source="${OPENWBBASEDIR}/data/config/boot_config.txt" boot_config_target="/boot/config.txt" - echo "checking init in $boot_config_target..." - if versionMatch "$boot_config_source" "$boot_config_target"; then - echo "already up to date" + if [ "$PLATFORM_IS_RPI" = true ]; then + echo "checking init in $boot_config_target..." + if versionMatch "$boot_config_source" "$boot_config_target"; then + echo "already up to date" + else + echo "openwb section not found or outdated" + pattern_begin=$(grep -m 1 '#' "$boot_config_source") + pattern_end=$(grep '#' "$boot_config_source" | tail -n 1) + sudo sed -i "/$pattern_begin/,/$pattern_end/d" "$boot_config_target" + echo "adding init to $boot_config_target..." + sudo tee -a "$boot_config_target" <"$boot_config_source" >/dev/null + echo "done" + sudo reboot now + fi else - echo "openwb section not found or outdated" - pattern_begin=$(grep -m 1 '#' "$boot_config_source") - pattern_end=$(grep '#' "$boot_config_source" | tail -n 1) - sudo sed -i "/$pattern_begin/,/$pattern_end/d" "$boot_config_target" - echo "adding init to $boot_config_target..." - sudo tee -a "$boot_config_target" <"$boot_config_source" >/dev/null - echo "done" - sudo reboot now + echo "not a Raspberry Pi, skipping boot config" fi ramdisk_config_source="${OPENWBBASEDIR}/data/config/ramdisk_config.txt" @@ -126,14 +119,14 @@ chmod 666 "$LOGFILE" echo -n "Final group membership: " groups openwb - # allow apache to restart some services - echo "Apache service restart permissions..." - if versionMatch "${OPENWBBASEDIR}/data/config/sudoers/apache2" "/etc/sudoers.d/apache2"; then - echo "apache2 sudoers already up to date" + # allow caddy to restart some services + echo "Caddy service restart permissions..." + if versionMatch "${OPENWBBASEDIR}/data/config/sudoers/caddy" "/etc/sudoers.d/caddy"; then + echo "caddy sudoers already up to date" else - echo "updating apache2 sudoers" - sudo cp "${OPENWBBASEDIR}/data/config/sudoers/apache2" "/etc/sudoers.d/apache2" - sudo chmod 440 /etc/sudoers.d/apache2 + echo "updating caddy sudoers" + sudo cp "${OPENWBBASEDIR}/data/config/sudoers/caddy" "/etc/sudoers.d/caddy" + sudo chmod 440 /etc/sudoers.d/caddy fi # network setup @@ -148,6 +141,35 @@ chmod 666 "$LOGFILE" echo "#### continue anyway..." fi + # run stack upgrade (Python, Caddy, PHP-FPM, Chrony, etc.) + # idempotent - only changes what's needed + echo "Checking for stack upgrades..." + if ((hasInet == 1)); then + sudo "${OPENWBBASEDIR}/runs/upgrade_stack.sh" + else + echo "no internet connection, skipping stack upgrade" + fi + + # chrony NTP setup + echo "NTP time synchronization..." + if versionMatch "${OPENWBBASEDIR}/data/config/chrony/chrony.conf" "/etc/chrony/chrony.conf"; then + echo "chrony config already up to date" + else + echo "configuring chrony NTP..." + sudo systemctl stop systemd-timesyncd 2>/dev/null || true + sudo systemctl disable systemd-timesyncd 2>/dev/null || true + sudo cp "${OPENWBBASEDIR}/data/config/chrony/chrony.conf" /etc/chrony/chrony.conf + sudo systemctl enable chrony + sudo systemctl restart chrony + echo "chrony configured" + fi + + # MOTD setup + echo "MOTD setup..." + sudo cp "${OPENWBBASEDIR}/data/config/profile.d/99-openwb-motd.sh" /etc/profile.d/99-openwb-motd.sh + sudo chmod 755 /etc/profile.d/99-openwb-motd.sh + echo "done" + # tune apt configuration and install required packages if [ -d "/etc/apt/apt.conf.d" ]; then if versionMatch "${OPENWBBASEDIR}/data/config/apt/99openwb" "/etc/apt/apt.conf.d/99openwb"; then @@ -160,8 +182,8 @@ chmod 666 "$LOGFILE" echo "path '/etc/apt/apt.conf.d' is missing! unsupported system!" fi if ((hasInet == 1)); then - # remove urllib3 version to avoid conflicts - pip uninstall urllib3 -y + echo "ensuring python virtual environment..." + ensure_venv "$PLATFORM_VENV" "${OPENWBBASEDIR}/runs/install_packages.sh" else echo "no internet connection, skipping package installation" @@ -241,7 +263,7 @@ chmod 666 "$LOGFILE" # detect connected displays # set default to "true" as fallback if "tvservice" is missing displayDetected="true" - if which tvservice >/dev/null; then + if [ "$PLATFORM_IS_RPI" = true ] && which tvservice >/dev/null; then echo "detected 'tvservice', query for connected displays" output=$(tvservice -l) echo "$output" @@ -251,8 +273,11 @@ chmod 666 "$LOGFILE" else echo "detected HDMI or LCD display(s)" fi + elif [ "$PLATFORM_VIRT" != "none" ]; then + echo "virtualized environment detected, no physical display" + displayDetected="false" else - echo "'tvservice' not found, assuming a display is present" + echo "no tvservice, assuming a display is present" fi echo "displayDetected: $displayDetected" forceDisplaySetup=0 @@ -303,8 +328,8 @@ chmod 666 "$LOGFILE" "${OPENWBBASEDIR}/runs/update_local_display.sh" $forceDisplaySetup fi - # check apache configuration - "${OPENWBBASEDIR}/runs/setup_apache2.sh" + # check caddy configuration + "${OPENWBBASEDIR}/runs/setup_caddy.sh" # check for mosquitto configuration "${OPENWBBASEDIR}/runs/setup_mosquitto.sh" 1 @@ -316,12 +341,12 @@ chmod 666 "$LOGFILE" # check for python dependencies if ((hasInet == 1)); then - echo "install required python packages with 'pip3'..." - if pip3 install --only-binary :all: -r "${OPENWBBASEDIR}/requirements.txt"; then + echo "install required python packages into venv..." + if $PLATFORM_VENV/bin/python3 -m pip install --only-binary :all: -r "${OPENWBBASEDIR}/requirements.txt"; then echo "done" else echo "failed!" - message="Bei der Installation der benötigten Python-Bibliotheken ist ein Fehler aufgetreten! Bitte die Logdateien prüfen." + message="Bei der Installation der benoetigten Python-Bibliotheken ist ein Fehler aufgetreten! Bitte die Logdateien pruefen." payload=$(printf '{"source": "system", "type": "danger", "message": "%s", "timestamp": %d}' "$message" "$(date +"%s")") mosquitto_pub -p 1886 -t "openWB/system/messages/$(date +"%s%3N")" -r -m "$payload" fi @@ -340,8 +365,8 @@ chmod 666 "$LOGFILE" echo "no internet connection, skipping version update" fi - # set restore dir permissions to allow file upload for apache - sudo chgrp -R www-data "${OPENWBBASEDIR}/data/restore/." "${OPENWBBASEDIR}/data/data_migration/." + # set restore dir permissions to allow file upload for caddy + sudo chgrp -R caddy "${OPENWBBASEDIR}/data/restore/." "${OPENWBBASEDIR}/data/data_migration/." sudo chmod -R g+w "${OPENWBBASEDIR}/data/restore/." "${OPENWBBASEDIR}/data/data_migration/." # cleanup some folders diff --git a/runs/backup.sh b/runs/backup.sh index e7453cbf58..5ba7952d7a 100755 --- a/runs/backup.sh +++ b/runs/backup.sh @@ -298,7 +298,7 @@ create_archive() { fix_permissions() { echo "setting permissions of new backup file" - sudo chown openwb:www-data "$BACKUPFILE$FILENAMESUFFIX" + sudo chown openwb:caddy "$BACKUPFILE$FILENAMESUFFIX" sudo chmod 664 "$BACKUPFILE$FILENAMESUFFIX" } diff --git a/runs/evse_read_modbus.py b/runs/evse_read_modbus.py index e513dd6ab8..d736d4fcb5 100644 --- a/runs/evse_read_modbus.py +++ b/runs/evse_read_modbus.py @@ -15,4 +15,4 @@ num = int(sys.argv[3]) client = ModbusSerialClient_(str(list(Path("/dev/serial/by-path").glob("*"))[0].resolve())) -print(client.read_holding_registers(register, [ModbusDataType.INT_16]*num, unit=unit)) +print(client.read_holding_registers(register, [ModbusDataType.INT_16]*num, device_id=unit)) diff --git a/runs/evse_write_modbus.py b/runs/evse_write_modbus.py index 16f2446618..1f0a31e461 100644 --- a/runs/evse_write_modbus.py +++ b/runs/evse_write_modbus.py @@ -15,4 +15,4 @@ value = int(sys.argv[3]) client = ModbusSerialClient_(str(list(Path("/dev/serial/by-path").glob("*"))[0].resolve())) -client.write_register(register, value, unit=unit) +client.write_register(register, value, device_id=unit) diff --git a/runs/evsewritembusdev.py b/runs/evsewritembusdev.py index 7a5bbfee58..8322d9ae73 100644 --- a/runs/evsewritembusdev.py +++ b/runs/evsewritembusdev.py @@ -1,11 +1,11 @@ #!/usr/bin/python3 import sys -from pymodbus.client.sync import ModbusSerialClient +from pymodbus.client import ModbusSerialClient seradd = str(sys.argv[1]) evseid = int(sys.argv[2]) wreg = int(sys.argv[3]) val = int(sys.argv[4]) -client = ModbusSerialClient(method="rtu", port=seradd, baudrate=9600, stopbits=1, bytesize=8, timeout=1) -rq = client.write_registers(wreg, val, unit=evseid) +client = ModbusSerialClient(seradd, baudrate=9600, stopbits=1, bytesize=8, timeout=1) +rq = client.write_registers(wreg, val, device_id=evseid) diff --git a/runs/install_packages.sh b/runs/install_packages.sh index f16ed31182..15d255831b 100755 --- a/runs/install_packages.sh +++ b/runs/install_packages.sh @@ -1,25 +1,47 @@ #!/bin/bash +OPENWBBASEDIR=$(cd "$(dirname "${BASH_SOURCE[0]}")/.." && pwd) +source "${OPENWBBASEDIR}/runs/platform_detect.sh" +detect_platform + +echo "=== Platform Detection ===" +echo " Architecture: $PLATFORM_ARCH ($PLATFORM_KERNEL)" +echo " Debian: $PLATFORM_DEBIAN_VERSION ($PLATFORM_DEBIAN_CODENAME)" +echo " Virtualization: $PLATFORM_VIRT" +echo " Raspberry Pi: $PLATFORM_IS_RPI" +echo " 64-bit: $PLATFORM_IS_64BIT" +echo "===========================" + echo "add required repositories..." -# add mosquitto repository if [ ! -f /etc/apt/sources.list.d/mosquitto.list ]; then sudo apt-get -q -y install wget apt-transport-https sudo wget -q https://repo.mosquitto.org/debian/mosquitto-repo.gpg -O /etc/apt/trusted.gpg.d/mosquitto-repo.gpg - # get installed debian version - . /etc/os-release - sudo wget -q -O /etc/apt/sources.list.d/mosquitto.list "https://repo.mosquitto.org/debian/mosquitto-${VERSION_CODENAME}.list" + sudo wget -q -O /etc/apt/sources.list.d/mosquitto.list \ + "https://repo.mosquitto.org/debian/mosquitto-${PLATFORM_DEBIAN_CODENAME}.list" fi echo "done" echo "install required packages with 'apt-get'..." sudo apt-get -q update -sudo apt-get -q -y install \ - vim bc jq curl socat sshpass sudo ssl-cert mmc-utils inotify-tools iptables \ - apache2 libapache2-mod-php \ - php php-gd php-curl php-xml php-json \ - git \ - mosquitto mosquitto-clients \ - python3-pip \ - python3-urllib3 \ - xserver-xorg x11-xserver-utils openbox-lxde-session lightdm lightdm-autologin-greeter accountsservice \ - chromium chromium-l10n + +COMMON_PACKAGES=( + vim bc jq curl socat sshpass sudo ssl-cert inotify-tools iptables + caddy php-fpm + php php-gd php-curl php-xml php-json + git + mosquitto mosquitto-clients + python3 python3-venv python3-dev gcc linux-headers-$(uname -r) + chrony +) + +if [ "$PLATFORM_IS_RPI" = true ]; then + COMMON_PACKAGES+=(mmc-utils) +fi + +sudo apt-get -q -y install "${COMMON_PACKAGES[@]}" +echo "base packages done" + +platform_install_rpi_packages + +platform_install_gui_packages + echo "done" diff --git a/runs/platform_detect.sh b/runs/platform_detect.sh new file mode 100644 index 0000000000..568abe52fa --- /dev/null +++ b/runs/platform_detect.sh @@ -0,0 +1,99 @@ +#!/bin/bash +detect_platform() { + PLATFORM_ARCH=$(dpkg --print-architecture 2>/dev/null || echo "unknown") + PLATFORM_KERNEL=$(uname -m) + PLATFORM_VIRT="none" + PLATFORM_IS_RPI=false + PLATFORM_IS_64BIT=false + PLATFORM_DEBIAN_VERSION="" + PLATFORM_DEBIAN_CODENAME="" + + if [ -f /etc/os-release ]; then + . /etc/os-release + PLATFORM_DEBIAN_VERSION="${VERSION_ID:-unknown}" + PLATFORM_DEBIAN_CODENAME="${VERSION_CODENAME:-unknown}" + fi + + if command -v systemd-detect-virt >/dev/null 2>&1; then + PLATFORM_VIRT=$(systemd-detect-virt 2>/dev/null || echo "none") + fi + + if [ -f /proc/device-tree/model ]; then + local model + model=$(tr -d '\0' < /proc/device-tree/model 2>/dev/null) + case "$model" in + *Raspberry*Pi* | *RPI*) + PLATFORM_IS_RPI=true + ;; + esac + fi + + case "$PLATFORM_KERNEL" in + x86_64 | aarch64) + PLATFORM_IS_64BIT=true + ;; + esac + + PLATFORM_VENV="/opt/openwb-venv" +} + +platform_has_gui() { + if [ "$PLATFORM_IS_RPI" = true ] || [ "$PLATFORM_VIRT" = "none" ]; then + return 0 + fi + return 1 +} + +platform_install_gui_packages() { + if platform_has_gui; then + sudo apt-get -q -y install \ + xserver-xorg x11-xserver-utils openbox-lxde-session lightdm \ + lightdm-autologin-greeter accountsservice \ + chromium chromium-l10n 2>/dev/null || \ + sudo apt-get -q -y install \ + xserver-xorg x11-xserver-utils openbox-lxde-session lightdm \ + lightdm-autologin-greeter accountsservice + fi +} + +platform_install_rpi_packages() { + if [ "$PLATFORM_IS_RPI" = true ]; then + echo "Raspberry Pi detected, installing RPi-specific packages..." + sudo apt-get -q -y install gpiozero 2>/dev/null || true + fi +} + +ensure_venv() { + local venv_path="${1:-$PLATFORM_VENV}" + if [ ! -f "$venv_path/bin/python3" ]; then + echo "Creating Python virtual environment at $venv_path..." + sudo python3 -m venv "$venv_path" + sudo chown -R openwb:openwb "$venv_path" + $venv_path/bin/python3 -m pip install --upgrade pip + echo "venv created." + else + echo "venv already exists at $venv_path." + fi +} + +venv_pip() { + $PLATFORM_VENV/bin/python3 -m pip "$@" +} + +versionMatch() { + local file=$1 + local target=$2 + local currentVersion + local installedVersion + currentVersion=$(grep -o "openwb-version:[0-9]\+" "$file" 2>/dev/null | grep -o "[0-9]\+$") + if [ -r "$target" ]; then + installedVersion=$(grep -o "openwb-version:[0-9]\+" "$target" 2>/dev/null | grep -o "[0-9]\+$") + else + installedVersion=$(sudo grep -o "openwb-version:[0-9]\+" "$target" 2>/dev/null | grep -o "[0-9]\+$") + fi + if [[ -n "$currentVersion" ]] && [[ "$currentVersion" == "$installedVersion" ]]; then + return 0 + else + return 1 + fi +} diff --git a/runs/readmodbus.py b/runs/readmodbus.py index bc865216e9..0579904265 100644 --- a/runs/readmodbus.py +++ b/runs/readmodbus.py @@ -1,14 +1,14 @@ #!/usr/bin/env python3 import sys -from pymodbus.client.sync import ModbusSerialClient +from pymodbus.client import ModbusSerialClient seradd = str(sys.argv[1]) modbusid = int(sys.argv[2]) readreg = int(sys.argv[3]) reganzahl = int(sys.argv[4]) -client = ModbusSerialClient(method="rtu", port=seradd, baudrate=9600, stopbits=1, bytesize=8, timeout=1) -request = client.read_holding_registers(readreg, reganzahl, unit=modbusid) +client = ModbusSerialClient(seradd, baudrate=9600, stopbits=1, bytesize=8, timeout=1) +request = client.read_holding_registers(readreg, count=reganzahl, device_id=modbusid) if request.isError(): print('Modbus Error:', request) else: diff --git a/runs/remoteSupport/remoteSupport.py b/runs/remoteSupport/remoteSupport.py index f20ab349b6..65f03ea2b7 100755 --- a/runs/remoteSupport/remoteSupport.py +++ b/runs/remoteSupport/remoteSupport.py @@ -222,7 +222,7 @@ def on_message(client: mqtt.Client, userdata, msg: mqtt.MQTTMessage): signal(SIGTERM, handle_terminate) # Handle SIGTERM from systemctl for graceful shutdown signal(SIGINT, handle_terminate) # Handle SIGINT from keyboard (Strg+C) for graceful shutdown lt_executable = get_lt_executable() -client = mqtt.Client(f"openWB-remote-{get_serial()}-{datetime.today().timestamp()}") +client = mqtt.Client(mqtt.CallbackAPIVersion.VERSION1, client_id=f"openWB-remote-{get_serial()}-{datetime.today().timestamp()}") client.on_connect = on_connect client.on_message = on_message client.will_set(STATE_TOPIC, json.dumps("offline"), qos=2, retain=True) diff --git a/runs/setup_apache2.sh b/runs/setup_apache2.sh deleted file mode 100755 index d2f84bd4b6..0000000000 --- a/runs/setup_apache2.sh +++ /dev/null @@ -1,156 +0,0 @@ -#!/bin/bash -OPENWBBASEDIR=$(cd "$(dirname "${BASH_SOURCE[0]}")/.." && pwd) -restartService=0 - -versionMatch() { - file=$1 - target=$2 - currentVersion=$(grep -o "openwb-version:[0-9]\+" "$file" | grep -o "[0-9]\+$") - installedVersion=$(sudo grep -o "openwb-version:[0-9]\+" "$target" | grep -o "[0-9]\+$") - if ((currentVersion == installedVersion)); then - return 0 - else - return 1 - fi -} - -updateFile() { - file=$1 - target=$2 - if versionMatch "$file" "$target"; then - echo "$target is up to date" - else - sudo cp "$file" "$target" - restartService=1 - fi -} - -enableModule() { - module=$1 - if sudo a2query -m "$module" -q; then - echo "module '$module' already enabled" - else - echo "module '$module' currently disabled; enabling module" - sudo a2enmod "$module" - restartService=1 - fi -} - -disableModule() { - module=$1 - if sudo a2query -m "$module" -q; then - echo "module '$module' currently enabled; disabling module" - sudo a2dismod "$module" - restartService=1 - else - echo "module '$module' already disabled" - fi -} - -enableSite() { - site=$1 - if sudo a2query -s "$site" -q; then - echo "site '$site' already enabled" - else - echo "site '$site' currently disabled; enabling site" - sudo a2ensite "$site" - restartService=1 - fi -} - -disableSite() { - site=$1 - if sudo a2query -s "$site" -q; then - echo "site '$site' currently enabled; disabling site" - sudo a2dissite "$site" - restartService=1 - else - echo "site '$site' already disabled" - fi -} - -# check apache modules -echo "checking required apache modules..." -enableModule headers -enableModule ssl -enableModule proxy_wstunnel - -# default site (http and https) -echo "apache default site..." -updateFile "${OPENWBBASEDIR}/data/config/apache/000-default.conf" "/etc/apache2/sites-available/000-default.conf" -echo "apache localhost site..." -updateFile "${OPENWBBASEDIR}/data/config/apache/localhost.conf" "/etc/apache2/sites-available/localhost.conf" -# ssl sites -echo "apache redirect ssl site..." -updateFile "${OPENWBBASEDIR}/data/config/apache/apache-redirect-ssl.conf" "/etc/apache2/sites-available/apache-redirect-ssl.conf" -echo "apache default ssl site..." -updateFile "${OPENWBBASEDIR}/data/config/apache/apache-openwb-ssl.conf" "/etc/apache2/sites-available/apache-openwb-ssl.conf" -# http api site (https only) -echo "apache http api ssl site..." -updateFile "${OPENWBBASEDIR}/data/config/apache/http-api-ssl.conf" "/etc/apache2/sites-available/http-api-ssl.conf" -# proplus site -echo "apache pro plus site..." -updateFile "${OPENWBBASEDIR}/data/config/apache/apache-proplus.conf" "/etc/apache2/sites-available/apache-proplus.conf" - -# enable localhost site -enableSite localhost -# disable apache default ssl site -disableSite default-ssl -# enable openwb ssl site -enableSite apache-openwb-ssl -# check if unencrypted access is configured -if allowUnencryptedAccess=$(mosquitto_sub -t "openWB/general/allow_unencrypted_access" -p 1886 -C 1 -W 1 --quiet); then - echo "got 'allow unencrypted access' setting: '$allowUnencryptedAccess'" -else - echo "failed getting 'allow unencrypted access' setting! assuming 'true'" - allowUnencryptedAccess="true" -fi -if [[ $allowUnencryptedAccess == "true" ]]; then - echo "WARNING: unencrypted access is enabled!" - disableSite apache-redirect-ssl - disableModule rewrite - enableSite 000-default -else - echo "unencrypted access is disabled" - disableSite 000-default - enableSite apache-redirect-ssl - enableModule rewrite -fi - -# enable http api ssl site if configured -if httpApiEnabled=$(mosquitto_sub -t "openWB/general/http_api" -p 1886 -C 1 -W 1 --quiet); then - echo "got 'http api enabled' setting: '$httpApiEnabled'" -else - echo "failed getting 'http api enabled' setting! assuming 'false'" - httpApiEnabled="false" -fi -if [[ $httpApiEnabled == "true" ]]; then - echo "http api is enabled" - enableSite http-api-ssl -else - echo "http api is disabled" - disableSite http-api-ssl -fi - -# check for pro+ -echo "Pro+ setup..." -if lsusb | grep -Eq 'RTL8153|AX88179'; then - echo "second network for pro plus detected" - # enable pro+ specific configurations - enableSite apache-proplus - enableModule proxy_http -else - echo "no second network for pro plus detected" - # disable all pro+ specific configurations - disableSite apache-proplus - disableModule proxy_http -fi - -# restart apache if required -if ((restartService == 1)); then - echo -n "restarting apache..." - sudo systemctl restart apache2 - echo "done" -else - echo "apache configuration is already up to date" -fi diff --git a/runs/setup_caddy.sh b/runs/setup_caddy.sh new file mode 100644 index 0000000000..81c4b7104e --- /dev/null +++ b/runs/setup_caddy.sh @@ -0,0 +1,212 @@ +#!/bin/bash +OPENWBBASEDIR=$(cd "$(dirname "${BASH_SOURCE[0]}")/.." && pwd) + +detectPhpFpmSocket() { + local sock + sock=$(ls /run/php/php*fpm*.sock 2>/dev/null | head -1) + if [ -n "$sock" ] && [ -S "$sock" ]; then + echo "$sock" + return 0 + fi + return 1 +} + +PHP_SOCK=$(detectPhpFpmSocket) +if [ -z "$PHP_SOCK" ]; then + echo "WARNING: No PHP-FPM socket found, attempting to start PHP-FPM..." + sudo systemctl start php*-fpm 2>/dev/null || true + PHP_SOCK=$(detectPhpFpmSocket) +fi + +if [ -z "$PHP_SOCK" ]; then + echo "ERROR: PHP-FPM is not running and no socket found. Aborting Caddy setup." + exit 1 +fi +echo "PHP-FPM socket: $PHP_SOCK" + +CADDYFILE_SRC="${OPENWBBASEDIR}/data/config/caddy/Caddyfile" +CADDYFILE_DST="/etc/caddy/Caddyfile" +CADDYFILE_TMP="${CADDYFILE_DST}.tmp" + +if [ ! -f "$CADDYFILE_SRC" ]; then + echo "ERROR: Caddyfile template not found at $CADDYFILE_SRC" + exit 1 +fi + +if allowUnencryptedAccess=$(mosquitto_sub -t "openWB/general/allow_unencrypted_access" -p 1886 -C 1 -W 1 --quiet); then + echo "got 'allow unencrypted access' setting: '$allowUnencryptedAccess'" +else + echo "failed getting 'allow unencrypted access' setting! assuming 'true'" + allowUnencryptedAccess="true" +fi + +if httpApiEnabled=$(mosquitto_sub -t "openWB/general/http_api" -p 1886 -C 1 -W 1 --quiet); then + echo "got 'http api enabled' setting: '$httpApiEnabled'" +else + echo "failed getting 'http api enabled' setting! assuming 'false'" + httpApiEnabled="false" +fi + +generate_site_block() { + local block_name="$1" + echo "${block_name} {" + if [[ "$block_name" == ":81" ]]; then + echo ' bind 127.0.0.1' + fi + echo ' root * /var/www/html' + if [[ "$block_name" == ":443" || "$block_name" == ":8443" ]]; then + echo ' tls /etc/ssl/certs/ssl-cert-snakeoil.pem /etc/ssl/private/ssl-cert-snakeoil.key' + fi + echo " php_fastcgi unix/${PHP_SOCK}" + echo ' file_server {' + echo ' index index.php index.html' + echo ' }' + echo ' handle_path /openWB/ramdisk/* {' + echo ' root * /var/www/html' + echo ' file_server browse' + echo ' }' + echo ' handle_path /openWB/data/backup/* {' + echo ' root * /var/www/html' + echo ' file_server browse' + echo ' }' + echo ' handle /ws* {' + echo ' reverse_proxy 127.0.0.1:9003' + echo ' }' + echo ' handle /mqtt* {' + echo ' reverse_proxy 127.0.0.1:9003' + echo ' }' + echo ' header {' + echo ' Cache-Control "no-cache, no-store, must-revalidate"' + echo ' Pragma "no-cache"' + echo ' Expires 0' + echo ' }' + echo ' @blocked {' + echo ' path *.conf' + echo ' path *.ini' + echo ' path *.py' + echo ' path *.sh' + echo ' }' + echo ' respond @blocked 404' + echo ' @clientJson path /openWB/data/clients/*.json' + echo ' respond @clientJson 403' + echo ' handle_errors {' + echo ' @404 expression {http.error.status_code} == 404' + echo ' handle @404 {' + echo ' rewrite * /openWB/web/error.html' + echo ' file_server' + echo ' }' + echo ' }' + if [[ "$block_name" != ":81" ]]; then + local logname + case "$block_name" in + ":80") logname="access" ;; + ":443") logname="ssl-access" ;; + *) logname="access" ;; + esac + echo " log {" + echo " output file /var/log/caddy/${logname}.log" + echo " }" + fi + echo '}' +} + +{ + echo '# openwb-version:'"$(grep -o 'openwb-version:[0-9]\+' "$CADDYFILE_SRC" | head -1 | grep -o '[0-9]\+$')" + echo '{' + echo ' auto_https off' + echo '}' + echo '' + + if [[ "$allowUnencryptedAccess" == "true" ]]; then + echo "WARNING: unencrypted access is enabled!" >&2 + generate_site_block ":80" + else + echo "unencrypted access is disabled" >&2 + echo ':80 {' + echo ' redir https://{host}{uri} permanent' + echo '}' + fi + echo '' + + generate_site_block ":443" + echo '' + + generate_site_block ":81" + echo '' + + if [[ "$httpApiEnabled" == "true" ]]; then + echo "http api is enabled" >&2 + echo ':8443 {' + echo ' root * /var/www/html/openWB/runs/http-api' + echo ' tls /etc/ssl/certs/ssl-cert-snakeoil.pem /etc/ssl/private/ssl-cert-snakeoil.key' + echo " php_fastcgi unix/${PHP_SOCK}" + echo ' file_server {' + echo ' index index.php index.html' + echo ' }' + echo ' log {' + echo ' output file /var/log/caddy/api-access.log' + echo ' }' + echo '}' + else + echo "http api is disabled" >&2 + fi + echo '' + + if lsusb 2>/dev/null | grep -qE 'RTL8153|AX88179'; then + echo "second network for pro plus detected" >&2 + echo ':8080 {' + echo ' reverse_proxy 192.168.192.50:80' + echo '}' + else + echo "no second network for pro plus detected" >&2 + fi +} | sudo tee "$CADDYFILE_TMP" > /dev/null + +NEEDS_RESTART=0 +if [ ! -f "$CADDYFILE_DST" ] || ! diff -q "$CADDYFILE_TMP" "$CADDYFILE_DST" > /dev/null 2>&1; then + echo "Caddyfile changed, updating..." + sudo mv "$CADDYFILE_TMP" "$CADDYFILE_DST" + NEEDS_RESTART=1 +else + echo "Caddyfile is up to date" + sudo rm -f "$CADDYFILE_TMP" +fi + +echo "checking PHP-FPM upload limit..." +php_dir="" +for dir in /etc/php/*/fpm/conf.d; do + if [ -d "$dir" ]; then + php_dir="$dir" + break + fi +done +if [ -n "$php_dir" ]; then + if [ ! -f "${php_dir}/20-uploadlimit.ini" ] || ! diff -q "${OPENWBBASEDIR}/data/config/php/fpm/20-uploadlimit.ini" "${php_dir}/20-uploadlimit.ini" > /dev/null 2>&1; then + echo "updating PHP upload limit..." + sudo cp "${OPENWBBASEDIR}/data/config/php/fpm/20-uploadlimit.ini" "${php_dir}/20-uploadlimit.ini" + sudo systemctl restart php*-fpm 2>/dev/null + else + echo "PHP upload limit already up to date" + fi +else + echo "no PHP-FPM config directory found, skipping" +fi + +sudo usermod -aG ssl-cert caddy 2>/dev/null +sudo mkdir -p /var/log/caddy +sudo chown caddy:caddy /var/log/caddy + +sudo chmod -R a+rX /var/www/html 2>/dev/null + +if [[ "$NEEDS_RESTART" == "1" ]]; then + echo -n "validating Caddyfile..." + if sudo caddy validate --config "$CADDYFILE_DST" --adapter caddyfile 2>&1; then + echo -n "restarting caddy..." + sudo systemctl restart caddy + echo "done" + else + echo "ERROR: Caddyfile validation failed, not restarting!" + fi +else + echo "caddy configuration is already up to date" +fi diff --git a/runs/setup_mosquitto.sh b/runs/setup_mosquitto.sh index f162cebbaf..38b0943432 100755 --- a/runs/setup_mosquitto.sh +++ b/runs/setup_mosquitto.sh @@ -1,20 +1,9 @@ #!/bin/bash OPENWBBASEDIR=$(cd "$(dirname "${BASH_SOURCE[0]}")/.." && pwd) +source "${OPENWBBASEDIR}/runs/platform_detect.sh" USER_MANAGEMENT_INIT_FILE="${OPENWBBASEDIR}/ramdisk/init_user_management" automaticServiceRestart=${1:-0} -versionMatch() { - file=$1 - target=$2 - currentVersion=$(grep -o "openwb-version:[0-9]\+" "$file" | grep -o "[0-9]\+$") - installedVersion=$(sudo grep -o "openwb-version:[0-9]\+" "$target" | grep -o "[0-9]\+$") - if ((currentVersion == installedVersion)); then - return 0 - else - return 1 - fi -} - waitForServiceStop() { # this function waits for a service to stop and kills the process if it takes too long # this is necessary at least for mosquitto, as the service is stopped, but the process is still running diff --git a/runs/setup_network.sh b/runs/setup_network.sh index 6ddf768e93..5afdb17377 100755 --- a/runs/setup_network.sh +++ b/runs/setup_network.sh @@ -1,5 +1,6 @@ #!/bin/bash OPENWBBASEDIR=$(cd "$(dirname "${BASH_SOURCE[0]}")/.." && pwd) +source "${OPENWBBASEDIR}/runs/platform_detect.sh" dhcpcd_config_source="${OPENWBBASEDIR}/data/config/dhcpcd.conf" dhcpcd_config_target="/etc/dhcpcd.conf" @@ -7,18 +8,6 @@ dhcpcd_config_target="/etc/dhcpcd.conf" dnsmasq_config_source="${OPENWBBASEDIR}/data/config/dnsmasq.conf" dnsmasq_config_target="/etc/dnsmasq.conf" -function versionMatch() { - file=$1 - target=$2 - currentVersion=$(grep -o "openwb-version:[0-9]\+" "$file" | grep -o "[0-9]\+$") - installedVersion=$(grep -o "openwb-version:[0-9]\+" "$target" | grep -o "[0-9]\+$") - if ((currentVersion == installedVersion)); then - return 0 - else - return 1 - fi -} - function update_file() { file=$1 target=$2 diff --git a/runs/upgrade_stack.sh b/runs/upgrade_stack.sh new file mode 100644 index 0000000000..4685c36555 --- /dev/null +++ b/runs/upgrade_stack.sh @@ -0,0 +1,429 @@ +#!/bin/bash +OPENWBBASEDIR=$(cd "$(dirname "${BASH_SOURCE[0]}")/.." && pwd) +source "${OPENWBBASEDIR}/runs/platform_detect.sh" +detect_platform + +UPGRADE_MARKER="${OPENWBBASEDIR}/.stack-version" +CURRENT_STACK=3 + +needs_upgrade() { + if [ ! -f "$UPGRADE_MARKER" ]; then + return 0 + fi + local marker_version + marker_version=$(cat "$UPGRADE_MARKER" 2>/dev/null) + if [[ "$marker_version" != "$CURRENT_STACK" ]]; then + return 0 + fi + return 1 +} + +is_python_supported() { + local py_bin="${1:-python3}" + local major minor + major=$($py_bin -c 'import sys; print(sys.version_info.major)' 2>/dev/null) + minor=$($py_bin -c 'import sys; print(sys.version_info.minor)' 2>/dev/null) + if [[ "$major" -ge 3 && "$minor" -ge 10 ]]; then + return 0 + fi + return 1 +} + +get_python_version() { + $1 -c 'import sys; print("{}.{}".format(sys.version_info.major, sys.version_info.minor))' 2>/dev/null +} + +# --- Main upgrade logic --- + +echo "=== openWB Stack Upgrade Check ===" +echo " OS: Debian $PLATFORM_DEBIAN_VERSION ($PLATFORM_DEBIAN_CODENAME)" +echo " Arch: $PLATFORM_ARCH ($PLATFORM_KERNEL)" +echo " Virtualization: $PLATFORM_VIRT" +echo " Raspberry Pi: $PLATFORM_IS_RPI" +echo "===================================" + +if ! needs_upgrade; then + echo "Stack is up to date (version $CURRENT_STACK). No upgrade needed." + exit 0 +fi + +echo "Stack upgrade required (target: version $CURRENT_STACK). Starting upgrade..." + +# --- Step 1: Enable backports on Bookworm --- +if [[ "$PLATFORM_DEBIAN_CODENAME" == "bookworm" ]]; then + echo "" + echo "--- Step 1: Enabling bookworm-backports ---" + if ! grep -q "bookworm-backports" /etc/apt/sources.list /etc/apt/sources.list.d/*.sources 2>/dev/null; then + if [ -f /etc/apt/sources.list.d/debian.sources ]; then + if ! grep -q "bookworm-backports" /etc/apt/sources.list.d/debian.sources; then + echo "Adding backports to DEB822 sources..." + sudo sed -i '/^URIs:.*\/debian$/ { N; /\nSuites:.*bookworm-updates/ s/\(Suites: .*\)/\1 bookworm-backports/ }' /etc/apt/sources.list.d/debian.sources + fi + else + echo "Adding backports to traditional sources.list..." + if ! grep -q "bookworm-backports" /etc/apt/sources.list; then + echo "deb http://deb.debian.org/debian bookworm-backports main" | sudo tee -a /etc/apt/sources.list > /dev/null + fi + fi + echo "Updating package lists..." + sudo apt-get -q update 2>/dev/null + else + echo "Backports already enabled." + fi +else + echo "--- Step 1: Not Bookworm, skipping backports setup ---" +fi + +# --- Step 2: Determine and install Python --- +echo "" +echo "--- Step 2: Python installation ---" + +PYTHON_TARGET="" +PYTHON_BIN="" + +# Check available Python versions - prefer 3.13, fall back to 3.12, then 3.11+ +for py_ver in 3.13 3.12 3.11 3.10; do + py_bin="/usr/bin/python${py_ver}" + if [ -x "$py_bin" ]; then + if is_python_supported "$py_bin"; then + PYTHON_BIN="$py_bin" + PYTHON_TARGET="$py_ver" + echo "Found system Python $py_ver: $($py_bin --version 2>/dev/null)" + break + fi + fi +done + +if [ -z "$PYTHON_BIN" ]; then + echo "No supported Python (>=3.10) found. Installing..." + if [[ "$PLATFORM_DEBIAN_CODENAME" == "bookworm" ]]; then + echo "Trying python3.13 from bookworm-backports..." + sudo apt-get -q -y install -t bookworm-backports python3.13 python3.13-venv python3.13-dev 2>/dev/null + if [ -x /usr/bin/python3.13 ]; then + PYTHON_BIN="/usr/bin/python3.13" + PYTHON_TARGET="3.13" + else + echo "python3.13 not available in backports, trying python3.12..." + sudo apt-get -q -y install -t bookworm-backports python3.12 python3.12-venv python3.12-dev 2>/dev/null + if [ -x /usr/bin/python3.12 ]; then + PYTHON_BIN="/usr/bin/python3.12" + PYTHON_TARGET="3.12" + fi + fi + fi + + if [ -z "$PYTHON_BIN" ]; then + echo "Installing default python3 + venv + dev..." + sudo apt-get -q -y install python3 python3-venv python3-dev + if is_python_supported /usr/bin/python3; then + PYTHON_BIN="/usr/bin/python3" + PYTHON_TARGET="python3" + fi + fi +fi + +if [ -z "$PYTHON_BIN" ]; then + echo "ERROR: No Python >= 3.10 available! Cannot continue." + echo "This system needs manual intervention." + exit 1 +fi + +echo "Using Python: $PYTHON_BIN ($(get_python_version $PYTHON_BIN))" + +# --- Step 3: Create / update virtual environment --- +echo "" +echo "--- Step 3: Virtual environment ---" + +VENV_PATH="$PLATFORM_VENV" +VENV_PYTHON_VERSION="" +if [ -f "$VENV_PATH/bin/python3" ]; then + VENV_PYTHON_VERSION=$($VENV_PATH/bin/python3 -c 'import sys; print("{}.{}".format(sys.version_info.major, sys.version_info.minor))' 2>/dev/null) +fi + +VENV_NEEDS_RECREATE=0 +if [ ! -f "$VENV_PATH/bin/python3" ]; then + VENV_NEEDS_RECREATE=1 + echo "No venv found, will create." +elif ! is_python_supported "$VENV_PATH/bin/python3"; then + VENV_NEEDS_RECREATE=1 + echo "Venv has Python $VENV_PYTHON_VERSION (< 3.10), needs recreation." +fi + +if [[ "$VENV_NEEDS_RECREATE" == "1" ]]; then + echo "Creating venv with $PYTHON_BIN at $VENV_PATH..." + if [ -d "$VENV_PATH" ]; then + echo "Removing old venv..." + sudo rm -rf "$VENV_PATH" + fi + sudo $PYTHON_BIN -m venv "$VENV_PATH" + sudo chown -R openwb:openwb "$VENV_PATH" + $VENV_PATH/bin/python3 -m pip install --upgrade pip + echo "Venv created with Python $($VENV_PATH/bin/python3 --version 2>/dev/null)" +else + echo "Venv already exists with Python $VENV_PYTHON_VERSION, OK." +fi + +# --- Step 4: Web server migration (Apache -> Caddy + PHP-FPM) --- +echo "" +echo "--- Step 4: Web server ---" + +APACHE_INSTALLED=0 +if dpkg -l apache2 2>/dev/null | grep -q "^ii"; then + APACHE_INSTALLED=1 +fi + +CADDY_INSTALLED=0 +if dpkg -l caddy 2>/dev/null | grep -q "^ii"; then + CADDY_INSTALLED=1 +fi + +PHP_FPM_INSTALLED=0 +if systemctl list-unit-files php*-fpm.service 2>/dev/null | grep -q "enabled"; then + PHP_FPM_INSTALLED=1 +fi + +if [[ "$CADDY_INSTALLED" == "0" ]]; then + echo "Installing Caddy + PHP-FPM..." + sudo apt-get -q -y install caddy php-fpm php php-gd php-curl php-xml php-json + + if [[ "$APACHE_INSTALLED" == "1" ]]; then + echo "Stopping and disabling Apache..." + sudo systemctl stop apache2 2>/dev/null || true + sudo systemctl disable apache2 2>/dev/null || true + fi + + echo "Adding caddy to ssl-cert group..." + sudo usermod -aG ssl-cert caddy 2>/dev/null + + echo "Caddy + PHP-FPM installed." +else + echo "Caddy already installed." +fi + +if [[ "$PHP_FPM_INSTALLED" == "0" ]]; then + echo "Enabling PHP-FPM..." + sudo systemctl enable php*-fpm 2>/dev/null + sudo systemctl start php*-fpm 2>/dev/null +fi + +# Ensure webroot is readable +sudo chmod -R a+rX /var/www/html 2>/dev/null + +# --- Step 5: Install remaining required packages --- +echo "" +echo "--- Step 5: Additional packages ---" + +REQUIRED_PACKAGES="vim bc jq curl socat sshpass sudo ssl-cert inotify-tools iptables git mosquitto mosquitto-clients chrony gcc usbutils" + +MISSING_PACKAGES="" +for pkg in $REQUIRED_PACKAGES; do + if ! dpkg -l "$pkg" 2>/dev/null | grep -q "^ii"; then + MISSING_PACKAGES="$MISSING_PACKAGES $pkg" + fi +done + +if [ -n "$MISSING_PACKAGES" ]; then + echo "Installing missing packages:$MISSING_PACKAGES" + sudo apt-get -q -y install $MISSING_PACKAGES +else + echo "All required packages already installed." +fi + +# Install linux-headers for evdev build (if not present) +if ! dpkg -l "linux-headers-$(uname -r)" 2>/dev/null | grep -q "^ii"; then + sudo apt-get -q -y install "linux-headers-$(uname -r)" 2>/dev/null || true +fi + +# --- Step 6: Chrony NTP --- +echo "" +echo "--- Step 6: NTP (Chrony) ---" +if ! systemctl is-active --quiet chrony 2>/dev/null; then + echo "Configuring chrony..." + sudo systemctl stop systemd-timesyncd 2>/dev/null || true + sudo systemctl disable systemd-timesyncd 2>/dev/null || true + if [ -f "${OPENWBBASEDIR}/data/config/chrony/chrony.conf" ]; then + sudo cp "${OPENWBBASEDIR}/data/config/chrony/chrony.conf" /etc/chrony/chrony.conf + fi + sudo systemctl enable chrony + sudo systemctl restart chrony + echo "Chrony configured." +else + echo "Chrony already active." +fi + +# --- Step 7: MOTD --- +echo "" +echo "--- Step 7: MOTD ---" +if [ -f "${OPENWBBASEDIR}/data/config/profile.d/99-openwb-motd.sh" ]; then + sudo cp "${OPENWBBASEDIR}/data/config/profile.d/99-openwb-motd.sh" /etc/profile.d/99-openwb-motd.sh + sudo chmod 755 /etc/profile.d/99-openwb-motd.sh + echo "MOTD installed." +else + echo "MOTD file not found, skipping." +fi + +# --- Step 8: Update sudoers --- +echo "" +echo "--- Step 8: Sudoers ---" +if [ -f "${OPENWBBASEDIR}/data/config/sudoers/caddy" ]; then + sudo cp "${OPENWBBASEDIR}/data/config/sudoers/caddy" "/etc/sudoers.d/caddy" + sudo chmod 440 /etc/sudoers.d/caddy + echo "Caddy sudoers installed." +fi +# Remove old apache sudoers if present +if [ -f "/etc/sudoers.d/apache2" ]; then + echo "Removing old Apache sudoers..." + sudo rm -f "/etc/sudoers.d/apache2" +fi + +# --- Step 9: Update service files --- +echo "" +echo "--- Step 9: Service files ---" +for svc in openwb2 openwb-simpleAPI openwbRemoteSupport; do + svc_file="${OPENWBBASEDIR}/data/config/${svc}.service" + svc_target="/etc/systemd/system/${svc}.service" + if [ -f "$svc_file" ]; then + if [ -L "$svc_target" ]; then + echo " ${svc}.service already a symlink, OK." + else + sudo rm -f "$svc_target" + sudo ln -s "$svc_file" "$svc_target" + echo " ${svc}.service symlinked." + fi + fi +done +sudo systemctl daemon-reload + +# --- Step 10: Remove obsolete Apache packages (after everything else is set up) --- +echo "" +echo "--- Step 10: Cleanup ---" +if [[ "$APACHE_INSTALLED" == "1" ]] && [[ "$CADDY_INSTALLED" == "1" ]]; then + echo "Removing Apache packages (Caddy is active)..." + sudo apt-get -q -y purge libapache2-mod-php apache2 2>/dev/null + sudo apt-get -q -y autoremove 2>/dev/null + echo "Apache removed." +else + echo "No Apache cleanup needed." +fi + +# --- Step 11: Install Python requirements --- +echo "" +echo "--- Step 11: Python requirements ---" +if [ -f "${OPENWBBASEDIR}/requirements.txt" ]; then + echo "Installing Python packages into venv..." + if $VENV_PATH/bin/python3 -m pip install --only-binary :all: -r "${OPENWBBASEDIR}/requirements.txt" 2>/dev/null; then + echo "Python packages installed (binary only)." + else + echo "Binary install failed, trying with build..." + $VENV_PATH/bin/python3 -m pip install -r "${OPENWBBASEDIR}/requirements.txt" 2>/dev/null + echo "Done (with build)." + fi +else + echo "requirements.txt not found, skipping." +fi + +# --- Step 12: Run Caddy setup --- +echo "" +echo "--- Step 12: Caddy configuration ---" +if [ -f "${OPENWBBASEDIR}/runs/setup_caddy.sh" ]; then + bash "${OPENWBBASEDIR}/runs/setup_caddy.sh" +else + echo "setup_caddy.sh not found, skipping." +fi + +# --- Step 13: Swap (zram on RPi, swapfile on x86) --- +echo "" +echo "--- Step 13: Swap setup ---" +HAS_SWAP=$(wc -l < /proc/swaps 2>/dev/null) +if [[ "$HAS_SWAP" -le 1 ]]; then + if [[ "$PLATFORM_IS_RPI" == "true" ]]; then + echo "Raspberry Pi detected: setting up zram swap..." + if ! dpkg -l zram-tools 2>/dev/null | grep -q "^ii"; then + sudo apt-get -q -y install zram-tools + fi + if [ ! -f /etc/default/zramswap ] || ! grep -q "^PERCENTAGE=" /etc/default/zramswap 2>/dev/null; then + echo "PERCENTAGE=50" | sudo tee /etc/default/zramswap > /dev/null + echo "PRIORITY=100" | sudo tee -a /etc/default/zramswap > /dev/null + echo "ALGO=lz4" | sudo tee -a /etc/default/zramswap > /dev/null + fi + sudo systemctl enable zramswap 2>/dev/null + sudo systemctl start zramswap 2>/dev/null || sudo systemctl restart zramswap 2>/dev/null + echo "zram swap configured (50% of RAM, lz4, priority 100)." + else + echo "Non-RPi system: setting up swapfile..." + if [ ! -f /swapfile ]; then + sudo fallocate -l 512M /swapfile + sudo chmod 600 /swapfile + sudo mkswap /swapfile + sudo swapon /swapfile + if ! grep -q "^/swapfile" /etc/fstab; then + echo "/swapfile none swap sw 0 0" | sudo tee -a /etc/fstab > /dev/null + fi + echo "512M swapfile created and activated." + else + echo "Swapfile already exists." + fi + fi +else + echo "Swap already active ($(wc -l < /proc/swaps) devices)." +fi + +# --- Step 14: Raspberry Pi SD card protection --- +echo "" +echo "--- Step 14: SD card protection (RPi only) ---" +if [[ "$PLATFORM_IS_RPI" == "true" ]]; then + FSTAB_MODIFIED=0 + + if ! grep -q "tmpfs.*/var/log" /etc/fstab 2>/dev/null; then + echo "Adding tmpfs for /var/log..." + echo "tmpfs /var/log tmpfs defaults,nosuid,nodev,noatime,size=64M 0 0" | sudo tee -a /etc/fstab > /dev/null + sudo mount /var/log 2>/dev/null || true + FSTAB_MODIFIED=1 + else + echo "tmpfs /var/log already in fstab." + fi + + if ! grep -q "noatime.* / " /etc/fstab 2>/dev/null; then + if grep -q "^/dev/.* / " /etc/fstab 2>/dev/null; then + echo "Adding noatime to root partition..." + sudo sed -i '/^\/dev\/.* \/ / s/defaults/defaults,noatime/' /etc/fstab + FSTAB_MODIFIED=1 + fi + else + echo "noatime already set on root partition." + fi + + if [ -f /etc/systemd/journald.conf ]; then + if ! grep -q "^Storage=volatile" /etc/systemd/journald.conf 2>/dev/null; then + echo "Setting journald to volatile storage..." + sudo sed -i 's/^#*Storage=.*/Storage=volatile/' /etc/systemd/journald.conf + sudo systemctl restart systemd-journald 2>/dev/null + else + echo "journald already volatile." + fi + fi + + if [[ "$FSTAB_MODIFIED" == "1" ]]; then + echo "Root partition noatime will take effect on next boot." + fi +else + echo "Not a Raspberry Pi, skipping SD card protection." +fi + +# --- Mark upgrade complete --- +echo "$CURRENT_STACK" > "$UPGRADE_MARKER" +echo "" +echo "=== Stack upgrade to version $CURRENT_STACK complete ===" +echo " Python: $($VENV_PATH/bin/python3 --version 2>/dev/null)" +echo " Venv: $VENV_PATH" +echo " Web: $(dpkg -l caddy 2>/dev/null | grep '^ii' | awk '{print $3}')" +echo " PHP-FPM: $(systemctl is-active php*-fpm 2>/dev/null || echo unknown)" +echo " Chrony: $(systemctl is-active chrony 2>/dev/null)" +if [[ "$PLATFORM_IS_RPI" == "true" ]]; then + echo " Swap: zram ($(swapon --show=SIZE --noheadings 2>/dev/null || echo N/A))" + echo " SD protection: active" +else + SWAP_SIZE=$(swapon --show=SIZE --noheadings 2>/dev/null | head -1) + echo " Swap: ${SWAP_SIZE:-none}" +fi +echo "===============================================" diff --git a/simpleAPI/simpleAPI_mqtt.py b/simpleAPI/simpleAPI_mqtt.py index 2882fcfd9e..f960d4d45e 100755 --- a/simpleAPI/simpleAPI_mqtt.py +++ b/simpleAPI/simpleAPI_mqtt.py @@ -47,7 +47,7 @@ def __init__(self, config_file: str): self.charge_template_cache: Dict[str, Dict[str, Any]] = {} # MQTT client setup - self.client = mqtt.Client() + self.client = mqtt.Client(mqtt.CallbackAPIVersion.VERSION1) self.client.on_connect = self._on_connect self.client.on_message = self._on_message self.client.on_disconnect = self._on_disconnect