From dd72b18f8fdac14ba4eae8493d3e176a0d4c00fe Mon Sep 17 00:00:00 2001 From: unl0ck Date: Wed, 8 May 2024 14:18:10 +0200 Subject: [PATCH 01/20] Update config.yaml --- GridboxConnectorAddon-dev/config.yaml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/GridboxConnectorAddon-dev/config.yaml b/GridboxConnectorAddon-dev/config.yaml index 97e0480..3084a60 100644 --- a/GridboxConnectorAddon-dev/config.yaml +++ b/GridboxConnectorAddon-dev/config.yaml @@ -3,7 +3,7 @@ name: Viessmann Gridbox Connector (dev) version: "1.9.11" slug: "gridbox_connector_dev" description: Development version of Viessmann Gridbox Connector -url: "https://github.com/unl0ck/homeassistant-addon-viessmann-gridbox/tree/main/GridboxConnectorAddon" +url: "https://github.com/unl0ck/homeassistant-addon-viessmann-gridbox/tree/main/GridboxConnectorAddon-dev" arch: - armhf - armv7 @@ -29,5 +29,5 @@ schema: OverrideMqttPw: password? OverrideMqttServer: str? OverrideMqttPort: int? -image: ghcr.io/unl0ck/homeassistant-addon-viessmann-gridbox-{arch} +image: ghcr.io/unl0ck/homeassistant-addon-viessmann-gridbox-dev-{arch} stage: experimental From 0cf3de59d1ae138656dea8611f9ce42a1a1f8018 Mon Sep 17 00:00:00 2001 From: unl0ck Date: Wed, 8 May 2024 21:14:09 +0200 Subject: [PATCH 02/20] Update README.md --- README.md | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index 071c053..46e9750 100644 --- a/README.md +++ b/README.md @@ -5,7 +5,8 @@ ## Add-ons -### [GridboxConnector add-on](./GridboxConnectorAddon) +### [Viessmann Gridbox Connector](./GridboxConnectorAddon) +### [Viessmann Gridbox Connector (Dev)](./GridboxConnectorAddon-dev) ![Supports aarch64 Architecture][aarch64-shield] ![Supports amd64 Architecture][amd64-shield] From 1eff8ca8cbc3b62d98a8c7d64a5b2e497fe29e5f Mon Sep 17 00:00:00 2001 From: unl0ck Date: Wed, 8 May 2024 21:14:44 +0200 Subject: [PATCH 03/20] Update README.md --- README.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/README.md b/README.md index 46e9750..9cd31a2 100644 --- a/README.md +++ b/README.md @@ -1,6 +1,8 @@ # Home Assistant Viessmann Gridbox Addons **Not an official Viessmann Addon** +Get your Gridbox Data via MQTT to your Home Assistant Server + [![Open your Home Assistant instance and show the add add-on repository dialog with a specific repository URL pre-filled.](https://my.home-assistant.io/badges/supervisor_add_addon_repository.svg)](https://my.home-assistant.io/redirect/supervisor_add_addon_repository/?repository_url=https%3A%2F%2Fgithub.com%2Funl0ck%2Fhomeassistant-addon-viessmann-gridbox) ## Add-ons From 7297a16d48a09d47ecc9486c60a6574f98a8b0de Mon Sep 17 00:00:00 2001 From: unl0ck Date: Wed, 8 May 2024 21:15:05 +0200 Subject: [PATCH 04/20] Update README.md --- README.md | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/README.md b/README.md index 9cd31a2..a62335d 100644 --- a/README.md +++ b/README.md @@ -1,4 +1,8 @@ # Home Assistant Viessmann Gridbox Addons +[aarch64-shield]: https://img.shields.io/badge/aarch64-yes-green.svg +[amd64-shield]: https://img.shields.io/badge/amd64-yes-green.svg +[armhf-shield]: https://img.shields.io/badge/armhf-yes-green.svg +[armv7-shield]: https://img.shields.io/badge/armv7-yes-green.svg **Not an official Viessmann Addon** Get your Gridbox Data via MQTT to your Home Assistant Server @@ -16,7 +20,4 @@ Get your Gridbox Data via MQTT to your Home Assistant Server ![Supports armv7 Architecture][armv7-shield] -[aarch64-shield]: https://img.shields.io/badge/aarch64-yes-green.svg -[amd64-shield]: https://img.shields.io/badge/amd64-yes-green.svg -[armhf-shield]: https://img.shields.io/badge/armhf-yes-green.svg -[armv7-shield]: https://img.shields.io/badge/armv7-yes-green.svg + From 09456f9dd578c61378aa98a5d20932cfd91c05dc Mon Sep 17 00:00:00 2001 From: unl0ck Date: Wed, 8 May 2024 21:15:26 +0200 Subject: [PATCH 05/20] Update README.md --- README.md | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/README.md b/README.md index a62335d..be79aeb 100644 --- a/README.md +++ b/README.md @@ -3,6 +3,10 @@ [amd64-shield]: https://img.shields.io/badge/amd64-yes-green.svg [armhf-shield]: https://img.shields.io/badge/armhf-yes-green.svg [armv7-shield]: https://img.shields.io/badge/armv7-yes-green.svg +![Supports aarch64 Architecture][aarch64-shield] +![Supports amd64 Architecture][amd64-shield] +![Supports armhf Architecture][armhf-shield] +![Supports armv7 Architecture][armv7-shield] **Not an official Viessmann Addon** Get your Gridbox Data via MQTT to your Home Assistant Server @@ -14,10 +18,7 @@ Get your Gridbox Data via MQTT to your Home Assistant Server ### [Viessmann Gridbox Connector](./GridboxConnectorAddon) ### [Viessmann Gridbox Connector (Dev)](./GridboxConnectorAddon-dev) -![Supports aarch64 Architecture][aarch64-shield] -![Supports amd64 Architecture][amd64-shield] -![Supports armhf Architecture][armhf-shield] -![Supports armv7 Architecture][armv7-shield] + From cc25680929d4d6b295879977928d62377f7a3c91 Mon Sep 17 00:00:00 2001 From: unl0ck Date: Wed, 8 May 2024 21:15:34 +0200 Subject: [PATCH 06/20] Update README.md --- README.md | 1 + 1 file changed, 1 insertion(+) diff --git a/README.md b/README.md index be79aeb..59a8360 100644 --- a/README.md +++ b/README.md @@ -7,6 +7,7 @@ ![Supports amd64 Architecture][amd64-shield] ![Supports armhf Architecture][armhf-shield] ![Supports armv7 Architecture][armv7-shield] + **Not an official Viessmann Addon** Get your Gridbox Data via MQTT to your Home Assistant Server From 7a6732c5427065702041567b03267a626ec5215e Mon Sep 17 00:00:00 2001 From: unl0ck Date: Wed, 8 May 2024 21:58:58 +0200 Subject: [PATCH 07/20] Update README.md --- GridboxConnectorAddon/README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/GridboxConnectorAddon/README.md b/GridboxConnectorAddon/README.md index 13cfb31..a013e5e 100644 --- a/GridboxConnectorAddon/README.md +++ b/GridboxConnectorAddon/README.md @@ -1,4 +1,4 @@ -# Viessmann Gridbox Add-on: Gridbox Connector add-on +# Viessmann Gridbox Connector **Not an Official Viessmann Addon** _Fetch live data from your Viessmann Gridbox_ From b0027008f55bb789be4d0d6aa32d068c6be31316 Mon Sep 17 00:00:00 2001 From: unl0ck Date: Wed, 8 May 2024 21:59:19 +0200 Subject: [PATCH 08/20] Update config.yaml --- GridboxConnectorAddon/config.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/GridboxConnectorAddon/config.yaml b/GridboxConnectorAddon/config.yaml index 0764de5..98d72a7 100644 --- a/GridboxConnectorAddon/config.yaml +++ b/GridboxConnectorAddon/config.yaml @@ -1,5 +1,5 @@ # https://developers.home-assistant.io/docs/add-ons/configuration#add-on-config -name: Viessmann Gridbox Connector add-on +name: Viessmann Gridbox Connector version: "1.9.10" slug: "gridbox_connector" description: Fetch your live data from your Viessmann Gridbox From d0f83e05f82139cd0bcf18cb8361ea163841d816 Mon Sep 17 00:00:00 2001 From: Simon Helming Date: Thu, 9 May 2024 12:13:25 +0200 Subject: [PATCH 09/20] fix: wrong method --- GridboxConnectorAddon-dev/CHANGELOG.md | 6 ++++++ GridboxConnectorAddon-dev/GridboxConnector/__main__.py | 4 ++-- GridboxConnectorAddon-dev/cloudSettings.json | 2 +- GridboxConnectorAddon-dev/config.yaml | 2 +- 4 files changed, 10 insertions(+), 4 deletions(-) diff --git a/GridboxConnectorAddon-dev/CHANGELOG.md b/GridboxConnectorAddon-dev/CHANGELOG.md index 1deff21..d20b5e4 100644 --- a/GridboxConnectorAddon-dev/CHANGELOG.md +++ b/GridboxConnectorAddon-dev/CHANGELOG.md @@ -1,4 +1,10 @@ +## 1.9.12 + +## Fixed + +- Fixed Battery Sum set_state + ## 1.9.11 diff --git a/GridboxConnectorAddon-dev/GridboxConnector/__main__.py b/GridboxConnectorAddon-dev/GridboxConnector/__main__.py index 401d21b..63f24f5 100644 --- a/GridboxConnectorAddon-dev/GridboxConnector/__main__.py +++ b/GridboxConnectorAddon-dev/GridboxConnector/__main__.py @@ -138,7 +138,7 @@ capacity = float(measurement["battery"]["capacity"]) power = float(measurement["battery"]["power"]) remaining_charge = float(measurement["battery"]["remainingCharge"]) - battery_sum.set_values(state_of_charge, capacity, power, remaining_charge) + battery_sum.set_states(state_of_charge, capacity, power, remaining_charge) if "batteries" in measurement: for index, battery in enumerate(measurement["batteries"]): appliance_id = battery["applianceID"] @@ -149,6 +149,6 @@ capacity = float(measurement["battery"]["capacity"]) power = float(measurement["battery"]["power"]) remaining_charge = float(measurement["battery"]["remainingCharge"]) - battery.set_values(state_of_charge, capacity, power, remaining_charge) + battery.set_states(state_of_charge, capacity, power, remaining_charge) # Wait until fetch new values in seconds time.sleep(WAIT) diff --git a/GridboxConnectorAddon-dev/cloudSettings.json b/GridboxConnectorAddon-dev/cloudSettings.json index 1febb31..142a702 100644 --- a/GridboxConnectorAddon-dev/cloudSettings.json +++ b/GridboxConnectorAddon-dev/cloudSettings.json @@ -1,5 +1,5 @@ { - "version":"1.9.11", + "version":"1.9.12", "urls": { "login":"https://gridx.eu.auth0.com/oauth/token", "gateways":"https://api.gridx.de/gateways", diff --git a/GridboxConnectorAddon-dev/config.yaml b/GridboxConnectorAddon-dev/config.yaml index 3084a60..ade22f0 100644 --- a/GridboxConnectorAddon-dev/config.yaml +++ b/GridboxConnectorAddon-dev/config.yaml @@ -1,6 +1,6 @@ # https://developers.home-assistant.io/docs/add-ons/configuration#add-on-config name: Viessmann Gridbox Connector (dev) -version: "1.9.11" +version: "1.9.12" slug: "gridbox_connector_dev" description: Development version of Viessmann Gridbox Connector url: "https://github.com/unl0ck/homeassistant-addon-viessmann-gridbox/tree/main/GridboxConnectorAddon-dev" From e1da09a43ca7d534d7f6a0aaf57b3487e9e65cdc Mon Sep 17 00:00:00 2001 From: Simon Helming Date: Thu, 9 May 2024 20:13:02 +0200 Subject: [PATCH 10/20] release: release 1.9.12 to stable --- .gitignore | 3 ++ .../GridboxConnector/__main__.py | 2 +- GridboxConnectorAddon-dev/README.md | 9 ++++-- GridboxConnectorAddon/CHANGELOG.md | 12 +++++++ .../GridboxConnector/__main__.py | 31 +++++++++++++------ GridboxConnectorAddon/README.md | 7 ++++- GridboxConnectorAddon/cloudSettings.json | 2 +- copy_to_release.sh | 2 +- 8 files changed, 53 insertions(+), 15 deletions(-) create mode 100644 .gitignore diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..1dd97f7 --- /dev/null +++ b/.gitignore @@ -0,0 +1,3 @@ +__pycache__ +.pytest_cache +.history \ No newline at end of file diff --git a/GridboxConnectorAddon-dev/GridboxConnector/__main__.py b/GridboxConnectorAddon-dev/GridboxConnector/__main__.py index 63f24f5..b72a1e3 100644 --- a/GridboxConnectorAddon-dev/GridboxConnector/__main__.py +++ b/GridboxConnectorAddon-dev/GridboxConnector/__main__.py @@ -143,7 +143,7 @@ for index, battery in enumerate(measurement["batteries"]): appliance_id = battery["applianceID"] if appliance_id not in battery_dict: - battery_dict[appliance_id] = Battery(mqtt_settings, device_info, f"{index}", appliance_id) + battery_dict[appliance_id] = Battery(mqtt_settings, device_info, f"{index+1}", appliance_id) battery = battery_dict[appliance_id] state_of_charge = float(measurement["battery"]["stateOfCharge"])*100 capacity = float(measurement["battery"]["capacity"]) diff --git a/GridboxConnectorAddon-dev/README.md b/GridboxConnectorAddon-dev/README.md index 13cfb31..0e1a9f7 100644 --- a/GridboxConnectorAddon-dev/README.md +++ b/GridboxConnectorAddon-dev/README.md @@ -1,4 +1,4 @@ -# Viessmann Gridbox Add-on: Gridbox Connector add-on +# Viessmann Gridbox Connector **Not an Official Viessmann Addon** _Fetch live data from your Viessmann Gridbox_ @@ -15,7 +15,12 @@ _Fetch live data from your Viessmann Gridbox_ # Supported Values The Overview splitted in PV and Battery -## Battery +## Battery Summery +* power +* capacity +* stateOfCharge + +## Each Battery * power * capacity * stateOfCharge diff --git a/GridboxConnectorAddon/CHANGELOG.md b/GridboxConnectorAddon/CHANGELOG.md index 89f067a..d20b5e4 100644 --- a/GridboxConnectorAddon/CHANGELOG.md +++ b/GridboxConnectorAddon/CHANGELOG.md @@ -1,4 +1,16 @@ +## 1.9.12 + +## Fixed + +- Fixed Battery Sum set_state + + +## 1.9.11 + +## Fixed + +- Fixed Battery Sum ApplianceID ## 1.9.10 diff --git a/GridboxConnectorAddon/GridboxConnector/__main__.py b/GridboxConnectorAddon/GridboxConnector/__main__.py index b15caec..b72a1e3 100644 --- a/GridboxConnectorAddon/GridboxConnector/__main__.py +++ b/GridboxConnectorAddon/GridboxConnector/__main__.py @@ -4,7 +4,7 @@ from ha_mqtt_discoverable import Settings, DeviceInfo from ha_mqtt_discoverable.sensors import Sensor, SensorInfo from gridbox_connector import GridboxConnector - +from Battery import Battery if __name__ == '__main__': f = open('/build/cloudSettings.json') @@ -29,6 +29,8 @@ print(data["login"]) one_time_print = True + battery_dict = {} + mqtt_settings = Settings.MQTT(host=mqtt_server, username=mqtt_user, password=mqtt_pw) device_info = DeviceInfo(name="Viessmann Gridbox", identifiers="viessmann_gridbox", manufacturer="Viessmann", model="Vitocharge 2.0") @@ -86,10 +88,8 @@ grid_sensor = Sensor(grid_settings) photovoltaic_sensor = Sensor(photovoltaic_settings) - # Battery - battery_sum_level = Sensor(battery_settings_sum) - battery_sum_capacity = Sensor(battery_settings_capacity_sum) - battery_sum_power = Sensor(battery_settings_power_sum) + # Battery sum + battery_sum = Battery(mqtt_settings, device_info, "sum", "") # Consumption consumption_household_sensor = Sensor(consumption_household_settings) @@ -134,8 +134,21 @@ if "battery" in measurement: - battery_sum_level.set_state(float(measurement["battery"]["stateOfCharge"])*100) - battery_sum_capacity.set_state(float(measurement["battery"]["capacity"])) - battery_sum_power.set_state(float(measurement["battery"]["power"])) + state_of_charge = float(measurement["battery"]["stateOfCharge"])*100 + capacity = float(measurement["battery"]["capacity"]) + power = float(measurement["battery"]["power"]) + remaining_charge = float(measurement["battery"]["remainingCharge"]) + battery_sum.set_states(state_of_charge, capacity, power, remaining_charge) + if "batteries" in measurement: + for index, battery in enumerate(measurement["batteries"]): + appliance_id = battery["applianceID"] + if appliance_id not in battery_dict: + battery_dict[appliance_id] = Battery(mqtt_settings, device_info, f"{index+1}", appliance_id) + battery = battery_dict[appliance_id] + state_of_charge = float(measurement["battery"]["stateOfCharge"])*100 + capacity = float(measurement["battery"]["capacity"]) + power = float(measurement["battery"]["power"]) + remaining_charge = float(measurement["battery"]["remainingCharge"]) + battery.set_states(state_of_charge, capacity, power, remaining_charge) # Wait until fetch new values in seconds - time.sleep(WAIT) \ No newline at end of file + time.sleep(WAIT) diff --git a/GridboxConnectorAddon/README.md b/GridboxConnectorAddon/README.md index a013e5e..0e1a9f7 100644 --- a/GridboxConnectorAddon/README.md +++ b/GridboxConnectorAddon/README.md @@ -15,7 +15,12 @@ _Fetch live data from your Viessmann Gridbox_ # Supported Values The Overview splitted in PV and Battery -## Battery +## Battery Summery +* power +* capacity +* stateOfCharge + +## Each Battery * power * capacity * stateOfCharge diff --git a/GridboxConnectorAddon/cloudSettings.json b/GridboxConnectorAddon/cloudSettings.json index aa5b8c4..142a702 100644 --- a/GridboxConnectorAddon/cloudSettings.json +++ b/GridboxConnectorAddon/cloudSettings.json @@ -1,5 +1,5 @@ { - "version":"1.9.10", + "version":"1.9.12", "urls": { "login":"https://gridx.eu.auth0.com/oauth/token", "gateways":"https://api.gridx.de/gateways", diff --git a/copy_to_release.sh b/copy_to_release.sh index 4c70373..e3e0945 100755 --- a/copy_to_release.sh +++ b/copy_to_release.sh @@ -5,4 +5,4 @@ src_dir="GridboxConnectorAddon-dev" target_dir="GridboxConnectorAddon" # Copy all files from source to target directory, excluding config.yml and build.yml -rsync -av --exclude='config.yaml' --exclude='build.yaml' $src_dir/ $target_dir/ \ No newline at end of file +rsync -av --exclude='config.yaml' --exclude='build.yaml' --exclude='__pycache__' --exclude='.pytest_cache' $src_dir/ $target_dir/ \ No newline at end of file From fdd91ce1b76bc79af817f5be8cdeb826d26c49a7 Mon Sep 17 00:00:00 2001 From: Simon Helming Date: Thu, 9 May 2024 21:04:34 +0200 Subject: [PATCH 11/20] fix: set correct version number fixed #23 --- GridboxConnectorAddon/config.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/GridboxConnectorAddon/config.yaml b/GridboxConnectorAddon/config.yaml index 98d72a7..be5f6e1 100644 --- a/GridboxConnectorAddon/config.yaml +++ b/GridboxConnectorAddon/config.yaml @@ -1,6 +1,6 @@ # https://developers.home-assistant.io/docs/add-ons/configuration#add-on-config name: Viessmann Gridbox Connector -version: "1.9.10" +version: "1.9.12" slug: "gridbox_connector" description: Fetch your live data from your Viessmann Gridbox url: "https://github.com/unl0ck/homeassistant-addon-viessmann-gridbox/tree/main/GridboxConnectorAddon" From cc859338ee031e4454513b217953802a73977e8a Mon Sep 17 00:00:00 2001 From: Simon Helming Date: Thu, 9 May 2024 21:19:05 +0200 Subject: [PATCH 12/20] test: start with implement unit test --- .bumpversion-dev.toml | 2 +- .bumpversion.toml | 4 +-- .../GridboxConnector/main_test.py | 26 ++++++++++++++++ .../rootfs/share/cloudSettings.json | 31 ++++++++++--------- 4 files changed, 45 insertions(+), 18 deletions(-) create mode 100644 GridboxConnectorAddon-dev/GridboxConnector/main_test.py diff --git a/.bumpversion-dev.toml b/.bumpversion-dev.toml index bf69e3f..8d12942 100644 --- a/.bumpversion-dev.toml +++ b/.bumpversion-dev.toml @@ -18,4 +18,4 @@ commit_args = "" [[tool.bumpversion.files]] filename="./GridboxConnectorAddon-dev/config.yaml" [[tool.bumpversion.files]] -filename="./GridboxConnectorAddon-dev/cloudSettings.json" \ No newline at end of file +filename="./GridboxConnectorAddon-dev/rootfs/share/cloudSettings.json" \ No newline at end of file diff --git a/.bumpversion.toml b/.bumpversion.toml index 9cb984d..58df3d6 100644 --- a/.bumpversion.toml +++ b/.bumpversion.toml @@ -18,8 +18,8 @@ commit_args = "" [[tool.bumpversion.files]] filename="./GridboxConnectorAddon/config.yaml" [[tool.bumpversion.files]] -filename="./GridboxConnectorAddon/cloudSettings.json" +filename="./GridboxConnectorAddon/rootfs/share/cloudSettings.json" [[tool.bumpversion.files]] filename="./GridboxConnectorAddon-dev/config.yaml" [[tool.bumpversion.files]] -filename="./GridboxConnectorAddon-dev/cloudSettings.json" \ No newline at end of file +filename="./GridboxConnectorAddon-dev/rootfs/share/cloudSettings.json" \ No newline at end of file diff --git a/GridboxConnectorAddon-dev/GridboxConnector/main_test.py b/GridboxConnectorAddon-dev/GridboxConnector/main_test.py new file mode 100644 index 0000000..e97232d --- /dev/null +++ b/GridboxConnectorAddon-dev/GridboxConnector/main_test.py @@ -0,0 +1,26 @@ +import unittest +from unittest.mock import Mock, patch +from gridbox_connector import GridboxConnector +import __main__ + +mock_data = "{'batteries': [{'applianceID': '97af25d0-3791-48cc-857c-14aaac749267', 'capacity': 10000, 'nominalCapacity': 10000, 'power': -853, 'remainingCharge': 7700, 'stateOfCharge': 0.77}], 'battery': {'capacity': 10000, 'nominalCapacity': 10000, 'power': -853, 'remainingCharge': 7700, 'stateOfCharge': 0.77}, 'consumption': 600, 'directConsumption': 600, 'directConsumptionEV': 0, 'directConsumptionHeatPump': 0, 'directConsumptionHeater': 0, 'directConsumptionHousehold': 600, 'directConsumptionRate': 0.3968253968253968, 'grid': -59, 'gridMeterReadingNegative': 14081760000, 'gridMeterReadingPositive': 7393320000, 'measuredAt': '2024-05-08T09:42:18Z', 'photovoltaic': 1512, 'production': 1512, 'selfConsumption': 1453, 'selfConsumptionRate': 0.9609788359788359, 'selfSufficiencyRate': 1, 'selfSupply': 600, 'totalConsumption': 600}" +class TestGridboxConnectorMethods(unittest.TestCase): + + @patch.object(GridboxConnector, 'init_auth', return_value=None) + @patch.object(GridboxConnector, '__init__', return_value=None) + @patch.object(GridboxConnector, 'retrieve_live_data', return_value=mock_data) + def test_main(self,mock_retrieve_live_data, mock_init, mock_init_auth): + # Create an instance of the class + gridbox_connector = GridboxConnector(None) + + # Call the function + result = gridbox_connector.retrieve_live_data() + + # Assert the function was called once + mock_retrieve_live_data.assert_called_once() + + # Assert the function returned the mock value + self.assertEqual(result, mock_data) + +if __name__ == '__main__': + unittest.main() \ No newline at end of file diff --git a/GridboxConnectorAddon-dev/rootfs/share/cloudSettings.json b/GridboxConnectorAddon-dev/rootfs/share/cloudSettings.json index 7902744..e261922 100644 --- a/GridboxConnectorAddon-dev/rootfs/share/cloudSettings.json +++ b/GridboxConnectorAddon-dev/rootfs/share/cloudSettings.json @@ -1,16 +1,17 @@ { - "urls": { - "login":"https://gridx.eu.auth0.com/oauth/token", - "gateways":"https://api.gridx.de/gateways", - "live":"https://api.gridx.de/systems/{}/live" - }, - "login":{ - "grant_type":"http://auth0.com/oauth/grant-type/password-realm", - "username":"email", - "password":"password", - "audience":"my.gridx", - "client_id":"oZpr934Ikn8OZOHTJEcrgXkjio0I0Q7b", - "scope":"email openid", - "realm":"viessmann-authentication-db" - } - } \ No newline at end of file + "version": "1.9.12", + "urls": { + "login": "https://gridx.eu.auth0.com/oauth/token", + "gateways": "https://api.gridx.de/gateways", + "live": "https://api.gridx.de/systems/{}/live" + }, + "login": { + "grant_type": "http://auth0.com/oauth/grant-type/password-realm", + "username": "username", + "password": "password", + "audience": "my.gridx", + "client_id": "oZpr934Ikn8OZOHTJEcrgXkjio0I0Q7b", + "scope": "email openid", + "realm": "viessmann-authentication-db" + } +} \ No newline at end of file From bea9c5a1a768cd6eb50a9a7e38afeaa489fcf32f Mon Sep 17 00:00:00 2001 From: Simon Helming Date: Thu, 9 May 2024 23:32:08 +0200 Subject: [PATCH 13/20] fix: each batterie values added Classes for more structure and better testing --- .bumpversion-dev.toml | 4 +- GridboxConnectorAddon-dev/CHANGELOG.md | 56 +----- .../GridboxConnector/Battery.py | 34 ---- .../GridboxConnector/__main__.py | 135 ++------------ .../GridboxConnector/ha_viessmann_battery.py | 62 +++++++ .../ha_viessmann_gridbox_connector.py | 172 ++++++++++++++++++ .../GridboxConnector/main_test.py | 17 +- GridboxConnectorAddon-dev/cloudSettings.json | 17 -- GridboxConnectorAddon-dev/config.yaml | 2 +- .../rootfs/share/cloudSettings.json | 2 +- 10 files changed, 268 insertions(+), 233 deletions(-) delete mode 100644 GridboxConnectorAddon-dev/GridboxConnector/Battery.py create mode 100644 GridboxConnectorAddon-dev/GridboxConnector/ha_viessmann_battery.py create mode 100644 GridboxConnectorAddon-dev/GridboxConnector/ha_viessmann_gridbox_connector.py delete mode 100644 GridboxConnectorAddon-dev/cloudSettings.json diff --git a/.bumpversion-dev.toml b/.bumpversion-dev.toml index 8d12942..9227011 100644 --- a/.bumpversion-dev.toml +++ b/.bumpversion-dev.toml @@ -1,5 +1,5 @@ [tool.bumpversion] -current_version = "1.9.11" +current_version = "1.10.0" parse = "(?P\\d+)\\.(?P\\d+)\\.(?P\\d+)" serialize = ["{major}.{minor}.{patch}"] search = "{current_version}" @@ -11,7 +11,7 @@ tag = false sign_tags = false tag_name = "{new_version}" tag_message = "Bump version: {current_version} → {new_version}" -allow_dirty = false +allow_dirty = true commit = false message = "Bump version: {current_version} → {new_version}" commit_args = "" diff --git a/GridboxConnectorAddon-dev/CHANGELOG.md b/GridboxConnectorAddon-dev/CHANGELOG.md index d20b5e4..d5f0ba0 100644 --- a/GridboxConnectorAddon-dev/CHANGELOG.md +++ b/GridboxConnectorAddon-dev/CHANGELOG.md @@ -1,161 +1,123 @@ +## 1.10.0 +## Added +- Added new sensor `directConsumptionHousehold` and `directConsumptionHeatPump` to show the direct consumption of the household +- Added new sensor `totalConsumption` to show the total consumption of the household +- Added Classes for the sensor to start with unit tests +## Fixed +- Fixed the issue with the battery sum sensor +- Fixed the issue with the battery sum appliance id +- Fixed the issue with each battery show now correct values ## 1.9.12 - ## Fixed - - Fixed Battery Sum set_state - ## 1.9.11 - ## Fixed - - Fixed Battery Sum ApplianceID ## 1.9.10 - ## Fixed - - Revert to 1.5.0 maybe issue with Battery refactor code ## 1.9.9 - ### Added - - Consumption Sensor - Total Consumption Sensor ### Fixed - - Fixed version number - Fixed copy script from dev to main - Fixed config.yml ## 1.5.0 - ### Added - - Consumption Sensor - Total Consumption Sensor - ### Fixed - - set Value only if available ## 1.4.5 - ### Fixed - - Code issue ## 1.4.4 - ### Added - - mqtt settings ## 1.4.3 - ### Fixed - - Code issue ## 1.4.2 - ### Fixed - - Versionnumber ## 1.4.0 - ### Added - - Sensor directConsumptionHousehold - Sensor directConsumptionHeatPump - Use py-lib connector ## 1.3.0 - ### Fixed - - wrong code (never use github online editor) ### Added - - add Battery Power ## 1.2.0 - ### Fixed - - fixed casting battery stateOfCharge ### Added - - battery capacity ## 1.1.3 - ### Fixed - - use correct battery information ## 1.1.2 - - added Vendor ## 1.1.1 - ### Fixed - - use correct battery sensor_info ## 1.1.0 - - Start with Battery support ## 1.0.10 - - fixed python issue ## 1.0.9 - - added one time print of data ## 1.0.8 - - added dict check ## 1.0.7 - - added delay if response is error ## 1.0.6 - - fixed multiple generate id_token ## 1.0.5 - - added more logs ## 1.0.4 - - removed version string in code ## 1.0.3 - - added version string ## 1.0.2 - - added print to find out why not fetch id_token ## 1.0.1 - - fixed refresh Auth Token - Worked on the Documentation ## 1.0.0 - - Initial release - Added Mqtt Device Discovery diff --git a/GridboxConnectorAddon-dev/GridboxConnector/Battery.py b/GridboxConnectorAddon-dev/GridboxConnector/Battery.py deleted file mode 100644 index 2a936bf..0000000 --- a/GridboxConnectorAddon-dev/GridboxConnector/Battery.py +++ /dev/null @@ -1,34 +0,0 @@ -from ha_mqtt_discoverable.sensors import Sensor, SensorInfo -from ha_mqtt_discoverable import Settings - -class Battery: - def __init__(self, mqtt_settings, device_info, name, id): - self.id = id - self.name = name - self.device_info = device_info - self.mqtt_settings = mqtt_settings - - self.battery_sensor_info = SensorInfo(name=f"Battery {name} Level", device_class="battery", unique_id=f"gridbox_battery_{name}", device=device_info, unit_of_measurement="%") - self.battery_settings = Settings(mqtt=mqtt_settings, entity=self.battery_sensor_info) - self.battery_level = Sensor(self.battery_settings) - - self.battery_sensor_capacity = SensorInfo(name=f"Battery {name} Capacity", device_class="energy", unique_id=f"gridbox_battery_level_{name}", device=device_info, unit_of_measurement="Wh") - self.battery_settings_capacity = Settings(mqtt=mqtt_settings, entity=self.battery_sensor_capacity) - self.battery_capacity = Sensor(self.battery_settings_capacity) - - self.battery_sensor_power = SensorInfo(name=f"Battery {name} Power", device_class="battery", unique_id=f"gridbox_battery_power_{name}", device=device_info, unit_of_measurement="W") - self.battery_settings_power = Settings(mqtt=mqtt_settings, entity=self.battery_sensor_power) - self.battery_power = Sensor(self.battery_settings_power) - - self.battery_sensor_remaining_charge = SensorInfo(name=f"Battery {name} Remaining Charge", device_class="energy", unique_id=f"gridbox_remaining_charge_{name}", device=device_info, unit_of_measurement="Wh") - self.battery_settings_remaining_charge = Settings(mqtt=mqtt_settings, entity=self.battery_sensor_remaining_charge) - self.battery_remaining_charge = Sensor(self.battery_settings_remaining_charge) - - def get_name(self): - return self.name - - def set_states(self, level, capacity, power, remaining_charge): - self.battery_level.set_state(level) - self.battery_capacity.set_state(capacity) - self.battery_power.set_state(power) - self.battery_remaining_charge.set_state(remaining_charge) \ No newline at end of file diff --git a/GridboxConnectorAddon-dev/GridboxConnector/__main__.py b/GridboxConnectorAddon-dev/GridboxConnector/__main__.py index b72a1e3..7ba945e 100644 --- a/GridboxConnectorAddon-dev/GridboxConnector/__main__.py +++ b/GridboxConnectorAddon-dev/GridboxConnector/__main__.py @@ -1,10 +1,9 @@ import os import json import time -from ha_mqtt_discoverable import Settings, DeviceInfo -from ha_mqtt_discoverable.sensors import Sensor, SensorInfo from gridbox_connector import GridboxConnector -from Battery import Battery +from ha_mqtt_discoverable import Settings +from ha_viessmann_gridbox_connector import HAViessmannGridboxConnector if __name__ == '__main__': f = open('/build/cloudSettings.json') @@ -13,142 +12,30 @@ data = json.load(f) f.close() print("Start Viessmann Connector") - #print(f"====Version {data["version"]}====") + # print(f"====Version {data["version"]}====") options_file = open('/data/options.json') options_json = json.load(options_file) WAIT = int(options_json["wait_time"]) USER = os.getenv('USERNAME') PASSWORD = os.environ.get('PASSWORD') - mqtt_user = os.getenv('MqttUser') - mqtt_pw = os.getenv('MqttPw') - mqtt_server = os.getenv('MqttServer') - mqtt_port = os.getenv('MqttPort') + mqtt_user = os.getenv('MqttUser', "") + mqtt_pw = os.getenv('MqttPw', "") + mqtt_server = os.getenv('MqttServer', "") + mqtt_port = os.getenv('MqttPort', "") data["login"]["username"] = USER data["login"]["password"] = PASSWORD print(data["login"]) one_time_print = True - - battery_dict = {} - - mqtt_settings = Settings.MQTT(host=mqtt_server, username=mqtt_user, password=mqtt_pw) - - device_info = DeviceInfo(name="Viessmann Gridbox", identifiers="viessmann_gridbox", manufacturer="Viessmann", model="Vitocharge 2.0") - - production_sensor_info = SensorInfo(name="Production", device_class="power", unique_id="gridbox_production", device=device_info, unit_of_measurement="W") - production_settings = Settings(mqtt=mqtt_settings, entity=production_sensor_info) - - grid_sensor_info = SensorInfo(name="Grid", device_class="power", unique_id="gridbox_grid", device=device_info, unit_of_measurement="W") - grid_settings = Settings(mqtt=mqtt_settings, entity=grid_sensor_info) - - photovoltaic_sensor_info = SensorInfo(name="Photovoltaic", device_class="power", unique_id="gridbox_photovoltaic", device=device_info, unit_of_measurement="W") - photovoltaic_settings = Settings(mqtt=mqtt_settings, entity=photovoltaic_sensor_info) - - # consumption - consumption_household_sensor_info = SensorInfo(name="Consumption", device_class="power", unique_id="gridbox_consumption_household", device=device_info, unit_of_measurement="W") - consumption_household_settings = Settings(mqtt=mqtt_settings, entity=consumption_household_sensor_info) - - total_consumption_household_sensor_info = SensorInfo(name="Total Consumption", device_class="power", unique_id="total_consumption_household", device=device_info, unit_of_measurement="W") - total_consumption_household_settings = Settings(mqtt=mqtt_settings, entity=total_consumption_household_sensor_info) - - # Direct Consumption - direct_consumption_household_sensor_info = SensorInfo(name="DirectConsumptionHousehold", device_class="power", unique_id="gridbox_direct_consumption_household", device=device_info, unit_of_measurement="W") - direct_consumption_household_settings = Settings(mqtt=mqtt_settings, entity=direct_consumption_household_sensor_info) - - direct_consumption_heatpump_sensor_info = SensorInfo(name="DirectConsumptionHeatPump", device_class="power", unique_id="gridbox_direct_consumption_heatpump", device=device_info, unit_of_measurement="W") - direct_consumption_heatpump_settings = Settings(mqtt=mqtt_settings, entity=direct_consumption_heatpump_sensor_info) - - direct_consumption_rate_sensor_info = SensorInfo(name="DirectConsumptionRate", device_class="power_factor", unique_id="gridbox_direct_consumption_rate", device=device_info, unit_of_measurement="%") - direct_consumption_rate_settings = Settings(mqtt=mqtt_settings, entity=direct_consumption_rate_sensor_info) - - - # Self Consumption - self_supply_sensor_info = SensorInfo(name="SelfSupply", device_class="power", unique_id="gridbox_self_supply", device=device_info, unit_of_measurement="W") - self_supply_settings = Settings(mqtt=mqtt_settings, entity=self_supply_sensor_info) - - self_consumption_rate_sensor_info = SensorInfo(name="SelfConsumptionRate", device_class="power_factor", unique_id="gridbox_self_consumption_rate", device=device_info, unit_of_measurement="%") - self_consumption_rate_settings = Settings(mqtt=mqtt_settings, entity=self_consumption_rate_sensor_info) - - self_sufficiency_rate_sensor_info = SensorInfo(name="SelfSufficiencyRate", device_class="power_factor", unique_id="gridbox_self_sufficiency_rate", device=device_info, unit_of_measurement="%") - self_sufficiency_rate_settings = Settings(mqtt=mqtt_settings, entity=self_sufficiency_rate_sensor_info) - - - # Battery Section - battery_sensor_info_sum = SensorInfo(name="Battery Sum Level", device_class="battery", unique_id="gridbox_battery_sum", device=device_info, unit_of_measurement="%") - battery_settings_sum = Settings(mqtt=mqtt_settings, entity=battery_sensor_info_sum) - - battery_sensor_capacity_sum = SensorInfo(name="Battery Sum Capacity", device_class="energy", unique_id="gridbox_battery_level_sum", device=device_info, unit_of_measurement="Wh") - battery_settings_capacity_sum = Settings(mqtt=mqtt_settings, entity=battery_sensor_capacity_sum) - - battery_sensor_power_sum = SensorInfo(name="Battery Sum Power", device_class="battery", unique_id="gridbox_battery_power_sum", device=device_info, unit_of_measurement="W") - battery_settings_power_sum = Settings(mqtt=mqtt_settings, entity=battery_sensor_power_sum) - - # Instantiate the sensor - production_sensor = Sensor(production_settings) - grid_sensor = Sensor(grid_settings) - photovoltaic_sensor = Sensor(photovoltaic_settings) - - # Battery sum - battery_sum = Battery(mqtt_settings, device_info, "sum", "") - - # Consumption - consumption_household_sensor = Sensor(consumption_household_settings) - total_consumption_household_sensor = Sensor(total_consumption_household_settings) - direct_consumption_household_sensor = Sensor(direct_consumption_household_settings) - direct_consumtion_heatpump_sensor = Sensor(direct_consumption_heatpump_settings) - direct_consumtion_rate_sensor = Sensor(direct_consumption_rate_settings) - - self_supply_sensor = Sensor(self_supply_settings) - self_consumtion_rate_sensor = Sensor(self_consumption_rate_settings) - + mqtt_settings = Settings.MQTT( + host=mqtt_server, username=mqtt_user, password=mqtt_pw) + viessmann_gridbox_connector = HAViessmannGridboxConnector(mqtt_settings) gridboxConnector = GridboxConnector(data) while True: measurement = gridboxConnector.retrieve_live_data() + viessmann_gridbox_connector.update_sensors(measurement) if one_time_print: print(measurement) one_time_print = False - if "production" in measurement: - production_sensor.set_state(measurement["production"]) - if "grid" in measurement: - grid_sensor.set_state(measurement["grid"]) - if "photovoltaic" in measurement: - photovoltaic_sensor.set_state(measurement["photovoltaic"]) - if "consumption" in measurement: - consumption_household_sensor.set_state(measurement["consumption"]) - if "totalConsumption" in measurement: - total_consumption_household_sensor.set_state(measurement["totalConsumption"]) - if "directConsumptionHousehold" in measurement: - direct_consumption_household_sensor.set_state(float(measurement["directConsumptionHousehold"])) - if "directConsumptionHeatPump" in measurement: - direct_consumtion_heatpump_sensor.set_state(float(measurement["directConsumptionHeatPump"])) - if "directConsumptionRate" in measurement: - direct_consumtion_rate_sensor.set_state(float(measurement["directConsumptionRate"])*100) - - - if "selfSupply" in measurement: - self_supply_sensor.set_state(float(measurement["selfSupply"])) - if "selfConsumptionRate" in measurement: - self_consumtion_rate_sensor.set_state(float(measurement["selfConsumptionRate"])*100) - if "selfSufficiencyRate" in measurement: - self_consumtion_rate_sensor.set_state(float(measurement["selfSufficiencyRate"])*100) - - - if "battery" in measurement: - state_of_charge = float(measurement["battery"]["stateOfCharge"])*100 - capacity = float(measurement["battery"]["capacity"]) - power = float(measurement["battery"]["power"]) - remaining_charge = float(measurement["battery"]["remainingCharge"]) - battery_sum.set_states(state_of_charge, capacity, power, remaining_charge) - if "batteries" in measurement: - for index, battery in enumerate(measurement["batteries"]): - appliance_id = battery["applianceID"] - if appliance_id not in battery_dict: - battery_dict[appliance_id] = Battery(mqtt_settings, device_info, f"{index+1}", appliance_id) - battery = battery_dict[appliance_id] - state_of_charge = float(measurement["battery"]["stateOfCharge"])*100 - capacity = float(measurement["battery"]["capacity"]) - power = float(measurement["battery"]["power"]) - remaining_charge = float(measurement["battery"]["remainingCharge"]) - battery.set_states(state_of_charge, capacity, power, remaining_charge) # Wait until fetch new values in seconds time.sleep(WAIT) diff --git a/GridboxConnectorAddon-dev/GridboxConnector/ha_viessmann_battery.py b/GridboxConnectorAddon-dev/GridboxConnector/ha_viessmann_battery.py new file mode 100644 index 0000000..4e4430f --- /dev/null +++ b/GridboxConnectorAddon-dev/GridboxConnector/ha_viessmann_battery.py @@ -0,0 +1,62 @@ +from ha_mqtt_discoverable.sensors import Sensor, SensorInfo +from ha_mqtt_discoverable import Settings, DeviceInfo + + +class HAViessmannBattery: + """ +The Battery class represents a battery with associated sensors for level, capacity, power, and remaining charge. Each sensor is created as an MQTT entity with its own SensorInfo and Settings. + +Attributes: + id (str): The unique ID of the battery. + name (str): The name of the battery. + device_info (DeviceInfo): The device information of the battery. + mqtt_settings (Settings.MQTT): The MQTT settings for the sensors. + battery_level (Sensor): The sensor for the battery level. + battery_capacity (Sensor): The sensor for the battery capacity. + battery_power (Sensor): The sensor for the battery power. + battery_remaining_charge (Sensor): The sensor for the remaining battery charge. + +Methods: + get_name(): Returns the name of the battery. + set_states(level, capacity, power, remaining_charge): Sets the states of the four sensors. +""" + + def __init__(self, mqtt_settings, device_info, name, id): + self.id: str = id + self.name: str = name + self.device_info: DeviceInfo = device_info + self.mqtt_settings: Settings.MQTT = mqtt_settings + + self.battery_sensor_info = SensorInfo( + name=f"Battery {name} Level", device_class="battery", unique_id=f"gridbox_battery_{name}", device=device_info, unit_of_measurement="%") + self.battery_settings = Settings( + mqtt=mqtt_settings, entity=self.battery_sensor_info) + self.battery_level = Sensor(self.battery_settings) + + self.battery_sensor_capacity = SensorInfo( + name=f"Battery {name} Capacity", device_class="energy", unique_id=f"gridbox_battery_level_{name}", device=device_info, unit_of_measurement="Wh") + self.battery_settings_capacity = Settings( + mqtt=mqtt_settings, entity=self.battery_sensor_capacity) + self.battery_capacity = Sensor(self.battery_settings_capacity) + + self.battery_sensor_power = SensorInfo( + name=f"Battery {name} Power", device_class="battery", unique_id=f"gridbox_battery_power_{name}", device=device_info, unit_of_measurement="W") + self.battery_settings_power = Settings( + mqtt=mqtt_settings, entity=self.battery_sensor_power) + self.battery_power = Sensor(self.battery_settings_power) + + self.battery_sensor_remaining_charge = SensorInfo( + name=f"Battery {name} Remaining Charge", device_class="energy", unique_id=f"gridbox_remaining_charge_{name}", device=device_info, unit_of_measurement="Wh") + self.battery_settings_remaining_charge = Settings( + mqtt=mqtt_settings, entity=self.battery_sensor_remaining_charge) + self.battery_remaining_charge = Sensor( + self.battery_settings_remaining_charge) + + def get_name(self): + return self.name + + def set_states(self, level, capacity, power, remaining_charge): + self.battery_level.set_state(level) + self.battery_capacity.set_state(capacity) + self.battery_power.set_state(power) + self.battery_remaining_charge.set_state(remaining_charge) diff --git a/GridboxConnectorAddon-dev/GridboxConnector/ha_viessmann_gridbox_connector.py b/GridboxConnectorAddon-dev/GridboxConnector/ha_viessmann_gridbox_connector.py new file mode 100644 index 0000000..434145c --- /dev/null +++ b/GridboxConnectorAddon-dev/GridboxConnector/ha_viessmann_gridbox_connector.py @@ -0,0 +1,172 @@ +from ha_mqtt_discoverable import Settings, DeviceInfo +from ha_mqtt_discoverable.sensors import Sensor, SensorInfo +from ha_viessmann_battery import HAViessmannBattery + + +class HAViessmannGridboxConnector: + battery_sensor_dict: dict + mqtt_settings: Settings.MQTT + device_info: DeviceInfo + production_sensor: Sensor + grid_sensor: Sensor + photovoltaic_sensor: Sensor + consumption_household_sensor: Sensor + total_consumption_household_sensor: Sensor + direct_consumption_household_sensor: Sensor + direct_consumtion_heatpump_sensor: Sensor + direct_consumtion_rate_sensor: Sensor + self_supply_sensor: Sensor + self_consumtion_rate_sensor: Sensor + self_sufficiency_rate_sensor: Sensor + battery_sum: HAViessmannBattery + + def __init__(self, mqtt_settings): + self.battery_sensor_dict = {} + self.mqtt_settings = mqtt_settings + self.device_info = DeviceInfo( + name="Viessmann Gridbox", identifiers="viessmann_gridbox", manufacturer="Viessmann", model="Vitocharge 2.0") + + production_sensor_info = SensorInfo(name="Production", device_class="power", + unique_id="gridbox_production", device=self.device_info, unit_of_measurement="W") + production_settings = Settings( + mqtt=mqtt_settings, entity=production_sensor_info) + + grid_sensor_info = SensorInfo(name="Grid", device_class="power", + unique_id="gridbox_grid", device=self.device_info, unit_of_measurement="W") + grid_settings = Settings(mqtt=mqtt_settings, entity=grid_sensor_info) + + photovoltaic_sensor_info = SensorInfo(name="Photovoltaic", device_class="power", + unique_id="gridbox_photovoltaic", device=self.device_info, unit_of_measurement="W") + photovoltaic_settings = Settings( + mqtt=mqtt_settings, entity=photovoltaic_sensor_info) + + # consumption + consumption_household_sensor_info = SensorInfo( + name="Consumption", device_class="power", unique_id="gridbox_consumption_household", device=self.device_info, unit_of_measurement="W") + consumption_household_settings = Settings( + mqtt=mqtt_settings, entity=consumption_household_sensor_info) + + total_consumption_household_sensor_info = SensorInfo( + name="Total Consumption", device_class="power", unique_id="total_consumption_household", device=self.device_info, unit_of_measurement="W") + total_consumption_household_settings = Settings( + mqtt=mqtt_settings, entity=total_consumption_household_sensor_info) + + # Direct Consumption + direct_consumption_household_sensor_info = SensorInfo( + name="DirectConsumptionHousehold", device_class="power", unique_id="gridbox_direct_consumption_household", device=self.device_info, unit_of_measurement="W") + direct_consumption_household_settings = Settings( + mqtt=mqtt_settings, entity=direct_consumption_household_sensor_info) + + direct_consumption_heatpump_sensor_info = SensorInfo( + name="DirectConsumptionHeatPump", device_class="power", unique_id="gridbox_direct_consumption_heatpump", device=self.device_info, unit_of_measurement="W") + direct_consumption_heatpump_settings = Settings( + mqtt=mqtt_settings, entity=direct_consumption_heatpump_sensor_info) + + direct_consumption_rate_sensor_info = SensorInfo( + name="DirectConsumptionRate", device_class="power_factor", unique_id="gridbox_direct_consumption_rate", device=self.device_info, unit_of_measurement="%") + direct_consumption_rate_settings = Settings( + mqtt=mqtt_settings, entity=direct_consumption_rate_sensor_info) + + # Self Consumption + self_supply_sensor_info = SensorInfo(name="SelfSupply", device_class="power", + unique_id="gridbox_self_supply", device=self.device_info, unit_of_measurement="W") + self_supply_settings = Settings( + mqtt=mqtt_settings, entity=self_supply_sensor_info) + + self_consumption_rate_sensor_info = SensorInfo( + name="SelfConsumptionRate", device_class="power_factor", unique_id="gridbox_self_consumption_rate", device=self.device_info, unit_of_measurement="%") + self_consumption_rate_settings = Settings( + mqtt=mqtt_settings, entity=self_consumption_rate_sensor_info) + + self_sufficiency_rate_sensor_info = SensorInfo( + name="SelfSufficiencyRate", device_class="power_factor", unique_id="gridbox_self_sufficiency_rate", device=self.device_info, unit_of_measurement="%") + self_sufficiency_rate_settings = Settings( + mqtt=mqtt_settings, entity=self_sufficiency_rate_sensor_info) + + # Instantiate the sensors + + self.production_sensor = Sensor(production_settings) + self.grid_sensor = Sensor(grid_settings) + self.photovoltaic_sensor = Sensor(photovoltaic_settings) + + # Battery sum + self.battery_sum = HAViessmannBattery( + mqtt_settings, self.device_info, "sum", "") + + # Consumption + self.consumption_household_sensor = Sensor( + consumption_household_settings) + self.total_consumption_household_sensor = Sensor( + total_consumption_household_settings) + self.direct_consumption_household_sensor = Sensor( + direct_consumption_household_settings) + self.direct_consumtion_heatpump_sensor = Sensor( + direct_consumption_heatpump_settings) + self.direct_consumtion_rate_sensor = Sensor( + direct_consumption_rate_settings) + + self.self_supply_sensor = Sensor(self_supply_settings) + self.self_consumtion_rate_sensor = Sensor( + self_consumption_rate_settings) + self.self_sufficiency_rate_sensor = Sensor( + self_sufficiency_rate_settings) + + def update_sensors(self, measurement: dict): + if "production" in measurement: + self.production_sensor.set_state(measurement.get("production", "")) + if "grid" in measurement: + self.grid_sensor.set_state(measurement.get("grid", "")) + if "photovoltaic" in measurement: + self.photovoltaic_sensor.set_state( + measurement.get("photovoltaic", "")) + if "consumption" in measurement: + self.consumption_household_sensor.set_state( + measurement.get("consumption", "")) + if "totalConsumption" in measurement: + self.total_consumption_household_sensor.set_state( + measurement.get("totalConsumption", "")) + if "directConsumptionHousehold" in measurement: + self.direct_consumption_household_sensor.set_state( + float(measurement.get("directConsumptionHousehold", "0"))) + if "directConsumptionHeatPump" in measurement: + self.direct_consumtion_heatpump_sensor.set_state( + float(measurement.get("directConsumptionHeatPump", "0"))) + if "directConsumptionRate" in measurement: + self.direct_consumtion_rate_sensor.set_state( + float(measurement.get("directConsumptionRate", "0"))*100) + + if "selfSupply" in measurement: + self.self_supply_sensor.set_state( + float(measurement.get("selfSupply", ""))) + if "selfConsumptionRate" in measurement: + self.self_consumtion_rate_sensor.set_state( + float(measurement.get("selfConsumptionRate", "0"))*100) + if "selfSufficiencyRate" in measurement: + self.self_consumtion_rate_sensor.set_state( + float(measurement.get("selfSufficiencyRate", "0"))*100) + + if "battery" in measurement: + battery: dict = measurement.get("battery", {}) + state_of_charge = float( + battery.get("stateOfCharge", "0"))*100 + capacity = float(battery.get("capacity", "0")) + power = float(battery.get("power", "0")) + remaining_charge = float(battery.get("remainingCharge", "0")) + self.battery_sum.set_states( + state_of_charge, capacity, power, remaining_charge) + if "batteries" in measurement: + batteries: list = measurement.get("batteries", []) + for index, battery in enumerate(batteries): + appliance_id = battery.get("applianceID", "") + if appliance_id not in self.battery_sensor_dict: + self.battery_sensor_dict[appliance_id] = HAViessmannBattery( + self.mqtt_settings, self.device_info, f"{index+1}", appliance_id) + battery_sensor = self.battery_sensor_dict[appliance_id] + state_of_charge = float( + battery.get("stateOfCharge", "0"))*100 + capacity = float(battery.get("capacity", "0")) + power = float(battery.get("power", "0")) + remaining_charge = float( + battery.get("remainingCharge", "0")) + battery_sensor.set_states(state_of_charge, capacity, + power, remaining_charge) diff --git a/GridboxConnectorAddon-dev/GridboxConnector/main_test.py b/GridboxConnectorAddon-dev/GridboxConnector/main_test.py index e97232d..fdeff49 100644 --- a/GridboxConnectorAddon-dev/GridboxConnector/main_test.py +++ b/GridboxConnectorAddon-dev/GridboxConnector/main_test.py @@ -1,15 +1,17 @@ import unittest from unittest.mock import Mock, patch from gridbox_connector import GridboxConnector -import __main__ +import json mock_data = "{'batteries': [{'applianceID': '97af25d0-3791-48cc-857c-14aaac749267', 'capacity': 10000, 'nominalCapacity': 10000, 'power': -853, 'remainingCharge': 7700, 'stateOfCharge': 0.77}], 'battery': {'capacity': 10000, 'nominalCapacity': 10000, 'power': -853, 'remainingCharge': 7700, 'stateOfCharge': 0.77}, 'consumption': 600, 'directConsumption': 600, 'directConsumptionEV': 0, 'directConsumptionHeatPump': 0, 'directConsumptionHeater': 0, 'directConsumptionHousehold': 600, 'directConsumptionRate': 0.3968253968253968, 'grid': -59, 'gridMeterReadingNegative': 14081760000, 'gridMeterReadingPositive': 7393320000, 'measuredAt': '2024-05-08T09:42:18Z', 'photovoltaic': 1512, 'production': 1512, 'selfConsumption': 1453, 'selfConsumptionRate': 0.9609788359788359, 'selfSufficiencyRate': 1, 'selfSupply': 600, 'totalConsumption': 600}" + + class TestGridboxConnectorMethods(unittest.TestCase): - - @patch.object(GridboxConnector, 'init_auth', return_value=None) - @patch.object(GridboxConnector, '__init__', return_value=None) - @patch.object(GridboxConnector, 'retrieve_live_data', return_value=mock_data) - def test_main(self,mock_retrieve_live_data, mock_init, mock_init_auth): + + @ patch.object(GridboxConnector, 'init_auth', return_value=None) + @ patch.object(GridboxConnector, '__init__', return_value=None) + @ patch.object(GridboxConnector, 'retrieve_live_data', return_value=mock_data) + def test_main(self, mock_retrieve_live_data, mock_init, mock_init_auth): # Create an instance of the class gridbox_connector = GridboxConnector(None) @@ -22,5 +24,6 @@ def test_main(self,mock_retrieve_live_data, mock_init, mock_init_auth): # Assert the function returned the mock value self.assertEqual(result, mock_data) + if __name__ == '__main__': - unittest.main() \ No newline at end of file + unittest.main() diff --git a/GridboxConnectorAddon-dev/cloudSettings.json b/GridboxConnectorAddon-dev/cloudSettings.json deleted file mode 100644 index 142a702..0000000 --- a/GridboxConnectorAddon-dev/cloudSettings.json +++ /dev/null @@ -1,17 +0,0 @@ -{ - "version":"1.9.12", - "urls": { - "login":"https://gridx.eu.auth0.com/oauth/token", - "gateways":"https://api.gridx.de/gateways", - "live":"https://api.gridx.de/systems/{}/live" - }, - "login":{ - "grant_type": "http://auth0.com/oauth/grant-type/password-realm", - "username": "username", - "password": "password", - "audience": "my.gridx", - "client_id": "oZpr934Ikn8OZOHTJEcrgXkjio0I0Q7b", - "scope": "email openid", - "realm": "viessmann-authentication-db" -} - } diff --git a/GridboxConnectorAddon-dev/config.yaml b/GridboxConnectorAddon-dev/config.yaml index ade22f0..1818c45 100644 --- a/GridboxConnectorAddon-dev/config.yaml +++ b/GridboxConnectorAddon-dev/config.yaml @@ -1,6 +1,6 @@ # https://developers.home-assistant.io/docs/add-ons/configuration#add-on-config name: Viessmann Gridbox Connector (dev) -version: "1.9.12" +version: "1.10.0" slug: "gridbox_connector_dev" description: Development version of Viessmann Gridbox Connector url: "https://github.com/unl0ck/homeassistant-addon-viessmann-gridbox/tree/main/GridboxConnectorAddon-dev" diff --git a/GridboxConnectorAddon-dev/rootfs/share/cloudSettings.json b/GridboxConnectorAddon-dev/rootfs/share/cloudSettings.json index e261922..1bed16e 100644 --- a/GridboxConnectorAddon-dev/rootfs/share/cloudSettings.json +++ b/GridboxConnectorAddon-dev/rootfs/share/cloudSettings.json @@ -1,5 +1,5 @@ { - "version": "1.9.12", + "version": "1.10.0", "urls": { "login": "https://gridx.eu.auth0.com/oauth/token", "gateways": "https://api.gridx.de/gateways", From 5796a13e25fc9b85fca5474fa0def3a66b986f23 Mon Sep 17 00:00:00 2001 From: Simon Helming Date: Thu, 9 May 2024 23:43:04 +0200 Subject: [PATCH 14/20] fix: added missed dockerfile --- GridboxConnectorAddon-dev/cloudSettings.json | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) create mode 100644 GridboxConnectorAddon-dev/cloudSettings.json diff --git a/GridboxConnectorAddon-dev/cloudSettings.json b/GridboxConnectorAddon-dev/cloudSettings.json new file mode 100644 index 0000000..1bed16e --- /dev/null +++ b/GridboxConnectorAddon-dev/cloudSettings.json @@ -0,0 +1,17 @@ +{ + "version": "1.10.0", + "urls": { + "login": "https://gridx.eu.auth0.com/oauth/token", + "gateways": "https://api.gridx.de/gateways", + "live": "https://api.gridx.de/systems/{}/live" + }, + "login": { + "grant_type": "http://auth0.com/oauth/grant-type/password-realm", + "username": "username", + "password": "password", + "audience": "my.gridx", + "client_id": "oZpr934Ikn8OZOHTJEcrgXkjio0I0Q7b", + "scope": "email openid", + "realm": "viessmann-authentication-db" + } +} \ No newline at end of file From e70894bc7c26f18994dfe85c5809475761f8fea2 Mon Sep 17 00:00:00 2001 From: Simon Helming Date: Thu, 9 May 2024 23:44:25 +0200 Subject: [PATCH 15/20] ci: modified release script added cloudSettings.json --- .bumpversion-dev.toml | 2 ++ copy_to_release.sh | 8 +++++++- 2 files changed, 9 insertions(+), 1 deletion(-) diff --git a/.bumpversion-dev.toml b/.bumpversion-dev.toml index 9227011..a669cf2 100644 --- a/.bumpversion-dev.toml +++ b/.bumpversion-dev.toml @@ -18,4 +18,6 @@ commit_args = "" [[tool.bumpversion.files]] filename="./GridboxConnectorAddon-dev/config.yaml" [[tool.bumpversion.files]] +filename="./GridboxConnectorAddon-dev/cloudSettings.json" +[[tool.bumpversion.files]] filename="./GridboxConnectorAddon-dev/rootfs/share/cloudSettings.json" \ No newline at end of file diff --git a/copy_to_release.sh b/copy_to_release.sh index e3e0945..32b91af 100755 --- a/copy_to_release.sh +++ b/copy_to_release.sh @@ -5,4 +5,10 @@ src_dir="GridboxConnectorAddon-dev" target_dir="GridboxConnectorAddon" # Copy all files from source to target directory, excluding config.yml and build.yml -rsync -av --exclude='config.yaml' --exclude='build.yaml' --exclude='__pycache__' --exclude='.pytest_cache' $src_dir/ $target_dir/ \ No newline at end of file +rsync -av --exclude='config.yaml' --exclude='build.yaml' --exclude='__pycache__' --exclude='.pytest_cache' $src_dir/ $target_dir/ +# Read the current version from .bumpversion-dev.toml +current_version=$(jq -r '.version' GridboxConnectorAddon/rootfs/share/cloudSettings.json) + +# Update the version in the config.yaml file +sed -i '' "s/version: \".*\"/version: \"$current_version\"/" GridboxConnectorAddon/config.yaml + From baa95c7e9dba37067c3225656012c7bceeab0153 Mon Sep 17 00:00:00 2001 From: Simon Helming Date: Thu, 9 May 2024 23:46:13 +0200 Subject: [PATCH 16/20] release: version 1.10.1 --- .bumpversion-dev.toml | 2 +- GridboxConnectorAddon-dev/CHANGELOG.md | 2 +- GridboxConnectorAddon-dev/cloudSettings.json | 2 +- GridboxConnectorAddon-dev/config.yaml | 2 +- GridboxConnectorAddon-dev/rootfs/share/cloudSettings.json | 2 +- 5 files changed, 5 insertions(+), 5 deletions(-) diff --git a/.bumpversion-dev.toml b/.bumpversion-dev.toml index a669cf2..d402130 100644 --- a/.bumpversion-dev.toml +++ b/.bumpversion-dev.toml @@ -1,5 +1,5 @@ [tool.bumpversion] -current_version = "1.10.0" +current_version = "1.10.1" parse = "(?P\\d+)\\.(?P\\d+)\\.(?P\\d+)" serialize = ["{major}.{minor}.{patch}"] search = "{current_version}" diff --git a/GridboxConnectorAddon-dev/CHANGELOG.md b/GridboxConnectorAddon-dev/CHANGELOG.md index d5f0ba0..645b31c 100644 --- a/GridboxConnectorAddon-dev/CHANGELOG.md +++ b/GridboxConnectorAddon-dev/CHANGELOG.md @@ -1,5 +1,5 @@ -## 1.10.0 +## 1.10.1 ## Added - Added new sensor `directConsumptionHousehold` and `directConsumptionHeatPump` to show the direct consumption of the household - Added new sensor `totalConsumption` to show the total consumption of the household diff --git a/GridboxConnectorAddon-dev/cloudSettings.json b/GridboxConnectorAddon-dev/cloudSettings.json index 1bed16e..ed9b77d 100644 --- a/GridboxConnectorAddon-dev/cloudSettings.json +++ b/GridboxConnectorAddon-dev/cloudSettings.json @@ -1,5 +1,5 @@ { - "version": "1.10.0", + "version": "1.10.1", "urls": { "login": "https://gridx.eu.auth0.com/oauth/token", "gateways": "https://api.gridx.de/gateways", diff --git a/GridboxConnectorAddon-dev/config.yaml b/GridboxConnectorAddon-dev/config.yaml index 1818c45..47fa222 100644 --- a/GridboxConnectorAddon-dev/config.yaml +++ b/GridboxConnectorAddon-dev/config.yaml @@ -1,6 +1,6 @@ # https://developers.home-assistant.io/docs/add-ons/configuration#add-on-config name: Viessmann Gridbox Connector (dev) -version: "1.10.0" +version: "1.10.1" slug: "gridbox_connector_dev" description: Development version of Viessmann Gridbox Connector url: "https://github.com/unl0ck/homeassistant-addon-viessmann-gridbox/tree/main/GridboxConnectorAddon-dev" diff --git a/GridboxConnectorAddon-dev/rootfs/share/cloudSettings.json b/GridboxConnectorAddon-dev/rootfs/share/cloudSettings.json index 1bed16e..ed9b77d 100644 --- a/GridboxConnectorAddon-dev/rootfs/share/cloudSettings.json +++ b/GridboxConnectorAddon-dev/rootfs/share/cloudSettings.json @@ -1,5 +1,5 @@ { - "version": "1.10.0", + "version": "1.10.1", "urls": { "login": "https://gridx.eu.auth0.com/oauth/token", "gateways": "https://api.gridx.de/gateways", From 4d3ed4f53ffb92f721f38373c00aed941869f5ba Mon Sep 17 00:00:00 2001 From: Simon Helming Date: Fri, 10 May 2024 16:01:26 +0200 Subject: [PATCH 17/20] fix: wrong sensor used --- .bumpversion-dev.toml | 2 +- GridboxConnectorAddon-dev/CHANGELOG.md | 54 ++++++++++++++++++- .../ha_viessmann_gridbox_connector.py | 45 ++++++---------- .../GridboxConnector/main_test.py | 34 +++++++++--- .../mock_data/mock_data_with_batteries.json | 37 +++++++++++++ GridboxConnectorAddon-dev/cloudSettings.json | 2 +- GridboxConnectorAddon-dev/config.yaml | 2 +- .../rootfs/share/cloudSettings.json | 2 +- 8 files changed, 137 insertions(+), 41 deletions(-) create mode 100644 GridboxConnectorAddon-dev/GridboxConnector/tests/mock_data/mock_data_with_batteries.json diff --git a/.bumpversion-dev.toml b/.bumpversion-dev.toml index d402130..480297e 100644 --- a/.bumpversion-dev.toml +++ b/.bumpversion-dev.toml @@ -1,5 +1,5 @@ [tool.bumpversion] -current_version = "1.10.1" +current_version = "1.10.2" parse = "(?P\\d+)\\.(?P\\d+)\\.(?P\\d+)" serialize = ["{major}.{minor}.{patch}"] search = "{current_version}" diff --git a/GridboxConnectorAddon-dev/CHANGELOG.md b/GridboxConnectorAddon-dev/CHANGELOG.md index 645b31c..cb23d4d 100644 --- a/GridboxConnectorAddon-dev/CHANGELOG.md +++ b/GridboxConnectorAddon-dev/CHANGELOG.md @@ -1,123 +1,175 @@ -## 1.10.1 + +## 1.10.2 + ## Added + - Added new sensor `directConsumptionHousehold` and `directConsumptionHeatPump` to show the direct consumption of the household - Added new sensor `totalConsumption` to show the total consumption of the household - Added Classes for the sensor to start with unit tests + ## Fixed + - Fixed the issue with the battery sum sensor - Fixed the issue with the battery sum appliance id - Fixed the issue with each battery show now correct values + ## 1.9.12 + ## Fixed + - Fixed Battery Sum set_state ## 1.9.11 + ## Fixed + - Fixed Battery Sum ApplianceID ## 1.9.10 + ## Fixed + - Revert to 1.5.0 maybe issue with Battery refactor code ## 1.9.9 + ### Added + - Consumption Sensor - Total Consumption Sensor ### Fixed + - Fixed version number - Fixed copy script from dev to main - Fixed config.yml ## 1.5.0 + ### Added + - Consumption Sensor - Total Consumption Sensor + ### Fixed + - set Value only if available ## 1.4.5 + ### Fixed + - Code issue ## 1.4.4 + ### Added + - mqtt settings ## 1.4.3 + ### Fixed + - Code issue ## 1.4.2 + ### Fixed + - Versionnumber ## 1.4.0 + ### Added + - Sensor directConsumptionHousehold - Sensor directConsumptionHeatPump - Use py-lib connector ## 1.3.0 + ### Fixed + - wrong code (never use github online editor) ### Added + - add Battery Power ## 1.2.0 + ### Fixed + - fixed casting battery stateOfCharge ### Added + - battery capacity ## 1.1.3 + ### Fixed + - use correct battery information ## 1.1.2 + - added Vendor ## 1.1.1 + ### Fixed + - use correct battery sensor_info ## 1.1.0 + - Start with Battery support ## 1.0.10 + - fixed python issue ## 1.0.9 + - added one time print of data ## 1.0.8 + - added dict check ## 1.0.7 + - added delay if response is error ## 1.0.6 + - fixed multiple generate id_token ## 1.0.5 + - added more logs ## 1.0.4 + - removed version string in code ## 1.0.3 + - added version string ## 1.0.2 + - added print to find out why not fetch id_token ## 1.0.1 + - fixed refresh Auth Token - Worked on the Documentation ## 1.0.0 + - Initial release - Added Mqtt Device Discovery diff --git a/GridboxConnectorAddon-dev/GridboxConnector/ha_viessmann_gridbox_connector.py b/GridboxConnectorAddon-dev/GridboxConnector/ha_viessmann_gridbox_connector.py index 434145c..57c99d8 100644 --- a/GridboxConnectorAddon-dev/GridboxConnector/ha_viessmann_gridbox_connector.py +++ b/GridboxConnectorAddon-dev/GridboxConnector/ha_viessmann_gridbox_connector.py @@ -117,56 +117,41 @@ def update_sensors(self, measurement: dict): if "grid" in measurement: self.grid_sensor.set_state(measurement.get("grid", "")) if "photovoltaic" in measurement: - self.photovoltaic_sensor.set_state( - measurement.get("photovoltaic", "")) + self.photovoltaic_sensor.set_state(measurement.get("photovoltaic", "")) if "consumption" in measurement: - self.consumption_household_sensor.set_state( - measurement.get("consumption", "")) + self.consumption_household_sensor.set_state(measurement.get("consumption", "")) if "totalConsumption" in measurement: - self.total_consumption_household_sensor.set_state( - measurement.get("totalConsumption", "")) + self.total_consumption_household_sensor.set_state(measurement.get("totalConsumption", "")) if "directConsumptionHousehold" in measurement: - self.direct_consumption_household_sensor.set_state( - float(measurement.get("directConsumptionHousehold", "0"))) + self.direct_consumption_household_sensor.set_state(float(measurement.get("directConsumptionHousehold", "0"))) if "directConsumptionHeatPump" in measurement: - self.direct_consumtion_heatpump_sensor.set_state( - float(measurement.get("directConsumptionHeatPump", "0"))) + self.direct_consumtion_heatpump_sensor.set_state(float(measurement.get("directConsumptionHeatPump", "0"))) if "directConsumptionRate" in measurement: - self.direct_consumtion_rate_sensor.set_state( - float(measurement.get("directConsumptionRate", "0"))*100) + self.direct_consumtion_rate_sensor.set_state(float(measurement.get("directConsumptionRate", "0"))*100) if "selfSupply" in measurement: - self.self_supply_sensor.set_state( - float(measurement.get("selfSupply", ""))) + self.self_supply_sensor.set_state(float(measurement.get("selfSupply", ""))) if "selfConsumptionRate" in measurement: - self.self_consumtion_rate_sensor.set_state( - float(measurement.get("selfConsumptionRate", "0"))*100) + self.self_consumtion_rate_sensor.set_state(float(measurement.get("selfConsumptionRate", "0"))*100) if "selfSufficiencyRate" in measurement: - self.self_consumtion_rate_sensor.set_state( - float(measurement.get("selfSufficiencyRate", "0"))*100) + self.self_sufficiency_rate_sensor.set_state(float(measurement.get("selfSufficiencyRate", "0"))*100) if "battery" in measurement: battery: dict = measurement.get("battery", {}) - state_of_charge = float( - battery.get("stateOfCharge", "0"))*100 + state_of_charge = float(battery.get("stateOfCharge", "0"))*100 capacity = float(battery.get("capacity", "0")) power = float(battery.get("power", "0")) remaining_charge = float(battery.get("remainingCharge", "0")) - self.battery_sum.set_states( - state_of_charge, capacity, power, remaining_charge) + self.battery_sum.set_states(state_of_charge, capacity, power, remaining_charge) if "batteries" in measurement: batteries: list = measurement.get("batteries", []) for index, battery in enumerate(batteries): appliance_id = battery.get("applianceID", "") if appliance_id not in self.battery_sensor_dict: - self.battery_sensor_dict[appliance_id] = HAViessmannBattery( - self.mqtt_settings, self.device_info, f"{index+1}", appliance_id) + self.battery_sensor_dict[appliance_id] = HAViessmannBattery(self.mqtt_settings, self.device_info, f"{index+1}", appliance_id) battery_sensor = self.battery_sensor_dict[appliance_id] - state_of_charge = float( - battery.get("stateOfCharge", "0"))*100 + state_of_charge = float(battery.get("stateOfCharge", "0"))*100 capacity = float(battery.get("capacity", "0")) power = float(battery.get("power", "0")) - remaining_charge = float( - battery.get("remainingCharge", "0")) - battery_sensor.set_states(state_of_charge, capacity, - power, remaining_charge) + remaining_charge = float(battery.get("remainingCharge", "0")) + battery_sensor.set_states(state_of_charge, capacity, power, remaining_charge) diff --git a/GridboxConnectorAddon-dev/GridboxConnector/main_test.py b/GridboxConnectorAddon-dev/GridboxConnector/main_test.py index fdeff49..9029956 100644 --- a/GridboxConnectorAddon-dev/GridboxConnector/main_test.py +++ b/GridboxConnectorAddon-dev/GridboxConnector/main_test.py @@ -2,16 +2,26 @@ from unittest.mock import Mock, patch from gridbox_connector import GridboxConnector import json +from ha_mqtt_discoverable import Settings +from ha_viessmann_gridbox_connector import HAViessmannGridboxConnector +from paho.mqtt.client import MQTT_ERR_SUCCESS +from ha_mqtt_discoverable.sensors import Sensor mock_data = "{'batteries': [{'applianceID': '97af25d0-3791-48cc-857c-14aaac749267', 'capacity': 10000, 'nominalCapacity': 10000, 'power': -853, 'remainingCharge': 7700, 'stateOfCharge': 0.77}], 'battery': {'capacity': 10000, 'nominalCapacity': 10000, 'power': -853, 'remainingCharge': 7700, 'stateOfCharge': 0.77}, 'consumption': 600, 'directConsumption': 600, 'directConsumptionEV': 0, 'directConsumptionHeatPump': 0, 'directConsumptionHeater': 0, 'directConsumptionHousehold': 600, 'directConsumptionRate': 0.3968253968253968, 'grid': -59, 'gridMeterReadingNegative': 14081760000, 'gridMeterReadingPositive': 7393320000, 'measuredAt': '2024-05-08T09:42:18Z', 'photovoltaic': 1512, 'production': 1512, 'selfConsumption': 1453, 'selfConsumptionRate': 0.9609788359788359, 'selfSufficiencyRate': 1, 'selfSupply': 600, 'totalConsumption': 600}" class TestGridboxConnectorMethods(unittest.TestCase): - @ patch.object(GridboxConnector, 'init_auth', return_value=None) - @ patch.object(GridboxConnector, '__init__', return_value=None) - @ patch.object(GridboxConnector, 'retrieve_live_data', return_value=mock_data) - def test_main(self, mock_retrieve_live_data, mock_init, mock_init_auth): + @patch('paho.mqtt.client.Client') + @patch.object(GridboxConnector, 'init_auth', return_value=None) + @patch.object(GridboxConnector, '__init__', return_value=None) + @patch.object(GridboxConnector, 'retrieve_live_data') + def test_main(self, mock_retrieve_live_data, mock_init, mock_init_auth,mock_mqtt_client): + # Load mock data from JSON file + with open('tests/mock_data/mock_data_with_batteries.json') as f: + mock_data = json.load(f) + mock_mqtt_client.return_value.connect.return_value = MQTT_ERR_SUCCESS + mock_retrieve_live_data.return_value = mock_data # Create an instance of the class gridbox_connector = GridboxConnector(None) @@ -23,7 +33,19 @@ def test_main(self, mock_retrieve_live_data, mock_init, mock_init_auth): # Assert the function returned the mock value self.assertEqual(result, mock_data) - - + mqtt_server = "mqtt_server" + mqtt_user = "mqtt_user" + mqtt_pw = "mqtt_pw" + mqtt_settings = Settings.MQTT( + host=mqtt_server, username=mqtt_user, password=mqtt_pw) + viessmann_gridbox_connector = HAViessmannGridboxConnector( + mqtt_settings) + + with patch.object(viessmann_gridbox_connector.self_supply_sensor, 'set_state') as mock_self_supply_sensor, \ + patch.object(viessmann_gridbox_connector.self_consumtion_rate_sensor, 'set_state') as mock_self_consumtion_rate_sensor: + viessmann_gridbox_connector.update_sensors(result) + mock_self_supply_sensor.assert_called_once_with(600.0) + mock_self_consumtion_rate_sensor.assert_called_once_with(96.09788359788359) + if __name__ == '__main__': unittest.main() diff --git a/GridboxConnectorAddon-dev/GridboxConnector/tests/mock_data/mock_data_with_batteries.json b/GridboxConnectorAddon-dev/GridboxConnector/tests/mock_data/mock_data_with_batteries.json new file mode 100644 index 0000000..566ffdf --- /dev/null +++ b/GridboxConnectorAddon-dev/GridboxConnector/tests/mock_data/mock_data_with_batteries.json @@ -0,0 +1,37 @@ +{ + "batteries": [ + { + "applianceID": "97af25d0-3791-48cc-857c-14aaac749267", + "capacity": 10000, + "nominalCapacity": 10000, + "power": -853, + "remainingCharge": 7700, + "stateOfCharge": 0.77 + } + ], + "battery": { + "capacity": 10000, + "nominalCapacity": 10000, + "power": -853, + "remainingCharge": 7700, + "stateOfCharge": 0.77 + }, + "consumption": 600, + "directConsumption": 600, + "directConsumptionEV": 0, + "directConsumptionHeatPump": 0, + "directConsumptionHeater": 0, + "directConsumptionHousehold": 600, + "directConsumptionRate": 0.3968253968253968, + "grid": -59, + "gridMeterReadingNegative": 14081760000, + "gridMeterReadingPositive": 7393320000, + "measuredAt": "2024-05-08T09: 42: 18Z", + "photovoltaic": 1512, + "production": 1512, + "selfConsumption": 1453, + "selfConsumptionRate": 0.9609788359788359, + "selfSufficiencyRate": 1, + "selfSupply": 600, + "totalConsumption": 600 +} diff --git a/GridboxConnectorAddon-dev/cloudSettings.json b/GridboxConnectorAddon-dev/cloudSettings.json index ed9b77d..93d420f 100644 --- a/GridboxConnectorAddon-dev/cloudSettings.json +++ b/GridboxConnectorAddon-dev/cloudSettings.json @@ -1,5 +1,5 @@ { - "version": "1.10.1", + "version": "1.10.2", "urls": { "login": "https://gridx.eu.auth0.com/oauth/token", "gateways": "https://api.gridx.de/gateways", diff --git a/GridboxConnectorAddon-dev/config.yaml b/GridboxConnectorAddon-dev/config.yaml index 47fa222..23c7f42 100644 --- a/GridboxConnectorAddon-dev/config.yaml +++ b/GridboxConnectorAddon-dev/config.yaml @@ -1,6 +1,6 @@ # https://developers.home-assistant.io/docs/add-ons/configuration#add-on-config name: Viessmann Gridbox Connector (dev) -version: "1.10.1" +version: "1.10.2" slug: "gridbox_connector_dev" description: Development version of Viessmann Gridbox Connector url: "https://github.com/unl0ck/homeassistant-addon-viessmann-gridbox/tree/main/GridboxConnectorAddon-dev" diff --git a/GridboxConnectorAddon-dev/rootfs/share/cloudSettings.json b/GridboxConnectorAddon-dev/rootfs/share/cloudSettings.json index ed9b77d..93d420f 100644 --- a/GridboxConnectorAddon-dev/rootfs/share/cloudSettings.json +++ b/GridboxConnectorAddon-dev/rootfs/share/cloudSettings.json @@ -1,5 +1,5 @@ { - "version": "1.10.1", + "version": "1.10.2", "urls": { "login": "https://gridx.eu.auth0.com/oauth/token", "gateways": "https://api.gridx.de/gateways", From 4afffe573f44c475db8aff79eeb58fa1010507f2 Mon Sep 17 00:00:00 2001 From: Simon Helming Date: Fri, 10 May 2024 23:01:43 +0200 Subject: [PATCH 18/20] feat: added experimental --- .../CHANGELOG.md | 175 ++++++++++++++++++ GridboxConnectorAddon-experimental/DOCS.md | 13 ++ GridboxConnectorAddon-experimental/Dockerfile | 27 +++ .../GridboxConnector/__init__.py | 0 .../GridboxConnector/__main__.py | 41 ++++ .../GridboxConnector/ha_viessmann_battery.py | 62 +++++++ .../ha_viessmann_gridbox_connector.py | 157 ++++++++++++++++ .../GridboxConnector/main_test.py | 61 ++++++ .../GridboxConnector/requirements.txt | 3 + .../mock_data/mock_data_with_batteries.json | 37 ++++ GridboxConnectorAddon-experimental/README.md | 39 ++++ .../apparmor.txt | 57 ++++++ GridboxConnectorAddon-experimental/build.yaml | 13 ++ .../cloudSettings.json | 17 ++ .../config.yaml | 33 ++++ .../etc/services.d/gridboxconnector/finish | 15 ++ .../etc/services.d/gridboxconnector/run | 19 ++ .../rootfs/share/cloudSettings.json | 17 ++ .../rootfs/usr/bin/gridboxconnector | 20 ++ GridboxConnectorAddon-experimental/run.sh | 19 ++ .../translations/en.yaml | 10 + 21 files changed, 835 insertions(+) create mode 100644 GridboxConnectorAddon-experimental/CHANGELOG.md create mode 100644 GridboxConnectorAddon-experimental/DOCS.md create mode 100644 GridboxConnectorAddon-experimental/Dockerfile create mode 100644 GridboxConnectorAddon-experimental/GridboxConnector/__init__.py create mode 100644 GridboxConnectorAddon-experimental/GridboxConnector/__main__.py create mode 100644 GridboxConnectorAddon-experimental/GridboxConnector/ha_viessmann_battery.py create mode 100644 GridboxConnectorAddon-experimental/GridboxConnector/ha_viessmann_gridbox_connector.py create mode 100644 GridboxConnectorAddon-experimental/GridboxConnector/main_test.py create mode 100644 GridboxConnectorAddon-experimental/GridboxConnector/requirements.txt create mode 100644 GridboxConnectorAddon-experimental/GridboxConnector/tests/mock_data/mock_data_with_batteries.json create mode 100644 GridboxConnectorAddon-experimental/README.md create mode 100644 GridboxConnectorAddon-experimental/apparmor.txt create mode 100644 GridboxConnectorAddon-experimental/build.yaml create mode 100644 GridboxConnectorAddon-experimental/cloudSettings.json create mode 100644 GridboxConnectorAddon-experimental/config.yaml create mode 100755 GridboxConnectorAddon-experimental/rootfs/etc/services.d/gridboxconnector/finish create mode 100755 GridboxConnectorAddon-experimental/rootfs/etc/services.d/gridboxconnector/run create mode 100644 GridboxConnectorAddon-experimental/rootfs/share/cloudSettings.json create mode 100755 GridboxConnectorAddon-experimental/rootfs/usr/bin/gridboxconnector create mode 100644 GridboxConnectorAddon-experimental/run.sh create mode 100644 GridboxConnectorAddon-experimental/translations/en.yaml diff --git a/GridboxConnectorAddon-experimental/CHANGELOG.md b/GridboxConnectorAddon-experimental/CHANGELOG.md new file mode 100644 index 0000000..cb23d4d --- /dev/null +++ b/GridboxConnectorAddon-experimental/CHANGELOG.md @@ -0,0 +1,175 @@ + + +## 1.10.2 + +## Added + +- Added new sensor `directConsumptionHousehold` and `directConsumptionHeatPump` to show the direct consumption of the household +- Added new sensor `totalConsumption` to show the total consumption of the household +- Added Classes for the sensor to start with unit tests + +## Fixed + +- Fixed the issue with the battery sum sensor +- Fixed the issue with the battery sum appliance id +- Fixed the issue with each battery show now correct values + +## 1.9.12 + +## Fixed + +- Fixed Battery Sum set_state + +## 1.9.11 + +## Fixed + +- Fixed Battery Sum ApplianceID + +## 1.9.10 + +## Fixed + +- Revert to 1.5.0 maybe issue with Battery refactor code + +## 1.9.9 + +### Added + +- Consumption Sensor +- Total Consumption Sensor + +### Fixed + +- Fixed version number +- Fixed copy script from dev to main +- Fixed config.yml + +## 1.5.0 + +### Added + +- Consumption Sensor +- Total Consumption Sensor + +### Fixed + +- set Value only if available + +## 1.4.5 + +### Fixed + +- Code issue + +## 1.4.4 + +### Added + +- mqtt settings + +## 1.4.3 + +### Fixed + +- Code issue + +## 1.4.2 + +### Fixed + +- Versionnumber + +## 1.4.0 + +### Added + +- Sensor directConsumptionHousehold +- Sensor directConsumptionHeatPump +- Use py-lib connector + +## 1.3.0 + +### Fixed + +- wrong code (never use github online editor) + +### Added + +- add Battery Power + +## 1.2.0 + +### Fixed + +- fixed casting battery stateOfCharge + +### Added + +- battery capacity + +## 1.1.3 + +### Fixed + +- use correct battery information + +## 1.1.2 + +- added Vendor + +## 1.1.1 + +### Fixed + +- use correct battery sensor_info + +## 1.1.0 + +- Start with Battery support + +## 1.0.10 + +- fixed python issue + +## 1.0.9 + +- added one time print of data + +## 1.0.8 + +- added dict check + +## 1.0.7 + +- added delay if response is error + +## 1.0.6 + +- fixed multiple generate id_token + +## 1.0.5 + +- added more logs + +## 1.0.4 + +- removed version string in code + +## 1.0.3 + +- added version string + +## 1.0.2 + +- added print to find out why not fetch id_token + +## 1.0.1 + +- fixed refresh Auth Token +- Worked on the Documentation + +## 1.0.0 + +- Initial release +- Added Mqtt Device Discovery diff --git a/GridboxConnectorAddon-experimental/DOCS.md b/GridboxConnectorAddon-experimental/DOCS.md new file mode 100644 index 0000000..b3bbfa1 --- /dev/null +++ b/GridboxConnectorAddon-experimental/DOCS.md @@ -0,0 +1,13 @@ +# Home Assistant Add-on: GridboxConnector +Fetch your Energy data from the Viessmann Gridbox Cloud +## How to use + +### Configuration +Enter your Gridbox Credentials in the Configuration +use your credentials from the Viessmann **myGridbox** App or from the Viessmann Gridbox Webseite https://mygridbox.viessmann.com/login +```yml +username: email +password: password +wait_time: timeout when will refresh +``` +_Remember you have to restart the Addon after changed the Credentials_ diff --git a/GridboxConnectorAddon-experimental/Dockerfile b/GridboxConnectorAddon-experimental/Dockerfile new file mode 100644 index 0000000..48fbae2 --- /dev/null +++ b/GridboxConnectorAddon-experimental/Dockerfile @@ -0,0 +1,27 @@ +# https://developers.home-assistant.io/docs/add-ons/configuration#add-on-dockerfile +ARG BUILD_FROM +FROM $BUILD_FROM +LABEL org.opencontainers.image.source https://github.com/unl0ck/homeassistant-addon-viessmann-gridbox +RUN \ + apk add --no-cache \ + python3 py3-pip +RUN ln -sf python3 /usr/bin/python +COPY rootfs / +#WORKDIR /data + +# Execute during the build of the image +ARG TEMPIO_VERSION BUILD_ARCH +RUN \ + curl -sSLf -o /usr/bin/tempio \ + "https://github.com/home-assistant/tempio/releases/download/${TEMPIO_VERSION}/tempio_${BUILD_ARCH}" + +# Copy root filesystem +COPY GridboxConnector/ /build/GridboxConnector +COPY cloudSettings.json /data/cloudSettings.json +COPY cloudSettings.json /build/. +WORKDIR /build/GridboxConnector +RUN pip install -r requirements.txt +COPY run.sh /run.sh +RUN chmod a+x /run.sh + +CMD [ "/run.sh" ] diff --git a/GridboxConnectorAddon-experimental/GridboxConnector/__init__.py b/GridboxConnectorAddon-experimental/GridboxConnector/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/GridboxConnectorAddon-experimental/GridboxConnector/__main__.py b/GridboxConnectorAddon-experimental/GridboxConnector/__main__.py new file mode 100644 index 0000000..7ba945e --- /dev/null +++ b/GridboxConnectorAddon-experimental/GridboxConnector/__main__.py @@ -0,0 +1,41 @@ +import os +import json +import time +from gridbox_connector import GridboxConnector +from ha_mqtt_discoverable import Settings +from ha_viessmann_gridbox_connector import HAViessmannGridboxConnector + +if __name__ == '__main__': + f = open('/build/cloudSettings.json') + # returns JSON object as + # a dictionary + data = json.load(f) + f.close() + print("Start Viessmann Connector") + # print(f"====Version {data["version"]}====") + + options_file = open('/data/options.json') + options_json = json.load(options_file) + WAIT = int(options_json["wait_time"]) + USER = os.getenv('USERNAME') + PASSWORD = os.environ.get('PASSWORD') + mqtt_user = os.getenv('MqttUser', "") + mqtt_pw = os.getenv('MqttPw', "") + mqtt_server = os.getenv('MqttServer', "") + mqtt_port = os.getenv('MqttPort', "") + data["login"]["username"] = USER + data["login"]["password"] = PASSWORD + print(data["login"]) + one_time_print = True + mqtt_settings = Settings.MQTT( + host=mqtt_server, username=mqtt_user, password=mqtt_pw) + viessmann_gridbox_connector = HAViessmannGridboxConnector(mqtt_settings) + gridboxConnector = GridboxConnector(data) + while True: + measurement = gridboxConnector.retrieve_live_data() + viessmann_gridbox_connector.update_sensors(measurement) + if one_time_print: + print(measurement) + one_time_print = False + # Wait until fetch new values in seconds + time.sleep(WAIT) diff --git a/GridboxConnectorAddon-experimental/GridboxConnector/ha_viessmann_battery.py b/GridboxConnectorAddon-experimental/GridboxConnector/ha_viessmann_battery.py new file mode 100644 index 0000000..4e4430f --- /dev/null +++ b/GridboxConnectorAddon-experimental/GridboxConnector/ha_viessmann_battery.py @@ -0,0 +1,62 @@ +from ha_mqtt_discoverable.sensors import Sensor, SensorInfo +from ha_mqtt_discoverable import Settings, DeviceInfo + + +class HAViessmannBattery: + """ +The Battery class represents a battery with associated sensors for level, capacity, power, and remaining charge. Each sensor is created as an MQTT entity with its own SensorInfo and Settings. + +Attributes: + id (str): The unique ID of the battery. + name (str): The name of the battery. + device_info (DeviceInfo): The device information of the battery. + mqtt_settings (Settings.MQTT): The MQTT settings for the sensors. + battery_level (Sensor): The sensor for the battery level. + battery_capacity (Sensor): The sensor for the battery capacity. + battery_power (Sensor): The sensor for the battery power. + battery_remaining_charge (Sensor): The sensor for the remaining battery charge. + +Methods: + get_name(): Returns the name of the battery. + set_states(level, capacity, power, remaining_charge): Sets the states of the four sensors. +""" + + def __init__(self, mqtt_settings, device_info, name, id): + self.id: str = id + self.name: str = name + self.device_info: DeviceInfo = device_info + self.mqtt_settings: Settings.MQTT = mqtt_settings + + self.battery_sensor_info = SensorInfo( + name=f"Battery {name} Level", device_class="battery", unique_id=f"gridbox_battery_{name}", device=device_info, unit_of_measurement="%") + self.battery_settings = Settings( + mqtt=mqtt_settings, entity=self.battery_sensor_info) + self.battery_level = Sensor(self.battery_settings) + + self.battery_sensor_capacity = SensorInfo( + name=f"Battery {name} Capacity", device_class="energy", unique_id=f"gridbox_battery_level_{name}", device=device_info, unit_of_measurement="Wh") + self.battery_settings_capacity = Settings( + mqtt=mqtt_settings, entity=self.battery_sensor_capacity) + self.battery_capacity = Sensor(self.battery_settings_capacity) + + self.battery_sensor_power = SensorInfo( + name=f"Battery {name} Power", device_class="battery", unique_id=f"gridbox_battery_power_{name}", device=device_info, unit_of_measurement="W") + self.battery_settings_power = Settings( + mqtt=mqtt_settings, entity=self.battery_sensor_power) + self.battery_power = Sensor(self.battery_settings_power) + + self.battery_sensor_remaining_charge = SensorInfo( + name=f"Battery {name} Remaining Charge", device_class="energy", unique_id=f"gridbox_remaining_charge_{name}", device=device_info, unit_of_measurement="Wh") + self.battery_settings_remaining_charge = Settings( + mqtt=mqtt_settings, entity=self.battery_sensor_remaining_charge) + self.battery_remaining_charge = Sensor( + self.battery_settings_remaining_charge) + + def get_name(self): + return self.name + + def set_states(self, level, capacity, power, remaining_charge): + self.battery_level.set_state(level) + self.battery_capacity.set_state(capacity) + self.battery_power.set_state(power) + self.battery_remaining_charge.set_state(remaining_charge) diff --git a/GridboxConnectorAddon-experimental/GridboxConnector/ha_viessmann_gridbox_connector.py b/GridboxConnectorAddon-experimental/GridboxConnector/ha_viessmann_gridbox_connector.py new file mode 100644 index 0000000..57c99d8 --- /dev/null +++ b/GridboxConnectorAddon-experimental/GridboxConnector/ha_viessmann_gridbox_connector.py @@ -0,0 +1,157 @@ +from ha_mqtt_discoverable import Settings, DeviceInfo +from ha_mqtt_discoverable.sensors import Sensor, SensorInfo +from ha_viessmann_battery import HAViessmannBattery + + +class HAViessmannGridboxConnector: + battery_sensor_dict: dict + mqtt_settings: Settings.MQTT + device_info: DeviceInfo + production_sensor: Sensor + grid_sensor: Sensor + photovoltaic_sensor: Sensor + consumption_household_sensor: Sensor + total_consumption_household_sensor: Sensor + direct_consumption_household_sensor: Sensor + direct_consumtion_heatpump_sensor: Sensor + direct_consumtion_rate_sensor: Sensor + self_supply_sensor: Sensor + self_consumtion_rate_sensor: Sensor + self_sufficiency_rate_sensor: Sensor + battery_sum: HAViessmannBattery + + def __init__(self, mqtt_settings): + self.battery_sensor_dict = {} + self.mqtt_settings = mqtt_settings + self.device_info = DeviceInfo( + name="Viessmann Gridbox", identifiers="viessmann_gridbox", manufacturer="Viessmann", model="Vitocharge 2.0") + + production_sensor_info = SensorInfo(name="Production", device_class="power", + unique_id="gridbox_production", device=self.device_info, unit_of_measurement="W") + production_settings = Settings( + mqtt=mqtt_settings, entity=production_sensor_info) + + grid_sensor_info = SensorInfo(name="Grid", device_class="power", + unique_id="gridbox_grid", device=self.device_info, unit_of_measurement="W") + grid_settings = Settings(mqtt=mqtt_settings, entity=grid_sensor_info) + + photovoltaic_sensor_info = SensorInfo(name="Photovoltaic", device_class="power", + unique_id="gridbox_photovoltaic", device=self.device_info, unit_of_measurement="W") + photovoltaic_settings = Settings( + mqtt=mqtt_settings, entity=photovoltaic_sensor_info) + + # consumption + consumption_household_sensor_info = SensorInfo( + name="Consumption", device_class="power", unique_id="gridbox_consumption_household", device=self.device_info, unit_of_measurement="W") + consumption_household_settings = Settings( + mqtt=mqtt_settings, entity=consumption_household_sensor_info) + + total_consumption_household_sensor_info = SensorInfo( + name="Total Consumption", device_class="power", unique_id="total_consumption_household", device=self.device_info, unit_of_measurement="W") + total_consumption_household_settings = Settings( + mqtt=mqtt_settings, entity=total_consumption_household_sensor_info) + + # Direct Consumption + direct_consumption_household_sensor_info = SensorInfo( + name="DirectConsumptionHousehold", device_class="power", unique_id="gridbox_direct_consumption_household", device=self.device_info, unit_of_measurement="W") + direct_consumption_household_settings = Settings( + mqtt=mqtt_settings, entity=direct_consumption_household_sensor_info) + + direct_consumption_heatpump_sensor_info = SensorInfo( + name="DirectConsumptionHeatPump", device_class="power", unique_id="gridbox_direct_consumption_heatpump", device=self.device_info, unit_of_measurement="W") + direct_consumption_heatpump_settings = Settings( + mqtt=mqtt_settings, entity=direct_consumption_heatpump_sensor_info) + + direct_consumption_rate_sensor_info = SensorInfo( + name="DirectConsumptionRate", device_class="power_factor", unique_id="gridbox_direct_consumption_rate", device=self.device_info, unit_of_measurement="%") + direct_consumption_rate_settings = Settings( + mqtt=mqtt_settings, entity=direct_consumption_rate_sensor_info) + + # Self Consumption + self_supply_sensor_info = SensorInfo(name="SelfSupply", device_class="power", + unique_id="gridbox_self_supply", device=self.device_info, unit_of_measurement="W") + self_supply_settings = Settings( + mqtt=mqtt_settings, entity=self_supply_sensor_info) + + self_consumption_rate_sensor_info = SensorInfo( + name="SelfConsumptionRate", device_class="power_factor", unique_id="gridbox_self_consumption_rate", device=self.device_info, unit_of_measurement="%") + self_consumption_rate_settings = Settings( + mqtt=mqtt_settings, entity=self_consumption_rate_sensor_info) + + self_sufficiency_rate_sensor_info = SensorInfo( + name="SelfSufficiencyRate", device_class="power_factor", unique_id="gridbox_self_sufficiency_rate", device=self.device_info, unit_of_measurement="%") + self_sufficiency_rate_settings = Settings( + mqtt=mqtt_settings, entity=self_sufficiency_rate_sensor_info) + + # Instantiate the sensors + + self.production_sensor = Sensor(production_settings) + self.grid_sensor = Sensor(grid_settings) + self.photovoltaic_sensor = Sensor(photovoltaic_settings) + + # Battery sum + self.battery_sum = HAViessmannBattery( + mqtt_settings, self.device_info, "sum", "") + + # Consumption + self.consumption_household_sensor = Sensor( + consumption_household_settings) + self.total_consumption_household_sensor = Sensor( + total_consumption_household_settings) + self.direct_consumption_household_sensor = Sensor( + direct_consumption_household_settings) + self.direct_consumtion_heatpump_sensor = Sensor( + direct_consumption_heatpump_settings) + self.direct_consumtion_rate_sensor = Sensor( + direct_consumption_rate_settings) + + self.self_supply_sensor = Sensor(self_supply_settings) + self.self_consumtion_rate_sensor = Sensor( + self_consumption_rate_settings) + self.self_sufficiency_rate_sensor = Sensor( + self_sufficiency_rate_settings) + + def update_sensors(self, measurement: dict): + if "production" in measurement: + self.production_sensor.set_state(measurement.get("production", "")) + if "grid" in measurement: + self.grid_sensor.set_state(measurement.get("grid", "")) + if "photovoltaic" in measurement: + self.photovoltaic_sensor.set_state(measurement.get("photovoltaic", "")) + if "consumption" in measurement: + self.consumption_household_sensor.set_state(measurement.get("consumption", "")) + if "totalConsumption" in measurement: + self.total_consumption_household_sensor.set_state(measurement.get("totalConsumption", "")) + if "directConsumptionHousehold" in measurement: + self.direct_consumption_household_sensor.set_state(float(measurement.get("directConsumptionHousehold", "0"))) + if "directConsumptionHeatPump" in measurement: + self.direct_consumtion_heatpump_sensor.set_state(float(measurement.get("directConsumptionHeatPump", "0"))) + if "directConsumptionRate" in measurement: + self.direct_consumtion_rate_sensor.set_state(float(measurement.get("directConsumptionRate", "0"))*100) + + if "selfSupply" in measurement: + self.self_supply_sensor.set_state(float(measurement.get("selfSupply", ""))) + if "selfConsumptionRate" in measurement: + self.self_consumtion_rate_sensor.set_state(float(measurement.get("selfConsumptionRate", "0"))*100) + if "selfSufficiencyRate" in measurement: + self.self_sufficiency_rate_sensor.set_state(float(measurement.get("selfSufficiencyRate", "0"))*100) + + if "battery" in measurement: + battery: dict = measurement.get("battery", {}) + state_of_charge = float(battery.get("stateOfCharge", "0"))*100 + capacity = float(battery.get("capacity", "0")) + power = float(battery.get("power", "0")) + remaining_charge = float(battery.get("remainingCharge", "0")) + self.battery_sum.set_states(state_of_charge, capacity, power, remaining_charge) + if "batteries" in measurement: + batteries: list = measurement.get("batteries", []) + for index, battery in enumerate(batteries): + appliance_id = battery.get("applianceID", "") + if appliance_id not in self.battery_sensor_dict: + self.battery_sensor_dict[appliance_id] = HAViessmannBattery(self.mqtt_settings, self.device_info, f"{index+1}", appliance_id) + battery_sensor = self.battery_sensor_dict[appliance_id] + state_of_charge = float(battery.get("stateOfCharge", "0"))*100 + capacity = float(battery.get("capacity", "0")) + power = float(battery.get("power", "0")) + remaining_charge = float(battery.get("remainingCharge", "0")) + battery_sensor.set_states(state_of_charge, capacity, power, remaining_charge) diff --git a/GridboxConnectorAddon-experimental/GridboxConnector/main_test.py b/GridboxConnectorAddon-experimental/GridboxConnector/main_test.py new file mode 100644 index 0000000..2fad74d --- /dev/null +++ b/GridboxConnectorAddon-experimental/GridboxConnector/main_test.py @@ -0,0 +1,61 @@ +import unittest +from unittest.mock import Mock, patch +from gridbox_connector import GridboxConnector +import json +from ha_mqtt_discoverable import Settings +from ha_viessmann_gridbox_connector import HAViessmannGridboxConnector +from paho.mqtt.client import MQTT_ERR_SUCCESS +from ha_mqtt_discoverable.sensors import Sensor + +mock_data = "{'batteries': [{'applianceID': '97af25d0-3791-48cc-857c-14aaac749267', 'capacity': 10000, 'nominalCapacity': 10000, 'power': -853, 'remainingCharge': 7700, 'stateOfCharge': 0.77}], 'battery': {'capacity': 10000, 'nominalCapacity': 10000, 'power': -853, 'remainingCharge': 7700, 'stateOfCharge': 0.77}, 'consumption': 600, 'directConsumption': 600, 'directConsumptionEV': 0, 'directConsumptionHeatPump': 0, 'directConsumptionHeater': 0, 'directConsumptionHousehold': 600, 'directConsumptionRate': 0.3968253968253968, 'grid': -59, 'gridMeterReadingNegative': 14081760000, 'gridMeterReadingPositive': 7393320000, 'measuredAt': '2024-05-08T09:42:18Z', 'photovoltaic': 1512, 'production': 1512, 'selfConsumption': 1453, 'selfConsumptionRate': 0.9609788359788359, 'selfSufficiencyRate': 1, 'selfSupply': 600, 'totalConsumption': 600}" + + +class TestGridboxConnectorMethods(unittest.TestCase): + + @patch('paho.mqtt.client.Client') + @patch.object(GridboxConnector, 'init_auth', return_value=None) + @patch.object(GridboxConnector, '__init__', return_value=None) + @patch.object(GridboxConnector, 'retrieve_live_data') + def test_main(self, mock_retrieve_live_data, mock_init, mock_init_auth,mock_mqtt_client): + # Load mock data from JSON file + with open('tests/mock_data/mock_data_with_batteries.json') as f: + mock_data = json.load(f) + mock_mqtt_client.return_value.connect.return_value = MQTT_ERR_SUCCESS + mock_retrieve_live_data.return_value = mock_data + # Create an instance of the class + gridbox_connector = GridboxConnector(None) + + # Call the function + result = gridbox_connector.retrieve_live_data() + + # Assert the function was called once + mock_retrieve_live_data.assert_called_once() + + # Assert the function returned the mock value + self.assertEqual(result, mock_data) + mqtt_server = "mqtt_server" + mqtt_user = "mqtt_user" + mqtt_pw = "mqtt_pw" + mqtt_settings = Settings.MQTT( + host=mqtt_server, username=mqtt_user, password=mqtt_pw) + viessmann_gridbox_connector = HAViessmannGridboxConnector( + mqtt_settings) + + with patch.object(viessmann_gridbox_connector.self_supply_sensor, 'set_state') as mock_self_supply_sensor, \ + patch.object(viessmann_gridbox_connector.self_consumtion_rate_sensor, 'set_state') as mock_self_consumtion_rate_sensor, \ + patch.object(viessmann_gridbox_connector.consumption_household_sensor, 'set_state') as mock_consumption_household_sensor, \ + patch.object(viessmann_gridbox_connector.direct_consumption_household_sensor, 'set_state') as mock_direct_consumption_household_sensor, \ + patch.object(viessmann_gridbox_connector.direct_consumtion_heatpump_sensor, 'set_state') as mock_direct_consumtion_heatpump_sensor, \ + patch.object(viessmann_gridbox_connector.direct_consumtion_rate_sensor, 'set_state') as mock_direct_consumtion_rate_sensor, \ + patch.object(viessmann_gridbox_connector.self_sufficiency_rate_sensor, 'set_state') as mock_self_sufficiency_rate_sensor: + viessmann_gridbox_connector.update_sensors(result) + mock_self_supply_sensor.assert_called_once_with(600.0) + mock_self_consumtion_rate_sensor.assert_called_once_with(96.09788359788359) + mock_consumption_household_sensor.assert_called_once_with(600) + mock_direct_consumption_household_sensor.assert_called_once_with(600.0) + mock_direct_consumtion_heatpump_sensor.assert_called_once_with(0.0) + mock_direct_consumtion_rate_sensor.assert_called_once_with(39.682539682539684) + mock_self_sufficiency_rate_sensor.assert_called_once_with(100.0) + +if __name__ == '__main__': + unittest.main() diff --git a/GridboxConnectorAddon-experimental/GridboxConnector/requirements.txt b/GridboxConnectorAddon-experimental/GridboxConnector/requirements.txt new file mode 100644 index 0000000..4f6a96a --- /dev/null +++ b/GridboxConnectorAddon-experimental/GridboxConnector/requirements.txt @@ -0,0 +1,3 @@ +ha-mqtt-discoverable==0.13.1 +requests==2.31.0 +viessmann-gridbox-connector==1.0.1 diff --git a/GridboxConnectorAddon-experimental/GridboxConnector/tests/mock_data/mock_data_with_batteries.json b/GridboxConnectorAddon-experimental/GridboxConnector/tests/mock_data/mock_data_with_batteries.json new file mode 100644 index 0000000..566ffdf --- /dev/null +++ b/GridboxConnectorAddon-experimental/GridboxConnector/tests/mock_data/mock_data_with_batteries.json @@ -0,0 +1,37 @@ +{ + "batteries": [ + { + "applianceID": "97af25d0-3791-48cc-857c-14aaac749267", + "capacity": 10000, + "nominalCapacity": 10000, + "power": -853, + "remainingCharge": 7700, + "stateOfCharge": 0.77 + } + ], + "battery": { + "capacity": 10000, + "nominalCapacity": 10000, + "power": -853, + "remainingCharge": 7700, + "stateOfCharge": 0.77 + }, + "consumption": 600, + "directConsumption": 600, + "directConsumptionEV": 0, + "directConsumptionHeatPump": 0, + "directConsumptionHeater": 0, + "directConsumptionHousehold": 600, + "directConsumptionRate": 0.3968253968253968, + "grid": -59, + "gridMeterReadingNegative": 14081760000, + "gridMeterReadingPositive": 7393320000, + "measuredAt": "2024-05-08T09: 42: 18Z", + "photovoltaic": 1512, + "production": 1512, + "selfConsumption": 1453, + "selfConsumptionRate": 0.9609788359788359, + "selfSufficiencyRate": 1, + "selfSupply": 600, + "totalConsumption": 600 +} diff --git a/GridboxConnectorAddon-experimental/README.md b/GridboxConnectorAddon-experimental/README.md new file mode 100644 index 0000000..0e1a9f7 --- /dev/null +++ b/GridboxConnectorAddon-experimental/README.md @@ -0,0 +1,39 @@ +# Viessmann Gridbox Connector +**Not an Official Viessmann Addon** + +_Fetch live data from your Viessmann Gridbox_ + +![Supports aarch64 Architecture][aarch64-shield] +![Supports amd64 Architecture][amd64-shield] +![Supports armhf Architecture][armhf-shield] +![Supports armv7 Architecture][armv7-shield] + +[aarch64-shield]: https://img.shields.io/badge/aarch64-yes-green.svg +[amd64-shield]: https://img.shields.io/badge/amd64-yes-green.svg +[armhf-shield]: https://img.shields.io/badge/armhf-yes-green.svg +[armv7-shield]: https://img.shields.io/badge/armv7-yes-green.svg + +# Supported Values +The Overview splitted in PV and Battery +## Battery Summery +* power +* capacity +* stateOfCharge + +## Each Battery +* power +* capacity +* stateOfCharge + +## Consumption +* production +* grid +* photovoltaic +* consumption +* totalConsumption +* directConsumptionHousehold +* directConsumptionHeatPump +* directConsumptionRate +* selfSupply +* selfConsumptionRate +* selfSufficiencyRate diff --git a/GridboxConnectorAddon-experimental/apparmor.txt b/GridboxConnectorAddon-experimental/apparmor.txt new file mode 100644 index 0000000..e788a6c --- /dev/null +++ b/GridboxConnectorAddon-experimental/apparmor.txt @@ -0,0 +1,57 @@ +#include + +profile example flags=(attach_disconnected,mediate_deleted) { + #include + + # 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/my_program cx -> my_program, + + profile my_program flags=(attach_disconnected,mediate_deleted) { + #include + + # Receive signals from S6-Overlay + signal (receive) peer=*_example, + + # 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 + # Note: List was built by doing the following: + # 1. Add what is obviously needed based on what is in the script + # 2. Add `complain` as a flag to this profile temporarily and run the addon + # 3. Review the audit log with `journalctl _TRANSPORT="audit" -g 'apparmor="ALLOWED"'` and add other access as needed + # Remember to remove the `complain` flag when you are done + /usr/bin/my_program r, + /bin/bash rix, + /bin/echo ix, + /etc/passwd r, + /dev/tty rw, + } +} \ No newline at end of file diff --git a/GridboxConnectorAddon-experimental/build.yaml b/GridboxConnectorAddon-experimental/build.yaml new file mode 100644 index 0000000..53d0e5c --- /dev/null +++ b/GridboxConnectorAddon-experimental/build.yaml @@ -0,0 +1,13 @@ +# https://developers.home-assistant.io/docs/add-ons/configuration#add-on-dockerfile +build_from: + aarch64: "ghcr.io/home-assistant/aarch64-base-python:3.10-alpine3.16" + amd64: "ghcr.io/home-assistant/amd64-base-python:3.10-alpine3.16" + armhf: "ghcr.io/home-assistant/armhf-base-python:3.10-alpine3.16" + armv7: "ghcr.io/home-assistant/armv7-base-python:3.10-alpine3.16" +labels: + org.opencontainers.image.title: "Viessmann Gridbox Connector (dev)" + org.opencontainers.image.description: "Development of Viessmann Gridbox Connector" + org.opencontainers.image.source: "https://github.com/unl0ck/homeassistant-addon-viessmann-gridbox" + org.opencontainers.image.licenses: "Apache License 2.0" +args: + TEMPIO_VERSION: "2021.09.0" diff --git a/GridboxConnectorAddon-experimental/cloudSettings.json b/GridboxConnectorAddon-experimental/cloudSettings.json new file mode 100644 index 0000000..93d420f --- /dev/null +++ b/GridboxConnectorAddon-experimental/cloudSettings.json @@ -0,0 +1,17 @@ +{ + "version": "1.10.2", + "urls": { + "login": "https://gridx.eu.auth0.com/oauth/token", + "gateways": "https://api.gridx.de/gateways", + "live": "https://api.gridx.de/systems/{}/live" + }, + "login": { + "grant_type": "http://auth0.com/oauth/grant-type/password-realm", + "username": "username", + "password": "password", + "audience": "my.gridx", + "client_id": "oZpr934Ikn8OZOHTJEcrgXkjio0I0Q7b", + "scope": "email openid", + "realm": "viessmann-authentication-db" + } +} \ No newline at end of file diff --git a/GridboxConnectorAddon-experimental/config.yaml b/GridboxConnectorAddon-experimental/config.yaml new file mode 100644 index 0000000..017d829 --- /dev/null +++ b/GridboxConnectorAddon-experimental/config.yaml @@ -0,0 +1,33 @@ +# https://developers.home-assistant.io/docs/add-ons/configuration#add-on-config +name: Viessmann Gridbox Connector (experimental) +version: "1.10.2" +slug: "gridbox_connector_experimental" +description: Development version of Viessmann Gridbox Connector +url: "https://github.com/unl0ck/homeassistant-addon-viessmann-gridbox/tree/main/GridboxConnectorAddon-experimental" +arch: + - armhf + - armv7 + - aarch64 + - amd64 +init: false +codenotary: notary@home-assistant.io +map: + - share:ro +discovery: + - "mqtt" +services: + - "mqtt:need" +options: + username: "email" + password: "password" + wait_time: 60 +schema: + username: str + password: password + wait_time: int + OverrideMqttUser: str? + OverrideMqttPw: password? + OverrideMqttServer: str? + OverrideMqttPort: int? +image: ghcr.io/unl0ck/homeassistant-addon-viessmann-gridbox-experimental-{arch} +stage: experimental diff --git a/GridboxConnectorAddon-experimental/rootfs/etc/services.d/gridboxconnector/finish b/GridboxConnectorAddon-experimental/rootfs/etc/services.d/gridboxconnector/finish new file mode 100755 index 0000000..ed9747c --- /dev/null +++ b/GridboxConnectorAddon-experimental/rootfs/etc/services.d/gridboxconnector/finish @@ -0,0 +1,15 @@ +#!/usr/bin/env bashio +# ============================================================================== +# Take down the S6 supervision tree when example fails +# s6-overlay docs: https://github.com/just-containers/s6-overlay +# ============================================================================== + +#declare APP_EXIT_CODE=${1} + +#if [[ "${APP_EXIT_CODE}" -ne 0 ]] && [[ "${APP_EXIT_CODE}" -ne 256 ]]; then + # bashio::log.warning "Halt add-on with exit code ${APP_EXIT_CODE}" + # echo "${APP_EXIT_CODE}" > /run/s6-linux-init-container-results/exitcode + # exec /run/s6/basedir/bin/halt +#fi + +#bashio::log.info "Service restart after closing" diff --git a/GridboxConnectorAddon-experimental/rootfs/etc/services.d/gridboxconnector/run b/GridboxConnectorAddon-experimental/rootfs/etc/services.d/gridboxconnector/run new file mode 100755 index 0000000..8e4bf98 --- /dev/null +++ b/GridboxConnectorAddon-experimental/rootfs/etc/services.d/gridboxconnector/run @@ -0,0 +1,19 @@ +#!/usr/bin/with-contenv bashio +# ============================================================================== +# Start the example service +# s6-overlay docs: https://github.com/just-containers/s6-overlay +# ============================================================================== + +# Add your code here + +# Declare variables +#declare message + +## Get the 'message' key from the user config options. +#message=$(bashio::config 'message') + +## Print the message the user supplied, defaults to "Hello World..." +bashio::log.info "${"Hello World..."}" + +## Run your program +#exec /usr/bin/my_program diff --git a/GridboxConnectorAddon-experimental/rootfs/share/cloudSettings.json b/GridboxConnectorAddon-experimental/rootfs/share/cloudSettings.json new file mode 100644 index 0000000..93d420f --- /dev/null +++ b/GridboxConnectorAddon-experimental/rootfs/share/cloudSettings.json @@ -0,0 +1,17 @@ +{ + "version": "1.10.2", + "urls": { + "login": "https://gridx.eu.auth0.com/oauth/token", + "gateways": "https://api.gridx.de/gateways", + "live": "https://api.gridx.de/systems/{}/live" + }, + "login": { + "grant_type": "http://auth0.com/oauth/grant-type/password-realm", + "username": "username", + "password": "password", + "audience": "my.gridx", + "client_id": "oZpr934Ikn8OZOHTJEcrgXkjio0I0Q7b", + "scope": "email openid", + "realm": "viessmann-authentication-db" + } +} \ No newline at end of file diff --git a/GridboxConnectorAddon-experimental/rootfs/usr/bin/gridboxconnector b/GridboxConnectorAddon-experimental/rootfs/usr/bin/gridboxconnector new file mode 100755 index 0000000..8d9d457 --- /dev/null +++ b/GridboxConnectorAddon-experimental/rootfs/usr/bin/gridboxconnector @@ -0,0 +1,20 @@ +#!/usr/bin/with-contenv bashio + +export MqttUser=$(bashio::config 'OverrideMqttUser') +export MqttPw=$(bashio::config 'OverrideMqttPw') +export MqttServer=$(bashio::config 'OverrideMqttServer') +export MqttPort=$(bashio::config 'OverrideMqttPort') + +test "$MqttUser" = "null" && export MqttUser=$(bashio::services "mqtt" "username") +test "$MqttPw" = "null" && export MqttPw=$(bashio::services "mqtt" "password") +test "$MqttServer" = "null" && export MqttServer=$(bashio::services "mqtt" "host") +test "$MqttPort" = "null" && export MqttPort=$(bashio::services "mqtt" "port") +export USERNAME=$(bashio::config 'username') +export PASSWORD=$(bashio::config 'password') +ls -lash /data +cat /data/options.json +cd /build/ +ls -lash +ls -lash /share +pwd +python GridboxConnector diff --git a/GridboxConnectorAddon-experimental/run.sh b/GridboxConnectorAddon-experimental/run.sh new file mode 100644 index 0000000..395707e --- /dev/null +++ b/GridboxConnectorAddon-experimental/run.sh @@ -0,0 +1,19 @@ +#!/usr/bin/with-contenv bashio + +export MqttUser=$(bashio::config 'OverrideMqttUser') +export MqttPw=$(bashio::config 'OverrideMqttPw') +export MqttServer=$(bashio::config 'OverrideMqttServer') +export MqttPort=$(bashio::config 'OverrideMqttPort') + +test "$MqttUser" = "null" && export MqttUser=$(bashio::services "mqtt" "username") +test "$MqttPw" = "null" && export MqttPw=$(bashio::services "mqtt" "password") +test "$MqttServer" = "null" && export MqttServer=$(bashio::services "mqtt" "host") +test "$MqttPort" = "null" && export MqttPort=$(bashio::services "mqtt" "port") +export USERNAME=$(bashio::config 'username') +export PASSWORD=$(bashio::config 'password') +ls -lash /data +cat /data/options.json +cd /build/ +ls -lash +pwd +python GridboxConnector diff --git a/GridboxConnectorAddon-experimental/translations/en.yaml b/GridboxConnectorAddon-experimental/translations/en.yaml new file mode 100644 index 0000000..c0b41d0 --- /dev/null +++ b/GridboxConnectorAddon-experimental/translations/en.yaml @@ -0,0 +1,10 @@ +configuration: + username: + name: Username + description: Enter here your email address + password: + name: Password + description: Enter here your Password + wait_time: + name: Wait + description: Set time in seconds how long will wait until fetch new data From b3ff9389f3ead3cfc3c7ccc6e33909ae609d3fa3 Mon Sep 17 00:00:00 2001 From: Simon Helming Date: Fri, 10 May 2024 23:47:20 +0200 Subject: [PATCH 19/20] feat: added s6-overlay to experimental --- .../CHANGELOG.md | 6 +++ GridboxConnectorAddon-experimental/Dockerfile | 10 ++--- .../cloudSettings.json | 4 +- .../config.yaml | 3 +- .../rootfs/etc/s6-overlay/s6-rc.d/banner/type | 1 + .../rootfs/etc/s6-overlay/s6-rc.d/banner/up | 1 + .../gridboxconnector/dependencies.d/banner | 0 .../s6-overlay/s6-rc.d/gridboxconnector/type | 1 + .../s6-overlay/s6-rc.d/gridboxconnector/up} | 1 - .../rootfs/etc/s6-overlay/scripts/banner.sh | 37 +++++++++++++++++++ .../etc/services.d/gridboxconnector/finish | 15 -------- .../etc/services.d/gridboxconnector/run | 19 ---------- .../rootfs/share/cloudSettings.json | 4 +- 13 files changed, 57 insertions(+), 45 deletions(-) create mode 100644 GridboxConnectorAddon-experimental/rootfs/etc/s6-overlay/s6-rc.d/banner/type create mode 100644 GridboxConnectorAddon-experimental/rootfs/etc/s6-overlay/s6-rc.d/banner/up create mode 100644 GridboxConnectorAddon-experimental/rootfs/etc/s6-overlay/s6-rc.d/gridboxconnector/dependencies.d/banner create mode 100644 GridboxConnectorAddon-experimental/rootfs/etc/s6-overlay/s6-rc.d/gridboxconnector/type rename GridboxConnectorAddon-experimental/rootfs/{usr/bin/gridboxconnector => etc/s6-overlay/s6-rc.d/gridboxconnector/up} (97%) mode change 100755 => 100644 create mode 100644 GridboxConnectorAddon-experimental/rootfs/etc/s6-overlay/scripts/banner.sh delete mode 100755 GridboxConnectorAddon-experimental/rootfs/etc/services.d/gridboxconnector/finish delete mode 100755 GridboxConnectorAddon-experimental/rootfs/etc/services.d/gridboxconnector/run diff --git a/GridboxConnectorAddon-experimental/CHANGELOG.md b/GridboxConnectorAddon-experimental/CHANGELOG.md index cb23d4d..591f342 100644 --- a/GridboxConnectorAddon-experimental/CHANGELOG.md +++ b/GridboxConnectorAddon-experimental/CHANGELOG.md @@ -1,5 +1,11 @@ +## 1.11.0 + +### Added + +- Added S6-overlay + ## 1.10.2 ## Added diff --git a/GridboxConnectorAddon-experimental/Dockerfile b/GridboxConnectorAddon-experimental/Dockerfile index 48fbae2..8fe5814 100644 --- a/GridboxConnectorAddon-experimental/Dockerfile +++ b/GridboxConnectorAddon-experimental/Dockerfile @@ -4,7 +4,7 @@ FROM $BUILD_FROM LABEL org.opencontainers.image.source https://github.com/unl0ck/homeassistant-addon-viessmann-gridbox RUN \ apk add --no-cache \ - python3 py3-pip + python3 py3-pip RUN ln -sf python3 /usr/bin/python COPY rootfs / #WORKDIR /data @@ -12,8 +12,8 @@ COPY rootfs / # Execute during the build of the image ARG TEMPIO_VERSION BUILD_ARCH RUN \ - curl -sSLf -o /usr/bin/tempio \ - "https://github.com/home-assistant/tempio/releases/download/${TEMPIO_VERSION}/tempio_${BUILD_ARCH}" + curl -sSLf -o /usr/bin/tempio \ + "https://github.com/home-assistant/tempio/releases/download/${TEMPIO_VERSION}/tempio_${BUILD_ARCH}" # Copy root filesystem COPY GridboxConnector/ /build/GridboxConnector @@ -23,5 +23,5 @@ WORKDIR /build/GridboxConnector RUN pip install -r requirements.txt COPY run.sh /run.sh RUN chmod a+x /run.sh - -CMD [ "/run.sh" ] +COPY rootfs / +#CMD [ "/run.sh" ] diff --git a/GridboxConnectorAddon-experimental/cloudSettings.json b/GridboxConnectorAddon-experimental/cloudSettings.json index 93d420f..e38d921 100644 --- a/GridboxConnectorAddon-experimental/cloudSettings.json +++ b/GridboxConnectorAddon-experimental/cloudSettings.json @@ -1,5 +1,5 @@ { - "version": "1.10.2", + "version": "1.11.0", "urls": { "login": "https://gridx.eu.auth0.com/oauth/token", "gateways": "https://api.gridx.de/gateways", @@ -14,4 +14,4 @@ "scope": "email openid", "realm": "viessmann-authentication-db" } -} \ No newline at end of file +} diff --git a/GridboxConnectorAddon-experimental/config.yaml b/GridboxConnectorAddon-experimental/config.yaml index 017d829..4dc5499 100644 --- a/GridboxConnectorAddon-experimental/config.yaml +++ b/GridboxConnectorAddon-experimental/config.yaml @@ -1,7 +1,8 @@ # https://developers.home-assistant.io/docs/add-ons/configuration#add-on-config name: Viessmann Gridbox Connector (experimental) -version: "1.10.2" +version: "1.11.0" slug: "gridbox_connector_experimental" +apparmor: false description: Development version of Viessmann Gridbox Connector url: "https://github.com/unl0ck/homeassistant-addon-viessmann-gridbox/tree/main/GridboxConnectorAddon-experimental" arch: diff --git a/GridboxConnectorAddon-experimental/rootfs/etc/s6-overlay/s6-rc.d/banner/type b/GridboxConnectorAddon-experimental/rootfs/etc/s6-overlay/s6-rc.d/banner/type new file mode 100644 index 0000000..3d92b15 --- /dev/null +++ b/GridboxConnectorAddon-experimental/rootfs/etc/s6-overlay/s6-rc.d/banner/type @@ -0,0 +1 @@ +oneshot \ No newline at end of file diff --git a/GridboxConnectorAddon-experimental/rootfs/etc/s6-overlay/s6-rc.d/banner/up b/GridboxConnectorAddon-experimental/rootfs/etc/s6-overlay/s6-rc.d/banner/up new file mode 100644 index 0000000..1bb9a0c --- /dev/null +++ b/GridboxConnectorAddon-experimental/rootfs/etc/s6-overlay/s6-rc.d/banner/up @@ -0,0 +1 @@ +/etc/s6-overlay/scripts/banner.sh \ No newline at end of file diff --git a/GridboxConnectorAddon-experimental/rootfs/etc/s6-overlay/s6-rc.d/gridboxconnector/dependencies.d/banner b/GridboxConnectorAddon-experimental/rootfs/etc/s6-overlay/s6-rc.d/gridboxconnector/dependencies.d/banner new file mode 100644 index 0000000..e69de29 diff --git a/GridboxConnectorAddon-experimental/rootfs/etc/s6-overlay/s6-rc.d/gridboxconnector/type b/GridboxConnectorAddon-experimental/rootfs/etc/s6-overlay/s6-rc.d/gridboxconnector/type new file mode 100644 index 0000000..1780f9f --- /dev/null +++ b/GridboxConnectorAddon-experimental/rootfs/etc/s6-overlay/s6-rc.d/gridboxconnector/type @@ -0,0 +1 @@ +longrun \ No newline at end of file diff --git a/GridboxConnectorAddon-experimental/rootfs/usr/bin/gridboxconnector b/GridboxConnectorAddon-experimental/rootfs/etc/s6-overlay/s6-rc.d/gridboxconnector/up old mode 100755 new mode 100644 similarity index 97% rename from GridboxConnectorAddon-experimental/rootfs/usr/bin/gridboxconnector rename to GridboxConnectorAddon-experimental/rootfs/etc/s6-overlay/s6-rc.d/gridboxconnector/up index 8d9d457..395707e --- a/GridboxConnectorAddon-experimental/rootfs/usr/bin/gridboxconnector +++ b/GridboxConnectorAddon-experimental/rootfs/etc/s6-overlay/s6-rc.d/gridboxconnector/up @@ -15,6 +15,5 @@ ls -lash /data cat /data/options.json cd /build/ ls -lash -ls -lash /share pwd python GridboxConnector diff --git a/GridboxConnectorAddon-experimental/rootfs/etc/s6-overlay/scripts/banner.sh b/GridboxConnectorAddon-experimental/rootfs/etc/s6-overlay/scripts/banner.sh new file mode 100644 index 0000000..7a8cae3 --- /dev/null +++ b/GridboxConnectorAddon-experimental/rootfs/etc/s6-overlay/scripts/banner.sh @@ -0,0 +1,37 @@ +#!/usr/bin/with-contenv bashio +# ============================================================================== +# Home Assistant Community Add-on: Base Images +# Displays a simple add-on banner on startup +# ============================================================================== +if bashio::supervisor.ping; then + bashio::log.blue \ + '-----------------------------------------------------------' + bashio::log.blue " Add-on: $(bashio::addon.name)" + bashio::log.blue " $(bashio::addon.description)" + bashio::log.blue \ + '-----------------------------------------------------------' + + bashio::log.blue " Add-on version: $(bashio::addon.version)" + if bashio::var.true "$(bashio::addon.update_available)"; then + bashio::log.magenta ' There is an update available for this add-on!' + bashio::log.magenta \ + " Latest add-on version: $(bashio::addon.version_latest)" + bashio::log.magenta ' Please consider upgrading as soon as possible.' + else + bashio::log.green ' You are running the latest version of this add-on.' + fi + + bashio::log.blue " System: $(bashio::info.operating_system)" \ + " ($(bashio::info.arch) / $(bashio::info.machine))" + bashio::log.blue " Home Assistant Core: $(bashio::info.homeassistant)" + bashio::log.blue " Home Assistant Supervisor: $(bashio::info.supervisor)" + + bashio::log.blue \ + '-----------------------------------------------------------' + bashio::log.blue \ + ' Please, share the above information when looking for help' + bashio::log.blue \ + ' or support in, e.g., GitHub, forums or the Discord chat.' + bashio::log.blue \ + '-----------------------------------------------------------' +fi \ No newline at end of file diff --git a/GridboxConnectorAddon-experimental/rootfs/etc/services.d/gridboxconnector/finish b/GridboxConnectorAddon-experimental/rootfs/etc/services.d/gridboxconnector/finish deleted file mode 100755 index ed9747c..0000000 --- a/GridboxConnectorAddon-experimental/rootfs/etc/services.d/gridboxconnector/finish +++ /dev/null @@ -1,15 +0,0 @@ -#!/usr/bin/env bashio -# ============================================================================== -# Take down the S6 supervision tree when example fails -# s6-overlay docs: https://github.com/just-containers/s6-overlay -# ============================================================================== - -#declare APP_EXIT_CODE=${1} - -#if [[ "${APP_EXIT_CODE}" -ne 0 ]] && [[ "${APP_EXIT_CODE}" -ne 256 ]]; then - # bashio::log.warning "Halt add-on with exit code ${APP_EXIT_CODE}" - # echo "${APP_EXIT_CODE}" > /run/s6-linux-init-container-results/exitcode - # exec /run/s6/basedir/bin/halt -#fi - -#bashio::log.info "Service restart after closing" diff --git a/GridboxConnectorAddon-experimental/rootfs/etc/services.d/gridboxconnector/run b/GridboxConnectorAddon-experimental/rootfs/etc/services.d/gridboxconnector/run deleted file mode 100755 index 8e4bf98..0000000 --- a/GridboxConnectorAddon-experimental/rootfs/etc/services.d/gridboxconnector/run +++ /dev/null @@ -1,19 +0,0 @@ -#!/usr/bin/with-contenv bashio -# ============================================================================== -# Start the example service -# s6-overlay docs: https://github.com/just-containers/s6-overlay -# ============================================================================== - -# Add your code here - -# Declare variables -#declare message - -## Get the 'message' key from the user config options. -#message=$(bashio::config 'message') - -## Print the message the user supplied, defaults to "Hello World..." -bashio::log.info "${"Hello World..."}" - -## Run your program -#exec /usr/bin/my_program diff --git a/GridboxConnectorAddon-experimental/rootfs/share/cloudSettings.json b/GridboxConnectorAddon-experimental/rootfs/share/cloudSettings.json index 93d420f..e38d921 100644 --- a/GridboxConnectorAddon-experimental/rootfs/share/cloudSettings.json +++ b/GridboxConnectorAddon-experimental/rootfs/share/cloudSettings.json @@ -1,5 +1,5 @@ { - "version": "1.10.2", + "version": "1.11.0", "urls": { "login": "https://gridx.eu.auth0.com/oauth/token", "gateways": "https://api.gridx.de/gateways", @@ -14,4 +14,4 @@ "scope": "email openid", "realm": "viessmann-authentication-db" } -} \ No newline at end of file +} From 9048bdc41efc892ad520cb0d46c5c98277496207 Mon Sep 17 00:00:00 2001 From: Simon Helming Date: Sat, 11 May 2024 00:07:25 +0200 Subject: [PATCH 20/20] dep: updated viessmann-gridbox-connector -> 1.0.2 --- .../GridboxConnector/main_test.py | 12 +++++++++++- .../GridboxConnector/requirements.txt | 2 +- .../GridboxConnector/requirements.txt | 2 +- 3 files changed, 13 insertions(+), 3 deletions(-) diff --git a/GridboxConnectorAddon-dev/GridboxConnector/main_test.py b/GridboxConnectorAddon-dev/GridboxConnector/main_test.py index 9029956..2fad74d 100644 --- a/GridboxConnectorAddon-dev/GridboxConnector/main_test.py +++ b/GridboxConnectorAddon-dev/GridboxConnector/main_test.py @@ -42,10 +42,20 @@ def test_main(self, mock_retrieve_live_data, mock_init, mock_init_auth,mock_mqtt mqtt_settings) with patch.object(viessmann_gridbox_connector.self_supply_sensor, 'set_state') as mock_self_supply_sensor, \ - patch.object(viessmann_gridbox_connector.self_consumtion_rate_sensor, 'set_state') as mock_self_consumtion_rate_sensor: + patch.object(viessmann_gridbox_connector.self_consumtion_rate_sensor, 'set_state') as mock_self_consumtion_rate_sensor, \ + patch.object(viessmann_gridbox_connector.consumption_household_sensor, 'set_state') as mock_consumption_household_sensor, \ + patch.object(viessmann_gridbox_connector.direct_consumption_household_sensor, 'set_state') as mock_direct_consumption_household_sensor, \ + patch.object(viessmann_gridbox_connector.direct_consumtion_heatpump_sensor, 'set_state') as mock_direct_consumtion_heatpump_sensor, \ + patch.object(viessmann_gridbox_connector.direct_consumtion_rate_sensor, 'set_state') as mock_direct_consumtion_rate_sensor, \ + patch.object(viessmann_gridbox_connector.self_sufficiency_rate_sensor, 'set_state') as mock_self_sufficiency_rate_sensor: viessmann_gridbox_connector.update_sensors(result) mock_self_supply_sensor.assert_called_once_with(600.0) mock_self_consumtion_rate_sensor.assert_called_once_with(96.09788359788359) + mock_consumption_household_sensor.assert_called_once_with(600) + mock_direct_consumption_household_sensor.assert_called_once_with(600.0) + mock_direct_consumtion_heatpump_sensor.assert_called_once_with(0.0) + mock_direct_consumtion_rate_sensor.assert_called_once_with(39.682539682539684) + mock_self_sufficiency_rate_sensor.assert_called_once_with(100.0) if __name__ == '__main__': unittest.main() diff --git a/GridboxConnectorAddon-dev/GridboxConnector/requirements.txt b/GridboxConnectorAddon-dev/GridboxConnector/requirements.txt index 4f6a96a..1155fcc 100644 --- a/GridboxConnectorAddon-dev/GridboxConnector/requirements.txt +++ b/GridboxConnectorAddon-dev/GridboxConnector/requirements.txt @@ -1,3 +1,3 @@ ha-mqtt-discoverable==0.13.1 requests==2.31.0 -viessmann-gridbox-connector==1.0.1 +viessmann-gridbox-connector==1.0.2 diff --git a/GridboxConnectorAddon-experimental/GridboxConnector/requirements.txt b/GridboxConnectorAddon-experimental/GridboxConnector/requirements.txt index 4f6a96a..1155fcc 100644 --- a/GridboxConnectorAddon-experimental/GridboxConnector/requirements.txt +++ b/GridboxConnectorAddon-experimental/GridboxConnector/requirements.txt @@ -1,3 +1,3 @@ ha-mqtt-discoverable==0.13.1 requests==2.31.0 -viessmann-gridbox-connector==1.0.1 +viessmann-gridbox-connector==1.0.2