Electrolyseur E-Pool Technologie Justsalt

Salut
oui mais je ne suis pas sur d avoir le niveaux pour faire ce que tu as fait !
si j’ai bien compris ton code est compiler dans « Arduino IDE »
et il y a un fichier de conf a remplir avant compilation !
c’est pas un peux plus compliqué pour les gens, que esphome ?

je vais regarder si je ne peux pas traiter les trames dans HA !si je galère de trop et si tu le permet, je m inspirerais de ton code ,et je te solliciterai peut êtres un peu si il y a des trucs que je ne comprend pas !

Après avoir passer beaucoup de temps a essayer d’améliorer le code pour récupérer les bonnes différentes valeurs je vais plutôt essayer de copier ce que fait @garsy020
et l’adapter au justsalt et solution rebrandé.

Même si cette solution me paraît plus complexe a réaliser, je pense qu’elle a de gros atouts de performance et de flexibilité.

@Brak27 si tu as d’autres commandes que la consigne de PH je prends

Je suis en congé pour 15 Jours donc je devrais avoir du temps pour essayer de comprendre le code et essayer de l adapter. Je posterai le nouveau code une fois arrivé au même niveau qu’actuellement.

Beau challenge en perspective. Bon courage.

Toujours dispo pour des tests si besoin

Oui j’ai la trame pour la commande du niveau de production, si ça t’intéresse je peux t’envoyer ça proprement demain. Je pense pouvoir trouver la commande pour mettre en mode boost également mais je ne l’ai pas sous la main

Salut
Bon , je me confronte déjà a des choix ! du coup je vais avoir besoin de vous
le justsalt n est pas interrogeable sur les service UID tant qu’il n est pas appairer

je me disais qu’il serait sympathique que le ESP détecte automatiquement le Justsalt
sans appairage je peux que récupérer que très peux d information
@Mac , nom , fabriquant
je pourait m’en sortir juste avec un filtre sur l adresse MAc mais essayons de faire les choses bien pour le plus grand nombre :slight_smile:

donc je préfèrerait me baser sur un regex du nom ou sur le fabriquant si il est le même pour les modèle rebrandé
pouvait vous installer nrf connect sur vos telephone et me faire un screen shot comme celui la

merci d’avance

C’est ça qu’il te faut ?

Just salt pro duo

yes c est parfait, merci
on a tous le même manufacturer et le même short Name
pour le moment je passe par la Mac adresse , mais j ai un soucis pour passer l appairage :slight_smile:

Salut @Ricky_D, je ne sais pas si mon code est un bon exemple, je ne suis pas développeur… Mais il est sur GitHub.
Par contre afin de rendre les choses plus simples, je t’invite a commencer a utiliser WifiManager , cela rendra la configuration beaucoup plus facile afin d’éviter que chacun compile le code. Il te permet de configurer le wifi via une interface et je crois même de mettre des paramètres.
Moi je l’ai pas fait, mais c’est une des prochaines étapes.

Dans mon code, je ne sais pas si c’est bien ou pas, mais afin de pouvoir gérer plusieurs tâches j’utilise TaskScheduler, donc ça peut être un peu déroutant au début, car ce n’est la simple boucle « loop » de arduino.

Voilà… Amuse-toi bien. :slight_smile:

Bon j’ai relancé le justsalt.
2 questions : comment trouver l’adresse MAC, j’utilise BLE Scanner j’ai ePool device avec DEVICE UUID et une suite de lettres et de chiffres séparés par des tirets, je trouve l’adresse mac dans cette suite ?
Dans le code à recopier il y a :
service_uuid: ‹ 09912756-7b32-4629-aeb1-b309d9a338ae ›
characteristic_uuid: ‹ ef785c24-22bb-463d-b651-0b7445ba091c ›
characteristic_uuid_write: ‹ 4d32c5e5-2bb5-45c6-8c89-6f59bb3930d2 ›
Je laisse ça ou bien je trouve les infos également quelque part ?
Merci

Bon l’adresse MAC je l’ai trouvé simplement sur l’affichage du boitier ePool, restent les uuid ??

Les UUID devraient être bon

ah d’accord, ce n’est donc pas propre à mon appareil

1 « J'aime »

salut
pour ceux qui veulent voici le début de code
il y a encore du taf , je ne suis pas sur de le faire ce WE mais je devait finir lundi
le code permet de détecter automatiquement le justsalt :slight_smile:
donc Wifi et serveur MQTT a remplir

#include <Arduino.h>


/** Electolyseur JustSalt & co
 *
 *  Passerelle Bt Justsalt to Mqtt
 *
 *  Created: Mai 2025
 *      Author: Ricky
 *
*/


#include <NimBLEDevice.h>
#include <ArduinoHA.h>
#include <WiFi.h>
#include <AsyncTCP.h>
#include <ESPAsyncWebServer.h>

const char* version = "0.0.1";
// Update these with values suitable for your wifi network.
const char* ssid = "wifi";
const char* password = "xxxxxxxxxxxxxxxxxxxx";

//Home Assistant integration
// configure here your HA params for connection to MQTT server
#define BROKER_ADDR IPAddress(192,168,50,11)
#define BROKER_USERNAME     "" // replace with your credentials
#define BROKER_PASSWORD     ""

//Unique device for HA integration
const byte deviceUniqID[] = { 0x94, 0xDE, 0xB8, 0xA1, 0x1A, 0xAC };

//justsalt service and char UUID
// The remote service we wish to connect to.
static  BLEUUID serviceUUID("09912756-7b32-4629-aeb1-b309d9a338ae");
// The characteristic of the remote service we are interested in.
static  BLEUUID    charUUID("ef785c24-22bb-463d-b651-0b7445ba091c");

WiFiClient wifiMQTT;
WiFiClient telnet;
WiFiServer telnetServer(23);

unsigned long previousMillis = 0;
unsigned long interval = 30000;

void scanEndedCB(NimBLEScanResults results);
void setup_wifi();
void reconnect_wifi();
void setupHaIntegration();
void setup_telnet();
void cb_handleTelnet();
void cb_loopHaIntegration();

static NimBLEAdvertisedDevice* advDevice;

static bool doConnect = false;
static uint32_t scanTime = 0; /** 0 = scan forever */

struct trame_value {
    uint8_t     V_id_00;
    float       V_id_01;
    float       V_id_02;
    float       V_id_03;
    float       V_id_06;
    float       V_id_08;
    float       V_id_09;
    float       V_id_0A;
    float       V_id_0B;
    float       V_id_0C;
    float       V_id_0D;
    float       V_id_0E;
    float       V_id_0F;
    float       V_id_10;
    float       V_id_11;
    float       V_id_12;
    float       V_id_13;
    float       V_id_1F;
    float       V_id_28;
    float       V_id_29;
    float       V_id_2A;
    float       V_id_30;
    float       V_id_31;
    float       V_id_32;
    float       V_id_33;
    float       V_id_35;
    float       V_id_37;
    float       V_id_39;
    float       V_id_50;
    float       V_id_51;
    float       V_id_5F;
    float       V_id_69;
    float       V_id_6A;
    float       V_id_8F;
    String      V_id_90;
    String      V_id_91;
    float       V_id_92;
    uint8_t     V_id_93;
    bool        V_id_93_b0;
    bool        V_id_93_b1;
    bool        V_id_93_b2;
    bool        V_id_93_b3;
    bool        V_id_93_b4;
    bool        V_id_93_b5;
    bool        V_id_93_b6;
    bool        V_id_93_b7;
    float       V_id_94;
    uint16_t       V_id_95;
    float       V_id_96;
    float       V_id_97;
    String      V_id_99;
    String      V_id_9A;
    float       V_id_9B;
    float       V_id_9C;
    String      V_id_9D;
    String      V_id_A3;
    float       V_id_B0;
    String      V_id_B1;
    String      V_id_D0;
    float       V_id_D1;
    String      V_id_E1;
    String      V_id_E2;
    String      V_id_E4;
    float       V_id_FE;
};
struct trame_value Electrovalue;
HADevice deviceHA;
// dernier paramètre pour le nombre de sensorMQTT à lister
HAMqtt  mqtt(wifiMQTT, deviceHA, 70);

//List of sensor for HA
HASensorNumber wifiStrength("pool_wifi_strength", HASensorNumber::PrecisionP2);
HASensor justsaltIp("pool_ip");
HASensorNumber temp("pool_temp",HASensorNumber::PrecisionP1) ; 
HASensorNumber ph("pool_ph",HASensorNumber::PrecisionP1);
HASensorNumber orp("pool_orp",HASensorNumber::PrecisionP0);
HASensorNumber sel("pool_sel",HASensorNumber::PrecisionP1);
HASensorNumber vol("pool_vol",HASensorNumber::PrecisionP0);
HASensorNumber phconsigne("pool_ph_consigne",HASensorNumber::PrecisionP1);
HASensorNumber acide("pool_acide",HASensorNumber::PrecisionP1);
HASensorNumber prod("pool_prod",HASensorNumber::PrecisionP0);
HASensorNumber orpconsigne("pool_orp_consigne",HASensorNumber::PrecisionP0);
HASensorNumber orpalarme("pool_orp_alarme",HASensorNumber::PrecisionP0);
HASensorNumber inversion("pool_inversion",HASensorNumber::PrecisionP0);
HASensorNumber temp02("pool_temp02",HASensorNumber::PrecisionP0);
HASensorNumber temp03("pool_temp03",HASensorNumber::PrecisionP0);
HASensorNumber temp08("pool_temp08",HASensorNumber::PrecisionP0);
HASensorNumber temp0B("pool_temp0B",HASensorNumber::PrecisionP0);
HASensorNumber temp0C("pool_temp0C",HASensorNumber::PrecisionP0);
HASensorNumber temp0D("pool_temp0D",HASensorNumber::PrecisionP0);
HASensorNumber temp0E("pool_temp0E",HASensorNumber::PrecisionP0);
HASensorNumber temp0F("pool_temp0F",HASensorNumber::PrecisionP0);
HASensorNumber temp10("pool_temp10",HASensorNumber::PrecisionP0);
HASensorNumber temp12("pool_temp12",HASensorNumber::PrecisionP0);
HASensorNumber temp13("pool_temp13",HASensorNumber::PrecisionP0);
HASensorNumber temp1F("pool_temp1F",HASensorNumber::PrecisionP0);
HASensorNumber temp28("pool_temp28",HASensorNumber::PrecisionP0);
HASensorNumber temp29("pool_temp29",HASensorNumber::PrecisionP0);
HASensorNumber temp2A("pool_temp2A",HASensorNumber::PrecisionP0);
HASensorNumber temp31("pool_temp31",HASensorNumber::PrecisionP0);
HASensorNumber temp50("pool_temp50",HASensorNumber::PrecisionP0);
HASensorNumber temp51("pool_temp51",HASensorNumber::PrecisionP0);
HASensorNumber temp5F("pool_temp5F",HASensorNumber::PrecisionP0);
HASensorNumber temp69("pool_temp69",HASensorNumber::PrecisionP0);
HASensorNumber temp6A("pool_temp6A",HASensorNumber::PrecisionP0);
HASensorNumber temp8F("pool_temp8F",HASensorNumber::PrecisionP0);
HASensor temp90("pool_temp90");
HASensor temp91("pool_temp91");
HASensorNumber temp92("pool_temp92",HASensorNumber::PrecisionP0);
HASensorNumber temp93("pool_temp93",HASensorNumber::PrecisionP0);
HABinarySensor temp93B0("false93B0");
HABinarySensor temp93B1("false93B1");
HABinarySensor temp93B2("false93B2");
HABinarySensor temp93B3("false93B3");
HABinarySensor temp93B4("false93B4");
HABinarySensor temp93B5("false93B5");
HABinarySensor temp93B6("false93B6");
HABinarySensor temp93B7("false93B7");
HASensorNumber temp94("pool_temp94",HASensorNumber::PrecisionP0);


void cb_handleTelnet() {
  if (telnetServer.hasClient()) {
    if (!telnet || !telnet.connected()) {
      if (telnet) telnet.stop();
      telnet = telnetServer.available();
    } else {
      telnetServer.available().stop();
    }
  }
}


void cb_loopAvaibilityMQTT(){
  mqtt.loop();
  //remove setAvaibility to use native check of Ha integration Shared availability
  deviceHA.setAvailability(true);

  //savoir si la connexion bluetooth est OK ou si le justsalt n'est pas sous tension.
  //bluetoothConnected.setState(connected);

}

void cb_loopHaIntegration(){

    //mqtt.loop();
    //remove setAvaibility to use native check of Ha integration Shared availability
    //deviceHA.setAvailability(true);
    wifiStrength.setValue(WiFi.RSSI());
    justsaltIp.setValue(WiFi.localIP().toString().c_str());

    ph.setValue(Electrovalue.V_id_01);
    temp02.setValue(Electrovalue.V_id_02);
    temp03.setValue(Electrovalue.V_id_03);
    orp.setValue(Electrovalue.V_id_06);
    temp08.setValue(Electrovalue.V_id_08);
    temp.setValue(Electrovalue.V_id_09);
    sel.setValue(Electrovalue.V_id_0A);
    temp0B.setValue(Electrovalue.V_id_0B);
    temp0C.setValue(Electrovalue.V_id_0C);
    temp0D.setValue(Electrovalue.V_id_0D);
    temp0E.setValue(Electrovalue.V_id_0E);
    temp0F.setValue(Electrovalue.V_id_0F);
    temp10.setValue(Electrovalue.V_id_10);
    vol.setValue(Electrovalue.V_id_11);
    temp12.setValue(Electrovalue.V_id_12);
    temp13.setValue(Electrovalue.V_id_13);
    temp1F.setValue(Electrovalue.V_id_1F);
    temp28.setValue(Electrovalue.V_id_28);
    temp29.setValue(Electrovalue.V_id_29);
    phconsigne.setValue(Electrovalue.V_id_30);
    temp31.setValue(Electrovalue.V_id_31);
    acide.setValue(Electrovalue.V_id_32);
    prod.setValue(Electrovalue.V_id_33);
    orpconsigne.setValue(Electrovalue.V_id_35);
    orpalarme.setValue(Electrovalue.V_id_37);
    inversion.setValue(Electrovalue.V_id_39);
    temp50.setValue(Electrovalue.V_id_50);
    temp51.setValue(Electrovalue.V_id_51);
    temp5F.setValue(Electrovalue.V_id_5F);
    temp69.setValue(Electrovalue.V_id_69);
    temp6A.setValue(Electrovalue.V_id_6A);
    temp8F.setValue(Electrovalue.V_id_8F);
    //temp90.setValue(Electrovalue.V_id_90);
    //temp91.setValue(Electrovalue.V_id_91);
    temp92.setValue(Electrovalue.V_id_92);
    temp93.setValue(Electrovalue.V_id_93);
    temp93B0.setCurrentState(Electrovalue.V_id_93_b0);
    temp93B1.setCurrentState(Electrovalue.V_id_93_b1);
    temp93B2.setCurrentState(Electrovalue.V_id_93_b2);
    temp93B3.setCurrentState(Electrovalue.V_id_93_b3);
    temp93B4.setCurrentState(Electrovalue.V_id_93_b4);
    temp93B5.setCurrentState(Electrovalue.V_id_93_b5);
    temp93B6.setCurrentState(Electrovalue.V_id_93_b6);
    temp93B7.setCurrentState(Electrovalue.V_id_93_b7);
    temp94.setValue(Electrovalue.V_id_94);
}

void setupHaIntegration(){
    //HA integration
    deviceHA.setUniqueId(deviceUniqID, sizeof(deviceUniqID));
    deviceHA.setName("justsalt");
    deviceHA.setSoftwareVersion(version);
    deviceHA.setModel("Electolyseur");
    deviceHA.setManufacturer("ricky");

    // This method enables availability for all device types registered on the device.
    // For example, if you have 5 sensors on the same device, you can enable
    // shared availability and change availability state of all sensors using
    // single method call "device.setAvailability(false|true)"
    deviceHA.enableSharedAvailability();

    // Optionally, you can enable MQTT LWT feature. If device will lose connection
    // to the broker, all device types related to it will be marked as offline in
    // the Home Assistant Panel.
    deviceHA.enableLastWill();

    wifiStrength.setName("Pool wifi Strength");
    wifiStrength.setDeviceClass("signal_strength");
    wifiStrength.setUnitOfMeasurement("dB");

    justsaltIp.setName("justsalt IP");
    justsaltIp.setIcon("mdi:ip-network");

        // HA integration List of Sensor
    temp.setName("Water temp");
    temp.setUnitOfMeasurement("°C");
    temp.setDeviceClass("temperature");
    temp.setIcon("mdi:thermometer");
    
    orp.setName("orp");
    orp.setUnitOfMeasurement("mV");
    orp.setIcon("mdi:alpha-r-box-outline");

    ph.setName("PH");
    ph.setIcon("mdi:ph");
    ph.setUnitOfMeasurement("ph");

    sel.setName("Sel");
    sel.setUnitOfMeasurement("g/L");
    sel.setIcon("mdi:alpha-s-box-outline");

    phconsigne.setName("PH Consigne");
    phconsigne.setIcon("mdi:ph");
    phconsigne.setUnitOfMeasurement("ph");

    orpconsigne.setName("orp Consigne");
    orpconsigne.setUnitOfMeasurement("mV");
    orpconsigne.setIcon("mdi:alpha-r-box-outline");
    
    orpalarme.setName("orp Alarme");
    orpalarme.setUnitOfMeasurement("h");
    orpalarme.setIcon("mdi:alpha-r-box-outline");
  
    vol.setName("volume piscine");
    vol.setUnitOfMeasurement("m3");
    vol.setIcon("mdi:alpha-r-box-outline");

    acide.setName("taux Acide");
    acide.setUnitOfMeasurement("%");
    acide.setStateClass("measurement");
    acide.setIcon("mdi:Skull-Crossbones");
    
    prod.setName("production");
    prod.setUnitOfMeasurement("%");
    prod.setStateClass("measurement");
    prod.setIcon("mdi:Cog-Outline");

    inversion.setName("inversion");
    inversion.setUnitOfMeasurement("%");

    temp02.setName("temp02");
    temp03.setName("temp03");
    temp08.setName("temp08");
    temp0B.setName("temp0B");
    temp0C.setName("temp0C");
    temp0D.setName("temp0D");
    temp0E.setName("temp0E");
    temp0F.setName("temp0F");
    temp10.setName("temp10");
    temp12.setName("temp12");
    temp13.setName("temp13");
    temp1F.setName("temp1F");
    temp28.setName("temp28");
    temp29.setName("temp29");
    temp31.setName("temp31");
    temp50.setName("temp50");
    temp51.setName("temp51");
    temp5F.setName("temp5F");
    temp69.setName("temp69");
    temp6A.setName("temp6A");
    temp8F.setName("temp8F");
    temp90.setName("temp90");
    temp91.setName("temp91");
    temp92.setName("temp92");
    temp93.setName("temp93");
    temp93B0.setName("temp93B0");
    temp93B1.setName("temp93B1");
    temp93B2.setName("temp93B2");
    temp93B3.setName("temp93B3");
    temp93B4.setName("temp93B4");
    temp93B5.setName("temp93B5");
    temp93B6.setName("temp93B6");
    temp93B7.setName("temp93B7");
    temp94.setName("temp94");

//   bluetoothConnected.setName("Bluetooth Status");

  mqtt.begin( BROKER_ADDR, BROKER_USERNAME, BROKER_PASSWORD );

}

void setup_telnet(){
  Serial.print("Ready! Use 'telnet ");
  Serial.print(WiFi.localIP());
  Serial.println(" 23' to connect");
}

void reconnect_wifi(){
   unsigned long currentMillis = millis();
  // if WiFi is down, try reconnecting every CHECK_WIFI_TIME seconds
  if ((WiFi.status() != WL_CONNECTED) && (currentMillis - previousMillis >=interval)) {
    Serial.print(millis());
    Serial.println("Reconnecting to WiFi...");
    WiFi.disconnect();
    WiFi.reconnect();
    #ifdef SYSLOG_SERVER
      syslog.log(LOG_INFO, "WIFI lost and reconnect automatically");
    #endif
    previousMillis = currentMillis;
  }
}

void setup_wifi() {

    // We start by connecting to a WiFi network
    Serial.println();
    Serial.print("Connecting to ");

    WiFi.mode(WIFI_STA);
    Serial.println(ssid);
    WiFi.begin(ssid, password);
    while (WiFi.status() != WL_CONNECTED) {
      delay(500);
      Serial.print(".");
    }
    randomSeed(micros());
    Serial.println("");
    Serial.println("WiFi connected");
    Serial.println("IP address: ");
    Serial.println(WiFi.localIP());


}


/**  None of these are required as they will be handled by the library with defaults. **
 **                       Remove as you see fit for your needs                        */
class ClientCallbacks : public NimBLEClientCallbacks {
    void onConnect(NimBLEClient* pClient) {
        Serial.println("Connected");
        /** After connection we should change the parameters if we don't need fast response times.
         *  These settings are 150ms interval, 0 latency, 450ms timout.
         *  Timeout should be a multiple of the interval, minimum is 100ms.
         *  I find a multiple of 3-5 * the interval works best for quick response/reconnect.
         *  Min interval: 120 * 1.25ms = 150, Max interval: 120 * 1.25ms = 150, 0 latency, 60 * 10ms = 600ms timeout
         */
        pClient->updateConnParams(120,120,0,60);
    };

    void onDisconnect(NimBLEClient* pClient) {
        Serial.print(pClient->getPeerAddress().toString().c_str());
        Serial.println(" Disconnected - Starting scan");
        NimBLEDevice::getScan()->start(scanTime, scanEndedCB);
    };

    /** Called when the peripheral requests a change to the connection parameters.
     *  Return true to accept and apply them or false to reject and keep
     *  the currently used parameters. Default will return true.
     */
    bool onConnParamsUpdateRequest(NimBLEClient* pClient, const ble_gap_upd_params* params) {
        if(params->itvl_min < 24) { /** 1.25ms units */
            return false;
        } else if(params->itvl_max > 40) { /** 1.25ms units */
            return false;
        } else if(params->latency > 2) { /** Number of intervals allowed to skip */
            return false;
        } else if(params->supervision_timeout > 100) { /** 10ms units */
            return false;
        }

        return true;
    };

    /********************* Security handled here **********************
    ****** Note: these are the same return values as defaults ********/
    uint32_t onPassKeyRequest(){
        Serial.println("Client Passkey Request");
        /** return the passkey to send to the server */
        return 123456;
    };

    bool onConfirmPIN(uint32_t pass_key){
        Serial.print("The passkey YES/NO number: ");
        Serial.println(pass_key);
    /** Return false if passkeys don't match. */
        return true;
    };

    /** Pairing process complete, we can check the results in ble_gap_conn_desc */
    void onAuthenticationComplete(ble_gap_conn_desc* desc){
        if(!desc->sec_state.encrypted) {
            Serial.println("Encrypt connection failed - disconnecting");
            /** Find the client with the connection handle provided in desc */
            NimBLEDevice::getClientByID(desc->conn_handle)->disconnect();
            return;
        }
    };
};


/** Define a class to handle the callbacks when advertisments are received */
class AdvertisedDeviceCallbacks: public NimBLEAdvertisedDeviceCallbacks {

    void onResult(NimBLEAdvertisedDevice* advertisedDevice) {
        Serial.print("Advertised Device found: ");
        Serial.println(advertisedDevice->toString().c_str());
        char* manufacturerdata = BLEUtils::buildHexData(NULL, (uint8_t*)advertisedDevice->getManufacturerData().data(), advertisedDevice->getManufacturerData().length());
        Serial.println(manufacturerdata);
        if ((strcmp(manufacturerdata , "ffff00202020202020202020202020202020202020") == 0) or (strcmp(manufacturerdata , "ffff01202020202020202020202020202020202020") == 0))  {
        //if(advertisedDevice->isAdvertisingService(NimBLEUUID("DEAD")))
        //{
            Serial.println("Found Our device");
            /** stop scan before connecting */
            NimBLEDevice::getScan()->stop();
            /** Save the device reference in a global for the client to use*/
            advDevice = advertisedDevice;
            /** Ready to connect now */
            doConnect = true;
        }
    };
};


/** Notification / Indication receiving handler callback */
void notifyCB(NimBLERemoteCharacteristic* pRemoteCharacteristic, uint8_t* pData, size_t length, bool isNotify){
    std::string str = (isNotify == true) ? "Notification" : "Indication";
    str += " from ";
    /** NimBLEAddress and NimBLEUUID have std::string operators */
    str += std::string(pRemoteCharacteristic->getRemoteService()->getClient()->getPeerAddress());
    str += ": Service = " + std::string(pRemoteCharacteristic->getRemoteService()->getUUID());
    str += ", Characteristic = " + std::string(pRemoteCharacteristic->getUUID());
    str += ", Value = " + std::string((char*)pData, length);
    Serial.println(str.c_str());
    Serial.print(" taille = ");
    Serial.println(length);

    if (length > 6){
        int index =3;
        while (index +2 < length) {
            uint8_t idvaleur = pData[index];
            int taillevaleur = pData[index + 1 ];
            
            switch (idvaleur) {
            case 0x00: { 
                Electrovalue.V_id_00 = 0;
                }break;
        
            case 0x01: {
                uint8_t phhex = pData[index + 2];
                float ph = static_cast<float>(phhex)/10;
                Electrovalue.V_id_01 = ph;
                Serial.print("PH : " );
                Serial.println(ph);
                }break;

            case 0x02: {
                uint8_t temphex = ((pData[index + 2]<< 8) + (pData[index +3]));
                float temp = static_cast<float>(temphex);
                Electrovalue.V_id_02 = temp;
                Serial.print("temp02 : " );
                Serial.println(temp);
                }break;

            case 0x03: {
                uint8_t temphex = pData[index + 2];
                float temp = static_cast<float>(temphex);
                Electrovalue.V_id_03 = temp; 
                }break;

            case 0x06: {
                uint8_t temphex = ((pData[index + 2]<< 8) + (pData[index + 3]));
                float temp = static_cast<float>(temphex);
                Electrovalue.V_id_06 = temp;
                Serial.print("ORP : " );
                Serial.println(temp);
                }break;

            case 0x08: {
                uint8_t temphex = pData[index + 2];
                float temp = static_cast<float>(temphex);
                Electrovalue.V_id_08 = temp;
                }break;

            case 0x09: {
                uint16_t tempeauhex = ((pData[index + 2]<< 8) + (pData[index +3]));
                float tempeau = static_cast<float>(tempeauhex)/10;
                Electrovalue.V_id_09 = tempeau;
                }break;
            
            case 0x0A: {
                uint8_t selhex = pData[index + 2] ;
                float sel = static_cast<float>(selhex)/10;
                Electrovalue.V_id_0A = sel;
                }break;

            case 0x0B: {
                uint8_t temphex = pData[index + 2];
                float temp = static_cast<float>(temphex);
                Electrovalue.V_id_0B = temp;
                }break;
            
            case 0x0C: {
                uint8_t temphex = pData[index + 2];
                float temp = static_cast<float>(temphex);
                Electrovalue.V_id_0C = temp;
                }break;

            case 0x0D: {
                uint8_t temphex = ((pData[index + 2]<< 8) + (pData[index +3]));
                float temp = static_cast<float>(temphex);
                Electrovalue.V_id_0D = temp;
                }break;

            case 0x0E: {
                uint8_t temphex = ((pData[index + 2]<< 8) + (pData[index +3]));
                float temp = static_cast<float>(temphex);
                Electrovalue.V_id_0E = temp;
                }break;

            case 0x0F: {
                uint8_t temphex = ((pData[index + 2]<< 8) + (pData[index +3]));
                float temp = static_cast<float>(temphex);
                Electrovalue.V_id_0F = temp;
                }break;
            
            case 0x10: {
                uint8_t temphex = ((pData[index + 2]<< 8) + (pData[index +3]));
                float temp = static_cast<float>(temphex);
                Electrovalue.V_id_10 = temp;
                }break;

            case 0x11: {
                uint16_t volhex = ((pData[index + 2]<< 8) + (pData[index +3]));
                float vol = static_cast<float>(volhex);
                Electrovalue.V_id_11 = vol;
                }break;
            
            case 0x12: {
                uint32_t temphex = (pData[index + 2]<< 24) + (pData[index + 3]<< 16)+ (pData[index + 4]<< 8) + (pData[index +5]);
                float temp = static_cast<float>(temphex);
                Electrovalue.V_id_12 = temp;
                }break;

            case 0x13: {
                uint32_t temphex = (pData[index + 2]<< 24) + (pData[index + 3]<< 16)+ (pData[index + 4]<< 8) + (pData[index +5]);
                float temp = static_cast<float>(temphex);
                //std::string tempstr = value_accuracy_to_string (temp,0);
                Electrovalue.V_id_13 = temp;
                }break;

            case 0x1F: {
                uint8_t temphex = ((pData[index + 2]<< 8) + (pData[index +3]));
                float temp = static_cast<float>(temphex);
                Electrovalue.V_id_1F = temp;
                }break;
            
            case 0x28: {
                uint8_t temphex = ((pData[index + 2]<< 8) + (pData[index +3]));
                float temp = static_cast<float>(temphex);
                Electrovalue.V_id_28 = temp;
                }break;
            
            case 0x29: {
                uint8_t temphex = pData[index + 2];
                float temp = static_cast<float>(temphex);
                Electrovalue.V_id_29 = temp;
                }break;
            
            case 0x2A: {
                uint8_t temphex = pData[index + 2];
                float temp = static_cast<float>(temphex);
                Electrovalue.V_id_2A = temp;
                }break;
            
            case 0x30: {
                uint8_t phchex = pData[index + 2] ;
                float phc = static_cast<float>(phchex)/10;
                Electrovalue.V_id_30 = phc;
                }break;
            
            case 0x31: {
                uint8_t temphex = pData[index + 2];
                float temp = static_cast<float>(temphex);
                Electrovalue.V_id_31 = temp;
                }break;         

            case 0x32: {
                uint8_t acidehex = pData[index + 2] ;
                float acide = static_cast<float>(acidehex);
                Electrovalue.V_id_32 = acide;
                }break;
            
            case 0x33: {
                uint8_t prodhex = pData[index + 2] ;
                float prod = static_cast<float>(prodhex);
                Electrovalue.V_id_33 = prod;
                }break;

            case 0x35: {
                uint8_t orpchex = pData[index + 2] ;
                float orpc = static_cast<float>(orpchex)*10;
                Electrovalue.V_id_35 = orpc;
                }break;
            
            case 0x37: {
                uint8_t alarmeorphex = pData[index + 2] ;
                float alarmeorp = static_cast<float>(alarmeorphex);
                Electrovalue.V_id_37 = alarmeorp;
                }break;
    
            case 0x39: {
                uint8_t inversionhex = pData[index + 2] ;
                float inversionval = static_cast<float>(inversionhex);
                Electrovalue.V_id_39 = inversionval;
                }break;

            case 0x50: {
                uint8_t temphex = pData[index + 2];
                float temp = static_cast<float>(temphex);
                Electrovalue.V_id_50 = temp;
                }break;

            case 0x51: {
                uint8_t temphex = pData[index + 2];
                float temp = static_cast<float>(temphex);
                Electrovalue.V_id_51 = temp;
                }break;

            case 0x5F: {
                uint8_t temphex = pData[index + 2];
                float temp = static_cast<float>(temphex);
                Electrovalue.V_id_5F = temp;
                }break;
            
            case 0x69: {
                uint32_t temphex = (pData[index + 2]<< 24) + (pData[index + 3]<< 16)+ (pData[index + 4]<< 8) + (pData[index +5]);
                float temp = static_cast<float>(temphex);
                Electrovalue.V_id_69 = temp;
                }break;

            case 0x6A: {
                uint8_t temphex = pData[index + 2];
                float temp = static_cast<float>(temphex);
                Electrovalue.V_id_6A = temp;
                }break;

            case 0x8F: {
                uint8_t temphex = pData[index + 2];
                float temp = static_cast<float>(temphex);
                Electrovalue.V_id_8F = temp;
                }break;
                
            case 0x90: {
                // 90.08.00.00.00.00.00.00.00.14.
                std::string tempstring = ""; 
                for ( int i = index + 2; i < index + 2 + taillevaleur ; i++ ) {
                    Serial.print( "data: " );
                    Serial.println( pData[i], HEX );
                    tempstring += pData[i];
                }
                temp90.setValue(tempstring.c_str());
                //Electrovalue.V_id_90 = tempstring.c_str();
                }break;

            case 0x91: {
                //  91.08.00.00.00.00.00.06.6F.C3.
                std::string tempstring = ""; 
                for ( int i = index + 2; i < index + 2 + taillevaleur ; i++ ) {
                    Serial.print( "data: " );
                    Serial.println( pData[i], HEX );
                    tempstring += pData[i];
                }
                temp91.setValue(tempstring.c_str());
                }break;
            
            case 0x92: {
                uint8_t temphex = pData[index + 2];
                float temp = static_cast<float>(temphex);
                Electrovalue.V_id_92 = temp;
                }break;

            case 0x93: {
                uint8_t temphex = ((pData[index + 2]<< 8) + (pData[index +3]));
                float temp = static_cast<float>(temphex);
                Electrovalue.V_id_93 = temp;
                Electrovalue.V_id_93_b0 = (bool)((temphex & 0x01) );
                Electrovalue.V_id_93_b1 = (bool)((temphex & 0x02) );
                Electrovalue.V_id_93_b2 = (bool)((temphex & 0x04) );
                Electrovalue.V_id_93_b3 = (bool)((temphex & 0x08) );
                Electrovalue.V_id_93_b4 = (bool)((temphex & 0x10) );
                Electrovalue.V_id_93_b5 = (bool)((temphex & 0x20) );
                Electrovalue.V_id_93_b6 = (bool)((temphex & 0x40) );
                Electrovalue.V_id_93_b7 = (bool)((temphex & 0x80) );
                }break;

            case 0x94: {
                uint8_t temphex = ((pData[index + 2]<< 8) + (pData[index +3]));
                float temp = static_cast<float>(temphex);
                Electrovalue.V_id_94 = temp;
                }break;

            // case 0x95: {
            //     uint16_t idcodehex = (pData[index + 2]<< 24) + (pData[index + 3]<< 16)+ (pData[index + 4]<< 8) + (pData[index +5]);
            //     float idcodefloat = static_cast<float>(idcodehex);
            //     std::string idcodestr = value_accuracy_to_string (idcodefloat,0);
            //     id(idcode).publish_state(idcodestr);
            //     }break;
            
            // case 0x96: {
            //     std::string verlog = rawhex.substr((index + 2 )* 2, 4);
            //     id(version_logiciel).publish_state(verlog);
            //     }break;
            
            // case 0x97: {
            //     std::string slaveval = rawhex.substr((index + 2 )* 2, 4);
            //     id(slave).publish_state(slaveval);
            //     }break;

            // case 0x99: {
            //     //99.16.47.45.4E.5F.30.35.32.32.2D.30.34.33.39.35.33.2D.30.30.33.00.00.00.
            //     std::string tempstring = value2.substr((index + 2 ), taillevaleur);
            //     id(JustSalt_nombt_textsensor).publish_state(tempstring.c_str());
            //     }break;

            // case 0x9A: {
            //     //9A.10.30.35.32.32.2D.30.34.33.39.35.33.2D.30.30.33.00.
            //     std::string tempstring = value2.substr((index + 2 ), taillevaleur);
            //     id(JustSalt_sn_textsensor).publish_state(tempstring.c_str());
            //     }break;

            // case 0x9B: {
            //     uint8_t temphex = ((pData[index + 2]<< 8) + (pData[index +3]));
            //     float temp = static_cast<float>(temphex);
            //     id(JustSalt_temp9b_sensor).publish_state(temp);
            //     }break;

            // case 0x9C: {
            //     uint8_t temphex = ((pData[index + 2]<< 8) + (pData[index +3]));
            //     float temp = static_cast<float>(temphex);
            //     id(JustSalt_temp9c_sensor).publish_state(temp);
            //     }break;

            // case 0x9D: {
            //     //  9D.08.00.00.00.00.00.00.01.FF
            //     std::string tempstring = rawhex.substr((index + 2 )* 2, 8);
            //     id(JustSalt_9d_textsensor).publish_state(tempstring);
            //     }break;
            
            // case 0xA3: {
            //     //  E1.0F.18.04.11.11.00.33.00.00.88.00.F8.00.00.00.00
            //     std::string tempstring = rawhex.substr((index + 2 )* 2, 15);
            //     id(JustSalt_a3_textsensor).publish_state(tempstring);
            //     }break;
            
            // case 0xB0: {
            //     uint8_t temphex = pData[index + 2];
            //     float temp = static_cast<float>(temphex);
            //     id(JustSalt_tempb0_sensor).publish_state(temp);
            //     }break;
    
            // case 0xB1: {
            //     std::string tempstring = rawhex.substr((index + 2 )* 2, 12);
            //     id(JustSalt_macbt_textsensor).publish_state(tempstring);
            //     }break;
            
            // case 0xD0: {
            //     //D0.06.30.00.00.00.00.00
            //     std::string tempstring = rawhex.substr((index + 2 )* 2, 6);
            //     id(JustSalt_d0_textsensor).publish_state(tempstring);
            //     }break;

            // case 0xD1: {
            //     uint8_t temphex = pData[index + 2];
            //     float temp = static_cast<float>(temphex);
            //     id(JustSalt_tempd1_sensor).publish_state(temp);
            //     }break;
    
            
            // case 0xFE: {
            //     uint8_t temphex = pData[index + 2];
            //     float temp = static_cast<float>(temphex);
            //     id(JustSalt_tempfe_sensor).publish_state(temp);
            //     }break;
    
            // case 0xE1: {
            //     //  E1.0F.18.04.11.11.00.33.00.00.88.00.F8.00.00.00.00
            //     std::string tempstring = rawhex.substr((index + 2 )* 2, 30);
            //     id(JustSalt_e1_textsensor).publish_state(tempstring);
            //     //uint8_t temphex = ((pData[index + 9]<< 8) + (pData[index +10]));
            //     //float temp = static_cast<float>(temphex);
            //     //id(tempe1o89b0).publish_state((bool)((temphex & 0x01) ));
            //     //id(tempe1o89b1).publish_state((bool)((temphex & 0x02) ));
            //     //id(tempe1o89b2).publish_state((bool)((temphex & 0x04) ));
            //     //id(tempe1o89b3).publish_state((bool)((temphex & 0x08) ));
            //     //id(tempe1o89b4).publish_state((bool)((temphex & 0x10) ));
            //     //id(tempe1o89b5).publish_state((bool)((temphex & 0x20) ));
            //     //id(tempe1o89b6).publish_state((bool)((temphex & 0x40) ));
            //     //id(tempe1o89b7).publish_state((bool)((temphex & 0x80) ));
            //     }break;
                
            // case 0xE2: {
            //     // E2.0F.18.04.16.0A.22.10.00.00.00.41.3E.DC.00.00.00
            //     std::string tempstring = rawhex.substr((index + 2 )* 2, 30);
            //     id(JustSalt_e2_textsensor).publish_state(tempstring);
            //     }break;

            // case 0xE4: {
            //     // E4.0F.18.04.12.15.00.00.46.00.0B.13.00.00.00.00.00
            //     std::string tempstring = rawhex.substr((index + 2 )* 2, 30);
            //     id(JustSalt_e4_textsensor).publish_state(tempstring);
            //     }break;

            default: {
                Serial.print( "idvaleur Non implementee " );
                Serial.println(idvaleur);
                };
            }
            index = index + 2 + taillevaleur ;

        }
        Serial.println("fin traitement trame");
        cb_loopHaIntegration();
        Serial.println("fin cb_loopHaIntegration");
        
    }
}

/** Callback to process the results of the last scan or restart it */
void scanEndedCB(NimBLEScanResults results){
    Serial.println("Scan Ended");
}


/** Create a single global instance of the callback class to be used by all clients */
static ClientCallbacks clientCB;


/** Handles the provisioning of clients and connects / interfaces with the server */
bool connectToServer() {
    NimBLEClient* pClient = nullptr;

    /** Check if we have a client we should reuse first **/
    if(NimBLEDevice::getClientListSize()) {
        /** Special case when we already know this device, we send false as the
         *  second argument in connect() to prevent refreshing the service database.
         *  This saves considerable time and power.
         */
        pClient = NimBLEDevice::getClientByPeerAddress(advDevice->getAddress());
        if(pClient){
            if(!pClient->connect(advDevice, false)) {
                Serial.println("Reconnect failed");
                return false;
            }
            Serial.println("Reconnected client");
        }
        /** We don't already have a client that knows this device,
         *  we will check for a client that is disconnected that we can use.
         */
        else {
            pClient = NimBLEDevice::getDisconnectedClient();
        }
    }

    /** No client to reuse? Create a new one. */
    if(!pClient) {
        if(NimBLEDevice::getClientListSize() >= NIMBLE_MAX_CONNECTIONS) {
            Serial.println("Max clients reached - no more connections available");
            return false;
        }

        pClient = NimBLEDevice::createClient();

        Serial.println("New client created");

        pClient->setClientCallbacks(&clientCB, false);
        /** Set initial connection parameters: These settings are 15ms interval, 0 latency, 120ms timout.
         *  These settings are safe for 3 clients to connect reliably, can go faster if you have less
         *  connections. Timeout should be a multiple of the interval, minimum is 100ms.
         *  Min interval: 12 * 1.25ms = 15, Max interval: 12 * 1.25ms = 15, 0 latency, 51 * 10ms = 510ms timeout
         */
        pClient->setConnectionParams(12,12,0,51);
        /** Set how long we are willing to wait for the connection to complete (seconds), default is 30. */
        pClient->setConnectTimeout(5);


        if (!pClient->connect(advDevice)) {
            /** Created a client but failed to connect, don't need to keep it as it has no data */
            NimBLEDevice::deleteClient(pClient);
            Serial.println("Failed to connect, deleted client");
            return false;
        }
    }

    if(!pClient->isConnected()) {
        if (!pClient->connect(advDevice)) {
            Serial.println("Failed to connect");
            return false;
        }
    }

    Serial.print("Connected to: ");
    Serial.println(pClient->getPeerAddress().toString().c_str());
    Serial.print("RSSI: ");
    Serial.println(pClient->getRssi());

    /** Now we can read/write/subscribe the charateristics of the services we are interested in */
    NimBLERemoteService* pSvc = nullptr;
    NimBLERemoteCharacteristic* pChr = nullptr;
    NimBLERemoteDescriptor* pDsc = nullptr;

    //pSvc = pClient->getService("DEAD");
   
    pSvc = pClient->getService("09912756-7b32-4629-aeb1-b309d9a338ae");
    if(pSvc) {     /** make sure it's not null */
        //pChr = pSvc->getCharacteristic("BEEF");
        pChr = pSvc->getCharacteristic("ef785c24-22bb-463d-b651-0b7445ba091c");
        
        if(pChr) {     /** make sure it's not null */
            if(pChr->canRead()) {
                std::string value = pChr->readValue();
                Serial.print(pChr->getUUID().toString().c_str());
                Serial.print(" Value: ");
                Serial.println(value.c_str());
            }

            // if(pChr->canWrite()) {
            //     if(pChr->writeValue("Tasty")) {
            //         Serial.print("Wrote new value to: ");
            //         Serial.println(pChr->getUUID().toString().c_str());
            //     }
            //     else {
            //         /** Disconnect if write failed */
            //         pClient->disconnect();
            //         return false;
            //     }

            //     if(pChr->canRead()) {
            //         Serial.print("The value of: ");
            //         Serial.print(pChr->getUUID().toString().c_str());
            //         Serial.print(" is now: ");
            //         Serial.println(pChr->readValue().c_str());
            //     }
            // }

            /** registerForNotify() has been deprecated and replaced with subscribe() / unsubscribe().
             *  Subscribe parameter defaults are: notifications=true, notifyCallback=nullptr, response=false.
             *  Unsubscribe parameter defaults are: response=false.
             */
            if(pChr->canNotify()) {
                //if(!pChr->registerForNotify(notifyCB)) {
                if(!pChr->subscribe(true, notifyCB)) {
                    /** Disconnect if subscribe failed */
                    pClient->disconnect();
                    return false;
                }
            }
            else if(pChr->canIndicate()) {
                /** Send false as first argument to subscribe to indications instead of notifications */
                //if(!pChr->registerForNotify(notifyCB, false)) {
                if(!pChr->subscribe(false, notifyCB)) {
                    /** Disconnect if subscribe failed */
                    pClient->disconnect();
                    return false;
                }
            }
        }

    } else {
        Serial.println("DEAD service not found.");
    }

    pSvc = pClient->getService("BAAD");
    if(pSvc) {     /** make sure it's not null */
        pChr = pSvc->getCharacteristic("F00D");

        if(pChr) {     /** make sure it's not null */
            if(pChr->canRead()) {
                Serial.print(pChr->getUUID().toString().c_str());
                Serial.print(" Value: ");
                Serial.println(pChr->readValue().c_str());
            }

            pDsc = pChr->getDescriptor(NimBLEUUID("C01D"));
            if(pDsc) {   /** make sure it's not null */
                Serial.print("Descriptor: ");
                Serial.print(pDsc->getUUID().toString().c_str());
                Serial.print(" Value: ");
                Serial.println(pDsc->readValue().c_str());
            }

            if(pChr->canWrite()) {
                if(pChr->writeValue("No tip!")) {
                    Serial.print("Wrote new value to: ");
                    Serial.println(pChr->getUUID().toString().c_str());
                }
                else {
                    /** Disconnect if write failed */
                    pClient->disconnect();
                    return false;
                }

                if(pChr->canRead()) {
                    Serial.print("The value of: ");
                    Serial.print(pChr->getUUID().toString().c_str());
                    Serial.print(" is now: ");
                    Serial.println(pChr->readValue().c_str());
                }
            }

            /** registerForNotify() has been deprecated and replaced with subscribe() / unsubscribe().
             *  Subscribe parameter defaults are: notifications=true, notifyCallback=nullptr, response=false.
             *  Unsubscribe parameter defaults are: response=false.
             */
            if(pChr->canNotify()) {
                //if(!pChr->registerForNotify(notifyCB)) {
                if(!pChr->subscribe(true, notifyCB)) {
                    /** Disconnect if subscribe failed */
                    pClient->disconnect();
                    return false;
                }
            }
            else if(pChr->canIndicate()) {
                /** Send false as first argument to subscribe to indications instead of notifications */
                //if(!pChr->registerForNotify(notifyCB, false)) {
                if(!pChr->subscribe(false, notifyCB)) {
                    /** Disconnect if subscribe failed */
                    pClient->disconnect();
                    return false;
                }
            }
        }

    } else {
        Serial.println("BAAD service not found.");
    }

    Serial.println("Done with this device!");
    return true;
}

void setup (){
    Serial.begin(115200);
    setup_wifi();
    setup_telnet();
    setupHaIntegration();

    Serial.println("Starting NimBLE Client");
    /** Initialize NimBLE, no device name spcified as we are not advertising */
    NimBLEDevice::init("");

    /** Set the IO capabilities of the device, each option will trigger a different pairing method.
     *  BLE_HS_IO_KEYBOARD_ONLY    - Passkey pairing
     *  BLE_HS_IO_DISPLAY_YESNO   - Numeric comparison pairing
     *  BLE_HS_IO_NO_INPUT_OUTPUT - DEFAULT setting - just works pairing
     */
    //NimBLEDevice::setSecurityIOCap(BLE_HS_IO_KEYBOARD_ONLY); // use passkey
    NimBLEDevice::setSecurityIOCap(BLE_HS_IO_DISPLAY_YESNO); //use numeric comparison

    /** 2 different ways to set security - both calls achieve the same result.
     *  no bonding, no man in the middle protection, secure connections.
     *
     *  These are the default values, only shown here for demonstration.
     */
    NimBLEDevice::setSecurityAuth(true, true, true);
    NimBLEDevice::setSecurityAuth(BLE_SM_PAIR_AUTHREQ_BOND | BLE_SM_PAIR_AUTHREQ_MITM | BLE_SM_PAIR_AUTHREQ_SC);

    /** Optional: set the transmit power, default is 3db */
#ifdef ESP_PLATFORM
    NimBLEDevice::setPower(ESP_PWR_LVL_P9); /** +9db */
#else
    NimBLEDevice::setPower(9); /** +9db */
#endif

    /** Optional: set any devices you don't want to get advertisments from */
    // NimBLEDevice::addIgnored(NimBLEAddress ("aa:bb:cc:dd:ee:ff"));

    /** create new scan */
    NimBLEScan* pScan = NimBLEDevice::getScan();

    /** create a callback that gets called when advertisers are found */
    pScan->setAdvertisedDeviceCallbacks(new AdvertisedDeviceCallbacks());

    /** Set scan interval (how often) and window (how long) in milliseconds */
    pScan->setInterval(45);
    pScan->setWindow(15);

    /** Active scan will gather scan response data from advertisers
     *  but will use more energy from both devices
     */
    pScan->setActiveScan(true);
    /** Start scanning for advertisers for the scan time specified (in seconds) 0 = forever
     *  Optional callback for when scanning stops.
     */
    pScan->start(scanTime, scanEndedCB);
    
}


void loop (){
    /** Loop here until we find a device we want to connect to */
    while(!doConnect){
        delay(1);
    }
    mqtt.loop();
    doConnect = false;

    /** Found a device we want to connect to, do it now */
    if(connectToServer()) {
        Serial.println("Success! we should now be getting notifications, scanning for more!");
    } else {
        Serial.println("Failed to connect, starting scan");
    }

    NimBLEDevice::getScan()->start(scanTime,scanEndedCB);
}

ca donne ca pour le moment


Bonjour, je suis intéressé par le code,mais c vrai que le travail que tu as accompli sur le esphome est déjà très bien pour ma part.

Ce que comprend cest avoir accès à vraiment tous les paramètres c’est ça qui te manque ?

salut
le projet ce déroule en plusieurs phase (et je ne suis pas sur qu’il soit complet cette été)

Phase analyse
on est encore dedans

  • connexion a l’électrolyseur → OK
  • récupération des info → OK
  • comprendre les info → en cours
    – certaine valeur sont identifier SEL ,PH, ORP ,température de l’eau, mais il nous reste encore bcp a trouver , les différentes alarmes , l’injection acide , le boost …
  • configuration via HA , seul la consigne PH est actuellement identifier

le projets était au départ sur ESPhome mais malheureusement certain traitement prenais trop de temps et était coupé par la réception des notification BLE ,pour l analyse nous avons besoin pour le moment de récupérer toutes les valeur afin de les comprendre du coup je refait le code sous « arduino en c++ »

état du dev en cours :
je suis en train d’essayer de reproduire tous ce que l on faisait avec ESPHome , je n en suis plus très loin
des que ca sera fini , je rendrai le code plus sexy , car la il est a vomir :slight_smile:
j ai bcp de fonction a créer et a optimiser les switch …
ensuite il faut que je remettre la partie Configue via HA ( pour le moment configue PH , mais @Brak27
en a identifier d autre je crois.

Phase implémentation
une fois toutes les valeur repérer
nous pourrons faire le choix de rester En C++ ou de repasser en ESPHome suivant la pertinence des valeur récupérer et nous pourrons cibler que celle si (donc moins de traitement)

donc si vous identifier des valeurs , a des évènement ou des fonctions n’hésité surtout pas
c est aussi pour ca que je partage le code, ensemble nous avançons plus vite, surtout que nous n avons pas tous la même configuration !

bonjour
j ai bien avancé et ça continue :slight_smile:
voilà ma réflexion du matin !
Nous avons bcp de conf différents et l’application epool nous propose que les réglages lié a notre configuration !
donc dans nos trame nous devons avoir une valeur qui ne change jamais et qui nous indique la conf matériel des capteurs
si vous avez des trames Fixe dans les « temp » merci de les partager
ça me fera gagner du temps

Avancement du projet
ce matin : ,
la lecture de toutes les valeurs est implémentée (il me reste 2 valeur buger)
le découpage en binaire des valeurs qui nous interagissaient est encore bugger
le reboot ESP par HA est KO
j ai commencé a travailler sur l 'écriture des consignes (ne reste plus que le send en BLE)
telnet OK
elegantota OK

je devrais pouvoir vous donner ca dans la journée :slight_smile:

bonjour,
pas de soucis pour te donner les infos dont tu as besoin.
Si j’ai bien suivi, on est plus dans esphome, pourrais tu nous refaire un petit tuto pour l’installation du nouveau code ?

oui c est prévu,
mais j essaie de regarder si il y a pas moyen de passer par ESPhome pour faire l’installation ce serai plus simple pour la plus part des gens
car pour le moment j utilise VScode et platform IO qui a besoin de python
du coup si je peux vous éviter ca je le ferais :slight_smile: , dans le cas contraire je vais essayer de faire une autre solution en essayant de rentrer aucune donnée dans le code mais ca passera par un portail captif pour rentrer les infos ! Wifi , serveur MQTT !
en tous cas il faudra installer si c est pas déjà fait un serveur MQTT , moi j’utilise Mosquitto

en attendant le code ESPhome te permet toujours d extraire les données :slight_smile: