Repository: V2G-liberty/addon-v2g-liberty

Issue:
feature: New default FM URL
goes from seita.energy to ems.seita.energy

Hints from issue comments:

Solution patch:
diff --git a/v2g-liberty-cards/src/edit-schedule-settings-dialog.ts b/v2g-liberty-cards/src/edit-schedule-settings-dialog.ts
index 28cd352..689374a 100644
--- a/v2g-liberty-cards/src/edit-schedule-settings-dialog.ts
+++ b/v2g-liberty-cards/src/edit-schedule-settings-dialog.ts
@@ -48,7 +48,7 @@ class EditScheduleSettingsDialog extends DialogBase {
       ''
     );
     this._fmUseOtherServer = this.hass.states[entityIds.fmUseOtherServer].state;
-    this._fmHostUrl = defaultState(this.hass.states[entityIds.fmHostUrl], 'https://seita.energy');
+    this._fmHostUrl = defaultState(this.hass.states[entityIds.fmHostUrl], 'https://ems.seita.energy');
     this._fmAsset = this.hass.states[entityIds.fmAsset].state;
 
     this._fmConnectionStatus = '';
diff --git a/v2g-liberty-cards/src/util/render.ts b/v2g-liberty-cards/src/util/render.ts
index 44cb352..1595d9e 100644
--- a/v2g-liberty-cards/src/util/render.ts
+++ b/v2g-liberty-cards/src/util/render.ts
@@ -236,7 +236,7 @@ export enum InputText {
   IpAddress = '^(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\\.(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\\.(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\\.(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)$',
   OctopusCode = '^[\\w\\d-]+$',
   URL = '^https?:\\/\\/[\\w@:%.\\+\\-~#=]{1,256}\\b([a-zA-Z0-9\\(\\)@:%_\\+\\-.~#?&\\/=]*)$',
-  // Among others tested for: 'http://localhost:1234', 'https://www.icloud.com/dav', 'https://seita.energy/'
+  // Among others tested for: 'http://localhost:1234', 'https://www.icloud.com/dav', 'https://ems.seita.energy/'
   UserName = '^[\\w\\-.@]{2,}$',
   Password = '.{4,}',
 }
diff --git a/v2g-liberty/CHANGELOG.md b/v2g-liberty/CHANGELOG.md
index c195586..e745ba5 100644
--- a/v2g-liberty/CHANGELOG.md
+++ b/v2g-liberty/CHANGELOG.md
@@ -1,19 +1,10 @@
 # What's changed?
 
-## 0.5.1 2025-02-05
+## 0.5.3 2025-03-06
 
 ### Fixed
 
-- Build in extra safeguards not to accept a None or 0 value for the SoC (unnumbered)
-- Removed annoying log statement that flooded the logging (unnumbered)
-
-## 0.5.0 2025-02-04
-
-### Fixed
-
-- 🪲 BUG: "no schedule available" not correctly reset (#219)
-- 🪲 BUG: No schedule leads to incorrect 'Not connected' notification (#224)
-- 🪲 BUG: No new schedule notification text and layout (#227)
+- None
 
 ### Added
 
@@ -21,9 +12,7 @@
 
 ### Changed
 
-- Feature Request: Make ping card look & feel compliant with HA snackbar (#199)
-- Feature Request: New frontend for settings page (unnumbered)
-- ⬆️ Bump PyModbus library to v3.8.3
+- Changed default url for the FlexMeasures cloud service from `https://seita.energy` to `https://ems.seita.energy`. This includes automated update of this setting for current clients.
 
 ### [Unreleased]
 
@@ -31,6 +20,7 @@ The next release might include:
 
 #### Adding
 
+- Manual dis-charge function
 - Support for uni-directional charging
 
 #### Changing
diff --git a/v2g-liberty/changelog_of_all_releases.md b/v2g-liberty/changelog_of_all_releases.md
index 304e60a..f6c5ebd 100644
--- a/v2g-liberty/changelog_of_all_releases.md
+++ b/v2g-liberty/changelog_of_all_releases.md
@@ -3,6 +3,34 @@
 A separate [changelog for only the current release](CHANGELOG.md) is available to keep things readable.
 That file also contains possible changes that the next release might include.
 
+## 0.5.3 2025-03-06
+
+### Fixed
+
+- None
+
+### Added
+
+- None
+
+### Changed
+
+- Changed default url for the FlexMeasures cloud service from `https://seita.energy` to `https://ems.seita.energy`. This includes automated update of this setting for current clients.
+
+## 0.5.2 2025-02-19
+
+### Fixed
+
+- 🪲 BUG: Build problems due to updated `build-base` and `patches`.
+
+### Added
+
+- None
+
+### Changed
+
+- None
+
 ## 0.5.1 2025-02-05
 
 ### Fixed
diff --git a/v2g-liberty/rootfs/root/appdaemon/apps/v2g_liberty/constants.py b/v2g-liberty/rootfs/root/appdaemon/apps/v2g_liberty/constants.py
index 2c2c9f0..213f0eb 100755
--- a/v2g-liberty/rootfs/root/appdaemon/apps/v2g_liberty/constants.py
+++ b/v2g-liberty/rootfs/root/appdaemon/apps/v2g_liberty/constants.py
@@ -109,7 +109,7 @@
 
 # CONSTANTS for FM URL's
 # FSC: Used in fm_client only, move there.
-FM_BASE_URL = "https://seita.energy"
+FM_BASE_URL = "https://ems.seita.energy"
 # Based on ELECTRICITY_PROVIDER
 # FSC: Used in fm_client only, move there.
 FM_OPTIMISATION_CONTEXT: dict = {}
diff --git a/v2g-liberty/rootfs/root/appdaemon/apps/v2g_liberty/settings_manager.py b/v2g-liberty/rootfs/root/appdaemon/apps/v2g_liberty/settings_manager.py
index f5476ca..59d35f7 100644
--- a/v2g-liberty/rootfs/root/appdaemon/apps/v2g_liberty/settings_manager.py
+++ b/v2g-liberty/rootfs/root/appdaemon/apps/v2g_liberty/settings_manager.py
@@ -23,6 +23,7 @@ def retrieve_settings(self):
                     settings = json.load(read_file)
                     if isinstance(settings, dict):
                         self.settings = self.__upgrade(settings)
+                        self.__write_to_file()
                     else:
                         self.__log(
                             f"loading file content error, no dict: '{settings}'.",
@@ -42,19 +43,24 @@ def __upgrade(self, settings: dict):
 
     def __upgrade_obsolete_settings(self, settings: dict):
         self.__log("Called")
+
+        # TODO: Review if this code can be removed again if all users have upgraded to
+        # version 0.5.0 (Feb 2025) or above."""
         for obsolete, new in {
             "input_select.admin_mobile_name": "input_text.admin_mobile_name",
             "input_select.fm_asset": "input_text.fm_asset",
             "input_select.integration_calendar_entity_name": "input_text.integration_calendar_entity_name",
             "input_select.car_calendar_source": "input_text.car_calendar_source",
-            "input_select.car_calendar_name": "input_text.car_calendar_name"
+            "input_select.car_calendar_name": "input_text.car_calendar_name",
         }.items():
             if obsolete in settings:
-                self.__log(f"Changed obsolete setting: {obsolete} to {new}.")
+                self.__log(f"Changed obsolete setting key: {obsolete} to {new}.")
                 value = settings.get(obsolete)
                 settings.update({new: value})
                 settings.pop(obsolete)
 
+        # TODO: Review if this code can be removed again if all users have upgraded to
+        # version 0.5.0 (Feb 2025) or above."""
         setting_key = "input_text.car_calendar_source"
         for obsolete, new in {
             "Home Assistant integration": "localIntegration",
@@ -62,9 +68,19 @@ def __upgrade_obsolete_settings(self, settings: dict):
         }.items():
             value = settings.get(setting_key)
             if value == obsolete:
-                self.__log(f"Changed obsolete setting: {obsolete} to {new}.")
+                self.__log(f"Changed setting ({setting_key}): {obsolete} to {new}.")
                 settings.update({setting_key: new})
 
+        # TODO: Review if this code can be removed again if all users have upgraded to
+        # version 0.5.3 (March 2025) or above."""
+        setting_key = "input_text.fm_host_url"
+        value = settings.get(setting_key)
+        if value == "https://seita.energy":
+            self.__log(
+                f"Changed ({setting_key}): 'https://seita.energy' to 'https://ems.seita.energy'."
+            )
+            settings.update({setting_key: "https://ems.seita.energy"})
+
         return settings
 
     def __upgrade_administrator_settings_initialised(self, settings: dict):
diff --git a/v2g-liberty/rootfs/root/appdaemon/apps/v2g_liberty/v2g_globals.py b/v2g-liberty/rootfs/root/appdaemon/apps/v2g_liberty/v2g_globals.py
index a83b9ed..5273be7 100755
--- a/v2g-liberty/rootfs/root/appdaemon/apps/v2g_liberty/v2g_globals.py
+++ b/v2g-liberty/rootfs/root/appdaemon/apps/v2g_liberty/v2g_globals.py
@@ -48,7 +48,7 @@ class V2GLibertyGlobals:
         "entity_name": "fm_host_url",
         "entity_type": "input_text",
         "value_type": "str",
-        "factory_default": "https://seita.energy",
+        "factory_default": "https://ems.seita.energy",
     }
     SETTING_FM_ASSET = {
         "entity_name": "fm_asset",
diff --git a/v2g-liberty/translations/en.yaml b/v2g-liberty/translations/en.yaml
index 5573e8c..d93e0f2 100755
--- a/v2g-liberty/translations/en.yaml
+++ b/v2g-liberty/translations/en.yaml
@@ -1,52 +1,2 @@
 ---
-configuration:
-  fm_account_username:
-    name: FlexMeasures username (e-mail address)
-    description: >-
-      This is the e-mail address you use for logging in to FlexMeasures.
-      You can test it by logging in online at https://flexmeasures.seita.energy (or your own instance).
-      In secrets.yaml this used to be called `fm_user_email`
-
-  fm_account_password:
-    name: FlexMeasures password
-    description: >-
-      Provided to you with the account details.
-      In secrets.yaml this used to be called `fm_user_password`
-
-  fm_host_url:
-    name: FlexMeasures host URL
-    description: >-
-      If you use the The default is https://flexmeasures.seita.energy".
-      
-      Only change this if you have your own instance of FlexMeasures running.
-      In was not stored in secrets.yaml.
-      
-      .
-
-  fm_account_power_sensor_id:
-    name: Power sensor_id in FlexMeasures
-    description: >-
-      This represents the history of the charging power as stored by FlexMeasures.
-      
-      In secrets.yaml this used to be called `fm_account_power_sensor_id`
-
-  fm_account_availability_sensor_id:
-    name: Availability sensor_id in FlexMeasures
-    description: >-
-      This represents the history of how often the system was available for automated charging as stored by FlexMeasures.
-      
-      In secrets.yaml this used to be called `fm_account_availability_sensor_id`
-
-  fm_account_soc_sensor_id:
-    name: State of charge sensor_id in FlexMeasures
-    description: >-
-      This represents the history of the state of charge (SoC), a.k.a. battery %, as stored by FlexMeasures.
-      
-      In secrets.yaml this used to be called `fm_account_soc_sensor_id`
-
-  fm_account_cost_sensor_id:
-    name: Costs sensor_id in FlexMeasures
-    description: >-
-      This represents the history of the charging costs as calculated by FlexMeasures.
-      
-      In secrets.yaml this used to be called `fm_account_cost_sensor_id`
\ No newline at end of file
+configuration:
\ No newline at end of file


Test patch:
diff --git a/v2g-liberty/rootfs/root/appdaemon/tests/test_settings_manager.py b/v2g-liberty/rootfs/root/appdaemon/tests/test_settings_manager.py
index cea7332..f556ff7 100644
--- a/v2g-liberty/rootfs/root/appdaemon/tests/test_settings_manager.py
+++ b/v2g-liberty/rootfs/root/appdaemon/tests/test_settings_manager.py
@@ -276,6 +276,42 @@ def test_upgrade_schedule_settings_initialised(self, settings_manager):
             settings_manager.get("input_boolean.schedule_settings_initialised") is True
         )
 
+    # Following two tests
+    # Check that the url to Seita's FlexMeasures server is updated automatically
+    # (update version 0.5.3 from March 2025).
+    # TODO: Review if this code can be removed again if all users have upgraded to version 0.5.3
+    # or above."""
+
+    @patch("os.path.exists", lambda _: True)
+    def test_upgrade_fm_url(self, settings_manager):
+        # Arrange
+        saved_settings = json.dumps(
+            {
+                "input_text.fm_host_url": "https://seita.energy",
+            }
+        )
+        with patch("builtins.open", mock_open(read_data=saved_settings)):
+            # Act
+            settings_manager.retrieve_settings()
+        # Assert
+        assert (
+            settings_manager.get("input_text.fm_host_url") == "https://ems.seita.energy"
+        )
+
+    @patch("os.path.exists", lambda _: True)
+    def test_upgrade_fm_url_non_default(self, settings_manager):
+        # Arrange
+        saved_settings = json.dumps(
+            {
+                "input_text.fm_host_url": "https://localhost:81",
+            }
+        )
+        with patch("builtins.open", mock_open(read_data=saved_settings)):
+            # Act
+            settings_manager.retrieve_settings()
+        # Assert
+        assert settings_manager.get("input_text.fm_host_url") == "https://localhost:81"
+
 
 @patch("builtins.open", mock_open())
 def test_store_setting(settings_manager, json_dump_mock):