]> git.basschouten.com Git - openhab-addons.git/commitdiff
[ecowatt] Add support for API version 5 (#15953)
authorlolodomo <lg.hc@free.fr>
Sun, 26 Nov 2023 22:34:45 +0000 (23:34 +0100)
committerGitHub <noreply@github.com>
Sun, 26 Nov 2023 22:34:45 +0000 (23:34 +0100)
A new thing parameter to define the API version has been added.
Its default value is 4 for backward compatibility even if this version
is now deprecated. The documentation explains what to do to switch from
a version to another.

Signed-off-by: Laurent Garnier <lg.hc@free.fr>
bundles/org.openhab.binding.ecowatt/README.md
bundles/org.openhab.binding.ecowatt/src/main/java/org/openhab/binding/ecowatt/internal/configuration/EcowattConfiguration.java
bundles/org.openhab.binding.ecowatt/src/main/java/org/openhab/binding/ecowatt/internal/handler/EcowattHandler.java
bundles/org.openhab.binding.ecowatt/src/main/java/org/openhab/binding/ecowatt/internal/restapi/EcowattDaySignals.java
bundles/org.openhab.binding.ecowatt/src/main/java/org/openhab/binding/ecowatt/internal/restapi/EcowattRestApi.java
bundles/org.openhab.binding.ecowatt/src/main/resources/OH-INF/i18n/ecowatt.properties
bundles/org.openhab.binding.ecowatt/src/main/resources/OH-INF/thing/thing-types.xml
bundles/org.openhab.binding.ecowatt/src/test/java/org/openhab/binding/ecowatt/internal/EcowattApiResponseTest.java
bundles/org.openhab.binding.ecowatt/src/test/resources/ApiResponse.json

index 7a5b3d79356cbe20cd867b12962afa46d6b76c8c..23a41ce69480e40833b5bf557257fdf8dc698de4 100644 (file)
@@ -17,11 +17,16 @@ You have to add the thing manually.
 
 You must create an account and an application on the RTE portal to obtain the OAuth2 credentials required to access the API.
 
-1. Open this [page](https://data.rte-france.com/catalog/-/api/consumption/Ecowatt/v4.0), find the "Ecowatt" tile and click on the "Abonnez-vous à l'API" button.
+1. Open this [page](https://data.rte-france.com/catalog/-/api/consumption/Ecowatt/v5.0), find the "Ecowatt" tile and click on the "Abonnez-vous à l'API" button.
 1. Create an account by following the instructions (you will receive an email to validate your new account).
 1. Once logged in, create an application by entering a name (for example "openHAB Integration"), choosing "Web Server" as type, entering any description of your choice and finally clicking on the "Valider" button.
 1. You will then see your application details, in particular the "ID client" and "ID Secret" information which you will need later to set up your binding thing.
 
+Note that you are subscribed to a particular version of the API.
+When a new version of the API is released, you will have to subscribe to this new version and create a new application.
+You will then get new information "ID client" and "ID Secret" and you will have to update your thing configuration in openHAB.
+After changing version, you will have to wait for your authentication token to be renewed (max 2 hours) to get a successful response from the API.
+
 ## Binding Configuration
 
 There are no overall binding configuration settings that need to be set.
@@ -29,10 +34,13 @@ All settings are through thing configuration parameters.
 
 ## Thing Configuration
 
-| Name      | Type    | Description                                                           | Required |
-|-----------|---------|-----------------------------------------------------------------------|----------|
-| idClient  | text    | ID client provided with the application you created in the RTE portal | yes      |
-| idSecret  | text    | ID secret provided with the application you created in the RTE portal | yes      |
+| Name       | Type    | Description                                                               | Required | Default |
+|------------|---------|---------------------------------------------------------------------------|----------|---------|
+| apiVersion | integer | The version of the Ecowatt tile to which you subscribed in the RTE portal | no       | 4       |
+| idClient   | text    | ID client provided with the application you created in the RTE portal     | yes      |         |
+| idSecret   | text    | ID secret provided with the application you created in the RTE portal     | yes      |         |
+
+Take care to select the API version corresponding to the one to which you subscribed in the RTE portal.
 
 ## Channels
 
@@ -42,14 +50,14 @@ All channels are read-only.
 |-------------------|--------|------------------------------------------------------------------|
 | todaySignal       | Number | The signal relating to the forecast consumption level for today. Values are 1 for normal consumption (green), 2 for strained electrical system (orange) and 3 for very strained electrical system (red). |
 | tomorrowSignal    | Number | The signal relating to the forecast consumption level for tomorrow. Values are 1 for normal consumption (green), 2 for strained electrical system (orange) and 3 for very strained electrical system (red). |
-| currentHourSignal | Number | The signal relating to the forecast consumption level for the current hour. Values are 1 for normal consumption (green), 2 for strained electrical system (orange) and 3 for very strained electrical system (red). |
+| currentHourSignal | Number | The signal relating to the forecast consumption level for the current hour. Values are 0 for normal consumption (green) and carbon-free production, 1 for normal consumption (green), 2 for strained electrical system (orange) and 3 for very strained electrical system (red). |
 
 ## Full Example
 
 example.things:
 
 ```java
-Thing ecowatt:signals:signals "Ecowatt Signals" [ idClient="xxxxx", idSecret="yyyyy"]
+Thing ecowatt:signals:signals "Ecowatt Signals" [ apiVersion=4, idClient="xxxxx", idSecret="yyyyy"]
 ```
 
 example.items:
index 61e037919dd128cb409a5e7486e8f0d47ddeaa87..f9b8e3bbff8022942a511d4ab2531b0842678e35 100644 (file)
@@ -18,10 +18,12 @@ import org.eclipse.jdt.annotation.NonNullByDefault;
  * The {@link EcowattConfiguration} class contains fields mapping thing configuration parameters.
  *
  * @author Laurent Garnier - Initial contribution
+ * @author Laurent Garnier - New parameter apiVersion
  */
 @NonNullByDefault
 public class EcowattConfiguration {
 
+    public int apiVersion = 4;
     public String idClient = "";
     public String idSecret = "";
 }
index 365d65c67e2b018f12fb6983d52c9f5c96587f44..912e93a9e2b4d6cf9d4268fdc289a5ac1f4f2d1e 100644 (file)
@@ -54,6 +54,7 @@ import org.slf4j.LoggerFactory;
  * The {@link EcowattHandler} is responsible for updating the state of the channels
  *
  * @author Laurent Garnier - Initial contribution
+ * @author Laurent Garnier - Add support for API version 5
  */
 @NonNullByDefault
 public class EcowattHandler extends BaseThingHandler {
@@ -100,7 +101,8 @@ public class EcowattHandler extends BaseThingHandler {
             updateStatus(ThingStatus.OFFLINE, ThingStatusDetail.CONFIGURATION_ERROR,
                     "@text/offline.config-error-unset-parameters");
         } else {
-            api = new EcowattRestApi(oAuthFactory, httpClient, thing.getUID().getAsString(), idClient, idSecret);
+            api = new EcowattRestApi(oAuthFactory, httpClient, thing.getUID().getAsString(), idClient, idSecret,
+                    config.apiVersion);
             updateStatus(ThingStatus.UNKNOWN);
             scheduleNextUpdate(0, true);
         }
@@ -264,7 +266,7 @@ public class EcowattHandler extends BaseThingHandler {
             int hour = dateTime.withZoneSameInstant(day.getZone()).getHour();
             int value = signals.getHourSignal(hour);
             LoggerFactory.getLogger(EcowattHandler.class).debug("hour {} value {}", hour, value);
-            if (value >= 1 && value <= 3) {
+            if (value >= 0 && value <= 3) {
                 return new DecimalType(value);
             }
         }
index 10dbf317ca6f164f12edeb07ba955e52c5d86dcc..e27ed283f7b808fd89a1e16565b76e5b53e2d4a6 100644 (file)
@@ -58,6 +58,6 @@ public class EcowattDaySignals {
                 }
             }
         }
-        return 0;
+        return -1;
     }
 }
index 7da333721b3cf712b599237e7cfd15d0238e6ba8..37a68fabfd448533e3924faace250fdfd1990765 100644 (file)
@@ -46,23 +46,25 @@ import com.google.gson.JsonSyntaxException;
  * The {@link EcowattRestApi} is responsible for handling all communication with the Ecowatt REST API
  *
  * @author Laurent Garnier - Initial contribution
+ * @author Laurent Garnier - Add support for different API versions
  */
 @NonNullByDefault
 public class EcowattRestApi {
 
     private static final String ECOWATT_API_TOKEN_URL = "https://digital.iservices.rte-france.com/token/oauth/";
-    private static final String ECOWATT_API_GET_SIGNALS_URL = "https://digital.iservices.rte-france.com/open_api/ecowatt/v4/signals";
+    private static final String ECOWATT_API_GET_SIGNALS_URL = "https://digital.iservices.rte-france.com/open_api/ecowatt/v%d/signals";
 
     private final Logger logger = LoggerFactory.getLogger(EcowattRestApi.class);
 
     private final OAuthFactory oAuthFactory;
     private final HttpClient httpClient;
     private final Gson gson;
+    private final String apiUrl;
     private OAuthClientService authService;
     private String authServiceHandle;
 
     public EcowattRestApi(OAuthFactory oAuthFactory, HttpClient httpClient, String authServiceHandle, String idClient,
-            String idSecret) {
+            String idSecret, int apiVersion) {
         this.oAuthFactory = oAuthFactory;
         this.httpClient = httpClient;
         GsonBuilder gsonBuilder = new GsonBuilder();
@@ -73,13 +75,14 @@ public class EcowattRestApi {
         this.authService = oAuthFactory.createOAuthClientService(authServiceHandle, ECOWATT_API_TOKEN_URL, null,
                 idClient, idSecret, null, true);
         this.authServiceHandle = authServiceHandle;
+        this.apiUrl = ECOWATT_API_GET_SIGNALS_URL.formatted(apiVersion);
     }
 
     public EcowattApiResponse getSignals() throws CommunicationException, EcowattApiLimitException {
-        logger.debug("API request signals");
+        logger.debug("API request {}", apiUrl);
         String token = authenticate().getAccessToken();
 
-        final Request request = httpClient.newRequest(ECOWATT_API_GET_SIGNALS_URL).method(HttpMethod.GET)
+        final Request request = httpClient.newRequest(apiUrl).method(HttpMethod.GET)
                 .header(HttpHeader.AUTHORIZATION, "Bearer " + token).timeout(10, TimeUnit.SECONDS);
 
         ContentResponse response;
index 690a2860198377a5fb49d9426c82d5143a831aad..832341843ce3bdac260ff49f4df85c5272e93f0e 100644 (file)
@@ -8,7 +8,7 @@ addon.ecowatt.description = This binding uses the Ecowatt API to expose clear si
 thing-type.ecowatt.signals.label = Electricity Forecast
 thing-type.ecowatt.signals.description = The French electricity consumption forecasts
 thing-type.ecowatt.signals.channel.currentHourSignal.label = Current Hour Signal
-thing-type.ecowatt.signals.channel.currentHourSignal.description = The signal relating to the forecast consumption level for the current hour. Values are 1 for normal consumption (green), 2 for strained electrical system (orange) and 3 for very strained electrical system (red).
+thing-type.ecowatt.signals.channel.currentHourSignal.description = The signal relating to the forecast consumption level for the current hour. Values are 0 for normal consumption (green) and carbon-free production, 1 for normal consumption (green), 2 for strained electrical system (orange) and 3 for very strained electrical system (red).
 thing-type.ecowatt.signals.channel.inThreeDaysSignal.label = In Three Days Signal
 thing-type.ecowatt.signals.channel.inThreeDaysSignal.description = The signal relating to the forecast consumption level in three days. Values are 1 for normal consumption (green), 2 for strained electrical system (orange) and 3 for very strained electrical system (red).
 thing-type.ecowatt.signals.channel.inTwoDaysSignal.label = In Two Days Signal
@@ -20,6 +20,10 @@ thing-type.ecowatt.signals.channel.tomorrowSignal.description = The signal relat
 
 # thing types config
 
+thing-type.config.ecowatt.signals.apiVersion.label = API Version
+thing-type.config.ecowatt.signals.apiVersion.description = The version of the Ecowatt tile to which you subscribed in the RTE portal.
+thing-type.config.ecowatt.signals.apiVersion.option.4 = V4.0 (deprecated)
+thing-type.config.ecowatt.signals.apiVersion.option.5 = V5.0
 thing-type.config.ecowatt.signals.idClient.label = ID Client
 thing-type.config.ecowatt.signals.idClient.description = ID client provided with the application you created in the RTE portal.
 thing-type.config.ecowatt.signals.idSecret.label = ID Secret
@@ -28,7 +32,8 @@ thing-type.config.ecowatt.signals.idSecret.description = ID secret provided with
 # channel types
 
 channel-type.ecowatt.signal.label = Consumption Signal
-channel-type.ecowatt.signal.description = The signal relating to the forecast consumption level. Values are 1 for normal consumption (green), 2 for strained electrical system (orange) and 3 for very strained electrical system (red).
+channel-type.ecowatt.signal.description = The signal relating to the forecast consumption level. Values are 0 for normal consumption (green) and carbon-free production, 1 for normal consumption (green), 2 for strained electrical system (orange) and 3 for very strained electrical system (red).
+channel-type.ecowatt.signal.state.option.0 = Green + carbon-free production
 channel-type.ecowatt.signal.state.option.1 = Green
 channel-type.ecowatt.signal.state.option.2 = Orange
 channel-type.ecowatt.signal.state.option.3 = Red
index b1d7b43504dbc31d82160d9976d8d6b9c9f5376e..1dbd4ac7e614ae202578f0b3d1f553a3bb701da7 100644 (file)
                        </channel>
                        <channel id="currentHourSignal" typeId="signal">
                                <label>Current Hour Signal</label>
-                               <description>The signal relating to the forecast consumption level for the current hour. Values are 1 for normal
-                                       consumption (green), 2 for strained electrical system (orange) and 3 for very strained electrical system (red).</description>
+                               <description>The signal relating to the forecast consumption level for the current hour. Values are 0 for normal
+                                       consumption (green) and carbon-free production, 1 for normal consumption (green), 2 for strained electrical system
+                                       (orange) and 3 for very strained electrical system (red).</description>
                        </channel>
                </channels>
 
                <config-description>
+                       <parameter name="apiVersion" type="integer" required="false">
+                               <label>API Version</label>
+                               <description>The version of the Ecowatt tile to which you subscribed in the RTE portal.</description>
+                               <options>
+                                       <option value="4">V4.0 (deprecated)</option>
+                                       <option value="5">V5.0</option>
+                               </options>
+                               <default>4</default>
+                       </parameter>
                        <parameter name="idClient" type="text" required="true">
                                <label>ID Client</label>
                                <description>ID client provided with the application you created in the RTE portal.</description>
        <channel-type id="signal">
                <item-type>Number</item-type>
                <label>Consumption Signal</label>
-               <description>The signal relating to the forecast consumption level. Values are 1 for normal consumption (green), 2 for
-                       strained electrical system (orange) and 3 for very strained electrical system (red).</description>
+               <description>The signal relating to the forecast consumption level. Values are 0 for normal consumption (green) and
+                       carbon-free production, 1 for normal consumption (green), 2 for strained electrical system (orange) and 3 for very
+                       strained electrical system (red).</description>
                <state readOnly="true">
                        <options>
+                               <option value="0">Green + carbon-free production</option>
                                <option value="1">Green</option>
                                <option value="2">Orange</option>
                                <option value="3">Red</option>
index f2dbba608b04152fd0ed1d6377609d13f4d688c6..b3b614adad092b3c74f7a51d0667594429c33ed4 100644 (file)
@@ -42,6 +42,7 @@ import com.google.gson.JsonDeserializer;
 @NonNullByDefault
 public class EcowattApiResponseTest {
 
+    private static final DecimalType STATE_ZERO = new DecimalType(0);
     private static final DecimalType STATE_ONE = new DecimalType(1);
     private static final DecimalType STATE_TWO = new DecimalType(2);
     private static final DecimalType STATE_THREE = new DecimalType(3);
@@ -104,6 +105,10 @@ public class EcowattApiResponseTest {
         State expectedState;
         for (int h = 0; h < 24; h++) {
             switch (h) {
+                case 2:
+                case 3:
+                    expectedState = STATE_ZERO;
+                    break;
                 case 7:
                 case 11:
                 case 19:
@@ -155,6 +160,10 @@ public class EcowattApiResponseTest {
                 case 2:
                     expectedState = UnDefType.UNDEF;
                     break;
+                case 5:
+                case 6:
+                    expectedState = STATE_ZERO;
+                    break;
                 case 10:
                 case 14:
                 case 22:
index c5ac41b743499a7989babf27909925f7eee8e5ad..a7b65bc5fd78711aa4dd9fbff3e743ae1cb88c9c 100644 (file)
@@ -1,4 +1,4 @@
 {"signals":[{"GenerationFichier":"2022-09-18T22:00:00+02:00","jour":"2022-09-22T00:00:00+02:00","dvalue":1,"message":"Notre consommation est raisonnable.","values":[{"pas":0,"hvalue":1},{"pas":1,"hvalue":1},{"pas":2,"hvalue":1},{"pas":3,"hvalue":1},{"pas":4,"hvalue":1},{"pas":5,"hvalue":1},{"pas":6,"hvalue":1},{"pas":7,"hvalue":1},{"pas":8,"hvalue":1},{"pas":9,"hvalue":1},{"pas":10,"hvalue":1},{"pas":11,"hvalue":1},{"pas":12,"hvalue":1},{"pas":13,"hvalue":1},{"pas":14,"hvalue":1},{"pas":15,"hvalue":1},{"pas":16,"hvalue":1},{"pas":17,"hvalue":1},{"pas":18,"hvalue":1},{"pas":19,"hvalue":1},{"pas":20,"hvalue":1},{"pas":21,"hvalue":1},{"pas":22,"hvalue":1}]},
 {"GenerationFichier":"2022-09-18T22:00:00+02:00","jour":"2022-09-20T00:00:00+02:00","dvalue":2,"message":"Notre consommation est raisonnable.","values":[{"pas":0,"hvalue":1},{"pas":1,"hvalue":1},{"pas":2,"hvalue":1},{"pas":3,"hvalue":1},{"pas":4,"hvalue":1},{"pas":5,"hvalue":1},{"pas":6,"hvalue":1},{"pas":7,"hvalue":1},{"pas":8,"hvalue":1},{"pas":9,"hvalue":1},{"pas":10,"hvalue":1},{"pas":11,"hvalue":1},{"pas":12,"hvalue":1},{"pas":13,"hvalue":1},{"pas":14,"hvalue":1},{"pas":15,"hvalue":1},{"pas":16,"hvalue":1},{"pas":17,"hvalue":1},{"pas":18,"hvalue":1},{"pas":19,"hvalue":1},{"pas":20,"hvalue":2},{"pas":21,"hvalue":1},{"pas":22,"hvalue":1},{"pas":23,"hvalue":1}]},
 {"GenerationFichier":"2022-09-18T22:00:00+02:00","jour":"2022-09-21T00:00:00+02:00","dvalue":1,"message":"Notre consommation est raisonnable.","values":[{"pas":0,"hvalue":1},{"pas":1,"hvalue":1},{"pas":2,"hvalue":1},{"pas":3,"hvalue":1},{"pas":4,"hvalue":1},{"pas":5,"hvalue":1},{"pas":6,"hvalue":1},{"pas":7,"hvalue":1},{"pas":8,"hvalue":1},{"pas":9,"hvalue":1},{"pas":10,"hvalue":1},{"pas":11,"hvalue":1},{"pas":12,"hvalue":1},{"pas":13,"hvalue":1},{"pas":14,"hvalue":1},{"pas":15,"hvalue":1},{"pas":16,"hvalue":1},{"pas":17,"hvalue":1},{"pas":18,"hvalue":1},{"pas":19,"hvalue":1},{"pas":20,"hvalue":1},{"pas":21,"hvalue":1},{"pas":22,"hvalue":1},{"pas":23,"hvalue":1}]},
-{"GenerationFichier":"2022-09-18T22:00:00+02:00","jour":"2022-09-19T00:00:00+02:00","dvalue":3,"message":"Notre consommation est raisonnable.","values":[{"pas":0,"hvalue":1},{"pas":1,"hvalue":1},{"pas":2,"hvalue":1},{"pas":3,"hvalue":1},{"pas":4,"hvalue":1},{"pas":5,"hvalue":1},{"pas":6,"hvalue":1},{"pas":7,"hvalue":2},{"pas":8,"hvalue":3},{"pas":9,"hvalue":3},{"pas":10,"hvalue":3},{"pas":11,"hvalue":2},{"pas":12,"hvalue":1},{"pas":13,"hvalue":1},{"pas":14,"hvalue":1},{"pas":15,"hvalue":1},{"pas":16,"hvalue":1},{"pas":17,"hvalue":1},{"pas":18,"hvalue":1},{"pas":19,"hvalue":2},{"pas":20,"hvalue":3},{"pas":21,"hvalue":2},{"pas":22,"hvalue":1},{"pas":23,"hvalue":1}]}]}
+{"GenerationFichier":"2022-09-18T22:00:00+02:00","jour":"2022-09-19T00:00:00+02:00","dvalue":3,"message":"Notre consommation est raisonnable.","values":[{"pas":0,"hvalue":1},{"pas":1,"hvalue":1},{"pas":2,"hvalue":0},{"pas":3,"hvalue":0},{"pas":4,"hvalue":1},{"pas":5,"hvalue":1},{"pas":6,"hvalue":1},{"pas":7,"hvalue":2},{"pas":8,"hvalue":3},{"pas":9,"hvalue":3},{"pas":10,"hvalue":3},{"pas":11,"hvalue":2},{"pas":12,"hvalue":1},{"pas":13,"hvalue":1},{"pas":14,"hvalue":1},{"pas":15,"hvalue":1},{"pas":16,"hvalue":1},{"pas":17,"hvalue":1},{"pas":18,"hvalue":1},{"pas":19,"hvalue":2},{"pas":20,"hvalue":3},{"pas":21,"hvalue":2},{"pas":22,"hvalue":1},{"pas":23,"hvalue":1}]}]}