Gérer ses radiateurs électriques avec Home Assistant + TIKO

Bonjour à tous,
Je voudrai partager avec vous un retour d’expérience avec le service TIKO (récemment racheté par ENEDIS), qui permet de gérer ses vieux radiateurs à distance, et que j’utilise depuis maintenant 1 mois.

Tiko propose à ceux qui ont au moins 3 radiateurs électriques chez eux de venir installer un dispositif permettant de gérer ses radiateurs à distance. Ils facturent l’installation 9€, et le service est sans abonnement et sans engagement. Voir les détails de l’offre sur leur site : https://tiko.fr/

A ce prix, l’état prend en charge une bonne partie des frais. L’intérêt est probablement de pouvoir délester des radiateurs connectés, afin d’avoir un maillon plus faible et précis qu’un quartier complet en cas de surcharge de consommation qui conduirait à devoir effectivement réaliser des coupures à grande échelle.

Le dispositif en question est composé d’un hub à brancher en RJ45 à sa box (ou à un hub), d’un module de pilotage branché à chaque radiateur, et d’un capteur de température/humidité par pièce. Les modules de pilotage des radiateurs communiquent avec le hub par CPL (courant porteur).

En complément, une APP est fournie pour permettre la gestion à distance de ses radiateurs :

  • Gestion de la température par pièce
  • Activation de modes HORS-GEL / ABSENT/ BOOST / OFF
  • Gestion de programmation horaires ↔ températures cibles par pièces

J’ai fait installer cette solution à mon bureau, et franchement c’est vraiment super pratique.

La première question que je me suis posée une fois le dispositif opérationnel c’est comment connecter ce truc à Home Assistant. Ne trouvant pas d’API ou docs de leur côté, j’ai remonté le fil en partant de leur APP, et me suis rendu compte qu’un API existait, et était utilisable.

J’ai dev une page PHP qui fait office de gateway avec leur API, et permet de récupérer les infos des radiateurs + gérer les différentes fonctions de l’APP (hors programmation horaires des pièces franchement bien intégrée dans leur APP). Cette page aide également à générer le YAML nécessaire à l’intégration des fonctionnalités/sensors dans Home Assistant.

Je n’ai pas vraiment envie d’hébergera cette solution, mais suis prêt à la mettre à dispo de qui souhaite s’en servir… Ce qui implique en l’état de pouvoir héberger quelque part la page PHP qui fait office de gateway vers leur API.

Je ne maitrise pas du tout Python, et ne saurai pas par ou commencer pour en faire une intégration, mais si quelqu’un est tenté pour s’y atteler, je serai ravi de l’assister dans cette tâche…

Ci-dessous, un exemple de l’intégration sur Lovelace :

5 « J'aime »

Bonjour noiwid,
Je serais très intéressé par la création d’une intégration avec un serveur NodeJS, afin de pouvoir ensuite contrôler mes radiateurs via HomeKit/HomeBridge. Serait-il possible d’accéder à ce que tu as pu réaliser afin de voir comment se présente l’API ? J’ai moi même beaucoup cherché comment celle-ci fonctionne et suis content de voir qu’elle existe bel et bien :slight_smile:
Merci pour ton travail !

Hello,

Alors, pour commencer, il faut t’identifier auprès de leur API.

Ce que j’ai fait en PHP, c’est une petite fonction, qui se charge des appels vers leur API.
Je me sert de cette fonction pour m’identifier, récupérer des infos de leur API ou modifier les réglages des radiateurs.

Voilà à quoi ressemble la fonction :

  function f_tiko($json, $token=false, $account_id=false){
   if(!$account_id) {
      $url = "https://particuliers-tiko.fr/api/v3/graphql/";
      $method = "POST";
   }
   else {
      $url = "https://particuliers-tiko.fr/api/v3/properties/".$account_id."/consumption_summary/";
      $method = "GET";
   }
   $headers = array(
      'Content-Type:application/json',
      // 'User-agent:Mozilla/5.0 (Linux; Android 13; Pixel 4a Build/T1B3.221003.003; wv) AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0 Chrome/106.0.5249.126 Mobile Safari/537.36' // needed with tiko.ch api endpoint
     );
   if($token)
      $headers[] = 'Authorization: token '.$token; 

   $chObj = curl_init();
   curl_setopt($chObj, CURLOPT_SSL_VERIFYPEER, FALSE); // needed localy with wamp
   curl_setopt($chObj, CURLOPT_URL, $url);
   curl_setopt($chObj, CURLOPT_FRESH_CONNECT, TRUE);
   curl_setopt($chObj, CURLOPT_RETURNTRANSFER, true);    
   curl_setopt($chObj, CURLOPT_CUSTOMREQUEST, $method);
   curl_setopt($chObj, CURLOPT_POSTFIELDS, $json);
   curl_setopt($chObj, CURLOPT_HTTPHEADER, $headers); 
   $json = curl_exec($chObj);
   curl_close($chObj);
   return json_decode($json,true);
}

Le premier paramètre $json permet de passer les paramètres souhaités à l’API de TIKO
Le paramètre $token, optionnel est à passer une fois identifié, il est récupéré lors du login
Le paramètre $account_id, optionnel est également à passer pour certaines commandes, il est récupéré lors du login.

Voici comment je m’identifie ensuite :

 // login params, email/password are same as thoose used for the Mobile App.
$json = '{ 
   "variables":{
      "email":"'.$email.'",
      "password":"'.$password.'",
      "langCode": "fr",
      "retainSession": true
   },
   "query":"mutation LogIn($email: String!, $password: String!, $langCode: String, $retainSession: Boolean) {\n  logIn(\n    input: {email: $email, password: $password, langCode: $langCode, retainSession: $retainSession}\n  ) {\n    settings {\n      client {\n        name\n        __typename\n      }\n      support {\n        serviceActive\n        phone\n        email\n        __typename\n      }\n      __typename\n    }\n    user {\n      id\n      clientCustomerId\n      agreements\n      properties {\n        id\n        allInstalled\n        __typename\n      }\n      inbox(modes: [\"app\"]) {\n        actions {\n          label\n          type\n          value\n          __typename\n        }\n        id\n        lockUser\n        maxNumberOfSkip\n        messageBody\n        messageHeader\n        __typename\n      }\n      __typename\n    }\n    token\n    firstLogin\n    __typename\n  }\n}\n"
}';
// Call the function that'll send request to TIKO
$login = f_tiko($json);  

// get account_id & token in login feedback
$account_id = $login["data"]["logIn"]["user"]["properties"][0]["id"];
$token = $login["data"]["logIn"]["token"];

Une fois identifié, tu peux récupérer les statuts/infos/réglages de tes radiateurs :

/*******************************
* GET GLOBAL ENERGY CONSUMPTION
*******************************/
if(!$_REQUEST["room_id"] and !isset($_REQUEST["mode"]) and $_REQUEST["consumption"]){
  $datas = f_tiko(false, $token, $account_id);
  $feedback = $datas["response"];
  $logs = file_put_contents($serv_root.$prod."/include/logs/".date("Ymd-His")."-getDatas.log", print_r($feedback, true));
}

/**********************************
* GET heaters datas + global modes
***********************************/
elseif(!$_REQUEST["room_id"] and !isset($_REQUEST["mode"]) and !isset($_REQUEST["install"])){
  $json = '{
     "operationName":"GET_PROPERTY_OVERVIEW_DECENTRALISED",
     "variables":{ "id":'.$account_id.' },
     "query":"query GET_PROPERTY_OVERVIEW_DECENTRALISED($id: Int!, $excludeRooms: [Int]) {\n  settings {\n    benchmark {\n      isEnabled\n      __typename\n    }\n    __typename\n  }\n  property(id: $id) {\n    id\n    mode\n    mboxDisconnected\n    isNetatmoAuthorised\n    netatmoLinkAccountUrl\n    isSinapsiEnabled\n    isSinapsiAuthorised\n    allInstalled\n    ownerPermission\n    constructionYear\n    surfaceArea\n    floors\n    valueProposition\n    address {\n      id\n      street\n      number\n      city\n      zipCode\n      __typename\n    }\n    tips {\n      id\n      tip\n      __typename\n    }\n    ...CentralisedDevicesCompact\n    rooms(excludeRooms: $excludeRooms) {\n      id\n      name\n      type\n      color\n      heaters\n      hasTemperatureSchedule\n      currentTemperatureDegrees\n      targetTemperatureDegrees\n      humidity\n      sensors\n      devices {\n        id\n        code\n        type\n        name\n        mac\n        __typename\n      }\n      ...Status\n      __typename\n    }\n    __typename\n  }\n}\n\nfragment CentralisedDevicesCompact on PropertyType {\n  devices(excludeDecentralised: true) {\n    id\n    code\n    type\n    name\n    mac\n    __typename\n  }\n  externalDevices {\n    id\n    name\n    __typename\n  }\n  __typename\n}\n\nfragment Status on RoomType {\n  status {\n    disconnected\n    heaterDisconnected\n    heatingOperating\n    sensorBatteryLow\n    sensorDisconnected\n    temporaryAdjustment\n    __typename\n  }\n  __typename\n}"
  }';
  $rooms = f_tiko($json, $token);  
  $modes = $rooms["data"]["property"]["mode"];
  foreach($modes as $k=>$v){
     $feedback[$k] = $v?true:false;
  }
  //$feedback["settings"] = $rooms["data"]["property"]["mode"];
  foreach($rooms["data"]["property"]["rooms"] as $k=>$v){
     $feedback[str_replace("-","",clean($v["name"]))."_cur"] = $v["currentTemperatureDegrees"];
     $feedback[str_replace("-","",clean($v["name"]))."_tar"] = $v["targetTemperatureDegrees"];
     $feedback[str_replace("-","",clean($v["name"]))."_dry"] = $v["humidity"];
     $feedback[str_replace("-","",clean($v["name"]))."_on"] = $v["status"]["heatingOperating"]?true:false;
  }
}

Ou modifier les réglages :

/**************************
   * CHANGE ROOM TEMPERATURE
   *
   * @param int $room_id target room
   * @param decimal $temperature target temperature
   * @return boolean
   **************************/
  if($_REQUEST["room_id"] and $_REQUEST["temperature"]>0){
      $json = '{ 
           "variables":{
              "propertyId": '.$account_id.',
              "roomId":'.$_REQUEST["room_id"].',
              "temperature":'.$_REQUEST["temperature"].'
           },
           "query":"mutation SET_PROPERTY_ROOM_ADJUST_TEMPERATURE($propertyId: Int!, $roomId: Int!, $temperature: Float!) {\n  setRoomAdjustTemperature(\n    input: {propertyId: $propertyId, roomId: $roomId, temperature: $temperature}\n  ) {\n    id\n    adjustTemperature {\n      active\n      endDateTime\n      temperature\n      __typename\n    }\n    __typename\n  }\n}"
        }';
        $temperature = f_tiko($json, $token);  
        if($temperature["data"]["setRoomAdjustTemperature"]) 
           $feedback["status"]=true;
        else 
           $feedback["status"]=false;

     $logs = file_put_contents($serv_root.$prod."/include/logs/".date("Ymd-His")."-changeRoomTemp_".$_REQUEST["room_id"].".log", print_r($feedback, true));
}

  /*********************************
   * CHANGE GLOBAL MODE
   *
   * @param enum $mode 
   *     frost
   *     boost
   *     absence
   *     disableHeating
   * @return boolean
   *********************************/
  if(isset($_REQUEST["mode"])){
     if($_REQUEST["mode"]) $mode = $_REQUEST["mode"];
     else $mode = "false";
      $json = '{ 
           "variables":{
              "propertyId": '.$account_id.',
              "mode":"'.$mode.'"
           },
           "query":"mutation SET_PROPERTY_MODE($propertyId: Int!, $mode: String!) {\n  setPropertyMode(input: {propertyId: $propertyId, mode: $mode}) {\n    id\n    mode\n    __typename\n  }\n}"
        }';
        $feedback_mode = f_tiko($json, $token);  
        $feedback["mode"]=$mode!="false"?$mode:false;
        if($feedback_mode["data"]["setPropertyMode"]) 
           $feedback["status"]=true;
        else 
           $feedback["status"]=false;
     $logs = file_put_contents($serv_root.$prod."/include/logs/".date("Ymd-His")."-changeMode_".$mode.".log", $_SERVER['REMOTE_ADDR']."\n".$_SERVER['HTTP_USER_AGENT']."\n".basename($_SERVER['REQUEST_URI'])."\n\n".print_r($feedback, true));
  }

Si tu n’es pas familier du PHP, les paramètres $_REQUEST["xxxx’'] sont récupérés depuis l’URL d’appel de la page (paramètres GET) ou via des post de formulaires (paramètres POST).
Mon programme PHP s’appelle tiko.php, pour récupérer les infos d’un radiateur en particulier, je dois appeler la page comme ca :

https://mondomaine.com/tiko.php?room_id=xxxxxx

Tu récuperera l’ID de chaque pièce via le second appel à l’API, une fois que tu seras identifié.

N’hésite pas à demander si tout n’est pas bien clair…

Attention, ce qui est à l’intérieur des query envoyées à TIKO via les appels json n’est pas à modifier, les données dedans ne viennent pas de PHP, c’est à laisser tel quel… même si tu fais tes appels autrement… Ce que tu peux modifier dans les appels c’est la partie variables des appels json.

ex :

"query":"mutation SET_PROPERTY_ROOM_ADJUST_TEMPERATURE($propertyId: Int!, $roomId: Int!, $temperature: Float!) {\n  setRoomAdjustTemperature(\n    input: {propertyId: $propertyId, roomId: $roomId, temperature: $temperature}\n  ) {\n    id\n    adjustTemperature {\n      active\n      endDateTime\n      temperature\n      __typename\n    }\n    __typename\n  }\n}"

Bonjour à tous,

Ayant des radiateurs électriques et une installation Home Assistant déjà en place, je souhaiterais domotiser les radiateurs et les intégrer dans HA. J’avais à l’époque cherché et trouvé un produit qui s’appelle Heatzy mais sans grande conviction pour son intégration dans HA.

@noiwid en effet ton intégration parait intéressante, comment la mettre en place si je choisis la solution Tiko ?

Merci d’avance pour vos retours !

@noiwid, solution très interessante, en effet je commencais aussi à regarder cette solution tiko. Le seul bemol était la partie api non disponible, mais avec ton reverse, cela semblerait integrable facile…et jouable en python sans trop de difficultés
Sinon, aurais-tu une photo d’une installation, car j’ai un peu de doute quand à la taille du boitier sous chaque radiateur …

Hello
Voici comment ca rend :

Sur un tout petit radiateur :


(vu de debout, on ne le voit pas)

Sur un radiateur de taille intermédiaire :


Merci pour les photos. C’est le poseur qui impose de l éloigné du radiateur ou c’est ton choix ? Car je trouve que cela fait gros…

@noiwid Comment intégrer ton install tiko dans HA ?

Hello,
J’ai enfin retrouvé un peu de temps pour bosser sur ce package, qui est disponible ici :

J’ai enrichi le script qui dispose désormais d’un installeur, qui génère le package complet pour home assistant.

Il faut installer ce script PHP sur une URL, puis y accéder :
Step 1 / Le script demande les identifiants login/password de l’APP TIKO, et crée un fichier tiko.env avec les variables + URL & Token du endpoint
Step 2 / L’utilisateur est redirigé vers la page de setup du script, qui fourni le code complet du package tiko.yaml, ainsi que les cartes lovelace à installer, avec toutes les instructions détaillées.

Attention, ce script doit resté hébergé pour que le lien entre Home Assistant et l’API de TIKO reste effectif, ce script sert de gateway entre les deux.

Si vous avez des questions, n’hésitez pas !

2 « J'aime »

j’ai laissé l’installateur faire comme il voulait, j’imagine que le boitier est déporté car trop épais pour tenir derrière le radiateur…

Merci beaucoup noiwid pour travail !
l’intégration fonctionne nickel, c’est que du bonheur :slight_smile:

1 « J'aime »

Salut à tous !

Je tenais déjà à remercier @noiwid pour son super travail. C’est grâce à lui que j’ai pu comprendre le fonctionnement de l’API de Tiko (merci la documentation inexistante de leur part !) et que j’ai pu mettre en place ce petit projet.

J’ai pris le temps de réaliser une petite API RESTful qui permet l’accès facile aux données Tiko, accessible sur GitHub avec l’identifiant paulchartres/hass-tiko (apparemment pas le droit de poster de liens, donc il vous faudra le trouver comme ça…)

C’est un projet en cours de développement et il reste encore sûrement pas mal de bugs, mais j’aimerais à terme en faire quelque chose d’assez robuste et facilement récupérable sur Docker.
C’est réalisé en Typescript avec NodeJS et Express, avec sa petite interface Swagger UI pour directement aller piocher la donnée nécessaire. Je me suis fortement inspiré du générateur de configuration YAML de noiwid pour écrire le mien, là encore, chapeau, la config est superbe et marche au top !

C’est actuellement hébergé sur mon serveur privé et utilisé sur mon instance de Home Assistant, sous Docker, donc facilement maintenable. J’ai pour projet de publier l’image sur Docker Hub, histoire que n’importe qui puisse héberger son propre pont HA/Tiko.

Petite précision, mon installation Tiko a été faite par Engie, le point d’accès n’est donc pas le même. C’est pour ça que j’ai fait en sorte que le serveur sur lequel l’API va taper soit configurable par une variable d’environnement.

N’hésitez pas à remonter les bugs ou les améliorations possibles, je maintiens cet outil comme tous mes autres projets :slight_smile:

Hello @paulchartres,
Merci pour ton retour et tes commentaires :pray: Je me suis pas mal pris la tête sur ce truc, déjà pour comprendre comment fonctionnait leur API (notamment l’authentification), mais aussi pour arriver à trouver comment intégrer tout ça dans un workflow H.A.

C’est top qu’une intégration soit développée pour prendre la suite de mon projet PHP, car bien que fonctionnel, c’est pas évident à déployer, et nécessite un serveur web accessible. Et moi qui voulait voir comment monter des intégrations H.A, je crois que j’ai trouvé le lab idéal avec ton intégration, pour le coup je devrai pouvoir m’y retrouver :sweat_smile:

Concernant le endpoint chez TIKO, cela ne fonctionnait pas pour toi avec https://particuliers-tiko.fr/api/v3/ ?
J’ai aussi repéré qu’il était également accessible via https://tiko.ch/api/v3/ qui pointe vers la même IP que le .fr, mais effectivement c’est pas le cas de https://portal-engie.tiko.ch. Es tu en Suisse?

Hello,

Un plugin pour Homebridge serait super, je n’ai malheuresement pas les connaissances pour le développer. J’utilise Homekit avec un ipad allumé en permanance, et il est penible de devoir switcher entre home et l’appli Tiko…

Hello Uhuru5!
Désolé pour la réponse un peu tardive, j’espère quand même pouvoir t’aider.
Bien que je n’utilise pas Homebridge, ma solution pour avoir accès à mes radiateurs sur Homekit a été d’activer l’intégration Homekit dans Home Assistant après avoir ajouté mes radiateurs dessus. Aucun souci, j’arrive a voir la température actuelle et à la régler depuis mon iPhone.
Je verrai si je trouverai le temps de faire un petit plugin Homebridge, mais en attendant cette technique marche plutôt pas mal !

Merci pour ta réponse, je n’ai pas Home Assistant pour l’instant, j’utilise seulement homebrige.
Le portage est-il compliqué? Ce que tu as développé est sous nodeJS.

Bonjour à tous
Installation ENFIN réalisée par Tiko ce matin, impeccable.
Intégration sur Home Assistant via le script et les instructions de @noiwid parfaitement réussie, un grand MERCI !


1 « J'aime »

Bonjour, merci pour les informations. Tres intéressant. En ce qui concerne l’installation proprement dite, je vois les boîtiers CPL prêt des radiateurs mais pas de sondes de température. Qu’en est-il ?

hello,
ils fournissent également des sondes de température (mobiles) pour chaque pièce, avec un support pour l’accrocher (mur, côté de placard…) :

c’est grâce à ces sondes que leur système peut piloter la termpérature de chaque pièce, avec le package que j’ai fait, tu récupères ces sondes comme des entités dans H.A…

Hello,
je viens de release une nouvelle version du package, qui respecte la nouvelle manière de déclarer les switchs et sensors command_line, qui sera très prochainement nécessaire pour la release 2023.8, et qui permet de dégager les alertes qui sont apparues depuis la release 2023.6 de H.A.

J’ai également ajouté deux nouveaux sensors qui calculent l’écart de conso du jour vs hier à la même heure, ainsi que du mois en cours vs mois dernier à la même date, pensez-donc bien à également remplacer la carte lovelace :wink: