some fixes on connectlinky page

tempo day support, WIP

Signed-off-by: Laurent ARNAL <laurent@clae.net>
This commit is contained in:
Laurent ARNAL 2024-02-01 18:54:21 +01:00
parent e7996bca12
commit 6e40ddfcf4
12 changed files with 400 additions and 62 deletions

View File

@ -42,4 +42,6 @@ public interface LinkyAccountHandler {
* @return the formatted url that should be used to call Smartthings Web Api with
*/
String formatAuthorizationUrl(String redirectUri);
String[] getAllPrmId();
}

View File

@ -48,7 +48,7 @@ public class LinkyAuthServlet extends HttpServlet {
private static final String CONTENT_TYPE = "text/html;charset=UTF-8";
private static final String HTML_USER_AUTHORIZED = "<p class='block authorized'>Addon authorized for user %s.</p>";
private static final String HTML_USER_AUTHORIZED = "<p class='block authorized'>Addon authorized for %s.</p>";
private static final String HTML_ERROR = "<p class='block error'>Call to Enedis failed with error: %s</p>";
private static final String HTML_META_REFRESH_CONTENT = "<meta http-equiv='refresh' content='10; url=%s'>";
@ -57,6 +57,7 @@ public class LinkyAuthServlet extends HttpServlet {
private static final String KEY_AUTHORIZE_URI = "authorize.uri";
private static final String KEY_RETRIEVE_TOKEN_URI = "retrieveToken.uri";
private static final String KEY_REDIRECT_URI = "redirectUri";
private static final String KEY_PRMID_OPTION = "prmId.Option";
private static final String KEY_AUTHORIZED_USER = "authorizedUser";
private static final String KEY_ERROR = "error";
private static final String KEY_PAGE_REFRESH = "pageRefresh";
@ -81,15 +82,23 @@ public class LinkyAuthServlet extends HttpServlet {
String servletBaseURLSecure = servletBaseURL;
// .replace("http://", "https://");
// .replace("8080", "8443");
servletBaseURLSecure = servletBaseURLSecure + "?state=OK";
handleLinkyRedirect(replaceMap, servletBaseURLSecure, req.getQueryString());
LinkyAccountHandler accountHandler = linkyAuthService.getLinkyAccountHandler();
resp.setContentType(CONTENT_TYPE);
StringBuffer optionBuffer = new StringBuffer();
String[] prmIds = accountHandler.getAllPrmId();
for (String prmId : prmIds) {
optionBuffer.append("<option value=\"" + prmId + "\">" + prmId + "</option>");
}
replaceMap.put(KEY_PRMID_OPTION, optionBuffer.toString());
replaceMap.put(KEY_REDIRECT_URI, servletBaseURLSecure);
replaceMap.put(KEY_RETRIEVE_TOKEN_URI, servletBaseURLSecure);
replaceMap.put(KEY_RETRIEVE_TOKEN_URI, servletBaseURLSecure + "?state=OK");
replaceMap.put(KEY_AUTHORIZE_URI, accountHandler.formatAuthorizationUrl(servletBaseURLSecure));
resp.getWriter().append(replaceKeysFromMap(indexTemplate, replaceMap));
resp.getWriter().close();
@ -128,7 +137,7 @@ public class LinkyAuthServlet extends HttpServlet {
} else if (!StringUtil.isBlank(reqState)) {
try {
replaceMap.put(KEY_AUTHORIZED_USER, String.format(HTML_USER_AUTHORIZED,
linkyAuthService.authorize(servletBaseURL, reqState, reqCode)));
reqCode + " / " + linkyAuthService.authorize(servletBaseURL, reqState, reqCode)));
} catch (RuntimeException e) {
logger.debug("Exception during authorizaton: ", e);
replaceMap.put(KEY_ERROR, String.format(HTML_ERROR, e.getMessage()));

View File

@ -60,6 +60,8 @@ public class LinkyBindingConstants {
public static final String YEAR_MINUS_1 = "yearly#year-1";
public static final String YEAR_MINUS_2 = "yearly#year-2";
public static final String TEST_SELECT = "main#linkyTestSelect";
// Authorization related Servlet and resources aliases.
public static final String LINKY_ALIAS = "/connectlinky";
public static final String LINKY_IMG_ALIAS = "/img";

View File

@ -19,7 +19,9 @@ import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.ZonedDateTime;
import java.time.format.DateTimeFormatter;
import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
import javax.net.ssl.SSLContext;
import javax.net.ssl.TrustManager;
@ -28,6 +30,7 @@ import org.eclipse.jdt.annotation.NonNullByDefault;
import org.eclipse.jdt.annotation.Nullable;
import org.eclipse.jetty.client.HttpClient;
import org.eclipse.jetty.util.ssl.SslContextFactory;
import org.openhab.binding.linky.internal.api.EnedisHttpApi;
import org.openhab.binding.linky.internal.handler.LinkyHandler;
import org.openhab.core.auth.client.oauth2.AccessTokenResponse;
import org.openhab.core.auth.client.oauth2.OAuthClientService;
@ -217,15 +220,27 @@ public class LinkyHandlerFactory extends BaseThingHandlerFactory implements Link
}
// Fallback for MyElectricalData
else {
String token = "";
/*
* String token = enedisApi.getToken(clientId, config.prmId);
* config.token = token;
*
* Configuration configuration = getConfig();
* configuration.put("token", token);
* updateConfiguration(configuration);
*/
String token = EnedisHttpApi.getToken(httpClient, clientId, reqCode);
logger.debug("token:" + token);
Collection<Thing> col = this.thingRegistry.getAll();
for (Thing thing : col) {
if (LinkyBindingConstants.THING_TYPE_LINKY.equals(thing.getThingTypeUID())) {
Configuration config = thing.getConfiguration();
String prmId = (String) config.get("prmId");
if (!prmId.equals(reqCode)) {
continue;
}
config.put("token", token);
LinkyHandler handler = (LinkyHandler) thing.getHandler();
handler.saveConfiguration(config);
}
}
return token;
}
}
@ -266,18 +281,6 @@ public class LinkyHandlerFactory extends BaseThingHandlerFactory implements Link
}
// Fallback for MyElectricalData
else {
Collection<Thing> col = this.thingRegistry.getAll();
for (Thing thing : col) {
if (LinkyBindingConstants.THING_TYPE_LINKY.equals(thing.getThingTypeUID())) {
Configuration config = thing.getConfiguration();
String prmId = (String) config.get("prmId");
prmId = prmId + "";
}
}
String uri = LinkyBindingConstants.ENEDIS_AUTHORIZE_URL;
uri = uri + "?";
uri = uri + "&client_id=" + clientId;
@ -288,4 +291,22 @@ public class LinkyHandlerFactory extends BaseThingHandlerFactory implements Link
}
@Override
public String[] getAllPrmId() {
Collection<Thing> col = this.thingRegistry.getAll();
List<String> result = new ArrayList<String>();
for (Thing thing : col) {
if (LinkyBindingConstants.THING_TYPE_LINKY.equals(thing.getThingTypeUID())) {
Configuration config = thing.getConfiguration();
String prmId = (String) config.get("prmId");
result.add(prmId);
}
}
return result.toArray(new String[0]);
}
}

View File

@ -48,6 +48,7 @@ import org.openhab.binding.linky.internal.dto.IdentityInfo;
import org.openhab.binding.linky.internal.dto.MeterReading;
import org.openhab.binding.linky.internal.dto.MeterResponse;
import org.openhab.binding.linky.internal.dto.PrmInfo;
import org.openhab.binding.linky.internal.dto.TempoResponse;
import org.openhab.binding.linky.internal.dto.UsagePoint;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@ -71,6 +72,7 @@ public class EnedisHttpApi {
private static final String CONTACT_URL = BASE_URL + "contact";
private static final String ADDRESS_URL = BASE_URL + "addresses";
private static final String MEASURE_URL = BASE_URL + "%s/%s/start/%s/end/%s/cache";
private static final String TEMPO_URL = BASE_URL + "rte/tempo/%s/%s";
private static final String TOKEN_URL = BASE_URL
+ "v1/oauth2/authorize?client_id=%s&response_type=code&redirect_uri=na&user_type=na&state=na&person_id=-1&usage_points_id=%s";
@ -111,10 +113,16 @@ public class EnedisHttpApi {
}
private String getData(String url) throws LinkyException {
return getData(url, httpClient, config.token);
}
private static String getData(String url, HttpClient httpClient, String token) throws LinkyException {
try {
Request request = httpClient.newRequest(url);
request = request.method(HttpMethod.GET);
request = request.header("Authorization", config.token);
if (!("".equals(token))) {
request = request.header("Authorization", token);
}
ContentResponse result = request.send();
if (result.getStatus() == 307) {
@ -272,10 +280,37 @@ public class EnedisHttpApi {
return getMeasures(userId, prmId, from, to, "daily_consumption_max_power");
}
public String getToken(String clientId, String prmId) {
public String getTempoData() throws LinkyException {
String url = String.format(TEMPO_URL, "2024-01-01", "2024-01-31");
if (!connected) {
initialize();
}
String data = getData(url);
if (data.isEmpty()) {
throw new LinkyException("Requesting '%s' returned an empty response", url);
}
logger.trace("getData returned {}", data);
try {
TempoResponse tempResponse = gson.fromJson(data, TempoResponse.class);
if (tempResponse == null) {
throw new LinkyException("No report data received");
}
return "{\"2024-01-20\":\"WHITE\",\"2024-01-21\":\"RED\",\"array\":[\"2024-01-20\",\"2024-01-21\"]}";
// return tempResponse.tempoDayInfo;
} catch (JsonSyntaxException e) {
logger.debug("invalid JSON response not matching ConsumptionReport.class: {}", data);
throw new LinkyException(e, "Requesting '%s' returned an invalid JSON response", url);
}
// return data;
}
public static String getToken(HttpClient httpClient, String clientId, String prmId) {
try {
String url = String.format(TOKEN_URL, clientId, prmId);
String token = getData(url);
String token = getData(url, httpClient, "");
return token;
} catch (LinkyException e) {
return "";

View File

@ -0,0 +1,27 @@
/**
* Copyright (c) 2010-2024 Contributors to the openHAB project
*
* See the NOTICE file(s) distributed with this work for additional
* information.
*
* This program and the accompanying materials are made available under the
* terms of the Eclipse Public License 2.0 which is available at
* http://www.eclipse.org/legal/epl-2.0
*
* SPDX-License-Identifier: EPL-2.0
*/
package org.openhab.binding.linky.internal.dto;
import org.eclipse.jetty.jaas.spi.UserInfo;
/**
* The {@link UserInfo} holds informations about energy delivery point
*
* @author Gaël L'hopital - Initial contribution
* @author Laurent Arnal - Rewrite addon to use official dataconect API
*/
public class TempoDayInfo {
public String tempoDay;
public String tempoVal;
}

View File

@ -0,0 +1,28 @@
/**
* Copyright (c) 2010-2024 Contributors to the openHAB project
*
* See the NOTICE file(s) distributed with this work for additional
* information.
*
* This program and the accompanying materials are made available under the
* terms of the Eclipse Public License 2.0 which is available at
* http://www.eclipse.org/legal/epl-2.0
*
* SPDX-License-Identifier: EPL-2.0
*/
package org.openhab.binding.linky.internal.dto;
import java.util.HashMap;
import org.eclipse.jetty.jaas.spi.UserInfo;
/**
* The {@link UserInfo} holds informations about energy delivery point
*
* @author Gaël L'hopital - Initial contribution
* @author Laurent Arnal - Rewrite addon to use official dataconect API
*/
public class TempoResponse extends HashMap<String, String> {
}

View File

@ -36,9 +36,14 @@ import org.openhab.binding.linky.internal.dto.IntervalReading;
import org.openhab.binding.linky.internal.dto.MeterReading;
import org.openhab.binding.linky.internal.dto.PrmInfo;
import org.openhab.core.auth.client.oauth2.OAuthFactory;
import org.openhab.core.config.core.Configuration;
import org.openhab.core.i18n.LocaleProvider;
import org.openhab.core.library.types.QuantityType;
<<<<<<< HEAD
import org.openhab.core.library.unit.MetricPrefix;
=======
import org.openhab.core.library.types.StringType;
>>>>>>> 8179e0592f (some fixes on connectlinky page)
import org.openhab.core.library.unit.Units;
import org.openhab.core.thing.ChannelUID;
import org.openhab.core.thing.Thing;
@ -160,13 +165,13 @@ public class LinkyHandler extends BaseThingHandler {
config = getConfigAs(LinkyConfiguration.class);
if (config.seemsValid()) {
enedisApi = new EnedisHttpApi(config, gson, httpClient);
scheduler.submit(() -> {
try {
EnedisHttpApi api = this.enedisApi;
api.initialize();
enedisApi.initialize();
updateStatus(ThingStatus.ONLINE);
PrmInfo prmInfo = api.getPrmInfo();
PrmInfo prmInfo = enedisApi.getPrmInfo();
updateProperties(Map.of(USER_ID, prmInfo.customerId, PUISSANCE,
prmInfo.contractInfo.subscribedPower, PRM_ID, prmInfo.prmId));
@ -206,6 +211,24 @@ public class LinkyHandler extends BaseThingHandler {
// updateMonthlyData();
// updateYearlyData();
String tempoData = getTempoData();
// LinkedTreeMap<String, String> obj = gson.fromJson(tempoData, LinkedTreeMap.class);
/*
*
*
* ArrayList<Object> list = new ArrayList<Object>();
* for (Object key : obj.keySet()) {
* Object val = obj.get(key);
*
* Pair<String, String> keyValue = new ImmutablePair(key, val);
* list.add(keyValue);
* }
*/
updateState(TEST_SELECT, new StringType(tempoData));
if (!connectedBefore && isConnected()) {
disconnect();
}
@ -441,6 +464,23 @@ public class LinkyHandler extends BaseThingHandler {
*
*/
private @Nullable String getTempoData() {
logger.debug("getTempoData from");
EnedisHttpApi api = this.enedisApi;
if (api != null) {
try {
String result = api.getTempoData();
updateStatus(ThingStatus.ONLINE);
return result;
} catch (LinkyException e) {
logger.debug("Exception when getting power data: {}", e.getMessage(), e);
updateStatus(ThingStatus.OFFLINE, ThingStatusDetail.OFFLINE.COMMUNICATION_ERROR, e.getMessage());
}
}
return null;
}
private boolean isConnected() {
EnedisHttpApi api = this.enedisApi;
return api == null ? false : api.isConnected();
@ -618,4 +658,34 @@ public class LinkyHandler extends BaseThingHandler {
*
*/
private void logData(IntervalReading[] ivArray, String title, DateTimeFormatter dateTimeFormatter, Target target) {
if (logger.isDebugEnabled()) {
int size = ivArray.length;
if (target == Target.FIRST) {
if (size > 0) {
logData(ivArray, 0, title, dateTimeFormatter);
}
} else if (target == Target.LAST) {
if (size > 0) {
logData(ivArray, size - 1, title, dateTimeFormatter);
}
} else {
for (int i = 0; i < size; i++) {
logData(ivArray, i, title, dateTimeFormatter);
}
}
}
}
private void logData(IntervalReading[] ivArray, int index, String title, DateTimeFormatter dateTimeFormatter) {
IntervalReading iv = ivArray[index];
logger.debug("{} {} value {}", title, iv.date.format(dateTimeFormatter), iv.value);
}
public void saveConfiguration(Configuration config) {
updateConfiguration(config);
}
}

View File

@ -12,13 +12,19 @@
https://espace-client-particuliers.enedis.fr/web/espace-particuliers/compteur-linky.
</description>
<channel-groups>
<channel-group typeId="main" id="main"/>
<channel-group typeId="daily" id="daily"/>
<channel-group typeId="weekly" id="weekly"/>
<channel-group typeId="monthly" id="monthly"/>
<channel-group typeId="yearly" id="yearly"/>
</channel-groups>
<config-description>
<parameter name="prmId" type="text" required="true">
<label>PrmId</label>
@ -29,6 +35,8 @@
<description>Your Enedis token (can be left empty, use the connection page to automatically fill it http://youopenhab/connectlinky)</description>
</parameter>
</config-description>
</thing-type>
<channel-group-type id="daily">
@ -106,6 +114,22 @@
</channels>
</channel-group-type>
<channel-group-type id="main">
<label>Main</label>
<channels>
<channel id="linkyTestSelect" typeId="typeTest">
<label>linkyTestSelect</label>
</channel>
</channels>
</channel-group-type>
<channel-type id="typeTest">
<item-type>String</item-type>
<label>Test Select</label>
<description>Test Select</description>
</channel-type>
<channel-type id="consumption">
<item-type>Number:Energy</item-type>
<label>Total Consumption</label>

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.7 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.2 KiB

View File

@ -12,11 +12,6 @@ html {
font-family: "Roboto", Helvetica, Arial, sans-serif;
}
.logo {
display: block;
margin: auto;
width: 100%;
}
.block {
border: 1px solid #bbb;
@ -37,7 +32,70 @@ html {
}
.button {
margin-left:30px;
margin-bottom: 10px;
float:left;
}
.olList {
margin-top:20px;
}
.olList li {
margin:20px;
}
.box {
float:left;
transform: translate(0%, -30%);
}
.box select {
background-color: #0563af;
color: white;
padding: 12px;
width: 350px;
border: none;
font-size: 20px;
box-shadow: 0 5px 25px rgba(0, 0, 0, 0.2);
-webkit-appearance: button;
appearance: button;
outline: none;
}
/* Style the arrow inside the select element: */
.box::before {
content: "\f13a";
font-family: FontAwesome;
position: absolute;
top: 0;
right: 0;
width: 50px;
height: 100%;
text-align: center;
font-size: 28px;
line-height: 45px;
color: rgba(255, 255, 255, 0.5);
background-color: rgba(255, 255, 255, 0.1);
pointer-events: none;
}
.logo {
display: inline;
}
.logoEnedis {
display: inline;
}
.logoTransfer {
display: inline;
margin-left:300px;
top: -30px;
}
.button a {
@ -51,22 +109,55 @@ html {
text-decoration: none;
}
</style>
<script language="javascript">
function retrieveToken()
{
var prmId = document.getElementById('prmId').value;
document.location= "${retrieveToken.uri}" + "&code=" + prmId;
}
</script>
</head>
<body>
<div class="logo">
<div class="logoEnedis">
<svg xmlns="http://www.w3.org/2000/svg" version="1.1" width="317px" height="109px" style="shape-rendering:geometricPrecision; text-rendering:geometricPrecision; image-rendering:optimizeQuality; fill-rule:evenodd; clip-rule:evenodd" xmlns:xlink="http://www.w3.org/1999/xlink">
<g><path style="opacity:1" fill="#fefefe" d="M -0.5,-0.5 C 105.167,-0.5 210.833,-0.5 316.5,-0.5C 316.5,52.5 316.5,105.5 316.5,158.5C 210.833,158.5 105.167,158.5 -0.5,158.5C -0.5,105.5 -0.5,52.5 -0.5,-0.5 Z"/></g>
<g><path style="opacity:1" fill="#1822dc" d="M 65.5,59.5 C 74.5,59.5 83.5,59.5 92.5,59.5C 92.7564,61.7925 92.4231,63.9592 91.5,66C 83.8333,66.3333 76.1667,66.6667 68.5,67C 67.5495,70.0567 67.2161,73.2234 67.5,76.5C 72.1667,76.5 76.8333,76.5 81.5,76.5C 81.7564,78.7925 81.4231,80.9592 80.5,83C 76.1794,83.499 71.8461,83.6657 67.5,83.5C 67.2317,86.1194 67.565,88.6194 68.5,91C 76.1667,91.3333 83.8333,91.6667 91.5,92C 92.4231,94.0408 92.7564,96.2075 92.5,98.5C 83.4938,98.6664 74.4938,98.4998 65.5,98C 63.714,97.2155 62.214,96.0488 61,94.5C 59.4133,84.9084 59.0799,75.2417 60,65.5C 61.3597,62.9774 63.193,60.9774 65.5,59.5 Z"/></g>
<g><path style="opacity:1" fill="#131fdb" d="M 97.5,59.5 C 104.841,59.3337 112.174,59.5003 119.5,60C 124.206,61.1045 127.373,63.9378 129,68.5C 129.5,78.4944 129.666,88.4944 129.5,98.5C 127.167,98.5 124.833,98.5 122.5,98.5C 122.948,88.7274 122.448,79.0607 121,69.5C 120.167,68.6667 119.333,67.8333 118.5,67C 113.845,66.5008 109.179,66.3342 104.5,66.5C 104.5,77.1667 104.5,87.8333 104.5,98.5C 102.167,98.5 99.8333,98.5 97.5,98.5C 97.5,85.5 97.5,72.5 97.5,59.5 Z"/></g>
<g><path style="opacity:1" fill="#96cd31" d="M 140.5,59.5 C 147.841,59.3337 155.174,59.5003 162.5,60C 167.105,62.208 169.105,65.8747 168.5,71C 169.147,76.4248 167.147,80.4248 162.5,83C 155.842,83.4996 149.175,83.6663 142.5,83.5C 142.269,86.7845 143.603,89.2845 146.5,91C 155.16,91.4998 163.827,91.6664 172.5,91.5C 172.5,93.8333 172.5,96.1667 172.5,98.5C 163.161,98.6665 153.827,98.4998 144.5,98C 137.824,95.4831 134.49,90.6497 134.5,83.5C 133.167,83.5 131.833,83.5 130.5,83.5C 130.5,81.1667 130.5,78.8333 130.5,76.5C 139.839,76.6665 149.173,76.4998 158.5,76C 160.703,73.24 161.036,70.24 159.5,67C 154.5,66.3333 149.5,66.3333 144.5,67C 142.771,68.7889 142.104,70.9556 142.5,73.5C 135.327,75.1611 132.827,72.4945 135,65.5C 136.36,62.9774 138.193,60.9774 140.5,59.5 Z"/></g>
<g><path style="opacity:1" fill="#1c23dc" d="M 173.5,59.5 C 198.925,53.4396 209.758,63.1062 206,88.5C 204.275,93.6148 200.775,96.7815 195.5,98C 188.174,98.4997 180.841,98.6663 173.5,98.5C 173.5,96.1667 173.5,93.8333 173.5,91.5C 180.508,91.6663 187.508,91.4996 194.5,91C 195.931,90.5348 197.097,89.7014 198,88.5C 198.915,82.0559 198.581,75.7226 197,69.5C 196.167,68.6667 195.333,67.8333 194.5,67C 189.845,66.5008 185.179,66.3342 180.5,66.5C 180.5,72.8333 180.5,79.1667 180.5,85.5C 178.167,85.5 175.833,85.5 173.5,85.5C 173.5,76.8333 173.5,68.1667 173.5,59.5 Z"/></g>
<g><path style="opacity:1" fill="#1c23dc" d="M 210.5,59.5 C 213.167,59.5 215.833,59.5 218.5,59.5C 218.5,61.8333 218.5,64.1667 218.5,66.5C 212.073,68.2382 209.406,65.9049 210.5,59.5 Z"/></g>
<g><path style="opacity:1" fill="#1620db" d="M 229.5,59.5 C 237.167,59.5 244.833,59.5 252.5,59.5C 252.5,61.8333 252.5,64.1667 252.5,66.5C 245.825,66.3337 239.158,66.5004 232.5,67C 230.909,70.2751 231.242,73.2751 233.5,76C 239.942,76.0827 246.275,76.7493 252.5,78C 256.776,82.8919 257.61,88.3919 255,94.5C 253.786,96.0488 252.286,97.2155 250.5,98C 241.506,98.4998 232.506,98.6664 223.5,98.5C 223.5,96.1667 223.5,93.8333 223.5,91.5C 231.752,91.8158 239.919,91.4825 248,90.5C 248.758,88.2305 248.591,86.0639 247.5,84C 241.5,83.6667 235.5,83.3333 229.5,83C 227.714,82.2155 226.214,81.0488 225,79.5C 223.445,74.6178 223.112,69.6178 224,64.5C 225.73,62.5981 227.563,60.9314 229.5,59.5 Z"/></g>
<g><path style="opacity:1" fill="#1e25dc" d="M 211.5,69.5 C 213.833,69.5 216.167,69.5 218.5,69.5C 218.5,79.1667 218.5,88.8333 218.5,98.5C 215.833,98.5 213.167,98.5 210.5,98.5C 210.194,88.7504 210.527,79.0838 211.5,69.5 Z"/></g>
</svg>
</div>
<div class="logoTransfer">
<svg class="logo" xmlns="http://www.w3.org/2000/svg" height="60px" version="1.1" viewBox="0 0 530 180">
<path style="stroke-width:0.625;stroke-linejoin:round;stroke:#000000;stroke-opacity:1;fill:#000000;fill-opacity:1;" d="m 195,90 l 15,10 c 0,0 -5,-5 0,-20 z m 10,3 l 120,0 l 0,-6 l -120,0 z m 130,-3 l -15,-10 c 0,0 5,5 0,20 z" />
<?xml version="1.0" encoding="utf-8"?><!-- Uploaded to: SVG Repo, www.svgrepo.com, Generator: SVG Repo Mixer Tools -->
<g transform="matrix(1.0671711,0,0,1.0802403,+350,+3.638968)">
<svg fill="#15BFFF" width="150px" height="150px" viewBox="0 0 24 24" role="img" xmlns="http://www.w3.org/2000/svg"><title>SmartThings icon</title>
<path d="M11.51 0C8.338 0 5.034.537 2.694 2.694.5 5.174 0 8.464 0 11.525v.942c0 3.165.537 6.499 2.694 8.84C5.188 23.513 8.494 24 11.569 24h.854c3.18 0 6.528-.53 8.883-2.694C23.514 18.811 24 15.5 24 12.423v-.853c0-3.18-.53-6.528-2.694-8.876C18.826.494 15.544 0 12.482 0zM12 3.505c1.244 0 2.256.99 2.256 2.206 0 1.065-.685 1.976-1.715 2.181v1.59c1.48.214 2.528 1.43 2.528 2.934 0 1.654-1.377 3-3.07 3-1.692 0-3.068-1.346-3.068-3 0-.17.017-.335.045-.497l-1.536-.488a2.258 2.258 0 01-1.962 1.12c-.237 0-.471-.037-.698-.11-1.183-.375-1.833-1.622-1.449-2.78a2.246 2.246 0 012.146-1.524c.237 0 .471.036.698.108a2.23 2.23 0 011.313 1.098c.204.391.282.823.232 1.249l1.535.488c.44-.86 1.378-1.453 2.384-1.599V7.892c-1.029-.205-1.896-1.116-1.896-2.181 0-1.217 1.012-2.206 2.257-2.206zm0 .882c-.747 0-1.354.594-1.354 1.324 0 .73.607 1.324 1.354 1.324.746 0 1.354-.594 1.354-1.324 0-.73-.608-1.324-1.354-1.324zm6.522 3.75c.98 0 1.843.613 2.146 1.525.186.56.138 1.158-.135 1.683-.274.526-.74.915-1.314 1.096-.227.073-.461.11-.698.11a2.258 2.258 0 01-1.962-1.12l-.634.201-.278-.838.632-.202a2.21 2.21 0 011.546-2.347c.226-.072.46-.108.697-.108zM5.476 9.02c-.588 0-1.105.368-1.287.915-.23.694.159 1.442.869 1.668.136.043.277.065.419.065.588 0 1.105-.368 1.287-.915a1.29 1.29 0 00-.081-1.01 1.338 1.338 0 00-.788-.658 1.377 1.377 0 00-.42-.065zm13.045 0c-.142 0-.282.021-.419.065a1.32 1.32 0 00-.869 1.668c.182.547.7.915 1.287.915.142 0 .283-.022.42-.065.344-.11.623-.343.787-.659.165-.315.193-.673.082-1.009a1.348 1.348 0 00-1.288-.915zM12 10.474c-1.095 0-1.986.871-1.986 1.942 0 1.07.89 1.941 1.986 1.941 1.094 0 1.985-.87 1.985-1.94 0-1.072-.89-1.943-1.985-1.943zm-2.706 4.831l.73.519-.39.526c.709.757.801 1.925.16 2.787-.423.57-1.106.91-1.827.91-.478 0-.937-.147-1.325-.422a2.177 2.177 0 01-.499-3.082 2.28 2.28 0 012.76-.71zm5.41 0l.392.528a2.285 2.285 0 012.76.71 2.178 2.178 0 01-.499 3.082 2.275 2.275 0 01-1.325.421 2.28 2.28 0 01-1.827-.91 2.172 2.172 0 01.16-2.785l-.39-.527zm-6.734 1.21c-.433 0-.843.205-1.097.547-.44.59-.304 1.42.3 1.849a1.37 1.37 0 001.891-.293c.44-.59.305-1.42-.3-1.85a1.364 1.364 0 00-.794-.252zm8.059 0c-.287 0-.561.088-.795.254a1.307 1.307 0 00-.299 1.849 1.371 1.371 0 001.891.293 1.307 1.307 0 00.3-1.85 1.37 1.37 0 00-1.097-.545Z"/>
</svg>
<g transform="matrix(0.8,0,0,0.8,+350,+3.638968)">
<svg xmlns="http://www.w3.org/2000/svg" version="1.1" width="225px" height="225px" style="shape-rendering:geometricPrecision; text-rendering:geometricPrecision; image-rendering:optimizeQuality; fill-rule:evenodd; clip-rule:evenodd" xmlns:xlink="http://www.w3.org/1999/xlink">
<g><path style="opacity:1" fill="#fdfefb" d="M -0.5,-0.5 C 11.5,-0.5 23.5,-0.5 35.5,-0.5C 16.4691,2.86542 4.46913,13.8654 -0.5,32.5C -0.5,21.5 -0.5,10.5 -0.5,-0.5 Z"/></g>
<g><path style="opacity:1" fill="#93c90f" d="M 35.5,-0.5 C 86.5,-0.5 137.5,-0.5 188.5,-0.5C 207.563,2.89939 219.563,13.8994 224.5,32.5C 224.5,76.8333 224.5,121.167 224.5,165.5C 182.165,165.667 139.832,165.5 97.5,165C 84.4772,161.742 76.8105,153.575 74.5,140.5C 74.5,137.5 74.5,134.5 74.5,131.5C 99.339,131.831 124.006,131.498 148.5,130.5C 166.806,127.692 178.306,117.358 183,99.5C 183.667,86.1667 183.667,72.8333 183,59.5C 178.86,43.3599 168.693,33.1932 152.5,29C 125.874,27.3783 99.2076,27.045 72.5,28C 45.8297,37.4849 35.3297,56.3183 41,84.5C 41.8333,85.3333 42.6667,86.1667 43.5,87C 52.5,87.6667 61.5,87.6667 70.5,87C 72,86.1667 73.1667,85 74,83.5C 74.3333,78.1667 74.6667,72.8333 75,67.5C 76.1049,64.0629 78.2716,61.5629 81.5,60C 100.768,58.3709 120.102,58.0376 139.5,59C 144.245,60.1148 147.412,62.9481 149,67.5C 149.667,75.5 149.667,83.5 149,91.5C 147.833,95.3333 145.333,97.8333 141.5,99C 94.2265,100.485 46.8932,100.985 -0.5,100.5C -0.5,77.8333 -0.5,55.1667 -0.5,32.5C 4.46913,13.8654 16.4691,2.86542 35.5,-0.5 Z"/></g>
<g><path style="opacity:1" fill="#fdfdfa" d="M 188.5,-0.5 C 200.5,-0.5 212.5,-0.5 224.5,-0.5C 224.5,10.5 224.5,21.5 224.5,32.5C 219.563,13.8994 207.563,2.89939 188.5,-0.5 Z"/></g>
<g><path style="opacity:1" fill="#fefefd" d="M 148.5,130.5 C 123.5,130.5 98.5,130.5 73.5,130.5C 73.1872,134.042 73.5206,137.375 74.5,140.5C 76.8105,153.575 84.4772,161.742 97.5,165C 139.832,165.5 182.165,165.667 224.5,165.5C 224.5,185.167 224.5,204.833 224.5,224.5C 213.167,224.5 201.833,224.5 190.5,224.5C 200.532,222.342 209.032,217.342 216,209.5C 218.112,206.273 219.945,202.94 221.5,199.5C 222.404,198.791 222.737,197.791 222.5,196.5C 182.5,196.5 142.5,196.5 102.5,196.5C 73.9388,194.76 54.1055,180.76 43,154.5C 41.0225,146.961 40.1892,139.294 40.5,131.5C 26.8333,131.5 13.1667,131.5 -0.5,131.5C -0.5,121.167 -0.5,110.833 -0.5,100.5C 46.8932,100.985 94.2265,100.485 141.5,99C 145.333,97.8333 147.833,95.3333 149,91.5C 149.667,83.5 149.667,75.5 149,67.5C 147.412,62.9481 144.245,60.1148 139.5,59C 120.102,58.0376 100.768,58.3709 81.5,60C 78.2716,61.5629 76.1049,64.0629 75,67.5C 74.6667,72.8333 74.3333,78.1667 74,83.5C 73.1667,85 72,86.1667 70.5,87C 61.5,87.6667 52.5,87.6667 43.5,87C 42.6667,86.1667 41.8333,85.3333 41,84.5C 35.3297,56.3183 45.8297,37.4849 72.5,28C 99.2076,27.045 125.874,27.3783 152.5,29C 168.693,33.1932 178.86,43.3599 183,59.5C 183.667,72.8333 183.667,86.1667 183,99.5C 178.306,117.358 166.806,127.692 148.5,130.5 Z"/></g>
<g><path style="opacity:1" fill="#eaf4d3" d="M 148.5,130.5 C 124.006,131.498 99.339,131.831 74.5,131.5C 74.5,134.5 74.5,137.5 74.5,140.5C 73.5206,137.375 73.1872,134.042 73.5,130.5C 98.5,130.5 123.5,130.5 148.5,130.5 Z"/></g>
<g><path style="opacity:1" fill="#93c90e" d="M -0.5,131.5 C 13.1667,131.5 26.8333,131.5 40.5,131.5C 40.1892,139.294 41.0225,146.961 43,154.5C 54.1055,180.76 73.9388,194.76 102.5,196.5C 142.344,196.835 182.011,197.835 221.5,199.5C 219.945,202.94 218.112,206.273 216,209.5C 209.032,217.342 200.532,222.342 190.5,224.5C 126.833,224.5 63.1667,224.5 -0.5,224.5C -0.5,193.5 -0.5,162.5 -0.5,131.5 Z"/></g>
<g><path style="opacity:1" fill="#b0d661" d="M 102.5,196.5 C 142.5,196.5 182.5,196.5 222.5,196.5C 222.737,197.791 222.404,198.791 221.5,199.5C 182.011,197.835 142.344,196.835 102.5,196.5 Z"/></g>
</svg>
</g>
<g transform="matrix(1.0671711,0,0,1.0802403,-242.07004,-3.638968)">
<path d="m 235.55996,122.32139 65.99684,-65.245439 9.61127,-9.494429 9.61126,9.494429 48.71786,48.127399 -0.0713,0.24287 -0.96104,2.79606 -1.09061,2.7291 -1.22617,2.66469 -1.34976,2.59982 -1.22704,2.10395 -52.40328,-51.76861 c -22.86589,22.605906 -45.73092,45.21138 -68.59595,67.81602 -2.64028,-3.84168 -5.09265,-7.79865 -7.01216,-12.06586 z" style="clip-rule:evenodd;fill:#e64a19;fill-rule:evenodd;stroke-width:0.87332809" />
<path d="m 311.16893,3.3686968 c 46.45255,0 84.33469,37.4250352 84.33469,83.3154142 0,45.887409 -37.88214,83.314139 -84.33469,83.314139 -25.37318,0 -48.18501,-11.17665 -63.66633,-28.79057 l 2.98008,-2.95501 2.16319,-2.13785 2.16749,-2.14377 2.16835,-2.14209 0.0884,-0.0865 c 13.00665,15.21415 32.43854,24.9082 54.09884,24.9082 39.00964,0 70.82522,-31.42855 70.82522,-69.966579 0,-38.540154 -31.81558,-69.969554 -70.82522,-69.969554 -39.01137,0 -70.82694,31.4294 -70.82694,69.969554 0,5.189918 0.58434,10.24717 1.67968,15.121749 l -4.69923,4.65206 -6.27207,6.2012 c -2.73168,-8.18222 -4.217,-16.909931 -4.217,-25.97501 0,-45.89038 37.88214,-83.3154145 84.33556,-83.3154145 z" style="clip-rule:evenodd;fill:#474747;fill-rule:evenodd;stroke-width:0.87332809" />
</g>
</svg>
</svg>
</div>
</div>
<br/><br/><br/>
<h3>Authorize openHAB Linky binding for Enedis</h3>
<p>On this page you can authorize the openHAB Linky binding to access your Enedis account.</p>
<p>
@ -75,19 +166,48 @@ html {
</p>
${error} ${authorizedUser}
<br/>
<p><b>This process need to be done for each electrical meter you have (each prmId).<br/>
This is a two step process:</b>
<ol class="olList">
<li>First you will need to do a consent on the enedis Site.<br/>
For this, click on the Authorize button.<br/>
You will be redirect to the enedis site. Login as usual with your userName / Password.<br/>
You will then be redirect to a consentment page. <br/>
You will have to select which prmId you would like to give the consent, click the checkbox, and then click on the validate button.<br/>
After this, you will be redirect to myelectricaldata information page.<br/>
</li>
<li>Second, come back to the /connectlinky page.<br/>
If you have multiple prm, select the PrmId in the combobox you want to authorize.v
Then click the Retrieve token button.<br/>
It will fill you linky thing configuration with the token.<br/>
</ol>
</p>
<br/><br/><br/>
<div class="block${bridge.authorized}">
Connect to Enedis:
<p>
<h1>Connect to Enedis:</h1>
<br/>
<br/>
<div>
<div class="box">
<b>Please select your prmId :</b>
<select id="prmId">
${prmId.Option}
</select>
</div>
<div class="button">
<a href=${authorize.uri}>Authorize Bridge
</a>
</div>
<br/><br/>
<div class="button">
<a href=${retrieveToken.uri}>Retrieve token
<a href="javascript:retrieveToken()">Retrieve token
</a>
</div>
</p>
</div>
</div>
</body>