Compare commits
32 Commits
s-allius/i
...
v0.12.1
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
446a0d88f0 | ||
|
|
ae4565238b | ||
|
|
abdbdefc18 | ||
|
|
4ffe8a395e | ||
|
|
868d3ef312 | ||
|
|
ce050e8ab5 | ||
|
|
354c204ce6 | ||
|
|
d8200b5a35 | ||
|
|
20503b46ab | ||
|
|
a93368336a | ||
|
|
772da4fa96 | ||
|
|
3f4997a0fd | ||
|
|
2220517b55 | ||
|
|
b28792a654 | ||
|
|
d4ecbfe2b3 | ||
|
|
84dfd17d7b | ||
|
|
7067977d78 | ||
|
|
f227faa16e | ||
|
|
9572fbf609 | ||
|
|
3fddbe9456 | ||
|
|
34c09edb07 | ||
|
|
ef3ed5d287 | ||
|
|
7878c54ecc | ||
|
|
097e0d2104 | ||
|
|
181a22c369 | ||
|
|
89ab2eea3f | ||
|
|
264e09651f | ||
|
|
3bb360d359 | ||
|
|
8731d1bae3 | ||
|
|
4f0918ef83 | ||
|
|
5501288b51 | ||
|
|
851122515e |
6
.github/workflows/python-app.yml
vendored
6
.github/workflows/python-app.yml
vendored
@@ -37,10 +37,10 @@ jobs:
|
|||||||
- uses: actions/checkout@v4
|
- uses: actions/checkout@v4
|
||||||
with:
|
with:
|
||||||
fetch-depth: 0 # Shallow clones should be disabled for a better relevancy of analysis
|
fetch-depth: 0 # Shallow clones should be disabled for a better relevancy of analysis
|
||||||
- name: Set up Python 3.13
|
- name: Set up Python 3.12
|
||||||
uses: actions/setup-python@v5
|
uses: actions/setup-python@v5
|
||||||
with:
|
with:
|
||||||
python-version: "3.13"
|
python-version: "3.12"
|
||||||
- name: Install dependencies
|
- name: Install dependencies
|
||||||
run: |
|
run: |
|
||||||
python -m pip install --upgrade pip
|
python -m pip install --upgrade pip
|
||||||
@@ -58,7 +58,7 @@ jobs:
|
|||||||
coverage report
|
coverage report
|
||||||
- name: Analyze with SonarCloud
|
- name: Analyze with SonarCloud
|
||||||
if: ${{ env.SONAR_TOKEN != 0 }}
|
if: ${{ env.SONAR_TOKEN != 0 }}
|
||||||
uses: SonarSource/sonarqube-scan-action@v5
|
uses: SonarSource/sonarqube-scan-action@v4
|
||||||
env:
|
env:
|
||||||
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||||
with:
|
with:
|
||||||
|
|||||||
@@ -1 +1 @@
|
|||||||
3.13.2
|
3.13.1
|
||||||
|
|||||||
17
CHANGELOG.md
17
CHANGELOG.md
@@ -7,23 +7,6 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
|
|||||||
|
|
||||||
## [unreleased]
|
## [unreleased]
|
||||||
|
|
||||||
- update dependency python to 3.13
|
|
||||||
- add initial support for TSUN MS-3000
|
|
||||||
- add initial apparmor support [#293](https://github.com/s-allius/tsun-gen3-proxy/issues/293)
|
|
||||||
- add Modbus polling mode for DCU1000 [#292](https://github.com/s-allius/tsun-gen3-proxy/issues/292)
|
|
||||||
- add Modbus scanning mode
|
|
||||||
- allow `R47`serial numbers for GEN3 inverters
|
|
||||||
- add watchdog for Add-ons
|
|
||||||
- add first costumer apparmor definition
|
|
||||||
- Respect logging.ini file, if LOG_ENV isn't set well [#288](https://github.com/s-allius/tsun-gen3-proxy/issues/288)
|
|
||||||
- Remove trailing apostrophe in the log output [#288](https://github.com/s-allius/tsun-gen3-proxy/issues/288)
|
|
||||||
- update AddOn base docker image to version 17.2.1
|
|
||||||
- addon: add date and time to dev container version
|
|
||||||
- Update AddOn python3 to 3.12.9-r0
|
|
||||||
- add initial DCU support
|
|
||||||
- update aiohttp to version 3.11.12
|
|
||||||
- fix the path handling for logging.ini and default_config.toml [#180](https://github.com/s-allius/tsun-gen3-proxy/issues/180)
|
|
||||||
|
|
||||||
## [0.12.1] - 2025-01-13
|
## [0.12.1] - 2025-01-13
|
||||||
|
|
||||||
- addon: bump base image version to v17.1.0
|
- addon: bump base image version to v17.1.0
|
||||||
|
|||||||
6
Makefile
6
Makefile
@@ -1,4 +1,4 @@
|
|||||||
.PHONY: build clean addon-dev addon-debug addon-rc addon-rel debug dev preview rc rel check-docker-compose install
|
.PHONY: build clean addon-dev addon-debug addon-rc addon-rel debug dev preview rc rel
|
||||||
|
|
||||||
debug dev preview rc rel:
|
debug dev preview rc rel:
|
||||||
$(MAKE) -C app $@
|
$(MAKE) -C app $@
|
||||||
@@ -12,7 +12,3 @@ addon-dev addon-debug addon-rc addon-rel:
|
|||||||
check-docker-compose:
|
check-docker-compose:
|
||||||
docker-compose config -q
|
docker-compose config -q
|
||||||
|
|
||||||
install:
|
|
||||||
python3 -m pip install --upgrade pip
|
|
||||||
python3 -m pip install -r requirements.txt
|
|
||||||
python3 -m pip install -r requirements-test.txt
|
|
||||||
@@ -6,7 +6,7 @@
|
|||||||
<p align="center">integration</p>
|
<p align="center">integration</p>
|
||||||
<p align="center">
|
<p align="center">
|
||||||
<a href="https://opensource.org/licenses/BSD-3-Clause"><img alt="License: BSD-3-Clause" src="https://img.shields.io/badge/License-BSD_3--Clause-green.svg"></a>
|
<a href="https://opensource.org/licenses/BSD-3-Clause"><img alt="License: BSD-3-Clause" src="https://img.shields.io/badge/License-BSD_3--Clause-green.svg"></a>
|
||||||
<a href="https://www.python.org/downloads/release/python-3130/"><img alt="Supported Python versions" src="https://img.shields.io/badge/python-3.13-blue.svg"></a>
|
<a href="https://www.python.org/downloads/release/python-3120/"><img alt="Supported Python versions" src="https://img.shields.io/badge/python-3.12-blue.svg"></a>
|
||||||
<a href="https://sbtinstruments.github.io/aiomqtt/introduction.html"><img alt="Supported aiomqtt versions" src="https://img.shields.io/badge/aiomqtt-2.3.0-lightblue.svg"></a>
|
<a href="https://sbtinstruments.github.io/aiomqtt/introduction.html"><img alt="Supported aiomqtt versions" src="https://img.shields.io/badge/aiomqtt-2.3.0-lightblue.svg"></a>
|
||||||
<a href="https://libraries.io/pypi/aiocron"><img alt="Supported aiocron versions" src="https://img.shields.io/badge/aiocron-1.8-lightblue.svg"></a>
|
<a href="https://libraries.io/pypi/aiocron"><img alt="Supported aiocron versions" src="https://img.shields.io/badge/aiocron-1.8-lightblue.svg"></a>
|
||||||
<a href="https://toml.io/en/v1.0.0"><img alt="Supported toml versions" src="https://img.shields.io/badge/toml-1.0.0-lightblue.svg"></a>
|
<a href="https://toml.io/en/v1.0.0"><img alt="Supported toml versions" src="https://img.shields.io/badge/toml-1.0.0-lightblue.svg"></a>
|
||||||
|
|||||||
@@ -1 +1 @@
|
|||||||
0.13.0
|
0.12.1
|
||||||
@@ -30,7 +30,7 @@ ARG SERVICE_NAME
|
|||||||
ARG VERSION
|
ARG VERSION
|
||||||
ARG UID
|
ARG UID
|
||||||
ARG GID
|
ARG GID
|
||||||
ARG LOG_LVL=INFO
|
ARG LOG_LVL
|
||||||
ARG environment
|
ARG environment
|
||||||
|
|
||||||
ENV SERVICE_NAME=$SERVICE_NAME
|
ENV SERVICE_NAME=$SERVICE_NAME
|
||||||
@@ -59,6 +59,7 @@ RUN python -m pip install --no-cache-dir --no-cache --no-index /root/wheels/* &&
|
|||||||
|
|
||||||
# copy the content of the local src and config directory to the working directory
|
# copy the content of the local src and config directory to the working directory
|
||||||
COPY --chmod=0700 entrypoint.sh /root/entrypoint.sh
|
COPY --chmod=0700 entrypoint.sh /root/entrypoint.sh
|
||||||
|
COPY config .
|
||||||
COPY src .
|
COPY src .
|
||||||
RUN echo ${VERSION} > /proxy-version.txt \
|
RUN echo ${VERSION} > /proxy-version.txt \
|
||||||
&& date > /build-date.txt
|
&& date > /build-date.txt
|
||||||
|
|||||||
33
app/Makefile
33
app/Makefile
@@ -7,6 +7,23 @@ IMAGE = tsun-gen3-proxy
|
|||||||
|
|
||||||
# Folders
|
# Folders
|
||||||
SRC=.
|
SRC=.
|
||||||
|
SRC_PROXY=$(SRC)/src
|
||||||
|
CNF_PROXY=$(SRC)/config
|
||||||
|
|
||||||
|
DST=rootfs
|
||||||
|
DST_PROXY=$(DST)/home/proxy
|
||||||
|
|
||||||
|
# collect source files
|
||||||
|
SRC_FILES := $(wildcard $(SRC_PROXY)/*.py)\
|
||||||
|
$(wildcard $(SRC_PROXY)/*.ini)\
|
||||||
|
$(wildcard $(SRC_PROXY)/cnf/*.py)\
|
||||||
|
$(wildcard $(SRC_PROXY)/gen3/*.py)\
|
||||||
|
$(wildcard $(SRC_PROXY)/gen3plus/*.py)
|
||||||
|
CNF_FILES := $(wildcard $(CNF_PROXY)/*.toml)
|
||||||
|
|
||||||
|
# determine destination files
|
||||||
|
TARGET_FILES = $(SRC_FILES:$(SRC_PROXY)/%=$(DST_PROXY)/%)
|
||||||
|
CONFIG_FILES = $(CNF_FILES:$(CNF_PROXY)/%=$(DST_PROXY)/%)
|
||||||
|
|
||||||
export BUILD_DATE := ${shell date -Iminutes}
|
export BUILD_DATE := ${shell date -Iminutes}
|
||||||
VERSION := $(shell cat $(SRC)/.version)
|
VERSION := $(shell cat $(SRC)/.version)
|
||||||
@@ -31,4 +48,20 @@ preview rc rel:
|
|||||||
docker buildx bake -f docker-bake.hcl $@
|
docker buildx bake -f docker-bake.hcl $@
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
.PHONY: debug dev preview rc rel
|
.PHONY: debug dev preview rc rel
|
||||||
|
|
||||||
|
|
||||||
|
$(CONFIG_FILES): $(DST_PROXY)/% : $(CNF_PROXY)/%
|
||||||
|
@echo Copy $< to $@
|
||||||
|
@mkdir -p $(@D)
|
||||||
|
@cp $< $@
|
||||||
|
|
||||||
|
$(TARGET_FILES): $(DST_PROXY)/% : $(SRC_PROXY)/%
|
||||||
|
@echo Copy $< to $@
|
||||||
|
@mkdir -p $(@D)
|
||||||
|
@cp $< $@
|
||||||
|
|
||||||
|
$(DST)/requirements.txt : $(SRC)/requirements.txt
|
||||||
|
@echo Copy $< to $@
|
||||||
|
@cp $< $@
|
||||||
|
|||||||
@@ -113,7 +113,7 @@ inverters.allow_all = false # only allow known inverters
|
|||||||
##
|
##
|
||||||
## For each GEN3 inverter, the serial number of the inverter must be mapped to an MQTT
|
## For each GEN3 inverter, the serial number of the inverter must be mapped to an MQTT
|
||||||
## definition. To do this, the corresponding configuration block is started with
|
## definition. To do this, the corresponding configuration block is started with
|
||||||
## `[inverters.“<16-digit serial number>”]` so that all subsequent parameters are assigned
|
## `[Inverter.“<16-digit serial number>”]` so that all subsequent parameters are assigned
|
||||||
## to this inverter. Further inverter-specific parameters (e.g. polling mode) can be set
|
## to this inverter. Further inverter-specific parameters (e.g. polling mode) can be set
|
||||||
## in the configuration block
|
## in the configuration block
|
||||||
##
|
##
|
||||||
@@ -132,7 +132,7 @@ pv2 = {type = 'RSM40-8-395M', manufacturer = 'Risen'} # Optional, PV module de
|
|||||||
##
|
##
|
||||||
## For each GEN3PLUS inverter, the serial number of the inverter must be mapped to an MQTT
|
## For each GEN3PLUS inverter, the serial number of the inverter must be mapped to an MQTT
|
||||||
## definition. To do this, the corresponding configuration block is started with
|
## definition. To do this, the corresponding configuration block is started with
|
||||||
## `[inverters.“<16-digit serial number>”]` so that all subsequent parameters are assigned
|
## `[Inverter.“<16-digit serial number>”]` so that all subsequent parameters are assigned
|
||||||
## to this inverter. Further inverter-specific parameters (e.g. polling mode, client mode)
|
## to this inverter. Further inverter-specific parameters (e.g. polling mode, client mode)
|
||||||
## can be set in the configuration block
|
## can be set in the configuration block
|
||||||
##
|
##
|
||||||
@@ -157,33 +157,6 @@ pv3 = {type = 'RSM40-8-410M', manufacturer = 'Risen'} # Optional, PV module de
|
|||||||
pv4 = {type = 'RSM40-8-410M', manufacturer = 'Risen'} # Optional, PV module descr
|
pv4 = {type = 'RSM40-8-410M', manufacturer = 'Risen'} # Optional, PV module descr
|
||||||
|
|
||||||
|
|
||||||
##########################################################################################
|
|
||||||
##
|
|
||||||
## For each GEN3PLUS enrgy storage system, the serial number must be mapped to an MQTT
|
|
||||||
## definition. To do this, the corresponding configuration block is started with
|
|
||||||
## `[batteries.“<16-digit serial number>”]` so that all subsequent parameters are assigned
|
|
||||||
## to this energy storage system. Further device-specific parameters (e.g. polling mode,
|
|
||||||
## client mode) can be set in the configuration block
|
|
||||||
##
|
|
||||||
## The serial numbers of all GEN3PLUS energy storage systems/batteries start with `410`!
|
|
||||||
## Each GEN3PLUS device is supplied with a “Monitoring SN:”. This can be found on a
|
|
||||||
## sticker enclosed with the inverter.
|
|
||||||
##
|
|
||||||
|
|
||||||
[batteries."4100000000000001"]
|
|
||||||
monitor_sn = 3000000000 # The GEN3PLUS "Monitoring SN:"
|
|
||||||
node_id = '' # MQTT replacement for devices serial number
|
|
||||||
suggested_area = '' # suggested installation place for home-assistant
|
|
||||||
modbus_polling = true # Enable optional MODBUS polling
|
|
||||||
|
|
||||||
# if your inverter supports SSL connections you must use the client_mode. Pls, uncomment
|
|
||||||
# the next line and configure the fixed IP of your inverter
|
|
||||||
#client_mode = {host = '192.168.0.1', port = 8899, forward = true}
|
|
||||||
|
|
||||||
pv1 = {type = 'RSM40-8-410M', manufacturer = 'Risen'} # Optional, PV module descr
|
|
||||||
pv2 = {type = 'RSM40-8-410M', manufacturer = 'Risen'} # Optional, PV module descr
|
|
||||||
|
|
||||||
|
|
||||||
##########################################################################################
|
##########################################################################################
|
||||||
###
|
###
|
||||||
### If the proxy mode is configured, commands from TSUN can be sent to the inverter via
|
### If the proxy mode is configured, commands from TSUN can be sent to the inverter via
|
||||||
@@ -1,263 +0,0 @@
|
|||||||
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
|
||||||
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN"
|
|
||||||
"http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
|
|
||||||
<!-- Generated by graphviz version 2.40.1 (20161225.0304)
|
|
||||||
-->
|
|
||||||
<!-- Title: G Pages: 1 -->
|
|
||||||
<svg width="634pt" height="966pt"
|
|
||||||
viewBox="0.00 0.00 634.00 966.00" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
|
|
||||||
<g id="graph0" class="graph" transform="scale(1 1) rotate(0) translate(4 962)">
|
|
||||||
<title>G</title>
|
|
||||||
<polygon fill="#ffffff" stroke="transparent" points="-4,4 -4,-962 630,-962 630,4 -4,4"/>
|
|
||||||
<!-- A0 -->
|
|
||||||
<g id="node1" class="node">
|
|
||||||
<title>A0</title>
|
|
||||||
<polygon fill="#fff8dc" stroke="#000000" points="200.1964,-934 91.8036,-934 91.8036,-898 206.1964,-898 206.1964,-928 200.1964,-934"/>
|
|
||||||
<polyline fill="none" stroke="#000000" points="200.1964,-934 200.1964,-928 "/>
|
|
||||||
<polyline fill="none" stroke="#000000" points="206.1964,-928 200.1964,-928 "/>
|
|
||||||
<text text-anchor="middle" x="149" y="-919" font-family="Helvetica,sans-Serif" font-size="10.00" fill="#000000">You can stick notes</text>
|
|
||||||
<text text-anchor="middle" x="149" y="-907" font-family="Helvetica,sans-Serif" font-size="10.00" fill="#000000">on diagrams too!</text>
|
|
||||||
</g>
|
|
||||||
<!-- A1 -->
|
|
||||||
<g id="node2" class="node">
|
|
||||||
<title>A1</title>
|
|
||||||
<polygon fill="none" stroke="#000000" points="224,-926 224,-958 340,-958 340,-926 224,-926"/>
|
|
||||||
<text text-anchor="start" x="233.649" y="-939" font-family="Helvetica,sans-Serif" font-size="10.00" fill="#000000"><<AbstractIterMeta>></text>
|
|
||||||
<polygon fill="none" stroke="#000000" points="224,-906 224,-926 340,-926 340,-906 224,-906"/>
|
|
||||||
<polygon fill="none" stroke="#000000" points="224,-874 224,-906 340,-906 340,-874 224,-874"/>
|
|
||||||
<text text-anchor="start" x="260.61" y="-887" font-family="Helvetica,sans-Serif" font-size="10.00" fill="#000000">__iter__()</text>
|
|
||||||
</g>
|
|
||||||
<!-- A4 -->
|
|
||||||
<g id="node5" class="node">
|
|
||||||
<title>A4</title>
|
|
||||||
<polygon fill="none" stroke="#000000" points="187,-726 187,-758 378,-758 378,-726 187,-726"/>
|
|
||||||
<text text-anchor="start" x="248.5965" y="-739" font-family="Helvetica,sans-Serif" font-size="10.00" fill="#000000"><<InverterIfc>></text>
|
|
||||||
<polygon fill="none" stroke="#000000" points="187,-706 187,-726 378,-726 378,-706 187,-706"/>
|
|
||||||
<polygon fill="none" stroke="#000000" points="187,-650 187,-706 378,-706 378,-650 187,-650"/>
|
|
||||||
<text text-anchor="start" x="249.022" y="-687" font-family="Helvetica,sans-Serif" font-size="10.00" fill="#000000">healthy()->bool</text>
|
|
||||||
<text text-anchor="start" x="196.7835" y="-675" font-family="Helvetica,sans-Serif" font-size="10.00" fill="#000000"><async>disc(shutdown_started=False)</text>
|
|
||||||
<text text-anchor="start" x="228.044" y="-663" font-family="Helvetica,sans-Serif" font-size="10.00" fill="#000000"><async>create_remote()</text>
|
|
||||||
</g>
|
|
||||||
<!-- A1->A4 -->
|
|
||||||
<g id="edge1" class="edge">
|
|
||||||
<title>A1->A4</title>
|
|
||||||
<path fill="none" stroke="#000000" stroke-dasharray="5,2" d="M282,-863.7744C282,-831.6663 282,-790.6041 282,-758.1476"/>
|
|
||||||
<polygon fill="none" stroke="#000000" points="278.5001,-863.8621 282,-873.8622 285.5001,-863.8622 278.5001,-863.8621"/>
|
|
||||||
</g>
|
|
||||||
<!-- A2 -->
|
|
||||||
<g id="node3" class="node">
|
|
||||||
<title>A2</title>
|
|
||||||
<polygon fill="none" stroke="#000000" points="450,-454 450,-498 572,-498 572,-454 450,-454"/>
|
|
||||||
<text text-anchor="start" x="501.277" y="-479" font-family="Helvetica,sans-Serif" font-size="10.00" fill="#000000">Mqtt</text>
|
|
||||||
<text text-anchor="start" x="478.4815" y="-467" font-family="Helvetica,sans-Serif" font-size="10.00" fill="#000000"><<Singleton>></text>
|
|
||||||
<polygon fill="none" stroke="#000000" points="450,-398 450,-454 572,-454 572,-398 450,-398"/>
|
|
||||||
<text text-anchor="start" x="468.4875" y="-435" font-family="Helvetica,sans-Serif" font-size="10.00" fill="#000000"><static>ha_restarts</text>
|
|
||||||
<text text-anchor="start" x="476.2665" y="-423" font-family="Helvetica,sans-Serif" font-size="10.00" fill="#000000"><static>__client</text>
|
|
||||||
<text text-anchor="start" x="459.8735" y="-411" font-family="Helvetica,sans-Serif" font-size="10.00" fill="#000000"><static>__cb_MqttIsUp</text>
|
|
||||||
<polygon fill="none" stroke="#000000" points="450,-354 450,-398 572,-398 572,-354 450,-354"/>
|
|
||||||
<text text-anchor="start" x="472.936" y="-379" font-family="Helvetica,sans-Serif" font-size="10.00" fill="#000000"><async>publish()</text>
|
|
||||||
<text text-anchor="start" x="477.1045" y="-367" font-family="Helvetica,sans-Serif" font-size="10.00" fill="#000000"><async>close()</text>
|
|
||||||
</g>
|
|
||||||
<!-- A3 -->
|
|
||||||
<g id="node4" class="node">
|
|
||||||
<title>A3</title>
|
|
||||||
<polygon fill="none" stroke="#000000" points="396,-792 396,-824 626,-824 626,-792 396,-792"/>
|
|
||||||
<text text-anchor="start" x="498.2215" y="-805" font-family="Helvetica,sans-Serif" font-size="10.00" fill="#000000">Proxy</text>
|
|
||||||
<polygon fill="none" stroke="#000000" points="396,-676 396,-792 626,-792 626,-676 396,-676"/>
|
|
||||||
<text text-anchor="start" x="482.6545" y="-773" font-family="Helvetica,sans-Serif" font-size="10.00" fill="#000000"><cls>db_stat</text>
|
|
||||||
<text text-anchor="start" x="475.991" y="-761" font-family="Helvetica,sans-Serif" font-size="10.00" fill="#000000"><cls>entity_prfx</text>
|
|
||||||
<text text-anchor="start" x="466.826" y="-749" font-family="Helvetica,sans-Serif" font-size="10.00" fill="#000000"><cls>discovery_prfx</text>
|
|
||||||
<text text-anchor="start" x="466.262" y="-737" font-family="Helvetica,sans-Serif" font-size="10.00" fill="#000000"><cls>proxy_node_id</text>
|
|
||||||
<text text-anchor="start" x="462.373" y="-725" font-family="Helvetica,sans-Serif" font-size="10.00" fill="#000000"><cls>proxy_unique_id</text>
|
|
||||||
<text text-anchor="start" x="478.216" y="-713" font-family="Helvetica,sans-Serif" font-size="10.00" fill="#000000"><cls>mqtt:Mqtt</text>
|
|
||||||
<text text-anchor="start" x="480.4355" y="-689" font-family="Helvetica,sans-Serif" font-size="10.00" fill="#000000">__ha_restarts</text>
|
|
||||||
<polygon fill="none" stroke="#000000" points="396,-584 396,-676 626,-676 626,-584 396,-584"/>
|
|
||||||
<text text-anchor="start" x="487.1145" y="-657" font-family="Helvetica,sans-Serif" font-size="10.00" fill="#000000">class_init()</text>
|
|
||||||
<text text-anchor="start" x="481.834" y="-645" font-family="Helvetica,sans-Serif" font-size="10.00" fill="#000000">class_close()</text>
|
|
||||||
<text text-anchor="start" x="453.484" y="-621" font-family="Helvetica,sans-Serif" font-size="10.00" fill="#000000"><async>_cb_mqtt_is_up()</text>
|
|
||||||
<text text-anchor="start" x="405.697" y="-609" font-family="Helvetica,sans-Serif" font-size="10.00" fill="#000000"><async>_register_proxy_stat_home_assistant()</text>
|
|
||||||
<text text-anchor="start" x="414.584" y="-597" font-family="Helvetica,sans-Serif" font-size="10.00" fill="#000000"><async>_async_publ_mqtt_proxy_stat(key)</text>
|
|
||||||
</g>
|
|
||||||
<!-- A3->A2 -->
|
|
||||||
<g id="edge9" class="edge">
|
|
||||||
<title>A3->A2</title>
|
|
||||||
<path fill="none" stroke="#000000" d="M511,-571.373C511,-549.9571 511,-528.339 511,-508.5579"/>
|
|
||||||
<polygon fill="#000000" stroke="#000000" points="511.0001,-571.682 515,-577.6821 511,-583.682 507,-577.682 511.0001,-571.682"/>
|
|
||||||
<polygon fill="#000000" stroke="#000000" points="511,-498.392 515.5001,-508.3919 511,-503.392 511.0001,-508.392 511.0001,-508.392 511.0001,-508.392 511,-503.392 506.5001,-508.392 511,-498.392 511,-498.392"/>
|
|
||||||
</g>
|
|
||||||
<!-- A5 -->
|
|
||||||
<g id="node6" class="node">
|
|
||||||
<title>A5</title>
|
|
||||||
<polygon fill="none" stroke="#000000" points="214,-502 214,-534 405,-534 405,-502 214,-502"/>
|
|
||||||
<text text-anchor="start" x="281.16" y="-515" font-family="Helvetica,sans-Serif" font-size="10.00" fill="#000000">InverterBase</text>
|
|
||||||
<polygon fill="none" stroke="#000000" points="214,-386 214,-502 405,-502 405,-386 214,-386"/>
|
|
||||||
<text text-anchor="start" x="290.3335" y="-483" font-family="Helvetica,sans-Serif" font-size="10.00" fill="#000000">_registry</text>
|
|
||||||
<text text-anchor="start" x="278.9355" y="-471" font-family="Helvetica,sans-Serif" font-size="10.00" fill="#000000">__ha_restarts</text>
|
|
||||||
<text text-anchor="start" x="299.497" y="-447" font-family="Helvetica,sans-Serif" font-size="10.00" fill="#000000">addr</text>
|
|
||||||
<text text-anchor="start" x="282.5505" y="-435" font-family="Helvetica,sans-Serif" font-size="10.00" fill="#000000">config_id:str</text>
|
|
||||||
<text text-anchor="start" x="255.8785" y="-423" font-family="Helvetica,sans-Serif" font-size="10.00" fill="#000000">prot_class:MessageProt</text>
|
|
||||||
<text text-anchor="start" x="270.053" y="-411" font-family="Helvetica,sans-Serif" font-size="10.00" fill="#000000">remote:StreamPtr</text>
|
|
||||||
<text text-anchor="start" x="275.332" y="-399" font-family="Helvetica,sans-Serif" font-size="10.00" fill="#000000">local:StreamPtr</text>
|
|
||||||
<polygon fill="none" stroke="#000000" points="214,-318 214,-386 405,-386 405,-318 214,-318"/>
|
|
||||||
<text text-anchor="start" x="276.022" y="-367" font-family="Helvetica,sans-Serif" font-size="10.00" fill="#000000">healthy()->bool</text>
|
|
||||||
<text text-anchor="start" x="223.7835" y="-355" font-family="Helvetica,sans-Serif" font-size="10.00" fill="#000000"><async>disc(shutdown_started=False)</text>
|
|
||||||
<text text-anchor="start" x="255.044" y="-343" font-family="Helvetica,sans-Serif" font-size="10.00" fill="#000000"><async>create_remote()</text>
|
|
||||||
<text text-anchor="start" x="249.484" y="-331" font-family="Helvetica,sans-Serif" font-size="10.00" fill="#000000"><async>async_publ_mqtt()</text>
|
|
||||||
</g>
|
|
||||||
<!-- A3->A5 -->
|
|
||||||
<g id="edge7" class="edge">
|
|
||||||
<title>A3->A5</title>
|
|
||||||
<path fill="none" stroke="#000000" d="M417.6791,-575.5683C407.6409,-561.7533 397.5008,-547.7982 387.6588,-534.2532"/>
|
|
||||||
<polygon fill="none" stroke="#000000" points="414.8649,-577.6495 423.5747,-583.682 420.5279,-573.5347 414.8649,-577.6495"/>
|
|
||||||
</g>
|
|
||||||
<!-- A4->A5 -->
|
|
||||||
<g id="edge2" class="edge">
|
|
||||||
<title>A4->A5</title>
|
|
||||||
<path fill="none" stroke="#000000" stroke-dasharray="5,2" d="M288.2719,-639.4228C291.3086,-608.1559 295.0373,-569.7639 298.491,-534.2034"/>
|
|
||||||
<polygon fill="none" stroke="#000000" points="284.7531,-639.4473 287.27,-649.7389 291.7203,-640.1241 284.7531,-639.4473"/>
|
|
||||||
</g>
|
|
||||||
<!-- A6 -->
|
|
||||||
<g id="node7" class="node">
|
|
||||||
<title>A6</title>
|
|
||||||
<polygon fill="none" stroke="#000000" points="365,-236 365,-268 465,-268 465,-236 365,-236"/>
|
|
||||||
<text text-anchor="start" x="392.4995" y="-249" font-family="Helvetica,sans-Serif" font-size="10.00" fill="#000000">StreamPtr</text>
|
|
||||||
<polygon fill="none" stroke="#000000" points="365,-216 365,-236 465,-236 465,-216 365,-216"/>
|
|
||||||
<polygon fill="none" stroke="#000000" points="365,-172 365,-216 465,-216 465,-172 365,-172"/>
|
|
||||||
<text text-anchor="start" x="374.7175" y="-197" font-family="Helvetica,sans-Serif" font-size="10.00" fill="#000000">stream:ProtocolIfc</text>
|
|
||||||
<text text-anchor="start" x="389.7185" y="-185" font-family="Helvetica,sans-Serif" font-size="10.00" fill="#000000">ifc:AsyncIfc</text>
|
|
||||||
</g>
|
|
||||||
<!-- A5->A6 -->
|
|
||||||
<g id="edge8" class="edge">
|
|
||||||
<title>A5->A6</title>
|
|
||||||
<path fill="none" stroke="#000000" d="M364.6387,-317.872C371.8786,-303.802 379.0526,-289.86 385.6187,-277.0995"/>
|
|
||||||
<polygon fill="#000000" stroke="#000000" points="390.2846,-268.0318 389.7105,-278.9826 387.9969,-272.4777 385.7091,-276.9237 385.7091,-276.9237 385.7091,-276.9237 387.9969,-272.4777 381.7078,-274.8647 390.2846,-268.0318 390.2846,-268.0318"/>
|
|
||||||
<text text-anchor="middle" x="389.5069" y="-285.0166" font-family="Helvetica,sans-Serif" font-size="10.00" fill="#000000">2</text>
|
|
||||||
</g>
|
|
||||||
<!-- A7 -->
|
|
||||||
<g id="node8" class="node">
|
|
||||||
<title>A7</title>
|
|
||||||
<polygon fill="none" stroke="#000000" points="346.7314,-238 271.2686,-238 271.2686,-202 346.7314,-202 346.7314,-238"/>
|
|
||||||
<text text-anchor="middle" x="309" y="-217" font-family="Helvetica,sans-Serif" font-size="10.00" fill="#000000">InverterG3</text>
|
|
||||||
</g>
|
|
||||||
<!-- A5->A7 -->
|
|
||||||
<g id="edge5" class="edge">
|
|
||||||
<title>A5->A7</title>
|
|
||||||
<path fill="none" stroke="#000000" d="M309,-307.7729C309,-280.5002 309,-254.684 309,-238.2013"/>
|
|
||||||
<polygon fill="none" stroke="#000000" points="305.5001,-307.872 309,-317.872 312.5001,-307.872 305.5001,-307.872"/>
|
|
||||||
</g>
|
|
||||||
<!-- A9 -->
|
|
||||||
<g id="node10" class="node">
|
|
||||||
<title>A9</title>
|
|
||||||
<polygon fill="none" stroke="#000000" points="102.9001,-238 21.0999,-238 21.0999,-202 102.9001,-202 102.9001,-238"/>
|
|
||||||
<text text-anchor="middle" x="62" y="-217" font-family="Helvetica,sans-Serif" font-size="10.00" fill="#000000">InverterG3P</text>
|
|
||||||
</g>
|
|
||||||
<!-- A5->A9 -->
|
|
||||||
<g id="edge6" class="edge">
|
|
||||||
<title>A5->A9</title>
|
|
||||||
<path fill="none" stroke="#000000" d="M205.2667,-346.4637C174.3973,-321.9347 140.8582,-294.4156 111,-268 100.2971,-258.5312 88.8616,-247.3925 79.732,-238.23"/>
|
|
||||||
<polygon fill="none" stroke="#000000" points="203.462,-349.4991 213.4739,-352.965 207.8086,-344.0121 203.462,-349.4991"/>
|
|
||||||
</g>
|
|
||||||
<!-- A11 -->
|
|
||||||
<g id="node12" class="node">
|
|
||||||
<title>A11</title>
|
|
||||||
<polygon fill="none" stroke="#000000" points="458.6421,-36 369.3579,-36 369.3579,0 458.6421,0 458.6421,-36"/>
|
|
||||||
<text text-anchor="middle" x="414" y="-15" font-family="Helvetica,sans-Serif" font-size="10.00" fill="#000000"><<AsyncIfc>></text>
|
|
||||||
</g>
|
|
||||||
<!-- A6->A11 -->
|
|
||||||
<g id="edge11" class="edge">
|
|
||||||
<title>A6->A11</title>
|
|
||||||
<path fill="none" stroke="#000000" d="M401.1633,-171.974C395.4982,-146.4565 391.0868,-114.547 395,-86 396.8468,-72.5276 400.661,-57.9618 404.3907,-45.7804"/>
|
|
||||||
<polygon fill="#000000" stroke="#000000" points="407.4587,-36.1851 408.6994,-47.0805 405.9359,-40.9476 404.4131,-45.71 404.4131,-45.71 404.4131,-45.71 405.9359,-40.9476 400.1269,-44.3395 407.4587,-36.1851 407.4587,-36.1851"/>
|
|
||||||
<text text-anchor="middle" x="409.9892" y="-53.0243" font-family="Helvetica,sans-Serif" font-size="10.00" fill="#000000">1</text>
|
|
||||||
</g>
|
|
||||||
<!-- A12 -->
|
|
||||||
<g id="node13" class="node">
|
|
||||||
<title>A12</title>
|
|
||||||
<polygon fill="none" stroke="#000000" points="502.0879,-122 403.9121,-122 403.9121,-86 502.0879,-86 502.0879,-122"/>
|
|
||||||
<text text-anchor="middle" x="453" y="-101" font-family="Helvetica,sans-Serif" font-size="10.00" fill="#000000"><<ProtocolIfc>></text>
|
|
||||||
</g>
|
|
||||||
<!-- A6->A12 -->
|
|
||||||
<g id="edge10" class="edge">
|
|
||||||
<title>A6->A12</title>
|
|
||||||
<path fill="none" stroke="#000000" d="M430.7853,-171.8133C435.2329,-158.2365 439.9225,-143.9208 443.8408,-131.9595"/>
|
|
||||||
<polygon fill="#000000" stroke="#000000" points="447.0602,-122.132 448.2235,-133.036 445.5036,-126.8835 443.9471,-131.6351 443.9471,-131.6351 443.9471,-131.6351 445.5036,-126.8835 439.6707,-130.2341 447.0602,-122.132 447.0602,-122.132"/>
|
|
||||||
<text text-anchor="middle" x="449.4498" y="-138.9887" font-family="Helvetica,sans-Serif" font-size="10.00" fill="#000000">1</text>
|
|
||||||
</g>
|
|
||||||
<!-- A8 -->
|
|
||||||
<g id="node9" class="node">
|
|
||||||
<title>A8</title>
|
|
||||||
<polygon fill="#fff8dc" stroke="#000000" points="583.406,-248 482.594,-248 482.594,-192 589.406,-192 589.406,-242 583.406,-248"/>
|
|
||||||
<polyline fill="none" stroke="#000000" points="583.406,-248 583.406,-242 "/>
|
|
||||||
<polyline fill="none" stroke="#000000" points="589.406,-242 583.406,-242 "/>
|
|
||||||
<text text-anchor="middle" x="536" y="-235" font-family="Helvetica,sans-Serif" font-size="10.00" fill="#000000">Creates an GEN3</text>
|
|
||||||
<text text-anchor="middle" x="536" y="-223" font-family="Helvetica,sans-Serif" font-size="10.00" fill="#000000">inverter instance</text>
|
|
||||||
<text text-anchor="middle" x="536" y="-211" font-family="Helvetica,sans-Serif" font-size="10.00" fill="#000000">with</text>
|
|
||||||
<text text-anchor="middle" x="536" y="-199" font-family="Helvetica,sans-Serif" font-size="10.00" fill="#000000">prot_class:Talent</text>
|
|
||||||
</g>
|
|
||||||
<!-- A7->A8 -->
|
|
||||||
<g id="edge3" class="edge">
|
|
||||||
<title>A7->A8</title>
|
|
||||||
<path fill="none" stroke="#000000" stroke-dasharray="5,2" d="M317.0491,-238.3283C325.9345,-256.0056 342.0793,-281.6949 365,-293 404.8598,-312.6598 424.0578,-310.2929 465,-293 486.6607,-283.8511 504.9784,-264.5049 517.5802,-248.0264"/>
|
|
||||||
</g>
|
|
||||||
<!-- A10 -->
|
|
||||||
<g id="node11" class="node">
|
|
||||||
<title>A10</title>
|
|
||||||
<polygon fill="#fff8dc" stroke="#000000" points="247.522,-248 120.478,-248 120.478,-192 253.522,-192 253.522,-242 247.522,-248"/>
|
|
||||||
<polyline fill="none" stroke="#000000" points="247.522,-248 247.522,-242 "/>
|
|
||||||
<polyline fill="none" stroke="#000000" points="253.522,-242 247.522,-242 "/>
|
|
||||||
<text text-anchor="middle" x="187" y="-235" font-family="Helvetica,sans-Serif" font-size="10.00" fill="#000000">Creates an GEN3PLUS</text>
|
|
||||||
<text text-anchor="middle" x="187" y="-223" font-family="Helvetica,sans-Serif" font-size="10.00" fill="#000000">inverter instance</text>
|
|
||||||
<text text-anchor="middle" x="187" y="-211" font-family="Helvetica,sans-Serif" font-size="10.00" fill="#000000">with</text>
|
|
||||||
<text text-anchor="middle" x="187" y="-199" font-family="Helvetica,sans-Serif" font-size="10.00" fill="#000000">prot_class:SolarmanV5</text>
|
|
||||||
</g>
|
|
||||||
<!-- A9->A10 -->
|
|
||||||
<g id="edge4" class="edge">
|
|
||||||
<title>A9->A10</title>
|
|
||||||
<path fill="none" stroke="#000000" stroke-dasharray="5,2" d="M103.0156,-220C108.8114,-220 114.6072,-220 120.403,-220"/>
|
|
||||||
</g>
|
|
||||||
<!-- A12->A11 -->
|
|
||||||
<g id="edge12" class="edge">
|
|
||||||
<title>A12->A11</title>
|
|
||||||
<path fill="none" stroke="#000000" stroke-dasharray="5,2" d="M444.7291,-85.7616C439.4033,-74.0176 432.3824,-58.5355 426.396,-45.3349"/>
|
|
||||||
<polygon fill="#000000" stroke="#000000" points="422.259,-36.2121 430.4874,-43.4608 424.324,-40.7657 426.3891,-45.3194 426.3891,-45.3194 426.3891,-45.3194 424.324,-40.7657 422.2908,-47.1779 422.259,-36.2121 422.259,-36.2121"/>
|
|
||||||
<text text-anchor="middle" x="429.5451" y="-69.7445" font-family="Helvetica,sans-Serif" font-size="10.00" fill="#000000">use</text>
|
|
||||||
</g>
|
|
||||||
<!-- A13 -->
|
|
||||||
<g id="node14" class="node">
|
|
||||||
<title>A13</title>
|
|
||||||
<polygon fill="none" stroke="#000000" points="9,-454 9,-486 116,-486 116,-454 9,-454"/>
|
|
||||||
<text text-anchor="start" x="32.7695" y="-467" font-family="Helvetica,sans-Serif" font-size="10.00" fill="#000000">ModbusConn</text>
|
|
||||||
<polygon fill="none" stroke="#000000" points="9,-386 9,-454 116,-454 116,-386 9,-386"/>
|
|
||||||
<text text-anchor="start" x="53.0515" y="-435" font-family="Helvetica,sans-Serif" font-size="10.00" fill="#000000">host</text>
|
|
||||||
<text text-anchor="start" x="53.887" y="-423" font-family="Helvetica,sans-Serif" font-size="10.00" fill="#000000">port</text>
|
|
||||||
<text text-anchor="start" x="52.497" y="-411" font-family="Helvetica,sans-Serif" font-size="10.00" fill="#000000">addr</text>
|
|
||||||
<text text-anchor="start" x="18.883" y="-399" font-family="Helvetica,sans-Serif" font-size="10.00" fill="#000000">stream:InverterG3P</text>
|
|
||||||
<polygon fill="none" stroke="#000000" points="9,-366 9,-386 116,-386 116,-366 9,-366"/>
|
|
||||||
</g>
|
|
||||||
<!-- A13->A9 -->
|
|
||||||
<g id="edge13" class="edge">
|
|
||||||
<title>A13->A9</title>
|
|
||||||
<path fill="none" stroke="#000000" d="M62,-365.8625C62,-327.1513 62,-278.6088 62,-248.4442"/>
|
|
||||||
<polygon fill="#000000" stroke="#000000" points="62,-238.2147 66.5001,-248.2147 62,-243.2147 62.0001,-248.2147 62.0001,-248.2147 62.0001,-248.2147 62,-243.2147 57.5001,-248.2148 62,-238.2147 62,-238.2147"/>
|
|
||||||
<text text-anchor="middle" x="70.4524" y="-253.3409" font-family="Helvetica,sans-Serif" font-size="10.00" fill="#000000">1</text>
|
|
||||||
<text text-anchor="middle" x="53.5476" y="-344.7363" font-family="Helvetica,sans-Serif" font-size="10.00" fill="#000000">has</text>
|
|
||||||
</g>
|
|
||||||
<!-- A14 -->
|
|
||||||
<g id="node15" class="node">
|
|
||||||
<title>A14</title>
|
|
||||||
<polygon fill="none" stroke="#000000" points="0,-714 0,-746 124,-746 124,-714 0,-714"/>
|
|
||||||
<text text-anchor="start" x="35.8835" y="-727" font-family="Helvetica,sans-Serif" font-size="10.00" fill="#000000">ModbusTcp</text>
|
|
||||||
<polygon fill="none" stroke="#000000" points="0,-694 0,-714 124,-714 124,-694 0,-694"/>
|
|
||||||
<polygon fill="none" stroke="#000000" points="0,-662 0,-694 124,-694 124,-662 0,-662"/>
|
|
||||||
<text text-anchor="start" x="9.763" y="-675" font-family="Helvetica,sans-Serif" font-size="10.00" fill="#000000"><async>modbus_loop()</text>
|
|
||||||
</g>
|
|
||||||
<!-- A14->A13 -->
|
|
||||||
<g id="edge14" class="edge">
|
|
||||||
<title>A14->A13</title>
|
|
||||||
<path fill="none" stroke="#000000" d="M62,-661.7778C62,-617.9184 62,-548.5387 62,-496.3736"/>
|
|
||||||
<polygon fill="#000000" stroke="#000000" points="62,-486.1827 66.5001,-496.1827 62,-491.1827 62.0001,-496.1827 62.0001,-496.1827 62.0001,-496.1827 62,-491.1827 57.5001,-496.1828 62,-486.1827 62,-486.1827"/>
|
|
||||||
<text text-anchor="middle" x="70.4524" y="-501.3089" font-family="Helvetica,sans-Serif" font-size="10.00" fill="#000000">*</text>
|
|
||||||
<text text-anchor="middle" x="53.5476" y="-640.6516" font-family="Helvetica,sans-Serif" font-size="10.00" fill="#000000">creates</text>
|
|
||||||
</g>
|
|
||||||
</g>
|
|
||||||
</svg>
|
|
||||||
|
Before Width: | Height: | Size: 20 KiB |
260
app/proxy.svg
Normal file
260
app/proxy.svg
Normal file
@@ -0,0 +1,260 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||||
|
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN"
|
||||||
|
"http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
|
||||||
|
<!-- Generated by graphviz version 2.40.1 (20161225.0304)
|
||||||
|
-->
|
||||||
|
<!-- Title: G Pages: 1 -->
|
||||||
|
<svg width="626pt" height="966pt"
|
||||||
|
viewBox="0.00 0.00 625.50 966.00" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
|
||||||
|
<g id="graph0" class="graph" transform="scale(1 1) rotate(0) translate(4 962)">
|
||||||
|
<title>G</title>
|
||||||
|
<polygon fill="#ffffff" stroke="transparent" points="-4,4 -4,-962 621.5,-962 621.5,4 -4,4"/>
|
||||||
|
<!-- A0 -->
|
||||||
|
<g id="node1" class="node">
|
||||||
|
<title>A0</title>
|
||||||
|
<polygon fill="#fff8dc" stroke="#000000" points="191.6964,-934 83.3036,-934 83.3036,-898 197.6964,-898 197.6964,-928 191.6964,-934"/>
|
||||||
|
<polyline fill="none" stroke="#000000" points="191.6964,-934 191.6964,-928 "/>
|
||||||
|
<polyline fill="none" stroke="#000000" points="197.6964,-928 191.6964,-928 "/>
|
||||||
|
<text text-anchor="middle" x="140.5" y="-919" font-family="Helvetica,sans-Serif" font-size="10.00" fill="#000000">You can stick notes</text>
|
||||||
|
<text text-anchor="middle" x="140.5" y="-907" font-family="Helvetica,sans-Serif" font-size="10.00" fill="#000000">on diagrams too!</text>
|
||||||
|
</g>
|
||||||
|
<!-- A1 -->
|
||||||
|
<g id="node2" class="node">
|
||||||
|
<title>A1</title>
|
||||||
|
<polygon fill="none" stroke="#000000" points="215.5,-926 215.5,-958 331.5,-958 331.5,-926 215.5,-926"/>
|
||||||
|
<text text-anchor="start" x="225.149" y="-939" font-family="Helvetica,sans-Serif" font-size="10.00" fill="#000000"><<AbstractIterMeta>></text>
|
||||||
|
<polygon fill="none" stroke="#000000" points="215.5,-906 215.5,-926 331.5,-926 331.5,-906 215.5,-906"/>
|
||||||
|
<polygon fill="none" stroke="#000000" points="215.5,-874 215.5,-906 331.5,-906 331.5,-874 215.5,-874"/>
|
||||||
|
<text text-anchor="start" x="252.11" y="-887" font-family="Helvetica,sans-Serif" font-size="10.00" fill="#000000">__iter__()</text>
|
||||||
|
</g>
|
||||||
|
<!-- A4 -->
|
||||||
|
<g id="node5" class="node">
|
||||||
|
<title>A4</title>
|
||||||
|
<polygon fill="none" stroke="#000000" points="178.5,-726 178.5,-758 369.5,-758 369.5,-726 178.5,-726"/>
|
||||||
|
<text text-anchor="start" x="240.0965" y="-739" font-family="Helvetica,sans-Serif" font-size="10.00" fill="#000000"><<InverterIfc>></text>
|
||||||
|
<polygon fill="none" stroke="#000000" points="178.5,-706 178.5,-726 369.5,-726 369.5,-706 178.5,-706"/>
|
||||||
|
<polygon fill="none" stroke="#000000" points="178.5,-650 178.5,-706 369.5,-706 369.5,-650 178.5,-650"/>
|
||||||
|
<text text-anchor="start" x="240.522" y="-687" font-family="Helvetica,sans-Serif" font-size="10.00" fill="#000000">healthy()->bool</text>
|
||||||
|
<text text-anchor="start" x="188.2835" y="-675" font-family="Helvetica,sans-Serif" font-size="10.00" fill="#000000"><async>disc(shutdown_started=False)</text>
|
||||||
|
<text text-anchor="start" x="219.544" y="-663" font-family="Helvetica,sans-Serif" font-size="10.00" fill="#000000"><async>create_remote()</text>
|
||||||
|
</g>
|
||||||
|
<!-- A1->A4 -->
|
||||||
|
<g id="edge1" class="edge">
|
||||||
|
<title>A1->A4</title>
|
||||||
|
<path fill="none" stroke="#000000" stroke-dasharray="5,2" d="M273.5,-863.7744C273.5,-831.6663 273.5,-790.6041 273.5,-758.1476"/>
|
||||||
|
<polygon fill="none" stroke="#000000" points="270.0001,-863.8621 273.5,-873.8622 277.0001,-863.8622 270.0001,-863.8621"/>
|
||||||
|
</g>
|
||||||
|
<!-- A2 -->
|
||||||
|
<g id="node3" class="node">
|
||||||
|
<title>A2</title>
|
||||||
|
<polygon fill="none" stroke="#000000" points="441.5,-454 441.5,-498 563.5,-498 563.5,-454 441.5,-454"/>
|
||||||
|
<text text-anchor="start" x="492.777" y="-479" font-family="Helvetica,sans-Serif" font-size="10.00" fill="#000000">Mqtt</text>
|
||||||
|
<text text-anchor="start" x="469.9815" y="-467" font-family="Helvetica,sans-Serif" font-size="10.00" fill="#000000"><<Singleton>></text>
|
||||||
|
<polygon fill="none" stroke="#000000" points="441.5,-398 441.5,-454 563.5,-454 563.5,-398 441.5,-398"/>
|
||||||
|
<text text-anchor="start" x="459.9875" y="-435" font-family="Helvetica,sans-Serif" font-size="10.00" fill="#000000"><static>ha_restarts</text>
|
||||||
|
<text text-anchor="start" x="467.7665" y="-423" font-family="Helvetica,sans-Serif" font-size="10.00" fill="#000000"><static>__client</text>
|
||||||
|
<text text-anchor="start" x="451.3735" y="-411" font-family="Helvetica,sans-Serif" font-size="10.00" fill="#000000"><static>__cb_MqttIsUp</text>
|
||||||
|
<polygon fill="none" stroke="#000000" points="441.5,-354 441.5,-398 563.5,-398 563.5,-354 441.5,-354"/>
|
||||||
|
<text text-anchor="start" x="464.436" y="-379" font-family="Helvetica,sans-Serif" font-size="10.00" fill="#000000"><async>publish()</text>
|
||||||
|
<text text-anchor="start" x="468.6045" y="-367" font-family="Helvetica,sans-Serif" font-size="10.00" fill="#000000"><async>close()</text>
|
||||||
|
</g>
|
||||||
|
<!-- A3 -->
|
||||||
|
<g id="node4" class="node">
|
||||||
|
<title>A3</title>
|
||||||
|
<polygon fill="none" stroke="#000000" points="387.5,-792 387.5,-824 617.5,-824 617.5,-792 387.5,-792"/>
|
||||||
|
<text text-anchor="start" x="489.7215" y="-805" font-family="Helvetica,sans-Serif" font-size="10.00" fill="#000000">Proxy</text>
|
||||||
|
<polygon fill="none" stroke="#000000" points="387.5,-676 387.5,-792 617.5,-792 617.5,-676 387.5,-676"/>
|
||||||
|
<text text-anchor="start" x="474.1545" y="-773" font-family="Helvetica,sans-Serif" font-size="10.00" fill="#000000"><cls>db_stat</text>
|
||||||
|
<text text-anchor="start" x="467.491" y="-761" font-family="Helvetica,sans-Serif" font-size="10.00" fill="#000000"><cls>entity_prfx</text>
|
||||||
|
<text text-anchor="start" x="458.326" y="-749" font-family="Helvetica,sans-Serif" font-size="10.00" fill="#000000"><cls>discovery_prfx</text>
|
||||||
|
<text text-anchor="start" x="457.762" y="-737" font-family="Helvetica,sans-Serif" font-size="10.00" fill="#000000"><cls>proxy_node_id</text>
|
||||||
|
<text text-anchor="start" x="453.873" y="-725" font-family="Helvetica,sans-Serif" font-size="10.00" fill="#000000"><cls>proxy_unique_id</text>
|
||||||
|
<text text-anchor="start" x="469.716" y="-713" font-family="Helvetica,sans-Serif" font-size="10.00" fill="#000000"><cls>mqtt:Mqtt</text>
|
||||||
|
<text text-anchor="start" x="471.9355" y="-689" font-family="Helvetica,sans-Serif" font-size="10.00" fill="#000000">__ha_restarts</text>
|
||||||
|
<polygon fill="none" stroke="#000000" points="387.5,-584 387.5,-676 617.5,-676 617.5,-584 387.5,-584"/>
|
||||||
|
<text text-anchor="start" x="478.6145" y="-657" font-family="Helvetica,sans-Serif" font-size="10.00" fill="#000000">class_init()</text>
|
||||||
|
<text text-anchor="start" x="473.334" y="-645" font-family="Helvetica,sans-Serif" font-size="10.00" fill="#000000">class_close()</text>
|
||||||
|
<text text-anchor="start" x="444.984" y="-621" font-family="Helvetica,sans-Serif" font-size="10.00" fill="#000000"><async>_cb_mqtt_is_up()</text>
|
||||||
|
<text text-anchor="start" x="397.197" y="-609" font-family="Helvetica,sans-Serif" font-size="10.00" fill="#000000"><async>_register_proxy_stat_home_assistant()</text>
|
||||||
|
<text text-anchor="start" x="406.084" y="-597" font-family="Helvetica,sans-Serif" font-size="10.00" fill="#000000"><async>_async_publ_mqtt_proxy_stat(key)</text>
|
||||||
|
</g>
|
||||||
|
<!-- A3->A2 -->
|
||||||
|
<g id="edge9" class="edge">
|
||||||
|
<title>A3->A2</title>
|
||||||
|
<path fill="none" stroke="#000000" d="M502.5,-571.373C502.5,-549.9571 502.5,-528.339 502.5,-508.5579"/>
|
||||||
|
<polygon fill="#000000" stroke="#000000" points="502.5001,-571.682 506.5,-577.6821 502.5,-583.682 498.5,-577.682 502.5001,-571.682"/>
|
||||||
|
<polygon fill="#000000" stroke="#000000" points="502.5,-498.392 507.0001,-508.3919 502.5,-503.392 502.5001,-508.392 502.5001,-508.392 502.5001,-508.392 502.5,-503.392 498.0001,-508.392 502.5,-498.392 502.5,-498.392"/>
|
||||||
|
</g>
|
||||||
|
<!-- A5 -->
|
||||||
|
<g id="node6" class="node">
|
||||||
|
<title>A5</title>
|
||||||
|
<polygon fill="none" stroke="#000000" points="205.5,-502 205.5,-534 396.5,-534 396.5,-502 205.5,-502"/>
|
||||||
|
<text text-anchor="start" x="272.66" y="-515" font-family="Helvetica,sans-Serif" font-size="10.00" fill="#000000">InverterBase</text>
|
||||||
|
<polygon fill="none" stroke="#000000" points="205.5,-386 205.5,-502 396.5,-502 396.5,-386 205.5,-386"/>
|
||||||
|
<text text-anchor="start" x="281.8335" y="-483" font-family="Helvetica,sans-Serif" font-size="10.00" fill="#000000">_registry</text>
|
||||||
|
<text text-anchor="start" x="270.4355" y="-471" font-family="Helvetica,sans-Serif" font-size="10.00" fill="#000000">__ha_restarts</text>
|
||||||
|
<text text-anchor="start" x="290.997" y="-447" font-family="Helvetica,sans-Serif" font-size="10.00" fill="#000000">addr</text>
|
||||||
|
<text text-anchor="start" x="274.0505" y="-435" font-family="Helvetica,sans-Serif" font-size="10.00" fill="#000000">config_id:str</text>
|
||||||
|
<text text-anchor="start" x="247.3785" y="-423" font-family="Helvetica,sans-Serif" font-size="10.00" fill="#000000">prot_class:MessageProt</text>
|
||||||
|
<text text-anchor="start" x="261.553" y="-411" font-family="Helvetica,sans-Serif" font-size="10.00" fill="#000000">remote:StreamPtr</text>
|
||||||
|
<text text-anchor="start" x="266.832" y="-399" font-family="Helvetica,sans-Serif" font-size="10.00" fill="#000000">local:StreamPtr</text>
|
||||||
|
<polygon fill="none" stroke="#000000" points="205.5,-318 205.5,-386 396.5,-386 396.5,-318 205.5,-318"/>
|
||||||
|
<text text-anchor="start" x="267.522" y="-367" font-family="Helvetica,sans-Serif" font-size="10.00" fill="#000000">healthy()->bool</text>
|
||||||
|
<text text-anchor="start" x="215.2835" y="-355" font-family="Helvetica,sans-Serif" font-size="10.00" fill="#000000"><async>disc(shutdown_started=False)</text>
|
||||||
|
<text text-anchor="start" x="246.544" y="-343" font-family="Helvetica,sans-Serif" font-size="10.00" fill="#000000"><async>create_remote()</text>
|
||||||
|
<text text-anchor="start" x="240.984" y="-331" font-family="Helvetica,sans-Serif" font-size="10.00" fill="#000000"><async>async_publ_mqtt()</text>
|
||||||
|
</g>
|
||||||
|
<!-- A3->A5 -->
|
||||||
|
<g id="edge7" class="edge">
|
||||||
|
<title>A3->A5</title>
|
||||||
|
<path fill="none" stroke="#000000" d="M409.1791,-575.5683C399.1409,-561.7533 389.0008,-547.7982 379.1588,-534.2532"/>
|
||||||
|
<polygon fill="none" stroke="#000000" points="406.3649,-577.6495 415.0747,-583.682 412.0279,-573.5347 406.3649,-577.6495"/>
|
||||||
|
</g>
|
||||||
|
<!-- A4->A5 -->
|
||||||
|
<g id="edge2" class="edge">
|
||||||
|
<title>A4->A5</title>
|
||||||
|
<path fill="none" stroke="#000000" stroke-dasharray="5,2" d="M279.7719,-639.4228C282.8086,-608.1559 286.5373,-569.7639 289.991,-534.2034"/>
|
||||||
|
<polygon fill="none" stroke="#000000" points="276.2531,-639.4473 278.77,-649.7389 283.2203,-640.1241 276.2531,-639.4473"/>
|
||||||
|
</g>
|
||||||
|
<!-- A6 -->
|
||||||
|
<g id="node7" class="node">
|
||||||
|
<title>A6</title>
|
||||||
|
<polygon fill="none" stroke="#000000" points="356.5,-236 356.5,-268 456.5,-268 456.5,-236 356.5,-236"/>
|
||||||
|
<text text-anchor="start" x="383.9995" y="-249" font-family="Helvetica,sans-Serif" font-size="10.00" fill="#000000">StreamPtr</text>
|
||||||
|
<polygon fill="none" stroke="#000000" points="356.5,-216 356.5,-236 456.5,-236 456.5,-216 356.5,-216"/>
|
||||||
|
<polygon fill="none" stroke="#000000" points="356.5,-172 356.5,-216 456.5,-216 456.5,-172 356.5,-172"/>
|
||||||
|
<text text-anchor="start" x="366.2175" y="-197" font-family="Helvetica,sans-Serif" font-size="10.00" fill="#000000">stream:ProtocolIfc</text>
|
||||||
|
<text text-anchor="start" x="381.2185" y="-185" font-family="Helvetica,sans-Serif" font-size="10.00" fill="#000000">ifc:AsyncIfc</text>
|
||||||
|
</g>
|
||||||
|
<!-- A5->A6 -->
|
||||||
|
<g id="edge8" class="edge">
|
||||||
|
<title>A5->A6</title>
|
||||||
|
<path fill="none" stroke="#000000" d="M356.1387,-317.872C363.3786,-303.802 370.5526,-289.86 377.1187,-277.0995"/>
|
||||||
|
<polygon fill="#000000" stroke="#000000" points="381.7846,-268.0318 381.2105,-278.9826 379.4969,-272.4777 377.2091,-276.9237 377.2091,-276.9237 377.2091,-276.9237 379.4969,-272.4777 373.2078,-274.8647 381.7846,-268.0318 381.7846,-268.0318"/>
|
||||||
|
<text text-anchor="middle" x="381.0069" y="-285.0166" font-family="Helvetica,sans-Serif" font-size="10.00" fill="#000000">2</text>
|
||||||
|
</g>
|
||||||
|
<!-- A7 -->
|
||||||
|
<g id="node8" class="node">
|
||||||
|
<title>A7</title>
|
||||||
|
<polygon fill="none" stroke="#000000" points="338.2314,-238 262.7686,-238 262.7686,-202 338.2314,-202 338.2314,-238"/>
|
||||||
|
<text text-anchor="middle" x="300.5" y="-217" font-family="Helvetica,sans-Serif" font-size="10.00" fill="#000000">InverterG3</text>
|
||||||
|
</g>
|
||||||
|
<!-- A5->A7 -->
|
||||||
|
<g id="edge5" class="edge">
|
||||||
|
<title>A5->A7</title>
|
||||||
|
<path fill="none" stroke="#000000" d="M300.5,-307.7729C300.5,-280.5002 300.5,-254.684 300.5,-238.2013"/>
|
||||||
|
<polygon fill="none" stroke="#000000" points="297.0001,-307.872 300.5,-317.872 304.0001,-307.872 297.0001,-307.872"/>
|
||||||
|
</g>
|
||||||
|
<!-- A9 -->
|
||||||
|
<g id="node10" class="node">
|
||||||
|
<title>A9</title>
|
||||||
|
<polygon fill="none" stroke="#000000" points="94.4001,-238 12.5999,-238 12.5999,-202 94.4001,-202 94.4001,-238"/>
|
||||||
|
<text text-anchor="middle" x="53.5" y="-217" font-family="Helvetica,sans-Serif" font-size="10.00" fill="#000000">InverterG3P</text>
|
||||||
|
</g>
|
||||||
|
<!-- A5->A9 -->
|
||||||
|
<g id="edge6" class="edge">
|
||||||
|
<title>A5->A9</title>
|
||||||
|
<path fill="none" stroke="#000000" d="M196.7667,-346.4637C165.8973,-321.9347 132.3582,-294.4156 102.5,-268 91.7971,-258.5312 80.3616,-247.3925 71.232,-238.23"/>
|
||||||
|
<polygon fill="none" stroke="#000000" points="194.962,-349.4991 204.9739,-352.965 199.3086,-344.0121 194.962,-349.4991"/>
|
||||||
|
</g>
|
||||||
|
<!-- A11 -->
|
||||||
|
<g id="node12" class="node">
|
||||||
|
<title>A11</title>
|
||||||
|
<polygon fill="none" stroke="#000000" points="450.1421,-36 360.8579,-36 360.8579,0 450.1421,0 450.1421,-36"/>
|
||||||
|
<text text-anchor="middle" x="405.5" y="-15" font-family="Helvetica,sans-Serif" font-size="10.00" fill="#000000"><<AsyncIfc>></text>
|
||||||
|
</g>
|
||||||
|
<!-- A6->A11 -->
|
||||||
|
<g id="edge11" class="edge">
|
||||||
|
<title>A6->A11</title>
|
||||||
|
<path fill="none" stroke="#000000" d="M392.6633,-171.974C386.9982,-146.4565 382.5868,-114.547 386.5,-86 388.3468,-72.5276 392.161,-57.9618 395.8907,-45.7804"/>
|
||||||
|
<polygon fill="#000000" stroke="#000000" points="398.9587,-36.1851 400.1994,-47.0805 397.4359,-40.9476 395.9131,-45.71 395.9131,-45.71 395.9131,-45.71 397.4359,-40.9476 391.6269,-44.3395 398.9587,-36.1851 398.9587,-36.1851"/>
|
||||||
|
<text text-anchor="middle" x="401.4892" y="-53.0243" font-family="Helvetica,sans-Serif" font-size="10.00" fill="#000000">1</text>
|
||||||
|
</g>
|
||||||
|
<!-- A12 -->
|
||||||
|
<g id="node13" class="node">
|
||||||
|
<title>A12</title>
|
||||||
|
<polygon fill="none" stroke="#000000" points="493.5879,-122 395.4121,-122 395.4121,-86 493.5879,-86 493.5879,-122"/>
|
||||||
|
<text text-anchor="middle" x="444.5" y="-101" font-family="Helvetica,sans-Serif" font-size="10.00" fill="#000000"><<ProtocolIfc>></text>
|
||||||
|
</g>
|
||||||
|
<!-- A6->A12 -->
|
||||||
|
<g id="edge10" class="edge">
|
||||||
|
<title>A6->A12</title>
|
||||||
|
<path fill="none" stroke="#000000" d="M422.2853,-171.8133C426.7329,-158.2365 431.4225,-143.9208 435.3408,-131.9595"/>
|
||||||
|
<polygon fill="#000000" stroke="#000000" points="438.5602,-122.132 439.7235,-133.036 437.0036,-126.8835 435.4471,-131.6351 435.4471,-131.6351 435.4471,-131.6351 437.0036,-126.8835 431.1707,-130.2341 438.5602,-122.132 438.5602,-122.132"/>
|
||||||
|
<text text-anchor="middle" x="440.9498" y="-138.9887" font-family="Helvetica,sans-Serif" font-size="10.00" fill="#000000">1</text>
|
||||||
|
</g>
|
||||||
|
<!-- A8 -->
|
||||||
|
<g id="node9" class="node">
|
||||||
|
<title>A8</title>
|
||||||
|
<polygon fill="#fff8dc" stroke="#000000" points="574.906,-248 474.094,-248 474.094,-192 580.906,-192 580.906,-242 574.906,-248"/>
|
||||||
|
<polyline fill="none" stroke="#000000" points="574.906,-248 574.906,-242 "/>
|
||||||
|
<polyline fill="none" stroke="#000000" points="580.906,-242 574.906,-242 "/>
|
||||||
|
<text text-anchor="middle" x="527.5" y="-235" font-family="Helvetica,sans-Serif" font-size="10.00" fill="#000000">Creates an GEN3</text>
|
||||||
|
<text text-anchor="middle" x="527.5" y="-223" font-family="Helvetica,sans-Serif" font-size="10.00" fill="#000000">inverter instance</text>
|
||||||
|
<text text-anchor="middle" x="527.5" y="-211" font-family="Helvetica,sans-Serif" font-size="10.00" fill="#000000">with</text>
|
||||||
|
<text text-anchor="middle" x="527.5" y="-199" font-family="Helvetica,sans-Serif" font-size="10.00" fill="#000000">prot_class:Talent</text>
|
||||||
|
</g>
|
||||||
|
<!-- A7->A8 -->
|
||||||
|
<g id="edge3" class="edge">
|
||||||
|
<title>A7->A8</title>
|
||||||
|
<path fill="none" stroke="#000000" stroke-dasharray="5,2" d="M308.5491,-238.3283C317.4345,-256.0056 333.5793,-281.6949 356.5,-293 396.3598,-312.6598 415.5578,-310.2929 456.5,-293 478.1607,-283.8511 496.4784,-264.5049 509.0802,-248.0264"/>
|
||||||
|
</g>
|
||||||
|
<!-- A10 -->
|
||||||
|
<g id="node11" class="node">
|
||||||
|
<title>A10</title>
|
||||||
|
<polygon fill="#fff8dc" stroke="#000000" points="239.022,-248 111.978,-248 111.978,-192 245.022,-192 245.022,-242 239.022,-248"/>
|
||||||
|
<polyline fill="none" stroke="#000000" points="239.022,-248 239.022,-242 "/>
|
||||||
|
<polyline fill="none" stroke="#000000" points="245.022,-242 239.022,-242 "/>
|
||||||
|
<text text-anchor="middle" x="178.5" y="-235" font-family="Helvetica,sans-Serif" font-size="10.00" fill="#000000">Creates an GEN3PLUS</text>
|
||||||
|
<text text-anchor="middle" x="178.5" y="-223" font-family="Helvetica,sans-Serif" font-size="10.00" fill="#000000">inverter instance</text>
|
||||||
|
<text text-anchor="middle" x="178.5" y="-211" font-family="Helvetica,sans-Serif" font-size="10.00" fill="#000000">with</text>
|
||||||
|
<text text-anchor="middle" x="178.5" y="-199" font-family="Helvetica,sans-Serif" font-size="10.00" fill="#000000">prot_class:SolarmanV5</text>
|
||||||
|
</g>
|
||||||
|
<!-- A9->A10 -->
|
||||||
|
<g id="edge4" class="edge">
|
||||||
|
<title>A9->A10</title>
|
||||||
|
<path fill="none" stroke="#000000" stroke-dasharray="5,2" d="M94.5156,-220C100.3114,-220 106.1072,-220 111.903,-220"/>
|
||||||
|
</g>
|
||||||
|
<!-- A12->A11 -->
|
||||||
|
<g id="edge12" class="edge">
|
||||||
|
<title>A12->A11</title>
|
||||||
|
<path fill="none" stroke="#000000" stroke-dasharray="5,2" d="M436.2291,-85.7616C430.9033,-74.0176 423.8824,-58.5355 417.896,-45.3349"/>
|
||||||
|
<polygon fill="#000000" stroke="#000000" points="413.759,-36.2121 421.9874,-43.4608 415.824,-40.7657 417.8891,-45.3194 417.8891,-45.3194 417.8891,-45.3194 415.824,-40.7657 413.7908,-47.1779 413.759,-36.2121 413.759,-36.2121"/>
|
||||||
|
<text text-anchor="middle" x="421.0451" y="-69.7445" font-family="Helvetica,sans-Serif" font-size="10.00" fill="#000000">use</text>
|
||||||
|
</g>
|
||||||
|
<!-- A13 -->
|
||||||
|
<g id="node14" class="node">
|
||||||
|
<title>A13</title>
|
||||||
|
<polygon fill="none" stroke="#000000" points=".5,-454 .5,-486 107.5,-486 107.5,-454 .5,-454"/>
|
||||||
|
<text text-anchor="start" x="24.2695" y="-467" font-family="Helvetica,sans-Serif" font-size="10.00" fill="#000000">ModbusConn</text>
|
||||||
|
<polygon fill="none" stroke="#000000" points=".5,-386 .5,-454 107.5,-454 107.5,-386 .5,-386"/>
|
||||||
|
<text text-anchor="start" x="44.5515" y="-435" font-family="Helvetica,sans-Serif" font-size="10.00" fill="#000000">host</text>
|
||||||
|
<text text-anchor="start" x="45.387" y="-423" font-family="Helvetica,sans-Serif" font-size="10.00" fill="#000000">port</text>
|
||||||
|
<text text-anchor="start" x="43.997" y="-411" font-family="Helvetica,sans-Serif" font-size="10.00" fill="#000000">addr</text>
|
||||||
|
<text text-anchor="start" x="10.383" y="-399" font-family="Helvetica,sans-Serif" font-size="10.00" fill="#000000">stream:InverterG3P</text>
|
||||||
|
<polygon fill="none" stroke="#000000" points=".5,-366 .5,-386 107.5,-386 107.5,-366 .5,-366"/>
|
||||||
|
</g>
|
||||||
|
<!-- A13->A9 -->
|
||||||
|
<g id="edge13" class="edge">
|
||||||
|
<title>A13->A9</title>
|
||||||
|
<path fill="none" stroke="#000000" d="M53.5,-365.8625C53.5,-327.1513 53.5,-278.6088 53.5,-248.4442"/>
|
||||||
|
<polygon fill="#000000" stroke="#000000" points="53.5,-238.2147 58.0001,-248.2147 53.5,-243.2147 53.5001,-248.2147 53.5001,-248.2147 53.5001,-248.2147 53.5,-243.2147 49.0001,-248.2148 53.5,-238.2147 53.5,-238.2147"/>
|
||||||
|
<text text-anchor="middle" x="61.9524" y="-253.3409" font-family="Helvetica,sans-Serif" font-size="10.00" fill="#000000">1</text>
|
||||||
|
<text text-anchor="middle" x="45.0476" y="-344.7363" font-family="Helvetica,sans-Serif" font-size="10.00" fill="#000000">has</text>
|
||||||
|
</g>
|
||||||
|
<!-- A14 -->
|
||||||
|
<g id="node15" class="node">
|
||||||
|
<title>A14</title>
|
||||||
|
<polygon fill="none" stroke="#000000" points="93.7333,-722 13.2667,-722 13.2667,-686 93.7333,-686 93.7333,-722"/>
|
||||||
|
<text text-anchor="middle" x="53.5" y="-701" font-family="Helvetica,sans-Serif" font-size="10.00" fill="#000000">ModbusTcp</text>
|
||||||
|
</g>
|
||||||
|
<!-- A14->A13 -->
|
||||||
|
<g id="edge14" class="edge">
|
||||||
|
<title>A14->A13</title>
|
||||||
|
<path fill="none" stroke="#000000" d="M53.5,-685.7596C53.5,-647.9991 53.5,-559.5189 53.5,-496.3277"/>
|
||||||
|
<polygon fill="#000000" stroke="#000000" points="53.5,-486.0223 58.0001,-496.0223 53.5,-491.0223 53.5001,-496.0223 53.5001,-496.0223 53.5001,-496.0223 53.5,-491.0223 49.0001,-496.0224 53.5,-486.0223 53.5,-486.0223"/>
|
||||||
|
<text text-anchor="middle" x="61.9524" y="-501.1485" font-family="Helvetica,sans-Serif" font-size="10.00" fill="#000000">*</text>
|
||||||
|
<text text-anchor="middle" x="45.0476" y="-664.6335" font-family="Helvetica,sans-Serif" font-size="10.00" fill="#000000">creates</text>
|
||||||
|
</g>
|
||||||
|
</g>
|
||||||
|
</svg>
|
||||||
|
After Width: | Height: | Size: 20 KiB |
@@ -32,5 +32,5 @@
|
|||||||
|
|
||||||
|
|
||||||
[ModbusConn|host;port;addr;stream:InverterG3P;|]has-1>[InverterG3P]
|
[ModbusConn|host;port;addr;stream:InverterG3P;|]has-1>[InverterG3P]
|
||||||
[ModbusTcp||<async>modbus_loop()]creates-*>[ModbusConn]
|
[ModbusTcp]creates-*>[ModbusConn]
|
||||||
|
|
||||||
|
Before Width: | Height: | Size: 33 KiB After Width: | Height: | Size: 33 KiB |
@@ -4,11 +4,11 @@
|
|||||||
<!-- Generated by graphviz version 2.40.1 (20161225.0304)
|
<!-- Generated by graphviz version 2.40.1 (20161225.0304)
|
||||||
-->
|
-->
|
||||||
<!-- Title: G Pages: 1 -->
|
<!-- Title: G Pages: 1 -->
|
||||||
<svg width="541pt" height="1940pt"
|
<svg width="539pt" height="1940pt"
|
||||||
viewBox="0.00 0.00 540.62 1940.00" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
|
viewBox="0.00 0.00 538.62 1940.00" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
|
||||||
<g id="graph0" class="graph" transform="scale(1 1) rotate(0) translate(4 1936)">
|
<g id="graph0" class="graph" transform="scale(1 1) rotate(0) translate(4 1936)">
|
||||||
<title>G</title>
|
<title>G</title>
|
||||||
<polygon fill="#ffffff" stroke="transparent" points="-4,4 -4,-1936 536.6165,-1936 536.6165,4 -4,4"/>
|
<polygon fill="#ffffff" stroke="transparent" points="-4,4 -4,-1936 534.6165,-1936 534.6165,4 -4,4"/>
|
||||||
<!-- A0 -->
|
<!-- A0 -->
|
||||||
<g id="node1" class="node">
|
<g id="node1" class="node">
|
||||||
<title>A0</title>
|
<title>A0</title>
|
||||||
@@ -47,78 +47,78 @@
|
|||||||
<!-- A2 -->
|
<!-- A2 -->
|
||||||
<g id="node3" class="node">
|
<g id="node3" class="node">
|
||||||
<title>A2</title>
|
<title>A2</title>
|
||||||
<polygon fill="none" stroke="#000000" points="199.1165,-632 199.1165,-664 297.1165,-664 297.1165,-632 199.1165,-632"/>
|
<polygon fill="none" stroke="#000000" points="202.1165,-632 202.1165,-664 300.1165,-664 300.1165,-632 202.1165,-632"/>
|
||||||
<text text-anchor="start" x="221.1665" y="-645" font-family="Helvetica,sans-Serif" font-size="10.00" fill="#000000">InverterG3P</text>
|
<text text-anchor="start" x="224.1665" y="-645" font-family="Helvetica,sans-Serif" font-size="10.00" fill="#000000">InverterG3P</text>
|
||||||
<polygon fill="none" stroke="#000000" points="199.1165,-576 199.1165,-632 297.1165,-632 297.1165,-576 199.1165,-576"/>
|
<polygon fill="none" stroke="#000000" points="202.1165,-576 202.1165,-632 300.1165,-632 300.1165,-576 202.1165,-576"/>
|
||||||
<text text-anchor="start" x="238.1135" y="-613" font-family="Helvetica,sans-Serif" font-size="10.00" fill="#000000">addr</text>
|
<text text-anchor="start" x="241.1135" y="-613" font-family="Helvetica,sans-Serif" font-size="10.00" fill="#000000">addr</text>
|
||||||
<text text-anchor="start" x="208.6695" y="-601" font-family="Helvetica,sans-Serif" font-size="10.00" fill="#000000">remote:StreamPtr</text>
|
<text text-anchor="start" x="211.6695" y="-601" font-family="Helvetica,sans-Serif" font-size="10.00" fill="#000000">remote:StreamPtr</text>
|
||||||
<text text-anchor="start" x="213.9485" y="-589" font-family="Helvetica,sans-Serif" font-size="10.00" fill="#000000">local:StreamPtr</text>
|
<text text-anchor="start" x="216.9485" y="-589" font-family="Helvetica,sans-Serif" font-size="10.00" fill="#000000">local:StreamPtr</text>
|
||||||
<polygon fill="none" stroke="#000000" points="199.1165,-520 199.1165,-576 297.1165,-576 297.1165,-520 199.1165,-520"/>
|
<polygon fill="none" stroke="#000000" points="202.1165,-520 202.1165,-576 300.1165,-576 300.1165,-520 202.1165,-520"/>
|
||||||
<text text-anchor="start" x="212.5585" y="-557" font-family="Helvetica,sans-Serif" font-size="10.00" fill="#000000">create_remote()</text>
|
<text text-anchor="start" x="215.5585" y="-557" font-family="Helvetica,sans-Serif" font-size="10.00" fill="#000000">create_remote()</text>
|
||||||
<text text-anchor="start" x="233.119" y="-533" font-family="Helvetica,sans-Serif" font-size="10.00" fill="#000000">close()</text>
|
<text text-anchor="start" x="236.119" y="-533" font-family="Helvetica,sans-Serif" font-size="10.00" fill="#000000">close()</text>
|
||||||
</g>
|
</g>
|
||||||
<!-- A3 -->
|
<!-- A3 -->
|
||||||
<g id="node4" class="node">
|
<g id="node4" class="node">
|
||||||
<title>A3</title>
|
<title>A3</title>
|
||||||
<polygon fill="none" stroke="#000000" points="415.4531,-320 318.7799,-320 318.7799,-284 415.4531,-284 415.4531,-320"/>
|
<polygon fill="none" stroke="#000000" points="419.4531,-320 322.7799,-320 322.7799,-284 419.4531,-284 419.4531,-320"/>
|
||||||
<text text-anchor="middle" x="367.1165" y="-299" font-family="Helvetica,sans-Serif" font-size="10.00" fill="#000000">local:StreamPtr</text>
|
<text text-anchor="middle" x="371.1165" y="-299" font-family="Helvetica,sans-Serif" font-size="10.00" fill="#000000">local:StreamPtr</text>
|
||||||
</g>
|
</g>
|
||||||
<!-- A2->A3 -->
|
<!-- A2->A3 -->
|
||||||
<g id="edge1" class="edge">
|
<g id="edge1" class="edge">
|
||||||
<title>A2->A3</title>
|
<title>A2->A3</title>
|
||||||
<path fill="none" stroke="#000000" d="M282.2534,-508.8093C307.0525,-448.3743 339.0836,-370.3156 355.8099,-329.5539"/>
|
<path fill="none" stroke="#000000" d="M285.5402,-508.8093C310.5478,-448.3743 342.848,-370.3156 359.7149,-329.5539"/>
|
||||||
<polygon fill="#000000" stroke="#000000" points="282.2407,-508.8403 283.6635,-515.9097 277.6851,-519.942 276.2624,-512.8726 282.2407,-508.8403"/>
|
<polygon fill="#000000" stroke="#000000" points="285.5219,-508.8538 286.9238,-515.9273 280.9336,-519.942 279.5317,-512.8685 285.5219,-508.8538"/>
|
||||||
<polygon fill="#000000" stroke="#000000" points="359.6225,-320.2627 359.9893,-331.2224 357.7243,-324.8884 355.8262,-329.5141 355.8262,-329.5141 355.8262,-329.5141 357.7243,-324.8884 351.663,-327.8058 359.6225,-320.2627 359.6225,-320.2627"/>
|
<polygon fill="#000000" stroke="#000000" points="363.5595,-320.2627 363.894,-331.2235 361.6477,-324.8828 359.7359,-329.5029 359.7359,-329.5029 359.7359,-329.5029 361.6477,-324.8828 355.5779,-327.7823 363.5595,-320.2627 363.5595,-320.2627"/>
|
||||||
</g>
|
</g>
|
||||||
<!-- A4 -->
|
<!-- A4 -->
|
||||||
<g id="node5" class="node">
|
<g id="node5" class="node">
|
||||||
<title>A4</title>
|
<title>A4</title>
|
||||||
<polygon fill="none" stroke="#000000" points="300.5106,-320 193.7224,-320 193.7224,-284 300.5106,-284 300.5106,-320"/>
|
<polygon fill="none" stroke="#000000" points="304.5106,-320 197.7224,-320 197.7224,-284 304.5106,-284 304.5106,-320"/>
|
||||||
<text text-anchor="middle" x="247.1165" y="-299" font-family="Helvetica,sans-Serif" font-size="10.00" fill="#000000">remote:StreamPtr</text>
|
<text text-anchor="middle" x="251.1165" y="-299" font-family="Helvetica,sans-Serif" font-size="10.00" fill="#000000">remote:StreamPtr</text>
|
||||||
</g>
|
</g>
|
||||||
<!-- A2->A4 -->
|
<!-- A2->A4 -->
|
||||||
<g id="edge2" class="edge">
|
<g id="edge2" class="edge">
|
||||||
<title>A2->A4</title>
|
<title>A2->A4</title>
|
||||||
<path fill="none" stroke="#000000" d="M247.8254,-507.5905C247.6188,-447.68 247.3542,-370.9429 247.214,-330.266"/>
|
<path fill="none" stroke="#000000" d="M251.1165,-507.5905C251.1165,-447.68 251.1165,-370.9429 251.1165,-330.266"/>
|
||||||
<polygon fill="#000000" stroke="#000000" points="247.8265,-507.9421 251.8473,-513.9282 247.868,-519.942 243.8473,-513.9559 247.8265,-507.9421"/>
|
<polygon fill="#000000" stroke="#000000" points="251.1166,-507.942 255.1165,-513.942 251.1165,-519.942 247.1165,-513.942 251.1166,-507.942"/>
|
||||||
<polygon fill="#000000" stroke="#000000" points="247.1795,-320.2627 251.714,-330.2471 247.1968,-325.2627 247.2141,-330.2626 247.2141,-330.2626 247.2141,-330.2626 247.1968,-325.2627 242.7141,-330.2782 247.1795,-320.2627 247.1795,-320.2627"/>
|
<polygon fill="#000000" stroke="#000000" points="251.1165,-320.2627 255.6166,-330.2626 251.1165,-325.2627 251.1166,-330.2627 251.1166,-330.2627 251.1166,-330.2627 251.1165,-325.2627 246.6166,-330.2627 251.1165,-320.2627 251.1165,-320.2627"/>
|
||||||
</g>
|
</g>
|
||||||
<!-- A8 -->
|
<!-- A8 -->
|
||||||
<g id="node9" class="node">
|
<g id="node9" class="node">
|
||||||
<title>A8</title>
|
<title>A8</title>
|
||||||
<polygon fill="none" stroke="#000000" points="261.1165,-100 261.1165,-132 439.1165,-132 439.1165,-100 261.1165,-100"/>
|
<polygon fill="none" stroke="#000000" points="265.1165,-100 265.1165,-132 443.1165,-132 443.1165,-100 265.1165,-100"/>
|
||||||
<text text-anchor="start" x="305.668" y="-113" font-family="Helvetica,sans-Serif" font-size="10.00" fill="#000000">AsyncStreamServer</text>
|
<text text-anchor="start" x="309.668" y="-113" font-family="Helvetica,sans-Serif" font-size="10.00" fill="#000000">AsyncStreamServer</text>
|
||||||
<polygon fill="none" stroke="#000000" points="261.1165,-68 261.1165,-100 439.1165,-100 439.1165,-68 261.1165,-68"/>
|
<polygon fill="none" stroke="#000000" points="265.1165,-68 265.1165,-100 443.1165,-100 443.1165,-68 265.1165,-68"/>
|
||||||
<text text-anchor="start" x="317.8875" y="-81" font-family="Helvetica,sans-Serif" font-size="10.00" fill="#000000">create_remote</text>
|
<text text-anchor="start" x="321.8875" y="-81" font-family="Helvetica,sans-Serif" font-size="10.00" fill="#000000">create_remote</text>
|
||||||
<polygon fill="none" stroke="#000000" points="261.1165,0 261.1165,-68 439.1165,-68 439.1165,0 261.1165,0"/>
|
<polygon fill="none" stroke="#000000" points="265.1165,0 265.1165,-68 443.1165,-68 443.1165,0 265.1165,0"/>
|
||||||
<text text-anchor="start" x="301.774" y="-49" font-family="Helvetica,sans-Serif" font-size="10.00" fill="#000000"><async>server_loop()</text>
|
<text text-anchor="start" x="305.774" y="-49" font-family="Helvetica,sans-Serif" font-size="10.00" fill="#000000"><async>server_loop()</text>
|
||||||
<text text-anchor="start" x="292.605" y="-37" font-family="Helvetica,sans-Serif" font-size="10.00" fill="#000000"><async>_async_forward()</text>
|
<text text-anchor="start" x="296.605" y="-37" font-family="Helvetica,sans-Serif" font-size="10.00" fill="#000000"><async>_async_forward()</text>
|
||||||
<text text-anchor="start" x="270.9255" y="-25" font-family="Helvetica,sans-Serif" font-size="10.00" fill="#000000"><async>publish_outstanding_mqtt()</text>
|
<text text-anchor="start" x="274.9255" y="-25" font-family="Helvetica,sans-Serif" font-size="10.00" fill="#000000"><async>publish_outstanding_mqtt()</text>
|
||||||
<text text-anchor="start" x="335.119" y="-13" font-family="Helvetica,sans-Serif" font-size="10.00" fill="#000000">close()</text>
|
<text text-anchor="start" x="339.119" y="-13" font-family="Helvetica,sans-Serif" font-size="10.00" fill="#000000">close()</text>
|
||||||
</g>
|
</g>
|
||||||
<!-- A3->A8 -->
|
<!-- A3->A8 -->
|
||||||
<g id="edge8" class="edge">
|
<g id="edge8" class="edge">
|
||||||
<title>A3->A8</title>
|
<title>A3->A8</title>
|
||||||
<path fill="none" stroke="#000000" d="M364.9314,-271.6651C362.5869,-239.1181 358.7725,-186.1658 355.6014,-142.1431"/>
|
<path fill="none" stroke="#000000" d="M368.9314,-271.6651C366.5869,-239.1181 362.7725,-186.1658 359.6014,-142.1431"/>
|
||||||
<polygon fill="#000000" stroke="#000000" points="364.9485,-271.9044 369.3693,-277.6014 365.8108,-283.8733 361.39,-278.1763 364.9485,-271.9044"/>
|
<polygon fill="#000000" stroke="#000000" points="368.9485,-271.9044 373.3693,-277.6014 369.8108,-283.8733 365.39,-278.1763 368.9485,-271.9044"/>
|
||||||
<polygon fill="#000000" stroke="#000000" points="354.8731,-132.0321 360.08,-141.6829 355.2323,-137.0192 355.5916,-142.0063 355.5916,-142.0063 355.5916,-142.0063 355.2323,-137.0192 351.1032,-142.3296 354.8731,-132.0321 354.8731,-132.0321"/>
|
<polygon fill="#000000" stroke="#000000" points="358.8731,-132.0321 364.08,-141.6829 359.2323,-137.0192 359.5916,-142.0063 359.5916,-142.0063 359.5916,-142.0063 359.2323,-137.0192 355.1032,-142.3296 358.8731,-132.0321 358.8731,-132.0321"/>
|
||||||
</g>
|
</g>
|
||||||
<!-- A9 -->
|
<!-- A9 -->
|
||||||
<g id="node10" class="node">
|
<g id="node10" class="node">
|
||||||
<title>A9</title>
|
<title>A9</title>
|
||||||
<polygon fill="none" stroke="#000000" points="89.1165,-82 89.1165,-114 227.1165,-114 227.1165,-82 89.1165,-82"/>
|
<polygon fill="none" stroke="#000000" points="93.1165,-82 93.1165,-114 231.1165,-114 231.1165,-82 93.1165,-82"/>
|
||||||
<text text-anchor="start" x="115.6135" y="-95" font-family="Helvetica,sans-Serif" font-size="10.00" fill="#000000">AsyncStreamClient</text>
|
<text text-anchor="start" x="119.6135" y="-95" font-family="Helvetica,sans-Serif" font-size="10.00" fill="#000000">AsyncStreamClient</text>
|
||||||
<polygon fill="none" stroke="#000000" points="89.1165,-62 89.1165,-82 227.1165,-82 227.1165,-62 89.1165,-62"/>
|
<polygon fill="none" stroke="#000000" points="93.1165,-62 93.1165,-82 231.1165,-82 231.1165,-62 93.1165,-62"/>
|
||||||
<polygon fill="none" stroke="#000000" points="89.1165,-18 89.1165,-62 227.1165,-62 227.1165,-18 89.1165,-18"/>
|
<polygon fill="none" stroke="#000000" points="93.1165,-18 93.1165,-62 231.1165,-62 231.1165,-18 93.1165,-18"/>
|
||||||
<text text-anchor="start" x="111.9945" y="-43" font-family="Helvetica,sans-Serif" font-size="10.00" fill="#000000"><async>client_loop()</text>
|
<text text-anchor="start" x="115.9945" y="-43" font-family="Helvetica,sans-Serif" font-size="10.00" fill="#000000"><async>client_loop()</text>
|
||||||
<text text-anchor="start" x="98.9405" y="-31" font-family="Helvetica,sans-Serif" font-size="10.00" fill="#000000"><async>_async_forward())</text>
|
<text text-anchor="start" x="102.9405" y="-31" font-family="Helvetica,sans-Serif" font-size="10.00" fill="#000000"><async>_async_forward())</text>
|
||||||
</g>
|
</g>
|
||||||
<!-- A4->A9 -->
|
<!-- A4->A9 -->
|
||||||
<g id="edge10" class="edge">
|
<g id="edge10" class="edge">
|
||||||
<title>A4->A9</title>
|
<title>A4->A9</title>
|
||||||
<path fill="none" stroke="#000000" d="M240.2806,-283.8733C227.5204,-250.0372 199.5834,-175.9573 179.8383,-123.5994"/>
|
<path fill="none" stroke="#000000" d="M244.2806,-283.8733C231.5204,-250.0372 203.5834,-175.9573 183.8383,-123.5994"/>
|
||||||
<polygon fill="#000000" stroke="#000000" points="176.2523,-114.0904 183.9915,-121.8593 178.0166,-118.7688 179.781,-123.4472 179.781,-123.4472 179.781,-123.4472 178.0166,-118.7688 175.5704,-125.0351 176.2523,-114.0904 176.2523,-114.0904"/>
|
<polygon fill="#000000" stroke="#000000" points="180.2523,-114.0904 187.9915,-121.8593 182.0166,-118.7688 183.781,-123.4472 183.781,-123.4472 183.781,-123.4472 182.0166,-118.7688 179.5704,-125.0351 180.2523,-114.0904 180.2523,-114.0904"/>
|
||||||
<text text-anchor="middle" x="225.9759" y="-266.8956" font-family="Helvetica,sans-Serif" font-size="10.00" fill="#000000">0..1</text>
|
<text text-anchor="middle" x="229.9759" y="-266.8956" font-family="Helvetica,sans-Serif" font-size="10.00" fill="#000000">0..1</text>
|
||||||
</g>
|
</g>
|
||||||
<!-- A5 -->
|
<!-- A5 -->
|
||||||
<g id="node6" class="node">
|
<g id="node6" class="node">
|
||||||
@@ -149,138 +149,135 @@
|
|||||||
<!-- A6 -->
|
<!-- A6 -->
|
||||||
<g id="node7" class="node">
|
<g id="node7" class="node">
|
||||||
<title>A6</title>
|
<title>A6</title>
|
||||||
<polygon fill="none" stroke="#000000" points="84.1165,-622 84.1165,-654 177.1165,-654 177.1165,-622 84.1165,-622"/>
|
<polygon fill="none" stroke="#000000" points="87.1165,-622 87.1165,-654 180.1165,-654 180.1165,-622 87.1165,-622"/>
|
||||||
<text text-anchor="start" x="102.2805" y="-635" font-family="Helvetica,sans-Serif" font-size="10.00" fill="#000000">AsyncIfcImpl</text>
|
<text text-anchor="start" x="105.2805" y="-635" font-family="Helvetica,sans-Serif" font-size="10.00" fill="#000000">AsyncIfcImpl</text>
|
||||||
<polygon fill="none" stroke="#000000" points="84.1165,-530 84.1165,-622 177.1165,-622 177.1165,-530 84.1165,-530"/>
|
<polygon fill="none" stroke="#000000" points="87.1165,-530 87.1165,-622 180.1165,-622 180.1165,-530 87.1165,-530"/>
|
||||||
<text text-anchor="start" x="93.6645" y="-603" font-family="Helvetica,sans-Serif" font-size="10.00" fill="#000000">fwd_fifo:ByteFifo</text>
|
<text text-anchor="start" x="96.6645" y="-603" font-family="Helvetica,sans-Serif" font-size="10.00" fill="#000000">fwd_fifo:ByteFifo</text>
|
||||||
<text text-anchor="start" x="97.5535" y="-591" font-family="Helvetica,sans-Serif" font-size="10.00" fill="#000000">tx_fifo:ByteFifo</text>
|
<text text-anchor="start" x="100.5535" y="-591" font-family="Helvetica,sans-Serif" font-size="10.00" fill="#000000">tx_fifo:ByteFifo</text>
|
||||||
<text text-anchor="start" x="97.2785" y="-579" font-family="Helvetica,sans-Serif" font-size="10.00" fill="#000000">rx_fifo:ByteFifo</text>
|
<text text-anchor="start" x="100.2785" y="-579" font-family="Helvetica,sans-Serif" font-size="10.00" fill="#000000">rx_fifo:ByteFifo</text>
|
||||||
<text text-anchor="start" x="96.7125" y="-567" font-family="Helvetica,sans-Serif" font-size="10.00" fill="#000000">conn_no:Count</text>
|
<text text-anchor="start" x="99.7125" y="-567" font-family="Helvetica,sans-Serif" font-size="10.00" fill="#000000">conn_no:Count</text>
|
||||||
<text text-anchor="start" x="112.83" y="-555" font-family="Helvetica,sans-Serif" font-size="10.00" fill="#000000">node_id</text>
|
<text text-anchor="start" x="115.83" y="-555" font-family="Helvetica,sans-Serif" font-size="10.00" fill="#000000">node_id</text>
|
||||||
<text text-anchor="start" x="106.166" y="-543" font-family="Helvetica,sans-Serif" font-size="10.00" fill="#000000">timeout_cb</text>
|
<text text-anchor="start" x="109.166" y="-543" font-family="Helvetica,sans-Serif" font-size="10.00" fill="#000000">timeout_cb</text>
|
||||||
</g>
|
</g>
|
||||||
<!-- A5->A6 -->
|
<!-- A5->A6 -->
|
||||||
<g id="edge3" class="edge">
|
<g id="edge3" class="edge">
|
||||||
<title>A5->A6</title>
|
<title>A5->A6</title>
|
||||||
<path fill="none" stroke="#000000" stroke-dasharray="5,2" d="M165.2976,-752.0017C157.592,-716.9571 149.9649,-682.2694 143.7924,-654.1971"/>
|
<path fill="none" stroke="#000000" stroke-dasharray="5,2" d="M166.8518,-752.0017C159.4629,-716.9571 152.1492,-682.2694 146.2303,-654.1971"/>
|
||||||
<polygon fill="none" stroke="#000000" points="161.906,-752.8753 167.4719,-761.8903 168.7427,-751.372 161.906,-752.8753"/>
|
<polygon fill="none" stroke="#000000" points="163.4489,-752.8275 168.9367,-761.8903 170.2983,-751.3833 163.4489,-752.8275"/>
|
||||||
</g>
|
</g>
|
||||||
<!-- A7 -->
|
<!-- A7 -->
|
||||||
<g id="node8" class="node">
|
<g id="node8" class="node">
|
||||||
<title>A7</title>
|
<title>A7</title>
|
||||||
<polygon fill="none" stroke="#000000" points="74.1165,-390 74.1165,-422 176.1165,-422 176.1165,-390 74.1165,-390"/>
|
<polygon fill="none" stroke="#000000" points="78.1165,-390 78.1165,-422 180.1165,-422 180.1165,-390 78.1165,-390"/>
|
||||||
<text text-anchor="start" x="95.3905" y="-403" font-family="Helvetica,sans-Serif" font-size="10.00" fill="#000000">AsyncStream</text>
|
<text text-anchor="start" x="99.3905" y="-403" font-family="Helvetica,sans-Serif" font-size="10.00" fill="#000000">AsyncStream</text>
|
||||||
<polygon fill="none" stroke="#000000" points="74.1165,-310 74.1165,-390 176.1165,-390 176.1165,-310 74.1165,-310"/>
|
<polygon fill="none" stroke="#000000" points="78.1165,-310 78.1165,-390 180.1165,-390 180.1165,-310 78.1165,-310"/>
|
||||||
<text text-anchor="start" x="110.6695" y="-371" font-family="Helvetica,sans-Serif" font-size="10.00" fill="#000000">reader</text>
|
<text text-anchor="start" x="114.6695" y="-371" font-family="Helvetica,sans-Serif" font-size="10.00" fill="#000000">reader</text>
|
||||||
<text text-anchor="start" x="112.8995" y="-359" font-family="Helvetica,sans-Serif" font-size="10.00" fill="#000000">writer</text>
|
<text text-anchor="start" x="116.8995" y="-359" font-family="Helvetica,sans-Serif" font-size="10.00" fill="#000000">writer</text>
|
||||||
<text text-anchor="start" x="115.1135" y="-347" font-family="Helvetica,sans-Serif" font-size="10.00" fill="#000000">addr</text>
|
<text text-anchor="start" x="119.1135" y="-347" font-family="Helvetica,sans-Serif" font-size="10.00" fill="#000000">addr</text>
|
||||||
<text text-anchor="start" x="110.6695" y="-335" font-family="Helvetica,sans-Serif" font-size="10.00" fill="#000000">r_addr</text>
|
<text text-anchor="start" x="114.6695" y="-335" font-family="Helvetica,sans-Serif" font-size="10.00" fill="#000000">r_addr</text>
|
||||||
<text text-anchor="start" x="111.2245" y="-323" font-family="Helvetica,sans-Serif" font-size="10.00" fill="#000000">l_addr</text>
|
<text text-anchor="start" x="115.2245" y="-323" font-family="Helvetica,sans-Serif" font-size="10.00" fill="#000000">l_addr</text>
|
||||||
<polygon fill="none" stroke="#000000" points="74.1165,-182 74.1165,-310 176.1165,-310 176.1165,-182 74.1165,-182"/>
|
<polygon fill="none" stroke="#000000" points="78.1165,-182 78.1165,-310 180.1165,-310 180.1165,-182 78.1165,-182"/>
|
||||||
<text text-anchor="start" x="96.7705" y="-279" font-family="Helvetica,sans-Serif" font-size="10.00" fill="#000000"><async>loop</text>
|
<text text-anchor="start" x="100.7705" y="-279" font-family="Helvetica,sans-Serif" font-size="10.00" fill="#000000"><async>loop</text>
|
||||||
<text text-anchor="start" x="112.8985" y="-267" font-family="Helvetica,sans-Serif" font-size="10.00" fill="#000000">disc()</text>
|
<text text-anchor="start" x="116.8985" y="-267" font-family="Helvetica,sans-Serif" font-size="10.00" fill="#000000">disc()</text>
|
||||||
<text text-anchor="start" x="110.119" y="-255" font-family="Helvetica,sans-Serif" font-size="10.00" fill="#000000">close()</text>
|
<text text-anchor="start" x="114.119" y="-255" font-family="Helvetica,sans-Serif" font-size="10.00" fill="#000000">close()</text>
|
||||||
<text text-anchor="start" x="105.6705" y="-243" font-family="Helvetica,sans-Serif" font-size="10.00" fill="#000000">healthy()</text>
|
<text text-anchor="start" x="109.6705" y="-243" font-family="Helvetica,sans-Serif" font-size="10.00" fill="#000000">healthy()</text>
|
||||||
<text text-anchor="start" x="90.387" y="-219" font-family="Helvetica,sans-Serif" font-size="10.00" fill="#000000">__async_read()</text>
|
<text text-anchor="start" x="94.387" y="-219" font-family="Helvetica,sans-Serif" font-size="10.00" fill="#000000">__async_read()</text>
|
||||||
<text text-anchor="start" x="89.8375" y="-207" font-family="Helvetica,sans-Serif" font-size="10.00" fill="#000000">__async_write()</text>
|
<text text-anchor="start" x="93.8375" y="-207" font-family="Helvetica,sans-Serif" font-size="10.00" fill="#000000">__async_write()</text>
|
||||||
<text text-anchor="start" x="83.7235" y="-195" font-family="Helvetica,sans-Serif" font-size="10.00" fill="#000000">__async_forward()</text>
|
<text text-anchor="start" x="87.7235" y="-195" font-family="Helvetica,sans-Serif" font-size="10.00" fill="#000000">__async_forward()</text>
|
||||||
</g>
|
</g>
|
||||||
<!-- A6->A7 -->
|
<!-- A6->A7 -->
|
||||||
<g id="edge4" class="edge">
|
<g id="edge4" class="edge">
|
||||||
<title>A6->A7</title>
|
<title>A6->A7</title>
|
||||||
<path fill="none" stroke="#000000" d="M128.868,-519.5861C128.3592,-490.0737 127.7571,-455.1552 127.186,-422.0295"/>
|
<path fill="none" stroke="#000000" d="M132.1177,-519.5861C131.7106,-490.0737 131.229,-455.1552 130.7721,-422.0295"/>
|
||||||
<polygon fill="none" stroke="#000000" points="125.3719,-519.8496 129.0439,-529.7877 132.3709,-519.7288 125.3719,-519.8496"/>
|
<polygon fill="none" stroke="#000000" points="128.6207,-519.837 132.2584,-529.7877 135.6201,-519.7404 128.6207,-519.837"/>
|
||||||
</g>
|
</g>
|
||||||
<!-- A7->A8 -->
|
<!-- A7->A8 -->
|
||||||
<g id="edge5" class="edge">
|
<g id="edge5" class="edge">
|
||||||
<title>A7->A8</title>
|
<title>A7->A8</title>
|
||||||
<path fill="none" stroke="#000000" d="M182.5777,-185.0204C183.4154,-184.0001 184.2616,-182.9929 185.1165,-182 206.4788,-157.1889 234.2469,-135.0276 260.8921,-116.8901"/>
|
<path fill="none" stroke="#000000" d="M186.5777,-185.0204C187.4154,-184.0001 188.2616,-182.9929 189.1165,-182 210.4788,-157.1889 238.2469,-135.0276 264.8921,-116.8901"/>
|
||||||
<polygon fill="none" stroke="#000000" points="179.6875,-183.0361 176.3256,-193.0834 185.2193,-187.3255 179.6875,-183.0361"/>
|
<polygon fill="none" stroke="#000000" points="183.6875,-183.0361 180.3256,-193.0834 189.2193,-187.3255 183.6875,-183.0361"/>
|
||||||
</g>
|
</g>
|
||||||
<!-- A7->A9 -->
|
<!-- A7->A9 -->
|
||||||
<g id="edge6" class="edge">
|
<g id="edge6" class="edge">
|
||||||
<title>A7->A9</title>
|
<title>A7->A9</title>
|
||||||
<path fill="none" stroke="#000000" d="M143.3214,-171.8077C146.1952,-151.2556 148.9992,-131.2022 151.3799,-114.1772"/>
|
<path fill="none" stroke="#000000" d="M147.3214,-171.8077C150.1952,-151.2556 152.9992,-131.2022 155.3799,-114.1772"/>
|
||||||
<polygon fill="none" stroke="#000000" points="139.8252,-171.5375 141.9065,-181.9259 146.7577,-172.5069 139.8252,-171.5375"/>
|
<polygon fill="none" stroke="#000000" points="143.8252,-171.5375 145.9065,-181.9259 150.7577,-172.5069 143.8252,-171.5375"/>
|
||||||
</g>
|
</g>
|
||||||
<!-- A10 -->
|
<!-- A10 -->
|
||||||
<g id="node11" class="node">
|
<g id="node11" class="node">
|
||||||
<title>A10</title>
|
<title>A10</title>
|
||||||
<polygon fill="none" stroke="#000000" points="318.1165,-668 318.1165,-700 409.1165,-700 409.1165,-668 318.1165,-668"/>
|
<polygon fill="none" stroke="#000000" points="319.1165,-668 319.1165,-700 410.1165,-700 410.1165,-668 319.1165,-668"/>
|
||||||
<text text-anchor="start" x="336.1115" y="-681" font-family="Helvetica,sans-Serif" font-size="10.00" fill="#000000">SolarmanV5</text>
|
<text text-anchor="start" x="337.1115" y="-681" font-family="Helvetica,sans-Serif" font-size="10.00" fill="#000000">SolarmanV5</text>
|
||||||
<polygon fill="none" stroke="#000000" points="318.1165,-552 318.1165,-668 409.1165,-668 409.1165,-552 318.1165,-552"/>
|
<polygon fill="none" stroke="#000000" points="319.1165,-552 319.1165,-668 410.1165,-668 410.1165,-552 319.1165,-552"/>
|
||||||
<text text-anchor="start" x="344.4395" y="-649" font-family="Helvetica,sans-Serif" font-size="10.00" fill="#000000">conn_no</text>
|
<text text-anchor="start" x="345.4395" y="-649" font-family="Helvetica,sans-Serif" font-size="10.00" fill="#000000">conn_no</text>
|
||||||
<text text-anchor="start" x="353.6135" y="-637" font-family="Helvetica,sans-Serif" font-size="10.00" fill="#000000">addr</text>
|
<text text-anchor="start" x="354.6135" y="-637" font-family="Helvetica,sans-Serif" font-size="10.00" fill="#000000">addr</text>
|
||||||
<text text-anchor="start" x="348.6145" y="-613" font-family="Helvetica,sans-Serif" font-size="10.00" fill="#000000">control</text>
|
<text text-anchor="start" x="349.6145" y="-613" font-family="Helvetica,sans-Serif" font-size="10.00" fill="#000000">control</text>
|
||||||
<text text-anchor="start" x="351.674" y="-601" font-family="Helvetica,sans-Serif" font-size="10.00" fill="#000000">serial</text>
|
<text text-anchor="start" x="352.674" y="-601" font-family="Helvetica,sans-Serif" font-size="10.00" fill="#000000">serial</text>
|
||||||
<text text-anchor="start" x="356.6725" y="-589" font-family="Helvetica,sans-Serif" font-size="10.00" fill="#000000">snr</text>
|
<text text-anchor="start" x="357.6725" y="-589" font-family="Helvetica,sans-Serif" font-size="10.00" fill="#000000">snr</text>
|
||||||
<text text-anchor="start" x="335.8265" y="-577" font-family="Helvetica,sans-Serif" font-size="10.00" fill="#000000">db:InfosG3P</text>
|
<text text-anchor="start" x="336.8265" y="-577" font-family="Helvetica,sans-Serif" font-size="10.00" fill="#000000">db:InfosG3P</text>
|
||||||
<text text-anchor="start" x="349.7285" y="-565" font-family="Helvetica,sans-Serif" font-size="10.00" fill="#000000">switch</text>
|
<text text-anchor="start" x="350.7285" y="-565" font-family="Helvetica,sans-Serif" font-size="10.00" fill="#000000">switch</text>
|
||||||
<polygon fill="none" stroke="#000000" points="318.1165,-484 318.1165,-552 409.1165,-552 409.1165,-484 318.1165,-484"/>
|
<polygon fill="none" stroke="#000000" points="319.1165,-484 319.1165,-552 410.1165,-552 410.1165,-484 319.1165,-484"/>
|
||||||
<text text-anchor="start" x="328.057" y="-533" font-family="Helvetica,sans-Serif" font-size="10.00" fill="#000000">msg_unknown()</text>
|
<text text-anchor="start" x="329.057" y="-533" font-family="Helvetica,sans-Serif" font-size="10.00" fill="#000000">msg_unknown()</text>
|
||||||
<text text-anchor="start" x="344.1705" y="-509" font-family="Helvetica,sans-Serif" font-size="10.00" fill="#000000">healthy()</text>
|
<text text-anchor="start" x="345.1705" y="-509" font-family="Helvetica,sans-Serif" font-size="10.00" fill="#000000">healthy()</text>
|
||||||
<text text-anchor="start" x="348.619" y="-497" font-family="Helvetica,sans-Serif" font-size="10.00" fill="#000000">close()</text>
|
<text text-anchor="start" x="349.619" y="-497" font-family="Helvetica,sans-Serif" font-size="10.00" fill="#000000">close()</text>
|
||||||
</g>
|
</g>
|
||||||
<!-- A10->A3 -->
|
<!-- A10->A3 -->
|
||||||
<g id="edge7" class="edge">
|
<g id="edge7" class="edge">
|
||||||
<title>A10->A3</title>
|
<title>A10->A3</title>
|
||||||
<path fill="none" stroke="#000000" d="M364.7507,-473.5237C365.4625,-421.9136 366.2384,-365.6622 366.7008,-332.138"/>
|
<path fill="none" stroke="#000000" d="M366.9763,-473.5237C368.222,-421.9136 369.5798,-365.6622 370.389,-332.138"/>
|
||||||
<polygon fill="#000000" stroke="#000000" points="364.6116,-483.6023 360.2501,-473.5412 364.6806,-478.6028 364.7497,-473.6033 364.7497,-473.6033 364.7497,-473.6033 364.6806,-478.6028 369.2492,-473.6654 364.6116,-483.6023 364.6116,-483.6023"/>
|
<polygon fill="#000000" stroke="#000000" points="366.733,-483.6023 362.4757,-473.4966 366.8537,-478.6038 366.9744,-473.6052 366.9744,-473.6052 366.9744,-473.6052 366.8537,-478.6038 371.4731,-473.7139 366.733,-483.6023 366.733,-483.6023"/>
|
||||||
<polygon fill="#000000" stroke="#000000" points="366.7019,-332.0519 362.7851,-325.9973 366.8675,-320.053 370.7843,-326.1077 366.7019,-332.0519"/>
|
<polygon fill="#000000" stroke="#000000" points="370.3911,-332.0495 366.5371,-325.9547 370.6807,-320.053 374.5347,-326.1478 370.3911,-332.0495"/>
|
||||||
</g>
|
</g>
|
||||||
<!-- A10->A4 -->
|
<!-- A10->A4 -->
|
||||||
<g id="edge9" class="edge">
|
<g id="edge9" class="edge">
|
||||||
<title>A10->A4</title>
|
<title>A10->A4</title>
|
||||||
<path fill="none" stroke="#000000" d="M316.0157,-474.2481C292.5547,-415.5956 266.6257,-350.7729 254.3377,-320.053"/>
|
<path fill="none" stroke="#000000" d="M318.2339,-474.2481C295.3796,-415.5956 270.1211,-350.7729 258.151,-320.053"/>
|
||||||
<polygon fill="#000000" stroke="#000000" points="319.7574,-483.6023 311.8653,-475.9888 317.9004,-478.9599 316.0435,-474.3175 316.0435,-474.3175 316.0435,-474.3175 317.9004,-478.9599 320.2216,-472.6462 319.7574,-483.6023 319.7574,-483.6023"/>
|
<polygon fill="#000000" stroke="#000000" points="321.8788,-483.6023 314.0551,-475.9185 320.0634,-478.9435 318.2481,-474.2847 318.2481,-474.2847 318.2481,-474.2847 320.0634,-478.9435 322.441,-472.6508 321.8788,-483.6023 321.8788,-483.6023"/>
|
||||||
<text text-anchor="middle" x="268.9174" y="-330.7436" font-family="Helvetica,sans-Serif" font-size="10.00" fill="#000000">0..1</text>
|
<text text-anchor="middle" x="272.6076" y="-330.8736" font-family="Helvetica,sans-Serif" font-size="10.00" fill="#000000">0..1</text>
|
||||||
</g>
|
</g>
|
||||||
<!-- A12 -->
|
<!-- A12 -->
|
||||||
<g id="node13" class="node">
|
<g id="node13" class="node">
|
||||||
<title>A12</title>
|
<title>A12</title>
|
||||||
<polygon fill="none" stroke="#000000" points="434.1165,-336 434.1165,-368 529.1165,-368 529.1165,-336 434.1165,-336"/>
|
<polygon fill="none" stroke="#000000" points="442.1165,-318 442.1165,-350 509.1165,-350 509.1165,-318 442.1165,-318"/>
|
||||||
<text text-anchor="start" x="460.775" y="-349" font-family="Helvetica,sans-Serif" font-size="10.00" fill="#000000">InfosG3P</text>
|
<text text-anchor="start" x="454.775" y="-331" font-family="Helvetica,sans-Serif" font-size="10.00" fill="#000000">InfosG3P</text>
|
||||||
<polygon fill="none" stroke="#000000" points="434.1165,-304 434.1165,-336 529.1165,-336 529.1165,-304 434.1165,-304"/>
|
<polygon fill="none" stroke="#000000" points="442.1165,-298 442.1165,-318 509.1165,-318 509.1165,-298 442.1165,-298"/>
|
||||||
<text text-anchor="start" x="443.829" y="-317" font-family="Helvetica,sans-Serif" font-size="10.00" fill="#000000">client_mode:bool</text>
|
<polygon fill="none" stroke="#000000" points="442.1165,-254 442.1165,-298 509.1165,-298 509.1165,-254 442.1165,-254"/>
|
||||||
<polygon fill="none" stroke="#000000" points="434.1165,-236 434.1165,-304 529.1165,-304 529.1165,-236 434.1165,-236"/>
|
<text text-anchor="start" x="452.0005" y="-279" font-family="Helvetica,sans-Serif" font-size="10.00" fill="#000000">ha_confs()</text>
|
||||||
<text text-anchor="start" x="458.0005" y="-285" font-family="Helvetica,sans-Serif" font-size="10.00" fill="#000000">ha_confs()</text>
|
<text text-anchor="start" x="459.7845" y="-267" font-family="Helvetica,sans-Serif" font-size="10.00" fill="#000000">parse()</text>
|
||||||
<text text-anchor="start" x="465.7845" y="-273" font-family="Helvetica,sans-Serif" font-size="10.00" fill="#000000">parse()</text>
|
|
||||||
<text text-anchor="start" x="469.3985" y="-261" font-family="Helvetica,sans-Serif" font-size="10.00" fill="#000000">calc()</text>
|
|
||||||
<text text-anchor="start" x="467.73" y="-249" font-family="Helvetica,sans-Serif" font-size="10.00" fill="#000000">build()</text>
|
|
||||||
</g>
|
</g>
|
||||||
<!-- A10->A12 -->
|
<!-- A10->A12 -->
|
||||||
<g id="edge12" class="edge">
|
<g id="edge12" class="edge">
|
||||||
<title>A10->A12</title>
|
<title>A10->A12</title>
|
||||||
<path fill="none" stroke="#000000" d="M407.2231,-483.6023C421.5819,-448.3138 437.2,-409.9305 450.3629,-377.5809"/>
|
<path fill="none" stroke="#000000" d="M405.6067,-483.6023C421.7045,-441.5449 439.4849,-395.0916 453.0329,-359.6958"/>
|
||||||
<polygon fill="#000000" stroke="#000000" points="454.1856,-368.1861 454.5848,-379.1447 452.3011,-372.8174 450.4166,-377.4487 450.4166,-377.4487 450.4166,-377.4487 452.3011,-372.8174 446.2485,-375.7526 454.1856,-368.1861 454.1856,-368.1861"/>
|
<polygon fill="#000000" stroke="#000000" points="456.737,-350.0185 457.3649,-360.9664 454.9496,-354.6881 453.1623,-359.3577 453.1623,-359.3577 453.1623,-359.3577 454.9496,-354.6881 448.9596,-357.7491 456.737,-350.0185 456.737,-350.0185"/>
|
||||||
</g>
|
</g>
|
||||||
<!-- A11 -->
|
<!-- A11 -->
|
||||||
<g id="node12" class="node">
|
<g id="node12" class="node">
|
||||||
<title>A11</title>
|
<title>A11</title>
|
||||||
<polygon fill="none" stroke="#000000" points="430.1165,-680 430.1165,-712 533.1165,-712 533.1165,-680 430.1165,-680"/>
|
<polygon fill="none" stroke="#000000" points="428.1165,-680 428.1165,-712 531.1165,-712 531.1165,-680 428.1165,-680"/>
|
||||||
<text text-anchor="start" x="470.7785" y="-693" font-family="Helvetica,sans-Serif" font-size="10.00" fill="#000000">Infos</text>
|
<text text-anchor="start" x="468.7785" y="-693" font-family="Helvetica,sans-Serif" font-size="10.00" fill="#000000">Infos</text>
|
||||||
<polygon fill="none" stroke="#000000" points="430.1165,-624 430.1165,-680 533.1165,-680 533.1165,-624 430.1165,-624"/>
|
<polygon fill="none" stroke="#000000" points="428.1165,-624 428.1165,-680 531.1165,-680 531.1165,-624 428.1165,-624"/>
|
||||||
<text text-anchor="start" x="473.558" y="-661" font-family="Helvetica,sans-Serif" font-size="10.00" fill="#000000">stat</text>
|
<text text-anchor="start" x="471.558" y="-661" font-family="Helvetica,sans-Serif" font-size="10.00" fill="#000000">stat</text>
|
||||||
<text text-anchor="start" x="449.1025" y="-649" font-family="Helvetica,sans-Serif" font-size="10.00" fill="#000000">new_stat_data</text>
|
<text text-anchor="start" x="447.1025" y="-649" font-family="Helvetica,sans-Serif" font-size="10.00" fill="#000000">new_stat_data</text>
|
||||||
<text text-anchor="start" x="462.72" y="-637" font-family="Helvetica,sans-Serif" font-size="10.00" fill="#000000">info_dev</text>
|
<text text-anchor="start" x="460.72" y="-637" font-family="Helvetica,sans-Serif" font-size="10.00" fill="#000000">info_dev</text>
|
||||||
<polygon fill="none" stroke="#000000" points="430.1165,-472 430.1165,-624 533.1165,-624 533.1165,-472 430.1165,-472"/>
|
<polygon fill="none" stroke="#000000" points="428.1165,-472 428.1165,-624 531.1165,-624 531.1165,-472 428.1165,-472"/>
|
||||||
<text text-anchor="start" x="457.452" y="-605" font-family="Helvetica,sans-Serif" font-size="10.00" fill="#000000">static_init()</text>
|
<text text-anchor="start" x="455.452" y="-605" font-family="Helvetica,sans-Serif" font-size="10.00" fill="#000000">static_init()</text>
|
||||||
<text text-anchor="start" x="455.501" y="-593" font-family="Helvetica,sans-Serif" font-size="10.00" fill="#000000">dev_value()</text>
|
<text text-anchor="start" x="453.501" y="-593" font-family="Helvetica,sans-Serif" font-size="10.00" fill="#000000">dev_value()</text>
|
||||||
<text text-anchor="start" x="452.447" y="-581" font-family="Helvetica,sans-Serif" font-size="10.00" fill="#000000">inc_counter()</text>
|
<text text-anchor="start" x="450.447" y="-581" font-family="Helvetica,sans-Serif" font-size="10.00" fill="#000000">inc_counter()</text>
|
||||||
<text text-anchor="start" x="450.777" y="-569" font-family="Helvetica,sans-Serif" font-size="10.00" fill="#000000">dec_counter()</text>
|
<text text-anchor="start" x="448.777" y="-569" font-family="Helvetica,sans-Serif" font-size="10.00" fill="#000000">dec_counter()</text>
|
||||||
<text text-anchor="start" x="448.8265" y="-557" font-family="Helvetica,sans-Serif" font-size="10.00" fill="#000000">ha_proxy_conf</text>
|
<text text-anchor="start" x="446.8265" y="-557" font-family="Helvetica,sans-Serif" font-size="10.00" fill="#000000">ha_proxy_conf</text>
|
||||||
<text text-anchor="start" x="463.8295" y="-545" font-family="Helvetica,sans-Serif" font-size="10.00" fill="#000000">ha_conf</text>
|
<text text-anchor="start" x="461.8295" y="-545" font-family="Helvetica,sans-Serif" font-size="10.00" fill="#000000">ha_conf</text>
|
||||||
<text text-anchor="start" x="456.6105" y="-533" font-family="Helvetica,sans-Serif" font-size="10.00" fill="#000000">ha_remove</text>
|
<text text-anchor="start" x="454.6105" y="-533" font-family="Helvetica,sans-Serif" font-size="10.00" fill="#000000">ha_remove</text>
|
||||||
<text text-anchor="start" x="457.991" y="-521" font-family="Helvetica,sans-Serif" font-size="10.00" fill="#000000">update_db</text>
|
<text text-anchor="start" x="455.991" y="-521" font-family="Helvetica,sans-Serif" font-size="10.00" fill="#000000">update_db</text>
|
||||||
<text text-anchor="start" x="442.1535" y="-509" font-family="Helvetica,sans-Serif" font-size="10.00" fill="#000000">set_db_def_value</text>
|
<text text-anchor="start" x="440.1535" y="-509" font-family="Helvetica,sans-Serif" font-size="10.00" fill="#000000">set_db_def_value</text>
|
||||||
<text text-anchor="start" x="451.602" y="-497" font-family="Helvetica,sans-Serif" font-size="10.00" fill="#000000">get_db_value</text>
|
<text text-anchor="start" x="449.602" y="-497" font-family="Helvetica,sans-Serif" font-size="10.00" fill="#000000">get_db_value</text>
|
||||||
<text text-anchor="start" x="439.939" y="-485" font-family="Helvetica,sans-Serif" font-size="10.00" fill="#000000">ignore_this_device</text>
|
<text text-anchor="start" x="437.939" y="-485" font-family="Helvetica,sans-Serif" font-size="10.00" fill="#000000">ignore_this_device</text>
|
||||||
</g>
|
</g>
|
||||||
<!-- A11->A12 -->
|
<!-- A11->A12 -->
|
||||||
<g id="edge11" class="edge">
|
<g id="edge11" class="edge">
|
||||||
<title>A11->A12</title>
|
<title>A11->A12</title>
|
||||||
<path fill="none" stroke="#000000" d="M481.1165,-461.9134C481.1165,-429.4373 481.1165,-395.9527 481.1165,-368.0691"/>
|
<path fill="none" stroke="#000000" d="M477.322,-461.8987C476.7744,-422.1971 476.206,-380.9898 475.7834,-350.352"/>
|
||||||
<polygon fill="none" stroke="#000000" points="477.6166,-461.9525 481.1165,-471.9525 484.6166,-461.9526 477.6166,-461.9525"/>
|
<polygon fill="none" stroke="#000000" points="473.823,-462.0018 477.4607,-471.9525 480.8223,-461.9052 473.823,-462.0018"/>
|
||||||
</g>
|
</g>
|
||||||
<!-- A13 -->
|
<!-- A13 -->
|
||||||
<g id="node14" class="node">
|
<g id="node14" class="node">
|
||||||
@@ -324,8 +321,8 @@
|
|||||||
<!-- A13->A10 -->
|
<!-- A13->A10 -->
|
||||||
<g id="edge16" class="edge">
|
<g id="edge16" class="edge">
|
||||||
<title>A13->A10</title>
|
<title>A13->A10</title>
|
||||||
<path fill="none" stroke="#000000" d="M276.8964,-1125.5329C298.8204,-989.8666 327.5006,-812.3923 345.6214,-700.2604"/>
|
<path fill="none" stroke="#000000" d="M277.1595,-1125.5329C299.2708,-989.8666 328.1962,-812.3923 346.4719,-700.2604"/>
|
||||||
<polygon fill="none" stroke="#000000" points="273.4037,-1125.2075 275.2634,-1135.6378 280.314,-1126.3243 273.4037,-1125.2075"/>
|
<polygon fill="none" stroke="#000000" points="273.6668,-1125.205 275.5125,-1135.6378 280.5757,-1126.3311 273.6668,-1125.205"/>
|
||||||
</g>
|
</g>
|
||||||
<!-- A14->A13 -->
|
<!-- A14->A13 -->
|
||||||
<g id="edge15" class="edge">
|
<g id="edge15" class="edge">
|
||||||
|
Before Width: | Height: | Size: 32 KiB After Width: | Height: | Size: 32 KiB |
@@ -26,7 +26,7 @@
|
|||||||
[remote:StreamPtr]0..1->[AsyncStreamClient]
|
[remote:StreamPtr]0..1->[AsyncStreamClient]
|
||||||
|
|
||||||
[Infos|stat;new_stat_data;info_dev|static_init();dev_value();inc_counter();dec_counter();ha_proxy_conf;ha_conf;ha_remove;update_db;set_db_def_value;get_db_value;ignore_this_device]
|
[Infos|stat;new_stat_data;info_dev|static_init();dev_value();inc_counter();dec_counter();ha_proxy_conf;ha_conf;ha_remove;update_db;set_db_def_value;get_db_value;ignore_this_device]
|
||||||
[Infos]^[InfosG3P|client_mode:bool|ha_confs();parse();calc();build()]
|
[Infos]^[InfosG3P||ha_confs();parse()]
|
||||||
|
|
||||||
[SolarmanV5]->[InfosG3P]
|
[SolarmanV5]->[InfosG3P]
|
||||||
|
|
||||||
@@ -1,8 +1,8 @@
|
|||||||
flake8==7.1.2
|
flake8
|
||||||
pytest==8.3.5
|
pytest
|
||||||
pytest-asyncio==0.25.3
|
pytest-asyncio
|
||||||
pytest-cov==6.0.0
|
pytest-cov
|
||||||
python-dotenv==1.0.1
|
python-dotenv
|
||||||
mock==5.2.0
|
mock
|
||||||
coverage==7.7.1
|
coverage
|
||||||
jinja2-cli==0.8.2
|
jinja2-cli
|
||||||
@@ -1,4 +1,4 @@
|
|||||||
aiomqtt==2.3.0
|
aiomqtt==2.3.0
|
||||||
schema==0.7.7
|
schema==0.7.7
|
||||||
aiocron==2.1
|
aiocron==1.8
|
||||||
aiohttp==3.11.14
|
aiohttp==3.11.11
|
||||||
@@ -78,8 +78,7 @@ class Config():
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
'inverters': {
|
'inverters': {
|
||||||
'allow_all': Use(bool),
|
'allow_all': Use(bool), And(Use(str), lambda s: len(s) == 16): {
|
||||||
And(Use(str), lambda s: len(s) == 16): {
|
|
||||||
Optional('monitor_sn', default=0): Use(int),
|
Optional('monitor_sn', default=0): Use(int),
|
||||||
Optional('node_id', default=""): And(Use(str),
|
Optional('node_id', default=""): And(Use(str),
|
||||||
Use(lambda s: s + '/'
|
Use(lambda s: s + '/'
|
||||||
@@ -93,13 +92,8 @@ class Config():
|
|||||||
Optional('forward', default=False): Use(bool),
|
Optional('forward', default=False): Use(bool),
|
||||||
},
|
},
|
||||||
Optional('modbus_polling', default=True): Use(bool),
|
Optional('modbus_polling', default=True): Use(bool),
|
||||||
Optional('modbus_scanning'): {
|
|
||||||
'start': Use(int),
|
|
||||||
Optional('step', default=0x400): Use(int),
|
|
||||||
Optional('bytes', default=0x10): Use(int),
|
|
||||||
},
|
|
||||||
Optional('suggested_area', default=""): Use(str),
|
Optional('suggested_area', default=""): Use(str),
|
||||||
Optional('sensor_list', default=0): Use(int),
|
Optional('sensor_list', default=0x2b0): Use(int),
|
||||||
Optional('pv1'): {
|
Optional('pv1'): {
|
||||||
Optional('type'): Use(str),
|
Optional('type'): Use(str),
|
||||||
Optional('manufacturer'): Use(str),
|
Optional('manufacturer'): Use(str),
|
||||||
@@ -125,38 +119,6 @@ class Config():
|
|||||||
Optional('manufacturer'): Use(str),
|
Optional('manufacturer'): Use(str),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
|
||||||
'batteries': {
|
|
||||||
And(Use(str), lambda s: len(s) == 16): {
|
|
||||||
Optional('monitor_sn', default=0): Use(int),
|
|
||||||
Optional('node_id', default=""): And(Use(str),
|
|
||||||
Use(lambda s: s + '/'
|
|
||||||
if len(s) > 0
|
|
||||||
and s[-1] != '/'
|
|
||||||
else s)),
|
|
||||||
Optional('client_mode'): {
|
|
||||||
'host': Use(str),
|
|
||||||
Optional('port', default=8899):
|
|
||||||
And(Use(int), lambda n: 1024 <= n <= 65535),
|
|
||||||
Optional('forward', default=False): Use(bool),
|
|
||||||
},
|
|
||||||
Optional('modbus_polling', default=True): Use(bool),
|
|
||||||
Optional('modbus_scanning'): {
|
|
||||||
'start': Use(int),
|
|
||||||
Optional('step', default=0x400): Use(int),
|
|
||||||
Optional('bytes', default=0x10): Use(int),
|
|
||||||
},
|
|
||||||
Optional('suggested_area', default=""): Use(str),
|
|
||||||
Optional('sensor_list', default=0): Use(int),
|
|
||||||
Optional('pv1'): {
|
|
||||||
Optional('type'): Use(str),
|
|
||||||
Optional('manufacturer'): Use(str),
|
|
||||||
},
|
|
||||||
Optional('pv2'): {
|
|
||||||
Optional('type'): Use(str),
|
|
||||||
Optional('manufacturer'): Use(str),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}, ignore_extra_keys=True
|
}, ignore_extra_keys=True
|
||||||
)
|
)
|
||||||
@@ -216,7 +178,7 @@ here. The default config reader is handled in the Config.init method'''
|
|||||||
rd_config = reader.get_config()
|
rd_config = reader.get_config()
|
||||||
config = cls.act_config.copy()
|
config = cls.act_config.copy()
|
||||||
for key in ['tsun', 'solarman', 'mqtt', 'ha', 'inverters',
|
for key in ['tsun', 'solarman', 'mqtt', 'ha', 'inverters',
|
||||||
'gen3plus', 'batteries']:
|
'gen3plus']:
|
||||||
if key in rd_config:
|
if key in rd_config:
|
||||||
config[key] = config[key] | rd_config[key]
|
config[key] = config[key] | rd_config[key]
|
||||||
|
|
||||||
|
|||||||
@@ -31,8 +31,7 @@ class ConfigReadJson(ConfigIfc):
|
|||||||
def convert_to_obj(self, data):
|
def convert_to_obj(self, data):
|
||||||
conf = {}
|
conf = {}
|
||||||
for key, val in data.items():
|
for key, val in data.items():
|
||||||
if (key == 'inverters' or key == 'batteries') and \
|
if key == 'inverters' and isinstance(val, list):
|
||||||
isinstance(val, list):
|
|
||||||
self.convert_inv_arr(conf, key, val)
|
self.convert_inv_arr(conf, key, val)
|
||||||
else:
|
else:
|
||||||
self._extend_key(conf, key, val)
|
self._extend_key(conf, key, val)
|
||||||
|
|||||||
@@ -2,14 +2,26 @@
|
|||||||
import struct
|
import struct
|
||||||
import logging
|
import logging
|
||||||
from typing import Generator
|
from typing import Generator
|
||||||
from itertools import chain
|
|
||||||
|
|
||||||
from infos import Infos, Register
|
from infos import Infos, Register
|
||||||
|
|
||||||
|
|
||||||
class RegisterMap:
|
class RegisterMap:
|
||||||
__slots__ = ()
|
__slots__ = ()
|
||||||
|
|
||||||
map = {
|
map = {
|
||||||
|
0x00092ba8: {'reg': Register.COLLECTOR_FW_VERSION},
|
||||||
|
0x000927c0: {'reg': Register.CHIP_TYPE},
|
||||||
|
0x00092f90: {'reg': Register.CHIP_MODEL},
|
||||||
|
0x00094ae8: {'reg': Register.MAC_ADDR},
|
||||||
|
0x00095a88: {'reg': Register.TRACE_URL},
|
||||||
|
0x00095aec: {'reg': Register.LOGGER_URL},
|
||||||
|
0x0000000a: {'reg': Register.PRODUCT_NAME},
|
||||||
|
0x00000014: {'reg': Register.MANUFACTURER},
|
||||||
|
0x0000001e: {'reg': Register.VERSION},
|
||||||
|
0x00000028: {'reg': Register.SERIAL_NUMBER},
|
||||||
|
0x00000032: {'reg': Register.EQUIPMENT_MODEL},
|
||||||
|
0x00013880: {'reg': Register.NO_INPUTS},
|
||||||
0xffffff00: {'reg': Register.INVERTER_CNT},
|
0xffffff00: {'reg': Register.INVERTER_CNT},
|
||||||
0xffffff01: {'reg': Register.UNKNOWN_SNR},
|
0xffffff01: {'reg': Register.UNKNOWN_SNR},
|
||||||
0xffffff02: {'reg': Register.UNKNOWN_MSG},
|
0xffffff02: {'reg': Register.UNKNOWN_MSG},
|
||||||
@@ -21,100 +33,6 @@ class RegisterMap:
|
|||||||
0xffffff08: {'reg': Register.POLLING_INTERVAL},
|
0xffffff08: {'reg': Register.POLLING_INTERVAL},
|
||||||
0xfffffffe: {'reg': Register.TEST_REG1},
|
0xfffffffe: {'reg': Register.TEST_REG1},
|
||||||
0xffffffff: {'reg': Register.TEST_REG2},
|
0xffffffff: {'reg': Register.TEST_REG2},
|
||||||
}
|
|
||||||
map_0e100000 = {
|
|
||||||
0x00092ba8: {'reg': Register.COLLECTOR_FW_VERSION},
|
|
||||||
0x000927c0: {'reg': Register.CHIP_TYPE},
|
|
||||||
0x00092f90: {'reg': Register.CHIP_MODEL},
|
|
||||||
0x00094ae8: {'reg': Register.MAC_ADDR},
|
|
||||||
0x00095a88: {'reg': Register.TRACE_URL},
|
|
||||||
0x00095aec: {'reg': Register.LOGGER_URL},
|
|
||||||
0x000cfc38: {'reg': Register.CONNECT_COUNT},
|
|
||||||
0x000c3500: {'reg': Register.SIGNAL_STRENGTH},
|
|
||||||
0x000c96a8: {'reg': Register.POWER_ON_TIME},
|
|
||||||
0x000d0020: {'reg': Register.COLLECT_INTERVAL},
|
|
||||||
0x000cf850: {'reg': Register.DATA_UP_INTERVAL},
|
|
||||||
0x000c7f38: {'reg': Register.COMMUNICATION_TYPE},
|
|
||||||
}
|
|
||||||
map_01900000 = {
|
|
||||||
0x0000000a: {'reg': Register.PRODUCT_NAME},
|
|
||||||
0x00000014: {'reg': Register.MANUFACTURER},
|
|
||||||
0x0000001e: {'reg': Register.VERSION},
|
|
||||||
0x00000046: {'reg': Register.SERIAL_NUMBER},
|
|
||||||
0x0000005A: {'reg': Register.EQUIPMENT_MODEL},
|
|
||||||
0x00000064: {'reg': Register.INVERTER_STATUS},
|
|
||||||
0x00000190: {'reg': Register.EVENT_ALARM},
|
|
||||||
0x000001f4: {'reg': Register.EVENT_FAULT},
|
|
||||||
0x00000258: {'reg': Register.EVENT_BF1},
|
|
||||||
0x000002bc: {'reg': Register.EVENT_BF2},
|
|
||||||
0x00000320: {'reg': Register.TEST_IVAL_1},
|
|
||||||
0x000003e8: {'reg': Register.TEST_VAL_0},
|
|
||||||
0x0000044c: {'reg': Register.TEST_VAL_1}, # DC 1 Inpput Voltage *10
|
|
||||||
0x000004b0: {'reg': Register.TEST_VAL_2},
|
|
||||||
0x00000514: {'reg': Register.GRID_VOLTAGE}, # Grid Voltage
|
|
||||||
0x00000578: {'reg': Register.GRID_CURRENT}, # Grid Current
|
|
||||||
0x000005dc: {'reg': Register.TEST_VAL_3},
|
|
||||||
0x00000640: {'reg': Register.GRID_FREQUENCY},
|
|
||||||
0x000006a4: {'reg': Register.TEST_IVAL_2},
|
|
||||||
0x00000708: {'reg': Register.TEST_IVAL_3},
|
|
||||||
0x0000076c: {'reg': Register.TEST_IVAL_4},
|
|
||||||
0x000007d0: {'reg': Register.TEST_VAL_4}, # DC 2 Input Voltage *10
|
|
||||||
0x00000834: {'reg': Register.MAX_DESIGNED_POWER},
|
|
||||||
0x00000898: {'reg': Register.OUTPUT_POWER}, # Grid Power
|
|
||||||
0x000008fc: {'reg': Register.DAILY_GENERATION}, # Daily Generation
|
|
||||||
0x00000960: {'reg': Register.TOTAL_GENERATION}, # Total Genration
|
|
||||||
0x000009c4: {'reg': Register.TEST_IVAL_5},
|
|
||||||
0x00000a28: {'reg': Register.TEST_VAL_10}, # Isolationsimpedanz Rx
|
|
||||||
0x00000a8c: {'reg': Register.TEST_VAL_11}, # Isolationsimpedanz Ry
|
|
||||||
0x00000af0: {'reg': Register.TEST_IVAL_6},
|
|
||||||
0x000001324: {'reg': Register.PV1_VOLTAGE}, # PV1 Voltage
|
|
||||||
0x000001388: {'reg': Register.PV1_CURRENT}, # PV1 Current
|
|
||||||
0x0000013ec: {'reg': Register.PV1_POWER}, # PV1 Power
|
|
||||||
0x000001450: {'reg': Register.TEST_VAL_5},
|
|
||||||
0x0000015e0: {'reg': Register.PV2_VOLTAGE}, # PV2 Voltage
|
|
||||||
0x000001644: {'reg': Register.PV2_CURRENT}, # PV2 Current
|
|
||||||
0x0000016a8: {'reg': Register.PV2_POWER}, # PV2 Power
|
|
||||||
0x00000170c: {'reg': Register.TEST_VAL_6},
|
|
||||||
0x00000189c: {'reg': Register.PV3_VOLTAGE},
|
|
||||||
0x000001900: {'reg': Register.PV3_CURRENT},
|
|
||||||
0x000001964: {'reg': Register.PV3_POWER},
|
|
||||||
0x0000019c8: {'reg': Register.TEST_VAL_7},
|
|
||||||
0x000001c20: {'reg': Register.TEST_VAL_14},
|
|
||||||
0x000001c84: {'reg': Register.TEST_VAL_15},
|
|
||||||
0x000001ce8: {'reg': Register.TEST_VAL_16}, # DC 1 Voltage
|
|
||||||
0x000001d4c: {'reg': Register.TEST_VAL_17},
|
|
||||||
0x000001db0: {'reg': Register.TEST_VAL_18},
|
|
||||||
0x000001e14: {'reg': Register.TEST_IVAL_8},
|
|
||||||
0x000001e78: {'reg': Register.PV4_VOLTAGE},
|
|
||||||
0x000001edc: {'reg': Register.PV4_CURRENT},
|
|
||||||
0x000001f40: {'reg': Register.PV4_POWER},
|
|
||||||
0x000001fa4: {'reg': Register.TEST_VAL_8},
|
|
||||||
0x0000020c9: {'reg': Register.TEST_IVAL_9},
|
|
||||||
0x0000020db: {'reg': Register.TEST_IVAL_10},
|
|
||||||
|
|
||||||
0x000002134: {'reg': Register.PV5_VOLTAGE},
|
|
||||||
0x000002198: {'reg': Register.PV5_CURRENT},
|
|
||||||
0x0000021fc: {'reg': Register.PV5_POWER},
|
|
||||||
# 0x000002260: {'reg': Register.TEST_VAL_13},
|
|
||||||
0x0000023f0: {'reg': Register.PV6_VOLTAGE},
|
|
||||||
0x000002454: {'reg': Register.PV6_CURRENT},
|
|
||||||
0x0000024b8: {'reg': Register.PV6_POWER},
|
|
||||||
# 0x00000251c: {'reg': Register.TEST_VAL_14},
|
|
||||||
0x000002774: {'reg': Register.TEST_VAL_24},
|
|
||||||
0x0000027d8: {'reg': Register.TEST_VAL_25},
|
|
||||||
0x00000283c: {'reg': Register.TEST_VAL_26}, # DC 2 Voltage
|
|
||||||
0x0000028a0: {'reg': Register.TEST_VAL_27},
|
|
||||||
0x000002904: {'reg': Register.TEST_VAL_28},
|
|
||||||
0x000002968: {'reg': Register.TEST_IVAL_11},
|
|
||||||
0x0000029cc: {'reg': Register.TEST_IVAL_12},
|
|
||||||
}
|
|
||||||
map_01900001 = {
|
|
||||||
0x0000000a: {'reg': Register.PRODUCT_NAME},
|
|
||||||
0x00000014: {'reg': Register.MANUFACTURER},
|
|
||||||
0x0000001e: {'reg': Register.VERSION},
|
|
||||||
0x00000028: {'reg': Register.SERIAL_NUMBER},
|
|
||||||
0x00000032: {'reg': Register.EQUIPMENT_MODEL},
|
|
||||||
0x00013880: {'reg': Register.NO_INPUTS},
|
|
||||||
0x00000640: {'reg': Register.OUTPUT_POWER},
|
0x00000640: {'reg': Register.OUTPUT_POWER},
|
||||||
0x000005dc: {'reg': Register.RATED_POWER},
|
0x000005dc: {'reg': Register.RATED_POWER},
|
||||||
0x00000514: {'reg': Register.INVERTER_TEMP},
|
0x00000514: {'reg': Register.INVERTER_TEMP},
|
||||||
@@ -143,7 +61,12 @@ class RegisterMap:
|
|||||||
0x000003e8: {'reg': Register.GRID_VOLTAGE},
|
0x000003e8: {'reg': Register.GRID_VOLTAGE},
|
||||||
0x0000044c: {'reg': Register.GRID_CURRENT},
|
0x0000044c: {'reg': Register.GRID_CURRENT},
|
||||||
0x000004b0: {'reg': Register.GRID_FREQUENCY},
|
0x000004b0: {'reg': Register.GRID_FREQUENCY},
|
||||||
|
0x000cfc38: {'reg': Register.CONNECT_COUNT},
|
||||||
|
0x000c3500: {'reg': Register.SIGNAL_STRENGTH},
|
||||||
|
0x000c96a8: {'reg': Register.POWER_ON_TIME},
|
||||||
|
0x000d0020: {'reg': Register.COLLECT_INTERVAL},
|
||||||
|
0x000cf850: {'reg': Register.DATA_UP_INTERVAL},
|
||||||
|
0x000c7f38: {'reg': Register.COMMUNICATION_TYPE},
|
||||||
0x00000190: {'reg': Register.EVENT_ALARM},
|
0x00000190: {'reg': Register.EVENT_ALARM},
|
||||||
0x000001f4: {'reg': Register.EVENT_FAULT},
|
0x000001f4: {'reg': Register.EVENT_FAULT},
|
||||||
0x00000258: {'reg': Register.EVENT_BF1},
|
0x00000258: {'reg': Register.EVENT_BF1},
|
||||||
@@ -163,18 +86,6 @@ class RegisterMap:
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
class RegisterSel:
|
|
||||||
__sensor_map = {
|
|
||||||
0x0e100000: RegisterMap.map_0e100000,
|
|
||||||
0x01900000: RegisterMap.map_01900000,
|
|
||||||
0x01900001: RegisterMap.map_01900001,
|
|
||||||
}
|
|
||||||
|
|
||||||
@classmethod
|
|
||||||
def get(cls, sensor: int):
|
|
||||||
return cls.__sensor_map.get(sensor, RegisterMap.map)
|
|
||||||
|
|
||||||
|
|
||||||
class InfosG3(Infos):
|
class InfosG3(Infos):
|
||||||
__slots__ = ()
|
__slots__ = ()
|
||||||
|
|
||||||
@@ -190,27 +101,18 @@ class InfosG3(Infos):
|
|||||||
entity strings
|
entity strings
|
||||||
sug_area:str ==> suggested area string from the config file'''
|
sug_area:str ==> suggested area string from the config file'''
|
||||||
# iterate over RegisterMap.map and get the register values
|
# iterate over RegisterMap.map and get the register values
|
||||||
sensor = self.get_db_value(Register.SENSOR_LIST)
|
for row in RegisterMap.map.values():
|
||||||
if "01900000" == sensor:
|
|
||||||
items = RegisterMap.map_01900000.items()
|
|
||||||
elif "01900001" == sensor:
|
|
||||||
items = RegisterMap.map_01900001.items()
|
|
||||||
else:
|
|
||||||
items = {}
|
|
||||||
|
|
||||||
for _, row in chain(RegisterMap.map_0e100000.items(), items):
|
|
||||||
reg = row['reg']
|
reg = row['reg']
|
||||||
res = self.ha_conf(reg, ha_prfx, node_id, snr, False, sug_area) # noqa: E501
|
res = self.ha_conf(reg, ha_prfx, node_id, snr, False, sug_area) # noqa: E501
|
||||||
if res:
|
if res:
|
||||||
yield res
|
yield res
|
||||||
|
|
||||||
def parse(self, buf, ind=0, sensor: int = 0, node_id: str = '') -> \
|
def parse(self, buf, ind=0, node_id: str = '') -> \
|
||||||
Generator[tuple[str, bool], None, None]:
|
Generator[tuple[str, bool], None, None]:
|
||||||
'''parse a data sequence received from the inverter and
|
'''parse a data sequence received from the inverter and
|
||||||
stores the values in Infos.db
|
stores the values in Infos.db
|
||||||
|
|
||||||
buf: buffer of the sequence to parse'''
|
buf: buffer of the sequence to parse'''
|
||||||
reg_map = RegisterSel.get(sensor)
|
|
||||||
result = struct.unpack_from('!l', buf, ind)
|
result = struct.unpack_from('!l', buf, ind)
|
||||||
elms = result[0]
|
elms = result[0]
|
||||||
i = 0
|
i = 0
|
||||||
@@ -218,11 +120,11 @@ class InfosG3(Infos):
|
|||||||
while i < elms:
|
while i < elms:
|
||||||
result = struct.unpack_from('!lB', buf, ind)
|
result = struct.unpack_from('!lB', buf, ind)
|
||||||
addr = result[0]
|
addr = result[0]
|
||||||
if addr not in reg_map:
|
if addr not in RegisterMap.map:
|
||||||
row = None
|
row = None
|
||||||
info_id = -1
|
info_id = -1
|
||||||
else:
|
else:
|
||||||
row = reg_map[addr]
|
row = RegisterMap.map[addr]
|
||||||
info_id = row['reg']
|
info_id = row['reg']
|
||||||
data_type = result[1]
|
data_type = result[1]
|
||||||
ind += 5
|
ind += 5
|
||||||
@@ -290,6 +192,3 @@ class InfosG3(Infos):
|
|||||||
if update:
|
if update:
|
||||||
self.tracer.log(level, f'[{node_id}] GEN3: {name} :'
|
self.tracer.log(level, f'[{node_id}] GEN3: {name} :'
|
||||||
f' {result}{unit}')
|
f' {result}{unit}')
|
||||||
|
|
||||||
logging.log(level, f'[{node_id}] GEN3: {name} :'
|
|
||||||
f' {result}{unit}')
|
|
||||||
|
|||||||
@@ -75,7 +75,6 @@ class Talent(Message):
|
|||||||
0x87: self.get_modbus_log_lvl,
|
0x87: self.get_modbus_log_lvl,
|
||||||
0x04: logging.INFO,
|
0x04: logging.INFO,
|
||||||
}
|
}
|
||||||
self.sensor_list = 0
|
|
||||||
|
|
||||||
'''
|
'''
|
||||||
Our puplic methods
|
Our puplic methods
|
||||||
@@ -99,9 +98,13 @@ class Talent(Message):
|
|||||||
|
|
||||||
if serial_no in inverters:
|
if serial_no in inverters:
|
||||||
inv = inverters[serial_no]
|
inv = inverters[serial_no]
|
||||||
self._set_config_parms(inv)
|
self.node_id = inv['node_id']
|
||||||
self.db.set_pv_module_details(inv)
|
self.sug_area = inv['suggested_area']
|
||||||
|
self.modbus_polling = inv['modbus_polling']
|
||||||
logger.debug(f'SerialNo {serial_no} allowed! area:{self.sug_area}') # noqa: E501
|
logger.debug(f'SerialNo {serial_no} allowed! area:{self.sug_area}') # noqa: E501
|
||||||
|
self.db.set_pv_module_details(inv)
|
||||||
|
if self.mb:
|
||||||
|
self.mb.set_node_id(self.node_id)
|
||||||
else:
|
else:
|
||||||
self.node_id = ''
|
self.node_id = ''
|
||||||
self.sug_area = ''
|
self.sug_area = ''
|
||||||
@@ -172,17 +175,12 @@ class Talent(Message):
|
|||||||
|
|
||||||
def mb_timout_cb(self, exp_cnt):
|
def mb_timout_cb(self, exp_cnt):
|
||||||
self.mb_timer.start(self.mb_timeout)
|
self.mb_timer.start(self.mb_timeout)
|
||||||
if self.mb_scan:
|
|
||||||
self._send_modbus_scan()
|
|
||||||
return
|
|
||||||
|
|
||||||
if 2 == (exp_cnt % 30):
|
if 2 == (exp_cnt % 30):
|
||||||
# logging.info("Regular Modbus Status request")
|
# logging.info("Regular Modbus Status request")
|
||||||
self._send_modbus_cmd(Modbus.INV_ADDR, Modbus.READ_REGS, 0x2000,
|
self._send_modbus_cmd(Modbus.READ_REGS, 0x2000, 96, logging.DEBUG)
|
||||||
96, logging.DEBUG)
|
|
||||||
else:
|
else:
|
||||||
self._send_modbus_cmd(Modbus.INV_ADDR, Modbus.READ_REGS, 0x3000,
|
self._send_modbus_cmd(Modbus.READ_REGS, 0x3000, 48, logging.DEBUG)
|
||||||
48, logging.DEBUG)
|
|
||||||
|
|
||||||
def _init_new_client_conn(self) -> bool:
|
def _init_new_client_conn(self) -> bool:
|
||||||
contact_name = self.contact_name
|
contact_name = self.contact_name
|
||||||
@@ -444,7 +442,7 @@ class Talent(Message):
|
|||||||
logger.debug(f'time: {timestamp:08x}')
|
logger.debug(f'time: {timestamp:08x}')
|
||||||
# logger.info(f'time: {datetime.utcfromtimestamp(result[2]).strftime(
|
# logger.info(f'time: {datetime.utcfromtimestamp(result[2]).strftime(
|
||||||
# "%Y-%m-%d %H:%M:%S")}')
|
# "%Y-%m-%d %H:%M:%S")}')
|
||||||
return msg_hdr_len, data_id, timestamp
|
return msg_hdr_len, timestamp
|
||||||
|
|
||||||
def msg_collector_data(self):
|
def msg_collector_data(self):
|
||||||
if self.ctrl.is_ind():
|
if self.ctrl.is_ind():
|
||||||
@@ -481,51 +479,21 @@ class Talent(Message):
|
|||||||
|
|
||||||
self.forward()
|
self.forward()
|
||||||
|
|
||||||
def __build_model_name(self):
|
def __process_data(self, ignore_replay: bool):
|
||||||
db = self.db
|
msg_hdr_len, ts = self.parse_msg_header()
|
||||||
model = db.get_db_value(Register.EQUIPMENT_MODEL, None)
|
if ignore_replay:
|
||||||
if model:
|
|
||||||
return
|
|
||||||
max_pow = db.get_db_value(Register.MAX_DESIGNED_POWER, 0)
|
|
||||||
if max_pow == 3000:
|
|
||||||
model = f'TSOL-MS{max_pow}'
|
|
||||||
self.db.set_db_def_value(Register.EQUIPMENT_MODEL, model)
|
|
||||||
self.db.set_db_def_value(Register.MANUFACTURER, 'TSUN')
|
|
||||||
self.db.set_db_def_value(Register.NO_INPUTS, 4)
|
|
||||||
|
|
||||||
def __process_data(self, inv_data: bool):
|
|
||||||
msg_hdr_len, data_id, ts = self.parse_msg_header()
|
|
||||||
if inv_data:
|
|
||||||
# handle register mapping
|
|
||||||
if 0 == self.sensor_list:
|
|
||||||
self.sensor_list = data_id
|
|
||||||
self.db.set_db_def_value(Register.SENSOR_LIST,
|
|
||||||
f"{self.sensor_list:08x}")
|
|
||||||
logging.debug(f"Use sensor-list: {self.sensor_list:#08x}"
|
|
||||||
f" for '{self.unique_id}'")
|
|
||||||
if data_id != self.sensor_list:
|
|
||||||
logging.warning(f'Unexpected Sensor-List:{data_id:08x}'
|
|
||||||
f' (!={self.sensor_list:08x})')
|
|
||||||
# ignore replays for inverter data
|
|
||||||
age = self._utc() - self._utcfromts(ts)
|
age = self._utc() - self._utcfromts(ts)
|
||||||
age = age/(3600*24)
|
age = age/(3600*24)
|
||||||
logger.debug(f"Age: {age} days")
|
logger.debug(f"Age: {age} days")
|
||||||
if age > 1: # is a replay?
|
if age > 1:
|
||||||
return
|
return
|
||||||
|
|
||||||
inv_update = False
|
|
||||||
|
|
||||||
for key, update in self.db.parse(self.ifc.rx_peek(), self.header_len
|
for key, update in self.db.parse(self.ifc.rx_peek(), self.header_len
|
||||||
+ msg_hdr_len, data_id, self.node_id):
|
+ msg_hdr_len, self.node_id):
|
||||||
if update:
|
if update:
|
||||||
if key == 'inverter':
|
|
||||||
inv_update = True
|
|
||||||
self._set_mqtt_timestamp(key, self._utcfromts(ts))
|
self._set_mqtt_timestamp(key, self._utcfromts(ts))
|
||||||
self.new_data[key] = True
|
self.new_data[key] = True
|
||||||
|
|
||||||
if inv_update:
|
|
||||||
self.__build_model_name()
|
|
||||||
|
|
||||||
def msg_ota_update(self):
|
def msg_ota_update(self):
|
||||||
if self.ctrl.is_req():
|
if self.ctrl.is_req():
|
||||||
self.inc_counter('OTA_Start_Msg')
|
self.inc_counter('OTA_Start_Msg')
|
||||||
@@ -586,9 +554,6 @@ class Talent(Message):
|
|||||||
logger.warning('Unknown Message')
|
logger.warning('Unknown Message')
|
||||||
self.inc_counter('Unknown_Msg')
|
self.inc_counter('Unknown_Msg')
|
||||||
return
|
return
|
||||||
if (self.mb_scan):
|
|
||||||
modbus_msg_len = self.data_len - hdr_len
|
|
||||||
self._dump_modbus_scan(data, hdr_len, modbus_msg_len)
|
|
||||||
|
|
||||||
for key, update, _ in self.mb.recv_resp(self.db, data[
|
for key, update, _ in self.mb.recv_resp(self.db, data[
|
||||||
hdr_len:]):
|
hdr_len:]):
|
||||||
|
|||||||
@@ -1,25 +1,9 @@
|
|||||||
|
|
||||||
from typing import Generator
|
from typing import Generator
|
||||||
from itertools import chain
|
|
||||||
|
|
||||||
from infos import Infos, Register, ProxyMode, Fmt
|
from infos import Infos, Register, ProxyMode, Fmt
|
||||||
|
|
||||||
|
|
||||||
class RegisterFunc:
|
|
||||||
@staticmethod
|
|
||||||
def prod_sum(info: Infos, arr: dict) -> None | int:
|
|
||||||
result = 0
|
|
||||||
for sum in arr:
|
|
||||||
prod = 1
|
|
||||||
for factor in sum:
|
|
||||||
val = info.get_db_value(factor)
|
|
||||||
if val is None:
|
|
||||||
return None
|
|
||||||
prod = prod * val
|
|
||||||
result += prod
|
|
||||||
return result
|
|
||||||
|
|
||||||
|
|
||||||
class RegisterMap:
|
class RegisterMap:
|
||||||
# make the class read/only by using __slots__
|
# make the class read/only by using __slots__
|
||||||
__slots__ = ()
|
__slots__ = ()
|
||||||
@@ -48,8 +32,7 @@ class RegisterMap:
|
|||||||
0x4102008e: {'reg': None, 'fmt': '<B'}, # noqa: E501 Encryption Certificate File Status
|
0x4102008e: {'reg': None, 'fmt': '<B'}, # noqa: E501 Encryption Certificate File Status
|
||||||
0x4102008f: {'reg': None, 'fmt': '!40s'}, # noqa: E501
|
0x4102008f: {'reg': None, 'fmt': '!40s'}, # noqa: E501
|
||||||
0x410200b7: {'reg': Register.SSID, 'fmt': '!40s'}, # noqa: E501
|
0x410200b7: {'reg': Register.SSID, 'fmt': '!40s'}, # noqa: E501
|
||||||
}
|
|
||||||
map_02b0 = {
|
|
||||||
0x4201000c: {'reg': Register.SENSOR_LIST, 'fmt': '<H', 'func': Fmt.hex4}, # noqa: E501
|
0x4201000c: {'reg': Register.SENSOR_LIST, 'fmt': '<H', 'func': Fmt.hex4}, # noqa: E501
|
||||||
0x4201001c: {'reg': Register.POWER_ON_TIME, 'fmt': '<H', 'ratio': 1, 'dep': ProxyMode.SERVER}, # noqa: E501, or packet number
|
0x4201001c: {'reg': Register.POWER_ON_TIME, 'fmt': '<H', 'ratio': 1, 'dep': ProxyMode.SERVER}, # noqa: E501, or packet number
|
||||||
0x42010020: {'reg': Register.SERIAL_NUMBER, 'fmt': '!16s'}, # noqa: E501
|
0x42010020: {'reg': Register.SERIAL_NUMBER, 'fmt': '!16s'}, # noqa: E501
|
||||||
@@ -127,69 +110,6 @@ class RegisterMap:
|
|||||||
0xffffff02: {'reg': Register.POLLING_INTERVAL},
|
0xffffff02: {'reg': Register.POLLING_INTERVAL},
|
||||||
# 0x4281001c: {'reg': Register.POWER_ON_TIME, 'fmt': '<H', 'ratio': 1}, # noqa: E501
|
# 0x4281001c: {'reg': Register.POWER_ON_TIME, 'fmt': '<H', 'ratio': 1}, # noqa: E501
|
||||||
}
|
}
|
||||||
map_3026 = {
|
|
||||||
0x4201000c: {'reg': Register.SENSOR_LIST, 'fmt': '<H', 'func': Fmt.hex4}, # noqa: E501
|
|
||||||
0x4201001c: {'reg': Register.POWER_ON_TIME, 'fmt': '<H', 'ratio': 1, 'dep': ProxyMode.SERVER}, # noqa: E501, or packet number
|
|
||||||
0x42010020: {'reg': Register.SERIAL_NUMBER, 'fmt': '!16s'}, # noqa: E501
|
|
||||||
0x42010030: {'reg': Register.BATT_PV1_VOLT, 'fmt': '!H', 'ratio': 0.01}, # noqa: E501, PV1 voltage
|
|
||||||
0x42010032: {'reg': Register.BATT_PV1_CUR, 'fmt': '!H', 'ratio': 0.01}, # noqa: E501, PV1 current
|
|
||||||
0x42010034: {'reg': Register.BATT_PV2_VOLT, 'fmt': '!H', 'ratio': 0.01}, # noqa: E501, PV2 voltage
|
|
||||||
0x42010036: {'reg': Register.BATT_PV2_CUR, 'fmt': '!H', 'ratio': 0.01}, # noqa: E501, PV2 current
|
|
||||||
0x42010038: {'reg': Register.BATT_38, 'fmt': '!h'}, # noqa: E501
|
|
||||||
0x4201003a: {'reg': Register.BATT_TOTAL_GEN, 'fmt': '!h', 'ratio': 0.01}, # noqa: E501
|
|
||||||
0x4201003c: {'reg': Register.BATT_STATUS_1, 'fmt': '!h'}, # noqa: E501 MPTT-1 Status?
|
|
||||||
0x4201003e: {'reg': Register.BATT_STATUS_2, 'fmt': '!h'}, # noqa: E501 MPTT-2 Status?
|
|
||||||
0x42010040: {'reg': Register.BATT_VOLT, 'fmt': '!h', 'ratio': 0.01}, # noqa: E501
|
|
||||||
0x42010042: {'reg': Register.BATT_CUR, 'fmt': '!h', 'ratio': 0.01}, # noqa: E501
|
|
||||||
0x42010044: {'reg': Register.BATT_SOC, 'fmt': '!H', 'ratio': 0.01}, # noqa: E501, state of charge (SOC) in percent
|
|
||||||
0x42010046: {'reg': Register.BATT_CELL1_VOLT, 'fmt': '!h', 'ratio': 0.001}, # noqa: E501
|
|
||||||
0x42010048: {'reg': Register.BATT_CELL2_VOLT, 'fmt': '!h', 'ratio': 0.001}, # noqa: E501
|
|
||||||
0x4201004a: {'reg': Register.BATT_CELL3_VOLT, 'fmt': '!h', 'ratio': 0.001}, # noqa: E501
|
|
||||||
0x4201004c: {'reg': Register.BATT_CELL4_VOLT, 'fmt': '!h', 'ratio': 0.001}, # noqa: E501
|
|
||||||
0x4201004e: {'reg': Register.BATT_CELL5_VOLT, 'fmt': '!h', 'ratio': 0.001}, # noqa: E501
|
|
||||||
0x42010050: {'reg': Register.BATT_CELL6_VOLT, 'fmt': '!h', 'ratio': 0.001}, # noqa: E501
|
|
||||||
0x42010052: {'reg': Register.BATT_CELL7_VOLT, 'fmt': '!h', 'ratio': 0.001}, # noqa: E501
|
|
||||||
0x42010054: {'reg': Register.BATT_CELL8_VOLT, 'fmt': '!h', 'ratio': 0.001}, # noqa: E501
|
|
||||||
0x42010056: {'reg': Register.BATT_CELL9_VOLT, 'fmt': '!h', 'ratio': 0.001}, # noqa: E501
|
|
||||||
0x42010058: {'reg': Register.BATT_CELL10_VOLT, 'fmt': '!h', 'ratio': 0.001}, # noqa: E501
|
|
||||||
0x4201005a: {'reg': Register.BATT_CELL11_VOLT, 'fmt': '!h', 'ratio': 0.001}, # noqa: E501
|
|
||||||
0x4201005c: {'reg': Register.BATT_CELL12_VOLT, 'fmt': '!h', 'ratio': 0.001}, # noqa: E501
|
|
||||||
0x4201005e: {'reg': Register.BATT_CELL13_VOLT, 'fmt': '!h', 'ratio': 0.001}, # noqa: E501
|
|
||||||
0x42010060: {'reg': Register.BATT_CELL14_VOLT, 'fmt': '!h', 'ratio': 0.001}, # noqa: E501
|
|
||||||
0x42010062: {'reg': Register.BATT_CELL15_VOLT, 'fmt': '!h', 'ratio': 0.001}, # noqa: E501
|
|
||||||
0x42010064: {'reg': Register.BATT_CELL16_VOLT, 'fmt': '!h', 'ratio': 0.001}, # noqa: E501
|
|
||||||
|
|
||||||
0x42010066: {'reg': Register.BATT_TEMP_1, 'fmt': '!h'}, # noqa: E501
|
|
||||||
0x42010068: {'reg': Register.BATT_TEMP_2, 'fmt': '!h'}, # noqa: E501
|
|
||||||
0x4201006a: {'reg': Register.BATT_TEMP_3, 'fmt': '!h'}, # noqa: E501
|
|
||||||
0x4201006c: {'reg': Register.BATT_OUT_VOLT, 'fmt': '!h', 'ratio': 0.01}, # noqa: E501
|
|
||||||
0x4201006e: {'reg': Register.BATT_OUT_CUR, 'fmt': '!h', 'ratio': 0.01}, # noqa: E501
|
|
||||||
0x42010070: {'reg': Register.BATT_OUT_STATUS, 'fmt': '!h'}, # noqa: E501, state of output value 0 or 1
|
|
||||||
0x42010072: {'reg': Register.BATT_TEMP_4, 'fmt': '!h'}, # noqa: E501 controller temp
|
|
||||||
0x42010074: {'reg': Register.BATT_74, 'fmt': '!h'}, # noqa: E501, control input 0..2048
|
|
||||||
0x42010076: {'reg': Register.BATT_76, 'fmt': '!h'}, # noqa: E501
|
|
||||||
0x42010078: {'reg': Register.BATT_78, 'fmt': '!h'}, # noqa: E501
|
|
||||||
'calc': {
|
|
||||||
1: {'reg': Register.BATT_PV_PWR, 'func': RegisterFunc.prod_sum, # noqa: E501
|
|
||||||
'params': [[Register.BATT_PV1_VOLT, Register.BATT_PV1_CUR],
|
|
||||||
[Register.BATT_PV2_VOLT, Register.BATT_PV2_CUR]]},
|
|
||||||
2: {'reg': Register.BATT_PWR, 'func': RegisterFunc.prod_sum, # noqa: E501
|
|
||||||
'params': [[Register.BATT_VOLT, Register.BATT_CUR]]},
|
|
||||||
3: {'reg': Register.BATT_OUT_PWR, 'func': RegisterFunc.prod_sum, # noqa: E501
|
|
||||||
'params': [[Register.BATT_OUT_VOLT, Register.BATT_OUT_CUR]]},
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
class RegisterSel:
|
|
||||||
__sensor_map = {
|
|
||||||
0x02b0: RegisterMap.map_02b0,
|
|
||||||
0x3026: RegisterMap.map_3026,
|
|
||||||
}
|
|
||||||
|
|
||||||
@classmethod
|
|
||||||
def get(cls, sensor: int):
|
|
||||||
return cls.__sensor_map.get(sensor, RegisterMap.map)
|
|
||||||
|
|
||||||
|
|
||||||
class InfosG3P(Infos):
|
class InfosG3P(Infos):
|
||||||
@@ -224,22 +144,7 @@ class InfosG3P(Infos):
|
|||||||
entity strings
|
entity strings
|
||||||
sug_area:str ==> suggested area string from the config file'''
|
sug_area:str ==> suggested area string from the config file'''
|
||||||
# iterate over RegisterMap.map and get the register values
|
# iterate over RegisterMap.map and get the register values
|
||||||
sensor = self.get_db_value(Register.SENSOR_LIST)
|
for row in RegisterMap.map.values():
|
||||||
if "3026" == sensor:
|
|
||||||
reg_map = RegisterMap.map_3026
|
|
||||||
elif "02b0" == sensor:
|
|
||||||
reg_map = RegisterMap.map_02b0
|
|
||||||
else:
|
|
||||||
reg_map = {}
|
|
||||||
items = reg_map.items()
|
|
||||||
if 'calc' in reg_map:
|
|
||||||
virt = reg_map['calc'].items()
|
|
||||||
else:
|
|
||||||
virt = {}
|
|
||||||
|
|
||||||
for idx, row in chain(RegisterMap.map.items(), items, virt):
|
|
||||||
if 'calc' == idx:
|
|
||||||
continue
|
|
||||||
info_id = row['reg']
|
info_id = row['reg']
|
||||||
if self.__hide_topic(row):
|
if self.__hide_topic(row):
|
||||||
res = self.ha_remove(info_id, node_id, snr) # noqa: E501
|
res = self.ha_remove(info_id, node_id, snr) # noqa: E501
|
||||||
@@ -248,17 +153,13 @@ class InfosG3P(Infos):
|
|||||||
if res:
|
if res:
|
||||||
yield res
|
yield res
|
||||||
|
|
||||||
def parse(self, buf, msg_type: int, rcv_ftype: int,
|
def parse(self, buf, msg_type: int, rcv_ftype: int, node_id: str = '') \
|
||||||
sensor: int = 0, node_id: str = '') \
|
|
||||||
-> Generator[tuple[str, bool], None, None]:
|
-> Generator[tuple[str, bool], None, None]:
|
||||||
'''parse a data sequence received from the inverter and
|
'''parse a data sequence received from the inverter and
|
||||||
stores the values in Infos.db
|
stores the values in Infos.db
|
||||||
|
|
||||||
buf: buffer of the sequence to parse'''
|
buf: buffer of the sequence to parse'''
|
||||||
reg_map = RegisterSel.get(sensor)
|
for idx, row in RegisterMap.map.items():
|
||||||
for idx, row in reg_map.items():
|
|
||||||
if 'calc' == idx:
|
|
||||||
continue
|
|
||||||
addr = idx & 0xffff
|
addr = idx & 0xffff
|
||||||
ftype = (idx >> 16) & 0xff
|
ftype = (idx >> 16) & 0xff
|
||||||
mtype = (idx >> 24) & 0xff
|
mtype = (idx >> 24) & 0xff
|
||||||
@@ -268,36 +169,23 @@ class InfosG3P(Infos):
|
|||||||
continue
|
continue
|
||||||
info_id = row['reg']
|
info_id = row['reg']
|
||||||
result = Fmt.get_value(buf, addr, row)
|
result = Fmt.get_value(buf, addr, row)
|
||||||
yield from self.__update_val(node_id, "GEN3PLUS", info_id, result)
|
|
||||||
yield from self.calc(sensor, node_id)
|
|
||||||
|
|
||||||
def calc(self, sensor: int = 0, node_id: str = '') \
|
keys, level, unit, must_incr = self._key_obj(info_id)
|
||||||
-> Generator[tuple[str, bool], None, None]:
|
|
||||||
'''calculate meta values from the
|
|
||||||
stored values in Infos.db
|
|
||||||
|
|
||||||
sensor: sensor_list number
|
if keys:
|
||||||
node_id: id-string for the node'''
|
name, update = self.update_db(keys, must_incr, result)
|
||||||
|
yield keys[0], update
|
||||||
|
else:
|
||||||
|
name = str(f'info-id.0x{addr:x}')
|
||||||
|
update = False
|
||||||
|
|
||||||
reg_map = RegisterSel.get(sensor)
|
|
||||||
if 'calc' in reg_map:
|
|
||||||
for row in reg_map['calc'].values():
|
|
||||||
info_id = row['reg']
|
|
||||||
result = row['func'](self, row['params'])
|
|
||||||
yield from self.__update_val(node_id, "CALC", info_id, result)
|
|
||||||
|
|
||||||
def __update_val(self, node_id, source: str, info_id, result):
|
|
||||||
keys, level, unit, must_incr = self._key_obj(info_id)
|
|
||||||
if keys:
|
|
||||||
name, update = self.update_db(keys, must_incr, result)
|
|
||||||
yield keys[0], update
|
|
||||||
if update:
|
if update:
|
||||||
self.tracer.log(level, f'[{node_id}] {source}: {name}'
|
self.tracer.log(level, f'[{node_id}] GEN3PLUS: {name}'
|
||||||
f' : {result}{unit}')
|
f' : {result}{unit}')
|
||||||
|
|
||||||
def build(self, len, msg_type: int, rcv_ftype: int, sensor: int = 0):
|
def build(self, len, msg_type: int, rcv_ftype: int):
|
||||||
buf = bytearray(len)
|
buf = bytearray(len)
|
||||||
for idx, row in RegisterSel.get(sensor).items():
|
for idx, row in RegisterMap.map.items():
|
||||||
addr = idx & 0xffff
|
addr = idx & 0xffff
|
||||||
ftype = (idx >> 16) & 0xff
|
ftype = (idx >> 16) & 0xff
|
||||||
mtype = (idx >> 24) & 0xff
|
mtype = (idx >> 24) & 0xff
|
||||||
|
|||||||
@@ -103,7 +103,7 @@ class SolarmanEmu(SolarmanBase):
|
|||||||
self.data_timer.start(self.data_up_inv)
|
self.data_timer.start(self.data_up_inv)
|
||||||
_len = 420
|
_len = 420
|
||||||
ftype = 1
|
ftype = 1
|
||||||
build_msg = self.db.build(_len, 0x42, ftype, 0x02b0)
|
build_msg = self.db.build(_len, 0x42, ftype)
|
||||||
|
|
||||||
self._build_header(0x4210)
|
self._build_header(0x4210)
|
||||||
self.ifc.tx_add(
|
self.ifc.tx_add(
|
||||||
|
|||||||
@@ -2,10 +2,8 @@ import struct
|
|||||||
import logging
|
import logging
|
||||||
import time
|
import time
|
||||||
import asyncio
|
import asyncio
|
||||||
from itertools import chain
|
|
||||||
from datetime import datetime
|
from datetime import datetime
|
||||||
|
|
||||||
from proxy import Proxy
|
|
||||||
from async_ifc import AsyncIfc
|
from async_ifc import AsyncIfc
|
||||||
from messages import hex_dump_memory, Message, State
|
from messages import hex_dump_memory, Message, State
|
||||||
from cnf.config import Config
|
from cnf.config import Config
|
||||||
@@ -247,7 +245,6 @@ class SolarmanBase(Message):
|
|||||||
class SolarmanV5(SolarmanBase):
|
class SolarmanV5(SolarmanBase):
|
||||||
AT_CMD = 1
|
AT_CMD = 1
|
||||||
MB_RTU_CMD = 2
|
MB_RTU_CMD = 2
|
||||||
AT_CMD_RSP = 8
|
|
||||||
MB_CLIENT_DATA_UP = 30
|
MB_CLIENT_DATA_UP = 30
|
||||||
'''Data up time in client mode'''
|
'''Data up time in client mode'''
|
||||||
HDR_FMT = '<BLLL'
|
HDR_FMT = '<BLLL'
|
||||||
@@ -293,7 +290,7 @@ class SolarmanV5(SolarmanBase):
|
|||||||
# MODbus or AT cmd
|
# MODbus or AT cmd
|
||||||
0x4510: self.msg_command_req, # from server
|
0x4510: self.msg_command_req, # from server
|
||||||
0x1510: self.msg_command_rsp, # from inverter
|
0x1510: self.msg_command_rsp, # from inverter
|
||||||
0x0510: self.msg_command_rsp, # from inverter
|
# 0x0510: self.msg_command_rsp, # from inverter
|
||||||
}
|
}
|
||||||
|
|
||||||
self.log_lvl = {
|
self.log_lvl = {
|
||||||
@@ -324,8 +321,6 @@ class SolarmanV5(SolarmanBase):
|
|||||||
self.at_acl = g3p_cnf['at_acl']
|
self.at_acl = g3p_cnf['at_acl']
|
||||||
|
|
||||||
self.sensor_list = 0
|
self.sensor_list = 0
|
||||||
self.mb_regs = [{'addr': 0x3000, 'len': 48},
|
|
||||||
{'addr': 0x2000, 'len': 96}]
|
|
||||||
|
|
||||||
'''
|
'''
|
||||||
Our puplic methods
|
Our puplic methods
|
||||||
@@ -361,16 +356,7 @@ class SolarmanV5(SolarmanBase):
|
|||||||
self.new_data['controller'] = True
|
self.new_data['controller'] = True
|
||||||
|
|
||||||
self.state = State.up
|
self.state = State.up
|
||||||
|
self._send_modbus_cmd(Modbus.READ_REGS, 0x3000, 48, logging.DEBUG)
|
||||||
if self.mb_scan:
|
|
||||||
self._send_modbus_cmd(self.mb_inv_no, Modbus.READ_REGS,
|
|
||||||
self.mb_start_reg, self.mb_bytes,
|
|
||||||
logging.INFO)
|
|
||||||
else:
|
|
||||||
self._send_modbus_cmd(Modbus.INV_ADDR, Modbus.READ_REGS,
|
|
||||||
self.mb_regs[0]['addr'],
|
|
||||||
self.mb_regs[0]['len'], logging.DEBUG)
|
|
||||||
|
|
||||||
self.mb_timer.start(self.mb_timeout)
|
self.mb_timer.start(self.mb_timeout)
|
||||||
|
|
||||||
def new_state_up(self):
|
def new_state_up(self):
|
||||||
@@ -390,25 +376,14 @@ class SolarmanV5(SolarmanBase):
|
|||||||
self.ifc.fwd_add(build_msg)
|
self.ifc.fwd_add(build_msg)
|
||||||
self.ifc.fwd_add(struct.pack('<BB', 0, 0x15)) # crc & stop
|
self.ifc.fwd_add(struct.pack('<BB', 0, 0x15)) # crc & stop
|
||||||
|
|
||||||
def _set_config_parms(self, inv: dict, serial_no: str = ""):
|
def __set_config_parms(self, inv: dict):
|
||||||
'''init connection with params from the configuration'''
|
'''init connection with params from the configuration'''
|
||||||
super()._set_config_parms(inv)
|
self.node_id = inv['node_id']
|
||||||
snr = serial_no[:3]
|
self.sug_area = inv['suggested_area']
|
||||||
if '410' == snr:
|
self.modbus_polling = inv['modbus_polling']
|
||||||
self.db.set_db_def_value(Register.EQUIPMENT_MODEL,
|
|
||||||
'TSOL-DC1000')
|
|
||||||
|
|
||||||
self.sensor_list = inv['sensor_list']
|
self.sensor_list = inv['sensor_list']
|
||||||
if 0 == self.sensor_list:
|
if self.mb:
|
||||||
if '410' == snr:
|
self.mb.set_node_id(self.node_id)
|
||||||
self.sensor_list = 0x3026
|
|
||||||
self.mb_regs = [{'addr': 0x0000, 'len': 45}]
|
|
||||||
else:
|
|
||||||
self.sensor_list = 0x02b0
|
|
||||||
self.db.set_db_def_value(Register.SENSOR_LIST,
|
|
||||||
f"{self.sensor_list:04x}")
|
|
||||||
logging.debug(f"Use sensor-list: {self.sensor_list:#04x}"
|
|
||||||
f" for '{serial_no}'")
|
|
||||||
|
|
||||||
def _set_serial_no(self, snr: int):
|
def _set_serial_no(self, snr: int):
|
||||||
'''check the serial number and configure the inverter connection'''
|
'''check the serial number and configure the inverter connection'''
|
||||||
@@ -417,14 +392,13 @@ class SolarmanV5(SolarmanBase):
|
|||||||
logger.debug(f'SerialNo: {serial_no}')
|
logger.debug(f'SerialNo: {serial_no}')
|
||||||
else:
|
else:
|
||||||
inverters = Config.get('inverters')
|
inverters = Config.get('inverters')
|
||||||
batteries = Config.get('batteries')
|
|
||||||
# logger.debug(f'Inverters: {inverters}')
|
# logger.debug(f'Inverters: {inverters}')
|
||||||
|
|
||||||
for key, inv in chain(inverters.items(), batteries.items()):
|
for key, inv in inverters.items():
|
||||||
# logger.debug(f'key: {key} -> {inv}')
|
# logger.debug(f'key: {key} -> {inv}')
|
||||||
if (type(inv) is dict and 'monitor_sn' in inv
|
if (type(inv) is dict and 'monitor_sn' in inv
|
||||||
and inv['monitor_sn'] == snr):
|
and inv['monitor_sn'] == snr):
|
||||||
self._set_config_parms(inv, key)
|
self.__set_config_parms(inv)
|
||||||
self.db.set_pv_module_details(inv)
|
self.db.set_pv_module_details(inv)
|
||||||
logger.debug(f'SerialNo {serial_no} allowed! area:{self.sug_area}') # noqa: E501
|
logger.debug(f'SerialNo {serial_no} allowed! area:{self.sug_area}') # noqa: E501
|
||||||
|
|
||||||
@@ -437,11 +411,9 @@ class SolarmanV5(SolarmanBase):
|
|||||||
if 'allow_all' not in inverters or not inverters['allow_all']:
|
if 'allow_all' not in inverters or not inverters['allow_all']:
|
||||||
self.inc_counter('Unknown_SNR')
|
self.inc_counter('Unknown_SNR')
|
||||||
self.unique_id = None
|
self.unique_id = None
|
||||||
logging.error(f"Ignore message from unknow inverter with Monitoring-SN: {serial_no})!\n" # noqa: E501
|
logger.warning(f'ignore message from unknow inverter! (SerialNo: {serial_no})') # noqa: E501
|
||||||
" !!Check the 'monitor_sn' setting in your configuration!!") # noqa: E501
|
|
||||||
return
|
return
|
||||||
logging.warning(f"Monitoring-SN: {serial_no} not configured but accepted!" # noqa: E501
|
logger.warning(f'SerialNo {serial_no} not known but accepted!')
|
||||||
" !!Check the 'monitor_sn' setting in your configuration!!") # noqa: E501
|
|
||||||
|
|
||||||
self.unique_id = serial_no
|
self.unique_id = serial_no
|
||||||
|
|
||||||
@@ -487,18 +459,12 @@ class SolarmanV5(SolarmanBase):
|
|||||||
|
|
||||||
def mb_timout_cb(self, exp_cnt):
|
def mb_timout_cb(self, exp_cnt):
|
||||||
self.mb_timer.start(self.mb_timeout)
|
self.mb_timer.start(self.mb_timeout)
|
||||||
if self.mb_scan:
|
|
||||||
self._send_modbus_scan()
|
|
||||||
else:
|
|
||||||
self._send_modbus_cmd(Modbus.INV_ADDR, Modbus.READ_REGS,
|
|
||||||
self.mb_regs[0]['addr'],
|
|
||||||
self.mb_regs[0]['len'], logging.INFO)
|
|
||||||
|
|
||||||
if 1 == (exp_cnt % 30) and len(self.mb_regs) > 1:
|
self._send_modbus_cmd(Modbus.READ_REGS, 0x3000, 48, logging.DEBUG)
|
||||||
# logging.info("Regular Modbus Status request")
|
|
||||||
self._send_modbus_cmd(Modbus.INV_ADDR, Modbus.READ_REGS,
|
if 1 == (exp_cnt % 30):
|
||||||
self.mb_regs[1]['addr'],
|
# logging.info("Regular Modbus Status request")
|
||||||
self.mb_regs[1]['len'], logging.INFO)
|
self._send_modbus_cmd(Modbus.READ_REGS, 0x2000, 96, logging.DEBUG)
|
||||||
|
|
||||||
def at_cmd_forbidden(self, cmd: str, connection: str) -> bool:
|
def at_cmd_forbidden(self, cmd: str, connection: str) -> bool:
|
||||||
return not cmd.startswith(tuple(self.at_acl[connection]['allow'])) or \
|
return not cmd.startswith(tuple(self.at_acl[connection]['allow'])) or \
|
||||||
@@ -516,7 +482,7 @@ class SolarmanV5(SolarmanBase):
|
|||||||
node_id = self.node_id
|
node_id = self.node_id
|
||||||
key = 'at_resp'
|
key = 'at_resp'
|
||||||
logger.info(f'{key}: {data_json}')
|
logger.info(f'{key}: {data_json}')
|
||||||
await Proxy.mqtt.publish(f'{Proxy.entity_prfx}{node_id}{key}', data_json) # noqa: E501
|
await self.mqtt.publish(f'{self.entity_prfx}{node_id}{key}', data_json) # noqa: E501
|
||||||
return
|
return
|
||||||
|
|
||||||
self.forward_at_cmd_resp = False
|
self.forward_at_cmd_resp = False
|
||||||
@@ -550,11 +516,11 @@ class SolarmanV5(SolarmanBase):
|
|||||||
logger.info(f'Model: {model}')
|
logger.info(f'Model: {model}')
|
||||||
self.db.set_db_def_value(Register.EQUIPMENT_MODEL, model)
|
self.db.set_db_def_value(Register.EQUIPMENT_MODEL, model)
|
||||||
|
|
||||||
def __process_data(self, ftype, ts, sensor=0):
|
def __process_data(self, ftype, ts):
|
||||||
inv_update = False
|
inv_update = False
|
||||||
msg_type = self.control >> 8
|
msg_type = self.control >> 8
|
||||||
for key, update in self.db.parse(self.ifc.rx_peek(), msg_type,
|
for key, update in self.db.parse(self.ifc.rx_peek(), msg_type, ftype,
|
||||||
ftype, sensor, self.node_id):
|
self.node_id):
|
||||||
if update:
|
if update:
|
||||||
if key == 'inverter':
|
if key == 'inverter':
|
||||||
inv_update = True
|
inv_update = True
|
||||||
@@ -615,7 +581,7 @@ class SolarmanV5(SolarmanBase):
|
|||||||
else:
|
else:
|
||||||
ts = None
|
ts = None
|
||||||
|
|
||||||
self.__process_data(ftype, ts, sensor)
|
self.__process_data(ftype, ts)
|
||||||
self.__forward_msg()
|
self.__forward_msg()
|
||||||
self.__send_ack_rsp(0x1210, ftype)
|
self.__send_ack_rsp(0x1210, ftype)
|
||||||
self.new_state_up()
|
self.new_state_up()
|
||||||
@@ -660,7 +626,7 @@ class SolarmanV5(SolarmanBase):
|
|||||||
|
|
||||||
def publish_mqtt(self, key, data): # pragma: no cover
|
def publish_mqtt(self, key, data): # pragma: no cover
|
||||||
asyncio.ensure_future(
|
asyncio.ensure_future(
|
||||||
Proxy.mqtt.publish(key, data))
|
self.mqtt.publish(key, data))
|
||||||
|
|
||||||
def get_cmd_rsp_log_lvl(self) -> int:
|
def get_cmd_rsp_log_lvl(self) -> int:
|
||||||
ftype = self.ifc.rx_peek()[self.header_len]
|
ftype = self.ifc.rx_peek()[self.header_len]
|
||||||
@@ -678,39 +644,29 @@ class SolarmanV5(SolarmanBase):
|
|||||||
data = self.ifc.rx_peek()[self.header_len:
|
data = self.ifc.rx_peek()[self.header_len:
|
||||||
self.header_len+self.data_len]
|
self.header_len+self.data_len]
|
||||||
ftype = data[0]
|
ftype = data[0]
|
||||||
if ftype == self.AT_CMD or \
|
if ftype == self.AT_CMD:
|
||||||
ftype == self.AT_CMD_RSP:
|
|
||||||
if not self.forward_at_cmd_resp:
|
if not self.forward_at_cmd_resp:
|
||||||
data_json = data[14:].decode("utf-8")
|
data_json = data[14:].decode("utf-8")
|
||||||
node_id = self.node_id
|
node_id = self.node_id
|
||||||
key = 'at_resp'
|
key = 'at_resp'
|
||||||
logger.info(f'{key}: {data_json}')
|
logger.info(f'{key}: {data_json}')
|
||||||
self.publish_mqtt(f'{Proxy.entity_prfx}{node_id}{key}', data_json) # noqa: E501
|
self.publish_mqtt(f'{self.entity_prfx}{node_id}{key}', data_json) # noqa: E501
|
||||||
return
|
return
|
||||||
elif ftype == self.MB_RTU_CMD:
|
elif ftype == self.MB_RTU_CMD:
|
||||||
self.__modbus_command_rsp(data)
|
self.__modbus_command_rsp(data)
|
||||||
return
|
return
|
||||||
self.__forward_msg()
|
self.__forward_msg()
|
||||||
|
|
||||||
def __parse_modbus_rsp(self, data, modbus_msg_len):
|
def __parse_modbus_rsp(self, data):
|
||||||
inv_update = False
|
inv_update = False
|
||||||
self.modbus_elms = 0
|
self.modbus_elms = 0
|
||||||
if (self.mb_scan):
|
|
||||||
self._dump_modbus_scan(data, 14, modbus_msg_len)
|
|
||||||
|
|
||||||
ts = self._timestamp()
|
|
||||||
for key, update, _ in self.mb.recv_resp(self.db, data[14:]):
|
for key, update, _ in self.mb.recv_resp(self.db, data[14:]):
|
||||||
self.modbus_elms += 1
|
self.modbus_elms += 1
|
||||||
if update:
|
if update:
|
||||||
if key == 'inverter':
|
if key == 'inverter':
|
||||||
inv_update = True
|
inv_update = True
|
||||||
self._set_mqtt_timestamp(key, ts)
|
self._set_mqtt_timestamp(key, self._timestamp())
|
||||||
self.new_data[key] = True
|
self.new_data[key] = True
|
||||||
for key, update in self.db.calc(self.sensor_list, self.node_id):
|
|
||||||
if update:
|
|
||||||
self._set_mqtt_timestamp(key, ts)
|
|
||||||
self.new_data[key] = True
|
|
||||||
|
|
||||||
return inv_update
|
return inv_update
|
||||||
|
|
||||||
def __modbus_command_rsp(self, data):
|
def __modbus_command_rsp(self, data):
|
||||||
@@ -720,7 +676,7 @@ class SolarmanV5(SolarmanBase):
|
|||||||
# logger.debug(f'modbus_len:{modbus_msg_len} accepted:{valid}')
|
# logger.debug(f'modbus_len:{modbus_msg_len} accepted:{valid}')
|
||||||
if valid == 1 and modbus_msg_len > 4:
|
if valid == 1 and modbus_msg_len > 4:
|
||||||
# logger.info(f'first byte modbus:{data[14]}')
|
# logger.info(f'first byte modbus:{data[14]}')
|
||||||
inv_update = self.__parse_modbus_rsp(data, modbus_msg_len)
|
inv_update = self.__parse_modbus_rsp(data)
|
||||||
if inv_update:
|
if inv_update:
|
||||||
self.__build_model_name()
|
self.__build_model_name()
|
||||||
|
|
||||||
|
|||||||
211
app/src/infos.py
211
app/src/infos.py
@@ -121,94 +121,6 @@ class Register(Enum):
|
|||||||
TS_INPUT = 600
|
TS_INPUT = 600
|
||||||
TS_GRID = 601
|
TS_GRID = 601
|
||||||
TS_TOTAL = 602
|
TS_TOTAL = 602
|
||||||
BATT_PV1_VOLT = 1000
|
|
||||||
BATT_PV1_CUR = 1001
|
|
||||||
BATT_PV2_VOLT = 1002
|
|
||||||
BATT_PV2_CUR = 1003
|
|
||||||
BATT_38 = 1004
|
|
||||||
BATT_TOTAL_GEN = 1005
|
|
||||||
BATT_STATUS_1 = 1006
|
|
||||||
BATT_STATUS_2 = 1007
|
|
||||||
BATT_VOLT = 1010
|
|
||||||
BATT_CUR = 1011
|
|
||||||
BATT_SOC = 1012
|
|
||||||
BATT_CELL1_VOLT = 1013
|
|
||||||
BATT_CELL2_VOLT = 1014
|
|
||||||
BATT_CELL3_VOLT = 1015
|
|
||||||
BATT_CELL4_VOLT = 1016
|
|
||||||
BATT_CELL5_VOLT = 1017
|
|
||||||
BATT_CELL6_VOLT = 1018
|
|
||||||
BATT_CELL7_VOLT = 1019
|
|
||||||
BATT_CELL8_VOLT = 1020
|
|
||||||
BATT_CELL9_VOLT = 1021
|
|
||||||
BATT_CELL10_VOLT = 1022
|
|
||||||
BATT_CELL11_VOLT = 1023
|
|
||||||
BATT_CELL12_VOLT = 1024
|
|
||||||
BATT_CELL13_VOLT = 1025
|
|
||||||
BATT_CELL14_VOLT = 1026
|
|
||||||
BATT_CELL15_VOLT = 1027
|
|
||||||
BATT_CELL16_VOLT = 1028
|
|
||||||
BATT_TEMP_1 = 1029
|
|
||||||
BATT_TEMP_2 = 1030
|
|
||||||
BATT_TEMP_3 = 1031
|
|
||||||
BATT_OUT_VOLT = 1032
|
|
||||||
BATT_OUT_CUR = 1033
|
|
||||||
BATT_OUT_STATUS = 1034
|
|
||||||
BATT_TEMP_4 = 1035
|
|
||||||
BATT_74 = 1036
|
|
||||||
BATT_76 = 1037
|
|
||||||
BATT_78 = 1038
|
|
||||||
BATT_PV_PWR = 1040
|
|
||||||
BATT_PWR = 1041
|
|
||||||
BATT_OUT_PWR = 1042
|
|
||||||
|
|
||||||
TEST_VAL_0 = 2000
|
|
||||||
TEST_VAL_1 = 2001
|
|
||||||
TEST_VAL_2 = 2002
|
|
||||||
TEST_VAL_3 = 2003
|
|
||||||
TEST_VAL_4 = 2004
|
|
||||||
TEST_VAL_5 = 2005
|
|
||||||
TEST_VAL_6 = 2006
|
|
||||||
TEST_VAL_7 = 2007
|
|
||||||
TEST_VAL_8 = 2008
|
|
||||||
TEST_VAL_9 = 2009
|
|
||||||
TEST_VAL_10 = 2010
|
|
||||||
TEST_VAL_11 = 2011
|
|
||||||
TEST_VAL_12 = 2012
|
|
||||||
TEST_VAL_13 = 2013
|
|
||||||
TEST_VAL_14 = 2014
|
|
||||||
TEST_VAL_15 = 2015
|
|
||||||
TEST_VAL_16 = 2016
|
|
||||||
TEST_VAL_17 = 2017
|
|
||||||
TEST_VAL_18 = 2018
|
|
||||||
TEST_VAL_19 = 2019
|
|
||||||
TEST_VAL_20 = 2020
|
|
||||||
TEST_VAL_21 = 2021
|
|
||||||
TEST_VAL_22 = 2022
|
|
||||||
TEST_VAL_23 = 2023
|
|
||||||
TEST_VAL_24 = 2024
|
|
||||||
TEST_VAL_25 = 2025
|
|
||||||
TEST_VAL_26 = 2026
|
|
||||||
TEST_VAL_27 = 2027
|
|
||||||
TEST_VAL_28 = 2028
|
|
||||||
TEST_VAL_29 = 2029
|
|
||||||
TEST_VAL_30 = 2030
|
|
||||||
TEST_VAL_31 = 2031
|
|
||||||
TEST_VAL_32 = 2032
|
|
||||||
|
|
||||||
TEST_IVAL_1 = 2041
|
|
||||||
TEST_IVAL_2 = 2042
|
|
||||||
TEST_IVAL_3 = 2043
|
|
||||||
TEST_IVAL_4 = 2044
|
|
||||||
TEST_IVAL_5 = 2045
|
|
||||||
TEST_IVAL_6 = 2046
|
|
||||||
TEST_IVAL_7 = 2047
|
|
||||||
TEST_IVAL_8 = 2048
|
|
||||||
TEST_IVAL_9 = 2049
|
|
||||||
TEST_IVAL_10 = 2050
|
|
||||||
TEST_IVAL_11 = 2051
|
|
||||||
TEST_IVAL_12 = 2052
|
|
||||||
|
|
||||||
VALUE_1 = 9000
|
VALUE_1 = 9000
|
||||||
TEST_REG1 = 10000
|
TEST_REG1 = 10000
|
||||||
TEST_REG2 = 10001
|
TEST_REG2 = 10001
|
||||||
@@ -219,10 +131,7 @@ class Fmt:
|
|||||||
def get_value(buf: bytes, idx: int, row: dict):
|
def get_value(buf: bytes, idx: int, row: dict):
|
||||||
'''Get a value from buf and interpret as in row defined'''
|
'''Get a value from buf and interpret as in row defined'''
|
||||||
fmt = row['fmt']
|
fmt = row['fmt']
|
||||||
try:
|
res = struct.unpack_from(fmt, buf, idx)
|
||||||
res = struct.unpack_from(fmt, buf, idx)
|
|
||||||
except Exception:
|
|
||||||
return None
|
|
||||||
result = res[0]
|
result = res[0]
|
||||||
if isinstance(result, (bytearray, bytes)):
|
if isinstance(result, (bytearray, bytes)):
|
||||||
result = result.decode().split('\x00')[0]
|
result = result.decode().split('\x00')[0]
|
||||||
@@ -321,7 +230,6 @@ class Infos:
|
|||||||
LIGHTNING = 'mdi:lightning-bolt'
|
LIGHTNING = 'mdi:lightning-bolt'
|
||||||
COUNTER = 'mdi:counter'
|
COUNTER = 'mdi:counter'
|
||||||
GAUGE = 'mdi:gauge'
|
GAUGE = 'mdi:gauge'
|
||||||
POWER = 'mdi:power'
|
|
||||||
SOLAR_POWER_VAR = 'mdi:solar-power-variant'
|
SOLAR_POWER_VAR = 'mdi:solar-power-variant'
|
||||||
SOLAR_POWER = 'mdi:solar-power'
|
SOLAR_POWER = 'mdi:solar-power'
|
||||||
WIFI = 'mdi:wifi'
|
WIFI = 'mdi:wifi'
|
||||||
@@ -358,7 +266,6 @@ class Infos:
|
|||||||
__info_devs = {
|
__info_devs = {
|
||||||
'proxy': {'singleton': True, 'name': 'Proxy', 'mf': 'Stefan Allius'}, # noqa: E501
|
'proxy': {'singleton': True, 'name': 'Proxy', 'mf': 'Stefan Allius'}, # noqa: E501
|
||||||
'controller': {'via': 'proxy', 'name': 'Controller', 'mdl': Register.CHIP_MODEL, 'mf': Register.CHIP_TYPE, 'sw': Register.COLLECTOR_FW_VERSION, 'mac': Register.MAC_ADDR, 'sn': Register.COLLECTOR_SNR}, # noqa: E501
|
'controller': {'via': 'proxy', 'name': 'Controller', 'mdl': Register.CHIP_MODEL, 'mf': Register.CHIP_TYPE, 'sw': Register.COLLECTOR_FW_VERSION, 'mac': Register.MAC_ADDR, 'sn': Register.COLLECTOR_SNR}, # noqa: E501
|
||||||
|
|
||||||
'inverter': {'via': 'controller', 'name': 'Micro Inverter', 'mdl': Register.EQUIPMENT_MODEL, 'mf': Register.MANUFACTURER, 'sw': Register.VERSION, 'sn': Register.SERIAL_NUMBER}, # noqa: E501
|
'inverter': {'via': 'controller', 'name': 'Micro Inverter', 'mdl': Register.EQUIPMENT_MODEL, 'mf': Register.MANUFACTURER, 'sw': Register.VERSION, 'sn': Register.SERIAL_NUMBER}, # noqa: E501
|
||||||
'input_pv1': {'via': 'inverter', 'name': 'Module PV1', 'mdl': Register.PV1_MODEL, 'mf': Register.PV1_MANUFACTURER}, # noqa: E501
|
'input_pv1': {'via': 'inverter', 'name': 'Module PV1', 'mdl': Register.PV1_MODEL, 'mf': Register.PV1_MANUFACTURER}, # noqa: E501
|
||||||
'input_pv2': {'via': 'inverter', 'name': 'Module PV2', 'mdl': Register.PV2_MODEL, 'mf': Register.PV2_MANUFACTURER, 'dep': {'reg': Register.NO_INPUTS, 'gte': 2}}, # noqa: E501
|
'input_pv2': {'via': 'inverter', 'name': 'Module PV2', 'mdl': Register.PV2_MODEL, 'mf': Register.PV2_MANUFACTURER, 'dep': {'reg': Register.NO_INPUTS, 'gte': 2}}, # noqa: E501
|
||||||
@@ -366,18 +273,11 @@ class Infos:
|
|||||||
'input_pv4': {'via': 'inverter', 'name': 'Module PV4', 'mdl': Register.PV4_MODEL, 'mf': Register.PV4_MANUFACTURER, 'dep': {'reg': Register.NO_INPUTS, 'gte': 4}}, # noqa: E501
|
'input_pv4': {'via': 'inverter', 'name': 'Module PV4', 'mdl': Register.PV4_MODEL, 'mf': Register.PV4_MANUFACTURER, 'dep': {'reg': Register.NO_INPUTS, 'gte': 4}}, # noqa: E501
|
||||||
'input_pv5': {'via': 'inverter', 'name': 'Module PV5', 'mdl': Register.PV5_MODEL, 'mf': Register.PV5_MANUFACTURER, 'dep': {'reg': Register.NO_INPUTS, 'gte': 5}}, # noqa: E501
|
'input_pv5': {'via': 'inverter', 'name': 'Module PV5', 'mdl': Register.PV5_MODEL, 'mf': Register.PV5_MANUFACTURER, 'dep': {'reg': Register.NO_INPUTS, 'gte': 5}}, # noqa: E501
|
||||||
'input_pv6': {'via': 'inverter', 'name': 'Module PV6', 'mdl': Register.PV6_MODEL, 'mf': Register.PV6_MANUFACTURER, 'dep': {'reg': Register.NO_INPUTS, 'gte': 6}}, # noqa: E501
|
'input_pv6': {'via': 'inverter', 'name': 'Module PV6', 'mdl': Register.PV6_MODEL, 'mf': Register.PV6_MANUFACTURER, 'dep': {'reg': Register.NO_INPUTS, 'gte': 6}}, # noqa: E501
|
||||||
|
|
||||||
'batterie': {'via': 'controller', 'name': 'Batterie', 'mdl': Register.EQUIPMENT_MODEL, 'mf': Register.MANUFACTURER, 'sw': Register.VERSION, 'sn': Register.SERIAL_NUMBER}, # noqa: E501
|
|
||||||
'bat_inp_pv1': {'via': 'batterie', 'name': 'Module PV1', 'mdl': Register.PV1_MODEL, 'mf': Register.PV1_MANUFACTURER}, # noqa: E501
|
|
||||||
'bat_inp_pv2': {'via': 'batterie', 'name': 'Module PV2', 'mdl': Register.PV2_MODEL, 'mf': Register.PV2_MANUFACTURER}, # noqa: E501
|
|
||||||
}
|
}
|
||||||
|
|
||||||
__comm_type_val_tpl = "{%set com_types = ['n/a','Wi-Fi', 'G4', 'G5', 'GPRS'] %}{{com_types[value_json['Communication_Type']|int(0)]|default(value_json['Communication_Type'])}}" # noqa: E501
|
__comm_type_val_tpl = "{%set com_types = ['n/a','Wi-Fi', 'G4', 'G5', 'GPRS'] %}{{com_types[value_json['Communication_Type']|int(0)]|default(value_json['Communication_Type'])}}" # noqa: E501
|
||||||
__work_mode_val_tpl = "{%set mode = ['Normal-Mode', 'Aging-Mode', 'ATE-Mode', 'Shielding GFDI', 'DTU-Mode'] %}{{mode[value_json['Work_Mode']|int(0)]|default(value_json['Work_Mode'])}}" # noqa: E501
|
__work_mode_val_tpl = "{%set mode = ['Normal-Mode', 'Aging-Mode', 'ATE-Mode', 'Shielding GFDI', 'DTU-Mode'] %}{{mode[value_json['Work_Mode']|int(0)]|default(value_json['Work_Mode'])}}" # noqa: E501
|
||||||
__status_type_val_tpl = "{%set inv_status = ['Off-line', 'On-grid', 'Off-grid'] %}{{inv_status[value_json['Inverter_Status']|int(0)]|default(value_json['Inverter_Status'])}}" # noqa: E501
|
__status_type_val_tpl = "{%set inv_status = ['Off-line', 'On-grid', 'Off-grid'] %}{{inv_status[value_json['Inverter_Status']|int(0)]|default(value_json['Inverter_Status'])}}" # noqa: E501
|
||||||
__mppt1_status_type_val_tpl = "{%set mppt_status = ['Locked', 'On', 'Off'] %}{{mppt_status[value_json['Status_1']|int(0)]|default(value_json['Status_1'])}}" # noqa: E501
|
|
||||||
__mppt2_status_type_val_tpl = "{%set mppt_status = ['Locked', 'On', 'Off'] %}{{mppt_status[value_json['Status_2']|int(0)]|default(value_json['Status_2'])}}" # noqa: E501
|
|
||||||
__out_status_type_val_tpl = "{%set out_status = ['Off', 'On'] %}{{out_status[value_json['out']['Out_Status']|int(0)]|default(value_json['out']['Out_Status'])}}" # noqa: E501
|
|
||||||
__rated_power_val_tpl = "{% if 'Rated_Power' in value_json and value_json['Rated_Power'] != None %}{{value_json['Rated_Power']|string() +' W'}}{% else %}{{ this.state }}{% endif %}" # noqa: E501
|
__rated_power_val_tpl = "{% if 'Rated_Power' in value_json and value_json['Rated_Power'] != None %}{{value_json['Rated_Power']|string() +' W'}}{% else %}{{ this.state }}{% endif %}" # noqa: E501
|
||||||
__designed_power_val_tpl = '''
|
__designed_power_val_tpl = '''
|
||||||
{% if 'Max_Designed_Power' in value_json and
|
{% if 'Max_Designed_Power' in value_json and
|
||||||
@@ -528,7 +428,7 @@ class Infos:
|
|||||||
Register.NO_INPUTS: {'name': ['inverter', 'No_Inputs'], 'level': logging.DEBUG, 'unit': ''}, # noqa: E501
|
Register.NO_INPUTS: {'name': ['inverter', 'No_Inputs'], 'level': logging.DEBUG, 'unit': ''}, # noqa: E501
|
||||||
Register.MAX_DESIGNED_POWER: {'name': ['inverter', 'Max_Designed_Power'], 'level': logging.INFO, 'unit': 'W', 'ha': {'dev': 'inverter', 'dev_cla': None, 'stat_cla': None, 'id': 'designed_power_', 'val_tpl': __designed_power_val_tpl, 'name': 'Max Designed Power', 'icon': LIGHTNING, 'ent_cat': 'diagnostic'}}, # noqa: E501
|
Register.MAX_DESIGNED_POWER: {'name': ['inverter', 'Max_Designed_Power'], 'level': logging.INFO, 'unit': 'W', 'ha': {'dev': 'inverter', 'dev_cla': None, 'stat_cla': None, 'id': 'designed_power_', 'val_tpl': __designed_power_val_tpl, 'name': 'Max Designed Power', 'icon': LIGHTNING, 'ent_cat': 'diagnostic'}}, # noqa: E501
|
||||||
Register.RATED_POWER: {'name': ['inverter', 'Rated_Power'], 'level': logging.DEBUG, 'unit': 'W', 'ha': {'dev': 'inverter', 'dev_cla': None, 'stat_cla': None, 'id': 'rated_power_', 'val_tpl': __rated_power_val_tpl, 'name': 'Rated Power', 'icon': LIGHTNING, 'ent_cat': 'diagnostic'}}, # noqa: E501
|
Register.RATED_POWER: {'name': ['inverter', 'Rated_Power'], 'level': logging.DEBUG, 'unit': 'W', 'ha': {'dev': 'inverter', 'dev_cla': None, 'stat_cla': None, 'id': 'rated_power_', 'val_tpl': __rated_power_val_tpl, 'name': 'Rated Power', 'icon': LIGHTNING, 'ent_cat': 'diagnostic'}}, # noqa: E501
|
||||||
Register.WORK_MODE: {'name': ['inverter', 'Work_Mode'], 'level': logging.DEBUG, 'unit': '', 'ha': {'dev': 'inverter', 'comp': 'sensor', 'dev_cla': None, 'stat_cla': None, 'id': 'work_mode_', 'name': 'Work Mode', 'val_tpl': __work_mode_val_tpl, 'icon': POWER, 'ent_cat': 'diagnostic'}}, # noqa: E501
|
Register.WORK_MODE: {'name': ['inverter', 'Work_Mode'], 'level': logging.DEBUG, 'unit': '', 'ha': {'dev': 'inverter', 'comp': 'sensor', 'dev_cla': None, 'stat_cla': None, 'id': 'work_mode_', 'name': 'Work Mode', 'val_tpl': __work_mode_val_tpl, 'icon': 'mdi:power', 'ent_cat': 'diagnostic'}}, # noqa: E501
|
||||||
Register.INPUT_COEFFICIENT: {'name': ['inverter', 'Input_Coefficient'], 'level': logging.DEBUG, 'unit': '%', 'ha': {'dev': 'inverter', 'dev_cla': None, 'stat_cla': None, 'id': 'input_coef_', 'val_tpl': __input_coef_val_tpl, 'name': 'Input Coefficient', 'icon': LIGHTNING, 'ent_cat': 'diagnostic'}}, # noqa: E501
|
Register.INPUT_COEFFICIENT: {'name': ['inverter', 'Input_Coefficient'], 'level': logging.DEBUG, 'unit': '%', 'ha': {'dev': 'inverter', 'dev_cla': None, 'stat_cla': None, 'id': 'input_coef_', 'val_tpl': __input_coef_val_tpl, 'name': 'Input Coefficient', 'icon': LIGHTNING, 'ent_cat': 'diagnostic'}}, # noqa: E501
|
||||||
Register.OUTPUT_COEFFICIENT: {'name': ['inverter', 'Output_Coefficient'], 'level': logging.INFO, 'unit': '%', 'ha': {'dev': 'inverter', 'dev_cla': None, 'stat_cla': None, 'id': 'output_coef_', 'val_tpl': __output_coef_val_tpl, 'name': 'Output Coefficient', 'icon': LIGHTNING, 'ent_cat': 'diagnostic'}}, # noqa: E501
|
Register.OUTPUT_COEFFICIENT: {'name': ['inverter', 'Output_Coefficient'], 'level': logging.INFO, 'unit': '%', 'ha': {'dev': 'inverter', 'dev_cla': None, 'stat_cla': None, 'id': 'output_coef_', 'val_tpl': __output_coef_val_tpl, 'name': 'Output Coefficient', 'icon': LIGHTNING, 'ent_cat': 'diagnostic'}}, # noqa: E501
|
||||||
Register.PV1_MANUFACTURER: {'name': ['inverter', 'PV1_Manufacturer'], 'level': logging.DEBUG, 'unit': ''}, # noqa: E501
|
Register.PV1_MANUFACTURER: {'name': ['inverter', 'PV1_Manufacturer'], 'level': logging.DEBUG, 'unit': ''}, # noqa: E501
|
||||||
@@ -576,7 +476,7 @@ class Infos:
|
|||||||
Register.GRID_FREQUENCY: {'name': ['grid', 'Frequency'], 'level': logging.DEBUG, 'unit': 'Hz', 'ha': {'dev': 'inverter', 'dev_cla': 'frequency', 'stat_cla': 'measurement', 'id': 'out_freq_', 'fmt': FMT_FLOAT, 'name': 'Grid Frequency', 'ent_cat': 'diagnostic'}}, # noqa: E501
|
Register.GRID_FREQUENCY: {'name': ['grid', 'Frequency'], 'level': logging.DEBUG, 'unit': 'Hz', 'ha': {'dev': 'inverter', 'dev_cla': 'frequency', 'stat_cla': 'measurement', 'id': 'out_freq_', 'fmt': FMT_FLOAT, 'name': 'Grid Frequency', 'ent_cat': 'diagnostic'}}, # noqa: E501
|
||||||
Register.OUTPUT_POWER: {'name': ['grid', 'Output_Power'], 'level': logging.INFO, 'unit': 'W', 'ha': {'dev': 'inverter', 'dev_cla': 'power', 'stat_cla': 'measurement', 'id': 'out_power_', 'fmt': FMT_FLOAT, 'name': 'Power'}}, # noqa: E501
|
Register.OUTPUT_POWER: {'name': ['grid', 'Output_Power'], 'level': logging.INFO, 'unit': 'W', 'ha': {'dev': 'inverter', 'dev_cla': 'power', 'stat_cla': 'measurement', 'id': 'out_power_', 'fmt': FMT_FLOAT, 'name': 'Power'}}, # noqa: E501
|
||||||
Register.INVERTER_TEMP: {'name': ['env', 'Inverter_Temp'], 'level': logging.DEBUG, 'unit': '°C', 'ha': {'dev': 'inverter', 'dev_cla': 'temperature', 'stat_cla': 'measurement', 'id': 'temp_', 'fmt': FMT_INT, 'name': 'Temperature'}}, # noqa: E501
|
Register.INVERTER_TEMP: {'name': ['env', 'Inverter_Temp'], 'level': logging.DEBUG, 'unit': '°C', 'ha': {'dev': 'inverter', 'dev_cla': 'temperature', 'stat_cla': 'measurement', 'id': 'temp_', 'fmt': FMT_INT, 'name': 'Temperature'}}, # noqa: E501
|
||||||
Register.INVERTER_STATUS: {'name': ['env', 'Inverter_Status'], 'level': logging.INFO, 'unit': '', 'ha': {'dev': 'inverter', 'comp': 'sensor', 'dev_cla': None, 'stat_cla': None, 'id': 'inv_status_', 'name': 'Inverter Status', 'val_tpl': __status_type_val_tpl, 'icon': POWER}}, # noqa: E501
|
Register.INVERTER_STATUS: {'name': ['env', 'Inverter_Status'], 'level': logging.INFO, 'unit': '', 'ha': {'dev': 'inverter', 'comp': 'sensor', 'dev_cla': None, 'stat_cla': None, 'id': 'inv_status_', 'name': 'Inverter Status', 'val_tpl': __status_type_val_tpl, 'icon': 'mdi:power'}}, # noqa: E501
|
||||||
Register.DETECT_STATUS_1: {'name': ['env', 'Detect_Status_1'], 'level': logging.DEBUG, 'unit': ''}, # noqa: E501
|
Register.DETECT_STATUS_1: {'name': ['env', 'Detect_Status_1'], 'level': logging.DEBUG, 'unit': ''}, # noqa: E501
|
||||||
Register.DETECT_STATUS_2: {'name': ['env', 'Detect_Status_2'], 'level': logging.DEBUG, 'unit': ''}, # noqa: E501
|
Register.DETECT_STATUS_2: {'name': ['env', 'Detect_Status_2'], 'level': logging.DEBUG, 'unit': ''}, # noqa: E501
|
||||||
|
|
||||||
@@ -618,15 +518,15 @@ class Infos:
|
|||||||
Register.TOTAL_GENERATION: {'name': ['total', 'Total_Generation'], 'level': logging.INFO, 'unit': 'kWh', 'ha': {'dev': 'inverter', 'dev_cla': 'energy', 'stat_cla': 'total', 'id': 'total_gen_', 'fmt': FMT_FLOAT, 'name': TOTAL_GEN, 'icon': SOLAR_POWER, 'must_incr': True}}, # noqa: E501
|
Register.TOTAL_GENERATION: {'name': ['total', 'Total_Generation'], 'level': logging.INFO, 'unit': 'kWh', 'ha': {'dev': 'inverter', 'dev_cla': 'energy', 'stat_cla': 'total', 'id': 'total_gen_', 'fmt': FMT_FLOAT, 'name': TOTAL_GEN, 'icon': SOLAR_POWER, 'must_incr': True}}, # noqa: E501
|
||||||
|
|
||||||
# controller:
|
# controller:
|
||||||
Register.SIGNAL_STRENGTH: {'name': ['controller', 'Signal_Strength'], 'level': logging.INFO, 'unit': '%', 'ha': {'dev': 'controller', 'dev_cla': None, 'stat_cla': 'measurement', 'id': 'signal_', 'fmt': FMT_INT, 'name': 'Signal Strength', 'icon': WIFI}}, # noqa: E501
|
Register.SIGNAL_STRENGTH: {'name': ['controller', 'Signal_Strength'], 'level': logging.DEBUG, 'unit': '%', 'ha': {'dev': 'controller', 'dev_cla': None, 'stat_cla': 'measurement', 'id': 'signal_', 'fmt': FMT_INT, 'name': 'Signal Strength', 'icon': WIFI}}, # noqa: E501
|
||||||
Register.POWER_ON_TIME: {'name': ['controller', 'Power_On_Time'], 'level': logging.INFO, 'unit': 's', 'ha': {'dev': 'controller', 'dev_cla': 'duration', 'stat_cla': 'measurement', 'id': 'power_on_time_', 'fmt': FMT_INT, 'name': 'Power on Time', 'ent_cat': 'diagnostic'}}, # noqa: E501
|
Register.POWER_ON_TIME: {'name': ['controller', 'Power_On_Time'], 'level': logging.DEBUG, 'unit': 's', 'ha': {'dev': 'controller', 'dev_cla': 'duration', 'stat_cla': 'measurement', 'id': 'power_on_time_', 'fmt': FMT_INT, 'name': 'Power on Time', 'ent_cat': 'diagnostic'}}, # noqa: E501
|
||||||
Register.COLLECT_INTERVAL: {'name': ['controller', 'Collect_Interval'], 'level': logging.INFO, 'unit': 'min', 'ha': {'dev': 'controller', 'dev_cla': None, 'stat_cla': None, 'id': 'data_collect_intval_', 'fmt': '| string + " min"', 'name': 'Data Collect Interval', 'icon': UPDATE, 'ent_cat': 'diagnostic'}}, # noqa: E501
|
Register.COLLECT_INTERVAL: {'name': ['controller', 'Collect_Interval'], 'level': logging.DEBUG, 'unit': 'min', 'ha': {'dev': 'controller', 'dev_cla': None, 'stat_cla': None, 'id': 'data_collect_intval_', 'fmt': '| string + " min"', 'name': 'Data Collect Interval', 'icon': UPDATE, 'ent_cat': 'diagnostic'}}, # noqa: E501
|
||||||
Register.CONNECT_COUNT: {'name': ['controller', 'Connect_Count'], 'level': logging.INFO, 'unit': '', 'ha': {'dev': 'controller', 'dev_cla': None, 'stat_cla': None, 'id': 'connect_count_', 'fmt': FMT_INT, 'name': 'Connect Count', 'icon': COUNTER, 'comp': 'sensor', 'ent_cat': 'diagnostic'}}, # noqa: E501
|
Register.CONNECT_COUNT: {'name': ['controller', 'Connect_Count'], 'level': logging.DEBUG, 'unit': '', 'ha': {'dev': 'controller', 'dev_cla': None, 'stat_cla': None, 'id': 'connect_count_', 'fmt': FMT_INT, 'name': 'Connect Count', 'icon': COUNTER, 'comp': 'sensor', 'ent_cat': 'diagnostic'}}, # noqa: E501
|
||||||
Register.COMMUNICATION_TYPE: {'name': ['controller', 'Communication_Type'], 'level': logging.INFO, 'unit': '', 'ha': {'dev': 'controller', 'dev_cla': None, 'stat_cla': None, 'id': 'comm_type_', 'name': 'Communication Type', 'val_tpl': __comm_type_val_tpl, 'comp': 'sensor', 'icon': WIFI}}, # noqa: E501
|
Register.COMMUNICATION_TYPE: {'name': ['controller', 'Communication_Type'], 'level': logging.DEBUG, 'unit': '', 'ha': {'dev': 'controller', 'dev_cla': None, 'stat_cla': None, 'id': 'comm_type_', 'name': 'Communication Type', 'val_tpl': __comm_type_val_tpl, 'comp': 'sensor', 'icon': WIFI}}, # noqa: E501
|
||||||
Register.DATA_UP_INTERVAL: {'name': ['controller', 'Data_Up_Interval'], 'level': logging.INFO, 'unit': 's', 'ha': {'dev': 'controller', 'dev_cla': None, 'stat_cla': None, 'id': 'data_up_intval_', 'fmt': FMT_STRING_SEC, 'name': 'Data Up Interval', 'icon': UPDATE, 'ent_cat': 'diagnostic'}}, # noqa: E501
|
Register.DATA_UP_INTERVAL: {'name': ['controller', 'Data_Up_Interval'], 'level': logging.DEBUG, 'unit': 's', 'ha': {'dev': 'controller', 'dev_cla': None, 'stat_cla': None, 'id': 'data_up_intval_', 'fmt': FMT_STRING_SEC, 'name': 'Data Up Interval', 'icon': UPDATE, 'ent_cat': 'diagnostic'}}, # noqa: E501
|
||||||
Register.HEARTBEAT_INTERVAL: {'name': ['controller', 'Heartbeat_Interval'], 'level': logging.INFO, 'unit': 's', 'ha': {'dev': 'controller', 'dev_cla': None, 'stat_cla': None, 'id': 'heartbeat_intval_', 'fmt': FMT_STRING_SEC, 'name': 'Heartbeat Interval', 'icon': UPDATE, 'ent_cat': 'diagnostic'}}, # noqa: E501
|
Register.HEARTBEAT_INTERVAL: {'name': ['controller', 'Heartbeat_Interval'], 'level': logging.DEBUG, 'unit': 's', 'ha': {'dev': 'controller', 'dev_cla': None, 'stat_cla': None, 'id': 'heartbeat_intval_', 'fmt': FMT_STRING_SEC, 'name': 'Heartbeat Interval', 'icon': UPDATE, 'ent_cat': 'diagnostic'}}, # noqa: E501
|
||||||
Register.IP_ADDRESS: {'name': ['controller', 'IP_Address'], 'level': logging.INFO, 'unit': '', 'ha': {'dev': 'controller', 'dev_cla': None, 'stat_cla': None, 'id': 'ip_address_', 'fmt': '| string', 'name': 'IP Address', 'icon': WIFI, 'ent_cat': 'diagnostic'}}, # noqa: E501
|
Register.IP_ADDRESS: {'name': ['controller', 'IP_Address'], 'level': logging.DEBUG, 'unit': '', 'ha': {'dev': 'controller', 'dev_cla': None, 'stat_cla': None, 'id': 'ip_address_', 'fmt': '| string', 'name': 'IP Address', 'icon': WIFI, 'ent_cat': 'diagnostic'}}, # noqa: E501
|
||||||
Register.POLLING_INTERVAL: {'name': ['controller', 'Polling_Interval'], 'level': logging.INFO, 'unit': 's', 'ha': {'dev': 'controller', 'dev_cla': None, 'stat_cla': None, 'id': 'polling_intval_', 'fmt': FMT_STRING_SEC, 'name': 'Polling Interval', 'icon': UPDATE, 'ent_cat': 'diagnostic'}}, # noqa: E501
|
Register.POLLING_INTERVAL: {'name': ['controller', 'Polling_Interval'], 'level': logging.DEBUG, 'unit': 's', 'ha': {'dev': 'controller', 'dev_cla': None, 'stat_cla': None, 'id': 'polling_intval_', 'fmt': FMT_STRING_SEC, 'name': 'Polling Interval', 'icon': UPDATE, 'ent_cat': 'diagnostic'}}, # noqa: E501
|
||||||
Register.SENSOR_LIST: {'name': ['controller', 'Sensor_List'], 'level': logging.INFO, 'unit': ''}, # noqa: E501
|
Register.SENSOR_LIST: {'name': ['controller', 'Sensor_List'], 'level': logging.INFO, 'unit': ''}, # noqa: E501
|
||||||
Register.SSID: {'name': ['controller', 'WiFi_SSID'], 'level': logging.DEBUG, 'unit': ''}, # noqa: E501
|
Register.SSID: {'name': ['controller', 'WiFi_SSID'], 'level': logging.DEBUG, 'unit': ''}, # noqa: E501
|
||||||
|
|
||||||
@@ -636,93 +536,6 @@ class Infos:
|
|||||||
Register.PROD_COMPL_TYPE: {'name': ['other', 'Prod_Compliance_Type'], 'level': logging.INFO, 'unit': ''}, # noqa: E501
|
Register.PROD_COMPL_TYPE: {'name': ['other', 'Prod_Compliance_Type'], 'level': logging.INFO, 'unit': ''}, # noqa: E501
|
||||||
Register.INV_UNKNOWN_1: {'name': ['inv_unknown', 'Unknown_1'], 'level': logging.DEBUG, 'unit': ''}, # noqa: E501
|
Register.INV_UNKNOWN_1: {'name': ['inv_unknown', 'Unknown_1'], 'level': logging.DEBUG, 'unit': ''}, # noqa: E501
|
||||||
|
|
||||||
Register.BATT_PV1_VOLT: {'name': ['batterie', 'pv1', 'Voltage'], 'level': logging.INFO, 'unit': 'V', 'ha': {'dev': 'bat_inp_pv1', 'dev_cla': 'voltage', 'stat_cla': 'measurement', 'id': 'volt_pv1_', 'val_tpl': "{{ (value_json['pv1']['Voltage'] | float)}}", 'icon': GAUGE, 'ent_cat': 'diagnostic'}}, # noqa: E501
|
|
||||||
Register.BATT_PV1_CUR: {'name': ['batterie', 'pv1', 'Current'], 'level': logging.INFO, 'unit': 'A', 'ha': {'dev': 'bat_inp_pv1', 'dev_cla': 'current', 'stat_cla': 'measurement', 'id': 'cur_pv1_', 'val_tpl': "{{ (value_json['pv1']['Current'] | float)}}", 'icon': GAUGE, 'ent_cat': 'diagnostic'}}, # noqa: E501
|
|
||||||
Register.BATT_PV2_VOLT: {'name': ['batterie', 'pv2', 'Voltage'], 'level': logging.INFO, 'unit': 'V', 'ha': {'dev': 'bat_inp_pv2', 'dev_cla': 'voltage', 'stat_cla': 'measurement', 'id': 'volt_pv2_', 'val_tpl': "{{ (value_json['pv2']['Voltage'] | float)}}", 'icon': GAUGE, 'ent_cat': 'diagnostic'}}, # noqa: E501
|
|
||||||
Register.BATT_PV2_CUR: {'name': ['batterie', 'pv2', 'Current'], 'level': logging.INFO, 'unit': 'A', 'ha': {'dev': 'bat_inp_pv2', 'dev_cla': 'current', 'stat_cla': 'measurement', 'id': 'cur_pv2_', 'val_tpl': "{{ (value_json['pv2']['Current'] | float)}}", 'icon': GAUGE, 'ent_cat': 'diagnostic'}}, # noqa: E501
|
|
||||||
Register.BATT_38: {'name': ['batterie', 'Reg_38'], 'level': logging.INFO, 'unit': '', 'ha': {'dev': 'batterie', 'dev_cla': 'power', 'stat_cla': 'measurement', 'id': 'batt_38_', 'fmt': FMT_FLOAT, 'ent_cat': 'diagnostic'}}, # noqa: E501
|
|
||||||
Register.BATT_TOTAL_GEN: {'name': ['batterie', 'Total_Generation'], 'level': logging.INFO, 'unit': 'kWh', 'ha': {'dev': 'batterie', 'dev_cla': 'energy', 'stat_cla': 'total', 'id': 'total_gen_', 'fmt': FMT_FLOAT, 'name': TOTAL_GEN, 'icon': SOLAR_POWER, 'must_incr': True}}, # noqa: E501
|
|
||||||
Register.BATT_STATUS_1: {'name': ['batterie', 'Status_1'], 'level': logging.INFO, 'unit': '', 'ha': {'dev': 'batterie', 'comp': 'sensor', 'dev_cla': None, 'stat_cla': None, 'id': 'status1_', 'name': 'MPPT-1 Status', 'val_tpl': __mppt1_status_type_val_tpl, 'icon': POWER}}, # noqa: E501
|
|
||||||
Register.BATT_STATUS_2: {'name': ['batterie', 'Status_2'], 'level': logging.INFO, 'unit': '', 'ha': {'dev': 'batterie', 'comp': 'sensor', 'dev_cla': None, 'stat_cla': None, 'id': 'status2_', 'name': 'MPPT-2 Status', 'val_tpl': __mppt2_status_type_val_tpl, 'icon': POWER}}, # noqa: E501
|
|
||||||
Register.BATT_VOLT: {'name': ['batterie', 'Voltage'], 'level': logging.INFO, 'unit': 'V', 'ha': {'dev': 'batterie', 'dev_cla': 'voltage', 'stat_cla': 'measurement', 'id': 'volt_bat_', 'fmt': FMT_FLOAT, 'name': 'Batterie Voltage', 'icon': GAUGE, 'ent_cat': 'diagnostic'}}, # noqa: E501
|
|
||||||
Register.BATT_CUR: {'name': ['batterie', 'Current'], 'level': logging.INFO, 'unit': 'A', 'ha': {'dev': 'batterie', 'dev_cla': 'current', 'stat_cla': 'measurement', 'id': 'cur_bat_', 'fmt': FMT_FLOAT, 'name': 'Batterie Current', 'icon': GAUGE, 'ent_cat': 'diagnostic'}}, # noqa: E501
|
|
||||||
Register.BATT_SOC: {'name': ['batterie', 'SOC'], 'level': logging.INFO, 'unit': '%', 'ha': {'dev': 'batterie', 'dev_cla': None, 'stat_cla': 'measurement', 'id': 'soc_', 'fmt': FMT_FLOAT, 'name': 'State of Charge (SOC)', 'icon': 'mdi:battery-90'}}, # noqa: E501
|
|
||||||
Register.BATT_CELL1_VOLT: {'name': ['batterie', 'Cell', 'Volt1'], 'level': logging.INFO, 'unit': 'V', 'ha': {'dev': 'batterie', 'dev_cla': 'voltage', 'stat_cla': 'measurement', 'id': 'volt_cell1_', 'val_tpl': "{{ (value_json['Cell']['Volt1'] | float)}}", 'name': 'Cell-01 Voltage', 'icon': GAUGE, 'ent_cat': 'diagnostic'}}, # noqa: E501
|
|
||||||
Register.BATT_CELL3_VOLT: {'name': ['batterie', 'Cell', 'Volt3'], 'level': logging.INFO, 'unit': 'V', 'ha': {'dev': 'batterie', 'dev_cla': 'voltage', 'stat_cla': 'measurement', 'id': 'volt_cell3_', 'val_tpl': "{{ (value_json['Cell']['Volt2'] | float)}}", 'name': 'Cell-03 Voltage', 'icon': GAUGE, 'ent_cat': 'diagnostic'}}, # noqa: E501
|
|
||||||
Register.BATT_CELL4_VOLT: {'name': ['batterie', 'Cell', 'Volt4'], 'level': logging.INFO, 'unit': 'V', 'ha': {'dev': 'batterie', 'dev_cla': 'voltage', 'stat_cla': 'measurement', 'id': 'volt_cell4_', 'val_tpl': "{{ (value_json['Cell']['Volt3'] | float)}}", 'name': 'Cell-04 Voltage', 'icon': GAUGE, 'ent_cat': 'diagnostic'}}, # noqa: E501
|
|
||||||
Register.BATT_CELL2_VOLT: {'name': ['batterie', 'Cell', 'Volt2'], 'level': logging.INFO, 'unit': 'V', 'ha': {'dev': 'batterie', 'dev_cla': 'voltage', 'stat_cla': 'measurement', 'id': 'volt_cell2_', 'val_tpl': "{{ (value_json['Cell']['Volt4'] | float)}}", 'name': 'Cell-02 Voltage', 'icon': GAUGE, 'ent_cat': 'diagnostic'}}, # noqa: E501
|
|
||||||
Register.BATT_CELL5_VOLT: {'name': ['batterie', 'Cell', 'Volt5'], 'level': logging.INFO, 'unit': 'V', 'ha': {'dev': 'batterie', 'dev_cla': 'voltage', 'stat_cla': 'measurement', 'id': 'volt_cell5_', 'val_tpl': "{{ (value_json['Cell']['Volt5'] | float)}}", 'name': 'Cell-05 Voltage', 'icon': GAUGE, 'ent_cat': 'diagnostic'}}, # noqa: E501
|
|
||||||
Register.BATT_CELL6_VOLT: {'name': ['batterie', 'Cell', 'Volt6'], 'level': logging.INFO, 'unit': 'V', 'ha': {'dev': 'batterie', 'dev_cla': 'voltage', 'stat_cla': 'measurement', 'id': 'volt_cell6_', 'val_tpl': "{{ (value_json['Cell']['Volt6'] | float)}}", 'name': 'Cell-06 Voltage', 'icon': GAUGE, 'ent_cat': 'diagnostic'}}, # noqa: E501
|
|
||||||
Register.BATT_CELL7_VOLT: {'name': ['batterie', 'Cell', 'Volt7'], 'level': logging.INFO, 'unit': 'V', 'ha': {'dev': 'batterie', 'dev_cla': 'voltage', 'stat_cla': 'measurement', 'id': 'volt_cell7_', 'val_tpl': "{{ (value_json['Cell']['Volt7'] | float)}}", 'name': 'Cell-07 Voltage', 'icon': GAUGE, 'ent_cat': 'diagnostic'}}, # noqa: E501
|
|
||||||
Register.BATT_CELL8_VOLT: {'name': ['batterie', 'Cell', 'Volt8'], 'level': logging.INFO, 'unit': 'V', 'ha': {'dev': 'batterie', 'dev_cla': 'voltage', 'stat_cla': 'measurement', 'id': 'volt_cell8_', 'val_tpl': "{{ (value_json['Cell']['Volt8'] | float)}}", 'name': 'Cell-08 Voltage', 'icon': GAUGE, 'ent_cat': 'diagnostic'}}, # noqa: E501
|
|
||||||
Register.BATT_CELL9_VOLT: {'name': ['batterie', 'Cell', 'Volt9'], 'level': logging.INFO, 'unit': 'V', 'ha': {'dev': 'batterie', 'dev_cla': 'voltage', 'stat_cla': 'measurement', 'id': 'volt_cell9_', 'val_tpl': "{{ (value_json['Cell']['Volt9'] | float)}}", 'name': 'Cell-09 Voltage', 'icon': GAUGE, 'ent_cat': 'diagnostic'}}, # noqa: E501
|
|
||||||
Register.BATT_CELL10_VOLT: {'name': ['batterie', 'Cell', 'Volt10'], 'level': logging.INFO, 'unit': 'V', 'ha': {'dev': 'batterie', 'dev_cla': 'voltage', 'stat_cla': 'measurement', 'id': 'volt_cell10_', 'val_tpl': "{{ (value_json['Cell']['Volt10'] | float)}}", 'name': 'Cell-10 Voltage', 'icon': GAUGE, 'ent_cat': 'diagnostic'}}, # noqa: E501
|
|
||||||
Register.BATT_CELL11_VOLT: {'name': ['batterie', 'Cell', 'Volt11'], 'level': logging.INFO, 'unit': 'V', 'ha': {'dev': 'batterie', 'dev_cla': 'voltage', 'stat_cla': 'measurement', 'id': 'volt_cell11_', 'val_tpl': "{{ (value_json['Cell']['Volt11'] | float)}}", 'name': 'Cell-11 Voltage', 'icon': GAUGE, 'ent_cat': 'diagnostic'}}, # noqa: E501
|
|
||||||
Register.BATT_CELL12_VOLT: {'name': ['batterie', 'Cell', 'Volt12'], 'level': logging.INFO, 'unit': 'V', 'ha': {'dev': 'batterie', 'dev_cla': 'voltage', 'stat_cla': 'measurement', 'id': 'volt_cell12_', 'val_tpl': "{{ (value_json['Cell']['Volt12'] | float)}}", 'name': 'Cell-12 Voltage', 'icon': GAUGE, 'ent_cat': 'diagnostic'}}, # noqa: E501
|
|
||||||
Register.BATT_CELL13_VOLT: {'name': ['batterie', 'Cell', 'Volt13'], 'level': logging.INFO, 'unit': 'V', 'ha': {'dev': 'batterie', 'dev_cla': 'voltage', 'stat_cla': 'measurement', 'id': 'volt_cell13_', 'val_tpl': "{{ (value_json['Cell']['Volt13'] | float)}}", 'name': 'Cell-13 Voltage', 'icon': GAUGE, 'ent_cat': 'diagnostic'}}, # noqa: E501
|
|
||||||
Register.BATT_CELL14_VOLT: {'name': ['batterie', 'Cell', 'Volt14'], 'level': logging.INFO, 'unit': 'V', 'ha': {'dev': 'batterie', 'dev_cla': 'voltage', 'stat_cla': 'measurement', 'id': 'volt_cell14_', 'val_tpl': "{{ (value_json['Cell']['Volt14'] | float)}}", 'name': 'Cell-14 Voltage', 'icon': GAUGE, 'ent_cat': 'diagnostic'}}, # noqa: E501
|
|
||||||
Register.BATT_CELL15_VOLT: {'name': ['batterie', 'Cell', 'Volt15'], 'level': logging.INFO, 'unit': 'V', 'ha': {'dev': 'batterie', 'dev_cla': 'voltage', 'stat_cla': 'measurement', 'id': 'volt_cell15_', 'val_tpl': "{{ (value_json['Cell']['Volt15'] | float)}}", 'name': 'Cell-15 Voltage', 'icon': GAUGE, 'ent_cat': 'diagnostic'}}, # noqa: E501
|
|
||||||
Register.BATT_CELL16_VOLT: {'name': ['batterie', 'Cell', 'Volt16'], 'level': logging.INFO, 'unit': 'V', 'ha': {'dev': 'batterie', 'dev_cla': 'voltage', 'stat_cla': 'measurement', 'id': 'volt_cell16_', 'val_tpl': "{{ (value_json['Cell']['Volt16'] | float)}}", 'name': 'Cell-16 Voltage', 'icon': GAUGE, 'ent_cat': 'diagnostic'}}, # noqa: E501
|
|
||||||
Register.BATT_TEMP_1: {'name': ['batterie', 'Temp_1'], 'level': logging.INFO, 'unit': '°C', 'ha': {'dev': 'batterie', 'dev_cla': 'temperature', 'stat_cla': 'measurement', 'id': 'temp_1_', 'fmt': FMT_INT, 'name': 'Batterie Temp-1', 'ent_cat': 'diagnostic'}}, # noqa: E501
|
|
||||||
Register.BATT_TEMP_2: {'name': ['batterie', 'Temp_2'], 'level': logging.INFO, 'unit': '°C', 'ha': {'dev': 'batterie', 'dev_cla': 'temperature', 'stat_cla': 'measurement', 'id': 'temp_2_', 'fmt': FMT_INT, 'name': 'Batterie Temp-2', 'ent_cat': 'diagnostic'}}, # noqa: E501
|
|
||||||
Register.BATT_TEMP_3: {'name': ['batterie', 'Temp_3'], 'level': logging.INFO, 'unit': '°C', 'ha': {'dev': 'batterie', 'dev_cla': 'temperature', 'stat_cla': 'measurement', 'id': 'temp_3_', 'fmt': FMT_INT, 'name': 'Batterie Temp-3', 'ent_cat': 'diagnostic'}}, # noqa: E501
|
|
||||||
Register.BATT_OUT_VOLT: {'name': ['batterie', 'out', 'Voltage'], 'level': logging.INFO, 'unit': 'V', 'ha': {'dev': 'batterie', 'dev_cla': 'voltage', 'stat_cla': 'measurement', 'id': 'out_volt_', 'val_tpl': "{{ (value_json['out']['Voltage'] | float)}}", 'name': 'Output Voltage', 'icon': GAUGE, 'ent_cat': 'diagnostic'}}, # noqa: E501
|
|
||||||
Register.BATT_OUT_CUR: {'name': ['batterie', 'out', 'Current'], 'level': logging.INFO, 'unit': 'A', 'ha': {'dev': 'batterie', 'dev_cla': 'current', 'stat_cla': 'measurement', 'id': 'out_cur_', 'val_tpl': "{{ (value_json['out']['Current'] | float)}}", 'name': 'Output Current', 'icon': GAUGE, 'ent_cat': 'diagnostic'}}, # noqa: E501
|
|
||||||
Register.BATT_OUT_STATUS: {'name': ['batterie', 'out', 'Out_Status'], 'level': logging.INFO, 'unit': '', 'ha': {'dev': 'batterie', 'comp': 'sensor', 'dev_cla': None, 'stat_cla': None, 'id': 'out_status_', 'name': 'Output Status', 'val_tpl': __out_status_type_val_tpl, 'icon': POWER}}, # noqa: E501
|
|
||||||
Register.BATT_TEMP_4: {'name': ['batterie', 'Controller_Temp'], 'level': logging.INFO, 'unit': '°C', 'ha': {'dev': 'batterie', 'dev_cla': 'temperature', 'stat_cla': 'measurement', 'id': 'temp_4_', 'fmt': FMT_INT, 'name': 'Ctrl Temperature'}}, # noqa: E501
|
|
||||||
Register.BATT_74: {'name': ['batterie', 'Reg_74'], 'level': logging.INFO, 'unit': '', 'ha': {'dev': 'batterie', 'dev_cla': 'power', 'stat_cla': 'measurement', 'id': 'batt_74_', 'fmt': FMT_INT, 'ent_cat': 'diagnostic'}}, # noqa: E501
|
|
||||||
Register.BATT_76: {'name': ['batterie', 'Reg_76'], 'level': logging.INFO, 'unit': '', 'ha': {'dev': 'batterie', 'dev_cla': 'power', 'stat_cla': 'measurement', 'id': 'batt_76_', 'fmt': FMT_INT, 'ent_cat': 'diagnostic'}}, # noqa: E501
|
|
||||||
Register.BATT_78: {'name': ['batterie', 'Reg_78'], 'level': logging.INFO, 'unit': '', 'ha': {'dev': 'batterie', 'dev_cla': 'power', 'stat_cla': 'measurement', 'id': 'batt_78_', 'fmt': FMT_INT, 'ent_cat': 'diagnostic'}}, # noqa: E501
|
|
||||||
Register.BATT_PV_PWR: {'name': ['batterie', 'PV_Power'], 'level': logging.INFO, 'unit': 'W', 'ha': {'dev': 'batterie', 'dev_cla': 'power', 'stat_cla': 'measurement', 'id': 'pv_power_', 'fmt': FMT_INT, 'name': 'PV Power'}}, # noqa: E501
|
|
||||||
Register.BATT_PWR: {'name': ['batterie', 'Power'], 'level': logging.INFO, 'unit': 'W', 'ha': {'dev': 'batterie', 'dev_cla': 'power', 'stat_cla': 'measurement', 'id': 'power_', 'fmt': FMT_INT, 'name': 'Batterie Power'}}, # noqa: E501
|
|
||||||
Register.BATT_OUT_PWR: {'name': ['batterie', 'out', 'Power'], 'level': logging.INFO, 'unit': 'W', 'ha': {'dev': 'batterie', 'dev_cla': 'power', 'stat_cla': 'measurement', 'id': 'out_power_', 'val_tpl': "{{ (value_json['out']['Power'] | int)}}", 'name': 'Output Power'}}, # noqa: E501
|
|
||||||
|
|
||||||
Register.TEST_VAL_0: {'name': ['input', 'Val_0'], 'level': logging.INFO, 'unit': '', 'ha': {'dev': 'inverter', 'dev_cla': 'power', 'stat_cla': 'measurement', 'id': 'val_0_', 'fmt': FMT_INT, 'ent_cat': 'diagnostic'}}, # noqa: E501
|
|
||||||
Register.TEST_VAL_1: {'name': ['input', 'Val_1'], 'level': logging.INFO, 'unit': '', 'ha': {'dev': 'inverter', 'dev_cla': 'power', 'stat_cla': 'measurement', 'id': 'val_1_', 'fmt': FMT_INT, 'ent_cat': 'diagnostic'}}, # noqa: E501
|
|
||||||
Register.TEST_VAL_2: {'name': ['input', 'Val_2'], 'level': logging.INFO, 'unit': '', 'ha': {'dev': 'inverter', 'dev_cla': 'power', 'stat_cla': 'measurement', 'id': 'val_2_', 'fmt': FMT_INT, 'ent_cat': 'diagnostic'}}, # noqa: E501
|
|
||||||
Register.TEST_VAL_3: {'name': ['input', 'Val_3'], 'level': logging.INFO, 'unit': '', 'ha': {'dev': 'inverter', 'dev_cla': 'power', 'stat_cla': 'measurement', 'id': 'val_3_', 'fmt': FMT_INT, 'ent_cat': 'diagnostic'}}, # noqa: E501
|
|
||||||
Register.TEST_VAL_4: {'name': ['input', 'Val_4'], 'level': logging.INFO, 'unit': '', 'ha': {'dev': 'inverter', 'dev_cla': 'power', 'stat_cla': 'measurement', 'id': 'val_4_', 'fmt': FMT_INT, 'ent_cat': 'diagnostic'}}, # noqa: E501
|
|
||||||
Register.TEST_VAL_5: {'name': ['input', 'Val_5'], 'level': logging.INFO, 'unit': '', 'ha': {'dev': 'inverter', 'dev_cla': 'power', 'stat_cla': 'measurement', 'id': 'val_5_', 'fmt': FMT_INT, 'ent_cat': 'diagnostic'}}, # noqa: E501
|
|
||||||
Register.TEST_VAL_6: {'name': ['input', 'Val_6'], 'level': logging.INFO, 'unit': '', 'ha': {'dev': 'inverter', 'dev_cla': 'power', 'stat_cla': 'measurement', 'id': 'val_6_', 'fmt': FMT_INT, 'ent_cat': 'diagnostic'}}, # noqa: E501
|
|
||||||
Register.TEST_VAL_7: {'name': ['input', 'Val_7'], 'level': logging.INFO, 'unit': '', 'ha': {'dev': 'inverter', 'dev_cla': 'power', 'stat_cla': 'measurement', 'id': 'val_7_', 'fmt': FMT_INT, 'ent_cat': 'diagnostic'}}, # noqa: E501
|
|
||||||
Register.TEST_VAL_8: {'name': ['input', 'Val_8'], 'level': logging.INFO, 'unit': '', 'ha': {'dev': 'inverter', 'dev_cla': 'power', 'stat_cla': 'measurement', 'id': 'val_8_', 'fmt': FMT_INT, 'ent_cat': 'diagnostic'}}, # noqa: E501
|
|
||||||
Register.TEST_VAL_9: {'name': ['input', 'Val_9'], 'level': logging.INFO, 'unit': '', 'ha': {'dev': 'inverter', 'dev_cla': 'power', 'stat_cla': 'measurement', 'id': 'val_9_', 'fmt': FMT_INT, 'ent_cat': 'diagnostic'}}, # noqa: E501
|
|
||||||
Register.TEST_VAL_10: {'name': ['input', 'Val_10'], 'level': logging.INFO, 'unit': '', 'ha': {'dev': 'inverter', 'dev_cla': 'power', 'stat_cla': 'measurement', 'id': 'val_10_', 'fmt': FMT_INT, 'ent_cat': 'diagnostic'}}, # noqa: E501
|
|
||||||
Register.TEST_VAL_11: {'name': ['input', 'Val_11'], 'level': logging.INFO, 'unit': '', 'ha': {'dev': 'inverter', 'dev_cla': 'power', 'stat_cla': 'measurement', 'id': 'val_11_', 'fmt': FMT_INT, 'ent_cat': 'diagnostic'}}, # noqa: E501
|
|
||||||
Register.TEST_VAL_12: {'name': ['input', 'Val_12'], 'level': logging.INFO, 'unit': '', 'ha': {'dev': 'inverter', 'dev_cla': 'power', 'stat_cla': 'measurement', 'id': 'val_12_', 'fmt': FMT_INT, 'ent_cat': 'diagnostic'}}, # noqa: E501
|
|
||||||
Register.TEST_VAL_13: {'name': ['input', 'Val_13'], 'level': logging.INFO, 'unit': '', 'ha': {'dev': 'inverter', 'dev_cla': 'power', 'stat_cla': 'measurement', 'id': 'val_13_', 'fmt': FMT_INT, 'ent_cat': 'diagnostic'}}, # noqa: E501
|
|
||||||
Register.TEST_VAL_14: {'name': ['input', 'Val_14'], 'level': logging.INFO, 'unit': '', 'ha': {'dev': 'inverter', 'dev_cla': 'power', 'stat_cla': 'measurement', 'id': 'val_14_', 'fmt': FMT_INT, 'ent_cat': 'diagnostic'}}, # noqa: E501
|
|
||||||
Register.TEST_VAL_15: {'name': ['input', 'Val_15'], 'level': logging.INFO, 'unit': '', 'ha': {'dev': 'inverter', 'dev_cla': 'power', 'stat_cla': 'measurement', 'id': 'val_15_', 'fmt': FMT_INT, 'ent_cat': 'diagnostic'}}, # noqa: E501
|
|
||||||
Register.TEST_VAL_16: {'name': ['input', 'Val_16'], 'level': logging.INFO, 'unit': '', 'ha': {'dev': 'inverter', 'dev_cla': 'power', 'stat_cla': 'measurement', 'id': 'val_16_', 'fmt': FMT_INT, 'ent_cat': 'diagnostic'}}, # noqa: E501
|
|
||||||
Register.TEST_VAL_17: {'name': ['input', 'Val_17'], 'level': logging.INFO, 'unit': '', 'ha': {'dev': 'inverter', 'dev_cla': 'power', 'stat_cla': 'measurement', 'id': 'val_17_', 'fmt': FMT_INT, 'ent_cat': 'diagnostic'}}, # noqa: E501
|
|
||||||
Register.TEST_VAL_18: {'name': ['input', 'Val_18'], 'level': logging.INFO, 'unit': '', 'ha': {'dev': 'inverter', 'dev_cla': 'power', 'stat_cla': 'measurement', 'id': 'val_18_', 'fmt': FMT_INT, 'ent_cat': 'diagnostic'}}, # noqa: E501
|
|
||||||
Register.TEST_VAL_19: {'name': ['input', 'Val_19'], 'level': logging.INFO, 'unit': '', 'ha': {'dev': 'inverter', 'dev_cla': 'power', 'stat_cla': 'measurement', 'id': 'val_19_', 'fmt': FMT_INT, 'ent_cat': 'diagnostic'}}, # noqa: E501
|
|
||||||
Register.TEST_VAL_20: {'name': ['input', 'Val_20'], 'level': logging.INFO, 'unit': '', 'ha': {'dev': 'inverter', 'dev_cla': 'power', 'stat_cla': 'measurement', 'id': 'val_20_', 'fmt': FMT_INT, 'ent_cat': 'diagnostic'}}, # noqa: E501
|
|
||||||
Register.TEST_VAL_21: {'name': ['input', 'Val_21'], 'level': logging.INFO, 'unit': '', 'ha': {'dev': 'inverter', 'dev_cla': 'power', 'stat_cla': 'measurement', 'id': 'val_21_', 'fmt': FMT_INT, 'ent_cat': 'diagnostic'}}, # noqa: E501
|
|
||||||
Register.TEST_VAL_22: {'name': ['input', 'Val_22'], 'level': logging.INFO, 'unit': '', 'ha': {'dev': 'inverter', 'dev_cla': 'power', 'stat_cla': 'measurement', 'id': 'val_22_', 'fmt': FMT_INT, 'ent_cat': 'diagnostic'}}, # noqa: E501
|
|
||||||
Register.TEST_VAL_23: {'name': ['input', 'Val_23'], 'level': logging.INFO, 'unit': '', 'ha': {'dev': 'inverter', 'dev_cla': 'power', 'stat_cla': 'measurement', 'id': 'val_23_', 'fmt': FMT_INT, 'ent_cat': 'diagnostic'}}, # noqa: E501
|
|
||||||
Register.TEST_VAL_24: {'name': ['input', 'Val_24'], 'level': logging.INFO, 'unit': '', 'ha': {'dev': 'inverter', 'dev_cla': 'power', 'stat_cla': 'measurement', 'id': 'val_24_', 'fmt': FMT_INT, 'ent_cat': 'diagnostic'}}, # noqa: E501
|
|
||||||
Register.TEST_VAL_25: {'name': ['input', 'Val_25'], 'level': logging.INFO, 'unit': '', 'ha': {'dev': 'inverter', 'dev_cla': 'power', 'stat_cla': 'measurement', 'id': 'val_25_', 'fmt': FMT_INT, 'ent_cat': 'diagnostic'}}, # noqa: E501
|
|
||||||
Register.TEST_VAL_26: {'name': ['input', 'Val_26'], 'level': logging.INFO, 'unit': '', 'ha': {'dev': 'inverter', 'dev_cla': 'power', 'stat_cla': 'measurement', 'id': 'val_26_', 'fmt': FMT_INT, 'ent_cat': 'diagnostic'}}, # noqa: E501
|
|
||||||
Register.TEST_VAL_27: {'name': ['input', 'Val_27'], 'level': logging.INFO, 'unit': '', 'ha': {'dev': 'inverter', 'dev_cla': 'power', 'stat_cla': 'measurement', 'id': 'val_27_', 'fmt': FMT_INT, 'ent_cat': 'diagnostic'}}, # noqa: E501
|
|
||||||
Register.TEST_VAL_28: {'name': ['input', 'Val_28'], 'level': logging.INFO, 'unit': '', 'ha': {'dev': 'inverter', 'dev_cla': 'power', 'stat_cla': 'measurement', 'id': 'val_28_', 'fmt': FMT_INT, 'ent_cat': 'diagnostic'}}, # noqa: E501
|
|
||||||
Register.TEST_VAL_29: {'name': ['input', 'Val_29'], 'level': logging.INFO, 'unit': '', 'ha': {'dev': 'inverter', 'dev_cla': 'power', 'stat_cla': 'measurement', 'id': 'val_29_', 'fmt': FMT_INT, 'ent_cat': 'diagnostic'}}, # noqa: E501
|
|
||||||
Register.TEST_VAL_30: {'name': ['input', 'Val_30'], 'level': logging.INFO, 'unit': '', 'ha': {'dev': 'inverter', 'dev_cla': 'power', 'stat_cla': 'measurement', 'id': 'val_30_', 'fmt': FMT_INT, 'ent_cat': 'diagnostic'}}, # noqa: E501
|
|
||||||
Register.TEST_VAL_31: {'name': ['input', 'Val_31'], 'level': logging.INFO, 'unit': '', 'ha': {'dev': 'inverter', 'dev_cla': 'power', 'stat_cla': 'measurement', 'id': 'val_31_', 'fmt': FMT_INT, 'ent_cat': 'diagnostic'}}, # noqa: E501
|
|
||||||
Register.TEST_VAL_32: {'name': ['input', 'Val_32'], 'level': logging.INFO, 'unit': '', 'ha': {'dev': 'inverter', 'dev_cla': 'power', 'stat_cla': 'measurement', 'id': 'val_32_', 'fmt': FMT_INT, 'ent_cat': 'diagnostic'}}, # noqa: E501
|
|
||||||
|
|
||||||
Register.TEST_IVAL_1: {'name': ['input', 'iVal_1'], 'level': logging.INFO, 'unit': '', 'ha': {'dev': 'inverter', 'dev_cla': 'power', 'stat_cla': 'measurement', 'id': 'ival_1_', 'fmt': FMT_INT, 'ent_cat': 'diagnostic'}}, # noqa: E501
|
|
||||||
Register.TEST_IVAL_2: {'name': ['input', 'iVal_2'], 'level': logging.INFO, 'unit': '', 'ha': {'dev': 'inverter', 'dev_cla': 'power', 'stat_cla': 'measurement', 'id': 'ival_2_', 'fmt': FMT_INT, 'ent_cat': 'diagnostic'}}, # noqa: E501
|
|
||||||
Register.TEST_IVAL_3: {'name': ['input', 'iVal_3'], 'level': logging.INFO, 'unit': '', 'ha': {'dev': 'inverter', 'dev_cla': 'power', 'stat_cla': 'measurement', 'id': 'ival_3_', 'fmt': FMT_INT, 'ent_cat': 'diagnostic'}}, # noqa: E501
|
|
||||||
Register.TEST_IVAL_4: {'name': ['input', 'iVal_4'], 'level': logging.INFO, 'unit': '', 'ha': {'dev': 'inverter', 'dev_cla': 'power', 'stat_cla': 'measurement', 'id': 'ival_4_', 'fmt': FMT_INT, 'ent_cat': 'diagnostic'}}, # noqa: E501
|
|
||||||
Register.TEST_IVAL_5: {'name': ['input', 'iVal_5'], 'level': logging.INFO, 'unit': '', 'ha': {'dev': 'inverter', 'dev_cla': 'power', 'stat_cla': 'measurement', 'id': 'ival_5_', 'fmt': FMT_INT, 'ent_cat': 'diagnostic'}}, # noqa: E501
|
|
||||||
Register.TEST_IVAL_6: {'name': ['input', 'iVal_6'], 'level': logging.INFO, 'unit': '', 'ha': {'dev': 'inverter', 'dev_cla': 'power', 'stat_cla': 'measurement', 'id': 'ival_6_', 'fmt': FMT_INT, 'ent_cat': 'diagnostic'}}, # noqa: E501
|
|
||||||
Register.TEST_IVAL_7: {'name': ['input', 'iVal_7'], 'level': logging.INFO, 'unit': '', 'ha': {'dev': 'inverter', 'dev_cla': 'power', 'stat_cla': 'measurement', 'id': 'ival_7_', 'fmt': FMT_INT, 'ent_cat': 'diagnostic'}}, # noqa: E501
|
|
||||||
Register.TEST_IVAL_8: {'name': ['input', 'iVal_8'], 'level': logging.INFO, 'unit': '', 'ha': {'dev': 'inverter', 'dev_cla': 'power', 'stat_cla': 'measurement', 'id': 'ival_8_', 'fmt': FMT_INT, 'ent_cat': 'diagnostic'}}, # noqa: E501
|
|
||||||
Register.TEST_IVAL_9: {'name': ['input', 'iVal_9'], 'level': logging.INFO, 'unit': '', 'ha': {'dev': 'inverter', 'dev_cla': 'power', 'stat_cla': 'measurement', 'id': 'ival_9_', 'fmt': FMT_INT, 'ent_cat': 'diagnostic'}}, # noqa: E501
|
|
||||||
Register.TEST_IVAL_10: {'name': ['input', 'iVal_10'], 'level': logging.INFO, 'unit': '', 'ha': {'dev': 'inverter', 'dev_cla': 'power', 'stat_cla': 'measurement', 'id': 'ival_10_', 'fmt': FMT_INT, 'ent_cat': 'diagnostic'}}, # noqa: E501
|
|
||||||
Register.TEST_IVAL_11: {'name': ['input', 'iVal_11'], 'level': logging.INFO, 'unit': '', 'ha': {'dev': 'inverter', 'dev_cla': 'power', 'stat_cla': 'measurement', 'id': 'ival_11_', 'fmt': FMT_INT, 'ent_cat': 'diagnostic'}}, # noqa: E501
|
|
||||||
Register.TEST_IVAL_12: {'name': ['input', 'iVal_12'], 'level': logging.INFO, 'unit': '', 'ha': {'dev': 'inverter', 'dev_cla': 'power', 'stat_cla': 'measurement', 'id': 'ival_12_', 'fmt': FMT_INT, 'ent_cat': 'diagnostic'}}, # noqa: E501
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@property
|
@property
|
||||||
|
|||||||
@@ -151,8 +151,6 @@ class InverterBase(InverterIfc, Proxy):
|
|||||||
# home assistant has changed the status back to online
|
# home assistant has changed the status back to online
|
||||||
try:
|
try:
|
||||||
if (('inverter' in stream.new_data and stream.new_data['inverter'])
|
if (('inverter' in stream.new_data and stream.new_data['inverter'])
|
||||||
or ('batterie' in stream.new_data and
|
|
||||||
stream.new_data['batterie'])
|
|
||||||
or ('collector' in stream.new_data and
|
or ('collector' in stream.new_data and
|
||||||
stream.new_data['collector'])
|
stream.new_data['collector'])
|
||||||
or self.mqtt.ha_restarts != self.__ha_restarts):
|
or self.mqtt.ha_restarts != self.__ha_restarts):
|
||||||
|
|||||||
@@ -67,10 +67,10 @@ formatter=file_formatter
|
|||||||
args=(handlers.log_path + 'trace.log', when:='midnight', backupCount:=handlers.log_backups)
|
args=(handlers.log_path + 'trace.log', when:='midnight', backupCount:=handlers.log_backups)
|
||||||
|
|
||||||
[formatter_console_formatter]
|
[formatter_console_formatter]
|
||||||
format=%(asctime)s %(levelname)5s | %(name)4s | %(message)s
|
format=%(asctime)s %(levelname)5s | %(name)4s | %(message)s'
|
||||||
datefmt=%Y-%m-%d %H:%M:%S
|
datefmt='%Y-%m-%d %H:%M:%S
|
||||||
|
|
||||||
[formatter_file_formatter]
|
[formatter_file_formatter]
|
||||||
format=%(asctime)s %(levelname)5s | %(name)4s | %(message)s
|
format=%(asctime)s %(levelname)5s | %(name)4s | %(message)s'
|
||||||
datefmt=%Y-%m-%d %H:%M:%S
|
datefmt='%Y-%m-%d %H:%M:%S
|
||||||
|
|
||||||
|
|||||||
@@ -117,11 +117,6 @@ class Message(ProtocolIfc):
|
|||||||
self.mb_first_timeout = self.MB_START_TIMEOUT
|
self.mb_first_timeout = self.MB_START_TIMEOUT
|
||||||
'''timer value for next Modbus polling request'''
|
'''timer value for next Modbus polling request'''
|
||||||
self.modbus_polling = False
|
self.modbus_polling = False
|
||||||
self.mb_start_reg = 0
|
|
||||||
self.mb_step = 0
|
|
||||||
self.mb_bytes = 0
|
|
||||||
self.mb_inv_no = 1
|
|
||||||
self.mb_scan = False
|
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def node_id(self):
|
def node_id(self):
|
||||||
@@ -140,25 +135,6 @@ class Message(ProtocolIfc):
|
|||||||
# to our _recv_buffer
|
# to our _recv_buffer
|
||||||
return # pragma: no cover
|
return # pragma: no cover
|
||||||
|
|
||||||
def _set_config_parms(self, inv: dict):
|
|
||||||
'''init connection with params from the configuration'''
|
|
||||||
self.node_id = inv['node_id']
|
|
||||||
self.sug_area = inv['suggested_area']
|
|
||||||
self.modbus_polling = inv['modbus_polling']
|
|
||||||
if 'modbus_scanning' in inv:
|
|
||||||
scan = inv['modbus_scanning']
|
|
||||||
self.mb_scan = True
|
|
||||||
self.mb_start_reg = scan['start']
|
|
||||||
self.mb_step = scan['step']
|
|
||||||
self.mb_bytes = scan['bytes']
|
|
||||||
if 'client_mode' in inv:
|
|
||||||
self.mb_start_reg = scan['start']
|
|
||||||
else:
|
|
||||||
self.mb_start_reg = scan['start'] - scan['step']
|
|
||||||
self.mb_start_reg &= 0xffff
|
|
||||||
if self.mb:
|
|
||||||
self.mb.set_node_id(self.node_id)
|
|
||||||
|
|
||||||
def _set_mqtt_timestamp(self, key, ts: float | None):
|
def _set_mqtt_timestamp(self, key, ts: float | None):
|
||||||
if key not in self.new_data or \
|
if key not in self.new_data or \
|
||||||
not self.new_data[key]:
|
not self.new_data[key]:
|
||||||
@@ -184,39 +160,15 @@ class Message(ProtocolIfc):
|
|||||||
to = self.MAX_DEF_IDLE_TIME
|
to = self.MAX_DEF_IDLE_TIME
|
||||||
return to
|
return to
|
||||||
|
|
||||||
def _send_modbus_cmd(self, dev_id, func, addr, val, log_lvl) -> None:
|
def _send_modbus_cmd(self, func, addr, val, log_lvl) -> None:
|
||||||
if self.state != State.up:
|
if self.state != State.up:
|
||||||
logger.log(log_lvl, f'[{self.node_id}] ignore MODBUS cmd,'
|
logger.log(log_lvl, f'[{self.node_id}] ignore MODBUS cmd,'
|
||||||
' as the state is not UP')
|
' as the state is not UP')
|
||||||
return
|
return
|
||||||
self.mb.build_msg(dev_id, func, addr, val, log_lvl)
|
self.mb.build_msg(Modbus.INV_ADDR, func, addr, val, log_lvl)
|
||||||
|
|
||||||
async def send_modbus_cmd(self, func, addr, val, log_lvl) -> None:
|
async def send_modbus_cmd(self, func, addr, val, log_lvl) -> None:
|
||||||
self._send_modbus_cmd(Modbus.INV_ADDR, func, addr, val, log_lvl)
|
self._send_modbus_cmd(func, addr, val, log_lvl)
|
||||||
|
|
||||||
def _send_modbus_scan(self):
|
|
||||||
self.mb_start_reg += self.mb_step
|
|
||||||
if self.mb_start_reg > 0xffff:
|
|
||||||
self.mb_start_reg = self.mb_start_reg & 0xffff
|
|
||||||
self.mb_inv_no += 1
|
|
||||||
logging.info(f"Next Round: inv:{self.mb_inv_no}"
|
|
||||||
f" reg:{self.mb_start_reg:04x}")
|
|
||||||
if (self.mb_start_reg & 0xfffc) % 0x80 == 0:
|
|
||||||
logging.info(f"[{self.node_id}] Scan info: "
|
|
||||||
f"inv:{self.mb_inv_no}"
|
|
||||||
f" reg:{self.mb_start_reg:04x}")
|
|
||||||
self._send_modbus_cmd(self.mb_inv_no, Modbus.READ_REGS,
|
|
||||||
self.mb_start_reg, self.mb_bytes,
|
|
||||||
logging.INFO)
|
|
||||||
|
|
||||||
def _dump_modbus_scan(self, data, hdr_len, modbus_msg_len):
|
|
||||||
if (data[hdr_len] == self.mb_inv_no and
|
|
||||||
data[hdr_len+1] == Modbus.READ_REGS):
|
|
||||||
logging.info(f'[{self.node_id}] Valid MODBUS data '
|
|
||||||
f'(reg: 0x{self.mb.last_reg:04x}):')
|
|
||||||
hex_dump_memory(logging.INFO, 'Valid MODBUS data '
|
|
||||||
f'(reg: 0x{self.mb.last_reg:04x}):',
|
|
||||||
data[hdr_len:], modbus_msg_len)
|
|
||||||
|
|
||||||
'''
|
'''
|
||||||
Our puplic methods
|
Our puplic methods
|
||||||
|
|||||||
@@ -37,45 +37,6 @@ class Modbus():
|
|||||||
|
|
||||||
__crc_tab = []
|
__crc_tab = []
|
||||||
mb_reg_mapping = {
|
mb_reg_mapping = {
|
||||||
0x0000: {'reg': Register.SERIAL_NUMBER, 'fmt': '!16s'}, # noqa: E501
|
|
||||||
0x0008: {'reg': Register.BATT_PV1_VOLT, 'fmt': '!H', 'ratio': 0.01}, # noqa: E501, PV1 voltage
|
|
||||||
0x0009: {'reg': Register.BATT_PV1_CUR, 'fmt': '!H', 'ratio': 0.01}, # noqa: E501, PV1 current
|
|
||||||
0x000a: {'reg': Register.BATT_PV2_VOLT, 'fmt': '!H', 'ratio': 0.01}, # noqa: E501, PV2 voltage
|
|
||||||
0x000b: {'reg': Register.BATT_PV2_CUR, 'fmt': '!H', 'ratio': 0.01}, # noqa: E501, PV2 current
|
|
||||||
0x000c: {'reg': Register.BATT_38, 'fmt': '!h'}, # noqa: E501
|
|
||||||
0x000d: {'reg': Register.BATT_TOTAL_GEN, 'fmt': '!h', 'ratio': 0.01}, # noqa: E501
|
|
||||||
0x000e: {'reg': Register.BATT_STATUS_1, 'fmt': '!h'}, # noqa: E501
|
|
||||||
0x000f: {'reg': Register.BATT_STATUS_2, 'fmt': '!h'}, # noqa: E501
|
|
||||||
0x0010: {'reg': Register.BATT_VOLT, 'fmt': '!h', 'ratio': 0.01}, # noqa: E501
|
|
||||||
0x0011: {'reg': Register.BATT_CUR, 'fmt': '!h', 'ratio': 0.01}, # noqa: E501
|
|
||||||
0x0012: {'reg': Register.BATT_SOC, 'fmt': '!H', 'ratio': 0.01}, # noqa: E501, state of charge (SOC) in percent
|
|
||||||
0x0013: {'reg': Register.BATT_CELL1_VOLT, 'fmt': '!h', 'ratio': 0.001}, # noqa: E501
|
|
||||||
0x0014: {'reg': Register.BATT_CELL2_VOLT, 'fmt': '!h', 'ratio': 0.001}, # noqa: E501
|
|
||||||
0x0015: {'reg': Register.BATT_CELL3_VOLT, 'fmt': '!h', 'ratio': 0.001}, # noqa: E501
|
|
||||||
0x0016: {'reg': Register.BATT_CELL4_VOLT, 'fmt': '!h', 'ratio': 0.001}, # noqa: E501
|
|
||||||
0x0017: {'reg': Register.BATT_CELL5_VOLT, 'fmt': '!h', 'ratio': 0.001}, # noqa: E501
|
|
||||||
0x0018: {'reg': Register.BATT_CELL6_VOLT, 'fmt': '!h', 'ratio': 0.001}, # noqa: E501
|
|
||||||
0x0019: {'reg': Register.BATT_CELL7_VOLT, 'fmt': '!h', 'ratio': 0.001}, # noqa: E501
|
|
||||||
0x001a: {'reg': Register.BATT_CELL8_VOLT, 'fmt': '!h', 'ratio': 0.001}, # noqa: E501
|
|
||||||
0x001b: {'reg': Register.BATT_CELL9_VOLT, 'fmt': '!h', 'ratio': 0.001}, # noqa: E501
|
|
||||||
0x001c: {'reg': Register.BATT_CELL10_VOLT, 'fmt': '!h', 'ratio': 0.001}, # noqa: E501
|
|
||||||
0x001d: {'reg': Register.BATT_CELL11_VOLT, 'fmt': '!h', 'ratio': 0.001}, # noqa: E501
|
|
||||||
0x001e: {'reg': Register.BATT_CELL12_VOLT, 'fmt': '!h', 'ratio': 0.001}, # noqa: E501
|
|
||||||
0x001f: {'reg': Register.BATT_CELL13_VOLT, 'fmt': '!h', 'ratio': 0.001}, # noqa: E501
|
|
||||||
0x0020: {'reg': Register.BATT_CELL14_VOLT, 'fmt': '!h', 'ratio': 0.001}, # noqa: E501
|
|
||||||
0x0021: {'reg': Register.BATT_CELL15_VOLT, 'fmt': '!h', 'ratio': 0.001}, # noqa: E501
|
|
||||||
0x0022: {'reg': Register.BATT_CELL16_VOLT, 'fmt': '!h', 'ratio': 0.001}, # noqa: E501
|
|
||||||
0x0023: {'reg': Register.BATT_TEMP_1, 'fmt': '!h'}, # noqa: E501
|
|
||||||
0x0024: {'reg': Register.BATT_TEMP_2, 'fmt': '!h'}, # noqa: E501
|
|
||||||
0x0025: {'reg': Register.BATT_TEMP_3, 'fmt': '!h'}, # noqa: E501
|
|
||||||
0x0026: {'reg': Register.BATT_OUT_VOLT, 'fmt': '!h', 'ratio': 0.01}, # noqa: E501
|
|
||||||
0x0027: {'reg': Register.BATT_OUT_CUR, 'fmt': '!h', 'ratio': 0.01}, # noqa: E501
|
|
||||||
0x0028: {'reg': Register.BATT_OUT_STATUS, 'fmt': '!h'}, # noqa: E501
|
|
||||||
0x0029: {'reg': Register.BATT_TEMP_4, 'fmt': '!h'}, # noqa: E501
|
|
||||||
0x002a: {'reg': Register.BATT_74, 'fmt': '!h'}, # noqa: E501
|
|
||||||
0x002b: {'reg': Register.BATT_76, 'fmt': '!h'}, # noqa: E501
|
|
||||||
0x002c: {'reg': Register.BATT_78, 'fmt': '!h'}, # noqa: E501
|
|
||||||
|
|
||||||
0x2000: {'reg': Register.BOOT_STATUS, 'fmt': '!H'}, # noqa: E501
|
0x2000: {'reg': Register.BOOT_STATUS, 'fmt': '!H'}, # noqa: E501
|
||||||
0x2001: {'reg': Register.DSP_STATUS, 'fmt': '!H'}, # noqa: E501
|
0x2001: {'reg': Register.DSP_STATUS, 'fmt': '!H'}, # noqa: E501
|
||||||
0x2003: {'reg': Register.WORK_MODE, 'fmt': '!H'},
|
0x2003: {'reg': Register.WORK_MODE, 'fmt': '!H'},
|
||||||
|
|||||||
@@ -1,7 +1,6 @@
|
|||||||
import logging
|
import logging
|
||||||
import traceback
|
import traceback
|
||||||
import asyncio
|
import asyncio
|
||||||
from itertools import chain
|
|
||||||
|
|
||||||
from cnf.config import Config
|
from cnf.config import Config
|
||||||
from gen3plus.inverter_g3p import InverterG3P
|
from gen3plus.inverter_g3p import InverterG3P
|
||||||
@@ -43,15 +42,14 @@ class ModbusTcp():
|
|||||||
self.tim_restart = tim_restart
|
self.tim_restart = tim_restart
|
||||||
|
|
||||||
inverters = Config.get('inverters')
|
inverters = Config.get('inverters')
|
||||||
batteries = Config.get('batteries')
|
|
||||||
# logging.info(f'Inverters: {inverters}')
|
# logging.info(f'Inverters: {inverters}')
|
||||||
|
|
||||||
for _, inv in chain(inverters.items(), batteries.items()):
|
for inv in inverters.values():
|
||||||
if (type(inv) is dict
|
if (type(inv) is dict
|
||||||
and 'monitor_sn' in inv
|
and 'monitor_sn' in inv
|
||||||
and 'client_mode' in inv):
|
and 'client_mode' in inv):
|
||||||
client = inv['client_mode']
|
client = inv['client_mode']
|
||||||
logger.info(f"'client_mode' for Monitoring-SN: {inv['monitor_sn']} host: {client['host']}:{client['port']}, forward: {client['forward']}") # noqa: E501
|
logger.info(f"'client_mode' for snr: {inv['monitor_sn']} host: {client['host']}:{client['port']}, forward: {client['forward']}") # noqa: E501
|
||||||
loop.create_task(self.modbus_loop(client['host'],
|
loop.create_task(self.modbus_loop(client['host'],
|
||||||
client['port'],
|
client['port'],
|
||||||
inv['monitor_sn'],
|
inv['monitor_sn'],
|
||||||
|
|||||||
@@ -1,7 +1,6 @@
|
|||||||
import asyncio
|
import asyncio
|
||||||
import logging
|
import logging
|
||||||
import json
|
import json
|
||||||
from itertools import chain
|
|
||||||
|
|
||||||
from cnf.config import Config
|
from cnf.config import Config
|
||||||
from mqtt import Mqtt
|
from mqtt import Mqtt
|
||||||
@@ -57,9 +56,8 @@ class Proxy():
|
|||||||
# reset at midnight when you restart the proxy just before
|
# reset at midnight when you restart the proxy just before
|
||||||
# midnight!
|
# midnight!
|
||||||
inverters = Config.get('inverters')
|
inverters = Config.get('inverters')
|
||||||
batteries = Config.get('batteries')
|
|
||||||
# logger.debug(f'Proxys: {inverters}')
|
# logger.debug(f'Proxys: {inverters}')
|
||||||
for _, inv in chain(inverters.items(), batteries.items()):
|
for inv in inverters.values():
|
||||||
if (type(inv) is dict):
|
if (type(inv) is dict):
|
||||||
node_id = inv['node_id']
|
node_id = inv['node_id']
|
||||||
cls.db_stat.reg_clr_at_midnight(f'{cls.entity_prfx}{node_id}',
|
cls.db_stat.reg_clr_at_midnight(f'{cls.entity_prfx}{node_id}',
|
||||||
|
|||||||
@@ -117,19 +117,19 @@ async def handle_shutdown(loop, web_task):
|
|||||||
loop.stop()
|
loop.stop()
|
||||||
|
|
||||||
|
|
||||||
def get_log_level() -> int | None:
|
def get_log_level() -> int:
|
||||||
'''checks if LOG_LVL is set in the environment and returns the
|
'''checks if LOG_LVL is set in the environment and returns the
|
||||||
corresponding logging.LOG_LEVEL'''
|
corresponding logging.LOG_LEVEL'''
|
||||||
switch = {
|
log_level = os.getenv('LOG_LVL', 'INFO')
|
||||||
'DEBUG': logging.DEBUG,
|
|
||||||
'WARN': logging.WARNING,
|
|
||||||
'INFO': logging.INFO,
|
|
||||||
'ERROR': logging.ERROR,
|
|
||||||
}
|
|
||||||
log_level = os.getenv('LOG_LVL', None)
|
|
||||||
logging.info(f"LOG_LVL : {log_level}")
|
logging.info(f"LOG_LVL : {log_level}")
|
||||||
|
|
||||||
return switch.get(log_level, None)
|
if log_level == 'DEBUG':
|
||||||
|
log_level = logging.DEBUG
|
||||||
|
elif log_level == 'WARN':
|
||||||
|
log_level = logging.WARNING
|
||||||
|
else:
|
||||||
|
log_level = logging.INFO
|
||||||
|
return log_level
|
||||||
|
|
||||||
|
|
||||||
def main(): # pragma: no cover
|
def main(): # pragma: no cover
|
||||||
@@ -156,10 +156,8 @@ def main(): # pragma: no cover
|
|||||||
|
|
||||||
setattr(logging.handlers, "log_path", args.log_path)
|
setattr(logging.handlers, "log_path", args.log_path)
|
||||||
setattr(logging.handlers, "log_backups", args.log_backups)
|
setattr(logging.handlers, "log_backups", args.log_backups)
|
||||||
os.makedirs(args.log_path, exist_ok=True)
|
|
||||||
|
|
||||||
src_dir = os.path.dirname(__file__) + '/'
|
logging.config.fileConfig('logging.ini')
|
||||||
logging.config.fileConfig(src_dir + 'logging.ini')
|
|
||||||
logging.info(f'Server "{serv_name} - {version}" will be started')
|
logging.info(f'Server "{serv_name} - {version}" will be started')
|
||||||
logging.info(f'current dir: {os.getcwd()}')
|
logging.info(f'current dir: {os.getcwd()}')
|
||||||
logging.info(f"config_path: {args.config_path}")
|
logging.info(f"config_path: {args.config_path}")
|
||||||
@@ -172,21 +170,21 @@ def main(): # pragma: no cover
|
|||||||
logging.info(f"log_backups: {args.log_backups} days")
|
logging.info(f"log_backups: {args.log_backups} days")
|
||||||
log_level = get_log_level()
|
log_level = get_log_level()
|
||||||
logging.info('******')
|
logging.info('******')
|
||||||
if log_level:
|
|
||||||
# set lowest-severity for 'root', 'msg', 'conn' and 'data' logger
|
# set lowest-severity for 'root', 'msg', 'conn' and 'data' logger
|
||||||
logging.getLogger().setLevel(log_level)
|
logging.getLogger().setLevel(log_level)
|
||||||
logging.getLogger('msg').setLevel(log_level)
|
logging.getLogger('msg').setLevel(log_level)
|
||||||
logging.getLogger('conn').setLevel(log_level)
|
logging.getLogger('conn').setLevel(log_level)
|
||||||
logging.getLogger('data').setLevel(log_level)
|
logging.getLogger('data').setLevel(log_level)
|
||||||
logging.getLogger('tracer').setLevel(log_level)
|
logging.getLogger('tracer').setLevel(log_level)
|
||||||
logging.getLogger('asyncio').setLevel(log_level)
|
logging.getLogger('asyncio').setLevel(log_level)
|
||||||
# logging.getLogger('mqtt').setLevel(log_level)
|
# logging.getLogger('mqtt').setLevel(log_level)
|
||||||
|
|
||||||
loop = asyncio.new_event_loop()
|
loop = asyncio.new_event_loop()
|
||||||
asyncio.set_event_loop(loop)
|
asyncio.set_event_loop(loop)
|
||||||
|
|
||||||
# read config file
|
# read config file
|
||||||
Config.init(ConfigReadToml(src_dir + "cnf/default_config.toml"))
|
Config.init(ConfigReadToml("default_config.toml"))
|
||||||
ConfigReadEnv()
|
ConfigReadEnv()
|
||||||
ConfigReadJson(args.config_path + "config.json")
|
ConfigReadJson(args.config_path + "config.json")
|
||||||
ConfigReadToml(args.config_path + "config.toml")
|
ConfigReadToml(args.config_path + "config.toml")
|
||||||
|
|||||||
@@ -76,7 +76,7 @@ def ConfigDefault():
|
|||||||
'type': 'RSM40-8-395M'},
|
'type': 'RSM40-8-395M'},
|
||||||
'pv2': {'manufacturer': 'Risen',
|
'pv2': {'manufacturer': 'Risen',
|
||||||
'type': 'RSM40-8-395M'},
|
'type': 'RSM40-8-395M'},
|
||||||
'sensor_list': 0
|
'sensor_list': 688
|
||||||
},
|
},
|
||||||
'Y170000000000001': {
|
'Y170000000000001': {
|
||||||
'modbus_polling': True,
|
'modbus_polling': True,
|
||||||
@@ -91,21 +91,8 @@ def ConfigDefault():
|
|||||||
'type': 'RSM40-8-410M'},
|
'type': 'RSM40-8-410M'},
|
||||||
'pv4': {'manufacturer': 'Risen',
|
'pv4': {'manufacturer': 'Risen',
|
||||||
'type': 'RSM40-8-410M'},
|
'type': 'RSM40-8-410M'},
|
||||||
'sensor_list': 0
|
'sensor_list': 688
|
||||||
}
|
}
|
||||||
},
|
|
||||||
'batteries': {
|
|
||||||
'4100000000000001': {
|
|
||||||
'modbus_polling': True,
|
|
||||||
'monitor_sn': 3000000000,
|
|
||||||
'suggested_area': '',
|
|
||||||
'node_id': '',
|
|
||||||
'pv1': {'manufacturer': 'Risen',
|
|
||||||
'type': 'RSM40-8-410M'},
|
|
||||||
'pv2': {'manufacturer': 'Risen',
|
|
||||||
'type': 'RSM40-8-410M'},
|
|
||||||
'sensor_list': 0,
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -152,49 +139,14 @@ def ConfigComplete():
|
|||||||
'pv4': {'manufacturer': 'man4',
|
'pv4': {'manufacturer': 'man4',
|
||||||
'type': 'type4'},
|
'type': 'type4'},
|
||||||
'suggested_area': 'Garage2',
|
'suggested_area': 'Garage2',
|
||||||
'sensor_list': 688},
|
|
||||||
'Y170000000000002': {'modbus_polling': False,
|
|
||||||
'modbus_scanning': {
|
|
||||||
'bytes': 16,
|
|
||||||
'start': 2048,
|
|
||||||
'step': 1024
|
|
||||||
},
|
|
||||||
'monitor_sn': 2000000001,
|
|
||||||
'node_id': 'PV-Garage3/',
|
|
||||||
'suggested_area': 'Garage3',
|
|
||||||
'sensor_list': 688}
|
'sensor_list': 688}
|
||||||
},
|
|
||||||
'batteries': {
|
|
||||||
'4100000000000001': {
|
|
||||||
'modbus_polling': True,
|
|
||||||
'monitor_sn': 3000000000,
|
|
||||||
'suggested_area': 'Garage3',
|
|
||||||
'node_id': 'Bat-Garage3/',
|
|
||||||
'pv1': {'manufacturer': 'man5',
|
|
||||||
'type': 'type5'},
|
|
||||||
'pv2': {'manufacturer': 'man6',
|
|
||||||
'type': 'type6'},
|
|
||||||
'sensor_list': 12326}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
def test_default_config():
|
def test_default_config():
|
||||||
Config.init(ConfigReadToml("app/src/cnf/default_config.toml"))
|
Config.init(ConfigReadToml("app/config/default_config.toml"))
|
||||||
validated = Config.def_config
|
validated = Config.def_config
|
||||||
assert validated == {'gen3plus': {'at_acl': {'mqtt': {'allow': ['AT+'], 'block': []}, 'tsun': {'allow': ['AT+Z', 'AT+UPURL', 'AT+SUPDATE'], 'block': []}}}, 'tsun': {'enabled': True, 'host': 'logger.talent-monitoring.com', 'port': 5005}, 'solarman': {'enabled': True, 'host': 'iot.talent-monitoring.com', 'port': 10000}, 'mqtt': {'host': 'mqtt', 'port': 1883, 'user': None, 'passwd': None}, 'ha': {'auto_conf_prefix': 'homeassistant', 'discovery_prefix': 'homeassistant', 'entity_prefix': 'tsun', 'proxy_node_id': 'proxy', 'proxy_unique_id': 'P170000000000001'},
|
assert validated == {'gen3plus': {'at_acl': {'mqtt': {'allow': ['AT+'], 'block': []}, 'tsun': {'allow': ['AT+Z', 'AT+UPURL', 'AT+SUPDATE'], 'block': []}}}, 'tsun': {'enabled': True, 'host': 'logger.talent-monitoring.com', 'port': 5005}, 'solarman': {'enabled': True, 'host': 'iot.talent-monitoring.com', 'port': 10000}, 'mqtt': {'host': 'mqtt', 'port': 1883, 'user': None, 'passwd': None}, 'ha': {'auto_conf_prefix': 'homeassistant', 'discovery_prefix': 'homeassistant', 'entity_prefix': 'tsun', 'proxy_node_id': 'proxy', 'proxy_unique_id': 'P170000000000001'},
|
||||||
'batteries': {
|
|
||||||
'4100000000000001': {
|
|
||||||
'modbus_polling': True,
|
|
||||||
'monitor_sn': 3000000000,
|
|
||||||
'node_id': '',
|
|
||||||
'pv1': {'manufacturer': 'Risen',
|
|
||||||
'type': 'RSM40-8-410M'},
|
|
||||||
'pv2': {'manufacturer': 'Risen',
|
|
||||||
'type': 'RSM40-8-410M'},
|
|
||||||
'sensor_list': 0,
|
|
||||||
'suggested_area': ''
|
|
||||||
}
|
|
||||||
},
|
|
||||||
'inverters': {
|
'inverters': {
|
||||||
'allow_all': False,
|
'allow_all': False,
|
||||||
'R170000000000001': {
|
'R170000000000001': {
|
||||||
@@ -206,7 +158,7 @@ def test_default_config():
|
|||||||
'modbus_polling': False,
|
'modbus_polling': False,
|
||||||
'monitor_sn': 0,
|
'monitor_sn': 0,
|
||||||
'suggested_area': '',
|
'suggested_area': '',
|
||||||
'sensor_list': 0},
|
'sensor_list': 688},
|
||||||
'Y170000000000001': {
|
'Y170000000000001': {
|
||||||
'modbus_polling': True,
|
'modbus_polling': True,
|
||||||
'monitor_sn': 2000000000,
|
'monitor_sn': 2000000000,
|
||||||
@@ -220,7 +172,7 @@ def test_default_config():
|
|||||||
'pv4': {'manufacturer': 'Risen',
|
'pv4': {'manufacturer': 'Risen',
|
||||||
'type': 'RSM40-8-410M'},
|
'type': 'RSM40-8-410M'},
|
||||||
'suggested_area': '',
|
'suggested_area': '',
|
||||||
'sensor_list': 0}}}
|
'sensor_list': 688}}}
|
||||||
|
|
||||||
def test_full_config(ConfigComplete):
|
def test_full_config(ConfigComplete):
|
||||||
cnf = {'tsun': {'enabled': True, 'host': 'logger.talent-monitoring.com', 'port': 5005},
|
cnf = {'tsun': {'enabled': True, 'host': 'logger.talent-monitoring.com', 'port': 5005},
|
||||||
@@ -229,15 +181,9 @@ def test_full_config(ConfigComplete):
|
|||||||
'solarman': {'enabled': True, 'host': 'iot.talent-monitoring.com', 'port': 10000},
|
'solarman': {'enabled': True, 'host': 'iot.talent-monitoring.com', 'port': 10000},
|
||||||
'mqtt': {'host': 'mqtt', 'port': 1883, 'user': '', 'passwd': ''},
|
'mqtt': {'host': 'mqtt', 'port': 1883, 'user': '', 'passwd': ''},
|
||||||
'ha': {'auto_conf_prefix': 'homeassistant', 'discovery_prefix': 'homeassistant', 'entity_prefix': 'tsun', 'proxy_node_id': 'proxy', 'proxy_unique_id': 'P170000000000001'},
|
'ha': {'auto_conf_prefix': 'homeassistant', 'discovery_prefix': 'homeassistant', 'entity_prefix': 'tsun', 'proxy_node_id': 'proxy', 'proxy_unique_id': 'P170000000000001'},
|
||||||
'batteries': {
|
|
||||||
'4100000000000001': {'modbus_polling': True, 'monitor_sn': 3000000000, 'node_id': 'Bat-Garage3/', 'sensor_list': 0x3026, 'suggested_area': 'Garage3', 'pv1': {'type': 'type5', 'manufacturer': 'man5'}, 'pv2': {'type': 'type6', 'manufacturer': 'man6'}}
|
|
||||||
},
|
|
||||||
'inverters': {'allow_all': False,
|
'inverters': {'allow_all': False,
|
||||||
'R170000000000001': {'modbus_polling': False, 'node_id': 'PV-Garage/', 'sensor_list': 0x02B0, 'suggested_area': 'Garage', 'pv1': {'type': 'type1', 'manufacturer': 'man1'}, 'pv2': {'type': 'type2', 'manufacturer': 'man2'}},
|
'R170000000000001': {'modbus_polling': False, 'node_id': 'PV-Garage/', 'sensor_list': 0x02B0, 'suggested_area': 'Garage', 'pv1': {'type': 'type1', 'manufacturer': 'man1'}, 'pv2': {'type': 'type2', 'manufacturer': 'man2'}},
|
||||||
'Y170000000000001': {'modbus_polling': True, 'monitor_sn': 2000000000, 'node_id': 'PV-Garage2/', 'sensor_list': 0x02B0, 'suggested_area': 'Garage2', 'pv1': {'type': 'type1', 'manufacturer': 'man1'}, 'pv2': {'type': 'type2', 'manufacturer': 'man2'}, 'pv3': {'type': 'type3', 'manufacturer': 'man3'}, 'pv4': {'type': 'type4', 'manufacturer': 'man4'}},
|
'Y170000000000001': {'modbus_polling': True, 'monitor_sn': 2000000000, 'node_id': 'PV-Garage2/', 'sensor_list': 0x02B0, 'suggested_area': 'Garage2', 'pv1': {'type': 'type1', 'manufacturer': 'man1'}, 'pv2': {'type': 'type2', 'manufacturer': 'man2'}, 'pv3': {'type': 'type3', 'manufacturer': 'man3'}, 'pv4': {'type': 'type4', 'manufacturer': 'man4'}}}}
|
||||||
'Y170000000000002': {'modbus_polling': False, 'monitor_sn': 2000000001, 'node_id': 'PV-Garage3/', 'sensor_list': 0x02B0, 'suggested_area': 'Garage3', 'modbus_scanning': {'start': 2048, 'step': 1024, 'bytes': 16}}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
try:
|
try:
|
||||||
validated = Config.conf_schema.validate(cnf)
|
validated = Config.conf_schema.validate(cnf)
|
||||||
except Exception:
|
except Exception:
|
||||||
@@ -247,7 +193,7 @@ def test_full_config(ConfigComplete):
|
|||||||
def test_read_empty(ConfigDefault):
|
def test_read_empty(ConfigDefault):
|
||||||
test_buffer.rd = ""
|
test_buffer.rd = ""
|
||||||
|
|
||||||
Config.init(ConfigReadToml("app/src/cnf/default_config.toml"))
|
Config.init(ConfigReadToml("app/config/default_config.toml"))
|
||||||
for _ in patch_open():
|
for _ in patch_open():
|
||||||
ConfigReadToml("config/config.toml")
|
ConfigReadToml("config/config.toml")
|
||||||
err = Config.get_error()
|
err = Config.get_error()
|
||||||
@@ -270,14 +216,14 @@ def test_no_file():
|
|||||||
assert defcnf == None
|
assert defcnf == None
|
||||||
|
|
||||||
def test_no_file2():
|
def test_no_file2():
|
||||||
Config.init(ConfigReadToml("app/src/cnf/default_config.toml"))
|
Config.init(ConfigReadToml("app/config/default_config.toml"))
|
||||||
assert Config.err == None
|
assert Config.err == None
|
||||||
ConfigReadToml("_no__file__no_")
|
ConfigReadToml("_no__file__no_")
|
||||||
err = Config.get_error()
|
err = Config.get_error()
|
||||||
assert err == None
|
assert err == None
|
||||||
|
|
||||||
def test_invalid_filename():
|
def test_invalid_filename():
|
||||||
Config.init(ConfigReadToml("app/src/cnf/default_config.toml"))
|
Config.init(ConfigReadToml("app/config/default_config.toml"))
|
||||||
assert Config.err == None
|
assert Config.err == None
|
||||||
ConfigReadToml(None)
|
ConfigReadToml(None)
|
||||||
err = Config.get_error()
|
err = Config.get_error()
|
||||||
@@ -286,7 +232,7 @@ def test_invalid_filename():
|
|||||||
def test_read_cnf1():
|
def test_read_cnf1():
|
||||||
test_buffer.rd = "solarman.enabled = false"
|
test_buffer.rd = "solarman.enabled = false"
|
||||||
|
|
||||||
Config.init(ConfigReadToml("app/src/cnf/default_config.toml"))
|
Config.init(ConfigReadToml("app/config/default_config.toml"))
|
||||||
for _ in patch_open():
|
for _ in patch_open():
|
||||||
ConfigReadToml("config/config.toml")
|
ConfigReadToml("config/config.toml")
|
||||||
err = Config.get_error()
|
err = Config.get_error()
|
||||||
@@ -294,19 +240,6 @@ def test_read_cnf1():
|
|||||||
assert err == None
|
assert err == None
|
||||||
cnf = Config.get()
|
cnf = Config.get()
|
||||||
assert cnf == {'gen3plus': {'at_acl': {'mqtt': {'allow': ['AT+'], 'block': []}, 'tsun': {'allow': ['AT+Z', 'AT+UPURL', 'AT+SUPDATE'], 'block': []}}}, 'tsun': {'enabled': True, 'host': 'logger.talent-monitoring.com', 'port': 5005}, 'solarman': {'enabled': False, 'host': 'iot.talent-monitoring.com', 'port': 10000}, 'mqtt': {'host': 'mqtt', 'port': 1883, 'user': None, 'passwd': None}, 'ha': {'auto_conf_prefix': 'homeassistant', 'discovery_prefix': 'homeassistant', 'entity_prefix': 'tsun', 'proxy_node_id': 'proxy', 'proxy_unique_id': 'P170000000000001'},
|
assert cnf == {'gen3plus': {'at_acl': {'mqtt': {'allow': ['AT+'], 'block': []}, 'tsun': {'allow': ['AT+Z', 'AT+UPURL', 'AT+SUPDATE'], 'block': []}}}, 'tsun': {'enabled': True, 'host': 'logger.talent-monitoring.com', 'port': 5005}, 'solarman': {'enabled': False, 'host': 'iot.talent-monitoring.com', 'port': 10000}, 'mqtt': {'host': 'mqtt', 'port': 1883, 'user': None, 'passwd': None}, 'ha': {'auto_conf_prefix': 'homeassistant', 'discovery_prefix': 'homeassistant', 'entity_prefix': 'tsun', 'proxy_node_id': 'proxy', 'proxy_unique_id': 'P170000000000001'},
|
||||||
'batteries': {
|
|
||||||
'4100000000000001': {
|
|
||||||
'modbus_polling': True,
|
|
||||||
'monitor_sn': 3000000000,
|
|
||||||
'node_id': '',
|
|
||||||
'pv1': {'manufacturer': 'Risen',
|
|
||||||
'type': 'RSM40-8-410M'},
|
|
||||||
'pv2': {'manufacturer': 'Risen',
|
|
||||||
'type': 'RSM40-8-410M'},
|
|
||||||
'sensor_list': 0,
|
|
||||||
'suggested_area': ''
|
|
||||||
}
|
|
||||||
},
|
|
||||||
'inverters': {
|
'inverters': {
|
||||||
'allow_all': False,
|
'allow_all': False,
|
||||||
'R170000000000001': {
|
'R170000000000001': {
|
||||||
@@ -318,7 +251,7 @@ def test_read_cnf1():
|
|||||||
'type': 'RSM40-8-395M'},
|
'type': 'RSM40-8-395M'},
|
||||||
'pv2': {'manufacturer': 'Risen',
|
'pv2': {'manufacturer': 'Risen',
|
||||||
'type': 'RSM40-8-395M'},
|
'type': 'RSM40-8-395M'},
|
||||||
'sensor_list': 0
|
'sensor_list': 688
|
||||||
},
|
},
|
||||||
'Y170000000000001': {
|
'Y170000000000001': {
|
||||||
'modbus_polling': True,
|
'modbus_polling': True,
|
||||||
@@ -333,7 +266,7 @@ def test_read_cnf1():
|
|||||||
'type': 'RSM40-8-410M'},
|
'type': 'RSM40-8-410M'},
|
||||||
'pv4': {'manufacturer': 'Risen',
|
'pv4': {'manufacturer': 'Risen',
|
||||||
'type': 'RSM40-8-410M'},
|
'type': 'RSM40-8-410M'},
|
||||||
'sensor_list': 0
|
'sensor_list': 688
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -346,7 +279,7 @@ def test_read_cnf1():
|
|||||||
def test_read_cnf2():
|
def test_read_cnf2():
|
||||||
test_buffer.rd = "solarman.enabled = 'FALSE'"
|
test_buffer.rd = "solarman.enabled = 'FALSE'"
|
||||||
|
|
||||||
Config.init(ConfigReadToml("app/src/cnf/default_config.toml"))
|
Config.init(ConfigReadToml("app/config/default_config.toml"))
|
||||||
for _ in patch_open():
|
for _ in patch_open():
|
||||||
ConfigReadToml("config/config.toml")
|
ConfigReadToml("config/config.toml")
|
||||||
err = Config.get_error()
|
err = Config.get_error()
|
||||||
@@ -354,19 +287,6 @@ def test_read_cnf2():
|
|||||||
assert err == None
|
assert err == None
|
||||||
cnf = Config.get()
|
cnf = Config.get()
|
||||||
assert cnf == {'gen3plus': {'at_acl': {'mqtt': {'allow': ['AT+'], 'block': []}, 'tsun': {'allow': ['AT+Z', 'AT+UPURL', 'AT+SUPDATE'], 'block': []}}}, 'tsun': {'enabled': True, 'host': 'logger.talent-monitoring.com', 'port': 5005}, 'solarman': {'enabled': True, 'host': 'iot.talent-monitoring.com', 'port': 10000}, 'mqtt': {'host': 'mqtt', 'port': 1883, 'user': None, 'passwd': None}, 'ha': {'auto_conf_prefix': 'homeassistant', 'discovery_prefix': 'homeassistant', 'entity_prefix': 'tsun', 'proxy_node_id': 'proxy', 'proxy_unique_id': 'P170000000000001'},
|
assert cnf == {'gen3plus': {'at_acl': {'mqtt': {'allow': ['AT+'], 'block': []}, 'tsun': {'allow': ['AT+Z', 'AT+UPURL', 'AT+SUPDATE'], 'block': []}}}, 'tsun': {'enabled': True, 'host': 'logger.talent-monitoring.com', 'port': 5005}, 'solarman': {'enabled': True, 'host': 'iot.talent-monitoring.com', 'port': 10000}, 'mqtt': {'host': 'mqtt', 'port': 1883, 'user': None, 'passwd': None}, 'ha': {'auto_conf_prefix': 'homeassistant', 'discovery_prefix': 'homeassistant', 'entity_prefix': 'tsun', 'proxy_node_id': 'proxy', 'proxy_unique_id': 'P170000000000001'},
|
||||||
'batteries': {
|
|
||||||
'4100000000000001': {
|
|
||||||
'modbus_polling': True,
|
|
||||||
'monitor_sn': 3000000000,
|
|
||||||
'node_id': '',
|
|
||||||
'pv1': {'manufacturer': 'Risen',
|
|
||||||
'type': 'RSM40-8-410M'},
|
|
||||||
'pv2': {'manufacturer': 'Risen',
|
|
||||||
'type': 'RSM40-8-410M'},
|
|
||||||
'sensor_list': 0,
|
|
||||||
'suggested_area': ''
|
|
||||||
}
|
|
||||||
},
|
|
||||||
'inverters': {
|
'inverters': {
|
||||||
'allow_all': False,
|
'allow_all': False,
|
||||||
'R170000000000001': {
|
'R170000000000001': {
|
||||||
@@ -378,7 +298,7 @@ def test_read_cnf2():
|
|||||||
'type': 'RSM40-8-395M'},
|
'type': 'RSM40-8-395M'},
|
||||||
'pv2': {'manufacturer': 'Risen',
|
'pv2': {'manufacturer': 'Risen',
|
||||||
'type': 'RSM40-8-395M'},
|
'type': 'RSM40-8-395M'},
|
||||||
'sensor_list': 0
|
'sensor_list': 688
|
||||||
},
|
},
|
||||||
'Y170000000000001': {
|
'Y170000000000001': {
|
||||||
'modbus_polling': True,
|
'modbus_polling': True,
|
||||||
@@ -393,7 +313,7 @@ def test_read_cnf2():
|
|||||||
'type': 'RSM40-8-410M'},
|
'type': 'RSM40-8-410M'},
|
||||||
'pv4': {'manufacturer': 'Risen',
|
'pv4': {'manufacturer': 'Risen',
|
||||||
'type': 'RSM40-8-410M'},
|
'type': 'RSM40-8-410M'},
|
||||||
'sensor_list': 0
|
'sensor_list': 688
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -402,7 +322,7 @@ def test_read_cnf2():
|
|||||||
def test_read_cnf3(ConfigDefault):
|
def test_read_cnf3(ConfigDefault):
|
||||||
test_buffer.rd = "solarman.port = 'FALSE'"
|
test_buffer.rd = "solarman.port = 'FALSE'"
|
||||||
|
|
||||||
Config.init(ConfigReadToml("app/src/cnf/default_config.toml"))
|
Config.init(ConfigReadToml("app/config/default_config.toml"))
|
||||||
for _ in patch_open():
|
for _ in patch_open():
|
||||||
ConfigReadToml("config/config.toml")
|
ConfigReadToml("config/config.toml")
|
||||||
err = Config.get_error()
|
err = Config.get_error()
|
||||||
@@ -414,7 +334,7 @@ def test_read_cnf3(ConfigDefault):
|
|||||||
def test_read_cnf4():
|
def test_read_cnf4():
|
||||||
test_buffer.rd = "solarman.port = 5000"
|
test_buffer.rd = "solarman.port = 5000"
|
||||||
|
|
||||||
Config.init(ConfigReadToml("app/src/cnf/default_config.toml"))
|
Config.init(ConfigReadToml("app/config/default_config.toml"))
|
||||||
for _ in patch_open():
|
for _ in patch_open():
|
||||||
ConfigReadToml("config/config.toml")
|
ConfigReadToml("config/config.toml")
|
||||||
err = Config.get_error()
|
err = Config.get_error()
|
||||||
@@ -422,19 +342,6 @@ def test_read_cnf4():
|
|||||||
assert err == None
|
assert err == None
|
||||||
cnf = Config.get()
|
cnf = Config.get()
|
||||||
assert cnf == {'gen3plus': {'at_acl': {'mqtt': {'allow': ['AT+'], 'block': []}, 'tsun': {'allow': ['AT+Z', 'AT+UPURL', 'AT+SUPDATE'], 'block': []}}}, 'tsun': {'enabled': True, 'host': 'logger.talent-monitoring.com', 'port': 5005}, 'solarman': {'enabled': True, 'host': 'iot.talent-monitoring.com', 'port': 5000}, 'mqtt': {'host': 'mqtt', 'port': 1883, 'user': None, 'passwd': None}, 'ha': {'auto_conf_prefix': 'homeassistant', 'discovery_prefix': 'homeassistant', 'entity_prefix': 'tsun', 'proxy_node_id': 'proxy', 'proxy_unique_id': 'P170000000000001'},
|
assert cnf == {'gen3plus': {'at_acl': {'mqtt': {'allow': ['AT+'], 'block': []}, 'tsun': {'allow': ['AT+Z', 'AT+UPURL', 'AT+SUPDATE'], 'block': []}}}, 'tsun': {'enabled': True, 'host': 'logger.talent-monitoring.com', 'port': 5005}, 'solarman': {'enabled': True, 'host': 'iot.talent-monitoring.com', 'port': 5000}, 'mqtt': {'host': 'mqtt', 'port': 1883, 'user': None, 'passwd': None}, 'ha': {'auto_conf_prefix': 'homeassistant', 'discovery_prefix': 'homeassistant', 'entity_prefix': 'tsun', 'proxy_node_id': 'proxy', 'proxy_unique_id': 'P170000000000001'},
|
||||||
'batteries': {
|
|
||||||
'4100000000000001': {
|
|
||||||
'modbus_polling': True,
|
|
||||||
'monitor_sn': 3000000000,
|
|
||||||
'node_id': '',
|
|
||||||
'pv1': {'manufacturer': 'Risen',
|
|
||||||
'type': 'RSM40-8-410M'},
|
|
||||||
'pv2': {'manufacturer': 'Risen',
|
|
||||||
'type': 'RSM40-8-410M'},
|
|
||||||
'sensor_list': 0,
|
|
||||||
'suggested_area': ''
|
|
||||||
}
|
|
||||||
},
|
|
||||||
'inverters': {
|
'inverters': {
|
||||||
'allow_all': False,
|
'allow_all': False,
|
||||||
'R170000000000001': {
|
'R170000000000001': {
|
||||||
@@ -446,7 +353,7 @@ def test_read_cnf4():
|
|||||||
'type': 'RSM40-8-395M'},
|
'type': 'RSM40-8-395M'},
|
||||||
'pv2': {'manufacturer': 'Risen',
|
'pv2': {'manufacturer': 'Risen',
|
||||||
'type': 'RSM40-8-395M'},
|
'type': 'RSM40-8-395M'},
|
||||||
'sensor_list': 0
|
'sensor_list': 688
|
||||||
},
|
},
|
||||||
'Y170000000000001': {
|
'Y170000000000001': {
|
||||||
'modbus_polling': True,
|
'modbus_polling': True,
|
||||||
@@ -461,7 +368,7 @@ def test_read_cnf4():
|
|||||||
'type': 'RSM40-8-410M'},
|
'type': 'RSM40-8-410M'},
|
||||||
'pv4': {'manufacturer': 'Risen',
|
'pv4': {'manufacturer': 'Risen',
|
||||||
'type': 'RSM40-8-410M'},
|
'type': 'RSM40-8-410M'},
|
||||||
'sensor_list': 0
|
'sensor_list': 688
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -470,7 +377,7 @@ def test_read_cnf4():
|
|||||||
def test_read_cnf5():
|
def test_read_cnf5():
|
||||||
test_buffer.rd = "solarman.port = 1023"
|
test_buffer.rd = "solarman.port = 1023"
|
||||||
|
|
||||||
Config.init(ConfigReadToml("app/src/cnf/default_config.toml"))
|
Config.init(ConfigReadToml("app/config/default_config.toml"))
|
||||||
for _ in patch_open():
|
for _ in patch_open():
|
||||||
ConfigReadToml("config/config.toml")
|
ConfigReadToml("config/config.toml")
|
||||||
err = Config.get_error()
|
err = Config.get_error()
|
||||||
@@ -479,7 +386,7 @@ def test_read_cnf5():
|
|||||||
def test_read_cnf6():
|
def test_read_cnf6():
|
||||||
test_buffer.rd = "solarman.port = 65536"
|
test_buffer.rd = "solarman.port = 65536"
|
||||||
|
|
||||||
Config.init(ConfigReadToml("app/src/cnf/default_config.toml"))
|
Config.init(ConfigReadToml("app/config/default_config.toml"))
|
||||||
for _ in patch_open():
|
for _ in patch_open():
|
||||||
ConfigReadToml("config/config.toml")
|
ConfigReadToml("config/config.toml")
|
||||||
err = Config.get_error()
|
err = Config.get_error()
|
||||||
|
|||||||
@@ -44,7 +44,7 @@ def test_extend_key():
|
|||||||
assert conf == {'': 'testuser'}
|
assert conf == {'': 'testuser'}
|
||||||
|
|
||||||
def test_read_env_config():
|
def test_read_env_config():
|
||||||
Config.init(ConfigReadToml("app/src/cnf/default_config.toml"))
|
Config.init(ConfigReadToml("app/config/default_config.toml"))
|
||||||
assert Config.get('mqtt') == {'host': 'mqtt', 'port': 1883, 'user': None, 'passwd': None}
|
assert Config.get('mqtt') == {'host': 'mqtt', 'port': 1883, 'user': None, 'passwd': None}
|
||||||
for _ in patch_getenv():
|
for _ in patch_getenv():
|
||||||
|
|
||||||
|
|||||||
@@ -84,7 +84,7 @@ def ConfigTomlEmpty():
|
|||||||
def test_no_config(ConfigDefault):
|
def test_no_config(ConfigDefault):
|
||||||
test_buffer.rd = "" # empty buffer, no json
|
test_buffer.rd = "" # empty buffer, no json
|
||||||
|
|
||||||
Config.init(ConfigReadToml("app/src/cnf/default_config.toml"))
|
Config.init(ConfigReadToml("app/config/default_config.toml"))
|
||||||
for _ in patch_open():
|
for _ in patch_open():
|
||||||
ConfigReadJson()
|
ConfigReadJson()
|
||||||
err = Config.get_error()
|
err = Config.get_error()
|
||||||
@@ -96,7 +96,7 @@ def test_no_config(ConfigDefault):
|
|||||||
def test_no_file(ConfigDefault):
|
def test_no_file(ConfigDefault):
|
||||||
test_buffer.rd = "" # empty buffer, no json
|
test_buffer.rd = "" # empty buffer, no json
|
||||||
|
|
||||||
Config.init(ConfigReadToml("app/src/cnf/default_config.toml"))
|
Config.init(ConfigReadToml("app/config/default_config.toml"))
|
||||||
for _ in patch_open():
|
for _ in patch_open():
|
||||||
ConfigReadJson("_no__file__no_")
|
ConfigReadJson("_no__file__no_")
|
||||||
err = Config.get_error()
|
err = Config.get_error()
|
||||||
@@ -108,7 +108,7 @@ def test_no_file(ConfigDefault):
|
|||||||
def test_invalid_filename(ConfigDefault):
|
def test_invalid_filename(ConfigDefault):
|
||||||
test_buffer.rd = "" # empty buffer, no json
|
test_buffer.rd = "" # empty buffer, no json
|
||||||
|
|
||||||
Config.init(ConfigReadToml("app/src/cnf/default_config.toml"))
|
Config.init(ConfigReadToml("app/config/default_config.toml"))
|
||||||
for _ in patch_open():
|
for _ in patch_open():
|
||||||
ConfigReadJson(None)
|
ConfigReadJson(None)
|
||||||
err = Config.get_error()
|
err = Config.get_error()
|
||||||
@@ -340,7 +340,7 @@ def test_cnv6():
|
|||||||
def test_empty_config(ConfigDefault):
|
def test_empty_config(ConfigDefault):
|
||||||
test_buffer.rd = "{}" # empty json
|
test_buffer.rd = "{}" # empty json
|
||||||
|
|
||||||
Config.init(ConfigReadToml("app/src/cnf/default_config.toml"))
|
Config.init(ConfigReadToml("app/config/default_config.toml"))
|
||||||
for _ in patch_open():
|
for _ in patch_open():
|
||||||
ConfigReadJson()
|
ConfigReadJson()
|
||||||
err = Config.get_error()
|
err = Config.get_error()
|
||||||
@@ -380,29 +380,6 @@ def test_full_config(ConfigComplete):
|
|||||||
"pv4.manufacturer": "man4",
|
"pv4.manufacturer": "man4",
|
||||||
"pv4.type": "type4",
|
"pv4.type": "type4",
|
||||||
"sensor_list": 688
|
"sensor_list": 688
|
||||||
},
|
|
||||||
{
|
|
||||||
"serial": "Y170000000000002",
|
|
||||||
"monitor_sn": 2000000001,
|
|
||||||
"modbus_polling": false,
|
|
||||||
"modbus_scanning.start": 2048,
|
|
||||||
"node_id": "PV-Garage3",
|
|
||||||
"suggested_area": "Garage3",
|
|
||||||
"sensor_list": 688
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"batteries": [
|
|
||||||
{
|
|
||||||
"serial": "4100000000000001",
|
|
||||||
"modbus_polling": true,
|
|
||||||
"monitor_sn": 3000000000,
|
|
||||||
"node_id": "Bat-Garage3",
|
|
||||||
"suggested_area": "Garage3",
|
|
||||||
"pv1.manufacturer": "man5",
|
|
||||||
"pv1.type": "type5",
|
|
||||||
"pv2.manufacturer": "man6",
|
|
||||||
"pv2.type": "type6",
|
|
||||||
"sensor_list": 12326
|
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"tsun.enabled": true,
|
"tsun.enabled": true,
|
||||||
@@ -424,7 +401,7 @@ def test_full_config(ConfigComplete):
|
|||||||
]
|
]
|
||||||
}
|
}
|
||||||
"""
|
"""
|
||||||
Config.init(ConfigReadToml("app/src/cnf/default_config.toml"))
|
Config.init(ConfigReadToml("app/config/default_config.toml"))
|
||||||
for _ in patch_open():
|
for _ in patch_open():
|
||||||
ConfigReadJson()
|
ConfigReadJson()
|
||||||
err = Config.get_error()
|
err = Config.get_error()
|
||||||
|
|||||||
@@ -93,86 +93,6 @@ def contr2_data_seq(): # Get Time Request message
|
|||||||
msg += b'\x00\x00\x00'
|
msg += b'\x00\x00\x00'
|
||||||
return msg
|
return msg
|
||||||
|
|
||||||
@pytest.fixture
|
|
||||||
def contr3_data_seq(): # Get Time Request message
|
|
||||||
msg = b'\x00\x00\x00\x39\x00\x09\x2b\xa8\x54\x10\x52' # | ..^.....9..+.T.R
|
|
||||||
msg += b'\x53\x57\x5f\x34\x30\x30\x5f\x56\x32\x2e\x30\x31\x2e\x31\x33\x00' # | SW_400_V2.01.13.
|
|
||||||
msg += b'\x09\x27\xc0\x54\x06\x52\x61\x79\x6d\x6f\x6e\x00\x09\x2f\x90\x54' # | .'.T.Raymon../.T
|
|
||||||
msg += b'\x0b\x52\x53\x57\x2d\x31\x2d\x31\x30\x30\x30\x31\x00\x09\x5a\x88' # | .RSW-1-10001..Z.
|
|
||||||
msg += b'\x54\x0f\x74\x2e\x72\x61\x79\x6d\x6f\x6e\x69\x6f\x74\x2e\x63\x6f' # | T.t.raymoniot.co
|
|
||||||
msg += b'\x6d\x00\x09\x5a\xec\x54\x1c\x6c\x6f\x67\x67\x65\x72\x2e\x74\x61' # | m..Z.T.logger.ta
|
|
||||||
msg += b'\x6c\x65\x6e\x74\x2d\x6d\x6f\x6e\x69\x74\x6f\x72\x69\x6e\x67\x2e' # | lent-monitoring.
|
|
||||||
msg += b'\x63\x6f\x6d\x00\x0d\x2f\x00\x54\x10\xff\xff\xff\xff\xff\xff\xff' # | com../.T........
|
|
||||||
msg += b'\xff\xff\xff\xff\xff\xff\xff\xff\xff\x00\x0d\x32\xe8\x54\x10\xff' # | ...........2.T..
|
|
||||||
msg += b'\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\x00' # | ................
|
|
||||||
msg += b'\x0d\x36\xd0\x54\x10\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff' # | .6.T............
|
|
||||||
msg += b'\xff\xff\xff\xff\xff\x00\x0d\x3a\xb8\x54\x10\xff\xff\xff\xff\xff' # | .......:.T......
|
|
||||||
msg += b'\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\x00\x0d\x3e\xa0\x54' # | .............>.T
|
|
||||||
msg += b'\x10\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff' # | ................
|
|
||||||
msg += b'\xff\x00\x0d\x42\x88\x54\x10\xff\xff\xff\xff\xff\xff\xff\xff\xff' # | ...B.T..........
|
|
||||||
msg += b'\xff\xff\xff\xff\xff\xff\xff\x00\x0d\x46\x70\x54\x10\xff\xff\xff' # | .........FpT....
|
|
||||||
msg += b'\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\x00\x0d\x4a' # | ...............J
|
|
||||||
msg += b'\x58\x54\x10\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff' # | XT..............
|
|
||||||
msg += b'\xff\xff\xff\x00\x0d\x4e\x40\x54\x10\xff\xff\xff\xff\xff\xff\xff' # | .....N@T........
|
|
||||||
msg += b'\xff\xff\xff\xff\xff\xff\xff\xff\xff\x00\x0d\x52\x28\x54\x10\xff' # | ...........R(T..
|
|
||||||
msg += b'\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\x00' # | ................
|
|
||||||
msg += b'\x0d\x56\x10\x54\x10\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff' # | .V.T............
|
|
||||||
msg += b'\xff\xff\xff\xff\xff\x00\x0d\x59\xf8\x54\x10\xff\xff\xff\xff\xff' # | .......Y.T......
|
|
||||||
msg += b'\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\x00\x0d\x5d\xe0\x54' # | .............].T
|
|
||||||
msg += b'\x10\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff' # | ................
|
|
||||||
msg += b'\xff\x00\x0d\x61\xc8\x54\x10\xff\xff\xff\xff\xff\xff\xff\xff\xff' # | ...a.T..........
|
|
||||||
msg += b'\xff\xff\xff\xff\xff\xff\xff\x00\x0d\x65\xb0\x54\x10\xff\xff\xff' # | .........e.T....
|
|
||||||
msg += b'\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\x00\x0d\x69' # | ...............i
|
|
||||||
msg += b'\x98\x54\x10\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff' # | .T..............
|
|
||||||
msg += b'\xff\xff\xff\x00\x0d\x6d\x80\x54\x10\xff\xff\xff\xff\xff\xff\xff' # | .....m.T........
|
|
||||||
msg += b'\xff\xff\xff\xff\xff\xff\xff\xff\xff\x00\x0d\x71\x68\x54\x10\xff' # | ...........qhT..
|
|
||||||
msg += b'\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\x00' # | ................
|
|
||||||
msg += b'\x0d\x75\x50\x54\x10\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff' # | .uPT............
|
|
||||||
msg += b'\xff\xff\xff\xff\xff\x00\x0d\x79\x38\x54\x10\xff\xff\xff\xff\xff' # | .......y8T......
|
|
||||||
msg += b'\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\x00\x0d\x7d\x20\x54' # | .............} T
|
|
||||||
msg += b'\x10\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff' # | ................
|
|
||||||
msg += b'\xff\x00\x0d\x81\x08\x54\x10\xff\xff\xff\xff\xff\xff\xff\xff\xff' # | .....T..........
|
|
||||||
msg += b'\xff\xff\xff\xff\xff\xff\xff\x00\x0d\x84\xf0\x54\x10\xff\xff\xff' # | ...........T....
|
|
||||||
msg += b'\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\x00\x0d\x88' # | ................
|
|
||||||
msg += b'\xd8\x54\x10\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff' # | .T..............
|
|
||||||
msg += b'\xff\xff\xff\x00\x0d\x8c\xc0\x54\x10\xff\xff\xff\xff\xff\xff\xff' # | .......T........
|
|
||||||
msg += b'\xff\xff\xff\xff\xff\xff\xff\xff\xff\x00\x0d\x90\xa8\x54\x10\xff' # | .............T..
|
|
||||||
msg += b'\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\x00' # | ................
|
|
||||||
msg += b'\x0d\x94\x90\x54\x10\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff' # | ...T............
|
|
||||||
msg += b'\xff\xff\xff\xff\xff\x00\x0d\x98\x78\x54\x10\xff\xff\xff\xff\xff' # | ........xT......
|
|
||||||
msg += b'\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\x00\x0d\x9c\x60\x54' # | ..............`T
|
|
||||||
msg += b'\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff' # | ................
|
|
||||||
msg += b'\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff' # | ................
|
|
||||||
msg += b'\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff' # | ................
|
|
||||||
msg += b'\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff' # | ................
|
|
||||||
msg += b'\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff' # | ................
|
|
||||||
msg += b'\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff' # | ................
|
|
||||||
msg += b'\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff' # | ................
|
|
||||||
msg += b'\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff' # | ................
|
|
||||||
msg += b'\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff' # | ................
|
|
||||||
msg += b'\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff' # | ................
|
|
||||||
msg += b'\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff' # | ................
|
|
||||||
msg += b'\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff' # | ................
|
|
||||||
msg += b'\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff' # | ................
|
|
||||||
msg += b'\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff' # | ................
|
|
||||||
msg += b'\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff' # | ................
|
|
||||||
msg += b'\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff' # | ................
|
|
||||||
msg += b'\x00\x0d\x00\x20\x49\x00\x00\x00\x01\x00\x0c\x35\x00\x49\x00\x00' # | ... I......5.I..
|
|
||||||
msg += b'\x00\x62\x00\x0c\x96\xa8\x49\x00\x00\x01\x4f\x00\x0c\x7f\x38\x49' # | .b....I...O...8I
|
|
||||||
msg += b'\x00\x00\x00\x01\x00\x0c\xfc\x38\x49\x00\x00\x00\x01\x00\x0c\xf8' # | .......8I.......
|
|
||||||
msg += b'\x50\x49\x00\x00\x01\x2c\x00\x0c\x63\xe0\x49\x00\x00\x00\x00\x00' # | PI...,..c.I.....
|
|
||||||
msg += b'\x0c\x67\xc8\x49\x00\x00\x00\x00\x00\x0c\x50\x58\x49\x00\x00\x00' # | .g.I......PXI...
|
|
||||||
msg += b'\x01\x00\x09\x5e\x70\x49\x00\x00\x13\x8d\x00\x09\x5e\xd4\x49\x00' # | ...^pI......^.I.
|
|
||||||
msg += b'\x00\x13\x8d\x00\x09\x5b\x50\x49\x00\x00\x00\x02\x00\x0d\x04\x08' # | .....[PI........
|
|
||||||
msg += b'\x49\x00\x00\x00\x00\x00\x07\xa1\x84\x49\x00\x00\x00\x01\x00\x0c' # | I........I......
|
|
||||||
msg += b'\x50\x59\x49\x00\x00\x00\x2d\x00\x0d\x1f\x60\x49\x00\x00\x00\x00' # | PYI...-...`I....
|
|
||||||
msg += b'\x00\x0d\x23\x48\x49\xff\xff\xff\xff\x00\x0d\x27\x30\x49\xff\xff' # | ..#HI......'0I..
|
|
||||||
msg += b'\xff\xff\x00\x0d\x2b\x18\x4c\x00\x00\x00\x00\xff\xff\xff\xff\x00' # | ....+.L.........
|
|
||||||
msg += b'\x0c\xa2\x60\x49\x00\x00\x00\x00\x00\x0d\xa0\x48\x49\x00\x00\x00' # | ..`I.......HI...
|
|
||||||
msg += b'\x00\x00\x0d\xa4\x30\x49\x00\x00\x00\xff\x00\x0d\xa8\x18\x49\x00' # | ....0I........I.
|
|
||||||
msg += b'\x00\x00\xff'
|
|
||||||
return msg
|
|
||||||
|
|
||||||
@pytest.fixture
|
@pytest.fixture
|
||||||
def inv_data_seq(): # Data indication from the controller
|
def inv_data_seq(): # Data indication from the controller
|
||||||
msg = b'\x00\x00\x00\x06\x00\x00\x00\x0a\x54\x08\x4d\x69\x63\x72\x6f\x69\x6e\x76\x00\x00\x00\x14\x54\x04\x54\x53\x55\x4e\x00\x00\x00\x1E\x54\x07\x56\x35\x2e\x30\x2e\x31\x31\x00\x00\x00\x28'
|
msg = b'\x00\x00\x00\x06\x00\x00\x00\x0a\x54\x08\x4d\x69\x63\x72\x6f\x69\x6e\x76\x00\x00\x00\x14\x54\x04\x54\x53\x55\x4e\x00\x00\x00\x1E\x54\x07\x56\x35\x2e\x30\x2e\x31\x31\x00\x00\x00\x28'
|
||||||
@@ -220,153 +140,6 @@ def inv_data_seq2(): # Data indication from the controller
|
|||||||
msg += b'\x53\x00\x00'
|
msg += b'\x53\x00\x00'
|
||||||
return msg
|
return msg
|
||||||
|
|
||||||
@pytest.fixture
|
|
||||||
def inv_data_seq3(): # Inverter indication from MS-2000
|
|
||||||
|
|
||||||
msg = b'\x00\x00\x01\x2c\x00\x00\x00\x64\x53\x00\x00' # | ..^.....,...dS..
|
|
||||||
msg += b'\x00\x00\x00\xc8\x53\x44\x00\x00\x00\x01\x2c\x53\x00\x00\x00\x00' # | ....SD....,S....
|
|
||||||
msg += b'\x01\x90\x49\x00\x00\x00\x00\x00\x00\x01\x91\x53\x00\x00\x00\x00' # | ..I........S....
|
|
||||||
msg += b'\x01\x92\x53\x00\x00\x00\x00\x01\x93\x53\x00\x00\x00\x00\x01\x94' # | ..S......S......
|
|
||||||
msg += b'\x53\x00\x00\x00\x00\x01\x95\x53\x00\x00\x00\x00\x01\x96\x53\x00' # | S......S......S.
|
|
||||||
msg += b'\x00\x00\x00\x01\x97\x53\x00\x00\x00\x00\x01\x98\x53\x00\x00\x00' # | .....S......S...
|
|
||||||
msg += b'\x00\x01\x99\x53\x00\x00\x00\x00\x01\x9a\x53\x00\x00\x00\x00\x01' # | ...S......S.....
|
|
||||||
msg += b'\x9b\x53\x00\x00\x00\x00\x01\x9c\x53\x00\x00\x00\x00\x01\x9d\x53' # | .S......S......S
|
|
||||||
msg += b'\x00\x00\x00\x00\x01\x9e\x53\x00\x00\x00\x00\x01\x9f\x53\x00\x00' # | ......S......S..
|
|
||||||
msg += b'\x00\x00\x01\xa0\x53\x00\x00\x00\x00\x01\xf4\x49\x00\x00\x00\x00' # | ....S......I....
|
|
||||||
msg += b'\x00\x00\x01\xf5\x53\x00\x00\x00\x00\x01\xf6\x53\x00\x00\x00\x00' # | ....S......S....
|
|
||||||
msg += b'\x01\xf7\x53\x00\x00\x00\x00\x01\xf8\x53\x00\x00\x00\x00\x01\xf9' # | ..S......S......
|
|
||||||
msg += b'\x53\x00\x00\x00\x00\x01\xfa\x53\x00\x00\x00\x00\x01\xfb\x53\x00' # | S......S......S.
|
|
||||||
msg += b'\x00\x00\x00\x01\xfc\x53\x00\x00\x00\x00\x01\xfd\x53\x00\x00\x00' # | .....S......S...
|
|
||||||
msg += b'\x00\x01\xfe\x53\x00\x00\x00\x00\x01\xff\x53\x00\x00\x00\x00\x02' # | ...S......S.....
|
|
||||||
msg += b'\x00\x53\x00\x00\x00\x00\x02\x01\x53\x00\x00\x00\x00\x02\x02\x53' # | .S......S......S
|
|
||||||
msg += b'\x00\x00\x00\x00\x02\x03\x53\x00\x00\x00\x00\x02\x04\x53\x00\x00' # | ......S......S..
|
|
||||||
msg += b'\x00\x00\x02\x58\x49\x00\x00\x00\x00\x00\x00\x02\x59\x53\x00\x00' # | ...XI.......YS..
|
|
||||||
msg += b'\x00\x00\x02\x5a\x53\x00\x00\x00\x00\x02\x5b\x53\x00\x00\x00\x00' # | ...ZS.....[S....
|
|
||||||
msg += b'\x02\x5c\x53\x00\x00\x00\x00\x02\x5d\x53\x00\x00\x00\x00\x02\x5e' # | .\S.....]S.....^
|
|
||||||
msg += b'\x53\x00\x00\x00\x00\x02\x5f\x53\x00\x00\x00\x00\x02\x60\x53\x00' # | S....._S.....`S.
|
|
||||||
msg += b'\x00\x00\x00\x02\x61\x53\x00\x00\x00\x00\x02\x62\x53\x00\x00\x00' # | ....aS.....bS...
|
|
||||||
msg += b'\x00\x02\x63\x53\x00\x00\x00\x00\x02\x64\x53\x00\x00\x00\x00\x02' # | ..cS.....dS.....
|
|
||||||
msg += b'\x65\x53\x00\x00\x00\x00\x02\x66\x53\x00\x00\x00\x00\x02\x67\x53' # | eS.....fS.....gS
|
|
||||||
msg += b'\x00\x00\x00\x00\x02\x68\x53\x00\x00\x00\x00\x02\xbc\x49\x00\x00' # | .....hS......I..
|
|
||||||
msg += b'\x00\x00\x00\x00\x02\xbd\x53\x00\x00\x00\x00\x02\xbe\x53\x00\x00' # | ......S......S..
|
|
||||||
msg += b'\x00\x00\x02\xbf\x53\x00\x00\x00\x00\x02\xc0\x53\x00\x00\x00\x00' # | ....S......S....
|
|
||||||
msg += b'\x02\xc1\x53\x00\x00\x00\x00\x02\xc2\x53\x00\x00\x00\x00\x02\xc3' # | ..S......S......
|
|
||||||
msg += b'\x53\x00\x00\x00\x00\x02\xc4\x53\x00\x00\x00\x00\x02\xc5\x53\x00' # | S......S......S.
|
|
||||||
msg += b'\x00\x00\x00\x02\xc6\x53\x00\x00\x00\x00\x02\xc7\x53\x00\x00\x00' # | .....S......S...
|
|
||||||
msg += b'\x00\x02\xc8\x53\x00\x00\x00\x00\x02\xc9\x53\x00\x00\x00\x00\x02' # | ...S......S.....
|
|
||||||
msg += b'\xca\x53\x00\x00\x00\x00\x02\xcb\x53\x00\x00\x00\x00\x02\xcc\x53' # | .S......S......S
|
|
||||||
msg += b'\x00\x00\x00\x00\x03\x20\x53\x00\x01\x00\x00\x03\x84\x53\x11\x68' # | ..... S......S.h
|
|
||||||
msg += b'\x00\x00\x03\xe8\x46\x44\x23\xd1\xec\x00\x00\x04\x4c\x46\x43\xa3' # | ....FD#.....LFC.
|
|
||||||
msg += b'\xb3\x33\x00\x00\x04\xb0\x46\x00\x00\x00\x00\x00\x00\x05\x14\x46' # | .3....F........F
|
|
||||||
msg += b'\x43\x6e\x80\x00\x00\x00\x05\x78\x46\x3d\x4c\xcc\xcd\x00\x00\x05' # | Cn.....xF=L.....
|
|
||||||
msg += b'\xdc\x46\x00\x00\x00\x00\x00\x00\x06\x40\x46\x42\x48\x00\x00\x00' # | .F.......@FBH...
|
|
||||||
msg += b'\x00\x06\xa4\x53\x00\x03\x00\x00\x07\x08\x53\x00\x0c\x00\x00\x07' # | ...S......S.....
|
|
||||||
msg += b'\x6c\x53\x00\x50\x00\x00\x07\xd0\x46\x43\xa3\xb3\x33\x00\x00\x08' # | lS.P....FC..3...
|
|
||||||
msg += b'\x34\x53\x0b\xb8\x00\x00\x08\x98\x46\x00\x00\x00\x00\x00\x00\x08' # | 4S......F.......
|
|
||||||
msg += b'\xfc\x46\x00\x00\x00\x00\x00\x00\x09\x60\x46\x41\xee\xe1\x48\x00' # | .F.......`FA..H.
|
|
||||||
msg += b'\x00\x09\xc4\x53\x00\x00\x00\x00\x0a\x28\x46\x41\xf2\x00\x00\x00' # | ...S.....(FA....
|
|
||||||
msg += b'\x00\x0a\x8c\x46\x3f\xac\x28\xf6\x00\x00\x0a\xf0\x53\x00\x0c\x00' # | ...F?.(.....S...
|
|
||||||
msg += b'\x00\x0b\x54\x53\x00\x00\x00\x00\x0b\xb8\x53\x00\x00\x00\x00\x0c' # | ..TS......S.....
|
|
||||||
msg += b'\x1c\x53\x00\x00\x00\x00\x0c\x80\x53\x00\x00\x00\x00\x0c\xe4\x53' # | .S......S......S
|
|
||||||
msg += b'\x00\x00\x00\x00\x0d\x48\x53\x00\x00\x00\x00\x0d\xac\x53\x00\x00' # | .....HS......S..
|
|
||||||
msg += b'\x00\x00\x0e\x10\x53\x00\x00\x00\x00\x0e\x74\x53\x00\x00\x00\x00' # | ....S.....tS....
|
|
||||||
msg += b'\x0e\xd8\x53\x00\x00\x00\x00\x0f\x3c\x53\x00\x00\x00\x00\x0f\xa0' # | ..S.....<S......
|
|
||||||
msg += b'\x53\x00\x00\x00\x00\x10\x04\x53\x00\x00\x00\x00\x10\x68\x53\x00' # | S......S.....hS.
|
|
||||||
msg += b'\x00\x00\x00\x10\xcc\x53\x00\x00\x00\x00\x11\x30\x53\x00\x00\x00' # | .....S.....0S...
|
|
||||||
msg += b'\x00\x11\x94\x53\x00\x00\x00\x00\x11\xf8\x53\x00\x00\x00\x00\x12' # | ...S......S.....
|
|
||||||
msg += b'\x5c\x53\x00\x00\x00\x00\x12\xc0\x53\x00\x00\x00\x00\x13\x24\x46' # | \S......S.....$F
|
|
||||||
msg += b'\x42\x9d\x33\x33\x00\x00\x13\x88\x46\x00\x00\x00\x00\x00\x00\x13' # | B.33....F.......
|
|
||||||
msg += b'\xec\x46\x00\x00\x00\x00\x00\x00\x14\x50\x46\x42\xdc\x00\x00\x00' # | .F.......PFB....
|
|
||||||
msg += b'\x00\x14\xb4\x53\x00\x00\x00\x00\x15\x18\x53\x00\x00\x00\x00\x15' # | ...S......S.....
|
|
||||||
msg += b'\x7c\x53\x00\x00\x00\x00\x15\x7d\x53\x00\x00\x00\x00\x15\x7e\x53' # | |S.....}S.....~S
|
|
||||||
msg += b'\x00\x00\x00\x00\x15\x7f\x53\x00\x00\x00\x00\x15\x80\x53\x00\x00' # | ......S......S..
|
|
||||||
msg += b'\x00\x00\x15\x81\x53\x00\x00\x00\x00\x15\x82\x53\x00\x00\x00\x00' # | ....S......S....
|
|
||||||
msg += b'\x15\x83\x53\x00\x00\x00\x00\x15\x84\x53\x00\x00\x00\x00\x15\x85' # | ..S......S......
|
|
||||||
msg += b'\x53\x00\x00\x00\x00\x15\x86\x53\x00\x00\x00\x00\x15\x87\x53\x00' # | S......S......S.
|
|
||||||
msg += b'\x00\x00\x00\x15\x88\x53\x00\x00\x00\x00\x15\x89\x53\x00\x00\x00' # | .....S......S...
|
|
||||||
msg += b'\x00\x15\x8a\x53\x00\x00\x00\x00\x15\x8b\x53\x00\x00\x00\x00\x15' # | ...S......S.....
|
|
||||||
msg += b'\x8c\x53\x00\x00\x00\x00\x15\xe0\x46\x42\x68\x66\x66\x00\x00\x16' # | .S......FBhff...
|
|
||||||
msg += b'\x44\x46\x00\x00\x00\x00\x00\x00\x16\xa8\x46\x00\x00\x00\x00\x00' # | DF........F.....
|
|
||||||
msg += b'\x00\x17\x0c\x46\x42\xdc\x00\x00\x00\x00\x17\x70\x53\x00\x00\x00' # | ...FB......pS...
|
|
||||||
msg += b'\x00\x17\xd4\x53\x00\x00\x00\x00\x18\x38\x53\x00\x00\x00\x00\x18' # | ...S.....8S.....
|
|
||||||
msg += b'\x39\x53\x00\x00\x00\x00\x18\x3a\x53\x00\x00\x00\x00\x18\x3b\x53' # | 9S.....:S.....;S
|
|
||||||
msg += b'\x00\x00\x00\x00\x18\x3c\x53\x00\x00\x00\x00\x18\x3d\x53\x00\x00' # | .....<S.....=S..
|
|
||||||
msg += b'\x00\x00\x18\x3e\x53\x00\x00\x00\x00\x18\x3f\x53\x00\x00\x00\x00' # | ...>S.....?S....
|
|
||||||
msg += b'\x18\x40\x53\x00\x00\x00\x00\x18\x41\x53\x00\x00\x00\x00\x18\x42' # | .@S.....AS.....B
|
|
||||||
msg += b'\x53\x00\x00\x00\x00\x18\x43\x53\x00\x00\x00\x00\x18\x44\x53\x00' # | S.....CS.....DS.
|
|
||||||
msg += b'\x00\x00\x00\x18\x45\x53\x00\x00\x00\x00\x18\x46\x53\x00\x00\x00' # | ....ES.....FS...
|
|
||||||
msg += b'\x00\x18\x47\x53\x00\x00\x00\x00\x18\x48\x53\x00\x00\x00\x00\x18' # | ..GS.....HS.....
|
|
||||||
msg += b'\x9c\x46\x42\x6b\x33\x33\x00\x00\x19\x00\x46\x00\x00\x00\x00\x00' # | .FBk33....F.....
|
|
||||||
msg += b'\x00\x19\x64\x46\x00\x00\x00\x00\x00\x00\x19\xc8\x46\x42\xdc\x00' # | ..dF........FB..
|
|
||||||
msg += b'\x00\x00\x00\x1a\x2c\x53\x00\x00\x00\x00\x1a\x90\x53\x00\x00\x00' # | ....,S......S...
|
|
||||||
msg += b'\x00\x1a\xf4\x53\x00\x00\x00\x00\x1a\xf5\x53\x00\x00\x00\x00\x1a' # | ...S......S.....
|
|
||||||
msg += b'\xf6\x53\x00\x00\x00\x00\x1a\xf7\x53\x00\x00\x00\x00\x1a\xf8\x53' # | .S......S......S
|
|
||||||
msg += b'\x00\x00\x00\x00\x1a\xf9\x53\x00\x00\x00\x00\x1a\xfa\x53\x00\x00' # | ......S......S..
|
|
||||||
msg += b'\x00\x00\x1a\xfb\x53\x00\x00\x00\x00\x1a\xfc\x53\x00\x00\x00\x00' # | ....S......S....
|
|
||||||
msg += b'\x1a\xfd\x53\x00\x00\x00\x00\x1a\xfe\x53\x00\x00\x00\x00\x1a\xff' # | ..S......S......
|
|
||||||
msg += b'\x53\x00\x00\x00\x00\x1b\x00\x53\x00\x00\x00\x00\x1b\x01\x53\x00' # | S......S......S.
|
|
||||||
msg += b'\x00\x00\x00\x1b\x02\x53\x00\x00\x00\x00\x1b\x03\x53\x00\x00\x00' # | .....S......S...
|
|
||||||
msg += b'\x00\x1b\x04\x53\x00\x00\x00\x00\x1b\x58\x53\x00\x00\x00\x00\x1b' # | ...S.....XS.....
|
|
||||||
msg += b'\xbc\x53\x11\x3d\x00\x00\x1c\x20\x46\x3c\x23\xd7\x0a\x00\x00\x1c' # | .S.=... F<#.....
|
|
||||||
msg += b'\x84\x46\x00\x00\x00\x00\x00\x00\x1c\xe8\x46\x42\x04\x00\x00\x00' # | .F........FB....
|
|
||||||
msg += b'\x00\x1d\x4c\x46\x00\x00\x00\x00\x00\x00\x1d\xb0\x46\x00\x00\x00' # | ..LF........F...
|
|
||||||
msg += b'\x00\x00\x00\x1e\x14\x53\x00\x02\x00\x00\x1e\x78\x46\x41\x8b\x33' # | .....S.....xFA.3
|
|
||||||
msg += b'\x33\x00\x00\x1e\xdc\x46\x3c\xa3\xd7\x0a\x00\x00\x1f\x40\x46\x3e' # | 3....F<......@F>
|
|
||||||
msg += b'\x99\x99\x9a\x00\x00\x1f\xa4\x46\x40\x99\x99\x9a\x00\x00\x20\x08' # | .......F@..... .
|
|
||||||
msg += b'\x53\x00\x00\x00\x00\x20\x6c\x53\x00\x00\x00\x00\x20\xd0\x53\x05' # | S.... lS.... .S.
|
|
||||||
msg += b'\x00\x00\x00\x20\xd1\x53\x00\x00\x00\x00\x20\xd2\x53\x00\x00\x00' # | ... .S.... .S...
|
|
||||||
msg += b'\x00\x20\xd3\x53\x00\x00\x00\x00\x20\xd4\x53\x00\x00\x00\x00\x20' # | . .S.... .S....
|
|
||||||
msg += b'\xd5\x53\x00\x00\x00\x00\x20\xd6\x53\x00\x00\x00\x00\x20\xd7\x53' # | .S.... .S.... .S
|
|
||||||
msg += b'\x00\x00\x00\x00\x20\xd8\x53\x00\x00\x00\x00\x20\xd9\x53\x00\x01' # | .... .S.... .S..
|
|
||||||
msg += b'\x00\x00\x20\xda\x53\x00\x00\x00\x00\x20\xdb\x53\x00\x01\x00\x00' # | .. .S.... .S....
|
|
||||||
msg += b'\x20\xdc\x53\x00\x00\x00\x00\x20\xdd\x53\x00\x00\x00\x00\x20\xde' # | .S.... .S.... .
|
|
||||||
msg += b'\x53\x00\x00\x00\x00\x20\xdf\x53\x00\x00\x00\x00\x20\xe0\x53\x00' # | S.... .S.... .S.
|
|
||||||
msg += b'\x00\x00\x00\x21\x34\x46\x00\x00\x00\x00\x00\x00\x21\x98\x46\x00' # | ...!4F......!.F.
|
|
||||||
msg += b'\x00\x00\x00\x00\x00\x21\xfc\x46\x00\x00\x00\x00\x00\x00\x22\x60' # | .....!.F......"`
|
|
||||||
msg += b'\x46\x00\x00\x00\x00\x00\x00\x22\xc4\x53\x00\x00\x00\x00\x23\x28' # | F......".S....#(
|
|
||||||
msg += b'\x53\x00\x00\x00\x00\x23\x8c\x53\x00\x00\x00\x00\x23\x8d\x53\x00' # | S....#.S....#.S.
|
|
||||||
msg += b'\x00\x00\x00\x23\x8e\x53\x00\x00\x00\x00\x23\x8f\x53\x00\x00\x00' # | ...#.S....#.S...
|
|
||||||
msg += b'\x00\x23\x90\x53\x00\x00\x00\x00\x23\x91\x53\x00\x00\x00\x00\x23' # | .#.S....#.S....#
|
|
||||||
msg += b'\x92\x53\x00\x00\x00\x00\x23\x93\x53\x00\x00\x00\x00\x23\x94\x53' # | .S....#.S....#.S
|
|
||||||
msg += b'\x00\x00\x00\x00\x23\x95\x53\x00\x00\x00\x00\x23\x96\x53\x00\x00' # | ....#.S....#.S..
|
|
||||||
msg += b'\x00\x00\x23\x97\x53\x00\x00\x00\x00\x23\x98\x53\x00\x00\x00\x00' # | ..#.S....#.S....
|
|
||||||
msg += b'\x23\x99\x53\x00\x00\x00\x00\x23\x9a\x53\x00\x00\x00\x00\x23\x9b' # | #.S....#.S....#.
|
|
||||||
msg += b'\x53\x00\x00\x00\x00\x23\x9c\x53\x00\x00\x00\x00\x23\xf0\x46\x00' # | S....#.S....#.F.
|
|
||||||
msg += b'\x00\x00\x00\x00\x00\x24\x54\x46\x00\x00\x00\x00\x00\x00\x24\xb8' # | .....$TF......$.
|
|
||||||
msg += b'\x46\x00\x00\x00\x00\x00\x00\x25\x1c\x46\x00\x00\x00\x00\x00\x00' # | F......%.F......
|
|
||||||
msg += b'\x25\x80\x53\x00\x00\x00\x00\x25\xe4\x53\x00\x00\x00\x00\x26\x48' # | %.S....%.S....&H
|
|
||||||
msg += b'\x53\x00\x00\x00\x00\x26\x49\x53\x00\x00\x00\x00\x26\x4a\x53\x00' # | S....&IS....&JS.
|
|
||||||
msg += b'\x00\x00\x00\x26\x4b\x53\x00\x00\x00\x00\x26\x4c\x53\x00\x00\x00' # | ...&KS....&LS...
|
|
||||||
msg += b'\x00\x26\x4d\x53\x00\x00\x00\x00\x26\x4e\x53\x00\x00\x00\x00\x26' # | .&MS....&NS....&
|
|
||||||
msg += b'\x4f\x53\x00\x00\x00\x00\x26\x50\x53\x00\x00\x00\x00\x26\x51\x53' # | OS....&PS....&QS
|
|
||||||
msg += b'\x00\x00\x00\x00\x26\x52\x53\x00\x00\x00\x00\x26\x53\x53\x00\x00' # | ....&RS....&SS..
|
|
||||||
msg += b'\x00\x00\x26\x54\x53\x00\x00\x00\x00\x26\x55\x53\x00\x00\x00\x00' # | ..&TS....&US....
|
|
||||||
msg += b'\x26\x56\x53\x00\x00\x00\x00\x26\x57\x53\x00\x00\x00\x00\x26\x58' # | &VS....&WS....&X
|
|
||||||
msg += b'\x53\x00\x00\x00\x00\x26\xac\x53\x00\x00\x00\x00\x27\x10\x53\x11' # | S....&.S....'.S.
|
|
||||||
msg += b'\x3d\x00\x00\x27\x74\x46\x00\x00\x00\x00\x00\x00\x27\xd8\x46\x00' # | =..'tF......'.F.
|
|
||||||
msg += b'\x00\x00\x00\x00\x00\x28\x3c\x46\x42\x03\xf5\xc3\x00\x00\x28\xa0' # | .....(<FB.....(.
|
|
||||||
msg += b'\x46\x00\x00\x00\x00\x00\x00\x29\x04\x46\x00\x00\x00\x00\x00\x00' # | F......).F......
|
|
||||||
msg += b'\x29\x68\x53\x00\x02\x00\x00\x29\xcc\x53\x00\x03\x00\x00\x2a\x30' # | )hS....).S....*0
|
|
||||||
msg += b'\x46\x42\x20\x00\x00\x00\x00\x2a\x94\x46\x42\x20\x00\x00\x00\x00' # | FB ....*.FB ....
|
|
||||||
msg += b'\x2a\xf8\x46\x44\x20\x00\x00\x00\x00\x2b\x5c\x46\x43\x7b\x00\x00' # | *.FD ....+\FC{..
|
|
||||||
msg += b'\x00\x00\x2b\xc0\x46\x43\x50\x00\x00\x00\x00\x2c\x24\x46\x42\x48' # | ..+.FCP....,$FBH
|
|
||||||
msg += b'\x5c\x29\x00\x00\x2c\x88\x46\x42\x47\xa3\xd7\x00\x00\x2c\xec\x53' # | \)..,.FBG....,.S
|
|
||||||
msg += b'\x00\x00\x00\x00\x2d\x50\x46\x43\x42\x00\x00\x00\x00\x2d\xb4\x46' # | ....-PFCB....-.F
|
|
||||||
msg += b'\x42\xbc\x00\x00\x00\x00\x2e\x18\x46\x3f\xe6\x66\x66\x00\x00\x2e' # | B.......F?.ff...
|
|
||||||
msg += b'\x7c\x46\x3f\xe6\x66\x66\x00\x00\x2e\xe0\x46\x43\x7e\x00\x00\x00' # | |F?.ff....FC~...
|
|
||||||
msg += b'\x00\x2f\x44\x46\x43\x83\xf3\x33\x00\x00\x2f\xa8\x46\x3f\xe6\x66' # | ./DFC..3../.F?.f
|
|
||||||
msg += b'\x66\x00\x00\x30\x0c\x46\x3f\xe6\x66\x66\x00\x00\x30\x70\x46\x43' # | f..0.F?.ff..0pFC
|
|
||||||
msg += b'\x7e\x00\x00\x00\x00\x30\xd4\x46\x42\x3f\xeb\x85\x00\x00\x31\x38' # | ~....0.FB?....18
|
|
||||||
msg += b'\x46\x42\x3d\xeb\x85\x00\x00\x31\x9c\x46\x3e\x4c\xcc\xcd\x00\x00' # | FB=....1.F>L....
|
|
||||||
msg += b'\x32\x00\x46\x3e\x4c\xcc\xcd\x00\x00\x32\x64\x46\x42\x4c\x14\x7b' # | 2.F>L....2dFBL.{
|
|
||||||
msg += b'\x00\x00\x32\xc8\x46\x42\x4d\xeb\x85\x00\x00\x33\x2c\x46\x3e\x4c' # | ..2.FBM....3,F>L
|
|
||||||
msg += b'\xcc\xcd\x00\x00\x33\x90\x46\x3e\x4c\xcc\xcd\x00\x00\x33\xf4\x53' # | ....3.F>L....3.S
|
|
||||||
msg += b'\x00\x00\x00\x00\x34\x58\x53\x00\x00\x00\x00\x34\xbc\x53\x04\x00' # | ....4XS....4.S..
|
|
||||||
msg += b'\x00\x00\x35\x20\x53\x00\x01\x00\x00\x35\x84\x53\x13\x9c\x00\x00' # | ..5 S....5.S....
|
|
||||||
msg += b'\x35\xe8\x53\x0f\xa0\x00\x00\x36\x4c\x53\x00\x00\x00\x00\x36\xb0' # | 5.S....6LS....6.
|
|
||||||
msg += b'\x53\x00\x66' # | S.f'
|
|
||||||
return msg
|
|
||||||
|
|
||||||
@pytest.fixture
|
@pytest.fixture
|
||||||
def inv_data_new(): # Data indication from DSP V5.0.17
|
def inv_data_new(): # Data indication from DSP V5.0.17
|
||||||
msg = b'\x00\x00\x00\xa3\x00\x00\x00\x00\x53\x00\x00'
|
msg = b'\x00\x00\x00\xa3\x00\x00\x00\x00\x53\x00\x00'
|
||||||
@@ -481,7 +254,7 @@ def inv_data_seq2_zero(): # Data indication from the controller
|
|||||||
|
|
||||||
def test_parse_control(contr_data_seq):
|
def test_parse_control(contr_data_seq):
|
||||||
i = InfosG3()
|
i = InfosG3()
|
||||||
for key, result in i.parse (contr_data_seq, sensor=0x0e100000):
|
for key, result in i.parse (contr_data_seq):
|
||||||
pass # side effect in calling i.parse()
|
pass # side effect in calling i.parse()
|
||||||
|
|
||||||
assert json.dumps(i.db) == json.dumps(
|
assert json.dumps(i.db) == json.dumps(
|
||||||
@@ -489,23 +262,15 @@ def test_parse_control(contr_data_seq):
|
|||||||
|
|
||||||
def test_parse_control2(contr2_data_seq):
|
def test_parse_control2(contr2_data_seq):
|
||||||
i = InfosG3()
|
i = InfosG3()
|
||||||
for key, result in i.parse (contr2_data_seq, sensor=0x0e100000):
|
for key, result in i.parse (contr2_data_seq):
|
||||||
pass # side effect in calling i.parse()
|
pass # side effect in calling i.parse()
|
||||||
|
|
||||||
assert json.dumps(i.db) == json.dumps(
|
assert json.dumps(i.db) == json.dumps(
|
||||||
{"collector": {"Collector_Fw_Version": "RSW_400_V1.00.20", "Chip_Type": "Raymon", "Chip_Model": "RSW-1-10001", "Trace_URL": "t.raymoniot.com", "Logger_URL": "logger.talent-monitoring.com"}, "controller": {"Collect_Interval": 1, "Signal_Strength": 16, "Power_On_Time": 334, "Communication_Type": 1, "Connect_Count": 1, "Data_Up_Interval": 300}})
|
{"collector": {"Collector_Fw_Version": "RSW_400_V1.00.20", "Chip_Type": "Raymon", "Chip_Model": "RSW-1-10001", "Trace_URL": "t.raymoniot.com", "Logger_URL": "logger.talent-monitoring.com"}, "controller": {"Collect_Interval": 1, "Signal_Strength": 16, "Power_On_Time": 334, "Communication_Type": 1, "Connect_Count": 1, "Data_Up_Interval": 300}})
|
||||||
|
|
||||||
def test_parse_control3(contr3_data_seq):
|
|
||||||
i = InfosG3()
|
|
||||||
for key, result in i.parse (contr3_data_seq, sensor=0x0e100000):
|
|
||||||
pass # side effect in calling i.parse()
|
|
||||||
|
|
||||||
assert json.dumps(i.db) == json.dumps(
|
|
||||||
{"collector": {"Collector_Fw_Version": "RSW_400_V2.01.13", "Chip_Type": "Raymon", "Chip_Model": "RSW-1-10001", "Trace_URL": "t.raymoniot.com", "Logger_URL": "logger.talent-monitoring.com"}, "controller": {"Collect_Interval": 1, "Signal_Strength": 98, "Power_On_Time": 335, "Communication_Type": 1, "Connect_Count": 1, "Data_Up_Interval": 300}})
|
|
||||||
|
|
||||||
def test_parse_inverter(inv_data_seq):
|
def test_parse_inverter(inv_data_seq):
|
||||||
i = InfosG3()
|
i = InfosG3()
|
||||||
for key, result in i.parse (inv_data_seq, sensor=0x01900001):
|
for key, result in i.parse (inv_data_seq):
|
||||||
pass # side effect in calling i.parse()
|
pass # side effect in calling i.parse()
|
||||||
|
|
||||||
assert json.dumps(i.db) == json.dumps(
|
assert json.dumps(i.db) == json.dumps(
|
||||||
@@ -513,10 +278,10 @@ def test_parse_inverter(inv_data_seq):
|
|||||||
|
|
||||||
def test_parse_cont_and_invert(contr_data_seq, inv_data_seq):
|
def test_parse_cont_and_invert(contr_data_seq, inv_data_seq):
|
||||||
i = InfosG3()
|
i = InfosG3()
|
||||||
for key, result in i.parse (contr_data_seq, sensor=0x0e100000):
|
for key, result in i.parse (contr_data_seq):
|
||||||
pass # side effect in calling i.parse()
|
pass # side effect in calling i.parse()
|
||||||
|
|
||||||
for key, result in i.parse (inv_data_seq, sensor=0x01900001):
|
for key, result in i.parse (inv_data_seq):
|
||||||
pass # side effect in calling i.parse()
|
pass # side effect in calling i.parse()
|
||||||
|
|
||||||
assert json.dumps(i.db) == json.dumps(
|
assert json.dumps(i.db) == json.dumps(
|
||||||
@@ -524,29 +289,10 @@ def test_parse_cont_and_invert(contr_data_seq, inv_data_seq):
|
|||||||
"collector": {"Collector_Fw_Version": "RSW_400_V1.00.06", "Chip_Type": "Raymon", "Chip_Model": "RSW-1-10001", "Trace_URL": "t.raymoniot.com", "Logger_URL": "logger.talent-monitoring.com"}, "controller": {"Collect_Interval": 1, "Signal_Strength": 100, "Power_On_Time": 29, "Communication_Type": 1, "Connect_Count": 1, "Data_Up_Interval": 300},
|
"collector": {"Collector_Fw_Version": "RSW_400_V1.00.06", "Chip_Type": "Raymon", "Chip_Model": "RSW-1-10001", "Trace_URL": "t.raymoniot.com", "Logger_URL": "logger.talent-monitoring.com"}, "controller": {"Collect_Interval": 1, "Signal_Strength": 100, "Power_On_Time": 29, "Communication_Type": 1, "Connect_Count": 1, "Data_Up_Interval": 300},
|
||||||
"inverter": {"Product_Name": "Microinv", "Manufacturer": "TSUN", "Version": "V5.0.11", "Serial_Number": "T170000000000001", "Equipment_Model": "TSOL-MS600"}})
|
"inverter": {"Product_Name": "Microinv", "Manufacturer": "TSUN", "Version": "V5.0.11", "Serial_Number": "T170000000000001", "Equipment_Model": "TSOL-MS600"}})
|
||||||
|
|
||||||
def test_parse_cont_and_invert2(contr3_data_seq, inv_data_seq3):
|
|
||||||
i = InfosG3()
|
|
||||||
for key, result in i.parse (contr3_data_seq, sensor=0x0e100000):
|
|
||||||
pass # side effect in calling i.parse()
|
|
||||||
|
|
||||||
for key, result in i.parse (inv_data_seq3, sensor=0x01900000):
|
|
||||||
pass # side effect in calling i.parse()
|
|
||||||
|
|
||||||
assert json.dumps(i.db) == json.dumps(
|
|
||||||
{
|
|
||||||
"collector": {"Collector_Fw_Version": "RSW_400_V2.01.13", "Chip_Type": "Raymon", "Chip_Model": "RSW-1-10001", "Trace_URL": "t.raymoniot.com", "Logger_URL": "logger.talent-monitoring.com"}, "controller": {"Collect_Interval": 1, "Signal_Strength": 98, "Power_On_Time": 335, "Communication_Type": 1, "Connect_Count": 1, "Data_Up_Interval": 300},
|
|
||||||
"env": {"Inverter_Status": 0},
|
|
||||||
"events": {"Inverter_Alarm": 0, "Inverter_Fault": 0, "Inverter_Bitfield_1": 0, "Inverter_bitfield_2": 0},
|
|
||||||
"input": {"iVal_1": 1, "Val_0": 655.28, "Val_1": 327.4, "Val_2": 0.0, "Val_3": 0.0, "iVal_2": 3, "iVal_3": 12, "iVal_4": 80, "Val_4": 327.4, "iVal_5": 0, "Val_10": 30.25, "Val_11": 1.35, "iVal_6": 12, "pv1": {"Voltage": 78.6, "Current": 0.0, "Power": 0.0}, "Val_5": 110.0, "pv2": {"Voltage": 58.1, "Current": 0.0, "Power": 0.0}, "Val_6": 110.0, "pv3": {"Voltage": 58.8, "Current": 0.0, "Power": 0.0}, "Val_7": 110.0, "Val_14": 0.01, "Val_15": 0.0, "Val_16": 33.0, "Val_17": 0.0, "Val_18": 0.0, "iVal_8": 2, "pv4": {"Voltage": 17.4, "Current": 0.02, "Power": 0.3}, "Val_8": 4.8, "iVal_10": 1, "pv5": {"Voltage": 0.0, "Current": 0.0, "Power": 0.0}, "pv6": {"Voltage": 0.0, "Current": 0.0, "Power": 0.0}, "Val_24": 0.0, "Val_25": 0.0, "Val_26": 32.99, "Val_27": 0.0, "Val_28": 0.0, "iVal_11": 2, "iVal_12": 3},
|
|
||||||
"grid": {"Voltage": 238.5, "Current": 0.05, "Frequency": 50.0, "Output_Power": 0.0},
|
|
||||||
"inverter": {"Max_Designed_Power": 3000},
|
|
||||||
"total": {"Total_Generation": 29.86}
|
|
||||||
})
|
|
||||||
|
|
||||||
def test_build_ha_conf1(contr_data_seq):
|
def test_build_ha_conf1(contr_data_seq):
|
||||||
i = InfosG3()
|
i = InfosG3()
|
||||||
i.static_init() # initialize counter
|
i.static_init() # initialize counter
|
||||||
i.set_db_def_value(Register.SENSOR_LIST, "01900001")
|
|
||||||
|
|
||||||
tests = 0
|
tests = 0
|
||||||
for d_json, comp, node_id, id in i.ha_confs(ha_prfx="tsun/", node_id="garagendach/", snr='123'):
|
for d_json, comp, node_id, id in i.ha_confs(ha_prfx="tsun/", node_id="garagendach/", snr='123'):
|
||||||
@@ -582,7 +328,6 @@ def test_build_ha_conf1(contr_data_seq):
|
|||||||
def test_build_ha_conf2(contr_data_seq):
|
def test_build_ha_conf2(contr_data_seq):
|
||||||
i = InfosG3()
|
i = InfosG3()
|
||||||
i.static_init() # initialize counter
|
i.static_init() # initialize counter
|
||||||
i.set_db_def_value(Register.SENSOR_LIST, "01900001")
|
|
||||||
|
|
||||||
tests = 0
|
tests = 0
|
||||||
for d_json, comp, node_id, id in i.ha_proxy_confs(ha_prfx="tsun/", node_id = 'proxy/', snr = '456'):
|
for d_json, comp, node_id, id in i.ha_proxy_confs(ha_prfx="tsun/", node_id = 'proxy/', snr = '456'):
|
||||||
@@ -607,12 +352,11 @@ def test_build_ha_conf2(contr_data_seq):
|
|||||||
|
|
||||||
def test_build_ha_conf3(contr_data_seq, inv_data_seq, inv_data_seq2):
|
def test_build_ha_conf3(contr_data_seq, inv_data_seq, inv_data_seq2):
|
||||||
i = InfosG3()
|
i = InfosG3()
|
||||||
i.set_db_def_value(Register.SENSOR_LIST, "01900001")
|
for key, result in i.parse (contr_data_seq):
|
||||||
for key, result in i.parse (contr_data_seq, sensor=0x0e100000):
|
|
||||||
pass # side effect in calling i.parse()
|
pass # side effect in calling i.parse()
|
||||||
for key, result in i.parse (inv_data_seq, sensor=0x01900001):
|
for key, result in i.parse (inv_data_seq):
|
||||||
pass # side effect in calling i.parse()
|
pass # side effect in calling i.parse()
|
||||||
for key, result in i.parse (inv_data_seq2, sensor=0x01900001):
|
for key, result in i.parse (inv_data_seq2):
|
||||||
pass # side effect in calling i.parse()
|
pass # side effect in calling i.parse()
|
||||||
|
|
||||||
tests = 0
|
tests = 0
|
||||||
@@ -646,10 +390,9 @@ def test_build_ha_conf3(contr_data_seq, inv_data_seq, inv_data_seq2):
|
|||||||
|
|
||||||
def test_build_ha_conf4(contr_data_seq, inv_data_seq):
|
def test_build_ha_conf4(contr_data_seq, inv_data_seq):
|
||||||
i = InfosG3()
|
i = InfosG3()
|
||||||
i.set_db_def_value(Register.SENSOR_LIST, "01900001")
|
for key, result in i.parse (contr_data_seq):
|
||||||
for key, result in i.parse (contr_data_seq, sensor=0x0e100000):
|
|
||||||
pass # side effect in calling i.parse()
|
pass # side effect in calling i.parse()
|
||||||
for key, result in i.parse (inv_data_seq, sensor=0x01900001):
|
for key, result in i.parse (inv_data_seq):
|
||||||
pass # side effect in calling i.parse()
|
pass # side effect in calling i.parse()
|
||||||
i.set_db_def_value(Register.MAC_ADDR, "00a057123456")
|
i.set_db_def_value(Register.MAC_ADDR, "00a057123456")
|
||||||
|
|
||||||
@@ -671,37 +414,10 @@ def test_build_ha_conf4(contr_data_seq, inv_data_seq):
|
|||||||
tests +=1
|
tests +=1
|
||||||
assert tests==1
|
assert tests==1
|
||||||
|
|
||||||
def test_build_ha_conf5(contr3_data_seq, inv_data_seq3):
|
|
||||||
i = InfosG3()
|
|
||||||
i.set_db_def_value(Register.SENSOR_LIST, "01900000")
|
|
||||||
for key, result in i.parse (contr3_data_seq, sensor=0x0e100000):
|
|
||||||
pass # side effect in calling i.parse()
|
|
||||||
for key, result in i.parse (inv_data_seq3, sensor=0x01900000):
|
|
||||||
pass # side effect in calling i.parse()
|
|
||||||
i.set_db_def_value(Register.MAC_ADDR, "00a057123456")
|
|
||||||
|
|
||||||
tests = 0
|
|
||||||
for d_json, comp, node_id, id in i.ha_confs(ha_prfx="tsun/", node_id="garagendach/", snr='123', sug_area = 'roof'):
|
|
||||||
if id == 'signal_123':
|
|
||||||
assert comp == 'sensor'
|
|
||||||
assert d_json == json.dumps({"name": "Signal Strength", "stat_t": "tsun/garagendach/controller", "dev_cla": None, "stat_cla": "measurement", "uniq_id": "signal_123", "val_tpl": "{{value_json[\'Signal_Strength\'] | int}}", "unit_of_meas": "%", "ic": "mdi:wifi", "dev": {"name": "Controller - roof", "sa": "Controller - roof", "via_device": "proxy", "mdl": "RSW-1-10001", "mf": "Raymon", "sw": "RSW_400_V2.01.13", "ids": ["controller_123"], "cns": [["mac", "00:a0:57:12:34:56"]]}, "o": {"name": "proxy", "sw": "unknown"}})
|
|
||||||
tests +=1
|
|
||||||
assert tests==1
|
|
||||||
|
|
||||||
i.set_db_def_value(Register.MAC_ADDR, "00:a0:57:12:34:57")
|
|
||||||
|
|
||||||
tests = 0
|
|
||||||
for d_json, comp, node_id, id in i.ha_confs(ha_prfx="tsun/", node_id="garagendach/", snr='123', sug_area = 'roof'):
|
|
||||||
if id == 'signal_123':
|
|
||||||
assert comp == 'sensor'
|
|
||||||
assert d_json == json.dumps({"name": "Signal Strength", "stat_t": "tsun/garagendach/controller", "dev_cla": None, "stat_cla": "measurement", "uniq_id": "signal_123", "val_tpl": "{{value_json[\'Signal_Strength\'] | int}}", "unit_of_meas": "%", "ic": "mdi:wifi", "dev": {"name": "Controller - roof", "sa": "Controller - roof", "via_device": "proxy", "mdl": "RSW-1-10001", "mf": "Raymon", "sw": "RSW_400_V2.01.13", "ids": ["controller_123"], "cns": [["mac", "00:a0:57:12:34:57"]]}, "o": {"name": "proxy", "sw": "unknown"}})
|
|
||||||
tests +=1
|
|
||||||
assert tests==1
|
|
||||||
|
|
||||||
def test_must_incr_total(inv_data_seq2, inv_data_seq2_zero):
|
def test_must_incr_total(inv_data_seq2, inv_data_seq2_zero):
|
||||||
i = InfosG3()
|
i = InfosG3()
|
||||||
tests = 0
|
tests = 0
|
||||||
for key, update in i.parse (inv_data_seq2, sensor=0x01900001):
|
for key, update in i.parse (inv_data_seq2):
|
||||||
if key == 'total' or key == 'inverter' or key == 'env':
|
if key == 'total' or key == 'inverter' or key == 'env':
|
||||||
assert update == True
|
assert update == True
|
||||||
tests +=1
|
tests +=1
|
||||||
@@ -710,7 +426,7 @@ def test_must_incr_total(inv_data_seq2, inv_data_seq2_zero):
|
|||||||
assert json.dumps(i.db['input']) == json.dumps({"pv1": {"Voltage": 33.6, "Current": 1.91, "Power": 64.5, "Daily_Generation": 1.08, "Total_Generation": 9.74}, "pv2": {"Voltage": 33.5, "Current": 1.36, "Power": 45.7, "Daily_Generation": 0.62, "Total_Generation": 7.62}, "pv3": {"Voltage": 0.0, "Current": 0.0, "Power": 0.0}, "pv4": {"Voltage": 0.0, "Current": 0.0, "Power": 0.0}})
|
assert json.dumps(i.db['input']) == json.dumps({"pv1": {"Voltage": 33.6, "Current": 1.91, "Power": 64.5, "Daily_Generation": 1.08, "Total_Generation": 9.74}, "pv2": {"Voltage": 33.5, "Current": 1.36, "Power": 45.7, "Daily_Generation": 0.62, "Total_Generation": 7.62}, "pv3": {"Voltage": 0.0, "Current": 0.0, "Power": 0.0}, "pv4": {"Voltage": 0.0, "Current": 0.0, "Power": 0.0}})
|
||||||
assert json.dumps(i.db['env']) == json.dumps({"Inverter_Status": 1, "Inverter_Temp": 23})
|
assert json.dumps(i.db['env']) == json.dumps({"Inverter_Status": 1, "Inverter_Temp": 23})
|
||||||
tests = 0
|
tests = 0
|
||||||
for key, update in i.parse (inv_data_seq2, sensor=0x01900001):
|
for key, update in i.parse (inv_data_seq2):
|
||||||
if key == 'total' or key == 'env':
|
if key == 'total' or key == 'env':
|
||||||
assert update == False
|
assert update == False
|
||||||
tests +=1
|
tests +=1
|
||||||
@@ -722,7 +438,7 @@ def test_must_incr_total(inv_data_seq2, inv_data_seq2_zero):
|
|||||||
assert json.dumps(i.db['inverter']) == json.dumps({"Rated_Power": 600, "BOOT_STATUS": 0, "DSP_STATUS": 21930, "Work_Mode": 0, "Max_Designed_Power": -1, "Input_Coefficient": -0.1, "Output_Coefficient": 100.0, "No_Inputs": 2})
|
assert json.dumps(i.db['inverter']) == json.dumps({"Rated_Power": 600, "BOOT_STATUS": 0, "DSP_STATUS": 21930, "Work_Mode": 0, "Max_Designed_Power": -1, "Input_Coefficient": -0.1, "Output_Coefficient": 100.0, "No_Inputs": 2})
|
||||||
|
|
||||||
tests = 0
|
tests = 0
|
||||||
for key, update in i.parse (inv_data_seq2_zero, sensor=0x01900001):
|
for key, update in i.parse (inv_data_seq2_zero):
|
||||||
if key == 'total':
|
if key == 'total':
|
||||||
assert update == False
|
assert update == False
|
||||||
tests +=1
|
tests +=1
|
||||||
@@ -737,7 +453,7 @@ def test_must_incr_total(inv_data_seq2, inv_data_seq2_zero):
|
|||||||
def test_must_incr_total2(inv_data_seq2, inv_data_seq2_zero):
|
def test_must_incr_total2(inv_data_seq2, inv_data_seq2_zero):
|
||||||
i = InfosG3()
|
i = InfosG3()
|
||||||
tests = 0
|
tests = 0
|
||||||
for key, update in i.parse (inv_data_seq2_zero, sensor=0x01900001):
|
for key, update in i.parse (inv_data_seq2_zero):
|
||||||
if key == 'total':
|
if key == 'total':
|
||||||
assert update == False
|
assert update == False
|
||||||
tests +=1
|
tests +=1
|
||||||
@@ -751,7 +467,7 @@ def test_must_incr_total2(inv_data_seq2, inv_data_seq2_zero):
|
|||||||
assert json.dumps(i.db['env']) == json.dumps({"Inverter_Status": 1, "Inverter_Temp": 0})
|
assert json.dumps(i.db['env']) == json.dumps({"Inverter_Status": 1, "Inverter_Temp": 0})
|
||||||
|
|
||||||
tests = 0
|
tests = 0
|
||||||
for key, update in i.parse (inv_data_seq2_zero, sensor=0x01900001):
|
for key, update in i.parse (inv_data_seq2_zero):
|
||||||
if key == 'total' or key == 'env':
|
if key == 'total' or key == 'env':
|
||||||
assert update == False
|
assert update == False
|
||||||
tests +=1
|
tests +=1
|
||||||
@@ -762,7 +478,7 @@ def test_must_incr_total2(inv_data_seq2, inv_data_seq2_zero):
|
|||||||
assert json.dumps(i.db['env']) == json.dumps({"Inverter_Status": 1, "Inverter_Temp": 0})
|
assert json.dumps(i.db['env']) == json.dumps({"Inverter_Status": 1, "Inverter_Temp": 0})
|
||||||
|
|
||||||
tests = 0
|
tests = 0
|
||||||
for key, update in i.parse (inv_data_seq2, sensor=0x01900001):
|
for key, update in i.parse (inv_data_seq2):
|
||||||
if key == 'total' or key == 'env':
|
if key == 'total' or key == 'env':
|
||||||
tests +=1
|
tests +=1
|
||||||
|
|
||||||
@@ -773,7 +489,7 @@ def test_must_incr_total2(inv_data_seq2, inv_data_seq2_zero):
|
|||||||
def test_new_data_types(inv_data_new):
|
def test_new_data_types(inv_data_new):
|
||||||
i = InfosG3()
|
i = InfosG3()
|
||||||
tests = 0
|
tests = 0
|
||||||
for key, update in i.parse (inv_data_new, sensor=0x01900001):
|
for key, update in i.parse (inv_data_new):
|
||||||
if key == 'events':
|
if key == 'events':
|
||||||
tests +=1
|
tests +=1
|
||||||
elif key == 'inverter':
|
elif key == 'inverter':
|
||||||
@@ -798,7 +514,7 @@ def test_invalid_data_type(invalid_data_seq):
|
|||||||
assert val == 0
|
assert val == 0
|
||||||
|
|
||||||
|
|
||||||
for key, result in i.parse (invalid_data_seq, sensor=0x01900001):
|
for key, result in i.parse (invalid_data_seq):
|
||||||
pass # side effect in calling i.parse()
|
pass # side effect in calling i.parse()
|
||||||
assert json.dumps(i.db) == json.dumps({"inverter": {"Product_Name": "Microinv"}})
|
assert json.dumps(i.db) == json.dumps({"inverter": {"Product_Name": "Microinv"}})
|
||||||
|
|
||||||
|
|||||||
@@ -70,28 +70,6 @@ def inverter_data(): # 0x4210 ftype: 0x01
|
|||||||
msg += b'\x00\x00\x00\x00'
|
msg += b'\x00\x00\x00\x00'
|
||||||
return msg
|
return msg
|
||||||
|
|
||||||
@pytest.fixture
|
|
||||||
def batterie_data(): # 0x4210 ftype: 0x01
|
|
||||||
msg = b'\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01\x26\x30\xc7\xde'
|
|
||||||
msg += b'\x2d\x32\x28\x00\x00\x00\x84\x17\x79\x35\x01\x00\x4c\x12\x00\x00'
|
|
||||||
msg += b'\x34\x31\x30\x31\x32\x34\x30\x37\x30\x31\x34\x39\x30\x33\x31\x34'
|
|
||||||
msg += b'\x0d\x3a\x00\x70\x0d\x2c\x00\x00\x00\x00\x08\x20\x00\x00\x00\x00'
|
|
||||||
msg += b'\x14\x0e\xff\xfe\x03\xe8\x0c\x89\x0c\x89\x0c\x89\x0c\x8a\x0c\x89'
|
|
||||||
msg += b'\x0c\x89\x0c\x8a\x0c\x89\x0c\x89\x0c\x8a\x0c\x8a\x0c\x89\x0c\x89'
|
|
||||||
msg += b'\x0c\x89\x0c\x89\x0c\x88\x00\x0f\x00\x0f\x00\x0f\x00\x0e\x00\x00'
|
|
||||||
msg += b'\x00\x00\x00\x0f\x00\x00\x02\x05\x02\x01'
|
|
||||||
return msg
|
|
||||||
|
|
||||||
@pytest.fixture
|
|
||||||
def batterie_data2(): # 0x4210 ftype: 0x01
|
|
||||||
msg = b'\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01\x26\x30\xc7\xde'
|
|
||||||
msg += b'\x2d\x32\x28\x00\x00\x00\x84\x17\x79\x35\x01\x00\x4c\x12\x00\x00'
|
|
||||||
msg += b'\x34\x31\x30\x31\x32\x34\x30\x37\x30\x31\x34\x39\x30\x33\x31\x34'
|
|
||||||
msg += b'\x0d\x3a\x00\x70\x0d\x2c\x00\x00\x00\x00\x08\x20\x00\x00\x00\x00'
|
|
||||||
msg += b'\x14\x0e\xff\xfe\x03\xe8\x0c\x89\x0c\x89\x0c\x89\x0c\x8a\x0c\x89'
|
|
||||||
msg += b'\x0c\x89\x0c\x8a\x0c\x89\x0c\x89\x0c\x8a\x0c\x8a\x0c\x89\x0c\x89'
|
|
||||||
msg += b'\x0c\x89\x0c\x89\x0c\x88\x00\x0f\x00\x0f\x00\x0f\x00\x0e'
|
|
||||||
return msg
|
|
||||||
|
|
||||||
def test_default_db():
|
def test_default_db():
|
||||||
i = InfosG3P(client_mode=False)
|
i = InfosG3P(client_mode=False)
|
||||||
@@ -123,11 +101,11 @@ def test_build_4110(str_test_ip, device_data: bytes):
|
|||||||
build_msg[i] = device_data[i]
|
build_msg[i] = device_data[i]
|
||||||
assert device_data == build_msg
|
assert device_data == build_msg
|
||||||
|
|
||||||
def test_parse_4210_02b0(inverter_data: bytes):
|
def test_parse_4210(inverter_data: bytes):
|
||||||
i = InfosG3P(client_mode=False)
|
i = InfosG3P(client_mode=False)
|
||||||
i.db.clear()
|
i.db.clear()
|
||||||
|
|
||||||
for key, update in i.parse (inverter_data, 0x42, 1, 0x02b0):
|
for key, update in i.parse (inverter_data, 0x42, 1):
|
||||||
pass # side effect is calling generator i.parse()
|
pass # side effect is calling generator i.parse()
|
||||||
|
|
||||||
assert json.dumps(i.db) == json.dumps({
|
assert json.dumps(i.db) == json.dumps({
|
||||||
@@ -145,56 +123,14 @@ def test_parse_4210_02b0(inverter_data: bytes):
|
|||||||
"other": {"Output_Shutdown": 65535, "Rated_Level": 3, "Grid_Volt_Cal_Coef": 1024, "Prod_Compliance_Type": 6}
|
"other": {"Output_Shutdown": 65535, "Rated_Level": 3, "Grid_Volt_Cal_Coef": 1024, "Prod_Compliance_Type": 6}
|
||||||
})
|
})
|
||||||
|
|
||||||
def test_parse_4210_3026(batterie_data: bytes):
|
|
||||||
i = InfosG3P(client_mode=False)
|
|
||||||
i.db.clear()
|
|
||||||
|
|
||||||
for key, update in i.parse (batterie_data, 0x42, 1, 0x3026):
|
|
||||||
pass # side effect is calling generator i.parse()
|
|
||||||
|
|
||||||
assert json.dumps(i.db) == json.dumps({
|
|
||||||
"controller": {"Sensor_List": "3026", "Power_On_Time": 4684},
|
|
||||||
"inverter": {"Serial_Number": "4101240701490314"},
|
|
||||||
"batterie": {"pv1": {"Voltage": 33.86, "Current": 1.12},
|
|
||||||
"pv2": {"Voltage": 33.72, "Current": 0.0},
|
|
||||||
"Reg_38": 0, "Total_Generation": 20.8, "Status_1": 0, "Status_2": 0,
|
|
||||||
"Voltage": 51.34, "Current": -0.02, "SOC": 10.0,
|
|
||||||
"Cell": {"Volt1": 3.21, "Volt2": 3.21, "Volt3": 3.21, "Volt4": 3.21, "Volt5": 3.21, "Volt6": 3.21, "Volt7": 3.21, "Volt8": 3.21, "Volt9": 3.21, "Volt10": 3.21, "Volt11": 3.21, "Volt12": 3.21, "Volt13": 3.21, "Volt14": 3.21, "Volt15": 3.21, "Volt16": 3.21},
|
|
||||||
"Temp_1": 15, "Temp_2": 15, "Temp_3": 15,
|
|
||||||
"out": {"Voltage": 0.14, "Current": 0.0, "Out_Status": 0, "Power": 0.0},
|
|
||||||
"Controller_Temp": 15, "Reg_74": 0, "Reg_76": 517, "Reg_78": 513,
|
|
||||||
"PV_Power": 37.9232, "Power": -1.0268000000000002},
|
|
||||||
})
|
|
||||||
|
|
||||||
def test_parse_4210_3026_incomplete(batterie_data2: bytes):
|
|
||||||
i = InfosG3P(client_mode=False)
|
|
||||||
i.db.clear()
|
|
||||||
|
|
||||||
for key, update in i.parse (batterie_data2, 0x42, 1, 0x3026):
|
|
||||||
pass # side effect is calling generator i.parse()
|
|
||||||
|
|
||||||
assert json.dumps(i.db) == json.dumps({
|
|
||||||
"controller": {"Sensor_List": "3026", "Power_On_Time": 4684},
|
|
||||||
"inverter": {"Serial_Number": "4101240701490314"},
|
|
||||||
"batterie": {"pv1": {"Voltage": 33.86, "Current": 1.12},
|
|
||||||
"pv2": {"Voltage": 33.72, "Current": 0.0},
|
|
||||||
"Reg_38": 0, "Total_Generation": 20.8, "Status_1": 0, "Status_2": 0,
|
|
||||||
"Voltage": 51.34, "Current": -0.02, "SOC": 10.0,
|
|
||||||
"Cell": {"Volt1": 3.21, "Volt2": 3.21, "Volt3": 3.21, "Volt4": 3.21, "Volt5": 3.21, "Volt6": 3.21, "Volt7": 3.21, "Volt8": 3.21, "Volt9": 3.21, "Volt10": 3.21, "Volt11": 3.21, "Volt12": 3.21, "Volt13": 3.21, "Volt14": 3.21, "Volt15": 3.21, "Volt16": 3.21},
|
|
||||||
"Temp_1": 15, "Temp_2": 15, "Temp_3": 15,
|
|
||||||
"out": {"Voltage": 0.14, "Current": None, "Out_Status": None, "Power": None},
|
|
||||||
"Controller_Temp": None, "Reg_74": None, "Reg_76": None, "Reg_78": None,
|
|
||||||
"PV_Power": 37.9232, "Power": -1.0268000000000002},
|
|
||||||
})
|
|
||||||
|
|
||||||
def test_build_4210(inverter_data: bytes):
|
def test_build_4210(inverter_data: bytes):
|
||||||
i = InfosG3P(client_mode=False)
|
i = InfosG3P(client_mode=False)
|
||||||
i.db.clear()
|
i.db.clear()
|
||||||
|
|
||||||
for key, update in i.parse (inverter_data, 0x42, 1, 0x02b0):
|
for key, update in i.parse (inverter_data, 0x42, 1):
|
||||||
pass # side effect is calling generator i.parse()
|
pass # side effect is calling generator i.parse()
|
||||||
|
|
||||||
build_msg = i.build(len(inverter_data), 0x42, 1, 0x02b0)
|
build_msg = i.build(len(inverter_data), 0x42, 1)
|
||||||
for i in range(11, 31):
|
for i in range(11, 31):
|
||||||
build_msg[i] = inverter_data[i]
|
build_msg[i] = inverter_data[i]
|
||||||
assert inverter_data == build_msg
|
assert inverter_data == build_msg
|
||||||
@@ -202,7 +138,6 @@ def test_build_4210(inverter_data: bytes):
|
|||||||
def test_build_ha_conf1():
|
def test_build_ha_conf1():
|
||||||
i = InfosG3P(client_mode=False)
|
i = InfosG3P(client_mode=False)
|
||||||
i.static_init() # initialize counter
|
i.static_init() # initialize counter
|
||||||
i.set_db_def_value(Register.SENSOR_LIST, "02b0")
|
|
||||||
|
|
||||||
tests = 0
|
tests = 0
|
||||||
for d_json, comp, node_id, id in i.ha_confs(ha_prfx="tsun/", node_id="garagendach/", snr='123'):
|
for d_json, comp, node_id, id in i.ha_confs(ha_prfx="tsun/", node_id="garagendach/", snr='123'):
|
||||||
@@ -277,7 +212,6 @@ def test_build_ha_conf2():
|
|||||||
def test_build_ha_conf3():
|
def test_build_ha_conf3():
|
||||||
i = InfosG3P(client_mode=True)
|
i = InfosG3P(client_mode=True)
|
||||||
i.static_init() # initialize counter
|
i.static_init() # initialize counter
|
||||||
i.set_db_def_value(Register.SENSOR_LIST, "02b0")
|
|
||||||
|
|
||||||
tests = 0
|
tests = 0
|
||||||
for d_json, comp, node_id, id in i.ha_confs(ha_prfx="tsun/", node_id="garagendach/", snr='123'):
|
for d_json, comp, node_id, id in i.ha_confs(ha_prfx="tsun/", node_id="garagendach/", snr='123'):
|
||||||
@@ -349,89 +283,56 @@ def test_build_ha_conf4():
|
|||||||
|
|
||||||
assert tests==1
|
assert tests==1
|
||||||
|
|
||||||
def test_build_ha_conf5():
|
|
||||||
i = InfosG3P(client_mode=True)
|
|
||||||
i.static_init() # initialize counter
|
|
||||||
i.set_db_def_value(Register.SENSOR_LIST, "3026")
|
|
||||||
|
|
||||||
tests = 0
|
|
||||||
for d_json, comp, node_id, id in i.ha_confs(ha_prfx="tsun/", node_id="garagendach/", snr='123'):
|
|
||||||
|
|
||||||
if id == 'out_power_123':
|
|
||||||
assert comp == 'sensor'
|
|
||||||
assert d_json == json.dumps({"name": "Output Power", "stat_t": "tsun/garagendach/batterie", "dev_cla": "power", "stat_cla": "measurement", "uniq_id": "out_power_123", "val_tpl": "{{ (value_json['out']['Power'] | int)}}", "unit_of_meas": "W", "dev": {"name": "Batterie", "sa": "Batterie", "via_device": "controller_123", "mdl": "TSOL-MSxx00", "mf": "TSUN", "ids": ["batterie_123"]}, "o": {"name": "proxy", "sw": "unknown"}})
|
|
||||||
tests +=1
|
|
||||||
elif id == 'daily_gen_123':
|
|
||||||
assert False
|
|
||||||
elif id == 'volt_pv1_123':
|
|
||||||
assert comp == 'sensor'
|
|
||||||
assert d_json == json.dumps({"name": "Voltage", "stat_t": "tsun/garagendach/batterie", "dev_cla": "voltage", "stat_cla": "measurement", "uniq_id": "volt_pv1_123", "val_tpl": "{{ (value_json['pv1']['Voltage'] | float)}}", "unit_of_meas": "V", "ic": "mdi:gauge", "ent_cat": "diagnostic", "dev": {"name": "Module PV1", "sa": "Module PV1", "via_device": "batterie_123", "ids": ["bat_inp_pv1_123"]}, "o": {"name": "proxy", "sw": "unknown"}})
|
|
||||||
tests +=1
|
|
||||||
elif id == 'volt_pv2_123':
|
|
||||||
assert comp == 'sensor'
|
|
||||||
assert d_json == json.dumps({"name": "Voltage", "stat_t": "tsun/garagendach/batterie", "dev_cla": "voltage", "stat_cla": "measurement", "uniq_id": "volt_pv2_123", "val_tpl": "{{ (value_json['pv2']['Voltage'] | float)}}", "unit_of_meas": "V", "ic": "mdi:gauge", "ent_cat": "diagnostic", "dev": {"name": "Module PV2", "sa": "Module PV2", "via_device": "batterie_123", "ids": ["bat_inp_pv2_123"]}, "o": {"name": "proxy", "sw": "unknown"}})
|
|
||||||
tests +=1
|
|
||||||
elif id == 'signal_123':
|
|
||||||
assert comp == 'sensor'
|
|
||||||
assert d_json == json.dumps({})
|
|
||||||
tests +=1
|
|
||||||
elif id == 'inv_count_456':
|
|
||||||
assert False
|
|
||||||
else:
|
|
||||||
print(id)
|
|
||||||
|
|
||||||
assert tests==4
|
|
||||||
|
|
||||||
def test_exception_and_calc(inverter_data: bytes):
|
def test_exception_and_calc(inverter_data: bytes):
|
||||||
|
|
||||||
# patch table to convert temperature from °F to °C
|
# patch table to convert temperature from °F to °C
|
||||||
ofs = RegisterMap.map_02b0[0x420100d8]['offset']
|
ofs = RegisterMap.map[0x420100d8]['offset']
|
||||||
RegisterMap.map_02b0[0x420100d8]['quotient'] = 1.8
|
RegisterMap.map[0x420100d8]['quotient'] = 1.8
|
||||||
RegisterMap.map_02b0[0x420100d8]['offset'] = -32/1.8
|
RegisterMap.map[0x420100d8]['offset'] = -32/1.8
|
||||||
# map PV1_VOLTAGE to invalid register
|
# map PV1_VOLTAGE to invalid register
|
||||||
RegisterMap.map_02b0[0x420100e0]['reg'] = Register.TEST_REG2
|
RegisterMap.map[0x420100e0]['reg'] = Register.TEST_REG2
|
||||||
# set invalid maping entry for OUTPUT_POWER (string instead of dict type)
|
# set invalid maping entry for OUTPUT_POWER (string instead of dict type)
|
||||||
backup = RegisterMap.map_02b0[0x420100de]
|
backup = RegisterMap.map[0x420100de]
|
||||||
RegisterMap.map_02b0[0x420100de] = 'invalid_entry'
|
RegisterMap.map[0x420100de] = 'invalid_entry'
|
||||||
|
|
||||||
i = InfosG3P(client_mode=False)
|
i = InfosG3P(client_mode=False)
|
||||||
i.db.clear()
|
i.db.clear()
|
||||||
|
|
||||||
for key, update in i.parse (inverter_data, 0x42, 1, 0x02b0):
|
for key, update in i.parse (inverter_data, 0x42, 1):
|
||||||
pass # side effect is calling generator i.parse()
|
pass # side effect is calling generator i.parse()
|
||||||
assert math.isclose(12.2222, round (i.get_db_value(Register.INVERTER_TEMP, 0),4), rel_tol=1e-09, abs_tol=1e-09)
|
assert math.isclose(12.2222, round (i.get_db_value(Register.INVERTER_TEMP, 0),4), rel_tol=1e-09, abs_tol=1e-09)
|
||||||
|
|
||||||
build_msg = i.build(len(inverter_data), 0x42, 1, 0x02b0)
|
build_msg = i.build(len(inverter_data), 0x42, 1)
|
||||||
assert build_msg[32:0xde] == inverter_data[32:0xde]
|
assert build_msg[32:0xde] == inverter_data[32:0xde]
|
||||||
assert build_msg[0xde:0xe2] == b'\x00\x00\x00\x00'
|
assert build_msg[0xde:0xe2] == b'\x00\x00\x00\x00'
|
||||||
assert build_msg[0xe2:-1] == inverter_data[0xe2:-1]
|
assert build_msg[0xe2:-1] == inverter_data[0xe2:-1]
|
||||||
|
|
||||||
|
|
||||||
# remove a table entry and test parsing and building
|
# remove a table entry and test parsing and building
|
||||||
del RegisterMap.map_02b0[0x420100d8]['quotient']
|
del RegisterMap.map[0x420100d8]['quotient']
|
||||||
del RegisterMap.map_02b0[0x420100d8]['offset']
|
del RegisterMap.map[0x420100d8]['offset']
|
||||||
|
|
||||||
i.db.clear()
|
i.db.clear()
|
||||||
|
|
||||||
for key, update in i.parse (inverter_data, 0x42, 1, 0x02b0):
|
for key, update in i.parse (inverter_data, 0x42, 1):
|
||||||
pass # side effect is calling generator i.parse()
|
pass # side effect is calling generator i.parse()
|
||||||
assert 54 == i.get_db_value(Register.INVERTER_TEMP, 0)
|
assert 54 == i.get_db_value(Register.INVERTER_TEMP, 0)
|
||||||
|
|
||||||
build_msg = i.build(len(inverter_data), 0x42, 1, 0x02b0)
|
build_msg = i.build(len(inverter_data), 0x42, 1)
|
||||||
assert build_msg[32:0xd8] == inverter_data[32:0xd8]
|
assert build_msg[32:0xd8] == inverter_data[32:0xd8]
|
||||||
assert build_msg[0xd8:0xe2] == b'\x006\x00\x00\x02X\x00\x00\x00\x00'
|
assert build_msg[0xd8:0xe2] == b'\x006\x00\x00\x02X\x00\x00\x00\x00'
|
||||||
assert build_msg[0xe2:-1] == inverter_data[0xe2:-1]
|
assert build_msg[0xe2:-1] == inverter_data[0xe2:-1]
|
||||||
|
|
||||||
# test restore table
|
# test restore table
|
||||||
RegisterMap.map_02b0[0x420100d8]['offset'] = ofs
|
RegisterMap.map[0x420100d8]['offset'] = ofs
|
||||||
RegisterMap.map_02b0[0x420100e0]['reg'] = Register.PV1_VOLTAGE # reset mapping
|
RegisterMap.map[0x420100e0]['reg'] = Register.PV1_VOLTAGE # reset mapping
|
||||||
RegisterMap.map_02b0[0x420100de] = backup # reset mapping
|
RegisterMap.map[0x420100de] = backup # reset mapping
|
||||||
|
|
||||||
# test orginial table
|
# test orginial table
|
||||||
i.db.clear()
|
i.db.clear()
|
||||||
for key, update in i.parse (inverter_data, 0x42, 1, 0x02b0):
|
for key, update in i.parse (inverter_data, 0x42, 1):
|
||||||
pass # side effect is calling generator i.parse()
|
pass # side effect is calling generator i.parse()
|
||||||
assert 14 == i.get_db_value(Register.INVERTER_TEMP, 0)
|
assert 14 == i.get_db_value(Register.INVERTER_TEMP, 0)
|
||||||
|
|
||||||
build_msg = i.build(len(inverter_data), 0x42, 1, 0x02b0)
|
build_msg = i.build(len(inverter_data), 0x42, 1)
|
||||||
assert build_msg[32:-1] == inverter_data[32:-1]
|
assert build_msg[32:-1] == inverter_data[32:-1]
|
||||||
|
|||||||
@@ -7,26 +7,18 @@ from server import get_log_level
|
|||||||
|
|
||||||
def test_get_log_level():
|
def test_get_log_level():
|
||||||
|
|
||||||
with patch.dict(os.environ, {}):
|
with patch.dict(os.environ, {'LOG_LVL': ''}):
|
||||||
log_lvl = get_log_level()
|
log_lvl = get_log_level()
|
||||||
assert log_lvl == None
|
assert log_lvl == logging.INFO
|
||||||
|
|
||||||
with patch.dict(os.environ, {'LOG_LVL': 'DEBUG'}):
|
with patch.dict(os.environ, {'LOG_LVL': 'DEBUG'}):
|
||||||
log_lvl = get_log_level()
|
log_lvl = get_log_level()
|
||||||
assert log_lvl == logging.DEBUG
|
assert log_lvl == logging.DEBUG
|
||||||
|
|
||||||
with patch.dict(os.environ, {'LOG_LVL': 'INFO'}):
|
|
||||||
log_lvl = get_log_level()
|
|
||||||
assert log_lvl == logging.INFO
|
|
||||||
|
|
||||||
with patch.dict(os.environ, {'LOG_LVL': 'WARN'}):
|
with patch.dict(os.environ, {'LOG_LVL': 'WARN'}):
|
||||||
log_lvl = get_log_level()
|
log_lvl = get_log_level()
|
||||||
assert log_lvl == logging.WARNING
|
assert log_lvl == logging.WARNING
|
||||||
|
|
||||||
with patch.dict(os.environ, {'LOG_LVL': 'ERROR'}):
|
|
||||||
log_lvl = get_log_level()
|
|
||||||
assert log_lvl == logging.ERROR
|
|
||||||
|
|
||||||
with patch.dict(os.environ, {'LOG_LVL': 'UNKNOWN'}):
|
with patch.dict(os.environ, {'LOG_LVL': 'UNKNOWN'}):
|
||||||
log_lvl = get_log_level()
|
log_lvl = get_log_level()
|
||||||
assert log_lvl == None
|
assert log_lvl == logging.INFO
|
||||||
|
|||||||
@@ -11,7 +11,6 @@ from cnf.config import Config
|
|||||||
from infos import Infos, Register
|
from infos import Infos, Register
|
||||||
from modbus import Modbus
|
from modbus import Modbus
|
||||||
from messages import State, Message
|
from messages import State, Message
|
||||||
from proxy import Proxy
|
|
||||||
|
|
||||||
|
|
||||||
pytest_plugins = ('pytest_asyncio',)
|
pytest_plugins = ('pytest_asyncio',)
|
||||||
@@ -25,8 +24,6 @@ heartbeat = 60
|
|||||||
|
|
||||||
class Mqtt():
|
class Mqtt():
|
||||||
def __init__(self):
|
def __init__(self):
|
||||||
self.clear()
|
|
||||||
def clear(self):
|
|
||||||
self.key = ''
|
self.key = ''
|
||||||
self.data = ''
|
self.data = ''
|
||||||
|
|
||||||
@@ -53,6 +50,7 @@ class MemoryStream(SolarmanV5):
|
|||||||
self.mb_timeout = 0.5
|
self.mb_timeout = 0.5
|
||||||
self.sent_pdu = b''
|
self.sent_pdu = b''
|
||||||
self.ifc.tx_fifo.reg_trigger(self.write_cb)
|
self.ifc.tx_fifo.reg_trigger(self.write_cb)
|
||||||
|
self.mqtt = Mqtt()
|
||||||
self.__msg = msg
|
self.__msg = msg
|
||||||
self.__msg_len = len(msg)
|
self.__msg_len = len(msg)
|
||||||
self.__chunks = chunks
|
self.__chunks = chunks
|
||||||
@@ -64,6 +62,7 @@ class MemoryStream(SolarmanV5):
|
|||||||
self.db.stat['proxy']['AT_Command'] = 0
|
self.db.stat['proxy']['AT_Command'] = 0
|
||||||
self.db.stat['proxy']['AT_Command_Blocked'] = 0
|
self.db.stat['proxy']['AT_Command_Blocked'] = 0
|
||||||
self.test_exception_async_write = False
|
self.test_exception_async_write = False
|
||||||
|
self.entity_prfx = ''
|
||||||
self.at_acl = {'mqtt': {'allow': ['AT+'], 'block': ['AT+WEBU']}, 'tsun': {'allow': ['AT+Z', 'AT+UPURL', 'AT+SUPDATE', 'AT+TIME'], 'block': ['AT+WEBU']}}
|
self.at_acl = {'mqtt': {'allow': ['AT+'], 'block': ['AT+WEBU']}, 'tsun': {'allow': ['AT+Z', 'AT+UPURL', 'AT+SUPDATE', 'AT+TIME'], 'block': ['AT+WEBU']}}
|
||||||
self.key = ''
|
self.key = ''
|
||||||
self.data = ''
|
self.data = ''
|
||||||
@@ -86,8 +85,8 @@ class MemoryStream(SolarmanV5):
|
|||||||
self.__chunk_idx = 0
|
self.__chunk_idx = 0
|
||||||
|
|
||||||
def publish_mqtt(self, key, data):
|
def publish_mqtt(self, key, data):
|
||||||
Proxy.mqtt.key = key
|
self.key = key
|
||||||
Proxy.mqtt.data = data
|
self.data = data
|
||||||
|
|
||||||
def _read(self) -> int:
|
def _read(self) -> int:
|
||||||
copied_bytes = 0
|
copied_bytes = 0
|
||||||
@@ -131,12 +130,6 @@ def get_sn() -> bytes:
|
|||||||
def get_sn_int() -> int:
|
def get_sn_int() -> int:
|
||||||
return 2070233889
|
return 2070233889
|
||||||
|
|
||||||
def get_dcu_sn() -> bytes:
|
|
||||||
return b'\x20\x43\x65\x7b'
|
|
||||||
|
|
||||||
def get_dcu_sn_int() -> int:
|
|
||||||
return 2070233888
|
|
||||||
|
|
||||||
def get_inv_no() -> bytes:
|
def get_inv_no() -> bytes:
|
||||||
return b'T170000000000001'
|
return b'T170000000000001'
|
||||||
|
|
||||||
@@ -567,17 +560,6 @@ def at_command_rsp_msg(): # 0x1510
|
|||||||
msg += b'\x15'
|
msg += b'\x15'
|
||||||
return msg
|
return msg
|
||||||
|
|
||||||
@pytest.fixture
|
|
||||||
def at_command_interim_rsp_msg(): # 0x0510
|
|
||||||
msg = b'\xa5\x25\x00\x10\x05\x03\x03' +get_sn() +b'\x08\x01'
|
|
||||||
msg += total()
|
|
||||||
msg += hb()
|
|
||||||
msg += b'\x00\x00\x00\x00+ok=10\x2c'
|
|
||||||
msg += b'start download\x0d\x0a'
|
|
||||||
msg += correct_checksum(msg)
|
|
||||||
msg += b'\x15'
|
|
||||||
return msg
|
|
||||||
|
|
||||||
@pytest.fixture
|
@pytest.fixture
|
||||||
def heartbeat_ind_msg(): # 0x4710
|
def heartbeat_ind_msg(): # 0x4710
|
||||||
msg = b'\xa5\x01\x00\x10\x47\x10\x84' +get_sn()
|
msg = b'\xa5\x01\x00\x10\x47\x10\x84' +get_sn()
|
||||||
@@ -633,15 +615,6 @@ def msg_modbus_cmd_fwd():
|
|||||||
msg += b'\x15'
|
msg += b'\x15'
|
||||||
return msg
|
return msg
|
||||||
|
|
||||||
@pytest.fixture
|
|
||||||
def msg_modbus_cmd_seq():
|
|
||||||
msg = b'\xa5\x17\x00\x10\x45\x03\x02' +get_sn() +b'\x05\x26\x30\x00\x00'
|
|
||||||
msg += b'\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01\x01\x06\x01\x00\x01'
|
|
||||||
msg += b'\x03\xe8'
|
|
||||||
msg += correct_checksum(msg)
|
|
||||||
msg += b'\x15'
|
|
||||||
return msg
|
|
||||||
|
|
||||||
@pytest.fixture
|
@pytest.fixture
|
||||||
def msg_modbus_cmd_crc_err():
|
def msg_modbus_cmd_crc_err():
|
||||||
msg = b'\xa5\x17\x00\x10\x45\x03\x02' +get_sn() +b'\x02\xb0\x02'
|
msg = b'\xa5\x17\x00\x10\x45\x03\x02' +get_sn() +b'\x02\xb0\x02'
|
||||||
@@ -664,32 +637,6 @@ def msg_modbus_rsp(): # 0x1510
|
|||||||
msg += b'\x15'
|
msg += b'\x15'
|
||||||
return msg
|
return msg
|
||||||
|
|
||||||
@pytest.fixture
|
|
||||||
def msg_modbus_interim_rsp(): # 0x0510
|
|
||||||
msg = b'\xa5\x3b\x00\x10\x15\x03\x03' +get_sn() +b'\x02\x01'
|
|
||||||
msg += total()
|
|
||||||
msg += hb()
|
|
||||||
msg += b'\x0a\xe2\xfa\x33\x01\x03\x28\x40\x10\x08\xd8'
|
|
||||||
msg += b'\x00\x00\x13\x87\x00\x31\x00\x68\x02\x58\x00\x00\x01\x53\x00\x02'
|
|
||||||
msg += b'\x00\x00\x01\x52\x00\x02\x00\x00\x01\x53\x00\x03\x00\x00\x00\x04'
|
|
||||||
msg += b'\x00\x01\x00\x00\x6c\x68'
|
|
||||||
msg += correct_checksum(msg)
|
|
||||||
msg += b'\x15'
|
|
||||||
return msg
|
|
||||||
|
|
||||||
@pytest.fixture
|
|
||||||
def msg_modbus_rsp_inv_id2(): # 0x1510
|
|
||||||
msg = b'\xa5\x3b\x00\x10\x15\x03\x03' +get_sn() +b'\x02\x01'
|
|
||||||
msg += total()
|
|
||||||
msg += hb()
|
|
||||||
msg += b'\x0a\xe2\xfa\x33\x02\x03\x28\x40\x10\x08\xd8'
|
|
||||||
msg += b'\x00\x00\x13\x87\x00\x31\x00\x68\x02\x58\x00\x00\x01\x53\x00\x02'
|
|
||||||
msg += b'\x00\x00\x01\x52\x00\x02\x00\x00\x01\x53\x00\x03\x00\x00\x00\x04'
|
|
||||||
msg += b'\x00\x01\x00\x00\x2a\xaa'
|
|
||||||
msg += correct_checksum(msg)
|
|
||||||
msg += b'\x15'
|
|
||||||
return msg
|
|
||||||
|
|
||||||
@pytest.fixture
|
@pytest.fixture
|
||||||
def msg_modbus_invalid(): # 0x1510
|
def msg_modbus_invalid(): # 0x1510
|
||||||
msg = b'\xa5\x3b\x00\x10\x15\x03\x03' +get_sn() +b'\x02\x00'
|
msg = b'\xa5\x3b\x00\x10\x15\x03\x03' +get_sn() +b'\x02\x00'
|
||||||
@@ -725,94 +672,9 @@ def msg_unknown_cmd_rsp(): # 0x1510
|
|||||||
msg += b'\x15'
|
msg += b'\x15'
|
||||||
return msg
|
return msg
|
||||||
|
|
||||||
@pytest.fixture
|
|
||||||
def dcu_modbus_rsp(): # 0x1510
|
|
||||||
msg = b'\xa5\x6d\x00\x10\x15\x03\x03' +get_dcu_sn() +b'\x02\x01'
|
|
||||||
msg += total()
|
|
||||||
msg += hb()
|
|
||||||
msg += b'\x4d\x0d\x84\x34\x01\x03\x5a\x34\x31\x30\x31'
|
|
||||||
msg += b'\x32\x34\x30\x37\x30\x31\x34\x39\x30\x33\x31\x34\x00\x32\x00\x00'
|
|
||||||
msg += b'\x00\x32\x00\x00\x00\x00\x10\x7b\x00\x02\x00\x02\x14\x9b\xfe\xfd'
|
|
||||||
msg += b'\x25\x28\x0c\xe1\x0c\xde\x0c\xe1\x0c\xe1\x0c\xe0\x0c\xe1\x0c\xe3'
|
|
||||||
msg += b'\x0c\xdf\x0c\xe0\x0c\xe2\x0c\xe1\x0c\xe1\x0c\xe2\x0c\xe2\x0c\xe3'
|
|
||||||
msg += b'\x0c\xdf\x00\x14\x00\x14\x00\x13\x0f\x94\x01\x4a\x00\x01\x00\x15'
|
|
||||||
msg += b'\x00\x00\x02\x05\x02\x01\x14\xab'
|
|
||||||
msg += correct_checksum(msg)
|
|
||||||
msg += b'\x15'
|
|
||||||
return msg
|
|
||||||
|
|
||||||
@pytest.fixture
|
|
||||||
def dcu_dev_ind_msg(): # 0x4110
|
|
||||||
msg = b'\xa5\x3a\x01\x10\x41\x91\x01' +get_dcu_sn() +b'\x02\xc6\xde\x2d\x32'
|
|
||||||
msg += b'\x27\x00\x00\x00\x00\x00\x00\x00\x05\x3c\x78\x01\x5c\x01\x4c\x53'
|
|
||||||
msg += b'\x57\x35\x5f\x30\x31\x5f\x33\x30\x32\x36\x5f\x4e\x53\x5f\x30\x35'
|
|
||||||
msg += b'\x5f\x30\x31\x2e\x30\x30\x2e\x30\x30\x2e\x30\x30\x00\x00\x00\x00'
|
|
||||||
msg += b'\x00\x00\x00\x00\x00\x00\xd4\x27\x87\x12\xad\xc0\x31\x39\x32\x2e'
|
|
||||||
msg += b'\x31\x36\x38\x2e\x39\x2e\x31\x34\x00\x00\x00\x00\x01\x00\x01\x26'
|
|
||||||
msg += b'\x30\x0f\x00\xff\x56\x31\x2e\x31\x2e\x30\x30\x2e\x30\x42\x00\x00'
|
|
||||||
msg += b'\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00'
|
|
||||||
msg += b'\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\xfe\xfe\x00\x00'
|
|
||||||
msg += b'\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00'
|
|
||||||
msg += b'\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00'
|
|
||||||
msg += b'\x00\x00\x00\x00\x00\x00\x00\x7a\x75\x68\x61\x75\x73\x65\x00\x00'
|
|
||||||
msg += b'\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00'
|
|
||||||
msg += b'\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00'
|
|
||||||
msg += b'\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00'
|
|
||||||
msg += b'\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00'
|
|
||||||
msg += b'\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00'
|
|
||||||
msg += b'\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00'
|
|
||||||
msg += b'\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00'
|
|
||||||
msg += b'\x00\x00\x00\x00\x00\x00\x00\x00\x08\x01\x01\x01\x00\x00\x00\x00'
|
|
||||||
msg += b'\x00\x00\x00\x00\x01'
|
|
||||||
msg += correct_checksum(msg)
|
|
||||||
msg += b'\x15'
|
|
||||||
return msg
|
|
||||||
|
|
||||||
@pytest.fixture
|
|
||||||
def dcu_dev_rsp_msg(): # 0x1110
|
|
||||||
msg = b'\xa5\x0a\x00\x10\x11\x92\x01' +get_dcu_sn() +b'\x02\x01'
|
|
||||||
msg += total()
|
|
||||||
msg += hb()
|
|
||||||
msg += correct_checksum(msg)
|
|
||||||
msg += b'\x15'
|
|
||||||
return msg
|
|
||||||
|
|
||||||
@pytest.fixture
|
|
||||||
def dcu_data_ind_msg(): # 0x4210
|
|
||||||
msg = b'\xa5\x6f\x00\x10\x42\x92\x02' +get_dcu_sn() +b'\x01\x26\x30\xc7\xde'
|
|
||||||
msg += b'\x2d\x32\x28\x00\x00\x00\x84\x17\x79\x35\x01\x00\x4c\x12\x00\x00'
|
|
||||||
msg += b'\x34\x31\x30\x31\x32\x34\x30\x37\x30\x31\x34\x39\x30\x33\x31\x34'
|
|
||||||
msg += b'\x0d\x3a\x00\x00\x0d\x2c\x00\x00\x00\x00\x08\x20\x00\x00\x00\x00'
|
|
||||||
msg += b'\x14\x0e\xff\xfe\x03\xe8\x0c\x89\x0c\x89\x0c\x89\x0c\x8a\x0c\x89'
|
|
||||||
msg += b'\x0c\x89\x0c\x8a\x0c\x89\x0c\x89\x0c\x8a\x0c\x8a\x0c\x89\x0c\x89'
|
|
||||||
msg += b'\x0c\x89\x0c\x89\x0c\x88\x00\x0f\x00\x0f\x00\x0f\x00\x0e\x00\x00'
|
|
||||||
msg += b'\x00\x00\x00\x0f\x00\x00\x02\x05\x02\x01'
|
|
||||||
msg += correct_checksum(msg)
|
|
||||||
msg += b'\x15'
|
|
||||||
return msg
|
|
||||||
|
|
||||||
@pytest.fixture
|
|
||||||
def dcu_data_rsp_msg(): # 0x1210
|
|
||||||
msg = b'\xa5\x0a\x00\x10\x12\x93\x02' +get_dcu_sn() +b'\x01\x01'
|
|
||||||
msg += total()
|
|
||||||
msg += hb()
|
|
||||||
msg += correct_checksum(msg)
|
|
||||||
msg += b'\x15'
|
|
||||||
return msg
|
|
||||||
|
|
||||||
@pytest.fixture
|
@pytest.fixture
|
||||||
def config_tsun_allow_all():
|
def config_tsun_allow_all():
|
||||||
Config.act_config = {
|
Config.act_config = {'solarman':{'enabled': True}, 'inverters':{'allow_all':True}}
|
||||||
'ha':{
|
|
||||||
'auto_conf_prefix': 'homeassistant',
|
|
||||||
'discovery_prefix': 'homeassistant',
|
|
||||||
'entity_prefix': 'tsun',
|
|
||||||
'proxy_node_id': 'test_1',
|
|
||||||
'proxy_unique_id': ''
|
|
||||||
},
|
|
||||||
'solarman':{'enabled': True}, 'inverters':{'allow_all':True}}
|
|
||||||
Proxy.class_init()
|
|
||||||
Proxy.mqtt = Mqtt() # set dummy mqtt instance
|
|
||||||
|
|
||||||
@pytest.fixture
|
@pytest.fixture
|
||||||
def config_no_tsun_inv1():
|
def config_no_tsun_inv1():
|
||||||
@@ -820,29 +682,7 @@ def config_no_tsun_inv1():
|
|||||||
|
|
||||||
@pytest.fixture
|
@pytest.fixture
|
||||||
def config_tsun_inv1():
|
def config_tsun_inv1():
|
||||||
Config.act_config = {
|
Config.act_config = {'solarman':{'enabled': True},'inverters':{'Y170000000000001':{'monitor_sn': 2070233889, 'node_id':'inv1', 'modbus_polling': True, 'suggested_area':'roof', 'sensor_list': 688}}}
|
||||||
'ha':{
|
|
||||||
'auto_conf_prefix': 'homeassistant',
|
|
||||||
'discovery_prefix': 'homeassistant',
|
|
||||||
'entity_prefix': 'tsun',
|
|
||||||
'proxy_node_id': 'test_1',
|
|
||||||
'proxy_unique_id': ''
|
|
||||||
},
|
|
||||||
'solarman':{'enabled': True},'inverters':{'Y170000000000001':{'monitor_sn': 2070233889, 'node_id':'inv1', 'modbus_polling': True, 'suggested_area':'roof', 'sensor_list': 0}}}
|
|
||||||
Proxy.class_init()
|
|
||||||
Proxy.mqtt = Mqtt()
|
|
||||||
|
|
||||||
@pytest.fixture
|
|
||||||
def config_tsun_scan():
|
|
||||||
Config.act_config = {'solarman':{'enabled': True},'inverters':{'Y170000000000001':{'monitor_sn': 2070233889, 'node_id':'inv1', 'modbus_polling': True, 'modbus_scanning': {'start': 0xffc0, 'step': 0x40, 'bytes':20}, 'suggested_area':'roof', 'sensor_list': 0}}}
|
|
||||||
|
|
||||||
@pytest.fixture
|
|
||||||
def config_tsun_scan_dcu():
|
|
||||||
Config.act_config = {'solarman':{'enabled': True},'inverters':{'4100000000000001':{'monitor_sn': 2070233888, 'node_id':'inv1', 'modbus_polling': True, 'modbus_scanning': {'start': 0x0000, 'step': 0x100, 'bytes':0x2d}, 'client_mode': {'host': '192.168.1.1.'}, 'suggested_area':'roof', 'sensor_list': 0}}}
|
|
||||||
|
|
||||||
@pytest.fixture
|
|
||||||
def config_tsun_dcu1():
|
|
||||||
Config.act_config = {'solarman':{'enabled': True},'batteries':{'4100000000000001':{'monitor_sn': 2070233888, 'node_id':'inv1', 'modbus_polling': True, 'suggested_area':'roof', 'sensor_list': 0}}}
|
|
||||||
|
|
||||||
def test_read_message(device_ind_msg):
|
def test_read_message(device_ind_msg):
|
||||||
Config.act_config = {'solarman':{'enabled': True}}
|
Config.act_config = {'solarman':{'enabled': True}}
|
||||||
@@ -1123,34 +963,6 @@ def test_read_two_messages3(config_tsun_allow_all, device_ind_msg2, device_rsp_m
|
|||||||
assert m.ifc.tx_fifo.get()==b''
|
assert m.ifc.tx_fifo.get()==b''
|
||||||
m.close()
|
m.close()
|
||||||
|
|
||||||
def test_read_two_messages4(config_tsun_dcu1, dcu_dev_ind_msg, dcu_dev_rsp_msg, dcu_data_ind_msg, dcu_data_rsp_msg):
|
|
||||||
_ = config_tsun_dcu1
|
|
||||||
m = MemoryStream(dcu_dev_ind_msg, (0,))
|
|
||||||
m.append_msg(dcu_data_ind_msg)
|
|
||||||
assert 0 == m.sensor_list
|
|
||||||
m._init_new_client_conn()
|
|
||||||
m.read() # read complete msg, and dispatch msg
|
|
||||||
assert m.db.stat['proxy']['Invalid_Msg_Format'] == 0
|
|
||||||
assert not m.header_valid # must be invalid, since msg was handled and buffer flushed
|
|
||||||
assert m.msg_count == 2
|
|
||||||
assert m.header_len==11
|
|
||||||
assert m.snr == 2070233888
|
|
||||||
assert m.unique_id == '2070233888'
|
|
||||||
assert m.msg_recvd[0]['control']==0x4110
|
|
||||||
assert m.msg_recvd[0]['seq']=='01:92'
|
|
||||||
assert m.msg_recvd[0]['data_len']==314
|
|
||||||
assert m.msg_recvd[1]['control']==0x4210
|
|
||||||
assert m.msg_recvd[1]['seq']=='02:93'
|
|
||||||
assert m.msg_recvd[1]['data_len']==111
|
|
||||||
assert '3026' == m.db.get_db_value(Register.SENSOR_LIST, None)
|
|
||||||
assert 0x3026 == m.sensor_list
|
|
||||||
assert m.ifc.fwd_fifo.get()==dcu_dev_ind_msg+dcu_data_ind_msg
|
|
||||||
assert m.ifc.tx_fifo.get()==dcu_dev_rsp_msg+dcu_data_rsp_msg
|
|
||||||
|
|
||||||
m._init_new_client_conn()
|
|
||||||
assert m.ifc.tx_fifo.get()==b''
|
|
||||||
m.close()
|
|
||||||
|
|
||||||
def test_unkown_frame_code(config_tsun_inv1, inverter_ind_msg_81, inverter_rsp_msg_81):
|
def test_unkown_frame_code(config_tsun_inv1, inverter_ind_msg_81, inverter_rsp_msg_81):
|
||||||
_ = config_tsun_inv1
|
_ = config_tsun_inv1
|
||||||
m = MemoryStream(inverter_ind_msg_81, (0,))
|
m = MemoryStream(inverter_ind_msg_81, (0,))
|
||||||
@@ -1519,8 +1331,8 @@ async def test_at_cmd(config_tsun_allow_all, device_ind_msg, device_rsp_msg, inv
|
|||||||
assert m.ifc.fwd_fifo.get()==b''
|
assert m.ifc.fwd_fifo.get()==b''
|
||||||
assert m.sent_pdu == b''
|
assert m.sent_pdu == b''
|
||||||
assert str(m.seq) == '01:01'
|
assert str(m.seq) == '01:01'
|
||||||
assert Proxy.mqtt.key == ''
|
assert m.mqtt.key == ''
|
||||||
assert Proxy.mqtt.data == ""
|
assert m.mqtt.data == ""
|
||||||
|
|
||||||
m.append_msg(inverter_ind_msg)
|
m.append_msg(inverter_ind_msg)
|
||||||
m.read() # read inverter ind
|
m.read() # read inverter ind
|
||||||
@@ -1536,8 +1348,8 @@ async def test_at_cmd(config_tsun_allow_all, device_ind_msg, device_rsp_msg, inv
|
|||||||
m.sent_pdu = bytearray()
|
m.sent_pdu = bytearray()
|
||||||
|
|
||||||
assert str(m.seq) == '02:03'
|
assert str(m.seq) == '02:03'
|
||||||
assert Proxy.mqtt.key == ''
|
assert m.mqtt.key == ''
|
||||||
assert Proxy.mqtt.data == ""
|
assert m.mqtt.data == ""
|
||||||
|
|
||||||
m.append_msg(at_command_rsp_msg)
|
m.append_msg(at_command_rsp_msg)
|
||||||
m.read() # read at resp
|
m.read() # read at resp
|
||||||
@@ -1546,9 +1358,8 @@ async def test_at_cmd(config_tsun_allow_all, device_ind_msg, device_rsp_msg, inv
|
|||||||
assert m.ifc.rx_get()==b''
|
assert m.ifc.rx_get()==b''
|
||||||
assert m.ifc.tx_fifo.get()==b''
|
assert m.ifc.tx_fifo.get()==b''
|
||||||
assert m.ifc.fwd_fifo.get()==b''
|
assert m.ifc.fwd_fifo.get()==b''
|
||||||
assert Proxy.mqtt.key == 'tsun/at_resp'
|
assert m.key == 'at_resp'
|
||||||
assert Proxy.mqtt.data == "+ok"
|
assert m.data == "+ok"
|
||||||
Proxy.mqtt.clear() # clear last test result
|
|
||||||
|
|
||||||
m.sent_pdu = bytearray()
|
m.sent_pdu = bytearray()
|
||||||
m.test_exception_async_write = True
|
m.test_exception_async_write = True
|
||||||
@@ -1560,8 +1371,8 @@ async def test_at_cmd(config_tsun_allow_all, device_ind_msg, device_rsp_msg, inv
|
|||||||
assert m.sent_pdu == b''
|
assert m.sent_pdu == b''
|
||||||
assert str(m.seq) == '03:04'
|
assert str(m.seq) == '03:04'
|
||||||
assert m.forward_at_cmd_resp == False
|
assert m.forward_at_cmd_resp == False
|
||||||
assert Proxy.mqtt.key == ''
|
assert m.mqtt.key == ''
|
||||||
assert Proxy.mqtt.data == ""
|
assert m.mqtt.data == ""
|
||||||
m.close()
|
m.close()
|
||||||
|
|
||||||
@pytest.mark.asyncio
|
@pytest.mark.asyncio
|
||||||
@@ -1578,8 +1389,8 @@ async def test_at_cmd_blocked(config_tsun_allow_all, device_ind_msg, device_rsp_
|
|||||||
assert m.ifc.tx_fifo.get()==b''
|
assert m.ifc.tx_fifo.get()==b''
|
||||||
assert m.ifc.fwd_fifo.get()==b''
|
assert m.ifc.fwd_fifo.get()==b''
|
||||||
assert str(m.seq) == '01:01'
|
assert str(m.seq) == '01:01'
|
||||||
assert Proxy.mqtt.key == ''
|
assert m.mqtt.key == ''
|
||||||
assert Proxy.mqtt.data == ""
|
assert m.mqtt.data == ""
|
||||||
|
|
||||||
m.append_msg(inverter_ind_msg)
|
m.append_msg(inverter_ind_msg)
|
||||||
m.read()
|
m.read()
|
||||||
@@ -1595,8 +1406,8 @@ async def test_at_cmd_blocked(config_tsun_allow_all, device_ind_msg, device_rsp_
|
|||||||
assert m.ifc.fwd_fifo.get()==b''
|
assert m.ifc.fwd_fifo.get()==b''
|
||||||
assert str(m.seq) == '02:02'
|
assert str(m.seq) == '02:02'
|
||||||
assert m.forward_at_cmd_resp == False
|
assert m.forward_at_cmd_resp == False
|
||||||
assert Proxy.mqtt.key == 'tsun/at_resp'
|
assert m.mqtt.key == 'at_resp'
|
||||||
assert Proxy.mqtt.data == "'AT+WEBU' is forbidden"
|
assert m.mqtt.data == "'AT+WEBU' is forbidden"
|
||||||
m.close()
|
m.close()
|
||||||
|
|
||||||
def test_at_cmd_ind(config_tsun_inv1, at_command_ind_msg):
|
def test_at_cmd_ind(config_tsun_inv1, at_command_ind_msg):
|
||||||
@@ -1685,29 +1496,6 @@ def test_msg_at_command_rsp2(config_tsun_inv1, at_command_rsp_msg):
|
|||||||
assert m.db.stat['proxy']['Modbus_Command'] == 0
|
assert m.db.stat['proxy']['Modbus_Command'] == 0
|
||||||
m.close()
|
m.close()
|
||||||
|
|
||||||
def test_msg_at_command_rsp3(config_tsun_inv1, at_command_interim_rsp_msg):
|
|
||||||
_ = config_tsun_inv1
|
|
||||||
m = MemoryStream(at_command_interim_rsp_msg)
|
|
||||||
m.db.stat['proxy']['Unknown_Ctrl'] = 0
|
|
||||||
m.db.stat['proxy']['Modbus_Command'] = 0
|
|
||||||
m.db.stat['proxy']['Invalid_Msg_Format'] = 0
|
|
||||||
m.db.stat['proxy']['Unknown_Msg'] = 0
|
|
||||||
m.forward_at_cmd_resp = True
|
|
||||||
m.read() # read complete msg, and dispatch msg
|
|
||||||
assert not m.header_valid # must be invalid, since msg was handled and buffer flushed
|
|
||||||
assert m.msg_count == 1
|
|
||||||
assert m.control == 0x0510
|
|
||||||
assert str(m.seq) == '03:03'
|
|
||||||
assert m.header_len==11
|
|
||||||
assert m.data_len==37
|
|
||||||
assert m.ifc.fwd_fifo.get()==at_command_interim_rsp_msg
|
|
||||||
assert m.ifc.tx_fifo.get()==b''
|
|
||||||
assert m.db.stat['proxy']['Unknown_Ctrl'] == 0
|
|
||||||
assert m.db.stat['proxy']['Modbus_Command'] == 0
|
|
||||||
assert m.db.stat['proxy']['Invalid_Msg_Format'] == 0
|
|
||||||
assert m.db.stat['proxy']['Unknown_Msg'] == 0
|
|
||||||
m.close()
|
|
||||||
|
|
||||||
def test_msg_modbus_req(config_tsun_inv1, msg_modbus_cmd, msg_modbus_cmd_fwd):
|
def test_msg_modbus_req(config_tsun_inv1, msg_modbus_cmd, msg_modbus_cmd_fwd):
|
||||||
_ = config_tsun_inv1
|
_ = config_tsun_inv1
|
||||||
m = MemoryStream(b'')
|
m = MemoryStream(b'')
|
||||||
@@ -1736,34 +1524,6 @@ def test_msg_modbus_req(config_tsun_inv1, msg_modbus_cmd, msg_modbus_cmd_fwd):
|
|||||||
assert m.db.stat['proxy']['Invalid_Msg_Format'] == 0
|
assert m.db.stat['proxy']['Invalid_Msg_Format'] == 0
|
||||||
m.close()
|
m.close()
|
||||||
|
|
||||||
def test_msg_modbus_req_seq(config_tsun_inv1, msg_modbus_cmd_seq):
|
|
||||||
_ = config_tsun_inv1
|
|
||||||
m = MemoryStream(b'')
|
|
||||||
m.snr = get_sn_int()
|
|
||||||
m.sensor_list = 0x2b0
|
|
||||||
m.state = State.up
|
|
||||||
c = m.createClientStream(msg_modbus_cmd_seq)
|
|
||||||
|
|
||||||
m.db.stat['proxy']['Unknown_Ctrl'] = 0
|
|
||||||
m.db.stat['proxy']['AT_Command'] = 0
|
|
||||||
m.db.stat['proxy']['Modbus_Command'] = 0
|
|
||||||
m.db.stat['proxy']['Invalid_Msg_Format'] = 0
|
|
||||||
c.read() # read complete msg, and dispatch msg
|
|
||||||
assert not c.header_valid # must be invalid, since msg was handled and buffer flushed
|
|
||||||
assert c.msg_count == 1
|
|
||||||
assert c.control == 0x4510
|
|
||||||
assert str(c.seq) == '03:02'
|
|
||||||
assert c.header_len==11
|
|
||||||
assert c.data_len==23
|
|
||||||
assert c.ifc.fwd_fifo.get()==msg_modbus_cmd_seq
|
|
||||||
assert c.ifc.tx_fifo.get()==b''
|
|
||||||
assert m.sent_pdu == b''
|
|
||||||
assert m.db.stat['proxy']['Unknown_Ctrl'] == 0
|
|
||||||
assert m.db.stat['proxy']['AT_Command'] == 0
|
|
||||||
assert m.db.stat['proxy']['Modbus_Command'] == 0
|
|
||||||
assert m.db.stat['proxy']['Invalid_Msg_Format'] == 0
|
|
||||||
m.close()
|
|
||||||
|
|
||||||
def test_msg_modbus_req2(config_tsun_inv1, msg_modbus_cmd_crc_err):
|
def test_msg_modbus_req2(config_tsun_inv1, msg_modbus_cmd_crc_err):
|
||||||
_ = config_tsun_inv1
|
_ = config_tsun_inv1
|
||||||
m = MemoryStream(b'')
|
m = MemoryStream(b'')
|
||||||
@@ -2002,79 +1762,6 @@ async def test_modbus_polling(config_tsun_inv1, heartbeat_ind_msg, heartbeat_rsp
|
|||||||
assert next(m.mb_timer.exp_count) == 4
|
assert next(m.mb_timer.exp_count) == 4
|
||||||
m.close()
|
m.close()
|
||||||
|
|
||||||
@pytest.mark.asyncio
|
|
||||||
async def test_modbus_scaning(config_tsun_scan, heartbeat_ind_msg, heartbeat_rsp_msg, msg_modbus_rsp, msg_modbus_rsp_inv_id2):
|
|
||||||
_ = config_tsun_scan
|
|
||||||
assert asyncio.get_running_loop()
|
|
||||||
|
|
||||||
m = MemoryStream(heartbeat_ind_msg, (0x15,0x56,0))
|
|
||||||
m.append_msg(msg_modbus_rsp)
|
|
||||||
m.append_msg(msg_modbus_rsp_inv_id2)
|
|
||||||
assert m.mb_scan == False
|
|
||||||
assert asyncio.get_running_loop() == m.mb_timer.loop
|
|
||||||
m.db.stat['proxy']['Unknown_Ctrl'] = 0
|
|
||||||
assert m.mb_timer.tim == None
|
|
||||||
m.read() # read complete msg, and dispatch msg
|
|
||||||
assert m.mb_scan == True
|
|
||||||
assert m.mb_start_reg == 0xff80
|
|
||||||
assert m.mb_step == 0x40
|
|
||||||
assert m.mb_bytes == 0x14
|
|
||||||
assert asyncio.get_running_loop() == m.mb_timer.loop
|
|
||||||
|
|
||||||
assert not m.header_valid # must be invalid, since msg was handled and buffer flushed
|
|
||||||
assert m.msg_count == 1
|
|
||||||
assert m.snr == 2070233889
|
|
||||||
assert m.control == 0x4710
|
|
||||||
|
|
||||||
assert m.msg_recvd[0]['control']==0x4710
|
|
||||||
assert m.msg_recvd[0]['seq']=='84:11'
|
|
||||||
assert m.msg_recvd[0]['data_len']==0x1
|
|
||||||
|
|
||||||
assert m.ifc.tx_fifo.get()==heartbeat_rsp_msg
|
|
||||||
assert m.ifc.fwd_fifo.get()==heartbeat_ind_msg
|
|
||||||
assert m.db.stat['proxy']['Unknown_Ctrl'] == 0
|
|
||||||
|
|
||||||
m.ifc.tx_clear() # clear send buffer for next test
|
|
||||||
assert isclose(m.mb_timeout, 0.5)
|
|
||||||
assert next(m.mb_timer.exp_count) == 0
|
|
||||||
|
|
||||||
await asyncio.sleep(0.5)
|
|
||||||
assert m.sent_pdu==b'\xa5\x17\x00\x10E\x12\x84!Ce{\x02\xb0\x02\x00\x00\x00\x00\x00\x00' \
|
|
||||||
b'\x00\x00\x00\x00\x00\x00\x01\x03\xff\xc0\x00\x14\x75\xed\x33\x15'
|
|
||||||
assert m.ifc.tx_fifo.get()==b''
|
|
||||||
|
|
||||||
m.read() # read complete msg, and dispatch msg
|
|
||||||
assert not m.header_valid # must be invalid, since msg was handled and buffer flushed
|
|
||||||
assert m.msg_count == 2
|
|
||||||
assert m.msg_recvd[1]['control']==0x1510
|
|
||||||
assert m.msg_recvd[1]['seq']=='03:03'
|
|
||||||
assert m.msg_recvd[1]['data_len']==0x3b
|
|
||||||
assert m.mb.last_addr == 1
|
|
||||||
assert m.mb.last_fcode == 3
|
|
||||||
assert m.mb.last_reg == 0xffc0 # mb_start_reg + mb_step
|
|
||||||
assert m.mb.last_len == 20
|
|
||||||
assert m.mb.err == 0
|
|
||||||
|
|
||||||
await asyncio.sleep(0.5)
|
|
||||||
assert m.sent_pdu==b'\xa5\x17\x00\x10E\x04\x03!Ce{\x02\xb0\x02\x00\x00\x00\x00\x00\x00' \
|
|
||||||
b'\x00\x00\x00\x00\x00\x00\x02\x03\x00\x00\x00\x14\x45\xf6\xbf\x15'
|
|
||||||
assert m.ifc.tx_fifo.get()==b''
|
|
||||||
|
|
||||||
m.read() # read complete msg, and dispatch msg
|
|
||||||
assert not m.header_valid # must be invalid, since msg was handled and buffer flushed
|
|
||||||
assert m.msg_count == 3
|
|
||||||
assert m.msg_recvd[2]['control']==0x1510
|
|
||||||
assert m.msg_recvd[2]['seq']=='03:03'
|
|
||||||
assert m.msg_recvd[2]['data_len']==0x3b
|
|
||||||
assert m.mb.last_addr == 2
|
|
||||||
assert m.mb.last_fcode == 3
|
|
||||||
assert m.mb.last_reg == 0x0000 # mb_start_reg + mb_step
|
|
||||||
assert m.mb.last_len == 20
|
|
||||||
assert m.mb.err == 0
|
|
||||||
|
|
||||||
assert next(m.mb_timer.exp_count) == 3
|
|
||||||
m.close()
|
|
||||||
|
|
||||||
@pytest.mark.asyncio
|
@pytest.mark.asyncio
|
||||||
async def test_start_client_mode(config_tsun_inv1, str_test_ip):
|
async def test_start_client_mode(config_tsun_inv1, str_test_ip):
|
||||||
_ = config_tsun_inv1
|
_ = config_tsun_inv1
|
||||||
@@ -2107,79 +1794,6 @@ async def test_start_client_mode(config_tsun_inv1, str_test_ip):
|
|||||||
assert next(m.mb_timer.exp_count) == 3
|
assert next(m.mb_timer.exp_count) == 3
|
||||||
m.close()
|
m.close()
|
||||||
|
|
||||||
@pytest.mark.asyncio
|
|
||||||
async def test_start_client_mode_scan(config_tsun_scan_dcu, str_test_ip, dcu_modbus_rsp):
|
|
||||||
_ = config_tsun_scan_dcu
|
|
||||||
assert asyncio.get_running_loop()
|
|
||||||
m = MemoryStream(dcu_modbus_rsp, (131,0,))
|
|
||||||
m.append_msg(dcu_modbus_rsp)
|
|
||||||
assert m.state == State.init
|
|
||||||
assert m.no_forwarding == False
|
|
||||||
assert m.mb_timer.tim == None
|
|
||||||
assert asyncio.get_running_loop() == m.mb_timer.loop
|
|
||||||
await m.send_start_cmd(get_dcu_sn_int(), str_test_ip, False, m.mb_first_timeout)
|
|
||||||
assert m.mb_start_reg == 0x0000
|
|
||||||
assert m.mb_step == 0x100
|
|
||||||
assert m.mb_bytes == 0x2d
|
|
||||||
|
|
||||||
assert m.sent_pdu==bytearray(b'\xa5\x17\x00\x10E\x01\x00 Ce{\x02&0\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01\x03\x00\x00\x00-\x85\xd7\x95\x15')
|
|
||||||
assert m.mb_scan == True
|
|
||||||
m.mb_step = 0
|
|
||||||
assert m.db.get_db_value(Register.IP_ADDRESS) == str_test_ip
|
|
||||||
assert isclose(m.db.get_db_value(Register.POLLING_INTERVAL), 0.5)
|
|
||||||
assert m.db.get_db_value(Register.HEARTBEAT_INTERVAL) == 120
|
|
||||||
|
|
||||||
assert m.state == State.up
|
|
||||||
assert m.no_forwarding == True
|
|
||||||
|
|
||||||
assert m.ifc.tx_fifo.get()==b''
|
|
||||||
assert isclose(m.mb_timeout, 0.5)
|
|
||||||
|
|
||||||
assert m.ifc.tx_fifo.get()==b''
|
|
||||||
|
|
||||||
m.read() # read complete msg, and dispatch msg
|
|
||||||
assert not m.header_valid # must be invalid, since msg was handled and buffer flushed
|
|
||||||
assert m.msg_count == 1
|
|
||||||
assert m.msg_recvd[0]['control']==0x1510
|
|
||||||
assert m.msg_recvd[0]['seq']=='03:03'
|
|
||||||
assert m.msg_recvd[0]['data_len']==109
|
|
||||||
assert m.mb.last_addr == 1
|
|
||||||
assert m.mb.last_fcode == 3
|
|
||||||
assert m.mb.last_reg == 0x0000 # mb_start_reg + mb_step
|
|
||||||
assert m.mb.last_len == 45
|
|
||||||
assert m.mb.err == 0
|
|
||||||
|
|
||||||
assert isclose(m.db.get_db_value(Register.BATT_PWR, None), -136.6225)
|
|
||||||
assert isclose(m.db.get_db_value(Register.BATT_OUT_PWR, None), 131.604)
|
|
||||||
assert isclose(m.db.get_db_value(Register.BATT_PV_PWR, None), 0.0)
|
|
||||||
assert m.new_data['batterie'] == True
|
|
||||||
m.new_data['batterie'] = False
|
|
||||||
|
|
||||||
await asyncio.sleep(0.5)
|
|
||||||
assert m.sent_pdu==bytearray(b'\xa5\x17\x00\x10E\x04\x03 Ce{\x02&0\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01\x03\x00\x00\x00-\x85\xd7\x9b\x15')
|
|
||||||
assert m.ifc.tx_fifo.get()==b''
|
|
||||||
|
|
||||||
m.read() # read complete msg, and dispatch msg
|
|
||||||
assert not m.header_valid # must be invalid, since msg was handled and buffer flushed
|
|
||||||
assert m.msg_count == 2
|
|
||||||
assert m.msg_recvd[1]['control']==0x1510
|
|
||||||
assert m.msg_recvd[1]['seq']=='03:03'
|
|
||||||
assert m.msg_recvd[1]['data_len']==109
|
|
||||||
assert m.mb.last_addr == 1
|
|
||||||
assert m.mb.last_fcode == 3
|
|
||||||
assert m.mb.last_reg == 0x0000 # mb_start_reg + mb_step
|
|
||||||
assert m.mb.last_len == 45
|
|
||||||
assert m.mb.err == 0
|
|
||||||
|
|
||||||
assert isclose(m.db.get_db_value(Register.BATT_PWR, None), -136.6225)
|
|
||||||
assert isclose(m.db.get_db_value(Register.BATT_OUT_PWR, None), 131.604)
|
|
||||||
assert isclose(m.db.get_db_value(Register.BATT_PV_PWR, None), 0.0)
|
|
||||||
assert m.new_data['batterie'] == False
|
|
||||||
|
|
||||||
assert next(m.mb_timer.exp_count) == 1
|
|
||||||
|
|
||||||
m.close()
|
|
||||||
|
|
||||||
def test_timeout(config_tsun_inv1):
|
def test_timeout(config_tsun_inv1):
|
||||||
_ = config_tsun_inv1
|
_ = config_tsun_inv1
|
||||||
m = MemoryStream(b'')
|
m = MemoryStream(b'')
|
||||||
|
|||||||
@@ -7,7 +7,6 @@ from cnf.config import Config
|
|||||||
from infos import Infos, Register
|
from infos import Infos, Register
|
||||||
from modbus import Modbus
|
from modbus import Modbus
|
||||||
from messages import State
|
from messages import State
|
||||||
from mock import patch
|
|
||||||
|
|
||||||
|
|
||||||
pytest_plugins = ('pytest_asyncio',)
|
pytest_plugins = ('pytest_asyncio',)
|
||||||
@@ -469,15 +468,15 @@ def config_tsun_allow_all():
|
|||||||
|
|
||||||
@pytest.fixture
|
@pytest.fixture
|
||||||
def config_no_tsun_inv1():
|
def config_no_tsun_inv1():
|
||||||
Config.act_config = {'tsun':{'enabled': False},'inverters':{'R170000000000001':{'node_id':'inv1', 'sensor_list': 0, 'modbus_polling': True, 'suggested_area':'roof'}}}
|
Config.act_config = {'tsun':{'enabled': False},'inverters':{'R170000000000001':{'node_id':'inv1', 'modbus_polling': True, 'suggested_area':'roof'}}}
|
||||||
|
|
||||||
@pytest.fixture
|
@pytest.fixture
|
||||||
def config_tsun_inv1():
|
def config_tsun_inv1():
|
||||||
Config.act_config = {'tsun':{'enabled': True},'inverters':{'R170000000000001':{'node_id':'inv1', 'sensor_list': 0x01900001, 'modbus_polling': True, 'suggested_area':'roof'}}}
|
Config.act_config = {'tsun':{'enabled': True},'inverters':{'R170000000000001':{'node_id':'inv1', 'modbus_polling': True, 'suggested_area':'roof'}}}
|
||||||
|
|
||||||
@pytest.fixture
|
@pytest.fixture
|
||||||
def config_no_modbus_poll():
|
def config_no_modbus_poll():
|
||||||
Config.act_config = {'tsun':{'enabled': True},'inverters':{'R170000000000001':{'node_id':'inv1', 'sensor_list': 0, 'modbus_polling': False, 'suggested_area':'roof'}}}
|
Config.act_config = {'tsun':{'enabled': True},'inverters':{'R170000000000001':{'node_id':'inv1', 'modbus_polling': False, 'suggested_area':'roof'}}}
|
||||||
|
|
||||||
@pytest.fixture
|
@pytest.fixture
|
||||||
def msg_ota_req(): # Over the air update request from tsun cloud
|
def msg_ota_req(): # Over the air update request from tsun cloud
|
||||||
@@ -818,236 +817,6 @@ def multiple_recv_buf(): # There are three message in the buffer, but the second
|
|||||||
msg += b'\x30\x00\x00\x00\x3c\x54\x05\x41\x2c\x42\x2c\x43' # | 0...<T.A,B,C'
|
msg += b'\x30\x00\x00\x00\x3c\x54\x05\x41\x2c\x42\x2c\x43' # | 0...<T.A,B,C'
|
||||||
return msg
|
return msg
|
||||||
|
|
||||||
@pytest.fixture
|
|
||||||
def msg_controller_ms3000_ind(): # Data indication from the controller
|
|
||||||
msg = b'\x00\x00\x04\xdf\x10R170000000000001\x91\x71\x0e\x10\x00\x00\x10R170000000000001'
|
|
||||||
msg += b'\x01\x00\x00\x01'
|
|
||||||
msg += b'\x95\x18\x5e\x19\x98\x00\x00\x00\x39\x00\x09\x2b\xa8\x54\x10\x52' # | ..^.....9..+.T.R
|
|
||||||
msg += b'\x53\x57\x5f\x34\x30\x30\x5f\x56\x32\x2e\x30\x31\x2e\x31\x33\x00' # | SW_400_V2.01.13.
|
|
||||||
msg += b'\x09\x27\xc0\x54\x06\x52\x61\x79\x6d\x6f\x6e\x00\x09\x2f\x90\x54' # | .'.T.Raymon../.T
|
|
||||||
msg += b'\x0b\x52\x53\x57\x2d\x31\x2d\x31\x30\x30\x30\x31\x00\x09\x5a\x88' # | .RSW-1-10001..Z.
|
|
||||||
msg += b'\x54\x0f\x74\x2e\x72\x61\x79\x6d\x6f\x6e\x69\x6f\x74\x2e\x63\x6f' # | T.t.raymoniot.co
|
|
||||||
msg += b'\x6d\x00\x09\x5a\xec\x54\x1c\x6c\x6f\x67\x67\x65\x72\x2e\x74\x61' # | m..Z.T.logger.ta
|
|
||||||
msg += b'\x6c\x65\x6e\x74\x2d\x6d\x6f\x6e\x69\x74\x6f\x72\x69\x6e\x67\x2e' # | lent-monitoring.
|
|
||||||
msg += b'\x63\x6f\x6d\x00\x0d\x2f\x00\x54\x10\xff\xff\xff\xff\xff\xff\xff' # | com../.T........
|
|
||||||
msg += b'\xff\xff\xff\xff\xff\xff\xff\xff\xff\x00\x0d\x32\xe8\x54\x10\xff' # | ...........2.T..
|
|
||||||
msg += b'\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\x00' # | ................
|
|
||||||
msg += b'\x0d\x36\xd0\x54\x10\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff' # | .6.T............
|
|
||||||
msg += b'\xff\xff\xff\xff\xff\x00\x0d\x3a\xb8\x54\x10\xff\xff\xff\xff\xff' # | .......:.T......
|
|
||||||
msg += b'\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\x00\x0d\x3e\xa0\x54' # | .............>.T
|
|
||||||
msg += b'\x10\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff' # | ................
|
|
||||||
msg += b'\xff\x00\x0d\x42\x88\x54\x10\xff\xff\xff\xff\xff\xff\xff\xff\xff' # | ...B.T..........
|
|
||||||
msg += b'\xff\xff\xff\xff\xff\xff\xff\x00\x0d\x46\x70\x54\x10\xff\xff\xff' # | .........FpT....
|
|
||||||
msg += b'\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\x00\x0d\x4a' # | ...............J
|
|
||||||
msg += b'\x58\x54\x10\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff' # | XT..............
|
|
||||||
msg += b'\xff\xff\xff\x00\x0d\x4e\x40\x54\x10\xff\xff\xff\xff\xff\xff\xff' # | .....N@T........
|
|
||||||
msg += b'\xff\xff\xff\xff\xff\xff\xff\xff\xff\x00\x0d\x52\x28\x54\x10\xff' # | ...........R(T..
|
|
||||||
msg += b'\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\x00' # | ................
|
|
||||||
msg += b'\x0d\x56\x10\x54\x10\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff' # | .V.T............
|
|
||||||
msg += b'\xff\xff\xff\xff\xff\x00\x0d\x59\xf8\x54\x10\xff\xff\xff\xff\xff' # | .......Y.T......
|
|
||||||
msg += b'\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\x00\x0d\x5d\xe0\x54' # | .............].T
|
|
||||||
msg += b'\x10\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff' # | ................
|
|
||||||
msg += b'\xff\x00\x0d\x61\xc8\x54\x10\xff\xff\xff\xff\xff\xff\xff\xff\xff' # | ...a.T..........
|
|
||||||
msg += b'\xff\xff\xff\xff\xff\xff\xff\x00\x0d\x65\xb0\x54\x10\xff\xff\xff' # | .........e.T....
|
|
||||||
msg += b'\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\x00\x0d\x69' # | ...............i
|
|
||||||
msg += b'\x98\x54\x10\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff' # | .T..............
|
|
||||||
msg += b'\xff\xff\xff\x00\x0d\x6d\x80\x54\x10\xff\xff\xff\xff\xff\xff\xff' # | .....m.T........
|
|
||||||
msg += b'\xff\xff\xff\xff\xff\xff\xff\xff\xff\x00\x0d\x71\x68\x54\x10\xff' # | ...........qhT..
|
|
||||||
msg += b'\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\x00' # | ................
|
|
||||||
msg += b'\x0d\x75\x50\x54\x10\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff' # | .uPT............
|
|
||||||
msg += b'\xff\xff\xff\xff\xff\x00\x0d\x79\x38\x54\x10\xff\xff\xff\xff\xff' # | .......y8T......
|
|
||||||
msg += b'\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\x00\x0d\x7d\x20\x54' # | .............} T
|
|
||||||
msg += b'\x10\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff' # | ................
|
|
||||||
msg += b'\xff\x00\x0d\x81\x08\x54\x10\xff\xff\xff\xff\xff\xff\xff\xff\xff' # | .....T..........
|
|
||||||
msg += b'\xff\xff\xff\xff\xff\xff\xff\x00\x0d\x84\xf0\x54\x10\xff\xff\xff' # | ...........T....
|
|
||||||
msg += b'\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\x00\x0d\x88' # | ................
|
|
||||||
msg += b'\xd8\x54\x10\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff' # | .T..............
|
|
||||||
msg += b'\xff\xff\xff\x00\x0d\x8c\xc0\x54\x10\xff\xff\xff\xff\xff\xff\xff' # | .......T........
|
|
||||||
msg += b'\xff\xff\xff\xff\xff\xff\xff\xff\xff\x00\x0d\x90\xa8\x54\x10\xff' # | .............T..
|
|
||||||
msg += b'\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\x00' # | ................
|
|
||||||
msg += b'\x0d\x94\x90\x54\x10\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff' # | ...T............
|
|
||||||
msg += b'\xff\xff\xff\xff\xff\x00\x0d\x98\x78\x54\x10\xff\xff\xff\xff\xff' # | ........xT......
|
|
||||||
msg += b'\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\x00\x0d\x9c\x60\x54' # | ..............`T
|
|
||||||
msg += b'\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff' # | ................
|
|
||||||
msg += b'\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff' # | ................
|
|
||||||
msg += b'\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff' # | ................
|
|
||||||
msg += b'\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff' # | ................
|
|
||||||
msg += b'\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff' # | ................
|
|
||||||
msg += b'\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff' # | ................
|
|
||||||
msg += b'\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff' # | ................
|
|
||||||
msg += b'\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff' # | ................
|
|
||||||
msg += b'\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff' # | ................
|
|
||||||
msg += b'\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff' # | ................
|
|
||||||
msg += b'\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff' # | ................
|
|
||||||
msg += b'\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff' # | ................
|
|
||||||
msg += b'\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff' # | ................
|
|
||||||
msg += b'\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff' # | ................
|
|
||||||
msg += b'\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff' # | ................
|
|
||||||
msg += b'\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff' # | ................
|
|
||||||
msg += b'\x00\x0d\x00\x20\x49\x00\x00\x00\x01\x00\x0c\x35\x00\x49\x00\x00' # | ... I......5.I..
|
|
||||||
msg += b'\x00\x62\x00\x0c\x96\xa8\x49\x00\x00\x01\x4f\x00\x0c\x7f\x38\x49' # | .b....I...O...8I
|
|
||||||
msg += b'\x00\x00\x00\x01\x00\x0c\xfc\x38\x49\x00\x00\x00\x01\x00\x0c\xf8' # | .......8I.......
|
|
||||||
msg += b'\x50\x49\x00\x00\x01\x2c\x00\x0c\x63\xe0\x49\x00\x00\x00\x00\x00' # | PI...,..c.I.....
|
|
||||||
msg += b'\x0c\x67\xc8\x49\x00\x00\x00\x00\x00\x0c\x50\x58\x49\x00\x00\x00' # | .g.I......PXI...
|
|
||||||
msg += b'\x01\x00\x09\x5e\x70\x49\x00\x00\x13\x8d\x00\x09\x5e\xd4\x49\x00' # | ...^pI......^.I.
|
|
||||||
msg += b'\x00\x13\x8d\x00\x09\x5b\x50\x49\x00\x00\x00\x02\x00\x0d\x04\x08' # | .....[PI........
|
|
||||||
msg += b'\x49\x00\x00\x00\x00\x00\x07\xa1\x84\x49\x00\x00\x00\x01\x00\x0c' # | I........I......
|
|
||||||
msg += b'\x50\x59\x49\x00\x00\x00\x2d\x00\x0d\x1f\x60\x49\x00\x00\x00\x00' # | PYI...-...`I....
|
|
||||||
msg += b'\x00\x0d\x23\x48\x49\xff\xff\xff\xff\x00\x0d\x27\x30\x49\xff\xff' # | ..#HI......'0I..
|
|
||||||
msg += b'\xff\xff\x00\x0d\x2b\x18\x4c\x00\x00\x00\x00\xff\xff\xff\xff\x00' # | ....+.L.........
|
|
||||||
msg += b'\x0c\xa2\x60\x49\x00\x00\x00\x00\x00\x0d\xa0\x48\x49\x00\x00\x00' # | ..`I.......HI...
|
|
||||||
msg += b'\x00\x00\x0d\xa4\x30\x49\x00\x00\x00\xff\x00\x0d\xa8\x18\x49\x00' # | ....0I........I.
|
|
||||||
msg += b'\x00\x00\xff'
|
|
||||||
return msg
|
|
||||||
|
|
||||||
@pytest.fixture
|
|
||||||
def msg_inverter_ms3000_ind(): # Data indication from the controller
|
|
||||||
msg = b'\x00\x00\x08\xff\x10R170000000000001\x91\x04\x01\x90\x00\x00\x10R170000000000001'
|
|
||||||
msg += b'\x01\x00\x00\x01'
|
|
||||||
msg += b'\x95\x18\x5e\x1d\x80\x00\x00\x01\x2c\x00\x00\x00\x64\x53\x00\x00' # | ..^.....,...dS..
|
|
||||||
msg += b'\x00\x00\x00\xc8\x53\x44\x00\x00\x00\x01\x2c\x53\x00\x00\x00\x00' # | ....SD....,S....
|
|
||||||
msg += b'\x01\x90\x49\x00\x00\x00\x00\x00\x00\x01\x91\x53\x00\x00\x00\x00' # | ..I........S....
|
|
||||||
msg += b'\x01\x92\x53\x00\x00\x00\x00\x01\x93\x53\x00\x00\x00\x00\x01\x94' # | ..S......S......
|
|
||||||
msg += b'\x53\x00\x00\x00\x00\x01\x95\x53\x00\x00\x00\x00\x01\x96\x53\x00' # | S......S......S.
|
|
||||||
msg += b'\x00\x00\x00\x01\x97\x53\x00\x00\x00\x00\x01\x98\x53\x00\x00\x00' # | .....S......S...
|
|
||||||
msg += b'\x00\x01\x99\x53\x00\x00\x00\x00\x01\x9a\x53\x00\x00\x00\x00\x01' # | ...S......S.....
|
|
||||||
msg += b'\x9b\x53\x00\x00\x00\x00\x01\x9c\x53\x00\x00\x00\x00\x01\x9d\x53' # | .S......S......S
|
|
||||||
msg += b'\x00\x00\x00\x00\x01\x9e\x53\x00\x00\x00\x00\x01\x9f\x53\x00\x00' # | ......S......S..
|
|
||||||
msg += b'\x00\x00\x01\xa0\x53\x00\x00\x00\x00\x01\xf4\x49\x00\x00\x00\x00' # | ....S......I....
|
|
||||||
msg += b'\x00\x00\x01\xf5\x53\x00\x00\x00\x00\x01\xf6\x53\x00\x00\x00\x00' # | ....S......S....
|
|
||||||
msg += b'\x01\xf7\x53\x00\x00\x00\x00\x01\xf8\x53\x00\x00\x00\x00\x01\xf9' # | ..S......S......
|
|
||||||
msg += b'\x53\x00\x00\x00\x00\x01\xfa\x53\x00\x00\x00\x00\x01\xfb\x53\x00' # | S......S......S.
|
|
||||||
msg += b'\x00\x00\x00\x01\xfc\x53\x00\x00\x00\x00\x01\xfd\x53\x00\x00\x00' # | .....S......S...
|
|
||||||
msg += b'\x00\x01\xfe\x53\x00\x00\x00\x00\x01\xff\x53\x00\x00\x00\x00\x02' # | ...S......S.....
|
|
||||||
msg += b'\x00\x53\x00\x00\x00\x00\x02\x01\x53\x00\x00\x00\x00\x02\x02\x53' # | .S......S......S
|
|
||||||
msg += b'\x00\x00\x00\x00\x02\x03\x53\x00\x00\x00\x00\x02\x04\x53\x00\x00' # | ......S......S..
|
|
||||||
msg += b'\x00\x00\x02\x58\x49\x00\x00\x00\x00\x00\x00\x02\x59\x53\x00\x00' # | ...XI.......YS..
|
|
||||||
msg += b'\x00\x00\x02\x5a\x53\x00\x00\x00\x00\x02\x5b\x53\x00\x00\x00\x00' # | ...ZS.....[S....
|
|
||||||
msg += b'\x02\x5c\x53\x00\x00\x00\x00\x02\x5d\x53\x00\x00\x00\x00\x02\x5e' # | .\S.....]S.....^
|
|
||||||
msg += b'\x53\x00\x00\x00\x00\x02\x5f\x53\x00\x00\x00\x00\x02\x60\x53\x00' # | S....._S.....`S.
|
|
||||||
msg += b'\x00\x00\x00\x02\x61\x53\x00\x00\x00\x00\x02\x62\x53\x00\x00\x00' # | ....aS.....bS...
|
|
||||||
msg += b'\x00\x02\x63\x53\x00\x00\x00\x00\x02\x64\x53\x00\x00\x00\x00\x02' # | ..cS.....dS.....
|
|
||||||
msg += b'\x65\x53\x00\x00\x00\x00\x02\x66\x53\x00\x00\x00\x00\x02\x67\x53' # | eS.....fS.....gS
|
|
||||||
msg += b'\x00\x00\x00\x00\x02\x68\x53\x00\x00\x00\x00\x02\xbc\x49\x00\x00' # | .....hS......I..
|
|
||||||
msg += b'\x00\x00\x00\x00\x02\xbd\x53\x00\x00\x00\x00\x02\xbe\x53\x00\x00' # | ......S......S..
|
|
||||||
msg += b'\x00\x00\x02\xbf\x53\x00\x00\x00\x00\x02\xc0\x53\x00\x00\x00\x00' # | ....S......S....
|
|
||||||
msg += b'\x02\xc1\x53\x00\x00\x00\x00\x02\xc2\x53\x00\x00\x00\x00\x02\xc3' # | ..S......S......
|
|
||||||
msg += b'\x53\x00\x00\x00\x00\x02\xc4\x53\x00\x00\x00\x00\x02\xc5\x53\x00' # | S......S......S.
|
|
||||||
msg += b'\x00\x00\x00\x02\xc6\x53\x00\x00\x00\x00\x02\xc7\x53\x00\x00\x00' # | .....S......S...
|
|
||||||
msg += b'\x00\x02\xc8\x53\x00\x00\x00\x00\x02\xc9\x53\x00\x00\x00\x00\x02' # | ...S......S.....
|
|
||||||
msg += b'\xca\x53\x00\x00\x00\x00\x02\xcb\x53\x00\x00\x00\x00\x02\xcc\x53' # | .S......S......S
|
|
||||||
msg += b'\x00\x00\x00\x00\x03\x20\x53\x00\x01\x00\x00\x03\x84\x53\x11\x68' # | ..... S......S.h
|
|
||||||
msg += b'\x00\x00\x03\xe8\x46\x44\x23\xd1\xec\x00\x00\x04\x4c\x46\x43\xa3' # | ....FD#.....LFC.
|
|
||||||
msg += b'\xb3\x33\x00\x00\x04\xb0\x46\x00\x00\x00\x00\x00\x00\x05\x14\x46' # | .3....F........F
|
|
||||||
msg += b'\x43\x6e\x80\x00\x00\x00\x05\x78\x46\x3d\x4c\xcc\xcd\x00\x00\x05' # | Cn.....xF=L.....
|
|
||||||
msg += b'\xdc\x46\x00\x00\x00\x00\x00\x00\x06\x40\x46\x42\x48\x00\x00\x00' # | .F.......@FBH...
|
|
||||||
msg += b'\x00\x06\xa4\x53\x00\x03\x00\x00\x07\x08\x53\x00\x0c\x00\x00\x07' # | ...S......S.....
|
|
||||||
msg += b'\x6c\x53\x00\x50\x00\x00\x07\xd0\x46\x43\xa3\xb3\x33\x00\x00\x08' # | lS.P....FC..3...
|
|
||||||
msg += b'\x34\x53\x0b\xb8\x00\x00\x08\x98\x46\x00\x00\x00\x00\x00\x00\x08' # | 4S......F.......
|
|
||||||
msg += b'\xfc\x46\x00\x00\x00\x00\x00\x00\x09\x60\x46\x41\xee\xe1\x48\x00' # | .F.......`FA..H.
|
|
||||||
msg += b'\x00\x09\xc4\x53\x00\x00\x00\x00\x0a\x28\x46\x41\xf2\x00\x00\x00' # | ...S.....(FA....
|
|
||||||
msg += b'\x00\x0a\x8c\x46\x3f\xac\x28\xf6\x00\x00\x0a\xf0\x53\x00\x0c\x00' # | ...F?.(.....S...
|
|
||||||
msg += b'\x00\x0b\x54\x53\x00\x00\x00\x00\x0b\xb8\x53\x00\x00\x00\x00\x0c' # | ..TS......S.....
|
|
||||||
msg += b'\x1c\x53\x00\x00\x00\x00\x0c\x80\x53\x00\x00\x00\x00\x0c\xe4\x53' # | .S......S......S
|
|
||||||
msg += b'\x00\x00\x00\x00\x0d\x48\x53\x00\x00\x00\x00\x0d\xac\x53\x00\x00' # | .....HS......S..
|
|
||||||
msg += b'\x00\x00\x0e\x10\x53\x00\x00\x00\x00\x0e\x74\x53\x00\x00\x00\x00' # | ....S.....tS....
|
|
||||||
msg += b'\x0e\xd8\x53\x00\x00\x00\x00\x0f\x3c\x53\x00\x00\x00\x00\x0f\xa0' # | ..S.....<S......
|
|
||||||
msg += b'\x53\x00\x00\x00\x00\x10\x04\x53\x00\x00\x00\x00\x10\x68\x53\x00' # | S......S.....hS.
|
|
||||||
msg += b'\x00\x00\x00\x10\xcc\x53\x00\x00\x00\x00\x11\x30\x53\x00\x00\x00' # | .....S.....0S...
|
|
||||||
msg += b'\x00\x11\x94\x53\x00\x00\x00\x00\x11\xf8\x53\x00\x00\x00\x00\x12' # | ...S......S.....
|
|
||||||
msg += b'\x5c\x53\x00\x00\x00\x00\x12\xc0\x53\x00\x00\x00\x00\x13\x24\x46' # | \S......S.....$F
|
|
||||||
msg += b'\x42\x9d\x33\x33\x00\x00\x13\x88\x46\x00\x00\x00\x00\x00\x00\x13' # | B.33....F.......
|
|
||||||
msg += b'\xec\x46\x00\x00\x00\x00\x00\x00\x14\x50\x46\x42\xdc\x00\x00\x00' # | .F.......PFB....
|
|
||||||
msg += b'\x00\x14\xb4\x53\x00\x00\x00\x00\x15\x18\x53\x00\x00\x00\x00\x15' # | ...S......S.....
|
|
||||||
msg += b'\x7c\x53\x00\x00\x00\x00\x15\x7d\x53\x00\x00\x00\x00\x15\x7e\x53' # | |S.....}S.....~S
|
|
||||||
msg += b'\x00\x00\x00\x00\x15\x7f\x53\x00\x00\x00\x00\x15\x80\x53\x00\x00' # | ......S......S..
|
|
||||||
msg += b'\x00\x00\x15\x81\x53\x00\x00\x00\x00\x15\x82\x53\x00\x00\x00\x00' # | ....S......S....
|
|
||||||
msg += b'\x15\x83\x53\x00\x00\x00\x00\x15\x84\x53\x00\x00\x00\x00\x15\x85' # | ..S......S......
|
|
||||||
msg += b'\x53\x00\x00\x00\x00\x15\x86\x53\x00\x00\x00\x00\x15\x87\x53\x00' # | S......S......S.
|
|
||||||
msg += b'\x00\x00\x00\x15\x88\x53\x00\x00\x00\x00\x15\x89\x53\x00\x00\x00' # | .....S......S...
|
|
||||||
msg += b'\x00\x15\x8a\x53\x00\x00\x00\x00\x15\x8b\x53\x00\x00\x00\x00\x15' # | ...S......S.....
|
|
||||||
msg += b'\x8c\x53\x00\x00\x00\x00\x15\xe0\x46\x42\x68\x66\x66\x00\x00\x16' # | .S......FBhff...
|
|
||||||
msg += b'\x44\x46\x00\x00\x00\x00\x00\x00\x16\xa8\x46\x00\x00\x00\x00\x00' # | DF........F.....
|
|
||||||
msg += b'\x00\x17\x0c\x46\x42\xdc\x00\x00\x00\x00\x17\x70\x53\x00\x00\x00' # | ...FB......pS...
|
|
||||||
msg += b'\x00\x17\xd4\x53\x00\x00\x00\x00\x18\x38\x53\x00\x00\x00\x00\x18' # | ...S.....8S.....
|
|
||||||
msg += b'\x39\x53\x00\x00\x00\x00\x18\x3a\x53\x00\x00\x00\x00\x18\x3b\x53' # | 9S.....:S.....;S
|
|
||||||
msg += b'\x00\x00\x00\x00\x18\x3c\x53\x00\x00\x00\x00\x18\x3d\x53\x00\x00' # | .....<S.....=S..
|
|
||||||
msg += b'\x00\x00\x18\x3e\x53\x00\x00\x00\x00\x18\x3f\x53\x00\x00\x00\x00' # | ...>S.....?S....
|
|
||||||
msg += b'\x18\x40\x53\x00\x00\x00\x00\x18\x41\x53\x00\x00\x00\x00\x18\x42' # | .@S.....AS.....B
|
|
||||||
msg += b'\x53\x00\x00\x00\x00\x18\x43\x53\x00\x00\x00\x00\x18\x44\x53\x00' # | S.....CS.....DS.
|
|
||||||
msg += b'\x00\x00\x00\x18\x45\x53\x00\x00\x00\x00\x18\x46\x53\x00\x00\x00' # | ....ES.....FS...
|
|
||||||
msg += b'\x00\x18\x47\x53\x00\x00\x00\x00\x18\x48\x53\x00\x00\x00\x00\x18' # | ..GS.....HS.....
|
|
||||||
msg += b'\x9c\x46\x42\x6b\x33\x33\x00\x00\x19\x00\x46\x00\x00\x00\x00\x00' # | .FBk33....F.....
|
|
||||||
msg += b'\x00\x19\x64\x46\x00\x00\x00\x00\x00\x00\x19\xc8\x46\x42\xdc\x00' # | ..dF........FB..
|
|
||||||
msg += b'\x00\x00\x00\x1a\x2c\x53\x00\x00\x00\x00\x1a\x90\x53\x00\x00\x00' # | ....,S......S...
|
|
||||||
msg += b'\x00\x1a\xf4\x53\x00\x00\x00\x00\x1a\xf5\x53\x00\x00\x00\x00\x1a' # | ...S......S.....
|
|
||||||
msg += b'\xf6\x53\x00\x00\x00\x00\x1a\xf7\x53\x00\x00\x00\x00\x1a\xf8\x53' # | .S......S......S
|
|
||||||
msg += b'\x00\x00\x00\x00\x1a\xf9\x53\x00\x00\x00\x00\x1a\xfa\x53\x00\x00' # | ......S......S..
|
|
||||||
msg += b'\x00\x00\x1a\xfb\x53\x00\x00\x00\x00\x1a\xfc\x53\x00\x00\x00\x00' # | ....S......S....
|
|
||||||
msg += b'\x1a\xfd\x53\x00\x00\x00\x00\x1a\xfe\x53\x00\x00\x00\x00\x1a\xff' # | ..S......S......
|
|
||||||
msg += b'\x53\x00\x00\x00\x00\x1b\x00\x53\x00\x00\x00\x00\x1b\x01\x53\x00' # | S......S......S.
|
|
||||||
msg += b'\x00\x00\x00\x1b\x02\x53\x00\x00\x00\x00\x1b\x03\x53\x00\x00\x00' # | .....S......S...
|
|
||||||
msg += b'\x00\x1b\x04\x53\x00\x00\x00\x00\x1b\x58\x53\x00\x00\x00\x00\x1b' # | ...S.....XS.....
|
|
||||||
msg += b'\xbc\x53\x11\x3d\x00\x00\x1c\x20\x46\x3c\x23\xd7\x0a\x00\x00\x1c' # | .S.=... F<#.....
|
|
||||||
msg += b'\x84\x46\x00\x00\x00\x00\x00\x00\x1c\xe8\x46\x42\x04\x00\x00\x00' # | .F........FB....
|
|
||||||
msg += b'\x00\x1d\x4c\x46\x00\x00\x00\x00\x00\x00\x1d\xb0\x46\x00\x00\x00' # | ..LF........F...
|
|
||||||
msg += b'\x00\x00\x00\x1e\x14\x53\x00\x02\x00\x00\x1e\x78\x46\x41\x8b\x33' # | .....S.....xFA.3
|
|
||||||
msg += b'\x33\x00\x00\x1e\xdc\x46\x3c\xa3\xd7\x0a\x00\x00\x1f\x40\x46\x3e' # | 3....F<......@F>
|
|
||||||
msg += b'\x99\x99\x9a\x00\x00\x1f\xa4\x46\x40\x99\x99\x9a\x00\x00\x20\x08' # | .......F@..... .
|
|
||||||
msg += b'\x53\x00\x00\x00\x00\x20\x6c\x53\x00\x00\x00\x00\x20\xd0\x53\x05' # | S.... lS.... .S.
|
|
||||||
msg += b'\x00\x00\x00\x20\xd1\x53\x00\x00\x00\x00\x20\xd2\x53\x00\x00\x00' # | ... .S.... .S...
|
|
||||||
msg += b'\x00\x20\xd3\x53\x00\x00\x00\x00\x20\xd4\x53\x00\x00\x00\x00\x20' # | . .S.... .S....
|
|
||||||
msg += b'\xd5\x53\x00\x00\x00\x00\x20\xd6\x53\x00\x00\x00\x00\x20\xd7\x53' # | .S.... .S.... .S
|
|
||||||
msg += b'\x00\x00\x00\x00\x20\xd8\x53\x00\x00\x00\x00\x20\xd9\x53\x00\x01' # | .... .S.... .S..
|
|
||||||
msg += b'\x00\x00\x20\xda\x53\x00\x00\x00\x00\x20\xdb\x53\x00\x01\x00\x00' # | .. .S.... .S....
|
|
||||||
msg += b'\x20\xdc\x53\x00\x00\x00\x00\x20\xdd\x53\x00\x00\x00\x00\x20\xde' # | .S.... .S.... .
|
|
||||||
msg += b'\x53\x00\x00\x00\x00\x20\xdf\x53\x00\x00\x00\x00\x20\xe0\x53\x00' # | S.... .S.... .S.
|
|
||||||
msg += b'\x00\x00\x00\x21\x34\x46\x00\x00\x00\x00\x00\x00\x21\x98\x46\x00' # | ...!4F......!.F.
|
|
||||||
msg += b'\x00\x00\x00\x00\x00\x21\xfc\x46\x00\x00\x00\x00\x00\x00\x22\x60' # | .....!.F......"`
|
|
||||||
msg += b'\x46\x00\x00\x00\x00\x00\x00\x22\xc4\x53\x00\x00\x00\x00\x23\x28' # | F......".S....#(
|
|
||||||
msg += b'\x53\x00\x00\x00\x00\x23\x8c\x53\x00\x00\x00\x00\x23\x8d\x53\x00' # | S....#.S....#.S.
|
|
||||||
msg += b'\x00\x00\x00\x23\x8e\x53\x00\x00\x00\x00\x23\x8f\x53\x00\x00\x00' # | ...#.S....#.S...
|
|
||||||
msg += b'\x00\x23\x90\x53\x00\x00\x00\x00\x23\x91\x53\x00\x00\x00\x00\x23' # | .#.S....#.S....#
|
|
||||||
msg += b'\x92\x53\x00\x00\x00\x00\x23\x93\x53\x00\x00\x00\x00\x23\x94\x53' # | .S....#.S....#.S
|
|
||||||
msg += b'\x00\x00\x00\x00\x23\x95\x53\x00\x00\x00\x00\x23\x96\x53\x00\x00' # | ....#.S....#.S..
|
|
||||||
msg += b'\x00\x00\x23\x97\x53\x00\x00\x00\x00\x23\x98\x53\x00\x00\x00\x00' # | ..#.S....#.S....
|
|
||||||
msg += b'\x23\x99\x53\x00\x00\x00\x00\x23\x9a\x53\x00\x00\x00\x00\x23\x9b' # | #.S....#.S....#.
|
|
||||||
msg += b'\x53\x00\x00\x00\x00\x23\x9c\x53\x00\x00\x00\x00\x23\xf0\x46\x00' # | S....#.S....#.F.
|
|
||||||
msg += b'\x00\x00\x00\x00\x00\x24\x54\x46\x00\x00\x00\x00\x00\x00\x24\xb8' # | .....$TF......$.
|
|
||||||
msg += b'\x46\x00\x00\x00\x00\x00\x00\x25\x1c\x46\x00\x00\x00\x00\x00\x00' # | F......%.F......
|
|
||||||
msg += b'\x25\x80\x53\x00\x00\x00\x00\x25\xe4\x53\x00\x00\x00\x00\x26\x48' # | %.S....%.S....&H
|
|
||||||
msg += b'\x53\x00\x00\x00\x00\x26\x49\x53\x00\x00\x00\x00\x26\x4a\x53\x00' # | S....&IS....&JS.
|
|
||||||
msg += b'\x00\x00\x00\x26\x4b\x53\x00\x00\x00\x00\x26\x4c\x53\x00\x00\x00' # | ...&KS....&LS...
|
|
||||||
msg += b'\x00\x26\x4d\x53\x00\x00\x00\x00\x26\x4e\x53\x00\x00\x00\x00\x26' # | .&MS....&NS....&
|
|
||||||
msg += b'\x4f\x53\x00\x00\x00\x00\x26\x50\x53\x00\x00\x00\x00\x26\x51\x53' # | OS....&PS....&QS
|
|
||||||
msg += b'\x00\x00\x00\x00\x26\x52\x53\x00\x00\x00\x00\x26\x53\x53\x00\x00' # | ....&RS....&SS..
|
|
||||||
msg += b'\x00\x00\x26\x54\x53\x00\x00\x00\x00\x26\x55\x53\x00\x00\x00\x00' # | ..&TS....&US....
|
|
||||||
msg += b'\x26\x56\x53\x00\x00\x00\x00\x26\x57\x53\x00\x00\x00\x00\x26\x58' # | &VS....&WS....&X
|
|
||||||
msg += b'\x53\x00\x00\x00\x00\x26\xac\x53\x00\x00\x00\x00\x27\x10\x53\x11' # | S....&.S....'.S.
|
|
||||||
msg += b'\x3d\x00\x00\x27\x74\x46\x00\x00\x00\x00\x00\x00\x27\xd8\x46\x00' # | =..'tF......'.F.
|
|
||||||
msg += b'\x00\x00\x00\x00\x00\x28\x3c\x46\x42\x03\xf5\xc3\x00\x00\x28\xa0' # | .....(<FB.....(.
|
|
||||||
msg += b'\x46\x00\x00\x00\x00\x00\x00\x29\x04\x46\x00\x00\x00\x00\x00\x00' # | F......).F......
|
|
||||||
msg += b'\x29\x68\x53\x00\x02\x00\x00\x29\xcc\x53\x00\x03\x00\x00\x2a\x30' # | )hS....).S....*0
|
|
||||||
msg += b'\x46\x42\x20\x00\x00\x00\x00\x2a\x94\x46\x42\x20\x00\x00\x00\x00' # | FB ....*.FB ....
|
|
||||||
msg += b'\x2a\xf8\x46\x44\x20\x00\x00\x00\x00\x2b\x5c\x46\x43\x7b\x00\x00' # | *.FD ....+\FC{..
|
|
||||||
msg += b'\x00\x00\x2b\xc0\x46\x43\x50\x00\x00\x00\x00\x2c\x24\x46\x42\x48' # | ..+.FCP....,$FBH
|
|
||||||
msg += b'\x5c\x29\x00\x00\x2c\x88\x46\x42\x47\xa3\xd7\x00\x00\x2c\xec\x53' # | \)..,.FBG....,.S
|
|
||||||
msg += b'\x00\x00\x00\x00\x2d\x50\x46\x43\x42\x00\x00\x00\x00\x2d\xb4\x46' # | ....-PFCB....-.F
|
|
||||||
msg += b'\x42\xbc\x00\x00\x00\x00\x2e\x18\x46\x3f\xe6\x66\x66\x00\x00\x2e' # | B.......F?.ff...
|
|
||||||
msg += b'\x7c\x46\x3f\xe6\x66\x66\x00\x00\x2e\xe0\x46\x43\x7e\x00\x00\x00' # | |F?.ff....FC~...
|
|
||||||
msg += b'\x00\x2f\x44\x46\x43\x83\xf3\x33\x00\x00\x2f\xa8\x46\x3f\xe6\x66' # | ./DFC..3../.F?.f
|
|
||||||
msg += b'\x66\x00\x00\x30\x0c\x46\x3f\xe6\x66\x66\x00\x00\x30\x70\x46\x43' # | f..0.F?.ff..0pFC
|
|
||||||
msg += b'\x7e\x00\x00\x00\x00\x30\xd4\x46\x42\x3f\xeb\x85\x00\x00\x31\x38' # | ~....0.FB?....18
|
|
||||||
msg += b'\x46\x42\x3d\xeb\x85\x00\x00\x31\x9c\x46\x3e\x4c\xcc\xcd\x00\x00' # | FB=....1.F>L....
|
|
||||||
msg += b'\x32\x00\x46\x3e\x4c\xcc\xcd\x00\x00\x32\x64\x46\x42\x4c\x14\x7b' # | 2.F>L....2dFBL.{
|
|
||||||
msg += b'\x00\x00\x32\xc8\x46\x42\x4d\xeb\x85\x00\x00\x33\x2c\x46\x3e\x4c' # | ..2.FBM....3,F>L
|
|
||||||
msg += b'\xcc\xcd\x00\x00\x33\x90\x46\x3e\x4c\xcc\xcd\x00\x00\x33\xf4\x53' # | ....3.F>L....3.S
|
|
||||||
msg += b'\x00\x00\x00\x00\x34\x58\x53\x00\x00\x00\x00\x34\xbc\x53\x04\x00' # | ....4XS....4.S..
|
|
||||||
msg += b'\x00\x00\x35\x20\x53\x00\x01\x00\x00\x35\x84\x53\x13\x9c\x00\x00' # | ..5 S....5.S....
|
|
||||||
msg += b'\x35\xe8\x53\x0f\xa0\x00\x00\x36\x4c\x53\x00\x00\x00\x00\x36\xb0' # | 5.S....6LS....6.
|
|
||||||
msg += b'\x53\x00\x66' # | S.f'
|
|
||||||
return msg
|
|
||||||
|
|
||||||
def test_read_message(msg_contact_info):
|
def test_read_message(msg_contact_info):
|
||||||
Config.act_config = {'tsun':{'enabled': True}}
|
Config.act_config = {'tsun':{'enabled': True}}
|
||||||
m = MemoryStream(msg_contact_info, (0,))
|
m = MemoryStream(msg_contact_info, (0,))
|
||||||
@@ -1801,64 +1570,6 @@ def test_msg_inv_ind3(config_tsun_inv1, msg_inverter_ind_0w, msg_inverter_ack):
|
|||||||
m.close()
|
m.close()
|
||||||
assert m.db.get_db_value(Register.INVERTER_STATUS) == 0
|
assert m.db.get_db_value(Register.INVERTER_STATUS) == 0
|
||||||
|
|
||||||
def test_msg_inv_ind4(config_tsun_inv1, msg_inverter_ms3000_ind, msg_inverter_ack):
|
|
||||||
'''Check sonar_lists of MS-3000 inverter'''
|
|
||||||
_ = config_tsun_inv1
|
|
||||||
tracer.setLevel(logging.DEBUG)
|
|
||||||
with patch.object(logging, 'warning') as spy:
|
|
||||||
m = MemoryStream(msg_inverter_ms3000_ind, (0,))
|
|
||||||
m.db.stat['proxy']['Unknown_Ctrl'] = 0
|
|
||||||
m.db.stat['proxy']['Invalid_Data_Type'] = 0
|
|
||||||
m.read() # read complete msg, and dispatch msg
|
|
||||||
spy.assert_not_called()
|
|
||||||
assert m.db.stat['proxy']['Unknown_Ctrl'] == 0
|
|
||||||
assert m.db.stat['proxy']['Invalid_Data_Type'] == 0
|
|
||||||
assert not m.header_valid # must be invalid, since msg was handled and buffer flushed
|
|
||||||
assert m.msg_count == 1
|
|
||||||
assert m.id_str == b"R170000000000001"
|
|
||||||
assert m.unique_id == 'R170000000000001'
|
|
||||||
assert int(m.ctrl)==145
|
|
||||||
assert m.msg_id==4
|
|
||||||
assert m.header_len==23
|
|
||||||
assert m.data_len==2284
|
|
||||||
m.ts_offset = 0
|
|
||||||
m._update_header(m.ifc.fwd_fifo.peek())
|
|
||||||
assert m.ifc.fwd_fifo.get()==msg_inverter_ms3000_ind
|
|
||||||
assert m.ifc.tx_fifo.get()==msg_inverter_ack
|
|
||||||
assert m.db.get_db_value(Register.INVERTER_STATUS) == 0
|
|
||||||
assert m.db.get_db_value(Register.TS_GRID) == 1739866976
|
|
||||||
m.db.db['grid'] = {'Output_Power': 100}
|
|
||||||
m.close()
|
|
||||||
|
|
||||||
def test_msg_inv_ind5(config_tsun_inv1, msg_inverter_ms3000_ind, msg_inverter_ack):
|
|
||||||
'''Check that unexpected sonar_lists will log a warning'''
|
|
||||||
_ = config_tsun_inv1
|
|
||||||
tracer.setLevel(logging.DEBUG)
|
|
||||||
with patch.object(logging, 'warning') as spy:
|
|
||||||
m = MemoryStream(msg_inverter_ms3000_ind, (0,))
|
|
||||||
m.sensor_list = 0x01900002 # change the expected sensor_list
|
|
||||||
m.db.stat['proxy']['Unknown_Ctrl'] = 0
|
|
||||||
m.db.stat['proxy']['Invalid_Data_Type'] = 0
|
|
||||||
m.read() # read complete msg, and dispatch msg
|
|
||||||
spy.assert_called()
|
|
||||||
assert m.db.stat['proxy']['Unknown_Ctrl'] == 0
|
|
||||||
assert m.db.stat['proxy']['Invalid_Data_Type'] == 0
|
|
||||||
assert not m.header_valid # must be invalid, since msg was handled and buffer flushed
|
|
||||||
assert m.msg_count == 1
|
|
||||||
assert m.id_str == b"R170000000000001"
|
|
||||||
assert m.unique_id == 'R170000000000001'
|
|
||||||
assert int(m.ctrl)==145
|
|
||||||
assert m.msg_id==4
|
|
||||||
assert m.header_len==23
|
|
||||||
assert m.data_len==2284
|
|
||||||
m.ts_offset = 0
|
|
||||||
m._update_header(m.ifc.fwd_fifo.peek())
|
|
||||||
assert m.ifc.fwd_fifo.get()==msg_inverter_ms3000_ind
|
|
||||||
assert m.ifc.tx_fifo.get()==msg_inverter_ack
|
|
||||||
assert m.db.get_db_value(Register.INVERTER_STATUS) == 0
|
|
||||||
assert m.db.get_db_value(Register.TS_GRID) == 1739866976
|
|
||||||
m.db.db['grid'] = {'Output_Power': 100}
|
|
||||||
m.close()
|
|
||||||
|
|
||||||
def test_msg_inv_ack(config_tsun_inv1, msg_inverter_ack):
|
def test_msg_inv_ack(config_tsun_inv1, msg_inverter_ack):
|
||||||
_ = config_tsun_inv1
|
_ = config_tsun_inv1
|
||||||
@@ -1903,18 +1614,6 @@ def test_msg_inv_invalid(config_tsun_inv1, msg_inverter_invalid):
|
|||||||
assert m.db.stat['proxy']['Unknown_Ctrl'] == 1
|
assert m.db.stat['proxy']['Unknown_Ctrl'] == 1
|
||||||
m.close()
|
m.close()
|
||||||
|
|
||||||
def test_build_modell_3000(config_tsun_allow_all, msg_inverter_ms3000_ind):
|
|
||||||
_ = config_tsun_allow_all
|
|
||||||
m = MemoryStream(msg_inverter_ms3000_ind, (0,))
|
|
||||||
assert 0 == m.db.get_db_value(Register.MAX_DESIGNED_POWER, 0)
|
|
||||||
assert None == m.db.get_db_value(Register.RATED_POWER, None)
|
|
||||||
assert None == m.db.get_db_value(Register.INVERTER_TEMP, None)
|
|
||||||
m.read() # read complete msg, and dispatch msg
|
|
||||||
assert 3000 == m.db.get_db_value(Register.MAX_DESIGNED_POWER, 0)
|
|
||||||
assert 0 == m.db.get_db_value(Register.RATED_POWER, 0)
|
|
||||||
assert 'TSOL-MS3000' == m.db.get_db_value(Register.EQUIPMENT_MODEL, 0)
|
|
||||||
m.close()
|
|
||||||
|
|
||||||
def test_msg_ota_req(config_tsun_inv1, msg_ota_req):
|
def test_msg_ota_req(config_tsun_inv1, msg_ota_req):
|
||||||
_ = config_tsun_inv1
|
_ = config_tsun_inv1
|
||||||
m = MemoryStream(msg_ota_req, (0,), False)
|
m = MemoryStream(msg_ota_req, (0,), False)
|
||||||
@@ -2485,56 +2184,6 @@ async def test_modbus_polling(config_tsun_inv1, msg_inverter_ind):
|
|||||||
assert next(m.mb_timer.exp_count) == 4
|
assert next(m.mb_timer.exp_count) == 4
|
||||||
m.close()
|
m.close()
|
||||||
|
|
||||||
@pytest.mark.asyncio
|
|
||||||
async def test_modbus_scaning(config_tsun_inv1, msg_inverter_ind, msg_modbus_rsp21):
|
|
||||||
_ = config_tsun_inv1
|
|
||||||
assert asyncio.get_running_loop()
|
|
||||||
|
|
||||||
m = MemoryStream(msg_inverter_ind, (0x8f,0))
|
|
||||||
m.append_msg(msg_modbus_rsp21)
|
|
||||||
m.mb_scan = True
|
|
||||||
m.mb_start_reg = 0x4560
|
|
||||||
m.mb_bytes = 0x14
|
|
||||||
assert asyncio.get_running_loop() == m.mb_timer.loop
|
|
||||||
m.db.stat['proxy']['Unknown_Ctrl'] = 0
|
|
||||||
assert m.mb_timer.tim == None
|
|
||||||
m.read() # read complete msg, and dispatch msg
|
|
||||||
assert not m.header_valid # must be invalid, since msg was handled and buffer flushed
|
|
||||||
assert m.msg_count == 1
|
|
||||||
assert m.id_str == b"R170000000000001"
|
|
||||||
assert m.unique_id == 'R170000000000001'
|
|
||||||
assert m.msg_recvd[0]['ctrl']==145
|
|
||||||
assert m.msg_recvd[0]['msg_id']==4
|
|
||||||
assert m.msg_recvd[0]['header_len']==23
|
|
||||||
assert m.msg_recvd[0]['data_len']==120
|
|
||||||
assert m.ifc.fwd_fifo.get()==msg_inverter_ind
|
|
||||||
assert m.ifc.tx_fifo.get()==b'\x00\x00\x00\x14\x10R170000000000001\x99\x04\x01'
|
|
||||||
assert m.db.stat['proxy']['Unknown_Ctrl'] == 0
|
|
||||||
|
|
||||||
m.ifc.tx_clear() # clear send buffer for next test
|
|
||||||
assert isclose(m.mb_timeout, 0.5)
|
|
||||||
assert next(m.mb_timer.exp_count) == 0
|
|
||||||
|
|
||||||
await asyncio.sleep(0.5)
|
|
||||||
assert m.sent_pdu==b'\x00\x00\x00 \x10R170000000000001pw\x00\x01\xa3(\x08\x01\x03\x45\x60\x00\x14\x50\xd7'
|
|
||||||
assert m.ifc.tx_fifo.get()==b''
|
|
||||||
|
|
||||||
m.read() # read complete msg, and dispatch msg
|
|
||||||
assert not m.header_valid # must be invalid, since msg was handled and buffer flushed
|
|
||||||
assert m.msg_count == 2
|
|
||||||
assert m.msg_recvd[1]['ctrl']==145
|
|
||||||
assert m.msg_recvd[1]['msg_id']==119
|
|
||||||
assert m.msg_recvd[1]['header_len']==23
|
|
||||||
assert m.msg_recvd[1]['data_len']==50
|
|
||||||
assert m.mb.last_addr == 1
|
|
||||||
assert m.mb.last_fcode == 3
|
|
||||||
assert m.mb.last_reg == 0x4560
|
|
||||||
assert m.mb.last_len == 20
|
|
||||||
assert m.mb.err == 0
|
|
||||||
|
|
||||||
assert next(m.mb_timer.exp_count) == 2
|
|
||||||
m.close()
|
|
||||||
|
|
||||||
def test_broken_recv_buf(config_tsun_allow_all, broken_recv_buf):
|
def test_broken_recv_buf(config_tsun_allow_all, broken_recv_buf):
|
||||||
_ = config_tsun_allow_all
|
_ = config_tsun_allow_all
|
||||||
m = MemoryStream(broken_recv_buf, (0,))
|
m = MemoryStream(broken_recv_buf, (0,))
|
||||||
|
|||||||
3
ha_addons/.gitignore
vendored
3
ha_addons/.gitignore
vendored
@@ -1,3 +1,2 @@
|
|||||||
.data.json
|
.data.json
|
||||||
config.yaml
|
config.yaml
|
||||||
apparmor.txt
|
|
||||||
@@ -8,71 +8,23 @@ JINJA = jinja2
|
|||||||
IMAGE = tsun-gen3-addon
|
IMAGE = tsun-gen3-addon
|
||||||
|
|
||||||
|
|
||||||
# Source folders for building the local add-on
|
# Folders
|
||||||
SRC=../app
|
SRC=../app
|
||||||
SRC_PROXY=$(SRC)/src
|
SRC_PROXY=$(SRC)/src
|
||||||
CNF_PROXY=$(SRC)/config
|
CNF_PROXY=$(SRC)/config
|
||||||
|
|
||||||
# Target folders for building the local add-on and the docker container
|
|
||||||
ADDON_PATH = ha_addon
|
ADDON_PATH = ha_addon
|
||||||
DST=$(ADDON_PATH)/rootfs
|
DST=$(ADDON_PATH)/rootfs
|
||||||
DST_PROXY=$(DST)/home/proxy
|
DST_PROXY=$(DST)/home/proxy
|
||||||
|
|
||||||
# base director of the add-on repro for installing the add-on git repros
|
INST_BASE=../../ha-addons/ha-addons
|
||||||
INST_BASE=../../ha-addons
|
|
||||||
|
|
||||||
# Template folder for build the config.yaml variants
|
|
||||||
TEMPL=templates
|
TEMPL=templates
|
||||||
|
|
||||||
# help variable STAGE determine the target to build
|
|
||||||
STAGE=dev
|
|
||||||
debug : STAGE=debug
|
|
||||||
rc : STAGE=rc
|
|
||||||
rel : STAGE=rel
|
|
||||||
|
|
||||||
|
|
||||||
export BUILD_DATE := ${shell date -Iminutes}
|
|
||||||
BUILD_ID := ${shell date +'%y%m%d%H%M'}
|
|
||||||
VERSION := $(shell cat $(SRC)/.version)
|
|
||||||
export MAJOR := $(shell echo $(VERSION) | cut -f1 -d.)
|
|
||||||
|
|
||||||
PUBLIC_URL := $(shell echo $(PUBLIC_CONTAINER_REGISTRY) | cut -f1 -d/)
|
|
||||||
PUBLIC_USER :=$(shell echo $(PUBLIC_CONTAINER_REGISTRY) | cut -f2 -d/)
|
|
||||||
|
|
||||||
build: local_add_on
|
|
||||||
|
|
||||||
dev debug: local_add_on
|
|
||||||
@echo version: $(VERSION) build-date: $(BUILD_DATE) image: $(PRIVAT_CONTAINER_REGISTRY)$(IMAGE)
|
|
||||||
export VERSION=$(VERSION)-$@-$(BUILD_ID) && \
|
|
||||||
export IMAGE=$(PRIVAT_CONTAINER_REGISTRY)$(IMAGE) && \
|
|
||||||
docker buildx bake -f docker-bake.hcl $@
|
|
||||||
|
|
||||||
rc rel: local_add_on
|
|
||||||
@echo version: $(VERSION) build-date: $(BUILD_DATE) image: $(PUBLIC_CONTAINER_REGISTRY)$(IMAGE)
|
|
||||||
@echo login at $(PUBLIC_URL) as $(PUBLIC_USER)
|
|
||||||
@DO_LOGIN="$(shell echo $(PUBLIC_CR_KEY) | docker login $(PUBLIC_URL) -u $(PUBLIC_USER) --password-stdin)"
|
|
||||||
export VERSION=$(VERSION)-$@ && \
|
|
||||||
export IMAGE=$(PUBLIC_CONTAINER_REGISTRY)$(IMAGE) && \
|
|
||||||
docker buildx bake -f docker-bake.hcl $@
|
|
||||||
|
|
||||||
clean:
|
|
||||||
rm -r -f $(DST_PROXY)
|
|
||||||
rm -f $(DST)/requirements.txt
|
|
||||||
rm -f $(ADDON_PATH)/config.yaml
|
|
||||||
rm -f $(TEMPL)/.data.json
|
|
||||||
docker logout ghcr.io
|
|
||||||
|
|
||||||
#############
|
|
||||||
# Build the local add-on with a rootfs and config.yaml
|
|
||||||
# The rootfs is needed to build the add-on Docker container
|
|
||||||
#
|
|
||||||
local_add_on: rootfs $(ADDON_PATH)/config.yaml $(ADDON_PATH)/apparmor.txt
|
|
||||||
|
|
||||||
# collect source files
|
# collect source files
|
||||||
SRC_FILES := $(wildcard $(SRC_PROXY)/*.py)\
|
SRC_FILES := $(wildcard $(SRC_PROXY)/*.py)\
|
||||||
$(wildcard $(SRC_PROXY)/*.ini)\
|
$(wildcard $(SRC_PROXY)/*.ini)\
|
||||||
$(wildcard $(SRC_PROXY)/cnf/*.py)\
|
$(wildcard $(SRC_PROXY)/cnf/*.py)\
|
||||||
$(wildcard $(SRC_PROXY)/cnf/*.toml)\
|
|
||||||
$(wildcard $(SRC_PROXY)/gen3/*.py)\
|
$(wildcard $(SRC_PROXY)/gen3/*.py)\
|
||||||
$(wildcard $(SRC_PROXY)/gen3plus/*.py)
|
$(wildcard $(SRC_PROXY)/gen3plus/*.py)
|
||||||
CNF_FILES := $(wildcard $(CNF_PROXY)/*.toml)
|
CNF_FILES := $(wildcard $(CNF_PROXY)/*.toml)
|
||||||
@@ -81,8 +33,49 @@ CNF_FILES := $(wildcard $(CNF_PROXY)/*.toml)
|
|||||||
TARGET_FILES = $(SRC_FILES:$(SRC_PROXY)/%=$(DST_PROXY)/%)
|
TARGET_FILES = $(SRC_FILES:$(SRC_PROXY)/%=$(DST_PROXY)/%)
|
||||||
CONFIG_FILES = $(CNF_FILES:$(CNF_PROXY)/%=$(DST_PROXY)/%)
|
CONFIG_FILES = $(CNF_FILES:$(CNF_PROXY)/%=$(DST_PROXY)/%)
|
||||||
|
|
||||||
|
export BUILD_DATE := ${shell date -Iminutes}
|
||||||
|
VERSION := $(shell cat $(SRC)/.version)
|
||||||
|
export MAJOR := $(shell echo $(VERSION) | cut -f1 -d.)
|
||||||
|
|
||||||
|
PUBLIC_URL := $(shell echo $(PUBLIC_CONTAINER_REGISTRY) | cut -f1 -d/)
|
||||||
|
PUBLIC_USER :=$(shell echo $(PUBLIC_CONTAINER_REGISTRY) | cut -f2 -d/)
|
||||||
|
|
||||||
|
|
||||||
|
dev debug: build
|
||||||
|
@echo version: $(VERSION) build-date: $(BUILD_DATE) image: $(PRIVAT_CONTAINER_REGISTRY)$(IMAGE)
|
||||||
|
export VERSION=$(VERSION)-$@ && \
|
||||||
|
export IMAGE=$(PRIVAT_CONTAINER_REGISTRY)$(IMAGE) && \
|
||||||
|
docker buildx bake -f docker-bake.hcl $@
|
||||||
|
|
||||||
|
rc rel: build
|
||||||
|
@echo version: $(VERSION) build-date: $(BUILD_DATE) image: $(PUBLIC_CONTAINER_REGISTRY)$(IMAGE)
|
||||||
|
@echo login at $(PUBLIC_URL) as $(PUBLIC_USER)
|
||||||
|
@DO_LOGIN="$(shell echo $(PUBLIC_CR_KEY) | docker login $(PUBLIC_URL) -u $(PUBLIC_USER) --password-stdin)"
|
||||||
|
export VERSION=$(VERSION)-$@ && \
|
||||||
|
export IMAGE=$(PUBLIC_CONTAINER_REGISTRY)$(IMAGE) && \
|
||||||
|
docker buildx bake -f docker-bake.hcl $@
|
||||||
|
|
||||||
|
|
||||||
|
build: rootfs $(ADDON_PATH)/config.yaml repro
|
||||||
|
|
||||||
|
clean:
|
||||||
|
rm -r -f $(DST_PROXY)
|
||||||
|
rm -f $(DST)/requirements.txt
|
||||||
|
rm -f $(ADDON_PATH)/config.yaml
|
||||||
|
rm -f $(TEMPL)/.data.json
|
||||||
|
|
||||||
|
#
|
||||||
|
# Build rootfs and config.yaml as local add-on
|
||||||
|
# The rootfs is needed to build the add-on Dockercontainers
|
||||||
|
#
|
||||||
|
|
||||||
rootfs: $(TARGET_FILES) $(CONFIG_FILES) $(DST)/requirements.txt
|
rootfs: $(TARGET_FILES) $(CONFIG_FILES) $(DST)/requirements.txt
|
||||||
|
|
||||||
|
STAGE=dev
|
||||||
|
debug : STAGE=debug
|
||||||
|
rc : STAGE=rc
|
||||||
|
rel : STAGE=rel
|
||||||
|
|
||||||
$(CONFIG_FILES): $(DST_PROXY)/% : $(CNF_PROXY)/%
|
$(CONFIG_FILES): $(DST_PROXY)/% : $(CNF_PROXY)/%
|
||||||
@echo Copy $< to $@
|
@echo Copy $< to $@
|
||||||
@mkdir -p $(@D)
|
@mkdir -p $(@D)
|
||||||
@@ -98,78 +91,40 @@ $(DST)/requirements.txt : $(SRC)/requirements.txt
|
|||||||
@cp $< $@
|
@cp $< $@
|
||||||
|
|
||||||
$(ADDON_PATH)/%.yaml: $(TEMPL)/%.jinja $(TEMPL)/.data.json
|
$(ADDON_PATH)/%.yaml: $(TEMPL)/%.jinja $(TEMPL)/.data.json
|
||||||
$(JINJA) --strict -D AppVersion=$(VERSION) -D BuildID=$(BUILD_ID) --format=json $^ -o $@
|
$(JINJA) --strict -D AppVersion=$(VERSION) --format=json $^ -o $@
|
||||||
|
|
||||||
$(ADDON_PATH)/%.txt: $(TEMPL)/%.jinja $(TEMPL)/.data.json
|
|
||||||
$(JINJA) --strict --format=json $^ -o $@
|
|
||||||
|
|
||||||
# build a common data.json file from STAGE depending source files
|
|
||||||
# don't touch the destination if the checksum of src and dst is equal
|
|
||||||
$(TEMPL)/.data.json: FORCE
|
$(TEMPL)/.data.json: FORCE
|
||||||
rsync --checksum $(TEMPL)/$(STAGE)_data.json $@
|
rsync --checksum $(TEMPL)/$(STAGE)_data.json $@
|
||||||
|
|
||||||
FORCE : ;
|
FORCE : ;
|
||||||
|
|
||||||
|
|
||||||
#############
|
#
|
||||||
# Build repository for Home Assistant Add-Onx
|
# Build repository for Home Assistant Add-On
|
||||||
#
|
#
|
||||||
|
|
||||||
|
INST=$(INST_BASE)/ha_addon_dev
|
||||||
repro_files = DOCS.md icon.png logo.png translations/de.yaml translations/en.yaml rootfs/run.sh
|
repro_files = DOCS.md icon.png logo.png translations/de.yaml translations/en.yaml rootfs/run.sh
|
||||||
repro_root = CHANGELOG.md LICENSE.md
|
repro_root = CHANGELOG.md
|
||||||
repro_templates = config.yaml
|
repro_templates = config.yaml
|
||||||
repro_apparmor = apparmor.txt
|
|
||||||
repro_subdirs = translations rootfs
|
repro_subdirs = translations rootfs
|
||||||
repro_vers = debug dev rc rel
|
repro_vers = debug dev rc rel
|
||||||
|
|
||||||
repro_all_files := $(foreach dir,$(repro_vers), $(foreach file,$(repro_files),$(INST_BASE)/ha_addon_$(dir)/$(file)))
|
repro_all_files := $(foreach dir,$(repro_vers), $(foreach file,$(repro_files),$(INST_BASE)/ha_addon_$(dir)/$(file)))
|
||||||
repro_root_files := $(foreach dir,$(repro_vers), $(foreach file,$(repro_root),$(INST_BASE)/ha_addon_$(dir)/$(file)))
|
repro_root_files := $(foreach dir,$(repro_vers), $(foreach file,$(repro_root),$(INST_BASE)/ha_addon_$(dir)/$(file)))
|
||||||
repro_all_templates := $(foreach dir,$(repro_vers), $(foreach file,$(repro_templates),$(INST_BASE)/ha_addon_$(dir)/$(file)))
|
repro_all_templates := $(foreach dir,$(repro_vers), $(foreach file,$(repro_templates),$(INST_BASE)/ha_addon_$(dir)/$(file)))
|
||||||
repro_all_apparmor := $(foreach dir,$(repro_vers), $(foreach file,$(repro_apparmor),$(INST_BASE)/ha_addon_$(dir)/$(file)))
|
|
||||||
repro_all_subdirs := $(foreach dir,$(repro_vers), $(foreach file,$(repro_subdirs),$(INST_BASE)/ha_addon_$(dir)/$(file)))
|
repro_all_subdirs := $(foreach dir,$(repro_vers), $(foreach file,$(repro_subdirs),$(INST_BASE)/ha_addon_$(dir)/$(file)))
|
||||||
|
|
||||||
debug: $(foreach file,$(repro_subdirs),$(INST_BASE)/ha_addon_debug/$(file)) \
|
repro: $(repro_all_subdirs) $(repro_all_templates) $(repro_all_files) $(repro_root_files)
|
||||||
$(foreach file,$(repro_templates),$(INST_BASE)/ha_addon_debug/$(file)) \
|
|
||||||
$(foreach file,$(repro_apparmor),$(INST_BASE)/ha_addon_debug/$(file)) \
|
|
||||||
$(foreach file,$(repro_files),$(INST_BASE)/ha_addon_debug/$(file)) \
|
|
||||||
$(foreach file,$(repro_root),$(INST_BASE)/ha_addon_debug/$(file))
|
|
||||||
|
|
||||||
dev: $(foreach file,$(repro_subdirs),$(INST_BASE)/ha_addon_dev/$(file)) \
|
|
||||||
$(foreach file,$(repro_templates),$(INST_BASE)/ha_addon_dev/$(file)) \
|
|
||||||
$(foreach file,$(repro_apparmor),$(INST_BASE)/ha_addon_dev/$(file)) \
|
|
||||||
$(foreach file,$(repro_files),$(INST_BASE)/ha_addon_dev/$(file)) \
|
|
||||||
$(foreach file,$(repro_root),$(INST_BASE)/ha_addon_dev/$(file))
|
|
||||||
|
|
||||||
rc: $(foreach file,$(repro_subdirs),$(INST_BASE)/ha_addon_rc/$(file)) \
|
|
||||||
$(foreach file,$(repro_templates),$(INST_BASE)/ha_addon_rc/$(file)) \
|
|
||||||
$(foreach file,$(repro_apparmor),$(INST_BASE)/ha_addon_rc/$(file)) \
|
|
||||||
$(foreach file,$(repro_files),$(INST_BASE)/ha_addon_rc/$(file)) \
|
|
||||||
$(foreach file,$(repro_root),$(INST_BASE)/ha_addon_rc/$(file))
|
|
||||||
|
|
||||||
rel: $(foreach file,$(repro_subdirs),$(INST_BASE)/ha_addon_rel/$(file)) \
|
|
||||||
$(foreach file,$(repro_templates),$(INST_BASE)/ha_addon_rel/$(file)) \
|
|
||||||
$(foreach file,$(repro_apparmor),$(INST_BASE)/ha_addon_rel/$(file)) \
|
|
||||||
$(foreach file,$(repro_files),$(INST_BASE)/ha_addon_rel/$(file)) \
|
|
||||||
$(foreach file,$(repro_root),$(INST_BASE)/ha_addon_rel/$(file))
|
|
||||||
|
|
||||||
$(repro_all_subdirs) :
|
$(repro_all_subdirs) :
|
||||||
mkdir -p $@
|
mkdir -p $@
|
||||||
|
|
||||||
$(repro_all_templates) : $(INST_BASE)/ha_addon_%/config.yaml: $(TEMPL)/config.jinja $(TEMPL)/%_data.json $(SRC)/.version FORCE
|
$(repro_all_templates) : $(INST_BASE)/ha_addon_%/config.yaml: $(TEMPL)/config.jinja $(TEMPL)/%_data.json $(SRC)/.version
|
||||||
$(JINJA) --strict -D AppVersion=$(VERSION)-$* -D BuildID=$(BUILD_ID) $< $(filter %.json,$^) -o $@
|
$(JINJA) --strict -D AppVersion=$(VERSION)-$* $< $(filter %.json,$^) -o $@
|
||||||
|
|
||||||
$(repro_all_apparmor) : $(INST_BASE)/ha_addon_%/apparmor.txt: $(TEMPL)/apparmor.jinja $(TEMPL)/%_data.json
|
$(repro_root_files) : %/CHANGELOG.md : ../CHANGELOG.md
|
||||||
$(JINJA) --strict $< $(filter %.json,$^) -o $@
|
|
||||||
|
|
||||||
$(filter $(INST_BASE)/ha_addon_debug/%,$(repro_root_files)) : $(INST_BASE)/ha_addon_debug/% : ../%
|
|
||||||
cp $< $@
|
cp $< $@
|
||||||
$(filter $(INST_BASE)/ha_addon_dev/%,$(repro_root_files)) : $(INST_BASE)/ha_addon_dev/% : ../%
|
|
||||||
cp $< $@
|
|
||||||
$(filter $(INST_BASE)/ha_addon_rc/%,$(repro_root_files)) : $(INST_BASE)/ha_addon_rc/% : ../%
|
|
||||||
cp $< $@
|
|
||||||
$(filter $(INST_BASE)/ha_addon_rel/%,$(repro_root_files)) : $(INST_BASE)/ha_addon_rel/% : ../%
|
|
||||||
cp $< $@
|
|
||||||
|
|
||||||
|
|
||||||
$(filter $(INST_BASE)/ha_addon_debug/%,$(repro_all_files)) : $(INST_BASE)/ha_addon_debug/% : ha_addon/%
|
$(filter $(INST_BASE)/ha_addon_debug/%,$(repro_all_files)) : $(INST_BASE)/ha_addon_debug/% : ha_addon/%
|
||||||
cp $< $@
|
cp $< $@
|
||||||
@@ -179,3 +134,5 @@ $(filter $(INST_BASE)/ha_addon_rc/%,$(repro_all_files)) : $(INST_BASE)/ha_addon_
|
|||||||
cp $< $@
|
cp $< $@
|
||||||
$(filter $(INST_BASE)/ha_addon_rel/%,$(repro_all_files)) : $(INST_BASE)/ha_addon_rel/% : ha_addon/%
|
$(filter $(INST_BASE)/ha_addon_rel/%,$(repro_all_files)) : $(INST_BASE)/ha_addon_rel/% : ha_addon/%
|
||||||
cp $< $@
|
cp $< $@
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -74,12 +74,12 @@ target "_prod" {
|
|||||||
}
|
}
|
||||||
target "debug" {
|
target "debug" {
|
||||||
inherits = ["_common", "_debug"]
|
inherits = ["_common", "_debug"]
|
||||||
tags = ["${IMAGE}:debug", "${IMAGE}:${VERSION}"]
|
tags = ["${IMAGE}:debug"]
|
||||||
}
|
}
|
||||||
|
|
||||||
target "dev" {
|
target "dev" {
|
||||||
inherits = ["_common"]
|
inherits = ["_common"]
|
||||||
tags = ["${IMAGE}:dev", "${IMAGE}:${VERSION}"]
|
tags = ["${IMAGE}:dev"]
|
||||||
}
|
}
|
||||||
|
|
||||||
target "preview" {
|
target "preview" {
|
||||||
|
|||||||
@@ -68,8 +68,8 @@ Example add-on configuration for GEN3PLUS inverters:
|
|||||||
inverters:
|
inverters:
|
||||||
- serial: Y17000000000000
|
- serial: Y17000000000000
|
||||||
monitor_sn: 2000000000
|
monitor_sn: 2000000000
|
||||||
node_id: inv_1
|
node_id: PV-Garage
|
||||||
suggested_area: Roof
|
suggested_area: Garage
|
||||||
modbus_polling: true
|
modbus_polling: true
|
||||||
client_mode.host: 192.168.x.x
|
client_mode.host: 192.168.x.x
|
||||||
client_mode.port: 8899
|
client_mode.port: 8899
|
||||||
@@ -84,21 +84,6 @@ inverters:
|
|||||||
pv4.type: SF-M18/144550
|
pv4.type: SF-M18/144550
|
||||||
```
|
```
|
||||||
|
|
||||||
Example add-on configuration for GEN3PLUS energie storages:
|
|
||||||
|
|
||||||
```yaml
|
|
||||||
batteries:
|
|
||||||
- serial: 4100000000000000
|
|
||||||
monitor_sn: 2300000000
|
|
||||||
node_id: bat_1
|
|
||||||
suggested_area: Garage
|
|
||||||
modbus_polling: false
|
|
||||||
pv1.manufacturer: Shinefar
|
|
||||||
pv1.type: SF-M18/144550
|
|
||||||
pv2.manufacturer: Shinefar
|
|
||||||
pv2.type: SF-M18/144550
|
|
||||||
```
|
|
||||||
|
|
||||||
**Note**: _This is just an example, you need to replace the values with your own!_
|
**Note**: _This is just an example, you need to replace the values with your own!_
|
||||||
|
|
||||||
more information about the configuration can be found in the [configuration details page][configdetails].
|
more information about the configuration can be found in the [configuration details page][configdetails].
|
||||||
|
|||||||
@@ -13,12 +13,12 @@
|
|||||||
# 1 Build Base Image #
|
# 1 Build Base Image #
|
||||||
######################
|
######################
|
||||||
|
|
||||||
ARG BUILD_FROM="ghcr.io/hassio-addons/base:17.2.2"
|
ARG BUILD_FROM="ghcr.io/hassio-addons/base:17.1.0"
|
||||||
# hadolint ignore=DL3006
|
# hadolint ignore=DL3006
|
||||||
FROM $BUILD_FROM AS base
|
FROM $BUILD_FROM AS base
|
||||||
|
|
||||||
# Installiere Python, pip und virtuelle Umgebungstools
|
# Installiere Python, pip und virtuelle Umgebungstools
|
||||||
RUN apk add --no-cache python3=3.12.9-r0 py3-pip=24.3.1-r0 && \
|
RUN apk add --no-cache python3=3.12.8-r1 py3-pip=24.3.1-r0 && \
|
||||||
python -m venv /opt/venv && \
|
python -m venv /opt/venv && \
|
||||||
. /opt/venv/bin/activate
|
. /opt/venv/bin/activate
|
||||||
|
|
||||||
@@ -47,8 +47,6 @@ FROM base AS runtime
|
|||||||
|
|
||||||
ARG SERVICE_NAME
|
ARG SERVICE_NAME
|
||||||
ARG VERSION
|
ARG VERSION
|
||||||
ARG LOG_LVL=INFO
|
|
||||||
ENV LOG_LVL=$LOG_LVL
|
|
||||||
ENV SERVICE_NAME=${SERVICE_NAME}
|
ENV SERVICE_NAME=${SERVICE_NAME}
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -10,21 +10,8 @@ configuration:
|
|||||||
Weitere wechselrichterspezifische Parameter (z.B. Polling Mode) können im
|
Weitere wechselrichterspezifische Parameter (z.B. Polling Mode) können im
|
||||||
Konfigurationsblock gesetzt werden.
|
Konfigurationsblock gesetzt werden.
|
||||||
|
|
||||||
Die Seriennummer der GEN3 Wechselrichter beginnen mit `R17` oder `R47` und die der GEN3PLUS
|
Die Seriennummer der GEN3 Wechselrichter beginnen mit `R17` und die der GEN3PLUS
|
||||||
Wechselrichter mit `Y17`oder `Y47`!
|
Wechselrichter mir `Y17`oder `47`!
|
||||||
|
|
||||||
Siehe Beispielkonfiguration im Dokumentations-Tab
|
|
||||||
batteries:
|
|
||||||
name: Batterien
|
|
||||||
description: >+
|
|
||||||
Für jeden Energiespeicher muss die Seriennummer des Speichers einer MQTT
|
|
||||||
Definition zugeordnet werden. Dazu wird der entsprechende Konfigurationsblock mit der
|
|
||||||
16-stellige Seriennummer gestartet, so dass alle nachfolgenden Parameter diesem
|
|
||||||
Speicher zugeordnet sind.
|
|
||||||
Weitere speicherspezifische Parameter (z.B. Polling Mode) können im
|
|
||||||
Konfigurationsblock gesetzt werden.
|
|
||||||
|
|
||||||
Die Seriennummer der GEN3PLUS Batteriespeicher beginnen mit `410`!
|
|
||||||
|
|
||||||
Siehe Beispielkonfiguration im Dokumentations-Tab
|
Siehe Beispielkonfiguration im Dokumentations-Tab
|
||||||
|
|
||||||
@@ -38,14 +25,14 @@ configuration:
|
|||||||
ein => normaler Proxy-Betrieb.
|
ein => normaler Proxy-Betrieb.
|
||||||
aus => Der Wechselrichter wird vom Internet isoliert.
|
aus => Der Wechselrichter wird vom Internet isoliert.
|
||||||
solarman.enabled:
|
solarman.enabled:
|
||||||
name: Verbindung zur Solarman/TSUN Cloud - nur für GEN3PLUS Wechselrichter
|
name: Verbindung zur Solarman Cloud - nur für GEN3PLUS Wechselrichter
|
||||||
description: >+
|
description: >+
|
||||||
Schaltet die Verbindung zur Solarman oder TSUN Cloud ein/aus.
|
Schaltet die Verbindung zur Solarman Cloud ein/aus.
|
||||||
Diese Verbindung ist erforderlich, wenn Sie Daten an die Cloud senden möchten,
|
Diese Verbindung ist erforderlich, wenn Sie Daten an die Solarman Cloud senden möchten,
|
||||||
z.B. um die Solarman App oder TSUN Smart App zu nutzen oder Firmware-Updates zu erhalten.
|
z.B. um die Solarman Apps zu nutzen oder Firmware-Updates zu erhalten.
|
||||||
|
|
||||||
ein => normaler Proxy-Betrieb.
|
ein => normaler Proxy-Betrieb.
|
||||||
aus => Die GEN3PLUS Geräte werden vom Internet isoliert.
|
aus => Der Wechselrichter wird vom Internet isoliert.
|
||||||
inverters.allow_all:
|
inverters.allow_all:
|
||||||
name: Erlaube Verbindungen von sämtlichen Wechselrichtern
|
name: Erlaube Verbindungen von sämtlichen Wechselrichtern
|
||||||
description: >-
|
description: >-
|
||||||
|
|||||||
@@ -7,27 +7,13 @@ configuration:
|
|||||||
definition. To do this, the corresponding configuration block is started with
|
definition. To do this, the corresponding configuration block is started with
|
||||||
16-digit serial number so that all subsequent parameters are assigned
|
16-digit serial number so that all subsequent parameters are assigned
|
||||||
to this inverter. Further inverter-specific parameters (e.g. polling mode) can be set
|
to this inverter. Further inverter-specific parameters (e.g. polling mode) can be set
|
||||||
in the configuration block.
|
in the configuration block
|
||||||
|
|
||||||
The serial numbers of all GEN3 inverters start with `R17` or `R47` and that of the GEN3PLUS
|
The serial numbers of all GEN3 inverters start with `R17` and that of the GEN3PLUS
|
||||||
inverters with ‘Y17’ or ‘Y47’!
|
inverters with ‘Y17’ or ‘47’!
|
||||||
|
|
||||||
For reference see example configuration in Documentation Tab
|
For reference see example configuration in Documentation Tab
|
||||||
|
|
||||||
batteries:
|
|
||||||
name: Energy Storages
|
|
||||||
description: >+
|
|
||||||
For each energy storage device, the serial number of the storage device must be
|
|
||||||
assigned to an MQTT definition. To do this, the corresponding configuration block
|
|
||||||
is started with the 16-digit serial number so that all subsequent parameters are
|
|
||||||
assigned to this energy storage. Further inverter-specific parameters (e.g. polling
|
|
||||||
mode) can be set in the configuration block.
|
|
||||||
|
|
||||||
The serial numbers of all GEN3PLUS energy storages start with ‘410’!
|
|
||||||
|
|
||||||
For reference see example configuration in Documentation Tab
|
|
||||||
|
|
||||||
|
|
||||||
tsun.enabled:
|
tsun.enabled:
|
||||||
name: Connection to TSUN Cloud - for GEN3 inverter only
|
name: Connection to TSUN Cloud - for GEN3 inverter only
|
||||||
description: >+
|
description: >+
|
||||||
@@ -38,14 +24,14 @@ configuration:
|
|||||||
on => normal proxy operation.
|
on => normal proxy operation.
|
||||||
off => The Inverter become isolated from Internet.
|
off => The Inverter become isolated from Internet.
|
||||||
solarman.enabled:
|
solarman.enabled:
|
||||||
name: Connection to Solarman/TSUN Cloud - for GEN3PLUS inverter only
|
name: Connection to Solarman Cloud - for GEN3PLUS inverter only
|
||||||
description: >+
|
description: >+
|
||||||
switch on/off connection to the Solarman or TSUN cloud.
|
switch on/off connection to the Solarman cloud.
|
||||||
This connection is only required if you want send data to the cloud
|
This connection is only required if you want send data to the Solarman cloud
|
||||||
eg. to use the Solarman APP, the TSUN Smart APP or receive firmware updates.
|
eg. to use the Solarman APPs or receive firmware updates.
|
||||||
|
|
||||||
on => normal proxy operation.
|
on => normal proxy operation.
|
||||||
off => The GEN3PLUS devices become isolated from Internet
|
off => The Inverter become isolated from Internet
|
||||||
inverters.allow_all:
|
inverters.allow_all:
|
||||||
name: Allow all connections from all inverters
|
name: Allow all connections from all inverters
|
||||||
description: >-
|
description: >-
|
||||||
|
|||||||
@@ -1,52 +0,0 @@
|
|||||||
#include <tunables/global>
|
|
||||||
|
|
||||||
profile {{slug}} flags=(attach_disconnected,mediate_deleted) {
|
|
||||||
#include <abstractions/base>
|
|
||||||
|
|
||||||
# Capabilities
|
|
||||||
file,
|
|
||||||
signal (send) set=(kill,term,int,hup,cont),
|
|
||||||
|
|
||||||
# S6-Overlay
|
|
||||||
/init ix,
|
|
||||||
/bin/** ix,
|
|
||||||
/usr/bin/** ix,
|
|
||||||
/run/{s6,s6-rc*,service}/** ix,
|
|
||||||
/package/** ix,
|
|
||||||
/command/** ix,
|
|
||||||
/etc/services.d/** rwix,
|
|
||||||
/etc/cont-init.d/** rwix,
|
|
||||||
/etc/cont-finish.d/** rwix,
|
|
||||||
/run/{,**} rwk,
|
|
||||||
/dev/tty rw,
|
|
||||||
|
|
||||||
# Bashio
|
|
||||||
/usr/lib/bashio/** ix,
|
|
||||||
/tmp/** rwk,
|
|
||||||
|
|
||||||
# Access to options.json and other files within your addon
|
|
||||||
/data/** rw,
|
|
||||||
|
|
||||||
# Start new profile for service
|
|
||||||
/usr/bin/myprogram cx -> myprogram,
|
|
||||||
|
|
||||||
profile myprogram flags=(attach_disconnected,mediate_deleted) {
|
|
||||||
#include <abstractions/base>
|
|
||||||
|
|
||||||
# Receive signals from S6-Overlay
|
|
||||||
signal (receive) peer=*_{{slug}},
|
|
||||||
|
|
||||||
# Access to options.json and other files within your addon
|
|
||||||
/data/** rw,
|
|
||||||
|
|
||||||
# Access to mapped volumes specified in config.json
|
|
||||||
/share/** rw,
|
|
||||||
|
|
||||||
# Access required for service functionality
|
|
||||||
/usr/bin/myprogram r,
|
|
||||||
/bin/bash rix,
|
|
||||||
/bin/echo ix,
|
|
||||||
/etc/passwd r,
|
|
||||||
/dev/tty rw,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,6 +1,6 @@
|
|||||||
name: {{name}}
|
name: {{name}}
|
||||||
description: {{description}}
|
description: {{description}}
|
||||||
version: {% if version is defined and version|length %} {{version}} {% elif BuildID is defined and BuildID|length %} {{AppVersion}}-{{BuildID}} {% else %} {{AppVersion}} {% endif %}
|
version: {% if version is defined and version|length %} {{version}} {% else %} {{AppVersion}} {% endif %}
|
||||||
image: {{image}}
|
image: {{image}}
|
||||||
url: https://github.com/s-allius/tsun-gen3-proxy
|
url: https://github.com/s-allius/tsun-gen3-proxy
|
||||||
slug: {{slug}}
|
slug: {{slug}}
|
||||||
@@ -24,15 +24,17 @@ ports:
|
|||||||
5005/tcp: 5005
|
5005/tcp: 5005
|
||||||
10000/tcp: 10000
|
10000/tcp: 10000
|
||||||
|
|
||||||
watchdog: "http://[HOST]:[PORT:8127]/-/healthy"
|
# FIXME: we disabled the watchdog due to exceptions in the ha supervisor. See: https://github.com/s-allius/tsun-gen3-proxy/issues/249
|
||||||
|
# watchdog: "http://[HOST]:[PORT:8127]/-/healthy"
|
||||||
|
|
||||||
# Definition of parameters in the configuration tab of the addon
|
# Definition of parameters in the configuration tab of the addon
|
||||||
# parameters are available within the container as /data/options.json
|
# parameters are available within the container as /data/options.json
|
||||||
# and should become picked up by the proxy - current workaround as a transfer script
|
# and should become picked up by the proxy - current workaround as a transfer script
|
||||||
|
# TODO: check again for multi hierarchie parameters
|
||||||
|
|
||||||
schema:
|
schema:
|
||||||
inverters:
|
inverters:
|
||||||
- serial: match(^(R17|R47|Y17|Y47).{13}$)
|
- serial: match(^(R17|Y17|Y47).{13}$)
|
||||||
monitor_sn: int?
|
monitor_sn: int?
|
||||||
node_id: str
|
node_id: str
|
||||||
suggested_area: str
|
suggested_area: str
|
||||||
@@ -40,9 +42,11 @@ schema:
|
|||||||
client_mode.host: match(\b((25[0-5]|2[0-4][0-9]|1[0-9]{2}|[1-9]?[0-9])\.){3}(25[0-5]|2[0-4][0-9]|1[0-9]{2}|[1-9]?[0-9])\b)?
|
client_mode.host: match(\b((25[0-5]|2[0-4][0-9]|1[0-9]{2}|[1-9]?[0-9])\.){3}(25[0-5]|2[0-4][0-9]|1[0-9]{2}|[1-9]?[0-9])\b)?
|
||||||
client_mode.port: port?
|
client_mode.port: port?
|
||||||
client_mode.forward: bool?
|
client_mode.forward: bool?
|
||||||
modbus_scanning.start: int(0,65535)?
|
#strings: # leider funktioniert es nicht die folgenden 3 parameter im schema aufzulisten. möglicherweise wird die verschachtelung nicht unterstützt.
|
||||||
modbus_scanning.step: int(0,65535)?
|
# - string: str
|
||||||
modbus_scanning.bytes: int(1,80)?
|
# type: str
|
||||||
|
# manufacturer: str
|
||||||
|
# daher diese variante
|
||||||
pv1.manufacturer: str?
|
pv1.manufacturer: str?
|
||||||
pv1.type: str?
|
pv1.type: str?
|
||||||
pv2.manufacturer: str?
|
pv2.manufacturer: str?
|
||||||
@@ -58,19 +62,6 @@ schema:
|
|||||||
tsun.enabled: bool
|
tsun.enabled: bool
|
||||||
solarman.enabled: bool
|
solarman.enabled: bool
|
||||||
inverters.allow_all: bool
|
inverters.allow_all: bool
|
||||||
batteries:
|
|
||||||
- serial: match(^(410).{13}$)
|
|
||||||
monitor_sn: int
|
|
||||||
node_id: str
|
|
||||||
suggested_area: str
|
|
||||||
modbus_polling: bool
|
|
||||||
client_mode.host: match(\b((25[0-5]|2[0-4][0-9]|1[0-9]{2}|[1-9]?[0-9])\.){3}(25[0-5]|2[0-4][0-9]|1[0-9]{2}|[1-9]?[0-9])\b)?
|
|
||||||
client_mode.port: port?
|
|
||||||
client_mode.forward: bool?
|
|
||||||
pv1.manufacturer: str?
|
|
||||||
pv1.type: str?
|
|
||||||
pv2.manufacturer: str?
|
|
||||||
pv2.type: str?
|
|
||||||
|
|
||||||
# optionale parameter
|
# optionale parameter
|
||||||
|
|
||||||
@@ -99,21 +90,17 @@ schema:
|
|||||||
# If any default value is given, the option becomes a required value.
|
# If any default value is given, the option becomes a required value.
|
||||||
options:
|
options:
|
||||||
inverters:
|
inverters:
|
||||||
- serial: R17E000000000000
|
- serial: R17E760702080400
|
||||||
monitor_sn: 0
|
node_id: PV-Garage
|
||||||
node_id: inv_1
|
|
||||||
suggested_area: Roof
|
|
||||||
modbus_polling: false
|
|
||||||
pv1.manufacturer: Shinefar
|
|
||||||
pv1.type: SF-M18/144550
|
|
||||||
pv2.manufacturer: Shinefar
|
|
||||||
pv2.type: SF-M18/144550
|
|
||||||
batteries:
|
|
||||||
- serial: 4100000000000000
|
|
||||||
monitor_sn: 0
|
|
||||||
node_id: bat_1
|
|
||||||
suggested_area: Garage
|
suggested_area: Garage
|
||||||
modbus_polling: false
|
modbus_polling: false
|
||||||
|
# strings:
|
||||||
|
# - string: PV1
|
||||||
|
# type: SF-M18/144550
|
||||||
|
# manufacturer: Shinefar
|
||||||
|
# - string: PV2
|
||||||
|
# type: SF-M18/144550
|
||||||
|
# manufacturer: Shinefar
|
||||||
pv1.manufacturer: Shinefar
|
pv1.manufacturer: Shinefar
|
||||||
pv1.type: SF-M18/144550
|
pv1.type: SF-M18/144550
|
||||||
pv2.manufacturer: Shinefar
|
pv2.manufacturer: Shinefar
|
||||||
|
|||||||
@@ -2,6 +2,7 @@
|
|||||||
{
|
{
|
||||||
"name": "TSUN-Proxy (Debug)",
|
"name": "TSUN-Proxy (Debug)",
|
||||||
"description": "MQTT Proxy for TSUN Photovoltaic Inverters with Debug Logging",
|
"description": "MQTT Proxy for TSUN Photovoltaic Inverters with Debug Logging",
|
||||||
|
"version": "debug",
|
||||||
"image": "docker.io/sallius/tsun-gen3-addon",
|
"image": "docker.io/sallius/tsun-gen3-addon",
|
||||||
"slug": "tsun-proxy-debug",
|
"slug": "tsun-proxy-debug",
|
||||||
"advanced": true,
|
"advanced": true,
|
||||||
|
|||||||
@@ -2,6 +2,7 @@
|
|||||||
{
|
{
|
||||||
"name": "TSUN-Proxy (Dev)",
|
"name": "TSUN-Proxy (Dev)",
|
||||||
"description": "MQTT Proxy for TSUN Photovoltaic Inverters",
|
"description": "MQTT Proxy for TSUN Photovoltaic Inverters",
|
||||||
|
"version": "dev",
|
||||||
"image": "docker.io/sallius/tsun-gen3-addon",
|
"image": "docker.io/sallius/tsun-gen3-addon",
|
||||||
"slug": "tsun-proxy-dev",
|
"slug": "tsun-proxy-dev",
|
||||||
"advanced": false,
|
"advanced": false,
|
||||||
|
|||||||
@@ -15,10 +15,6 @@ sonar.sources=app/src/
|
|||||||
sonar.python.version=3.12
|
sonar.python.version=3.12
|
||||||
sonar.tests=system_tests/,app/tests/
|
sonar.tests=system_tests/,app/tests/
|
||||||
sonar.exclusions=**/.vscode/**/*
|
sonar.exclusions=**/.vscode/**/*
|
||||||
|
|
||||||
# disable code dupication check for config grammar
|
|
||||||
sonar.cpd.exclusions=app/src/cnf/config.py
|
|
||||||
|
|
||||||
# Name your criteria
|
# Name your criteria
|
||||||
sonar.issue.ignore.multicriteria=e1,e2
|
sonar.issue.ignore.multicriteria=e1,e2
|
||||||
|
|
||||||
|
|||||||
@@ -93,155 +93,6 @@ def msg_inverter_ind(): # Data indication from the inverter
|
|||||||
msg += b'\x53\x00\x00'
|
msg += b'\x53\x00\x00'
|
||||||
return msg
|
return msg
|
||||||
|
|
||||||
@pytest.fixture
|
|
||||||
def msg_inverter_ind2(): # Data indication from the inverter
|
|
||||||
msg = b'\x00\x00\x08\xff\x10'+ get_sn() + b'\x91\x04\x01\x90\x00\x00\x10'+get_inv_no()
|
|
||||||
msg += b'\x01\x00\x00\x01'
|
|
||||||
msg += b'\x95\x18\x5e\x1d\x80\x00\x00\x01\x2c\x00\x00\x00\x64\x53\x00\x00' # | ..^.....,...dS..
|
|
||||||
msg += b'\x00\x00\x00\xc8\x53\x44\x00\x00\x00\x01\x2c\x53\x00\x00\x00\x00' # | ....SD....,S....
|
|
||||||
msg += b'\x01\x90\x49\x00\x00\x00\x00\x00\x00\x01\x91\x53\x00\x00\x00\x00' # | ..I........S....
|
|
||||||
msg += b'\x01\x92\x53\x00\x00\x00\x00\x01\x93\x53\x00\x00\x00\x00\x01\x94' # | ..S......S......
|
|
||||||
msg += b'\x53\x00\x00\x00\x00\x01\x95\x53\x00\x00\x00\x00\x01\x96\x53\x00' # | S......S......S.
|
|
||||||
msg += b'\x00\x00\x00\x01\x97\x53\x00\x00\x00\x00\x01\x98\x53\x00\x00\x00' # | .....S......S...
|
|
||||||
msg += b'\x00\x01\x99\x53\x00\x00\x00\x00\x01\x9a\x53\x00\x00\x00\x00\x01' # | ...S......S.....
|
|
||||||
msg += b'\x9b\x53\x00\x00\x00\x00\x01\x9c\x53\x00\x00\x00\x00\x01\x9d\x53' # | .S......S......S
|
|
||||||
msg += b'\x00\x00\x00\x00\x01\x9e\x53\x00\x00\x00\x00\x01\x9f\x53\x00\x00' # | ......S......S..
|
|
||||||
msg += b'\x00\x00\x01\xa0\x53\x00\x00\x00\x00\x01\xf4\x49\x00\x00\x00\x00' # | ....S......I....
|
|
||||||
msg += b'\x00\x00\x01\xf5\x53\x00\x00\x00\x00\x01\xf6\x53\x00\x00\x00\x00' # | ....S......S....
|
|
||||||
msg += b'\x01\xf7\x53\x00\x00\x00\x00\x01\xf8\x53\x00\x00\x00\x00\x01\xf9' # | ..S......S......
|
|
||||||
msg += b'\x53\x00\x00\x00\x00\x01\xfa\x53\x00\x00\x00\x00\x01\xfb\x53\x00' # | S......S......S.
|
|
||||||
msg += b'\x00\x00\x00\x01\xfc\x53\x00\x00\x00\x00\x01\xfd\x53\x00\x00\x00' # | .....S......S...
|
|
||||||
msg += b'\x00\x01\xfe\x53\x00\x00\x00\x00\x01\xff\x53\x00\x00\x00\x00\x02' # | ...S......S.....
|
|
||||||
msg += b'\x00\x53\x00\x00\x00\x00\x02\x01\x53\x00\x00\x00\x00\x02\x02\x53' # | .S......S......S
|
|
||||||
msg += b'\x00\x00\x00\x00\x02\x03\x53\x00\x00\x00\x00\x02\x04\x53\x00\x00' # | ......S......S..
|
|
||||||
msg += b'\x00\x00\x02\x58\x49\x00\x00\x00\x00\x00\x00\x02\x59\x53\x00\x00' # | ...XI.......YS..
|
|
||||||
msg += b'\x00\x00\x02\x5a\x53\x00\x00\x00\x00\x02\x5b\x53\x00\x00\x00\x00' # | ...ZS.....[S....
|
|
||||||
msg += b'\x02\x5c\x53\x00\x00\x00\x00\x02\x5d\x53\x00\x00\x00\x00\x02\x5e' # | .\S.....]S.....^
|
|
||||||
msg += b'\x53\x00\x00\x00\x00\x02\x5f\x53\x00\x00\x00\x00\x02\x60\x53\x00' # | S....._S.....`S.
|
|
||||||
msg += b'\x00\x00\x00\x02\x61\x53\x00\x00\x00\x00\x02\x62\x53\x00\x00\x00' # | ....aS.....bS...
|
|
||||||
msg += b'\x00\x02\x63\x53\x00\x00\x00\x00\x02\x64\x53\x00\x00\x00\x00\x02' # | ..cS.....dS.....
|
|
||||||
msg += b'\x65\x53\x00\x00\x00\x00\x02\x66\x53\x00\x00\x00\x00\x02\x67\x53' # | eS.....fS.....gS
|
|
||||||
msg += b'\x00\x00\x00\x00\x02\x68\x53\x00\x00\x00\x00\x02\xbc\x49\x00\x00' # | .....hS......I..
|
|
||||||
msg += b'\x00\x00\x00\x00\x02\xbd\x53\x00\x00\x00\x00\x02\xbe\x53\x00\x00' # | ......S......S..
|
|
||||||
msg += b'\x00\x00\x02\xbf\x53\x00\x00\x00\x00\x02\xc0\x53\x00\x00\x00\x00' # | ....S......S....
|
|
||||||
msg += b'\x02\xc1\x53\x00\x00\x00\x00\x02\xc2\x53\x00\x00\x00\x00\x02\xc3' # | ..S......S......
|
|
||||||
msg += b'\x53\x00\x00\x00\x00\x02\xc4\x53\x00\x00\x00\x00\x02\xc5\x53\x00' # | S......S......S.
|
|
||||||
msg += b'\x00\x00\x00\x02\xc6\x53\x00\x00\x00\x00\x02\xc7\x53\x00\x00\x00' # | .....S......S...
|
|
||||||
msg += b'\x00\x02\xc8\x53\x00\x00\x00\x00\x02\xc9\x53\x00\x00\x00\x00\x02' # | ...S......S.....
|
|
||||||
msg += b'\xca\x53\x00\x00\x00\x00\x02\xcb\x53\x00\x00\x00\x00\x02\xcc\x53' # | .S......S......S
|
|
||||||
msg += b'\x00\x00\x00\x00\x03\x20\x53\x00\x01\x00\x00\x03\x84\x53\x11\x68' # | ..... S......S.h
|
|
||||||
msg += b'\x00\x00\x03\xe8\x46\x44\x23\xd1\xec\x00\x00\x04\x4c\x46\x43\xa3' # | ....FD#.....LFC.
|
|
||||||
msg += b'\xb3\x33\x00\x00\x04\xb0\x46\x00\x00\x00\x00\x00\x00\x05\x14\x46' # | .3....F........F
|
|
||||||
msg += b'\x43\x6e\x80\x00\x00\x00\x05\x78\x46\x3d\x4c\xcc\xcd\x00\x00\x05' # | Cn.....xF=L.....
|
|
||||||
msg += b'\xdc\x46\x00\x00\x00\x00\x00\x00\x06\x40\x46\x42\x48\x00\x00\x00' # | .F.......@FBH...
|
|
||||||
msg += b'\x00\x06\xa4\x53\x00\x03\x00\x00\x07\x08\x53\x00\x0c\x00\x00\x07' # | ...S......S.....
|
|
||||||
msg += b'\x6c\x53\x00\x50\x00\x00\x07\xd0\x46\x43\xa3\xb3\x33\x00\x00\x08' # | lS.P....FC..3...
|
|
||||||
msg += b'\x34\x53\x0b\xb8\x00\x00\x08\x98\x46\x00\x00\x00\x00\x00\x00\x08' # | 4S......F.......
|
|
||||||
msg += b'\xfc\x46\x00\x00\x00\x00\x00\x00\x09\x60\x46\x41\xee\xe1\x48\x00' # | .F.......`FA..H.
|
|
||||||
msg += b'\x00\x09\xc4\x53\x00\x00\x00\x00\x0a\x28\x46\x41\xf2\x00\x00\x00' # | ...S.....(FA....
|
|
||||||
msg += b'\x00\x0a\x8c\x46\x3f\xac\x28\xf6\x00\x00\x0a\xf0\x53\x00\x0c\x00' # | ...F?.(.....S...
|
|
||||||
msg += b'\x00\x0b\x54\x53\x00\x00\x00\x00\x0b\xb8\x53\x00\x00\x00\x00\x0c' # | ..TS......S.....
|
|
||||||
msg += b'\x1c\x53\x00\x00\x00\x00\x0c\x80\x53\x00\x00\x00\x00\x0c\xe4\x53' # | .S......S......S
|
|
||||||
msg += b'\x00\x00\x00\x00\x0d\x48\x53\x00\x00\x00\x00\x0d\xac\x53\x00\x00' # | .....HS......S..
|
|
||||||
msg += b'\x00\x00\x0e\x10\x53\x00\x00\x00\x00\x0e\x74\x53\x00\x00\x00\x00' # | ....S.....tS....
|
|
||||||
msg += b'\x0e\xd8\x53\x00\x00\x00\x00\x0f\x3c\x53\x00\x00\x00\x00\x0f\xa0' # | ..S.....<S......
|
|
||||||
msg += b'\x53\x00\x00\x00\x00\x10\x04\x53\x00\x00\x00\x00\x10\x68\x53\x00' # | S......S.....hS.
|
|
||||||
msg += b'\x00\x00\x00\x10\xcc\x53\x00\x00\x00\x00\x11\x30\x53\x00\x00\x00' # | .....S.....0S...
|
|
||||||
msg += b'\x00\x11\x94\x53\x00\x00\x00\x00\x11\xf8\x53\x00\x00\x00\x00\x12' # | ...S......S.....
|
|
||||||
msg += b'\x5c\x53\x00\x00\x00\x00\x12\xc0\x53\x00\x00\x00\x00\x13\x24\x46' # | \S......S.....$F
|
|
||||||
msg += b'\x42\x9d\x33\x33\x00\x00\x13\x88\x46\x00\x00\x00\x00\x00\x00\x13' # | B.33....F.......
|
|
||||||
msg += b'\xec\x46\x00\x00\x00\x00\x00\x00\x14\x50\x46\x42\xdc\x00\x00\x00' # | .F.......PFB....
|
|
||||||
msg += b'\x00\x14\xb4\x53\x00\x00\x00\x00\x15\x18\x53\x00\x00\x00\x00\x15' # | ...S......S.....
|
|
||||||
msg += b'\x7c\x53\x00\x00\x00\x00\x15\x7d\x53\x00\x00\x00\x00\x15\x7e\x53' # | |S.....}S.....~S
|
|
||||||
msg += b'\x00\x00\x00\x00\x15\x7f\x53\x00\x00\x00\x00\x15\x80\x53\x00\x00' # | ......S......S..
|
|
||||||
msg += b'\x00\x00\x15\x81\x53\x00\x00\x00\x00\x15\x82\x53\x00\x00\x00\x00' # | ....S......S....
|
|
||||||
msg += b'\x15\x83\x53\x00\x00\x00\x00\x15\x84\x53\x00\x00\x00\x00\x15\x85' # | ..S......S......
|
|
||||||
msg += b'\x53\x00\x00\x00\x00\x15\x86\x53\x00\x00\x00\x00\x15\x87\x53\x00' # | S......S......S.
|
|
||||||
msg += b'\x00\x00\x00\x15\x88\x53\x00\x00\x00\x00\x15\x89\x53\x00\x00\x00' # | .....S......S...
|
|
||||||
msg += b'\x00\x15\x8a\x53\x00\x00\x00\x00\x15\x8b\x53\x00\x00\x00\x00\x15' # | ...S......S.....
|
|
||||||
msg += b'\x8c\x53\x00\x00\x00\x00\x15\xe0\x46\x42\x68\x66\x66\x00\x00\x16' # | .S......FBhff...
|
|
||||||
msg += b'\x44\x46\x00\x00\x00\x00\x00\x00\x16\xa8\x46\x00\x00\x00\x00\x00' # | DF........F.....
|
|
||||||
msg += b'\x00\x17\x0c\x46\x42\xdc\x00\x00\x00\x00\x17\x70\x53\x00\x00\x00' # | ...FB......pS...
|
|
||||||
msg += b'\x00\x17\xd4\x53\x00\x00\x00\x00\x18\x38\x53\x00\x00\x00\x00\x18' # | ...S.....8S.....
|
|
||||||
msg += b'\x39\x53\x00\x00\x00\x00\x18\x3a\x53\x00\x00\x00\x00\x18\x3b\x53' # | 9S.....:S.....;S
|
|
||||||
msg += b'\x00\x00\x00\x00\x18\x3c\x53\x00\x00\x00\x00\x18\x3d\x53\x00\x00' # | .....<S.....=S..
|
|
||||||
msg += b'\x00\x00\x18\x3e\x53\x00\x00\x00\x00\x18\x3f\x53\x00\x00\x00\x00' # | ...>S.....?S....
|
|
||||||
msg += b'\x18\x40\x53\x00\x00\x00\x00\x18\x41\x53\x00\x00\x00\x00\x18\x42' # | .@S.....AS.....B
|
|
||||||
msg += b'\x53\x00\x00\x00\x00\x18\x43\x53\x00\x00\x00\x00\x18\x44\x53\x00' # | S.....CS.....DS.
|
|
||||||
msg += b'\x00\x00\x00\x18\x45\x53\x00\x00\x00\x00\x18\x46\x53\x00\x00\x00' # | ....ES.....FS...
|
|
||||||
msg += b'\x00\x18\x47\x53\x00\x00\x00\x00\x18\x48\x53\x00\x00\x00\x00\x18' # | ..GS.....HS.....
|
|
||||||
msg += b'\x9c\x46\x42\x6b\x33\x33\x00\x00\x19\x00\x46\x00\x00\x00\x00\x00' # | .FBk33....F.....
|
|
||||||
msg += b'\x00\x19\x64\x46\x00\x00\x00\x00\x00\x00\x19\xc8\x46\x42\xdc\x00' # | ..dF........FB..
|
|
||||||
msg += b'\x00\x00\x00\x1a\x2c\x53\x00\x00\x00\x00\x1a\x90\x53\x00\x00\x00' # | ....,S......S...
|
|
||||||
msg += b'\x00\x1a\xf4\x53\x00\x00\x00\x00\x1a\xf5\x53\x00\x00\x00\x00\x1a' # | ...S......S.....
|
|
||||||
msg += b'\xf6\x53\x00\x00\x00\x00\x1a\xf7\x53\x00\x00\x00\x00\x1a\xf8\x53' # | .S......S......S
|
|
||||||
msg += b'\x00\x00\x00\x00\x1a\xf9\x53\x00\x00\x00\x00\x1a\xfa\x53\x00\x00' # | ......S......S..
|
|
||||||
msg += b'\x00\x00\x1a\xfb\x53\x00\x00\x00\x00\x1a\xfc\x53\x00\x00\x00\x00' # | ....S......S....
|
|
||||||
msg += b'\x1a\xfd\x53\x00\x00\x00\x00\x1a\xfe\x53\x00\x00\x00\x00\x1a\xff' # | ..S......S......
|
|
||||||
msg += b'\x53\x00\x00\x00\x00\x1b\x00\x53\x00\x00\x00\x00\x1b\x01\x53\x00' # | S......S......S.
|
|
||||||
msg += b'\x00\x00\x00\x1b\x02\x53\x00\x00\x00\x00\x1b\x03\x53\x00\x00\x00' # | .....S......S...
|
|
||||||
msg += b'\x00\x1b\x04\x53\x00\x00\x00\x00\x1b\x58\x53\x00\x00\x00\x00\x1b' # | ...S.....XS.....
|
|
||||||
msg += b'\xbc\x53\x11\x3d\x00\x00\x1c\x20\x46\x3c\x23\xd7\x0a\x00\x00\x1c' # | .S.=... F<#.....
|
|
||||||
msg += b'\x84\x46\x00\x00\x00\x00\x00\x00\x1c\xe8\x46\x42\x04\x00\x00\x00' # | .F........FB....
|
|
||||||
msg += b'\x00\x1d\x4c\x46\x00\x00\x00\x00\x00\x00\x1d\xb0\x46\x00\x00\x00' # | ..LF........F...
|
|
||||||
msg += b'\x00\x00\x00\x1e\x14\x53\x00\x02\x00\x00\x1e\x78\x46\x41\x8b\x33' # | .....S.....xFA.3
|
|
||||||
msg += b'\x33\x00\x00\x1e\xdc\x46\x3c\xa3\xd7\x0a\x00\x00\x1f\x40\x46\x3e' # | 3....F<......@F>
|
|
||||||
msg += b'\x99\x99\x9a\x00\x00\x1f\xa4\x46\x40\x99\x99\x9a\x00\x00\x20\x08' # | .......F@..... .
|
|
||||||
msg += b'\x53\x00\x00\x00\x00\x20\x6c\x53\x00\x00\x00\x00\x20\xd0\x53\x05' # | S.... lS.... .S.
|
|
||||||
msg += b'\x00\x00\x00\x20\xd1\x53\x00\x00\x00\x00\x20\xd2\x53\x00\x00\x00' # | ... .S.... .S...
|
|
||||||
msg += b'\x00\x20\xd3\x53\x00\x00\x00\x00\x20\xd4\x53\x00\x00\x00\x00\x20' # | . .S.... .S....
|
|
||||||
msg += b'\xd5\x53\x00\x00\x00\x00\x20\xd6\x53\x00\x00\x00\x00\x20\xd7\x53' # | .S.... .S.... .S
|
|
||||||
msg += b'\x00\x00\x00\x00\x20\xd8\x53\x00\x00\x00\x00\x20\xd9\x53\x00\x01' # | .... .S.... .S..
|
|
||||||
msg += b'\x00\x00\x20\xda\x53\x00\x00\x00\x00\x20\xdb\x53\x00\x01\x00\x00' # | .. .S.... .S....
|
|
||||||
msg += b'\x20\xdc\x53\x00\x00\x00\x00\x20\xdd\x53\x00\x00\x00\x00\x20\xde' # | .S.... .S.... .
|
|
||||||
msg += b'\x53\x00\x00\x00\x00\x20\xdf\x53\x00\x00\x00\x00\x20\xe0\x53\x00' # | S.... .S.... .S.
|
|
||||||
msg += b'\x00\x00\x00\x21\x34\x46\x00\x00\x00\x00\x00\x00\x21\x98\x46\x00' # | ...!4F......!.F.
|
|
||||||
msg += b'\x00\x00\x00\x00\x00\x21\xfc\x46\x00\x00\x00\x00\x00\x00\x22\x60' # | .....!.F......"`
|
|
||||||
msg += b'\x46\x00\x00\x00\x00\x00\x00\x22\xc4\x53\x00\x00\x00\x00\x23\x28' # | F......".S....#(
|
|
||||||
msg += b'\x53\x00\x00\x00\x00\x23\x8c\x53\x00\x00\x00\x00\x23\x8d\x53\x00' # | S....#.S....#.S.
|
|
||||||
msg += b'\x00\x00\x00\x23\x8e\x53\x00\x00\x00\x00\x23\x8f\x53\x00\x00\x00' # | ...#.S....#.S...
|
|
||||||
msg += b'\x00\x23\x90\x53\x00\x00\x00\x00\x23\x91\x53\x00\x00\x00\x00\x23' # | .#.S....#.S....#
|
|
||||||
msg += b'\x92\x53\x00\x00\x00\x00\x23\x93\x53\x00\x00\x00\x00\x23\x94\x53' # | .S....#.S....#.S
|
|
||||||
msg += b'\x00\x00\x00\x00\x23\x95\x53\x00\x00\x00\x00\x23\x96\x53\x00\x00' # | ....#.S....#.S..
|
|
||||||
msg += b'\x00\x00\x23\x97\x53\x00\x00\x00\x00\x23\x98\x53\x00\x00\x00\x00' # | ..#.S....#.S....
|
|
||||||
msg += b'\x23\x99\x53\x00\x00\x00\x00\x23\x9a\x53\x00\x00\x00\x00\x23\x9b' # | #.S....#.S....#.
|
|
||||||
msg += b'\x53\x00\x00\x00\x00\x23\x9c\x53\x00\x00\x00\x00\x23\xf0\x46\x00' # | S....#.S....#.F.
|
|
||||||
msg += b'\x00\x00\x00\x00\x00\x24\x54\x46\x00\x00\x00\x00\x00\x00\x24\xb8' # | .....$TF......$.
|
|
||||||
msg += b'\x46\x00\x00\x00\x00\x00\x00\x25\x1c\x46\x00\x00\x00\x00\x00\x00' # | F......%.F......
|
|
||||||
msg += b'\x25\x80\x53\x00\x00\x00\x00\x25\xe4\x53\x00\x00\x00\x00\x26\x48' # | %.S....%.S....&H
|
|
||||||
msg += b'\x53\x00\x00\x00\x00\x26\x49\x53\x00\x00\x00\x00\x26\x4a\x53\x00' # | S....&IS....&JS.
|
|
||||||
msg += b'\x00\x00\x00\x26\x4b\x53\x00\x00\x00\x00\x26\x4c\x53\x00\x00\x00' # | ...&KS....&LS...
|
|
||||||
msg += b'\x00\x26\x4d\x53\x00\x00\x00\x00\x26\x4e\x53\x00\x00\x00\x00\x26' # | .&MS....&NS....&
|
|
||||||
msg += b'\x4f\x53\x00\x00\x00\x00\x26\x50\x53\x00\x00\x00\x00\x26\x51\x53' # | OS....&PS....&QS
|
|
||||||
msg += b'\x00\x00\x00\x00\x26\x52\x53\x00\x00\x00\x00\x26\x53\x53\x00\x00' # | ....&RS....&SS..
|
|
||||||
msg += b'\x00\x00\x26\x54\x53\x00\x00\x00\x00\x26\x55\x53\x00\x00\x00\x00' # | ..&TS....&US....
|
|
||||||
msg += b'\x26\x56\x53\x00\x00\x00\x00\x26\x57\x53\x00\x00\x00\x00\x26\x58' # | &VS....&WS....&X
|
|
||||||
msg += b'\x53\x00\x00\x00\x00\x26\xac\x53\x00\x00\x00\x00\x27\x10\x53\x11' # | S....&.S....'.S.
|
|
||||||
msg += b'\x3d\x00\x00\x27\x74\x46\x00\x00\x00\x00\x00\x00\x27\xd8\x46\x00' # | =..'tF......'.F.
|
|
||||||
msg += b'\x00\x00\x00\x00\x00\x28\x3c\x46\x42\x03\xf5\xc3\x00\x00\x28\xa0' # | .....(<FB.....(.
|
|
||||||
msg += b'\x46\x00\x00\x00\x00\x00\x00\x29\x04\x46\x00\x00\x00\x00\x00\x00' # | F......).F......
|
|
||||||
msg += b'\x29\x68\x53\x00\x02\x00\x00\x29\xcc\x53\x00\x03\x00\x00\x2a\x30' # | )hS....).S....*0
|
|
||||||
msg += b'\x46\x42\x20\x00\x00\x00\x00\x2a\x94\x46\x42\x20\x00\x00\x00\x00' # | FB ....*.FB ....
|
|
||||||
msg += b'\x2a\xf8\x46\x44\x20\x00\x00\x00\x00\x2b\x5c\x46\x43\x7b\x00\x00' # | *.FD ....+\FC{..
|
|
||||||
msg += b'\x00\x00\x2b\xc0\x46\x43\x50\x00\x00\x00\x00\x2c\x24\x46\x42\x48' # | ..+.FCP....,$FBH
|
|
||||||
msg += b'\x5c\x29\x00\x00\x2c\x88\x46\x42\x47\xa3\xd7\x00\x00\x2c\xec\x53' # | \)..,.FBG....,.S
|
|
||||||
msg += b'\x00\x00\x00\x00\x2d\x50\x46\x43\x42\x00\x00\x00\x00\x2d\xb4\x46' # | ....-PFCB....-.F
|
|
||||||
msg += b'\x42\xbc\x00\x00\x00\x00\x2e\x18\x46\x3f\xe6\x66\x66\x00\x00\x2e' # | B.......F?.ff...
|
|
||||||
msg += b'\x7c\x46\x3f\xe6\x66\x66\x00\x00\x2e\xe0\x46\x43\x7e\x00\x00\x00' # | |F?.ff....FC~...
|
|
||||||
msg += b'\x00\x2f\x44\x46\x43\x83\xf3\x33\x00\x00\x2f\xa8\x46\x3f\xe6\x66' # | ./DFC..3../.F?.f
|
|
||||||
msg += b'\x66\x00\x00\x30\x0c\x46\x3f\xe6\x66\x66\x00\x00\x30\x70\x46\x43' # | f..0.F?.ff..0pFC
|
|
||||||
msg += b'\x7e\x00\x00\x00\x00\x30\xd4\x46\x42\x3f\xeb\x85\x00\x00\x31\x38' # | ~....0.FB?....18
|
|
||||||
msg += b'\x46\x42\x3d\xeb\x85\x00\x00\x31\x9c\x46\x3e\x4c\xcc\xcd\x00\x00' # | FB=....1.F>L....
|
|
||||||
msg += b'\x32\x00\x46\x3e\x4c\xcc\xcd\x00\x00\x32\x64\x46\x42\x4c\x14\x7b' # | 2.F>L....2dFBL.{
|
|
||||||
msg += b'\x00\x00\x32\xc8\x46\x42\x4d\xeb\x85\x00\x00\x33\x2c\x46\x3e\x4c' # | ..2.FBM....3,F>L
|
|
||||||
msg += b'\xcc\xcd\x00\x00\x33\x90\x46\x3e\x4c\xcc\xcd\x00\x00\x33\xf4\x53' # | ....3.F>L....3.S
|
|
||||||
msg += b'\x00\x00\x00\x00\x34\x58\x53\x00\x00\x00\x00\x34\xbc\x53\x04\x00' # | ....4XS....4.S..
|
|
||||||
msg += b'\x00\x00\x35\x20\x53\x00\x01\x00\x00\x35\x84\x53\x13\x9c\x00\x00' # | ..5 S....5.S....
|
|
||||||
msg += b'\x35\xe8\x53\x0f\xa0\x00\x00\x36\x4c\x53\x00\x00\x00\x00\x36\xb0' # | 5.S....6LS....6.
|
|
||||||
msg += b'\x53\x00\x66' # | S.f'
|
|
||||||
return msg
|
|
||||||
|
|
||||||
|
|
||||||
@pytest.fixture
|
@pytest.fixture
|
||||||
def msg_ota_update_req(): # Over the air update request from talent cloud
|
def msg_ota_update_req(): # Over the air update request from talent cloud
|
||||||
msg = b'\x00\x00\x01\x16\x10'+ get_sn() + b'\x70\x13\x01\x02\x76\x35'
|
msg = b'\x00\x00\x01\x16\x10'+ get_sn() + b'\x70\x13\x01\x02\x76\x35'
|
||||||
@@ -383,18 +234,3 @@ def test_ota_req(client_connection, msg_ota_update_req):
|
|||||||
_ = s.recv(1024)
|
_ = s.recv(1024)
|
||||||
except TimeoutError:
|
except TimeoutError:
|
||||||
pass
|
pass
|
||||||
|
|
||||||
def test_send_inv_data2(client_connection, msg_timestamp_req, msg_timestamp_resp, msg_inverter_ind2):
|
|
||||||
s = client_connection
|
|
||||||
try:
|
|
||||||
s.sendall(msg_timestamp_req)
|
|
||||||
_ = s.recv(1024)
|
|
||||||
except TimeoutError:
|
|
||||||
pass
|
|
||||||
# time.sleep(32.5)
|
|
||||||
# assert data == msg_timestamp_resp
|
|
||||||
try:
|
|
||||||
s.sendall(msg_inverter_ind2)
|
|
||||||
_ = s.recv(1024)
|
|
||||||
except TimeoutError:
|
|
||||||
pass
|
|
||||||
|
|||||||
@@ -10,12 +10,6 @@ SOLARMAN_SNR = os.getenv('SOLARMAN_SNR', '00000080')
|
|||||||
def get_sn() -> bytes:
|
def get_sn() -> bytes:
|
||||||
return bytes.fromhex(SOLARMAN_SNR)
|
return bytes.fromhex(SOLARMAN_SNR)
|
||||||
|
|
||||||
def get_dcu_sn() -> bytes:
|
|
||||||
return b'\x20\x43\x65\x7b'
|
|
||||||
|
|
||||||
def get_dcu_no() -> bytes:
|
|
||||||
return b'4100000000000001'
|
|
||||||
|
|
||||||
def get_inv_no() -> bytes:
|
def get_inv_no() -> bytes:
|
||||||
return b'T170000000000001'
|
return b'T170000000000001'
|
||||||
|
|
||||||
@@ -111,62 +105,6 @@ def MsgInvalidInfo(): # Contact Info message wrong start byte
|
|||||||
msg += b'\x15'
|
msg += b'\x15'
|
||||||
return msg
|
return msg
|
||||||
|
|
||||||
@pytest.fixture
|
|
||||||
def dcu_dev_ind_msg(): # 0x4110
|
|
||||||
msg = b'\xa5\x3a\x01\x10\x41\x00\x01' +get_dcu_sn() +b'\x02\xc6\xde\x2d\x32'
|
|
||||||
msg += b'\x27\x00\x00\x00\x00\x00\x00\x00\x05\x3c\x78\x01\x5c\x01\x4c\x53'
|
|
||||||
msg += b'\x57\x35\x5f\x30\x31\x5f\x33\x30\x32\x36\x5f\x4e\x53\x5f\x30\x35'
|
|
||||||
msg += b'\x5f\x30\x31\x2e\x30\x30\x2e\x30\x30\x2e\x30\x30\x00\x00\x00\x00'
|
|
||||||
msg += b'\x00\x00\x00\x00\x00\x00\xd4\x27\x87\x12\xad\xc0\x31\x39\x32\x2e'
|
|
||||||
msg += b'\x31\x36\x38\x2e\x39\x2e\x31\x34\x00\x00\x00\x00\x01\x00\x01\x26'
|
|
||||||
msg += b'\x30\x0f\x00\xff\x56\x31\x2e\x31\x2e\x30\x30\x2e\x30\x42\x00\x00'
|
|
||||||
msg += b'\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00'
|
|
||||||
msg += b'\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\xfe\xfe\x00\x00'
|
|
||||||
msg += b'\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00'
|
|
||||||
msg += b'\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00'
|
|
||||||
msg += b'\x00\x00\x00\x00\x00\x00\x00\x7a\x75\x68\x61\x75\x73\x65\x00\x00'
|
|
||||||
msg += b'\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00'
|
|
||||||
msg += b'\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00'
|
|
||||||
msg += b'\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00'
|
|
||||||
msg += b'\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00'
|
|
||||||
msg += b'\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00'
|
|
||||||
msg += b'\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00'
|
|
||||||
msg += b'\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00'
|
|
||||||
msg += b'\x00\x00\x00\x00\x00\x00\x00\x00\x08\x01\x01\x01\x00\x00\x00\x00'
|
|
||||||
msg += b'\x00\x00\x00\x00\x01'
|
|
||||||
msg += correct_checksum(msg)
|
|
||||||
msg += b'\x15'
|
|
||||||
return msg
|
|
||||||
|
|
||||||
@pytest.fixture
|
|
||||||
def dcu_dev_rsp_msg(): # 0x1110
|
|
||||||
msg = b'\xa5\x0a\x00\x10\x11\x92\x01' +get_dcu_sn() +b'\x02\x01\x4a\xf6\xa6'
|
|
||||||
msg += b'\x67\x3c\x00\x00\x00'
|
|
||||||
msg += correct_checksum(msg)
|
|
||||||
msg += b'\x15'
|
|
||||||
return msg
|
|
||||||
|
|
||||||
@pytest.fixture
|
|
||||||
def dcu_data_ind_msg(): # 0x4210
|
|
||||||
msg = b'\xa5\x6f\x00\x10\x42\x92\x02' +get_dcu_sn() +b'\x01\x26\x30\xc7\xde'
|
|
||||||
msg += b'\x2d\x32\x28\x00\x00\x00\x84\x17\x79\x35\x01\x00\x4c\x12\x00\x00'
|
|
||||||
msg += get_dcu_no()
|
|
||||||
msg += b'\x0d\x3a\x00\x0a\x0d\x2c\x00\x00\x00\x00\x08\x20\x00\x00\x00\x00'
|
|
||||||
msg += b'\x14\x0e\xff\xfe\x03\xe8\x0c\x89\x0c\x89\x0c\x89\x0c\x8a\x0c\x89'
|
|
||||||
msg += b'\x0c\x89\x0c\x8a\x0c\x89\x0c\x89\x0c\x8a\x0c\x8a\x0c\x89\x0c\x89'
|
|
||||||
msg += b'\x0c\x89\x0c\x89\x0c\x88\x00\x0f\x00\x0f\x00\x0f\x00\x0e\x00\x00'
|
|
||||||
msg += b'\x00\x00\x00\x0f\x00\x00\x02\x05\x02\x01'
|
|
||||||
msg += correct_checksum(msg)
|
|
||||||
msg += b'\x15'
|
|
||||||
return msg
|
|
||||||
|
|
||||||
@pytest.fixture
|
|
||||||
def dcu_data_rsp_msg(): # 0x1210
|
|
||||||
msg = b'\xa5\x0a\x00\x10\x12\x93\x02' +get_dcu_sn() +b'\x01\x01\xd1\x96\x04'
|
|
||||||
msg += b'\x66\x3c\x00\x00\x00'
|
|
||||||
msg += correct_checksum(msg)
|
|
||||||
msg += b'\x15'
|
|
||||||
return msg
|
|
||||||
|
|
||||||
@pytest.fixture(scope="session")
|
@pytest.fixture(scope="session")
|
||||||
def ClientConnection():
|
def ClientConnection():
|
||||||
@@ -243,24 +181,4 @@ def test_inavlid_msg(ClientConnection,MsgInvalidInfo,MsgContactInfo, MsgContactR
|
|||||||
# time.sleep(2.5)
|
# time.sleep(2.5)
|
||||||
checkResponse(data, MsgContactResp)
|
checkResponse(data, MsgContactResp)
|
||||||
|
|
||||||
def test_dcu_dev(ClientConnection,dcu_dev_ind_msg, dcu_dev_rsp_msg):
|
|
||||||
s = ClientConnection
|
|
||||||
try:
|
|
||||||
s.sendall(dcu_dev_ind_msg)
|
|
||||||
# time.sleep(2.5)
|
|
||||||
data = s.recv(1024)
|
|
||||||
except TimeoutError:
|
|
||||||
pass
|
|
||||||
# time.sleep(2.5)
|
|
||||||
checkResponse(data, dcu_dev_rsp_msg)
|
|
||||||
|
|
||||||
def test_dcu_ind(ClientConnection,dcu_data_ind_msg, dcu_data_rsp_msg):
|
|
||||||
s = ClientConnection
|
|
||||||
try:
|
|
||||||
s.sendall(dcu_data_ind_msg)
|
|
||||||
# time.sleep(2.5)
|
|
||||||
data = s.recv(1024)
|
|
||||||
except TimeoutError:
|
|
||||||
pass
|
|
||||||
# time.sleep(2.5)
|
|
||||||
checkResponse(data, dcu_data_rsp_msg)
|
|
||||||
@@ -4,11 +4,11 @@
|
|||||||
"path": "."
|
"path": "."
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"path": "../tsun-gen3-proxy.wiki"
|
"path": "../wiki"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"name": "ha-addons",
|
"name": "ha-addons",
|
||||||
"path": "../ha-addons"
|
"path": "../ha-addons/ha-addons"
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"settings": {}
|
"settings": {}
|
||||||
|
|||||||
Reference in New Issue
Block a user