boneio 1.2.0.dev27__tar.gz → 1.3.0.dev1__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- {boneio-1.2.0.dev27/boneio.egg-info → boneio-1.3.0.dev1}/PKG-INFO +2 -1
- {boneio-1.2.0.dev27 → boneio-1.3.0.dev1}/boneio/const.py +1 -0
- {boneio-1.2.0.dev27 → boneio-1.3.0.dev1}/boneio/core/config/config_helper.py +11 -0
- boneio-1.3.0.dev1/boneio/core/manager/canopen.py +552 -0
- {boneio-1.2.0.dev27 → boneio-1.3.0.dev1}/boneio/core/manager/manager.py +30 -0
- {boneio-1.2.0.dev27 → boneio-1.3.0.dev1}/boneio/core/manager/modbus.py +1 -0
- {boneio-1.2.0.dev27 → boneio-1.3.0.dev1}/boneio/core/manager/remote.py +15 -0
- {boneio-1.2.0.dev27 → boneio-1.3.0.dev1}/boneio/core/remote/__init__.py +2 -0
- boneio-1.3.0.dev1/boneio/core/remote/can.py +163 -0
- {boneio-1.2.0.dev27 → boneio-1.3.0.dev1}/boneio/core/utils/filter.py +1 -0
- boneio-1.3.0.dev1/boneio/example_config/can_master.yaml +74 -0
- boneio-1.3.0.dev1/boneio/example_config/can_slave.yaml +47 -0
- boneio-1.3.0.dev1/boneio/hardware/can/__init__.py +9 -0
- boneio-1.3.0.dev1/boneio/hardware/can/bridge.py +159 -0
- boneio-1.3.0.dev1/boneio/hardware/can/client.py +339 -0
- boneio-1.3.0.dev1/boneio/hardware/can/interface.py +204 -0
- boneio-1.3.0.dev1/boneio/hardware/can/node.py +225 -0
- boneio-1.3.0.dev1/boneio/hardware/can/node_id.py +136 -0
- {boneio-1.2.0.dev27 → boneio-1.3.0.dev1}/boneio/integration/homeassistant.py +29 -4
- {boneio-1.2.0.dev27 → boneio-1.3.0.dev1}/boneio/modbus/coordinator.py +112 -5
- {boneio-1.2.0.dev27 → boneio-1.3.0.dev1}/boneio/modbus/devices/energy_meters/socomec_e03.json +6 -6
- {boneio-1.2.0.dev27 → boneio-1.3.0.dev1}/boneio/modbus/devices/energy_meters/socomec_e23.json +11 -11
- {boneio-1.2.0.dev27 → boneio-1.3.0.dev1}/boneio/modbus/devices/inverters/sofar.json +14 -14
- {boneio-1.2.0.dev27 → boneio-1.3.0.dev1}/boneio/modbus/devices/inverters/thessla.json +13 -1
- {boneio-1.2.0.dev27 → boneio-1.3.0.dev1}/boneio/modbus/devices/other/n4dsc08.json +24 -0
- {boneio-1.2.0.dev27 → boneio-1.3.0.dev1}/boneio/modbus/devices/other/r4dcb08.json +8 -8
- {boneio-1.2.0.dev27 → boneio-1.3.0.dev1}/boneio/modbus/devices/other/wanas415.json +27 -0
- boneio-1.3.0.dev1/boneio/modbus/devices/sensors/boneio-edge-temp.json +108 -0
- {boneio-1.2.0.dev27 → boneio-1.3.0.dev1}/boneio/modbus/devices/sensors/cwt.json +2 -2
- {boneio-1.2.0.dev27 → boneio-1.3.0.dev1}/boneio/modbus/devices/sensors/dyp-a12-ultrasonic.json +1 -1
- {boneio-1.2.0.dev27 → boneio-1.3.0.dev1}/boneio/modbus/devices/sensors/liquid-sensor.json +1 -1
- {boneio-1.2.0.dev27 → boneio-1.3.0.dev1}/boneio/modbus/devices/sensors/pt100.json +1 -1
- {boneio-1.2.0.dev27 → boneio-1.3.0.dev1}/boneio/modbus/devices/sensors/sht20.json +2 -2
- {boneio-1.2.0.dev27 → boneio-1.3.0.dev1}/boneio/modbus/devices/sensors/sht30.json +2 -2
- {boneio-1.2.0.dev27 → boneio-1.3.0.dev1}/boneio/modbus/entities/base.py +36 -2
- {boneio-1.2.0.dev27 → boneio-1.3.0.dev1}/boneio/modbus/entities/derived/select.py +1 -2
- {boneio-1.2.0.dev27 → boneio-1.3.0.dev1}/boneio/modbus/entities/derived/switch.py +1 -1
- {boneio-1.2.0.dev27 → boneio-1.3.0.dev1}/boneio/modbus/entities/derived/text.py +1 -1
- {boneio-1.2.0.dev27 → boneio-1.3.0.dev1}/boneio/modbus/entities/sensor/binary.py +1 -1
- {boneio-1.2.0.dev27 → boneio-1.3.0.dev1}/boneio/modbus/entities/sensor/text.py +1 -1
- {boneio-1.2.0.dev27 → boneio-1.3.0.dev1}/boneio/modbus/entities/writeable/binary.py +1 -1
- {boneio-1.2.0.dev27 → boneio-1.3.0.dev1}/boneio/modbus/entities/writeable/numeric.py +2 -2
- {boneio-1.2.0.dev27 → boneio-1.3.0.dev1}/boneio/models/state.py +1 -0
- {boneio-1.2.0.dev27 → boneio-1.3.0.dev1}/boneio/runner.py +16 -1
- {boneio-1.2.0.dev27 → boneio-1.3.0.dev1}/boneio/schema/schema.yaml +96 -0
- boneio-1.3.0.dev1/boneio/version.py +2 -0
- {boneio-1.2.0.dev27 → boneio-1.3.0.dev1}/boneio/webui/app.py +2 -0
- boneio-1.2.0.dev27/boneio/webui/frontend-dist/assets/cssMode-BzCozbpl.js → boneio-1.3.0.dev1/boneio/webui/frontend-dist/assets/cssMode-DYzYCxj1.js +1 -1
- boneio-1.2.0.dev27/boneio/webui/frontend-dist/assets/freemarker2-CtmThL1b.js → boneio-1.3.0.dev1/boneio/webui/frontend-dist/assets/freemarker2-Bemoup4X.js +1 -1
- boneio-1.2.0.dev27/boneio/webui/frontend-dist/assets/handlebars-fiiZvevB.js → boneio-1.3.0.dev1/boneio/webui/frontend-dist/assets/handlebars-3t5vS37H.js +1 -1
- boneio-1.2.0.dev27/boneio/webui/frontend-dist/assets/html-BimETABr.js → boneio-1.3.0.dev1/boneio/webui/frontend-dist/assets/html-Cq68Vj92.js +1 -1
- boneio-1.2.0.dev27/boneio/webui/frontend-dist/assets/htmlMode-DHLVYo-c.js → boneio-1.3.0.dev1/boneio/webui/frontend-dist/assets/htmlMode-zRg51dux.js +1 -1
- boneio-1.2.0.dev27/boneio/webui/frontend-dist/assets/index-DE7XXR7y.js → boneio-1.3.0.dev1/boneio/webui/frontend-dist/assets/index-CedvLek6.js +202 -200
- boneio-1.2.0.dev27/boneio/webui/frontend-dist/assets/index-B2dz9R2t.css → boneio-1.3.0.dev1/boneio/webui/frontend-dist/assets/index-yfVmKD9N.css +1 -1
- boneio-1.2.0.dev27/boneio/webui/frontend-dist/assets/javascript-YzZE0D4_.js → boneio-1.3.0.dev1/boneio/webui/frontend-dist/assets/javascript-BeqHop1l.js +1 -1
- boneio-1.2.0.dev27/boneio/webui/frontend-dist/assets/jsonMode-BQm48WQe.js → boneio-1.3.0.dev1/boneio/webui/frontend-dist/assets/jsonMode-B_TKboJF.js +1 -1
- boneio-1.2.0.dev27/boneio/webui/frontend-dist/assets/liquid-DVUhP52g.js → boneio-1.3.0.dev1/boneio/webui/frontend-dist/assets/liquid-BK7PsOyv.js +1 -1
- boneio-1.2.0.dev27/boneio/webui/frontend-dist/assets/mdx-DOQ104-j.js → boneio-1.3.0.dev1/boneio/webui/frontend-dist/assets/mdx-Ckb8-VUx.js +1 -1
- boneio-1.2.0.dev27/boneio/webui/frontend-dist/assets/python-4pYZo98W.js → boneio-1.3.0.dev1/boneio/webui/frontend-dist/assets/python-CO1-gBqF.js +1 -1
- boneio-1.2.0.dev27/boneio/webui/frontend-dist/assets/razor-Dq6QqksM.js → boneio-1.3.0.dev1/boneio/webui/frontend-dist/assets/razor-Dx6x9ypa.js +1 -1
- boneio-1.2.0.dev27/boneio/webui/frontend-dist/assets/tsMode-tYO0JGIQ.js → boneio-1.3.0.dev1/boneio/webui/frontend-dist/assets/tsMode-Deid1skj.js +1 -1
- boneio-1.2.0.dev27/boneio/webui/frontend-dist/assets/typescript-DSsPzLFv.js → boneio-1.3.0.dev1/boneio/webui/frontend-dist/assets/typescript-JSH4I7cf.js +1 -1
- boneio-1.2.0.dev27/boneio/webui/frontend-dist/assets/xml-CrUPqEEX.js → boneio-1.3.0.dev1/boneio/webui/frontend-dist/assets/xml-BX_Opm8D.js +1 -1
- boneio-1.2.0.dev27/boneio/webui/frontend-dist/assets/yaml-9n910SQK.js → boneio-1.3.0.dev1/boneio/webui/frontend-dist/assets/yaml-BRsnPpO3.js +1 -1
- {boneio-1.2.0.dev27 → boneio-1.3.0.dev1}/boneio/webui/frontend-dist/index.html +2 -2
- {boneio-1.2.0.dev27 → boneio-1.3.0.dev1}/boneio/webui/frontend-dist/schema/boneio.schema.json +22 -0
- boneio-1.3.0.dev1/boneio/webui/frontend-dist/schema/can.schema.json +132 -0
- {boneio-1.2.0.dev27/boneio/webui → boneio-1.3.0.dev1/boneio/webui/frontend-dist}/schema/config.schema.json +156 -0
- {boneio-1.2.0.dev27 → boneio-1.3.0.dev1}/boneio/webui/frontend-dist/schema/modbus_devices.schema.json +8 -0
- {boneio-1.2.0.dev27 → boneio-1.3.0.dev1}/boneio/webui/frontend-dist/sw.js +1 -1
- {boneio-1.2.0.dev27 → boneio-1.3.0.dev1}/boneio/webui/routes/__init__.py +2 -0
- boneio-1.3.0.dev1/boneio/webui/routes/can.py +377 -0
- {boneio-1.2.0.dev27 → boneio-1.3.0.dev1}/boneio/webui/routes/config.py +45 -0
- {boneio-1.2.0.dev27 → boneio-1.3.0.dev1}/boneio/webui/routes/modbus.py +169 -1
- {boneio-1.2.0.dev27 → boneio-1.3.0.dev1}/boneio/webui/schema/boneio.schema.json +22 -0
- boneio-1.3.0.dev1/boneio/webui/schema/can.schema.json +132 -0
- {boneio-1.2.0.dev27/boneio/webui/frontend-dist → boneio-1.3.0.dev1/boneio/webui}/schema/config.schema.json +156 -0
- {boneio-1.2.0.dev27 → boneio-1.3.0.dev1}/boneio/webui/schema/modbus_devices.schema.json +8 -0
- {boneio-1.2.0.dev27 → boneio-1.3.0.dev1/boneio.egg-info}/PKG-INFO +2 -1
- {boneio-1.2.0.dev27 → boneio-1.3.0.dev1}/boneio.egg-info/SOURCES.txt +30 -17
- {boneio-1.2.0.dev27 → boneio-1.3.0.dev1}/boneio.egg-info/requires.txt +1 -0
- {boneio-1.2.0.dev27 → boneio-1.3.0.dev1}/pyproject.toml +2 -1
- boneio-1.2.0.dev27/boneio/modbus/devices/sensors/boneio-edge-temp.json +0 -50
- boneio-1.2.0.dev27/boneio/version.py +0 -2
- {boneio-1.2.0.dev27 → boneio-1.3.0.dev1}/LICENSE +0 -0
- {boneio-1.2.0.dev27 → boneio-1.3.0.dev1}/MANIFEST.in +0 -0
- {boneio-1.2.0.dev27 → boneio-1.3.0.dev1}/README.md +0 -0
- {boneio-1.2.0.dev27 → boneio-1.3.0.dev1}/boneio/__init__.py +0 -0
- {boneio-1.2.0.dev27 → boneio-1.3.0.dev1}/boneio/boards/0.2/input.yaml +0 -0
- {boneio-1.2.0.dev27 → boneio-1.3.0.dev1}/boneio/boards/0.2/output_24_16.yaml +0 -0
- {boneio-1.2.0.dev27 → boneio-1.3.0.dev1}/boneio/boards/0.2/output_32_10.yaml +0 -0
- {boneio-1.2.0.dev27 → boneio-1.3.0.dev1}/boneio/boards/0.2/output_32_5.yaml +0 -0
- {boneio-1.2.0.dev27 → boneio-1.3.0.dev1}/boneio/boards/0.2/output_cover.yaml +0 -0
- {boneio-1.2.0.dev27 → boneio-1.3.0.dev1}/boneio/boards/0.2/output_cover_mix.yaml +0 -0
- {boneio-1.2.0.dev27 → boneio-1.3.0.dev1}/boneio/boards/0.3/input.yaml +0 -0
- {boneio-1.2.0.dev27 → boneio-1.3.0.dev1}/boneio/boards/0.3/output_24_16.yaml +0 -0
- {boneio-1.2.0.dev27 → boneio-1.3.0.dev1}/boneio/boards/0.3/output_32_10.yaml +0 -0
- {boneio-1.2.0.dev27 → boneio-1.3.0.dev1}/boneio/boards/0.3/output_32_5.yaml +0 -0
- {boneio-1.2.0.dev27 → boneio-1.3.0.dev1}/boneio/boards/0.3/output_cover.yaml +0 -0
- {boneio-1.2.0.dev27 → boneio-1.3.0.dev1}/boneio/boards/0.3/output_cover_mix.yaml +0 -0
- {boneio-1.2.0.dev27 → boneio-1.3.0.dev1}/boneio/boards/0.4/input.yaml +0 -0
- {boneio-1.2.0.dev27 → boneio-1.3.0.dev1}/boneio/boards/0.4/output_24_16.yaml +0 -0
- {boneio-1.2.0.dev27 → boneio-1.3.0.dev1}/boneio/boards/0.4/output_32_10.yaml +0 -0
- {boneio-1.2.0.dev27 → boneio-1.3.0.dev1}/boneio/boards/0.4/output_32_5.yaml +0 -0
- {boneio-1.2.0.dev27 → boneio-1.3.0.dev1}/boneio/boards/0.4/output_cover.yaml +0 -0
- {boneio-1.2.0.dev27 → boneio-1.3.0.dev1}/boneio/boards/0.4/output_cover_mix.yaml +0 -0
- {boneio-1.2.0.dev27 → boneio-1.3.0.dev1}/boneio/boards/0.5/input.yaml +0 -0
- {boneio-1.2.0.dev27 → boneio-1.3.0.dev1}/boneio/boards/0.5/output_24_16.yaml +0 -0
- {boneio-1.2.0.dev27 → boneio-1.3.0.dev1}/boneio/boards/0.5/output_32_10.yaml +0 -0
- {boneio-1.2.0.dev27 → boneio-1.3.0.dev1}/boneio/boards/0.5/output_cover.yaml +0 -0
- {boneio-1.2.0.dev27 → boneio-1.3.0.dev1}/boneio/boards/0.5/output_cover_mix.yaml +0 -0
- {boneio-1.2.0.dev27 → boneio-1.3.0.dev1}/boneio/boards/0.6/input.yaml +0 -0
- {boneio-1.2.0.dev27 → boneio-1.3.0.dev1}/boneio/boards/0.6/output_24_16.yaml +0 -0
- {boneio-1.2.0.dev27 → boneio-1.3.0.dev1}/boneio/boards/0.6/output_32_10.yaml +0 -0
- {boneio-1.2.0.dev27 → boneio-1.3.0.dev1}/boneio/boards/0.6/output_cover.yaml +0 -0
- {boneio-1.2.0.dev27 → boneio-1.3.0.dev1}/boneio/boards/0.6/output_cover_mix.yaml +0 -0
- {boneio-1.2.0.dev27 → boneio-1.3.0.dev1}/boneio/boards/0.7/input.yaml +0 -0
- {boneio-1.2.0.dev27 → boneio-1.3.0.dev1}/boneio/boards/0.7/output_24_16.yaml +0 -0
- {boneio-1.2.0.dev27 → boneio-1.3.0.dev1}/boneio/boards/0.7/output_32_10.yaml +0 -0
- {boneio-1.2.0.dev27 → boneio-1.3.0.dev1}/boneio/boards/0.7/output_cover.yaml +0 -0
- {boneio-1.2.0.dev27 → boneio-1.3.0.dev1}/boneio/boards/0.7/output_cover_mix.yaml +0 -0
- {boneio-1.2.0.dev27 → boneio-1.3.0.dev1}/boneio/boards/0.8/input.yaml +0 -0
- {boneio-1.2.0.dev27 → boneio-1.3.0.dev1}/boneio/boards/0.8/output_24_16.yaml +0 -0
- {boneio-1.2.0.dev27 → boneio-1.3.0.dev1}/boneio/boards/0.8/output_32_10.yaml +0 -0
- {boneio-1.2.0.dev27 → boneio-1.3.0.dev1}/boneio/boards/0.8/output_cover.yaml +0 -0
- {boneio-1.2.0.dev27 → boneio-1.3.0.dev1}/boneio/boards/0.8/output_cover_mix.yaml +0 -0
- {boneio-1.2.0.dev27 → boneio-1.3.0.dev1}/boneio/bonecli.py +0 -0
- {boneio-1.2.0.dev27 → boneio-1.3.0.dev1}/boneio/components/__init__.py +0 -0
- {boneio-1.2.0.dev27 → boneio-1.3.0.dev1}/boneio/components/cover/__init__.py +0 -0
- {boneio-1.2.0.dev27 → boneio-1.3.0.dev1}/boneio/components/cover/cover.py +0 -0
- {boneio-1.2.0.dev27 → boneio-1.3.0.dev1}/boneio/components/cover/time_based.py +0 -0
- {boneio-1.2.0.dev27 → boneio-1.3.0.dev1}/boneio/components/cover/venetian.py +0 -0
- {boneio-1.2.0.dev27 → boneio-1.3.0.dev1}/boneio/components/group/__init__.py +0 -0
- {boneio-1.2.0.dev27 → boneio-1.3.0.dev1}/boneio/components/group/output_group.py +0 -0
- {boneio-1.2.0.dev27 → boneio-1.3.0.dev1}/boneio/components/input/__init__.py +0 -0
- {boneio-1.2.0.dev27 → boneio-1.3.0.dev1}/boneio/components/input/binary_sensor.py +0 -0
- {boneio-1.2.0.dev27 → boneio-1.3.0.dev1}/boneio/components/input/detectors.py +0 -0
- {boneio-1.2.0.dev27 → boneio-1.3.0.dev1}/boneio/components/input/event.py +0 -0
- {boneio-1.2.0.dev27 → boneio-1.3.0.dev1}/boneio/components/output/__init__.py +0 -0
- {boneio-1.2.0.dev27 → boneio-1.3.0.dev1}/boneio/components/output/basic.py +0 -0
- {boneio-1.2.0.dev27 → boneio-1.3.0.dev1}/boneio/components/output/mcp.py +0 -0
- {boneio-1.2.0.dev27 → boneio-1.3.0.dev1}/boneio/components/output/pca.py +0 -0
- {boneio-1.2.0.dev27 → boneio-1.3.0.dev1}/boneio/components/output/pcf.py +0 -0
- {boneio-1.2.0.dev27 → boneio-1.3.0.dev1}/boneio/components/sensor/__init__.py +0 -0
- {boneio-1.2.0.dev27 → boneio-1.3.0.dev1}/boneio/components/sensor/virtual_energy.py +0 -0
- {boneio-1.2.0.dev27 → boneio-1.3.0.dev1}/boneio/components/template/__init__.py +0 -0
- {boneio-1.2.0.dev27 → boneio-1.3.0.dev1}/boneio/components/template/alarm_panel.py +0 -0
- {boneio-1.2.0.dev27 → boneio-1.3.0.dev1}/boneio/components/template/gate_cover.py +0 -0
- {boneio-1.2.0.dev27 → boneio-1.3.0.dev1}/boneio/components/template/thermostat.py +0 -0
- {boneio-1.2.0.dev27 → boneio-1.3.0.dev1}/boneio/core/__init__.py +0 -0
- {boneio-1.2.0.dev27 → boneio-1.3.0.dev1}/boneio/core/cloud/__init__.py +0 -0
- {boneio-1.2.0.dev27 → boneio-1.3.0.dev1}/boneio/core/cloud/data/__init__.py +0 -0
- {boneio-1.2.0.dev27 → boneio-1.3.0.dev1}/boneio/core/cloud/data/docker-compose-cloud.yaml +0 -0
- {boneio-1.2.0.dev27 → boneio-1.3.0.dev1}/boneio/core/cloud/data/docker-compose.yaml +0 -0
- {boneio-1.2.0.dev27 → boneio-1.3.0.dev1}/boneio/core/cloud/data/init-certs-cloud.sh +0 -0
- {boneio-1.2.0.dev27 → boneio-1.3.0.dev1}/boneio/core/cloud/registration.py +0 -0
- {boneio-1.2.0.dev27 → boneio-1.3.0.dev1}/boneio/core/cloud/secrets.py +0 -0
- {boneio-1.2.0.dev27 → boneio-1.3.0.dev1}/boneio/core/config/__init__.py +0 -0
- {boneio-1.2.0.dev27 → boneio-1.3.0.dev1}/boneio/core/config/migrations/__init__.py +0 -0
- {boneio-1.2.0.dev27 → boneio-1.3.0.dev1}/boneio/core/config/migrations/v1_proxy_port.py +0 -0
- {boneio-1.2.0.dev27 → boneio-1.3.0.dev1}/boneio/core/config/migrations/v2_transition.py +0 -0
- {boneio-1.2.0.dev27 → boneio-1.3.0.dev1}/boneio/core/config/package-lock.json +0 -0
- {boneio-1.2.0.dev27 → boneio-1.3.0.dev1}/boneio/core/config/package.json +0 -0
- {boneio-1.2.0.dev27 → boneio-1.3.0.dev1}/boneio/core/config/schema_converter.py +0 -0
- {boneio-1.2.0.dev27 → boneio-1.3.0.dev1}/boneio/core/config/yaml_util.py +0 -0
- {boneio-1.2.0.dev27 → boneio-1.3.0.dev1}/boneio/core/discovery.py +0 -0
- {boneio-1.2.0.dev27 → boneio-1.3.0.dev1}/boneio/core/events/__init__.py +0 -0
- {boneio-1.2.0.dev27 → boneio-1.3.0.dev1}/boneio/core/events/bus.py +0 -0
- {boneio-1.2.0.dev27 → boneio-1.3.0.dev1}/boneio/core/manager/__init__.py +0 -0
- {boneio-1.2.0.dev27 → boneio-1.3.0.dev1}/boneio/core/manager/covers.py +0 -0
- {boneio-1.2.0.dev27 → boneio-1.3.0.dev1}/boneio/core/manager/display.py +0 -0
- {boneio-1.2.0.dev27 → boneio-1.3.0.dev1}/boneio/core/manager/inputs.py +0 -0
- {boneio-1.2.0.dev27 → boneio-1.3.0.dev1}/boneio/core/manager/outputs.py +0 -0
- {boneio-1.2.0.dev27 → boneio-1.3.0.dev1}/boneio/core/manager/sensors.py +0 -0
- {boneio-1.2.0.dev27 → boneio-1.3.0.dev1}/boneio/core/manager/templates/__init__.py +0 -0
- {boneio-1.2.0.dev27 → boneio-1.3.0.dev1}/boneio/core/manager/templates/alarm.py +0 -0
- {boneio-1.2.0.dev27 → boneio-1.3.0.dev1}/boneio/core/manager/templates/gate_cover.py +0 -0
- {boneio-1.2.0.dev27 → boneio-1.3.0.dev1}/boneio/core/manager/templates/thermostat.py +0 -0
- {boneio-1.2.0.dev27 → boneio-1.3.0.dev1}/boneio/core/manager/templates.py +0 -0
- {boneio-1.2.0.dev27 → boneio-1.3.0.dev1}/boneio/core/manager/update.py +0 -0
- {boneio-1.2.0.dev27 → boneio-1.3.0.dev1}/boneio/core/messaging/__init__.py +0 -0
- {boneio-1.2.0.dev27 → boneio-1.3.0.dev1}/boneio/core/messaging/basic.py +0 -0
- {boneio-1.2.0.dev27 → boneio-1.3.0.dev1}/boneio/core/messaging/basic_mqtt.py +0 -0
- {boneio-1.2.0.dev27 → boneio-1.3.0.dev1}/boneio/core/messaging/local.py +0 -0
- {boneio-1.2.0.dev27 → boneio-1.3.0.dev1}/boneio/core/messaging/mqtt.py +0 -0
- {boneio-1.2.0.dev27 → boneio-1.3.0.dev1}/boneio/core/messaging/queue.py +0 -0
- {boneio-1.2.0.dev27 → boneio-1.3.0.dev1}/boneio/core/remote/base.py +0 -0
- {boneio-1.2.0.dev27 → boneio-1.3.0.dev1}/boneio/core/remote/esphome.py +0 -0
- {boneio-1.2.0.dev27 → boneio-1.3.0.dev1}/boneio/core/remote/mqtt.py +0 -0
- {boneio-1.2.0.dev27 → boneio-1.3.0.dev1}/boneio/core/remote/wled.py +0 -0
- {boneio-1.2.0.dev27 → boneio-1.3.0.dev1}/boneio/core/sensor/__init__.py +0 -0
- {boneio-1.2.0.dev27 → boneio-1.3.0.dev1}/boneio/core/sensor/base.py +0 -0
- {boneio-1.2.0.dev27 → boneio-1.3.0.dev1}/boneio/core/sensor/system.py +0 -0
- {boneio-1.2.0.dev27 → boneio-1.3.0.dev1}/boneio/core/state/__init__.py +0 -0
- {boneio-1.2.0.dev27 → boneio-1.3.0.dev1}/boneio/core/state/manager.py +0 -0
- {boneio-1.2.0.dev27 → boneio-1.3.0.dev1}/boneio/core/system/__init__.py +0 -0
- {boneio-1.2.0.dev27 → boneio-1.3.0.dev1}/boneio/core/system/host_data.py +0 -0
- {boneio-1.2.0.dev27 → boneio-1.3.0.dev1}/boneio/core/system/monitor.py +0 -0
- {boneio-1.2.0.dev27 → boneio-1.3.0.dev1}/boneio/core/utils/__init__.py +0 -0
- {boneio-1.2.0.dev27 → boneio-1.3.0.dev1}/boneio/core/utils/async_updater.py +0 -0
- {boneio-1.2.0.dev27 → boneio-1.3.0.dev1}/boneio/core/utils/font_util.py +0 -0
- {boneio-1.2.0.dev27 → boneio-1.3.0.dev1}/boneio/core/utils/logger.py +0 -0
- {boneio-1.2.0.dev27 → boneio-1.3.0.dev1}/boneio/core/utils/timeperiod.py +0 -0
- {boneio-1.2.0.dev27 → boneio-1.3.0.dev1}/boneio/core/utils/util.py +0 -0
- {boneio-1.2.0.dev27 → boneio-1.3.0.dev1}/boneio/example_config/24x16/adc.yaml +0 -0
- {boneio-1.2.0.dev27 → boneio-1.3.0.dev1}/boneio/example_config/24x16/binary_sensor.yaml +0 -0
- {boneio-1.2.0.dev27 → boneio-1.3.0.dev1}/boneio/example_config/24x16/config.yaml +0 -0
- {boneio-1.2.0.dev27 → boneio-1.3.0.dev1}/boneio/example_config/24x16/event.yaml +0 -0
- {boneio-1.2.0.dev27 → boneio-1.3.0.dev1}/boneio/example_config/24x16/mqtt.yaml +0 -0
- {boneio-1.2.0.dev27 → boneio-1.3.0.dev1}/boneio/example_config/24x16/output24x16A.yaml +0 -0
- {boneio-1.2.0.dev27 → boneio-1.3.0.dev1}/boneio/example_config/32x10/adc.yaml +0 -0
- {boneio-1.2.0.dev27 → boneio-1.3.0.dev1}/boneio/example_config/32x10/binary_sensor.yaml +0 -0
- {boneio-1.2.0.dev27 → boneio-1.3.0.dev1}/boneio/example_config/32x10/config.yaml +0 -0
- {boneio-1.2.0.dev27 → boneio-1.3.0.dev1}/boneio/example_config/32x10/event.yaml +0 -0
- {boneio-1.2.0.dev27 → boneio-1.3.0.dev1}/boneio/example_config/32x10/mqtt.yaml +0 -0
- {boneio-1.2.0.dev27 → boneio-1.3.0.dev1}/boneio/example_config/32x10/output32x10A.yaml +0 -0
- {boneio-1.2.0.dev27 → boneio-1.3.0.dev1}/boneio/example_config/__init__.py +0 -0
- {boneio-1.2.0.dev27 → boneio-1.3.0.dev1}/boneio/example_config/cover/adc.yaml +0 -0
- {boneio-1.2.0.dev27 → boneio-1.3.0.dev1}/boneio/example_config/cover/binary_sensor.yaml +0 -0
- {boneio-1.2.0.dev27 → boneio-1.3.0.dev1}/boneio/example_config/cover/config.yaml +0 -0
- {boneio-1.2.0.dev27 → boneio-1.3.0.dev1}/boneio/example_config/cover/cover.yaml +0 -0
- {boneio-1.2.0.dev27 → boneio-1.3.0.dev1}/boneio/example_config/cover/event.yaml +0 -0
- {boneio-1.2.0.dev27 → boneio-1.3.0.dev1}/boneio/example_config/cover/mqtt.yaml +0 -0
- {boneio-1.2.0.dev27 → boneio-1.3.0.dev1}/boneio/example_config/cover/outputCover.yaml +0 -0
- {boneio-1.2.0.dev27 → boneio-1.3.0.dev1}/boneio/example_config/cover_mix/adc.yaml +0 -0
- {boneio-1.2.0.dev27 → boneio-1.3.0.dev1}/boneio/example_config/cover_mix/binary_sensor.yaml +0 -0
- {boneio-1.2.0.dev27 → boneio-1.3.0.dev1}/boneio/example_config/cover_mix/config.yaml +0 -0
- {boneio-1.2.0.dev27 → boneio-1.3.0.dev1}/boneio/example_config/cover_mix/cover.yaml +0 -0
- {boneio-1.2.0.dev27 → boneio-1.3.0.dev1}/boneio/example_config/cover_mix/event.yaml +0 -0
- {boneio-1.2.0.dev27 → boneio-1.3.0.dev1}/boneio/example_config/cover_mix/mqtt.yaml +0 -0
- {boneio-1.2.0.dev27 → boneio-1.3.0.dev1}/boneio/example_config/cover_mix/outputCoverMix.yaml +0 -0
- {boneio-1.2.0.dev27 → boneio-1.3.0.dev1}/boneio/example_config/different_configs/adc.yaml +0 -0
- {boneio-1.2.0.dev27 → boneio-1.3.0.dev1}/boneio/example_config/different_configs/all_binary_sensor.yaml +0 -0
- {boneio-1.2.0.dev27 → boneio-1.3.0.dev1}/boneio/example_config/different_configs/binary_sensor.yaml +0 -0
- {boneio-1.2.0.dev27 → boneio-1.3.0.dev1}/boneio/example_config/different_configs/binary_sensor_v_0_7.yaml +0 -0
- {boneio-1.2.0.dev27 → boneio-1.3.0.dev1}/boneio/example_config/different_configs/config_24_16.yaml +0 -0
- {boneio-1.2.0.dev27 → boneio-1.3.0.dev1}/boneio/example_config/different_configs/event_all.yaml +0 -0
- {boneio-1.2.0.dev27 → boneio-1.3.0.dev1}/boneio/example_config/different_configs/event_v_0_7.yaml +0 -0
- {boneio-1.2.0.dev27 → boneio-1.3.0.dev1}/boneio/example_config/different_configs/led32x4A.yaml +0 -0
- {boneio-1.2.0.dev27 → boneio-1.3.0.dev1}/boneio/example_config/different_configs/output24x16A.yaml +0 -0
- {boneio-1.2.0.dev27 → boneio-1.3.0.dev1}/boneio/example_config/different_configs/output24x16A_v0.3.yaml +0 -0
- {boneio-1.2.0.dev27 → boneio-1.3.0.dev1}/boneio/example_config/different_configs/output32x10A.yaml +0 -0
- {boneio-1.2.0.dev27 → boneio-1.3.0.dev1}/boneio/example_config/different_configs/output32x5A.yaml +0 -0
- {boneio-1.2.0.dev27 → boneio-1.3.0.dev1}/boneio/exceptions.py +0 -0
- {boneio-1.2.0.dev27 → boneio-1.3.0.dev1}/boneio/hardware/__init__.py +0 -0
- {boneio-1.2.0.dev27 → boneio-1.3.0.dev1}/boneio/hardware/analog/__init__.py +0 -0
- {boneio-1.2.0.dev27 → boneio-1.3.0.dev1}/boneio/hardware/analog/adc.py +0 -0
- {boneio-1.2.0.dev27 → boneio-1.3.0.dev1}/boneio/hardware/display/__init__.py +0 -0
- {boneio-1.2.0.dev27 → boneio-1.3.0.dev1}/boneio/hardware/display/fonts/danube__.ttf +0 -0
- {boneio-1.2.0.dev27 → boneio-1.3.0.dev1}/boneio/hardware/display/oled.py +0 -0
- {boneio-1.2.0.dev27 → boneio-1.3.0.dev1}/boneio/hardware/gpio/__init__.py +0 -0
- {boneio-1.2.0.dev27 → boneio-1.3.0.dev1}/boneio/hardware/gpio/expanders/__init__.py +0 -0
- {boneio-1.2.0.dev27 → boneio-1.3.0.dev1}/boneio/hardware/gpio/expanders/mcp23017.py +0 -0
- {boneio-1.2.0.dev27 → boneio-1.3.0.dev1}/boneio/hardware/gpio/expanders/pca9685.py +0 -0
- {boneio-1.2.0.dev27 → boneio-1.3.0.dev1}/boneio/hardware/gpio/expanders/pcf8575.py +0 -0
- {boneio-1.2.0.dev27 → boneio-1.3.0.dev1}/boneio/hardware/gpio/input/__init__.py +0 -0
- {boneio-1.2.0.dev27 → boneio-1.3.0.dev1}/boneio/hardware/gpio/input/base.py +0 -0
- {boneio-1.2.0.dev27 → boneio-1.3.0.dev1}/boneio/hardware/gpio/input/manager.py +0 -0
- {boneio-1.2.0.dev27 → boneio-1.3.0.dev1}/boneio/hardware/i2c/__init__.py +0 -0
- {boneio-1.2.0.dev27 → boneio-1.3.0.dev1}/boneio/hardware/i2c/bus.py +0 -0
- {boneio-1.2.0.dev27 → boneio-1.3.0.dev1}/boneio/hardware/i2c/ina219.py +0 -0
- {boneio-1.2.0.dev27 → boneio-1.3.0.dev1}/boneio/hardware/i2c/ina219_driver.py +0 -0
- {boneio-1.2.0.dev27 → boneio-1.3.0.dev1}/boneio/hardware/i2c/mcp9808.py +0 -0
- {boneio-1.2.0.dev27 → boneio-1.3.0.dev1}/boneio/hardware/i2c/pct2075.py +0 -0
- {boneio-1.2.0.dev27 → boneio-1.3.0.dev1}/boneio/hardware/onewire/__init__.py +0 -0
- {boneio-1.2.0.dev27 → boneio-1.3.0.dev1}/boneio/hardware/onewire/bus.py +0 -0
- {boneio-1.2.0.dev27 → boneio-1.3.0.dev1}/boneio/hardware/onewire/dallas.py +0 -0
- {boneio-1.2.0.dev27 → boneio-1.3.0.dev1}/boneio/hardware/onewire/ds2482.py +0 -0
- {boneio-1.2.0.dev27 → boneio-1.3.0.dev1}/boneio/hardware/sensor/__init__.py +0 -0
- {boneio-1.2.0.dev27 → boneio-1.3.0.dev1}/boneio/hardware/sensor/temperature/__init__.py +0 -0
- {boneio-1.2.0.dev27 → boneio-1.3.0.dev1}/boneio/hardware/sensor/temperature/base.py +0 -0
- {boneio-1.2.0.dev27 → boneio-1.3.0.dev1}/boneio/hardware/sensor/temperature/mcp9808.py +0 -0
- {boneio-1.2.0.dev27 → boneio-1.3.0.dev1}/boneio/hardware/sensor/temperature/pct2075.py +0 -0
- {boneio-1.2.0.dev27 → boneio-1.3.0.dev1}/boneio/integration/__init__.py +0 -0
- {boneio-1.2.0.dev27 → boneio-1.3.0.dev1}/boneio/integration/interlock.py +0 -0
- {boneio-1.2.0.dev27 → boneio-1.3.0.dev1}/boneio/modbus/__init__.py +0 -0
- {boneio-1.2.0.dev27 → boneio-1.3.0.dev1}/boneio/modbus/cli.py +0 -0
- {boneio-1.2.0.dev27 → boneio-1.3.0.dev1}/boneio/modbus/client.py +0 -0
- {boneio-1.2.0.dev27 → boneio-1.3.0.dev1}/boneio/modbus/devices/__init__.py +0 -0
- {boneio-1.2.0.dev27 → boneio-1.3.0.dev1}/boneio/modbus/devices/energy_meters/le-03mw.json +0 -0
- {boneio-1.2.0.dev27 → boneio-1.3.0.dev1}/boneio/modbus/devices/energy_meters/le-03mwct.json +0 -0
- {boneio-1.2.0.dev27 → boneio-1.3.0.dev1}/boneio/modbus/devices/energy_meters/orno-or-we-517.json +0 -0
- {boneio-1.2.0.dev27 → boneio-1.3.0.dev1}/boneio/modbus/devices/energy_meters/sdm120.json +0 -0
- {boneio-1.2.0.dev27 → boneio-1.3.0.dev1}/boneio/modbus/devices/energy_meters/sdm630.json +0 -0
- {boneio-1.2.0.dev27 → boneio-1.3.0.dev1}/boneio/modbus/devices/hvac/fujitsu-ac.json +0 -0
- {boneio-1.2.0.dev27 → boneio-1.3.0.dev1}/boneio/modbus/devices/hvac/ventclear.json +0 -0
- {boneio-1.2.0.dev27 → boneio-1.3.0.dev1}/boneio/modbus/devices/sensors/dts1964_3f.json +0 -0
- {boneio-1.2.0.dev27 → boneio-1.3.0.dev1}/boneio/modbus/devices/sensors/gdfs.json +0 -0
- {boneio-1.2.0.dev27 → boneio-1.3.0.dev1}/boneio/modbus/devices/sensors/gdfx.json +0 -0
- {boneio-1.2.0.dev27 → boneio-1.3.0.dev1}/boneio/modbus/entities/__init__.py +0 -0
- {boneio-1.2.0.dev27 → boneio-1.3.0.dev1}/boneio/modbus/entities/derived/__init__.py +0 -0
- {boneio-1.2.0.dev27 → boneio-1.3.0.dev1}/boneio/modbus/entities/derived/numeric.py +0 -0
- {boneio-1.2.0.dev27 → boneio-1.3.0.dev1}/boneio/modbus/entities/sensor/__init__.py +0 -0
- {boneio-1.2.0.dev27 → boneio-1.3.0.dev1}/boneio/modbus/entities/sensor/numeric.py +0 -0
- {boneio-1.2.0.dev27 → boneio-1.3.0.dev1}/boneio/modbus/entities/writeable/__init__.py +0 -0
- {boneio-1.2.0.dev27 → boneio-1.3.0.dev1}/boneio/modbus/utils.py +0 -0
- {boneio-1.2.0.dev27 → boneio-1.3.0.dev1}/boneio/models/__init__.py +0 -0
- {boneio-1.2.0.dev27 → boneio-1.3.0.dev1}/boneio/models/actions.py +0 -0
- {boneio-1.2.0.dev27 → boneio-1.3.0.dev1}/boneio/models/events.py +0 -0
- {boneio-1.2.0.dev27 → boneio-1.3.0.dev1}/boneio/models/files.py +0 -0
- {boneio-1.2.0.dev27 → boneio-1.3.0.dev1}/boneio/models/logs.py +0 -0
- {boneio-1.2.0.dev27 → boneio-1.3.0.dev1}/boneio/models/mqtt.py +0 -0
- {boneio-1.2.0.dev27 → boneio-1.3.0.dev1}/boneio/schema/actions.yaml +0 -0
- {boneio-1.2.0.dev27 → boneio-1.3.0.dev1}/boneio/schema/actions_sensor.yaml +0 -0
- {boneio-1.2.0.dev27 → boneio-1.3.0.dev1}/boneio/schema/actions_switch.yaml +0 -0
- {boneio-1.2.0.dev27 → boneio-1.3.0.dev1}/boneio/schema/filters.yaml +0 -0
- {boneio-1.2.0.dev27 → boneio-1.3.0.dev1}/boneio/schema/filters_adc.yaml +0 -0
- {boneio-1.2.0.dev27 → boneio-1.3.0.dev1}/boneio/schema/id.yaml +0 -0
- {boneio-1.2.0.dev27 → boneio-1.3.0.dev1}/boneio/schema/remote_devices.yaml +0 -0
- {boneio-1.2.0.dev27 → boneio-1.3.0.dev1}/boneio/schema/temp_unit.yaml +0 -0
- {boneio-1.2.0.dev27 → boneio-1.3.0.dev1}/boneio/schema/update_interval.yaml +0 -0
- {boneio-1.2.0.dev27 → boneio-1.3.0.dev1}/boneio/webui/frontend-dist/assets/abap-CRCWOmpq.js +0 -0
- {boneio-1.2.0.dev27 → boneio-1.3.0.dev1}/boneio/webui/frontend-dist/assets/apex-DnsZk_dE.js +0 -0
- {boneio-1.2.0.dev27 → boneio-1.3.0.dev1}/boneio/webui/frontend-dist/assets/azcli-1IWB1ccx.js +0 -0
- {boneio-1.2.0.dev27 → boneio-1.3.0.dev1}/boneio/webui/frontend-dist/assets/bat-DPkNLes8.js +0 -0
- {boneio-1.2.0.dev27 → boneio-1.3.0.dev1}/boneio/webui/frontend-dist/assets/bicep-Corcdgou.js +0 -0
- {boneio-1.2.0.dev27 → boneio-1.3.0.dev1}/boneio/webui/frontend-dist/assets/cameligo-CGrWLZr3.js +0 -0
- {boneio-1.2.0.dev27 → boneio-1.3.0.dev1}/boneio/webui/frontend-dist/assets/clojure-D9WOWImG.js +0 -0
- {boneio-1.2.0.dev27 → boneio-1.3.0.dev1}/boneio/webui/frontend-dist/assets/codicon-DCmgc-ay.ttf +0 -0
- {boneio-1.2.0.dev27 → boneio-1.3.0.dev1}/boneio/webui/frontend-dist/assets/coffee-B7EJu28W.js +0 -0
- {boneio-1.2.0.dev27 → boneio-1.3.0.dev1}/boneio/webui/frontend-dist/assets/cpp-SEyurbux.js +0 -0
- {boneio-1.2.0.dev27 → boneio-1.3.0.dev1}/boneio/webui/frontend-dist/assets/csharp-BoL64M5l.js +0 -0
- {boneio-1.2.0.dev27 → boneio-1.3.0.dev1}/boneio/webui/frontend-dist/assets/csp-C46ZqvIl.js +0 -0
- {boneio-1.2.0.dev27 → boneio-1.3.0.dev1}/boneio/webui/frontend-dist/assets/css-DQU6DXDx.js +0 -0
- {boneio-1.2.0.dev27 → boneio-1.3.0.dev1}/boneio/webui/frontend-dist/assets/cypher-D84EuPTj.js +0 -0
- {boneio-1.2.0.dev27 → boneio-1.3.0.dev1}/boneio/webui/frontend-dist/assets/dart-D8lhlL1r.js +0 -0
- {boneio-1.2.0.dev27 → boneio-1.3.0.dev1}/boneio/webui/frontend-dist/assets/dockerfile-DLk6rpji.js +0 -0
- {boneio-1.2.0.dev27 → boneio-1.3.0.dev1}/boneio/webui/frontend-dist/assets/ecl-BO6FnfXk.js +0 -0
- {boneio-1.2.0.dev27 → boneio-1.3.0.dev1}/boneio/webui/frontend-dist/assets/editor.worker-B4pQIWZD.js +0 -0
- {boneio-1.2.0.dev27 → boneio-1.3.0.dev1}/boneio/webui/frontend-dist/assets/elixir-BRjLKONM.js +0 -0
- {boneio-1.2.0.dev27 → boneio-1.3.0.dev1}/boneio/webui/frontend-dist/assets/flow9-Cac8vKd7.js +0 -0
- {boneio-1.2.0.dev27 → boneio-1.3.0.dev1}/boneio/webui/frontend-dist/assets/fsharp-fd1GTHhf.js +0 -0
- {boneio-1.2.0.dev27 → boneio-1.3.0.dev1}/boneio/webui/frontend-dist/assets/go-O9LJTZXk.js +0 -0
- {boneio-1.2.0.dev27 → boneio-1.3.0.dev1}/boneio/webui/frontend-dist/assets/graphql-LQdxqEYJ.js +0 -0
- {boneio-1.2.0.dev27 → boneio-1.3.0.dev1}/boneio/webui/frontend-dist/assets/hcl-DxDQ3s82.js +0 -0
- {boneio-1.2.0.dev27 → boneio-1.3.0.dev1}/boneio/webui/frontend-dist/assets/ini-BvajGCUy.js +0 -0
- {boneio-1.2.0.dev27 → boneio-1.3.0.dev1}/boneio/webui/frontend-dist/assets/java-SYsfObOQ.js +0 -0
- {boneio-1.2.0.dev27 → boneio-1.3.0.dev1}/boneio/webui/frontend-dist/assets/json.worker-aFakAbRR.js +0 -0
- {boneio-1.2.0.dev27 → boneio-1.3.0.dev1}/boneio/webui/frontend-dist/assets/julia-DQXNmw_w.js +0 -0
- {boneio-1.2.0.dev27 → boneio-1.3.0.dev1}/boneio/webui/frontend-dist/assets/kotlin-qQ0MG-9I.js +0 -0
- {boneio-1.2.0.dev27 → boneio-1.3.0.dev1}/boneio/webui/frontend-dist/assets/less-GGFNNJHn.js +0 -0
- {boneio-1.2.0.dev27 → boneio-1.3.0.dev1}/boneio/webui/frontend-dist/assets/lexon-Canl7DCW.js +0 -0
- {boneio-1.2.0.dev27 → boneio-1.3.0.dev1}/boneio/webui/frontend-dist/assets/lua-D28Ae8-K.js +0 -0
- {boneio-1.2.0.dev27 → boneio-1.3.0.dev1}/boneio/webui/frontend-dist/assets/m3-DPitgjJI.js +0 -0
- {boneio-1.2.0.dev27 → boneio-1.3.0.dev1}/boneio/webui/frontend-dist/assets/markdown-B811l8j2.js +0 -0
- {boneio-1.2.0.dev27 → boneio-1.3.0.dev1}/boneio/webui/frontend-dist/assets/mips-CdjsipkG.js +0 -0
- {boneio-1.2.0.dev27 → boneio-1.3.0.dev1}/boneio/webui/frontend-dist/assets/msdax-CYqgjx_P.js +0 -0
- {boneio-1.2.0.dev27 → boneio-1.3.0.dev1}/boneio/webui/frontend-dist/assets/mysql-BHd6q0vd.js +0 -0
- {boneio-1.2.0.dev27 → boneio-1.3.0.dev1}/boneio/webui/frontend-dist/assets/objective-c-B1aVtJYH.js +0 -0
- {boneio-1.2.0.dev27 → boneio-1.3.0.dev1}/boneio/webui/frontend-dist/assets/pascal-BhNW15KB.js +0 -0
- {boneio-1.2.0.dev27 → boneio-1.3.0.dev1}/boneio/webui/frontend-dist/assets/pascaligo-5jv8CcQD.js +0 -0
- {boneio-1.2.0.dev27 → boneio-1.3.0.dev1}/boneio/webui/frontend-dist/assets/perl-DlYyT36c.js +0 -0
- {boneio-1.2.0.dev27 → boneio-1.3.0.dev1}/boneio/webui/frontend-dist/assets/pgsql-Dy0bjov7.js +0 -0
- {boneio-1.2.0.dev27 → boneio-1.3.0.dev1}/boneio/webui/frontend-dist/assets/php-120yhfDK.js +0 -0
- {boneio-1.2.0.dev27 → boneio-1.3.0.dev1}/boneio/webui/frontend-dist/assets/pla-CjnFlu4u.js +0 -0
- {boneio-1.2.0.dev27 → boneio-1.3.0.dev1}/boneio/webui/frontend-dist/assets/postiats-CQpG440k.js +0 -0
- {boneio-1.2.0.dev27 → boneio-1.3.0.dev1}/boneio/webui/frontend-dist/assets/powerquery-DdJtto1Z.js +0 -0
- {boneio-1.2.0.dev27 → boneio-1.3.0.dev1}/boneio/webui/frontend-dist/assets/powershell-Bu_VLpJB.js +0 -0
- {boneio-1.2.0.dev27 → boneio-1.3.0.dev1}/boneio/webui/frontend-dist/assets/protobuf-IBS6jZEB.js +0 -0
- {boneio-1.2.0.dev27 → boneio-1.3.0.dev1}/boneio/webui/frontend-dist/assets/pug-kFxLfcjb.js +0 -0
- {boneio-1.2.0.dev27 → boneio-1.3.0.dev1}/boneio/webui/frontend-dist/assets/qsharp-q7JyzKFN.js +0 -0
- {boneio-1.2.0.dev27 → boneio-1.3.0.dev1}/boneio/webui/frontend-dist/assets/r-BIFz-_sK.js +0 -0
- {boneio-1.2.0.dev27 → boneio-1.3.0.dev1}/boneio/webui/frontend-dist/assets/redis-CHOsPHWR.js +0 -0
- {boneio-1.2.0.dev27 → boneio-1.3.0.dev1}/boneio/webui/frontend-dist/assets/redshift-CBifECDb.js +0 -0
- {boneio-1.2.0.dev27 → boneio-1.3.0.dev1}/boneio/webui/frontend-dist/assets/restructuredtext-CghPJEOS.js +0 -0
- {boneio-1.2.0.dev27 → boneio-1.3.0.dev1}/boneio/webui/frontend-dist/assets/ruby-CYWGW-b1.js +0 -0
- {boneio-1.2.0.dev27 → boneio-1.3.0.dev1}/boneio/webui/frontend-dist/assets/rust-DMDD0SHb.js +0 -0
- {boneio-1.2.0.dev27 → boneio-1.3.0.dev1}/boneio/webui/frontend-dist/assets/sb-BYAiYHFx.js +0 -0
- {boneio-1.2.0.dev27 → boneio-1.3.0.dev1}/boneio/webui/frontend-dist/assets/scala-Bqvq8jcR.js +0 -0
- {boneio-1.2.0.dev27 → boneio-1.3.0.dev1}/boneio/webui/frontend-dist/assets/scheme-Dhb-2j9p.js +0 -0
- {boneio-1.2.0.dev27 → boneio-1.3.0.dev1}/boneio/webui/frontend-dist/assets/scss-CTwUZ5N7.js +0 -0
- {boneio-1.2.0.dev27 → boneio-1.3.0.dev1}/boneio/webui/frontend-dist/assets/shell-CsDZo4DB.js +0 -0
- {boneio-1.2.0.dev27 → boneio-1.3.0.dev1}/boneio/webui/frontend-dist/assets/solidity-CME5AdoB.js +0 -0
- {boneio-1.2.0.dev27 → boneio-1.3.0.dev1}/boneio/webui/frontend-dist/assets/sophia-RYC1BQQz.js +0 -0
- {boneio-1.2.0.dev27 → boneio-1.3.0.dev1}/boneio/webui/frontend-dist/assets/sparql-KEyrF7De.js +0 -0
- {boneio-1.2.0.dev27 → boneio-1.3.0.dev1}/boneio/webui/frontend-dist/assets/sql-BdTr02Mf.js +0 -0
- {boneio-1.2.0.dev27 → boneio-1.3.0.dev1}/boneio/webui/frontend-dist/assets/st-C7iG7M4S.js +0 -0
- {boneio-1.2.0.dev27 → boneio-1.3.0.dev1}/boneio/webui/frontend-dist/assets/swift-D7IUmUK8.js +0 -0
- {boneio-1.2.0.dev27 → boneio-1.3.0.dev1}/boneio/webui/frontend-dist/assets/systemverilog-DgMryOEJ.js +0 -0
- {boneio-1.2.0.dev27 → boneio-1.3.0.dev1}/boneio/webui/frontend-dist/assets/tcl-PloMZuKG.js +0 -0
- {boneio-1.2.0.dev27 → boneio-1.3.0.dev1}/boneio/webui/frontend-dist/assets/twig-BfRIq3la.js +0 -0
- {boneio-1.2.0.dev27 → boneio-1.3.0.dev1}/boneio/webui/frontend-dist/assets/typespec-CzxlYoT_.js +0 -0
- {boneio-1.2.0.dev27 → boneio-1.3.0.dev1}/boneio/webui/frontend-dist/assets/vb-BwAE3J76.js +0 -0
- {boneio-1.2.0.dev27 → boneio-1.3.0.dev1}/boneio/webui/frontend-dist/assets/wgsl-B_1kOXbF.js +0 -0
- {boneio-1.2.0.dev27 → boneio-1.3.0.dev1}/boneio/webui/frontend-dist/assets/workbox-window.prod.es5-BIl4cyR9.js +0 -0
- {boneio-1.2.0.dev27 → boneio-1.3.0.dev1}/boneio/webui/frontend-dist/assets/yaml.worker-DBeHcBRc.js +0 -0
- {boneio-1.2.0.dev27 → boneio-1.3.0.dev1}/boneio/webui/frontend-dist/boneio-192.png +0 -0
- {boneio-1.2.0.dev27 → boneio-1.3.0.dev1}/boneio/webui/frontend-dist/boneio-512.png +0 -0
- {boneio-1.2.0.dev27 → boneio-1.3.0.dev1}/boneio/webui/frontend-dist/boneio.svg +0 -0
- {boneio-1.2.0.dev27 → boneio-1.3.0.dev1}/boneio/webui/frontend-dist/boneio_fav.svg +0 -0
- {boneio-1.2.0.dev27 → boneio-1.3.0.dev1}/boneio/webui/frontend-dist/schema/adc.schema.json +0 -0
- {boneio-1.2.0.dev27 → boneio-1.3.0.dev1}/boneio/webui/frontend-dist/schema/areas.schema.json +0 -0
- {boneio-1.2.0.dev27 → boneio-1.3.0.dev1}/boneio/webui/frontend-dist/schema/binary_sensor.schema.json +0 -0
- {boneio-1.2.0.dev27 → boneio-1.3.0.dev1}/boneio/webui/frontend-dist/schema/cover.schema.json +0 -0
- {boneio-1.2.0.dev27 → boneio-1.3.0.dev1}/boneio/webui/frontend-dist/schema/dallas.schema.json +0 -0
- {boneio-1.2.0.dev27 → boneio-1.3.0.dev1}/boneio/webui/frontend-dist/schema/ds2482.schema.json +0 -0
- {boneio-1.2.0.dev27 → boneio-1.3.0.dev1}/boneio/webui/frontend-dist/schema/event.schema.json +0 -0
- {boneio-1.2.0.dev27 → boneio-1.3.0.dev1}/boneio/webui/frontend-dist/schema/ina219.schema.json +0 -0
- {boneio-1.2.0.dev27 → boneio-1.3.0.dev1}/boneio/webui/frontend-dist/schema/lm75.schema.json +0 -0
- {boneio-1.2.0.dev27 → boneio-1.3.0.dev1}/boneio/webui/frontend-dist/schema/logger.schema.json +0 -0
- {boneio-1.2.0.dev27 → boneio-1.3.0.dev1}/boneio/webui/frontend-dist/schema/mcp23017.schema.json +0 -0
- {boneio-1.2.0.dev27 → boneio-1.3.0.dev1}/boneio/webui/frontend-dist/schema/mcp9808.schema.json +0 -0
- {boneio-1.2.0.dev27 → boneio-1.3.0.dev1}/boneio/webui/frontend-dist/schema/modbus.schema.json +0 -0
- {boneio-1.2.0.dev27 → boneio-1.3.0.dev1}/boneio/webui/frontend-dist/schema/mqtt.schema.json +0 -0
- {boneio-1.2.0.dev27 → boneio-1.3.0.dev1}/boneio/webui/frontend-dist/schema/oled.schema.json +0 -0
- {boneio-1.2.0.dev27 → boneio-1.3.0.dev1}/boneio/webui/frontend-dist/schema/output.schema.json +0 -0
- {boneio-1.2.0.dev27 → boneio-1.3.0.dev1}/boneio/webui/frontend-dist/schema/output_group.schema.json +0 -0
- {boneio-1.2.0.dev27 → boneio-1.3.0.dev1}/boneio/webui/frontend-dist/schema/pca9685.schema.json +0 -0
- {boneio-1.2.0.dev27 → boneio-1.3.0.dev1}/boneio/webui/frontend-dist/schema/pcf8575.schema.json +0 -0
- {boneio-1.2.0.dev27 → boneio-1.3.0.dev1}/boneio/webui/frontend-dist/schema/remote_devices.schema.json +0 -0
- {boneio-1.2.0.dev27 → boneio-1.3.0.dev1}/boneio/webui/frontend-dist/schema/sensor.schema.json +0 -0
- {boneio-1.2.0.dev27 → boneio-1.3.0.dev1}/boneio/webui/frontend-dist/schema/template.schema.json +0 -0
- {boneio-1.2.0.dev27 → boneio-1.3.0.dev1}/boneio/webui/frontend-dist/schema/virtual_energy_sensor.schema.json +0 -0
- {boneio-1.2.0.dev27 → boneio-1.3.0.dev1}/boneio/webui/frontend-dist/schema/web.schema.json +0 -0
- {boneio-1.2.0.dev27 → boneio-1.3.0.dev1}/boneio/webui/frontend-dist/workbox-226dbdbf.js +0 -0
- {boneio-1.2.0.dev27 → boneio-1.3.0.dev1}/boneio/webui/middleware/__init__.py +0 -0
- {boneio-1.2.0.dev27 → boneio-1.3.0.dev1}/boneio/webui/middleware/auth.py +0 -0
- {boneio-1.2.0.dev27 → boneio-1.3.0.dev1}/boneio/webui/routes/auth.py +0 -0
- {boneio-1.2.0.dev27 → boneio-1.3.0.dev1}/boneio/webui/routes/caddy.py +0 -0
- {boneio-1.2.0.dev27 → boneio-1.3.0.dev1}/boneio/webui/routes/covers.py +0 -0
- {boneio-1.2.0.dev27 → boneio-1.3.0.dev1}/boneio/webui/routes/outputs.py +0 -0
- {boneio-1.2.0.dev27 → boneio-1.3.0.dev1}/boneio/webui/routes/remote_devices.py +0 -0
- {boneio-1.2.0.dev27 → boneio-1.3.0.dev1}/boneio/webui/routes/sensors.py +0 -0
- {boneio-1.2.0.dev27 → boneio-1.3.0.dev1}/boneio/webui/routes/system.py +0 -0
- {boneio-1.2.0.dev27 → boneio-1.3.0.dev1}/boneio/webui/routes/templates.py +0 -0
- {boneio-1.2.0.dev27 → boneio-1.3.0.dev1}/boneio/webui/routes/tools.py +0 -0
- {boneio-1.2.0.dev27 → boneio-1.3.0.dev1}/boneio/webui/routes/update.py +0 -0
- {boneio-1.2.0.dev27 → boneio-1.3.0.dev1}/boneio/webui/schema/adc.schema.json +0 -0
- {boneio-1.2.0.dev27 → boneio-1.3.0.dev1}/boneio/webui/schema/areas.schema.json +0 -0
- {boneio-1.2.0.dev27 → boneio-1.3.0.dev1}/boneio/webui/schema/binary_sensor.schema.json +0 -0
- {boneio-1.2.0.dev27 → boneio-1.3.0.dev1}/boneio/webui/schema/cover.schema.json +0 -0
- {boneio-1.2.0.dev27 → boneio-1.3.0.dev1}/boneio/webui/schema/dallas.schema.json +0 -0
- {boneio-1.2.0.dev27 → boneio-1.3.0.dev1}/boneio/webui/schema/ds2482.schema.json +0 -0
- {boneio-1.2.0.dev27 → boneio-1.3.0.dev1}/boneio/webui/schema/event.schema.json +0 -0
- {boneio-1.2.0.dev27 → boneio-1.3.0.dev1}/boneio/webui/schema/ina219.schema.json +0 -0
- {boneio-1.2.0.dev27 → boneio-1.3.0.dev1}/boneio/webui/schema/lm75.schema.json +0 -0
- {boneio-1.2.0.dev27 → boneio-1.3.0.dev1}/boneio/webui/schema/logger.schema.json +0 -0
- {boneio-1.2.0.dev27 → boneio-1.3.0.dev1}/boneio/webui/schema/mcp23017.schema.json +0 -0
- {boneio-1.2.0.dev27 → boneio-1.3.0.dev1}/boneio/webui/schema/mcp9808.schema.json +0 -0
- {boneio-1.2.0.dev27 → boneio-1.3.0.dev1}/boneio/webui/schema/modbus.schema.json +0 -0
- {boneio-1.2.0.dev27 → boneio-1.3.0.dev1}/boneio/webui/schema/mqtt.schema.json +0 -0
- {boneio-1.2.0.dev27 → boneio-1.3.0.dev1}/boneio/webui/schema/oled.schema.json +0 -0
- {boneio-1.2.0.dev27 → boneio-1.3.0.dev1}/boneio/webui/schema/output.schema.json +0 -0
- {boneio-1.2.0.dev27 → boneio-1.3.0.dev1}/boneio/webui/schema/output_group.schema.json +0 -0
- {boneio-1.2.0.dev27 → boneio-1.3.0.dev1}/boneio/webui/schema/pca9685.schema.json +0 -0
- {boneio-1.2.0.dev27 → boneio-1.3.0.dev1}/boneio/webui/schema/pcf8575.schema.json +0 -0
- {boneio-1.2.0.dev27 → boneio-1.3.0.dev1}/boneio/webui/schema/remote_devices.schema.json +0 -0
- {boneio-1.2.0.dev27 → boneio-1.3.0.dev1}/boneio/webui/schema/sensor.schema.json +0 -0
- {boneio-1.2.0.dev27 → boneio-1.3.0.dev1}/boneio/webui/schema/template.schema.json +0 -0
- {boneio-1.2.0.dev27 → boneio-1.3.0.dev1}/boneio/webui/schema/virtual_energy_sensor.schema.json +0 -0
- {boneio-1.2.0.dev27 → boneio-1.3.0.dev1}/boneio/webui/schema/web.schema.json +0 -0
- {boneio-1.2.0.dev27 → boneio-1.3.0.dev1}/boneio/webui/services/__init__.py +0 -0
- {boneio-1.2.0.dev27 → boneio-1.3.0.dev1}/boneio/webui/services/logs.py +0 -0
- {boneio-1.2.0.dev27 → boneio-1.3.0.dev1}/boneio/webui/web_server.py +0 -0
- {boneio-1.2.0.dev27 → boneio-1.3.0.dev1}/boneio/webui/websocket_manager.py +0 -0
- {boneio-1.2.0.dev27 → boneio-1.3.0.dev1}/boneio.egg-info/dependency_links.txt +0 -0
- {boneio-1.2.0.dev27 → boneio-1.3.0.dev1}/boneio.egg-info/entry_points.txt +0 -0
- {boneio-1.2.0.dev27 → boneio-1.3.0.dev1}/boneio.egg-info/top_level.txt +0 -0
- {boneio-1.2.0.dev27 → boneio-1.3.0.dev1}/setup.cfg +0 -0
- {boneio-1.2.0.dev27 → boneio-1.3.0.dev1}/setup.py +0 -0
- {boneio-1.2.0.dev27 → boneio-1.3.0.dev1}/tests/test_py313_compatibility.py +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: boneio
|
|
3
|
-
Version: 1.
|
|
3
|
+
Version: 1.3.0.dev1
|
|
4
4
|
Summary: Python App for BoneIO
|
|
5
5
|
Author-email: Paweł Szafer <pszafer@gmail.com>
|
|
6
6
|
License: GNU General Public License v3.0
|
|
@@ -35,6 +35,7 @@ Requires-Dist: requests==2.32.5
|
|
|
35
35
|
Requires-Dist: packaging==25.0
|
|
36
36
|
Requires-Dist: aioesphomeapi>=29.0.0
|
|
37
37
|
Requires-Dist: zeroconf>=0.148.0
|
|
38
|
+
Requires-Dist: canopen-asyncio>=2.3.0
|
|
38
39
|
Dynamic: license-file
|
|
39
40
|
|
|
40
41
|
Example usage:
|
|
@@ -50,6 +50,7 @@ class ConfigHelper:
|
|
|
50
50
|
update_channel: str = "stable",
|
|
51
51
|
cloud_registration: bool = False,
|
|
52
52
|
pwa_name: str | None = None,
|
|
53
|
+
ha_child_devices: bool = False,
|
|
53
54
|
):
|
|
54
55
|
self._name = name
|
|
55
56
|
|
|
@@ -81,6 +82,7 @@ class ConfigHelper:
|
|
|
81
82
|
self._receive_boneio_autodiscovery = receive_boneio_autodiscovery
|
|
82
83
|
self._update_channel = update_channel
|
|
83
84
|
self._cloud_registration = cloud_registration
|
|
85
|
+
self._ha_child_devices = ha_child_devices
|
|
84
86
|
self._device_type = device_type
|
|
85
87
|
self._web_port = web_port
|
|
86
88
|
self._proxy_port = proxy_port
|
|
@@ -225,6 +227,15 @@ class ConfigHelper:
|
|
|
225
227
|
"""Check if cloud registration (PWA) is enabled."""
|
|
226
228
|
return self._cloud_registration
|
|
227
229
|
|
|
230
|
+
@property
|
|
231
|
+
def ha_child_devices(self) -> bool:
|
|
232
|
+
"""Check if experimental HA child devices mode is enabled.
|
|
233
|
+
|
|
234
|
+
When enabled, each output/input/cover becomes its own child device
|
|
235
|
+
in Home Assistant instead of being grouped under one main device.
|
|
236
|
+
"""
|
|
237
|
+
return self._ha_child_devices
|
|
238
|
+
|
|
228
239
|
@property
|
|
229
240
|
def device_type(self) -> str:
|
|
230
241
|
return self._device_type
|
|
@@ -0,0 +1,552 @@
|
|
|
1
|
+
"""CANopen manager for boneIO.
|
|
2
|
+
|
|
3
|
+
Manages CANopen network communication between boneIO devices.
|
|
4
|
+
Handles node discovery, heartbeat monitoring, and PDO exchange.
|
|
5
|
+
"""
|
|
6
|
+
|
|
7
|
+
from __future__ import annotations
|
|
8
|
+
|
|
9
|
+
import asyncio
|
|
10
|
+
import logging
|
|
11
|
+
import os
|
|
12
|
+
import time
|
|
13
|
+
from typing import TYPE_CHECKING, Any, Callable
|
|
14
|
+
|
|
15
|
+
from boneio.hardware.can.client import CANopenClient, CANOPEN_AVAILABLE
|
|
16
|
+
from boneio.hardware.can.node import (
|
|
17
|
+
BoneIOCANNode,
|
|
18
|
+
NMTState,
|
|
19
|
+
OutputStateMessage,
|
|
20
|
+
)
|
|
21
|
+
|
|
22
|
+
if TYPE_CHECKING:
|
|
23
|
+
from boneio.core.manager import Manager
|
|
24
|
+
|
|
25
|
+
_LOGGER = logging.getLogger(__name__)
|
|
26
|
+
|
|
27
|
+
# Heartbeat interval in seconds
|
|
28
|
+
HEARTBEAT_INTERVAL = 1.0
|
|
29
|
+
|
|
30
|
+
# Node timeout in seconds (consider offline if no heartbeat)
|
|
31
|
+
NODE_TIMEOUT = 5.0
|
|
32
|
+
|
|
33
|
+
|
|
34
|
+
class CANopenManager:
|
|
35
|
+
"""Manager for CANopen communication between boneIO devices.
|
|
36
|
+
|
|
37
|
+
Handles:
|
|
38
|
+
- Connection to CAN bus
|
|
39
|
+
- Periodic heartbeat transmission
|
|
40
|
+
- Discovery and monitoring of other nodes
|
|
41
|
+
- PDO exchange for output state synchronization
|
|
42
|
+
|
|
43
|
+
Args:
|
|
44
|
+
manager: Main boneIO manager instance
|
|
45
|
+
config: CANopen configuration dictionary
|
|
46
|
+
"""
|
|
47
|
+
|
|
48
|
+
def __init__(
|
|
49
|
+
self,
|
|
50
|
+
manager: Manager | None = None,
|
|
51
|
+
config: dict[str, Any] | None = None,
|
|
52
|
+
) -> None:
|
|
53
|
+
"""Initialize CANopen manager.
|
|
54
|
+
|
|
55
|
+
Args:
|
|
56
|
+
manager: Main boneIO manager instance
|
|
57
|
+
config: CANopen configuration with keys:
|
|
58
|
+
- enabled: bool (default: False)
|
|
59
|
+
- channel: str (default: 'can0')
|
|
60
|
+
- bitrate: int (default: 125000)
|
|
61
|
+
- node_id: int (default: 1)
|
|
62
|
+
"""
|
|
63
|
+
self._manager = manager
|
|
64
|
+
self._config = config or {}
|
|
65
|
+
|
|
66
|
+
self._enabled = self._config.get("enabled", False)
|
|
67
|
+
self._channel = self._config.get("channel", "can0")
|
|
68
|
+
self._bitrate = self._config.get("bitrate", 125000)
|
|
69
|
+
self._node_id: int | str = self._config.get("node_id", 1)
|
|
70
|
+
self._mode = self._config.get("mode", "master")
|
|
71
|
+
self._auto_setup = self._config.get("auto_setup", True)
|
|
72
|
+
self._restart_on_error = self._config.get("restart_on_error", True)
|
|
73
|
+
|
|
74
|
+
self._client: CANopenClient | None = None
|
|
75
|
+
self._nodes: dict[int, BoneIOCANNode] = {}
|
|
76
|
+
self._running = False
|
|
77
|
+
|
|
78
|
+
self._heartbeat_task: asyncio.Task | None = None
|
|
79
|
+
self._monitor_task: asyncio.Task | None = None
|
|
80
|
+
self._bridge = None # CANMQTTBridge, initialized in start() for master mode
|
|
81
|
+
|
|
82
|
+
# Callbacks for external handlers
|
|
83
|
+
self._output_state_callbacks: list[Callable[[int, int, int], None]] = []
|
|
84
|
+
|
|
85
|
+
@property
|
|
86
|
+
def is_enabled(self) -> bool:
|
|
87
|
+
"""Check if CANopen is enabled in configuration."""
|
|
88
|
+
return self._enabled and CANOPEN_AVAILABLE
|
|
89
|
+
|
|
90
|
+
@property
|
|
91
|
+
def is_connected(self) -> bool:
|
|
92
|
+
"""Check if connected to CAN bus."""
|
|
93
|
+
return self._client is not None and self._client.is_connected
|
|
94
|
+
|
|
95
|
+
@property
|
|
96
|
+
def node_id(self) -> int | str:
|
|
97
|
+
"""Get local node ID (int after start, may be 'auto' before)."""
|
|
98
|
+
return self._node_id
|
|
99
|
+
|
|
100
|
+
@property
|
|
101
|
+
def nodes(self) -> dict[int, BoneIOCANNode]:
|
|
102
|
+
"""Get dictionary of discovered nodes."""
|
|
103
|
+
return self._nodes
|
|
104
|
+
|
|
105
|
+
async def start(self) -> bool:
|
|
106
|
+
"""Start CANopen manager.
|
|
107
|
+
|
|
108
|
+
Connects to CAN bus and starts heartbeat/monitoring tasks.
|
|
109
|
+
|
|
110
|
+
Returns:
|
|
111
|
+
True if started successfully.
|
|
112
|
+
"""
|
|
113
|
+
if not self.is_enabled:
|
|
114
|
+
_LOGGER.info("CANopen is disabled or not available")
|
|
115
|
+
return False
|
|
116
|
+
|
|
117
|
+
if self._running:
|
|
118
|
+
_LOGGER.warning("CANopen manager already running")
|
|
119
|
+
return True
|
|
120
|
+
|
|
121
|
+
try:
|
|
122
|
+
# Resolve node_id if set to 'auto'
|
|
123
|
+
if self._node_id == "auto" or (isinstance(self._node_id, str) and self._node_id.lower() == "auto"):
|
|
124
|
+
from boneio.hardware.can.node_id import resolve_node_id
|
|
125
|
+
mac = ""
|
|
126
|
+
config_dir = ""
|
|
127
|
+
if self._manager is not None:
|
|
128
|
+
mac = self._manager.config_helper.network_info.get("mac", "")
|
|
129
|
+
config_dir = os.path.dirname(self._manager._config_file_path)
|
|
130
|
+
self._node_id = resolve_node_id(self._node_id, mac, config_dir)
|
|
131
|
+
|
|
132
|
+
# Auto-setup CAN interface if configured
|
|
133
|
+
if self._auto_setup:
|
|
134
|
+
from boneio.hardware.can.interface import setup_can_interface, interface_exists
|
|
135
|
+
if not interface_exists(self._channel):
|
|
136
|
+
_LOGGER.error("CAN interface %s does not exist in the system", self._channel)
|
|
137
|
+
return False
|
|
138
|
+
if not await setup_can_interface(self._channel, self._bitrate):
|
|
139
|
+
_LOGGER.error("Failed to auto-setup CAN interface %s", self._channel)
|
|
140
|
+
return False
|
|
141
|
+
|
|
142
|
+
# Create and connect client (node_id is guaranteed int after resolve)
|
|
143
|
+
self._client = CANopenClient(
|
|
144
|
+
channel=self._channel,
|
|
145
|
+
bitrate=self._bitrate,
|
|
146
|
+
node_id=int(self._node_id),
|
|
147
|
+
)
|
|
148
|
+
|
|
149
|
+
if not await self._client.connect():
|
|
150
|
+
_LOGGER.error("Failed to connect to CAN bus")
|
|
151
|
+
return False
|
|
152
|
+
|
|
153
|
+
# Register callbacks
|
|
154
|
+
self._client.add_heartbeat_callback(self._on_heartbeat)
|
|
155
|
+
self._client.add_pdo_callback(self._on_pdo)
|
|
156
|
+
|
|
157
|
+
# Check for node_id collision (listen 3s for heartbeats)
|
|
158
|
+
collision = await self._check_node_id_collision()
|
|
159
|
+
if collision:
|
|
160
|
+
_LOGGER.warning(
|
|
161
|
+
"Node ID %d collision detected, cannot start CANopen",
|
|
162
|
+
self._node_id,
|
|
163
|
+
)
|
|
164
|
+
await self._client.disconnect()
|
|
165
|
+
self._client = None
|
|
166
|
+
return False
|
|
167
|
+
|
|
168
|
+
# Start background tasks
|
|
169
|
+
self._running = True
|
|
170
|
+
self._heartbeat_task = asyncio.create_task(self._heartbeat_loop())
|
|
171
|
+
self._monitor_task = asyncio.create_task(self._monitor_loop())
|
|
172
|
+
|
|
173
|
+
# Start CAN-MQTT bridge in master mode
|
|
174
|
+
if self._mode == "master" and self._manager is not None:
|
|
175
|
+
from boneio.hardware.can.bridge import CANMQTTBridge
|
|
176
|
+
self._bridge = CANMQTTBridge(
|
|
177
|
+
manager=self._manager,
|
|
178
|
+
canopen_manager=self,
|
|
179
|
+
message_bus=self._manager.message_bus,
|
|
180
|
+
)
|
|
181
|
+
self._bridge.start()
|
|
182
|
+
|
|
183
|
+
_LOGGER.info(
|
|
184
|
+
"CANopen manager started: channel=%s, bitrate=%d, node_id=%d, mode=%s",
|
|
185
|
+
self._channel,
|
|
186
|
+
self._bitrate,
|
|
187
|
+
self._node_id,
|
|
188
|
+
self._mode,
|
|
189
|
+
)
|
|
190
|
+
return True
|
|
191
|
+
|
|
192
|
+
except Exception as e:
|
|
193
|
+
_LOGGER.error("Failed to start CANopen manager: %s", e)
|
|
194
|
+
self._running = False
|
|
195
|
+
return False
|
|
196
|
+
|
|
197
|
+
async def _check_node_id_collision(self, listen_seconds: float = 3.0) -> bool:
|
|
198
|
+
"""Check if another node on the bus uses the same node_id.
|
|
199
|
+
|
|
200
|
+
Listens for heartbeat messages for `listen_seconds`. If a heartbeat
|
|
201
|
+
from our own node_id is received, a collision is detected.
|
|
202
|
+
|
|
203
|
+
Args:
|
|
204
|
+
listen_seconds: How long to listen for collisions.
|
|
205
|
+
|
|
206
|
+
Returns:
|
|
207
|
+
True if collision detected.
|
|
208
|
+
"""
|
|
209
|
+
collision_detected = False
|
|
210
|
+
own_id = int(self._node_id)
|
|
211
|
+
|
|
212
|
+
def _collision_cb(node_id: int, state: str) -> None:
|
|
213
|
+
nonlocal collision_detected
|
|
214
|
+
if node_id == own_id:
|
|
215
|
+
collision_detected = True
|
|
216
|
+
|
|
217
|
+
# Temporarily register collision callback
|
|
218
|
+
if self._client is not None:
|
|
219
|
+
self._client.add_heartbeat_callback(_collision_cb)
|
|
220
|
+
|
|
221
|
+
_LOGGER.info(
|
|
222
|
+
"Checking for node_id %d collision (%0.1fs)...", own_id, listen_seconds
|
|
223
|
+
)
|
|
224
|
+
await asyncio.sleep(listen_seconds)
|
|
225
|
+
|
|
226
|
+
# Remove temporary callback
|
|
227
|
+
if self._client is not None and _collision_cb in self._client._heartbeat_callbacks:
|
|
228
|
+
self._client._heartbeat_callbacks.remove(_collision_cb)
|
|
229
|
+
|
|
230
|
+
if collision_detected:
|
|
231
|
+
_LOGGER.warning("Collision: another node is using node_id %d", own_id)
|
|
232
|
+
else:
|
|
233
|
+
_LOGGER.info("No node_id collision detected for %d", own_id)
|
|
234
|
+
|
|
235
|
+
return collision_detected
|
|
236
|
+
|
|
237
|
+
async def stop(self) -> None:
|
|
238
|
+
"""Stop CANopen manager."""
|
|
239
|
+
if not self._running:
|
|
240
|
+
return
|
|
241
|
+
|
|
242
|
+
self._running = False
|
|
243
|
+
|
|
244
|
+
# Stop bridge
|
|
245
|
+
if self._bridge is not None:
|
|
246
|
+
self._bridge.stop()
|
|
247
|
+
self._bridge = None
|
|
248
|
+
|
|
249
|
+
# Cancel background tasks
|
|
250
|
+
if self._heartbeat_task:
|
|
251
|
+
self._heartbeat_task.cancel()
|
|
252
|
+
try:
|
|
253
|
+
await self._heartbeat_task
|
|
254
|
+
except asyncio.CancelledError:
|
|
255
|
+
pass
|
|
256
|
+
self._heartbeat_task = None
|
|
257
|
+
|
|
258
|
+
if self._monitor_task:
|
|
259
|
+
self._monitor_task.cancel()
|
|
260
|
+
try:
|
|
261
|
+
await self._monitor_task
|
|
262
|
+
except asyncio.CancelledError:
|
|
263
|
+
pass
|
|
264
|
+
self._monitor_task = None
|
|
265
|
+
|
|
266
|
+
# Disconnect client
|
|
267
|
+
if self._client:
|
|
268
|
+
await self._client.disconnect()
|
|
269
|
+
self._client = None
|
|
270
|
+
|
|
271
|
+
_LOGGER.info("CANopen manager stopped")
|
|
272
|
+
|
|
273
|
+
async def send_output_state(
|
|
274
|
+
self,
|
|
275
|
+
output_index: int,
|
|
276
|
+
state: int,
|
|
277
|
+
brightness: int = 0,
|
|
278
|
+
) -> bool:
|
|
279
|
+
"""Send output state change to CAN bus.
|
|
280
|
+
|
|
281
|
+
Other boneIO devices on the bus will receive this and can
|
|
282
|
+
react accordingly (e.g., for synchronized lighting).
|
|
283
|
+
|
|
284
|
+
Args:
|
|
285
|
+
output_index: Output index (0-47)
|
|
286
|
+
state: State (0=OFF, 1=ON)
|
|
287
|
+
brightness: Brightness for dimmers (0-255)
|
|
288
|
+
|
|
289
|
+
Returns:
|
|
290
|
+
True if sent successfully.
|
|
291
|
+
"""
|
|
292
|
+
if not self.is_connected or self._client is None:
|
|
293
|
+
return False
|
|
294
|
+
|
|
295
|
+
return await self._client.send_output_state(output_index, state, brightness)
|
|
296
|
+
|
|
297
|
+
async def send_command_to_node(
|
|
298
|
+
self,
|
|
299
|
+
target_node_id: int,
|
|
300
|
+
output_index: int,
|
|
301
|
+
state: int,
|
|
302
|
+
brightness: int = 0,
|
|
303
|
+
) -> bool:
|
|
304
|
+
"""Send output command to a specific node via RPDO.
|
|
305
|
+
|
|
306
|
+
Args:
|
|
307
|
+
target_node_id: Target CAN node ID (1-127).
|
|
308
|
+
output_index: Output index on the target device (0-47).
|
|
309
|
+
state: Desired state (0=OFF, 1=ON).
|
|
310
|
+
brightness: Brightness level (0-255).
|
|
311
|
+
|
|
312
|
+
Returns:
|
|
313
|
+
True if sent successfully.
|
|
314
|
+
"""
|
|
315
|
+
if not self.is_connected or self._client is None:
|
|
316
|
+
return False
|
|
317
|
+
|
|
318
|
+
return await self._client.send_command_to_node(
|
|
319
|
+
target_node_id, output_index, state, brightness
|
|
320
|
+
)
|
|
321
|
+
|
|
322
|
+
def add_output_state_callback(
|
|
323
|
+
self,
|
|
324
|
+
callback: Callable[[int, int, int], None],
|
|
325
|
+
) -> None:
|
|
326
|
+
"""Add callback for received output state changes.
|
|
327
|
+
|
|
328
|
+
Args:
|
|
329
|
+
callback: Function(node_id, output_index, state) called on reception.
|
|
330
|
+
"""
|
|
331
|
+
self._output_state_callbacks.append(callback)
|
|
332
|
+
|
|
333
|
+
def get_node(self, node_id: int) -> BoneIOCANNode | None:
|
|
334
|
+
"""Get node by ID.
|
|
335
|
+
|
|
336
|
+
Args:
|
|
337
|
+
node_id: Node ID to look up.
|
|
338
|
+
|
|
339
|
+
Returns:
|
|
340
|
+
BoneIOCANNode if found, None otherwise.
|
|
341
|
+
"""
|
|
342
|
+
return self._nodes.get(node_id)
|
|
343
|
+
|
|
344
|
+
def get_online_nodes(self) -> list[BoneIOCANNode]:
|
|
345
|
+
"""Get list of online nodes.
|
|
346
|
+
|
|
347
|
+
Returns:
|
|
348
|
+
List of nodes that have sent heartbeat recently.
|
|
349
|
+
"""
|
|
350
|
+
return [node for node in self._nodes.values() if node.is_online]
|
|
351
|
+
|
|
352
|
+
async def _heartbeat_loop(self) -> None:
|
|
353
|
+
"""Background task for sending periodic heartbeats."""
|
|
354
|
+
_LOGGER.debug("Heartbeat loop started")
|
|
355
|
+
|
|
356
|
+
while self._running:
|
|
357
|
+
try:
|
|
358
|
+
if self._client is None:
|
|
359
|
+
break
|
|
360
|
+
await self._client.send_heartbeat(NMTState.OPERATIONAL)
|
|
361
|
+
await asyncio.sleep(HEARTBEAT_INTERVAL)
|
|
362
|
+
except asyncio.CancelledError:
|
|
363
|
+
break
|
|
364
|
+
except Exception as e:
|
|
365
|
+
_LOGGER.error("Error in heartbeat loop: %s", e)
|
|
366
|
+
await asyncio.sleep(HEARTBEAT_INTERVAL)
|
|
367
|
+
|
|
368
|
+
_LOGGER.debug("Heartbeat loop stopped")
|
|
369
|
+
|
|
370
|
+
async def _monitor_loop(self) -> None:
|
|
371
|
+
"""Background task for monitoring node timeouts and bus-off recovery."""
|
|
372
|
+
_LOGGER.debug("Monitor loop started")
|
|
373
|
+
|
|
374
|
+
while self._running:
|
|
375
|
+
try:
|
|
376
|
+
current_time = time.time()
|
|
377
|
+
|
|
378
|
+
# Check node timeouts
|
|
379
|
+
for node in list(self._nodes.values()):
|
|
380
|
+
if node.last_heartbeat is not None:
|
|
381
|
+
elapsed = current_time - node.last_heartbeat
|
|
382
|
+
if elapsed > NODE_TIMEOUT and node.is_online:
|
|
383
|
+
_LOGGER.warning(
|
|
384
|
+
"Node %d timed out (no heartbeat for %.1fs)",
|
|
385
|
+
node.node_id,
|
|
386
|
+
elapsed,
|
|
387
|
+
)
|
|
388
|
+
node.nmt_state = NMTState.PRE_OPERATIONAL
|
|
389
|
+
|
|
390
|
+
# Check for bus-off and auto-restart
|
|
391
|
+
if self._restart_on_error:
|
|
392
|
+
from boneio.hardware.can.interface import get_can_state
|
|
393
|
+
can_state = await get_can_state(self._channel)
|
|
394
|
+
if can_state == "BUS-OFF":
|
|
395
|
+
_LOGGER.warning("CAN bus-off detected on %s, restarting interface", self._channel)
|
|
396
|
+
from boneio.hardware.can.interface import restart_can_interface
|
|
397
|
+
if await restart_can_interface(self._channel, self._bitrate):
|
|
398
|
+
_LOGGER.info("CAN interface %s restarted successfully", self._channel)
|
|
399
|
+
else:
|
|
400
|
+
_LOGGER.error("Failed to restart CAN interface %s", self._channel)
|
|
401
|
+
|
|
402
|
+
await asyncio.sleep(1.0)
|
|
403
|
+
except asyncio.CancelledError:
|
|
404
|
+
break
|
|
405
|
+
except Exception as e:
|
|
406
|
+
_LOGGER.error("Error in monitor loop: %s", e)
|
|
407
|
+
await asyncio.sleep(1.0)
|
|
408
|
+
|
|
409
|
+
_LOGGER.debug("Monitor loop stopped")
|
|
410
|
+
|
|
411
|
+
def _on_heartbeat(self, node_id: int, state: str) -> None:
|
|
412
|
+
"""Handle received heartbeat message.
|
|
413
|
+
|
|
414
|
+
Args:
|
|
415
|
+
node_id: Node ID of sender
|
|
416
|
+
state: NMT state string
|
|
417
|
+
"""
|
|
418
|
+
if node_id == self._node_id:
|
|
419
|
+
return # Ignore own heartbeat
|
|
420
|
+
|
|
421
|
+
# Map state string to NMTState
|
|
422
|
+
state_map = {
|
|
423
|
+
"BOOT-UP": NMTState.BOOT_UP,
|
|
424
|
+
"STOPPED": NMTState.STOPPED,
|
|
425
|
+
"OPERATIONAL": NMTState.OPERATIONAL,
|
|
426
|
+
"PRE-OPERATIONAL": NMTState.PRE_OPERATIONAL,
|
|
427
|
+
}
|
|
428
|
+
nmt_state = state_map.get(state, NMTState.OPERATIONAL)
|
|
429
|
+
|
|
430
|
+
# Create or update node
|
|
431
|
+
if node_id not in self._nodes:
|
|
432
|
+
self._nodes[node_id] = BoneIOCANNode(node_id=node_id)
|
|
433
|
+
_LOGGER.info("Discovered new CANopen node: %d", node_id)
|
|
434
|
+
|
|
435
|
+
# Auto-register as CANRemoteDevice in Manager
|
|
436
|
+
if self._manager is not None:
|
|
437
|
+
from boneio.core.remote.can import CANRemoteDevice
|
|
438
|
+
can_device = CANRemoteDevice(
|
|
439
|
+
node=self._nodes[node_id],
|
|
440
|
+
canopen_manager=self,
|
|
441
|
+
)
|
|
442
|
+
self._manager.remote_devices.add_device(can_device)
|
|
443
|
+
|
|
444
|
+
self._nodes[node_id].update_heartbeat(time.time(), nmt_state)
|
|
445
|
+
|
|
446
|
+
def _on_pdo(self, cob_id: int, data: bytes) -> None:
|
|
447
|
+
"""Handle received PDO message.
|
|
448
|
+
|
|
449
|
+
Handles two PDO types:
|
|
450
|
+
- TPDO1 (0x180 + node_id): output state broadcast from other nodes
|
|
451
|
+
- RPDO1 (0x200 + node_id): command addressed to us from master
|
|
452
|
+
|
|
453
|
+
Args:
|
|
454
|
+
cob_id: COB-ID of the message
|
|
455
|
+
data: PDO data
|
|
456
|
+
"""
|
|
457
|
+
# RPDO1: 0x200 + our_node_id — command addressed to us (slave mode)
|
|
458
|
+
if cob_id == 0x200 + int(self._node_id) and len(data) >= 3:
|
|
459
|
+
output_index = data[0]
|
|
460
|
+
state = data[1] & 0x01
|
|
461
|
+
sender_id = data[3] if len(data) > 3 else 0
|
|
462
|
+
_LOGGER.info(
|
|
463
|
+
"Received command from node %d: output=%d, state=%d",
|
|
464
|
+
sender_id, output_index, state,
|
|
465
|
+
)
|
|
466
|
+
# Execute locally via Manager
|
|
467
|
+
if self._manager is not None:
|
|
468
|
+
asyncio.get_event_loop().create_task(
|
|
469
|
+
self._execute_local_output_command(output_index, state)
|
|
470
|
+
)
|
|
471
|
+
return
|
|
472
|
+
|
|
473
|
+
# TPDO1: 0x180 + node_id — output state broadcast from other nodes
|
|
474
|
+
if 0x181 <= cob_id <= 0x1FF:
|
|
475
|
+
node_id = cob_id - 0x180
|
|
476
|
+
|
|
477
|
+
if node_id == self._node_id:
|
|
478
|
+
return # Ignore own PDO
|
|
479
|
+
|
|
480
|
+
try:
|
|
481
|
+
msg = OutputStateMessage.from_bytes(data)
|
|
482
|
+
_LOGGER.debug(
|
|
483
|
+
"Received output state from node %d: output=%d, state=%d",
|
|
484
|
+
node_id,
|
|
485
|
+
msg.output_index,
|
|
486
|
+
msg.state,
|
|
487
|
+
)
|
|
488
|
+
|
|
489
|
+
# Update node state
|
|
490
|
+
if node_id in self._nodes:
|
|
491
|
+
self._nodes[node_id].update_output(msg.output_index, msg.state)
|
|
492
|
+
|
|
493
|
+
# Call registered callbacks
|
|
494
|
+
for callback in self._output_state_callbacks:
|
|
495
|
+
try:
|
|
496
|
+
callback(node_id, msg.output_index, msg.state)
|
|
497
|
+
except Exception as e:
|
|
498
|
+
_LOGGER.error("Error in output state callback: %s", e)
|
|
499
|
+
|
|
500
|
+
except Exception as e:
|
|
501
|
+
_LOGGER.error("Failed to parse PDO data: %s", e)
|
|
502
|
+
|
|
503
|
+
async def _execute_local_output_command(self, output_index: int, state: int) -> None:
|
|
504
|
+
"""Execute output command locally (slave receiving RPDO from master).
|
|
505
|
+
|
|
506
|
+
Finds the output by index and toggles/sets it.
|
|
507
|
+
|
|
508
|
+
Args:
|
|
509
|
+
output_index: Output index (0-47).
|
|
510
|
+
state: Desired state (0=OFF, 1=ON).
|
|
511
|
+
"""
|
|
512
|
+
if self._manager is None:
|
|
513
|
+
return
|
|
514
|
+
|
|
515
|
+
try:
|
|
516
|
+
outputs = self._manager.outputs
|
|
517
|
+
output_list = list(outputs.get_all_outputs().values())
|
|
518
|
+
if output_index >= len(output_list):
|
|
519
|
+
_LOGGER.warning(
|
|
520
|
+
"CAN command for output index %d but only %d outputs configured",
|
|
521
|
+
output_index, len(output_list),
|
|
522
|
+
)
|
|
523
|
+
return
|
|
524
|
+
|
|
525
|
+
output = output_list[output_index]
|
|
526
|
+
if state == 1:
|
|
527
|
+
await output.async_turn_on()
|
|
528
|
+
else:
|
|
529
|
+
await output.async_turn_off()
|
|
530
|
+
_LOGGER.info(
|
|
531
|
+
"Executed CAN command: output[%d]=%s -> %s",
|
|
532
|
+
output_index, output.name if hasattr(output, "name") else str(output_index),
|
|
533
|
+
"ON" if state else "OFF",
|
|
534
|
+
)
|
|
535
|
+
except Exception as e:
|
|
536
|
+
_LOGGER.error("Failed to execute local output command: %s", e)
|
|
537
|
+
|
|
538
|
+
def to_dict(self) -> dict[str, Any]:
|
|
539
|
+
"""Get manager status as dictionary.
|
|
540
|
+
|
|
541
|
+
Returns:
|
|
542
|
+
Dictionary with manager status.
|
|
543
|
+
"""
|
|
544
|
+
return {
|
|
545
|
+
"enabled": self._enabled,
|
|
546
|
+
"connected": self.is_connected,
|
|
547
|
+
"channel": self._channel,
|
|
548
|
+
"bitrate": self._bitrate,
|
|
549
|
+
"node_id": self._node_id,
|
|
550
|
+
"mode": self._mode,
|
|
551
|
+
"nodes": [node.to_dict() for node in self._nodes.values()],
|
|
552
|
+
}
|
|
@@ -15,8 +15,10 @@ from typing import TYPE_CHECKING, Any
|
|
|
15
15
|
|
|
16
16
|
from boneio.const import (
|
|
17
17
|
BUTTON,
|
|
18
|
+
CAN,
|
|
18
19
|
COVER,
|
|
19
20
|
COVER_OVER_MQTT,
|
|
21
|
+
ENABLED,
|
|
20
22
|
MQTT,
|
|
21
23
|
NONE,
|
|
22
24
|
ONLINE,
|
|
@@ -116,6 +118,7 @@ class Manager:
|
|
|
116
118
|
cover: list[dict] = [],
|
|
117
119
|
template: list[dict] = [],
|
|
118
120
|
remote_devices: list[dict] = [],
|
|
121
|
+
can: dict[str, Any] = {},
|
|
119
122
|
web_active: bool = False,
|
|
120
123
|
web_port: int = 8090,
|
|
121
124
|
) -> None:
|
|
@@ -219,6 +222,15 @@ class Manager:
|
|
|
219
222
|
template_config=template,
|
|
220
223
|
)
|
|
221
224
|
|
|
225
|
+
# 11. CANopenManager (optional - CAN bus communication)
|
|
226
|
+
self.canopen = None
|
|
227
|
+
if can.get(ENABLED, False):
|
|
228
|
+
from boneio.core.manager.canopen import CANopenManager
|
|
229
|
+
self.canopen = CANopenManager(
|
|
230
|
+
manager=self,
|
|
231
|
+
config=can,
|
|
232
|
+
)
|
|
233
|
+
|
|
222
234
|
# Configure virtual energy sensors (must be after outputs are initialized)
|
|
223
235
|
self.sensors.configure_virtual_energy_sensors()
|
|
224
236
|
|
|
@@ -227,15 +239,33 @@ class Manager:
|
|
|
227
239
|
|
|
228
240
|
_LOGGER.info("Manager initialization complete")
|
|
229
241
|
|
|
242
|
+
async def start_canopen(self) -> None:
|
|
243
|
+
"""Start CANopen manager if configured."""
|
|
244
|
+
if self.canopen is not None:
|
|
245
|
+
can_started = await self.canopen.start()
|
|
246
|
+
if can_started:
|
|
247
|
+
_LOGGER.info("CANopen manager started successfully")
|
|
248
|
+
else:
|
|
249
|
+
_LOGGER.warning("CANopen manager failed to start")
|
|
250
|
+
self.canopen = None
|
|
251
|
+
|
|
230
252
|
async def stop(self) -> None:
|
|
231
253
|
"""Stop manager async tasks.
|
|
232
254
|
|
|
233
255
|
This should be called during shutdown to cleanly stop:
|
|
256
|
+
- CANopen manager
|
|
234
257
|
- ESPHome connections
|
|
235
258
|
- Other async tasks
|
|
236
259
|
"""
|
|
237
260
|
_LOGGER.info("Stopping manager async tasks")
|
|
238
261
|
|
|
262
|
+
# Stop CANopen manager
|
|
263
|
+
if self.canopen is not None:
|
|
264
|
+
try:
|
|
265
|
+
await self.canopen.stop()
|
|
266
|
+
except Exception as e:
|
|
267
|
+
_LOGGER.error("Error stopping CANopen manager: %s", e)
|
|
268
|
+
|
|
239
269
|
# Stop ESPHome connections
|
|
240
270
|
await self.remote_devices.stop_all_connections()
|
|
241
271
|
|
|
@@ -169,6 +169,7 @@ class ModbusManager:
|
|
|
169
169
|
),
|
|
170
170
|
modbus=self._modbus,
|
|
171
171
|
sensors_filters=device_config.get("sensors_filters", {}),
|
|
172
|
+
entity_labels=device_config.get("entity_labels", {}),
|
|
172
173
|
additional_data=additional_data,
|
|
173
174
|
area=area,
|
|
174
175
|
has_custom_id=has_custom_id,
|