Création d'un protocole libre pour NOUS les MAKERS en 868MHz avec module low cost lora et protocole de transmission esp3

de souvenir la mm chose que la trame série Mysensors (à peu de choses près)
ma passerelle:

  • esp32
  • 2.4ghz (surtout pour dev)
  • 868Mhz Lora compatible (vieux RFM95)

Les nodes sont en RFM69CW ou si besoin d’une plus grande portée du Lora compatible.

En réalité pour le dev, j’ai plusieurs gw, toutes multi RF:

  • la sensebender GW officielle developpée par un membre de l’équipe (ATSAM en ethernet)
  • la gw esp32 dont j’ai parlé (wifi)
  • un dongle nrf52840 que j’ai dev qui embarque une puce LORA pour le dual RF (usb)

punaise à ce prix là interessant

oui; il a une très bonne portée, quand la partie RF est bien faite :slight_smile:
j’ai 50m, pile bouton, facile à travers plusieurs murs (d’un batiment à un autre) en direct sans répéteur.
quand c’est pour plus de puissance alors c’est mieux de passer en puce LORA, car plus efficient que le rfm69H

rfm69 c’est ce qu’il y a (ou du moins ce qu’il y avait) dans les alarmes Ajax :wink:

d’accord mais si on peut y mettre une antenne à gain (oui je sais c’est pas bien) ou mieux un system de peroquetage c’est encore mieux
je sui an train de regarder

ça serait surement interessant de dessiner un pcb generique

de ce genre
mais avec un esp car les atmega c’est « outof stock »

mieux dessiné plus compact

tiens ça y est je suis dessus interessant il faut que je digère un peu

ça serait surement interessant de dessiner un pcb generique

ça existe déjà, il y en a plein.
Ici par exemple, il s’agit de la partie hardware opensource MySensors

j’espère toujours avoir un peu plus de temps pour MySensors… mais pour le fun voici qq captures de mes passerelles.
Ca date d’il y a quelques années maintenant…

ESP32 + 2.4ghz + 868Mhz + IR + CAN + gadgets (usb/Wifi MQTT)

Et la webapp hebergée dans l’esp32 (Vue.Js + Bulma CSS, frontend websocket)

NRF52840 (2.4ghz 20dB) + 868Mhz LORA (usb)

J’ai dev pleins de modules aussi, multicapteurs, modules volets etc
On peut faire beaucoup de choses avec MySensors :slight_smile:

4 « J'aime »

https://lowpowerlab.com/shop/product/99
très interessant en base pour les capteurs

1 « J'aime »

Matériellement m’y sensor est très intéressant, au niveau des trames c’est enocean qui est carrément mieux affuté.
Surtout ça possible automnomie en cas de disfonctionnement de la box domotique

1 « J'aime »

Bon plusieurs choses sont intêressantes
en effet le mpatériel utilisé est le plus commun
en terme de protocole on pourrait imaginer un transformateur de data avec node-red
le protocole my sensor n’est pas dégueulasse mais me semble avoir des faiblesses, il faudrai intégrer un système d’UID qui me semble être une protection indispensable
récupérer la mac d’un esp, pas de problème, mais d’un rfm69HCW ou d’un sx1276 c’est difficile acr apparament inexistant, mais comme il faut un atmega pour les piloter on pourrait plutot ce baser sur leur sn pour fabriquer un UID
bon pour faire des tester je vais commencer par me renseigner sur la location d’un serveur.
faisons français donc OVH, c’est payant mais bon c’est pour la « communautée »

voyons ce que propose OVH
OVHcloud)

une solution starter me parait suffisante pour commencer, et puis c’est mon porte-monnaie d’abord. Et puis ils ont dût régler leur problème d’incendie maintenant ( j’aime l’humour noir)
est-ce que je tente la debian 11?

Est-ce que j’installe juste un serveur MQTT et node-red ou j’installe aussi un jeedom avec les plugin my sensor et Enocean?

Est-ce que je garde les port d’origine ou j’en mets d’autre pour éviter les attaques, bon là oui

1 « J'aime »

ou est-ce que les admin de @jeedom veulent bien nous ouvrir une vps?
je tente on ne sais jamais
Si ils sont à la lecture, je pense qu’il nous faudrait une vps avec un jeedom, un node-red, un serveur mqtt avec loget pass sans crytage ssl dans un premier temps, et avec des port modififié comme 2210 pour le ssh…
Peut être qu’ils ont déjà ça?
Il faudrait diffuser les accès uniquement en PV

1 « J'aime »

Je vais ouvrir un docker attent

Surtout qu’il ne faut que Mosquitto.

1 « J'aime »

Et node-red aussi je pense

Bon posons les bases
après discussion avec @Nivek2 et @krosand, on va ouvrir un vps avec docker chez contabo pour 6€ par mois
image

après discussion si on doit être une bonne dizaine à travailler dessus autant avoir un debit correct et une rom NVMe.
le choix est fait donc le temps que l’on prépare ça, je pense que milieu de semain prochaine on sera bon


bon je suis officiellement propriétaire d’un vps de chez contabo à 7.18 ttc par mois
avec un docker et debian 11
on va pourvoir jouer maintenant

pour rappel c’est un serveur de test que je fermerai un jour, il ne faut pas prendre ce serveur comme quelque chose à long terme

bref

pour la passerelle je vous donne ma solution
surement adaptable avec d’autre matériel
j’ai pris 2 ttgo lora32, qui étaient bien moins cher en début d’année

tranformé en passerelle LoRa MQTT


pour le code il est sous arduino, simple gratuit

//Libraries for LoRa
#include <SPI.h>
#include <LoRa.h>

//Libraries for OLED Display
#include <Wire.h>
#include <Adafruit_GFX.h>
#include <Adafruit_SSD1306.h>

#include <WiFi.h>
#include <ESP32Ping.h>
#include <PubSubClient.h>
//#include "EEPROM.h"
//#define EEPROM_SIZE 128
#include <Preferences.h>
#include <esp_int_wdt.h>
#include <esp_task_wdt.h>

//define the pins used by the LoRa transceiver module
#define SCK 5
#define MISO 19
#define MOSI 27
#define SS 18
#define RST 14
#define DIO0 26

//433E6 for Asia
//866E6 for Europe
//915E6 for North America
#define BAND 868E6

//OLED pins
#define OLED_SDA 4
#define OLED_SCL 15 
#define OLED_RST 16
#define SCREEN_WIDTH 128 // OLED display width, in pixels
#define SCREEN_HEIGHT 64 // OLED display height, in pixels


#include <BLEDevice.h>
#include <BLEServer.h>
#include <BLEUtils.h>
#include <BLE2902.h>

BLEServer *pServer = NULL;
BLECharacteristic *pCharacteristic;
bool deviceConnected = false;
bool oldDeviceConnected = false;
uint8_t txValue = 0;
const int wifiAddr = 10;
char  CrLf[2] = {0x0D,0x0A};
String ssids_array[50];
String network_string;
char charBuf[50];
int scanWifi;
String MQTTserver;
String MQTTport;
String telnetClient;
String MQTT_USER;
String MQTT_PASSWORD;
  String receivedData;

// See the following for generating UUIDs:
// https://www.uuidgenerator.net/

#define SERVICE_UUID           "6E400001-B5A3-F393-E0A9-E50E24DCCA9E" // UART service UUID
#define CHARACTERISTIC_UUID_RX "6E400002-B5A3-F393-E0A9-E50E24DCCA9E"
#define CHARACTERISTIC_UUID_TX "6E400003-B5A3-F393-E0A9-E50E24DCCA9E"

Adafruit_SSD1306 display(SCREEN_WIDTH, SCREEN_HEIGHT, &Wire, OLED_RST);

String LoRaSend;
String LoRaData;
String BLEreceiv;
int flagBLE;

Preferences preferences;
WiFiClient wifiClient;
PubSubClient client(wifiClient);

class MyServerCallbacks: public BLEServerCallbacks {
    void onConnect(BLEServer* pServer) {
      Serial.println("reco");
      deviceConnected = true;
    };

    void onDisconnect(BLEServer* pServer) {
      Serial.println("deco");
      deviceConnected = false;
    }
};

class MyCallbacks: public BLECharacteristicCallbacks {
  void onWrite(BLECharacteristic *pCharacteristic){
    std::string value = pCharacteristic->getValue();

    if(value.length() > 0){
      Serial.print("Rx : ");
      Serial.println(value.c_str());
      BLEreceiv = value.c_str();
      flagBLE = 1;
      
    if(BLEreceiv.startsWith("scan,")){ 
      Serial.println("ok test");       
      scanWifi = 1;      
    }
      
    if(BLEreceiv.startsWith("55,")){
      Serial.print("start config : ");
      writeString(wifiAddr, value.c_str()); 
    hard_restart();     
    }
    }
  }
  
  void writeString(int add, String data){
    /*int _size = data.length();
    for(int i=0; i<_size; i++){
      EEPROM.write(add+i, data[i]);
    }
    EEPROM.write(add+_size, '\0');
    EEPROM.commit();*/
    preferences.putString("Data", data);

    Serial.println("Network Credentials have been Saved");

    preferences.end();
  }

  void hard_restart() {
    esp_task_wdt_init(1,true);
    esp_task_wdt_add(NULL);
    while(true);
  }
};

void reconnect() {
  // Loop until we're reconnected
  while (!client.connected()) {
    Serial.print("Attempting MQTT connection...");
    // Create a random client ID
    String clientId = "ESP32Client-";
    clientId += String(random(0xffff), HEX);
    char charBuff1[MQTT_USER.length()+1];
    char charBuff2[MQTT_PASSWORD.length()+1];
    MQTT_USER.toCharArray(charBuff1,MQTT_USER.length()+1);
    MQTT_PASSWORD.toCharArray(charBuff2,MQTT_PASSWORD.length()+1);
    // Attempt to connect
    if (client.connect(clientId.c_str(),charBuff1,charBuff2)) {
      Serial.println("connected");
      // ... and resubscribe
    String stringTwo = WiFi.macAddress();
    stringTwo += "/gateway/rx";
    char charBuf[stringTwo.length()+1];
    stringTwo.toCharArray(charBuf, stringTwo.length()+1);
    client.subscribe(charBuf);
    } else {
      Serial.print("failed, rc=");
      Serial.print(client.state());
      Serial.println(" try again in 5 seconds");
      // Wait 5 seconds before retrying
      delay(5000);
    }
  }
}


void wifiToBLE(){
        WiFi.mode(WIFI_STA);
        // WiFi.scanNetworks will return the number of networks found
            delay(500);
        int n =  WiFi.scanNetworks();
          if (n == 0) {
            pCharacteristic->setValue("no networks found .");
            pCharacteristic->notify();
            pCharacteristic->setValue(CrLf);
            pCharacteristic->notify();
          } else {
            pCharacteristic->setValue("networks found .");
            pCharacteristic->notify();
            pCharacteristic->setValue(CrLf);
            pCharacteristic->notify();
            delay(500);
            for (int i = 0; i < n; ++i) {
              ssids_array[i + 1] = WiFi.SSID(i);
              Serial.print(i + 1);
              Serial.print(": ");
              Serial.println(ssids_array[i + 1]);
              network_string = i + 1;
              network_string = network_string + ": " + WiFi.SSID(i) + " (RSSI:" + WiFi.RSSI(i) + ")";
                      
              network_string.toCharArray(charBuf, network_string.length()+1);
              pCharacteristic->setValue(charBuf);
              pCharacteristic->notify();
              pCharacteristic->setValue(CrLf);
              pCharacteristic->notify();
            }
         }
}

void setup() {     
  scanWifi = 0;      
  flagBLE = 0;
  //initialize Serial Monitor
  Serial.begin(115200);

  preferences.begin("Credentials", false);
 
  receivedData = preferences.getString("Data", "");
  Serial.print("Read Data:");
  Serial.println(receivedData); 
 
 /* Serial.println("\nTesting EEPROM Library\n");
  if (!EEPROM.begin(EEPROM_SIZE)) {
    Serial.println("Failed to initialise EEPROM");
    Serial.println("Restarting...");
    delay(1000);
    ESP.restart();
  }
  delay (4000);
  receivedData = read_String(wifiAddr);
  Serial.print("Read Data:");
  Serial.println(receivedData);
  delay (4000);*/
  
  //reset OLED display via software
  pinMode(OLED_RST, OUTPUT);
  digitalWrite(OLED_RST, LOW);
  delay(20);
  digitalWrite(OLED_RST, HIGH);
  
  //initialize OLED
  Wire.begin(OLED_SDA, OLED_SCL);
  if(!display.begin(SSD1306_SWITCHCAPVCC, 0x3c, false, false)) { // Address 0x3C for 128x32
    Serial.println(F("SSD1306 allocation failed"));
    for(;;); // Don't proceed, loop forever
  }
    
  display.clearDisplay();
  display.setTextColor(WHITE);
  display.setTextSize(1);
  display.setCursor(0,0);
  display.print("LORA duplex 115200bd ");
  display.display();

    Serial.println("LoRa duplex Test");
  
  //SPI LoRa pins
  SPI.begin(SCK, MISO, MOSI, SS);
  //setup LoRa transceiver module
  LoRa.setPins(SS, RST, DIO0);

  if (!LoRa.begin(BAND)) {
    Serial.println("Starting LoRa failed!");
    while (1);
  }
    LoRa.setTxPower(14);//Supported values are 2 to 20 for PA_OUTPUT_PA_BOOST_PIN, and 0 to 14 for PA_OUTPUT_RFO_PIN.  LoRa.setTxPower(txPower, outputPin);
    LoRa.setSpreadingFactor(12);//Supported values are between 6 and 12. If a spreading factor of 6 is set, implicit header mode must be used to transmit and receive packets.
    LoRa.setSignalBandwidth(500E3);//signalBandwidth - signal bandwidth in Hz, defaults to 125E3.
//Supported values are 7.8E3, 10.4E3, 15.6E3, 20.8E3, 31.25E3, 41.7E3, 62.5E3, 125E3, 250E3, and 500E3.
    LoRa.enableCrc();//LoRa.disableCrc();
    //LoRa.setGain(6);//Supported values are between 0 and 6. If gain is 0, AGC will be enabled and LNA gain will not be used. Else if gain is from 1 to 6, AGC will be disabled and LNA gain will be used.
  bleTask();
  
  Serial.println("LoRa Initializing OK!");
  display.setCursor(0,10);
  display.println("LoRa Initializing OK!");
  display.display();
  delay(4000);
  wifiTask();  

   char charBuff3[MQTTserver.length()+1];
    MQTTserver.toCharArray(charBuff3,MQTTserver.length()+1);
  client.setServer(charBuff3, MQTTport.toInt());
  client.setCallback(callback);
  reconnect();
  delay (1000);
  publishSerialData("test");
}

void loop() {

  //try to parse packet
  int packetSize = LoRa.parsePacket();
  if (packetSize) {
    //received a packet
    received();
  }

  while (Serial.available()) // Attendre l'entré de l'utilisateur
  {    
      delay(10);
      LoRaSend = Serial.readString() ;
    transmittion();    
  }

  
  if (scanWifi == 1){
    wifiToBLE(); 
    scanWifi = 0;    
  }

  if (flagBLE == 1){
      LoRaSend = BLEreceiv ;
    transmittion();       
  flagBLE = 0;
  }
      // disconnecting
    if (!deviceConnected && oldDeviceConnected) {
        delay(500); // give the bluetooth stack the chance to get things ready
        pServer->startAdvertising(); // restart advertising
        Serial.println("start advertising");
        oldDeviceConnected = deviceConnected;
    }
    // connecting
    if (deviceConnected && !oldDeviceConnected) {
    // do stuff here on connecting
        oldDeviceConnected = deviceConnected;
    }
   client.loop();
}

void bleTask(){
  // Create the BLE Device
  BLEDevice::init("ESP32 LoRa GW"); // Give it a name

  // Create the BLE Server
  BLEServer *pServer = BLEDevice::createServer();
  pServer->setCallbacks(new MyServerCallbacks());

  // Create the BLE Service
  BLEService *pService = pServer->createService(SERVICE_UUID);

  // Create a BLE Characteristic
  pCharacteristic = pService->createCharacteristic(
                      CHARACTERISTIC_UUID_TX,
                      BLECharacteristic::PROPERTY_NOTIFY
                    );
                      
  pCharacteristic->addDescriptor(new BLE2902());

  BLECharacteristic *pCharacteristic = pService->createCharacteristic(
                                         CHARACTERISTIC_UUID_RX,
                                         BLECharacteristic::PROPERTY_WRITE
                                       );

  pCharacteristic->setCallbacks(new MyCallbacks());

  // Start the service
  pService->start();

  // Start advertising
  pServer->getAdvertising()->start();
  Serial.println("Attente connection client BLE...");
}

/*String read_String(char add)
{
  int i;
  char data[100]; //Max 100 Bytes
  int len=0;
  unsigned char k;
  k=EEPROM.read(add);
  while(k != '\0' && len<500)   //Read until null character
  {    
    k=EEPROM.read(add+len);
    data[len]=k;
    len++;
  }
  data[len]='\0';
  return String(data);
}*/

String getValue(String data, char separator, int index){
  int found = 0;
  int strIndex[] = {0, -1};
  int maxIndex = data.length()-1;

  for(int i=0; i<=maxIndex && found <=index; i++){
    if(data.charAt(i)==separator || i==maxIndex){
      found++;
      strIndex[0] = strIndex[1]+1;
      strIndex[1] = (i==maxIndex) ? i+1 : i;
    }
  }
  return found>index ? data.substring(strIndex[0], strIndex[1]) : "";
}

void wifiTask() {
  //receivedData = read_String(wifiAddr);
  //receivedData = "TP-Link_ELECTROPROD,Batimat2017,193.70.2.114,1883,1,Connected.Domotic.System,SuperCacahouette,";

  if(receivedData.length() > 0){
    String testTrame = getValue(receivedData, ',', 0);
    String wifiName = getValue(receivedData, ',', 1);
    String wifiPassword = getValue(receivedData, ',', 2);
    MQTTserver = getValue(receivedData, ',', 3);
    MQTTport = getValue(receivedData, ',', 4);
    telnetClient = getValue(receivedData, ',', 5);
    MQTT_USER = getValue(receivedData, ',', 6);
    MQTT_PASSWORD = getValue(receivedData, ',', 7);

    if(wifiName.length() > 0 && wifiPassword.length() > 0){
      Serial.print("WifiName : ");
      Serial.println(wifiName);

      Serial.print("wifiPassword : ");
      Serial.println(wifiPassword);

      Serial.print("MQTTserver : ");
      Serial.println(MQTTserver);

      Serial.print("MQTTport : ");
      Serial.println(MQTTport);

      Serial.print("telnetClient : ");
      Serial.println(telnetClient);

      Serial.print("MQTT_USER : ");
      Serial.println(MQTT_USER);

      Serial.print("MQTT_PASSWORD : ");
      Serial.println(MQTT_PASSWORD);

      WiFi.begin(wifiName.c_str(), wifiPassword.c_str());
      Serial.print("Connecting to Wifi");
      while(WiFi.status() != WL_CONNECTED){
        Serial.print(".");
        delay(1000);
      }
      Serial.println();
      Serial.print("Connected with IP: ");
      Serial.println(WiFi.localIP());
      

      Serial.print("Ping Host: ");
      Serial.println(MQTTserver);
      //Serial.println(remote_host);
      MQTTserver.toCharArray(charBuf, MQTTserver.length()+1);
      if(Ping.ping(charBuf)){
        Serial.println("Success!!");
      }else{
        Serial.println("ERROR!!");
      }
      
    }
  } 
}

void transmittion(){
      Serial.println(LoRaSend);
      LoRa.beginPacket();
      LoRa.print(LoRaSend);
      LoRa.endPacket();
   display.clearDisplay();
   display.setCursor(0,0);
   display.print("LORA DUPLEX");
   display.setCursor(0,10);
     display.print("Transmit packet:");
     display.setCursor(0,20);
     display.print(LoRaSend);
     display.display();   
  
}

void received(){
  Serial.print("Received packet ");

    //read packet
    while (LoRa.available()) {
      LoRaData = LoRa.readString();
      Serial.print(LoRaData);
    }

    //print RSSI of packet
    int rssi = LoRa.packetRssi();
    Serial.print(" with RSSI ");    
    Serial.println(rssi);

   // Dsiplay information
   display.clearDisplay();
   display.setCursor(0,0);
   display.print("LORA DUPLEX");
   display.setCursor(0,10);
   display.print("Receiv packet:");
   display.setCursor(87,10);
   display.print(rssi);
   display.print("dB");
   display.setCursor(0,20);
   display.print(LoRaData);
   display.display(); 
   
    char charBuf[LoRaData.length()+1];
      LoRaData.toCharArray(charBuf, LoRaData.length()+1);
    publishSerialData(charBuf);  
    
    if (deviceConnected) {      
            pCharacteristic->setValue(charBuf);
            pCharacteristic->notify();
    }
}

void callback(char* topic, byte *payload, unsigned int length) {
    Serial.println("-------new message from broker-----");
    Serial.print("channel:");
    Serial.println(topic);
    //Serial.println("");
    Serial.print("data:");  
    //Serial.write(payload, length);
    LoRaSend = "";
    for (int i = 0; i < length; i++) {
      LoRaSend += ((char)payload[i]);
    }
    
    transmittion();

 /*       char temp[2];
        char c;
        int index;
        int e;
        uint8_t tx_buffer[128];
        uint8_t len_buffer=0;
      
        for (e = 0; e < length; e += 2) {
          temp[0] = payload[e];
          temp[1] = payload[e + 1];
          tx_buffer[len_buffer] = strtol(temp,NULL,16);
                  if (tx_buffer[len_buffer] <= 0x0F){
                    tft.print("0");
                  }
            tft.print(strtol(temp,NULL,16),HEX);
          len_buffer++;}

          //Serial2.println(len_buffer);

          for (e=0; e<len_buffer; e++){
            Serial2.write(tx_buffer[e]);
            //Serial.print(" ");
        
          }
    //Serial2.write(payload, length);
            tft.println("                                                                                                                                                                                                                                      ");
          //delay(1);*/
}

void publishSerialData(char *serialData){
  if (!client.connected()) {
    reconnect();
  }
  String stringOne = WiFi.macAddress();
    stringOne += "/gateway/tx";
    char charBuf[stringOne.length()+1];
    stringOne.toCharArray(charBuf, stringOne.length()+1);
  client.publish(charBuf, serialData);
}

Les crédential wifi et mqtt se règle par le ble via votre smartphone
j’utilise

et on envoie
55,ssid,passWifi,servermqtt,portmqtt,logmqtt,passmqtt
car avec les nouveau smartphone règler un esp via wifimanager par exemple devient compliqué car le smartphone détecte l’absence d’internet et donc se déconnect du réseau
On a pas ce problème avec le bluetooth

bon belle avancée déjà on va avoir le serveur et passerelle en 868MHz
Un bon début?

donc jusque là tout va bien la passerelle écrira dans le topic macDuESP/gateway/tx
et on envoie les info sur le réseau LoRa avec macDuESP/gateway/rx
exemple avec mqtt explorer


s’il vous plait respecter le rangement par adresse mac pour éviter le bordel de s’écrire les uns sur les autres
jusqu’ici le passerelle est transparente on peut faire ce que l’on veut comme envoyer les codes mysensor ou autre
c’est à partir de là que l’on va établir notre protocole

chez jlc on trouve encore des puces LoRa chouette

1 « J'aime »

JE SUIS VERT, j’aurai attendu 24h


PU*****

1 « J'aime »

pour le serveur c’est en cours
par contre je suis en train de dessinner des circuit
mais pour le lora
quel chipset doit-on prendre
en 868 bien sur
sx1276
ou rfm69???
help
je vous laisse voter

1 « J'aime »