Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Adding LoRa WAN support #124

Open
stich86 opened this issue Mar 20, 2019 · 85 comments
Open

Adding LoRa WAN support #124

stich86 opened this issue Mar 20, 2019 · 85 comments

Comments

@stich86
Copy link

stich86 commented Mar 20, 2019

Describe the problem you have/What new integration you would like
Add support for LoRa WAN protocol like RFM95

Please describe your use case for this integration and alternatives you've tried:

it would be nice to integrate ESP between their self for various automation (like a far remote sensor)

Additional context

this is one of the primary library used on Arduino
https://github.com/sandeepmistry/arduino-LoRa

@mseefeldt
Copy link

mseefeldt commented May 23, 2019

In the german computer magazine c't was a project that contains an ATtiny and LoRaWan.

Maybe this can be used as an starting point?!
Here is the link to the source code:
c't Briefkastensensor

There is even a schematic to attach the LoRaWan module to the ATtiny which can maybe reused for the ESP32.

My use case:
I have a remote network to supervise (in a basement) where there is no cellular or wifi
network available (massive construction, tons of steel in the walls). I need to monitor the
hosts in the network and report the data regularly. Power consumption is an issue here since
the monitoring needs to be battery powered to work as well during a power outage. So any ESP is a must, i can't use a raspberry pi with HomeAssistant.
LoRaWan does work here, so the transfer of sensor data via LoRa would work, when ESPHome can
talk to the LoRa-Modem and transfer some payload regularly.

@Lefuneste83
Copy link

Lefuneste83 commented May 28, 2019

Hi there.

I have been trying to integrate Lora functionalities to Esphome on ESP32 TTGO OLED V1 boards.

I have had some success in sending messages. I am stuck on the receiver part.

Please find bellow my code. Please excuse the limitation of my skills in coding, I am no expert at all in this field.

Sender Side :

lora_sender.yaml file :

esphome:
  name: lora_sender
  platform: ESP32
  board: ttgo-lora32-v1
  includes:
    - lora_sender.h
  libraries:
    - "LoRa"
    - "SPI"

wifi:
  ssid: "myssid"
  password: "mypwd"
  fast_connect: on
  
  manual_ip:
    static_ip: 192.168.0.XX
    gateway: 192.168.0.XX
    subnet: 255.255.255.0

# Enable logging
logger:

# Enable Home Assistant API
api:
  password: 'mypwd'

ota:
  password: 'mypwd'

spi:
  clk_pin: GPIO5
  mosi_pin: GPIO27
  miso_pin: GPIO19

text_sensor:
- platform: custom
  lambda: |-
    auto lora_text_sensor = new lora_sender();
    App.register_component(lora_text_sensor);
    return {lora_text_sensor};

  text_sensors:
    name: "Lora Text Sensor"

The custom sensor code is lora_sender.h

#include "esphome.h"
#include "LoRa.h"
#include "SPI.h"

using namespace esphome;

class lora_sender : public PollingComponent, public text_sensor::TextSensor {
 public:
  // constructor
  lora_sender() : PollingComponent(15000) {}
  
  void setup() override {
      Serial.begin(115200);
      Serial.println("LoRa Sender");
      LoRa.setPins(18, 14, 26);
      if (!LoRa.begin(868E6)) {
        Serial.println("Starting LoRa failed!");
        while (1);
        delay(1000);
      }
Serial.println("Sending data packet...");
  }

  void update() override {
    // This will be called every "update_interval" milliseconds.
    // Publish state
    publish_state("Hello World");
    LoRa.beginPacket();
    LoRa.print("Hello World");
    LoRa.endPacket(); 
  }
};

This is obviously a very simple test case, as it pushes a simple string out. But I believe it is simple enough to adapt it to other cases.

I have validated that the messages gets properly sent by scanning RF with SDR.

Now for the receiving part, I am stuck on the custom text sensor definition. I don't know how to create a sensor that listen continuously (with continuous polling).

Any help would be appreciated.

@OttoWinter
Copy link
Member

Now for the receiving part, I am stuck on the custom text sensor definition. I don't know how to create a sensor that listen continuously (with continuous polling).

For that you can override the loop() method.

@Lefuneste83
Copy link

Thank you Otto. Sorry for asking but can you point me to some example code ? As I said I am really coming back to coding, as I find your project worth spending some time upon... But I am absolutely a newbie in this field.

@OttoWinter
Copy link
Member

For example components/gps/gps.h - It's basically the same thing as here just that the loop function is now part of the component.

@Lefuneste83
Copy link

Thank you Otto I will have a look at this and let you know.

@minsuke
Copy link

minsuke commented Dec 13, 2019

Thank you Otto I will have a look at this and let you know.

thank you for your codes, lefuneste82 and Otto winter's guide.

Can you share custom codes for the lora_receive.h

If Lora supports in ESPHOME , It will be more useful platform for the IOT things.

I wish I can integrate with Lora.

thank you for your trial Lefuneste83. : )

@rradar
Copy link

rradar commented Dec 25, 2019

I'm also looking forward to get lora supported in esphome. I ordered some SX1278 modules (Ra-02 Ai-Thinker with 433mhz) to make some tests.

My goal is to connect two different home assistant setup's/networks which are some kilometers apart. Idea is to have a esphome node on each side (in their own network/own home assistant instance) which are listening to some home assistant (binary)sensors and pushing a message via lora to the other esphome node when a (binary)sensor changes. So it should be possible to mirror states from one home assistant instance/network to another. Great! Isn't it? So much the theory...

@rradar
Copy link

rradar commented Dec 29, 2019

I think I found two very interesting libraries which could be useful for this:

https://github.com/sandeepmistry/arduino-LoRa

  • Support for LoRa Semtech SX1276/77/78/79

https://github.com/jgromes/RadioLib

Supported modules:

  • CC1101 FSK radio module
  • ESP8266 WiFi module
  • HC05 Bluetooth module
  • JDY08 BLE module
  • nRF24L01 2.4 GHz module
  • RF69 FSK/OOK radio module
  • RFM9x series LoRa modules (RFM95, RM96, RFM97, RFM98)
  • SX127x series LoRa modules (SX1272, SX1273, SX1276, SX1277, SX1278, SX1279)
  • SX126x series LoRa modules (SX1261, SX1262, SX1268)
  • SX1231 FSK/OOK radio module
  • XBee modules (S2B)

The second one is a bigger (not limited to lora) but very active project

@beikeland
Copy link

My goal is to connect two different home assistant setup's/networks which are some kilometers apart.

Have you looked at the duty cycle limits for the 433mhz band? You might come close to exceeding that with a somewhat smart smart house.

@Johni81
Copy link

Johni81 commented Jan 10, 2020

Hey All,
I wanted to share with you my custom code for a lora reciever. I'm using it at the moment as a gateway for two lora nodes, one for my power-meter in the basement, that is based on an arduino pro mini, and the second one as a mailbox sensor, that is based on an attiny84, similar to the one mentioned earlier from c't. I'm using the LoRa library for my RFM95 Lora modules and I included also some AES128 encryption with Crypto/CryptoLW library, the attiny84 limited the encryption to only AES128 due to RAM limits.

lora_gateway.yaml file:


esphome:
  name: lora_gateway
  platform: ESP32
  board: esp32dev
  includes:
    - lora_gateway.h
  libraries:
    - "LoRa"
    - "SPI"
    - "CryptoLW"
    - "Crypto"
    - "ArduinoJson-esphomelib"

wifi:
  ssid: "myssid"
  password: "mywlanpswd"
  fast_connect: on
  
  manual_ip:
    static_ip: 192.168.178.XXX
    gateway: 192.168.178.1
    subnet: 255.255.255.0

  # Enable fallback hotspot (captive portal) in case wifi connection fails
  ap:
    ssid: "Fallback Hotspot"
    password: "pswd"

captive_portal:

# Enable logging
logger:
  level: DEBUG

# Enable Home Assistant API
api:
  password: "apipswd"

ota:
  password: "otapswd"
  
# Enable SPI for LoRa
spi:
  clk_pin: GPIO18
  mosi_pin: GPIO23
  miso_pin: GPIO19
  

sensor:
  - platform: custom
    lambda: |-
      auto lora_sensor = new MyLoRaSensors();
      App.register_component(lora_sensor);
      return {lora_sensor->zaehler_sensor_id, 
              lora_sensor->zaehler_sensor_stand,
              lora_sensor->zaehler_sensor_power,
              lora_sensor->zaehler_sensor_elaps,
              lora_sensor->zaehler_sensor_msg,
              lora_sensor->zaehler_sensor_rssi,
              lora_sensor->zaehler_sensor_vbat,
              lora_sensor->mbox_sensor_post,
              lora_sensor->mbox_sensor_msg,
              lora_sensor->mbox_sensor_rssi,
              lora_sensor->mbox_sensor_vbat};
    sensors:
    - name: "Zählernummer"
      accuracy_decimals: 0
      icon: mdi:counter
    - name: "Zählerstand"
      unit_of_measurement: kWh
      accuracy_decimals: 4
      icon: mdi:counter
    - name: "Wirkleistung"
      unit_of_measurement: W
      accuracy_decimals: 0
      icon: mdi:gauge
    - name: "Zählersender: letzte Nachricht vor"
      unit_of_measurement: s
      accuracy_decimals: 0
      icon: mdi:timelapse
    - name: "Zählersender: Nachricht #"
      accuracy_decimals: 0
      icon: mdi:message-processing-outline
    - name: "Zählersender: Signalstärke"
      unit_of_measurement: dBm
      accuracy_decimals: 0
      icon: mdi:signal
    - name: "Zählersender: Batteriespannung"
      unit_of_measurement: V
      accuracy_decimals: 3
      icon: mdi:battery
    - name: "Briefkasten"
      accuracy_decimals: 0
      icon: mdi:email-box
    - name: "Briefkastensender: Nachricht #"
      accuracy_decimals: 0
      icon: mdi:message-processing-outline
    - name: "Briefkastensender: Signalstärke"
      unit_of_measurement: dBm
      accuracy_decimals: 0
      icon: mdi:signal
    - name: "Briefkastensender: Batteriespannung"
      unit_of_measurement: V
      accuracy_decimals: 3
      icon: mdi:battery

The custom reciever code lora_gateway.h:


#include "esphome.h"
#include "SPI.h"
#include "LoRa.h"
#include "Crypto.h"
#include "AES.h"
#include "CTR.h"
#include "string.h"
#include "ArduinoJson.h"

using namespace esphome;

#define csPin 5        // LoRa radio chip select
#define resetPin 21    // LoRa radio reset // -1 for not in use
#define dio0Pin 2      // change for your board; must be a hardware interrupt pin
#define freq 868700000 // LoRa used frequency 868 MHz
#define SF 7           // LoRa used spreadingFactor // ranges from 6-12,default 7 see API docs
#define bw 125E3       // LoRa signal bandwidth in Hz, defaults to 125E3
#define sw 0x12        // LoRa SyncWord ranges from 0-0xFF, default 0x12, see LoRa API docs		!!! MUST be equal on Lora sensor nodes and gateway

#define MAX_PLAINTEXT_SIZE 134
#define MAX_CIPHERTEXT_SIZE 134

byte key[16] = {0x01, 0x02, 0x0b, 0x5b, 0xc6, 0x6e, 0xa5, 0xa3, 0xfa, 0x1a, 0xf7, 0xf3, 0x8d, 0xc3, 0x7a, 0xbc}; // The very secret key !!! MUST be equal on Lora sensor nodes and gateway
byte iv[16] = {0xa7, 0x8a, 0x23, 0x2d, 0xed, 0x1c, 0x77, 0xd8, 0xfd, 0xab, 0x8b, 0x13, 0xc4, 0x8d, 0xb1, 0xf3};	//!!! MUST be equal on Lora sensor nodes and gateway
byte ciphertext[MAX_PLAINTEXT_SIZE] = {0};
byte plaintext[MAX_CIPHERTEXT_SIZE] = {0};
byte old_ciphertext[MAX_PLAINTEXT_SIZE] = {0};
String receive_buf = "";
String rssi = "";
String msg_Zaehler = "";
String msg_Briefkasten = "";
long Z_VBat = 0;   // 4066345
long Z_ID = 0;       // 12345678
long Z_Stand = 0; // 1130810033
int Z_Pow = 0;      // 1350
int Z_Elaps = 0;  // 32
long Z_msg = 0;     // 32452
int Z_RSSI = 0;    // -123
long B_VBat = 0; // 4066345
bool B_Post = 0; // 1
long B_msg = 0;   // 32452
int B_RSSI = 0;  // -123

CTR<AES128> ctr;

/*--------------------------------------------------------------------------------
                            LoRa Data Recieved
--------------------------------------------------------------------------------*/
void onReceive(int packetSize)
{
  // received a packet
  //ESP_LOGD("custom", "Received packet '");

  // read packet
  LoRa.readBytes(ciphertext, MAX_CIPHERTEXT_SIZE);
  //ESP_LOGD("custom", "%s", ciphertext);

  // print RSSI of packet
  rssi = "";
  rssi = String(LoRa.packetRssi());
  //ESP_LOGD("custom", "' with RSSI %s", rssi);
}

/*--------------------------------------------------------------------------------
                                  Decode Massage
--------------------------------------------------------------------------------*/
void decode_msg()
{
  ctr.clear();
  ctr.setKey(key, ctr.keySize());
  ctr.setIV(iv, ctr.ivSize());

  memset(plaintext, 0xBA, sizeof(plaintext));	// reset plaintext variable before next decryption

  ctr.decrypt(plaintext, ciphertext, sizeof(ciphertext));	// decrypt new massage

  receive_buf = (char*)plaintext;
  
  //ESP_LOGD("custom", (char*)ciphertext);
  //ESP_LOGD("custom", (char*)plaintext);
  //ESP_LOGD("custom", receive_buf.c_str());
}

/*--------------------------------------------------------------------------------
                           Json String parsing
--------------------------------------------------------------------------------*/
// {"Sensor":"Zaehler","VBat":4066345,"ID":12345678,"Stand":1130810033,"Pow":1350,"Elaps":32,"msg":32452,"RSSI":-123}
// {\"Sensor\":\"Zaehler\",\"VBat\":4066345,\"ID\":12345678,\"Stand\":1130810033,\"Pow\":1350,\"Elaps\":32,\"msg\":32452,\"RSSI\":-123}
void json_data_pars(String json)
{
  const size_t capacity = JSON_OBJECT_SIZE(8) + 60;
  DynamicJsonBuffer  jsonBuffer(capacity);

  JsonObject& doc = jsonBuffer.parseObject(json);

  String Sens = doc["Sensor"]; // "Zaehler"
  
  if (Sens == "Zaehler")
  {
    //msg_Zaehler = json;
	//ESP_LOGD("custom", "%s", msg_Zaehler);
    
    Z_VBat = doc["VBat"];   // 4066345
    Z_ID = doc["ID"];       // 12345678
    Z_Stand = doc["Stand"]; // 1130810033
    Z_Pow = doc["Pow"];      // 1350
    Z_Elaps = doc["Elaps"];  // 32
    Z_msg = doc["msg"];     // 32452
    Z_RSSI = doc["RSSI"];    // -123
	
    /*ESP_LOGD("custom", "%s", Sens.c_str());
    ESP_LOGD("custom", "%li", Z_VBat);
    ESP_LOGD("custom", "%li", Z_ID);
    ESP_LOGD("custom", "%li", Z_Stand);
    ESP_LOGD("custom", "%i", Z_Pow);
    ESP_LOGD("custom", "%i", Z_Elaps);
    ESP_LOGD("custom", "%li", Z_msg);
    ESP_LOGD("custom", "%i", Z_RSSI);*/
  }
  else if (Sens == "MBox")
  {
    //msg_Briefkasten = json;
	//ESP_LOGD("custom", "%s", msg_Briefkasten);
    
    B_VBat = doc["VBat"]; // 4066345
    B_Post = doc["Post"]; // 1
    B_msg = doc["msg"];   // 32452
    B_RSSI = doc["RSSI"];  // -123
	
	/*ESP_LOGD("custom", "%s", Sens.c_str());
    ESP_LOGD("custom", "%li", B_VBat);
    ESP_LOGD("custom", "%i", B_Post);
    ESP_LOGD("custom", "%li", B_msg);
    ESP_LOGD("custom", "%i", B_RSSI);*/
  }
}


class MyLoRaSensors : public PollingComponent {
 public:
  Sensor *zaehler_sensor_id = new Sensor();
  Sensor *zaehler_sensor_stand = new Sensor();
  Sensor *zaehler_sensor_power = new Sensor();
  Sensor *zaehler_sensor_elaps = new Sensor();
  Sensor *zaehler_sensor_msg = new Sensor();
  Sensor *zaehler_sensor_rssi = new Sensor();
  Sensor *zaehler_sensor_vbat = new Sensor();
  Sensor *mbox_sensor_post = new Sensor();
  Sensor *mbox_sensor_msg = new Sensor();
  Sensor *mbox_sensor_rssi = new Sensor();
  Sensor *mbox_sensor_vbat = new Sensor();
  
  MyLoRaSensors() : PollingComponent(4000) { }
  
  void setup() override {
    // This will be called by App.setup()
	
	LoRa.setPins(csPin, resetPin, dio0Pin); // set CS, reset, IRQ pin

	if (!LoRa.begin(freq)) // initialize radio at "freq" MHz
	{
		ESP_LOGD("custom", "LoRa init failed. Check your connections.");
		while (true); // if failed, do nothing
		//delay(1000);
	}
	//LoRa.setSpreadingFactor(SF);          // set spreadingFactor
	//LoRa.setSignalBandwidth(bw);          // set signal bandwidth
	LoRa.setSyncWord(sw);					// set SyncWord
	ESP_LOGD("custom", "LoRa init succeeded.");
	ESP_LOGD("custom", "Frequency %d Bandwidth %E SF %i SyncWord %x", freq, bw, SF, sw);
	ESP_LOGD("custom", "LoRa Connection ready...");

	// register the receive callback and put the radio into receive mode
	LoRa.onReceive(onReceive);
	LoRa.receive();
  }
  
  void update() override {
    // This will be called by App.loop()
	if (memcmp(old_ciphertext, ciphertext, MAX_CIPHERTEXT_SIZE) != 0)	// check if radio recieved new massage
	{
		decode_msg();
		receive_buf.replace("\"xxx\"", rssi);
		json_data_pars(receive_buf);
		
		zaehler_sensor_id->publish_state(Z_ID);
		zaehler_sensor_stand->publish_state(Z_Stand*0.0001);
		zaehler_sensor_power->publish_state(Z_Pow);
		zaehler_sensor_elaps->publish_state(Z_Elaps);
		zaehler_sensor_msg->publish_state(Z_msg);
		zaehler_sensor_rssi->publish_state(Z_RSSI);
		zaehler_sensor_vbat->publish_state(Z_VBat*0.000001);
		mbox_sensor_post->publish_state(B_Post);
		mbox_sensor_msg->publish_state(B_msg);
		mbox_sensor_rssi->publish_state(B_RSSI);
		mbox_sensor_vbat->publish_state(B_VBat*0.000001);
		
		for (uint8_t i = 0; i <= MAX_CIPHERTEXT_SIZE; i++)
		{
			old_ciphertext[i] = ciphertext[i];
		}
	}
  }
};

With this code I'm getting all the sensors publishing the values into HA.

@BrewNinja
Copy link

BrewNinja commented Jan 15, 2020

@Johni81 do you mind sharing your code for the one of the senders? Im looking to do a mailbox sender with lora, and might take a whack at it with your code. Thanks!

@Johni81
Copy link

Johni81 commented Jan 15, 2020

@BrewNinja here is my code for the mailbox sender.


#include <Arduino.h>
#include <ATTinyCore.h>
#include <SPI.h>
#include <LoRa.h>
#include <Crypto.h>
#include <AES.h>
#include <CTR.h>
#include <string.h>
#include <avr/sleep.h>
#include <avr/wdt.h>

// ATMEL ATTINY84 / ARDUINO
//
//                           +-\/-+
//                     VCC  1|    |14  GND
//             (D  0)  PB0  2|    |13  PA0  (D 10)        AREF
//             (D  1)  PB1  3|    |12  PA1  (D  9)
//             (D 11)  PB3  4|    |11  PA2  (D  8)
//  PWM  INT0  (D  2)  PB2  5|    |10  PA3  (D  7)
//  PWM        (D  3)  PA7  6|    |9   PA4  (D  6)
//  PWM        (D  4)  PA6  7|    |8   PA5  (D  5)        PWM
//                           +----+

// these arrays map port names (e.g. port B) to the
// appropriate addresses for various functions (e.g. reading
// and writing)
#define statusled 2    // LED for control
#define irled 1        // power for ir-led of proximity sensor (invisible)
#define irdiode 0      // power in for diode in proximity sensor
#define irsens PA0     //adc pin (connect to output of sensor)
#define csPin 7        // LoRa radio chip select
#define resetPin -1    // LoRa radio reset // -1 for not in use
#define dio0Pin 3      // change for your board; must be a hardware interrupt pin
#define freq 868700000 // LoRa used frequency 868 MHz
#define SF 7           // LoRa used spreadingFactor // ranges from 6-12,default 7 see API docs
#define bw 125E3       // LoRa signal bandwidth in Hz, defaults to 125E3
#define sw 0x12        // LoRa SyncWord ranges from 0-0xFF, default 0x12, see LoRa API docs

// define a threshold for your mailbox.
#define THRESHOLD 15

#define MAX_PLAINTEXT_SIZE 82
#define MAX_CIPHERTEXT_SIZE 82

byte key[16] = {0x01, 0x02, 0x0b, 0x5b, 0xc6, 0x6e, 0xa5, 0xa3, 0xfa, 0x1a, 0xf7, 0xf3, 0x8d, 0xc3, 0x7a, 0xbc}; // The very secret key
byte iv[16] = {0xa7, 0x8a, 0x23, 0x2d, 0xed, 0x1c, 0x77, 0xd8, 0xfd, 0xab, 0x8b, 0x13, 0xc4, 0x8d, 0xb1, 0xf3};
byte ciphertext[MAX_CIPHERTEXT_SIZE] = {0};
uint16_t msgCount = 0; // count of outgoing messages
long vbat = 0;
bool post = 0;
bool post_old = 0;
int sleepCycles = 1;

CTR<AESTiny128> ctr;

/*--------------------------------------------------------------------------------
                                    Setup
--------------------------------------------------------------------------------*/
void setup()
{
  Serial.begin(9600); // TX is AIN0, RX is AIN1
  pinMode(irled, OUTPUT);
  pinMode(irdiode, OUTPUT);
  pinMode(statusled, OUTPUT);

  LoRa.setPins(csPin, resetPin, dio0Pin); // set CS, reset, IRQ pin

  if (!LoRa.begin(freq))
  { // initialize radio at "freq" MHz
    //Serial.println("LoRa init fail");
    while (true)
      ; // if failed, do nothing
  }
  //LoRa.setSpreadingFactor(SF);          // set spreadingFactor
  //LoRa.setSignalBandwidth(bw);          // set signal bandwidth
  LoRa.setSyncWord(sw); // set SyncWord
  //Serial.println("LoRa init");

  //Serial.println("Connected");
}

/*--------------------------------------------------------------------------------
                          Überprüfung auf Briefkasteninhalt
--------------------------------------------------------------------------------*/
void checkLetter()
{
  digitalWrite(irled, HIGH);
  digitalWrite(irdiode, HIGH);
  unsigned int measure;
  for (int i = 0; i < 3; i++)
  {
    delay(5);
    measure += analogRead(irsens);
  }
  measure = measure / 3;
  digitalWrite(irled, LOW);
  digitalWrite(irdiode, LOW);

  if (measure > THRESHOLD)
  {
    post = 1;
  }
  else
  {
    post = 0;
  }
}

/*--------------------------------------------------------------------------------
                          Batteriespannung ermitteln
--------------------------------------------------------------------------------*/
void getVbat()
{
  // Select ADC inputs
  // bit    76543210
  // REFS = 00       = Vcc used as Vref
  // MUX  =   100001 = Single ended, 1.1V (Internal Ref) as Vin
  ADMUX = _BV(MUX5) | _BV(MUX0); // oder	ADMUX = 0b00100001;
  /*
		After switching to internal voltage reference the ADC requires a settling time of 1ms before
		measurements are stable. Conversions starting before this may not be reliable. The ADC must
		be enabled during the settling time.
	*/
  delay(2);
  /*
		The first conversion after switching voltage source may be inaccurate, and the user is advised to discard this result.
	*/
  ADCSRA |= _BV(ADSC); // Start a conversion
  while (bit_is_set(ADCSRA, ADSC))
    ;   // Wait for 1st conversion to be ready...
        //..and ignore the result
  uint8_t low = ADCL;
  uint8_t high = ADCH;
  uint16_t vbat = (high << 8) | low; // 0<= result <=1023
  vbat = (1125300L / vbat);          // 1125300 = 1.1 x 1023 x 1000
}

/*--------------------------------------------------------------------------------
                           Json String generierung
--------------------------------------------------------------------------------*/
// {"Sensor":"MBox","VBat":4066345,"Post":1,"msg":32452,"RSSI":"xxx"}
// "{\"Sensor\":\"MBox\",\"VBat\":4066345,\"Post\":1,\"msg\":32452,\"RSSI\":\"xxx\"}"
String json_data_prep()
{
  String json = "{\"Sensor\":\"MBox\",\"VBat\":";
  json += (long)vbat;
  json += ",\"Post\":";
  json += (bool)post;
  json += ",\"msg\":";
  json += (unsigned int)msgCount;
  json += ",\"RSSI\":\"xxx\"}";

  return json;
}

/*--------------------------------------------------------------------------------
                                  Encode Massage
--------------------------------------------------------------------------------*/
void encode_msg(String json)
{
  byte plaintext[MAX_PLAINTEXT_SIZE] = {0};

  for (uint8_t i = 0; i <= json.length(); i++)
  {
    plaintext[i] = (byte)json[i];
  }

  ctr.clear();
  ctr.setKey(key, ctr.keySize());
  ctr.setIV(iv, ctr.ivSize());

  memset(ciphertext, 0xBA, sizeof(ciphertext));

  ctr.encrypt(ciphertext, plaintext, sizeof(plaintext));
}

/*--------------------------------------------------------------------------------
                                LoRa Massage senden
--------------------------------------------------------------------------------*/
void sendMessage(byte *outgoing)
{
  // send packet
  LoRa.beginPacket(); // start packet
  //LoRa.print(outgoing); // add payload
  LoRa.write(outgoing, sizeof(ciphertext));
  LoRa.endPacket(); // finish packet and send it
  msgCount++;       // increment message ID
  LoRa.sleep();
}

/*--------------------------------------------------------------------------------
                                      Sleep
--------------------------------------------------------------------------------*/
void setSleeptime(int time)
{
  sleepCycles = time / 8;
}

void gotoSleep()
{
  //disable ADC
  ADCSRA &= ~(1 << ADEN);
  // WD Reset Flag to 0 (p. 45)
  bitClear(MCUSR, WDRF);
  // WD Change Enable (p. 46)
  bitSet(WDTCSR, WDCE);
  // WD Enable (p. 46)
  bitSet(WDTCSR, WDE);
  // create 8 second WD Timer Prescaler
  // 1 0 0 1 means "8 seconds" (p. 47)
  bitSet(WDTCSR, WDP3);
  bitClear(WDTCSR, WDP2);
  bitClear(WDTCSR, WDP1);
  bitSet(WDTCSR, WDP0);
  // WD Interrupt Enable (p. 45)
  bitSet(WDTCSR, WDIE);

  for (int i = 0; i < sleepCycles; i++)
  {
    set_sleep_mode(SLEEP_MODE_PWR_DOWN);
    sleep_mode(); // Start sleeping
  }

  wdt_disable();
  // enable ADC again
  ADCSRA |= (1 << ADEN);
}

/*--------------------------------------------------------------------------------
                                    Main Loop
--------------------------------------------------------------------------------*/
void loop()
{
  checkLetter();

  if (post_old != post) // Wenn Wert geändert, dann senden
  {
    getVbat();
    encode_msg(json_data_prep());
    sendMessage(ciphertext);
    post_old = post;
  }

  if (post == true)
  {
    digitalWrite(statusled, HIGH);
    Serial.println("1");
  }
  else
  {
    digitalWrite(statusled, LOW);
    Serial.println("0");
  }

  setSleeptime(900); // Sleeptime in seconds; teilbar durch 8 seconds
  gotoSleep();      // Sleep for x sleepCycles; 1 sleepCycles = 8 seconds
}

@BrewNinja
Copy link

Appreciate it! Thank you!

@rradar
Copy link

rradar commented Jan 19, 2020

I wonder if the title should be changed to "Add LoRa support". Because as far as I understand is it all about LoRa here and not about LoRa WAN (yet).

Maybe the LoRa support could be added to the already existing remote_receiver and remote_transmitter components of esphome?

@rradar
Copy link

rradar commented Jan 31, 2020

@Johni81 thank you very much for your sketch.

I was able to get a wemos d1 mini with a Ai-Thinker RA-02 433 Lora Module with SX1278 up and running as a receiver with your code. Little modifications for my 433Mhz module in lora_gateway.h are:

#define csPin 15       // LoRa radio chip select
#define resetPin 16    // LoRa radio reset // -1 for not in use
#define dio0Pin 5      // change for your board; must be a hardware interrupt pin
#define freq 433000000 // LoRa used frequency 433 MHz
#define SF 7           // LoRa used spreadingFactor // ranges from 6-12,default 7 see API docs
#define bw 125E3       // LoRa signal bandwidth in Hz, defaults to 125E3
#define sw 0x12        // LoRa SyncWord ranges from 0-0xFF, default 0x12, see LoRa API docs		!!! MUST be equal on Lora sensor nodes and gateway

and my spi pins on the wemos d1 mini are:

spi:
  clk_pin: D5
  mosi_pin: D7
  miso_pin: D6

My wiring:

   ESP8266      -  RA-02
	Gpio15/D8   - NSS
	Gpio13/D7   - MOSI
	Gpio12/D6   - MISO
	Gpio14/D5   - SCK
	Gpio05/D1   - DIO0
	Gpio16/D0   - RST
	VCC         - 3.3V
	GND         - GND

Now I wonder what's needed to get another pair of this (esp&ra-02) acting as a sender. My idea is to forward (binary)sensor data the esphome node is knowing (from local or home assistant) anyways.

Could this be possible? 🤔

@rradar
Copy link

rradar commented Apr 5, 2020

unstale this bot 😈

@JonathanTreffler
Copy link

Any Chance this will get properly implemented in Esphome ?

@rradar
Copy link

rradar commented Jun 29, 2020

Any Chance this will get properly implemented in Esphome ?

@TessyPowder I guess the best would to support RadioLib but I could imaging that it is a bunch of work to integrate into esphome

@philletourneau
Copy link

+1 desire for an official LORA integration with ESPHOME!

@rradar rradar added the good first issue Good for newcomers label Jul 11, 2020
@rradar rradar added this to the Top Requested milestone Jul 11, 2020
@reaction reaction bot deleted a comment from martin3000 Jul 30, 2020
@acelauwc
Copy link

acelauwc commented Sep 5, 2020

+1 desire for an official LORA integration with ESPHOME!

2 similar comments
@maxparrela
Copy link

+1 desire for an official LORA integration with ESPHOME!

@cristianm
Copy link

+1 desire for an official LORA integration with ESPHOME!

@pauldogg
Copy link

pauldogg commented Nov 2, 2020

+1 :-)

@AquaMCU
Copy link

AquaMCU commented Oct 20, 2022

Hello y'all.

There was a very promising commit here:

esphome/esphome#1609 (comment)

But the author ran out of time. what a shame. Can we not pick up, where he left of and finalize this? Looks quite nice.

Since I am not a c++ guy, I can help with testing. I have two of the boards here and I have home assistant up and running.

Who can review this and comment, what is missing for integration into esphome.

Oliver

@alf-scotland
Copy link

@AquaMCU I just created a new draft PR based on the original one from SenexCrenshaw. I am planning to put some work into it in the coming days as I am dependent on getting LoRa to work for a project of mine. Maybe the seasoned ESPHome experts here can help provide conceptual input.

I had previously worked on my end with a custom PollingComponent and the LoRa package (sandeepmistry/LoRa) to implement LoRa communication between two TTGO LORAv2 ESP32s. This was very "hand-woven" and felt like bending ESPHome into something that it could do better.

I read some comments above about LoRa vs LoRa WAN - and I think the latter is definitively desirable for the community but also a stretch for a single contributor (https://lora-alliance.org/resource_hub/lorawan-104-specification-package/).

So a shout out here I am super appreciative for any design/code input on the just opened draft PR esphome/esphome#3970 🙏

@matthew73210
Copy link

@AquaMCU I just created a new draft PR based on the original one from SenexCrenshaw. I am planning to put some work into it in the coming days as I am dependent on getting LoRa to work for a project of mine. Maybe the seasoned ESPHome experts here can help provide conceptual input.

I had previously worked on my end with a custom PollingComponent and the LoRa package (sandeepmistry/LoRa) to implement LoRa communication between two TTGO LORAv2 ESP32s. This was very "hand-woven" and felt like bending ESPHome into something that it could do better.

I read some comments above about LoRa vs LoRa WAN - and I think the latter is definitively desirable for the community but also a stretch for a single contributor (https://lora-alliance.org/resource_hub/lorawan-104-specification-package/).

So a shout out here I am super appreciative for any design/code input on the just opened draft PR esphome/esphome#3970 🙏

Hey,

Looking to have Lora working on some node too. For some reason I loose wifi on one or 2 devices depending on the weather. Can't do much as they live outside and and i'd rather not pay for a new AP. What I would like is LoRa to be a backup for only the data. Anyhow if you need some help testing I'll be happy to lend a hand. I currently have 2 TTGO lora V1.3 on hand, one is running openmqttgate but stability is an issue as it dissconnects from wifi. Strangly when flashed with esphome it never goes offline. I digress. I'll have a look at what you're doing and see if I can get it working on my end.

@AquaMCU
Copy link

AquaMCU commented Nov 21, 2022

Hello Folks.

Here is a new proposal. I am not giving up!


LORA to MQTT gateway component:
Receiving sensor data:
The sensor sends a string via LORA like "/sensorID/topic/value". This gets parsed in the gateway into topic and payload and is send to the MQTT server using the ESPHomes MQTT component

Sending Data:
The component gets a list of topics and will notify for these on the MQTT server. When receiving a message, it will send the data on lora like above "/sensorID/action/value"

For the nodes, we need a simple component that registers for a list of "/sensorID/action" that can be used with on_xxx statements

As for sending, an action can be called to send the data via lora to the gateway.

What do you guys think?

@prghix
Copy link

prghix commented Nov 22, 2022

What do you guys think?

I'd vote for anything that would work.

Missing LORA support is IMHO a growing handicap for ESPhome. Wifi or wire is not always available... so it limits the range of applications considerably.

@MrSuicideParrot
Copy link

Having support for LORA, is better than not having it.
So having a component that implements lora gateway to mqtt is nice.

However, I think it would to be better to have an approach similar to other existing solutions like ble. I know it's a little bit different because ble has a structured way of representing data, but there are workarounds. We could have two base component, one to receive and other to send. These components would receive raw data, and then people would implement on top of these two components what they want. They could develop a custom component or use templates and handle the data themselves.

Using this approach, the LORA to MQTT gateway would be straight forward to implement. It's the conjunction of two components, the future lora component and the existing MQTT Client Component.

@AquaMCU
Copy link

AquaMCU commented Dec 4, 2022

I have created and budgeted a project to develop the custom component. You can find it here:

https://www.upwork.com/freelance-jobs/apply/Two-Custom-Components-for-ESPhome-LORA_~0107924f9216450ddd/

@prghix
Copy link

prghix commented Dec 4, 2022

I have created and budgeted a project to develop the custom component. You can find it here:

https://www.upwork.com/freelance-jobs/apply/Two-Custom-Components-for-ESPhome-LORA_~0107924f9216450ddd/

I'll pay that 100USD straight away. Mmnt.

@prghix
Copy link

prghix commented Dec 4, 2022

It says we already got an account at Upwork. Wait another moment, I need to reset the password.

@prghix
Copy link

prghix commented Dec 4, 2022

I could not pay it because -- likely because you have same role, as me (client).

Thought you were THAT developer, not that you're looking for a developer... :)

@nagyrobi
Copy link
Member

nagyrobi commented Dec 4, 2022

Wondering if this offer will work out.

@Dodoooh
Copy link

Dodoooh commented Dec 13, 2022

I have created and budgeted a project to develop the custom component. You can find it here:

https://www.upwork.com/freelance-jobs/apply/Two-Custom-Components-for-ESPhome-LORA_~0107924f9216450ddd/

i can no longer find this on upwork?
I would also like to support the development of LORA I think that would be a game changer in terms of ESPHOME functionality

I would like to realize with it a remote control, read out sensors from far away... and many more ideas

@prghix
Copy link

prghix commented Dec 15, 2022

Hello. I'd sponsor this with additional 100 EUR.

@oxan
Copy link
Member

oxan commented Feb 20, 2023

Hypothetically, if I'd work on mesh networking support for ESPHome, would people be mostly interested in node-to-node communication (i.e. ability to retrieve state/control "entities"/run automations on other nodes), or on node-to-HA communication?

@MarkoPaasila
Copy link

MarkoPaasila commented Feb 21, 2023

I would be first and foremost interested in node<->HA communication. Reaching earlier unreachable locations and extending the possible coverage of a network (by means of node hopping) would be a game changer. The possibility of node-to-node communication wouldn't be a game changer in the same magnitude at least. It would enable some autonomous setups which however require much more planning since OTA wouldn't work - and eventually people want connection to HA anyway to monitor the remote nodes and collect data etc. Node-to-node communication would also add resilience by removing dependence on home-assistant/mqtt (and on a wifi access point?). Not by any means a game changer. So extending the reach of the network by meshing would absolutely be the greatest improvement!

@katsaplias
Copy link

I would be first and foremost interested in node<->HA communication. Reaching earlier unreachable locations and extending the possible coverage of a network (by means of node hopping) would be a game changer. The possibility of node-to-node communication wouldn't be a game changer in the same magnitude at least. It would enable some autonomous setups which however require much more planning since OTA wouldn't work - and eventually people want connection to HA anyway to monitor the remote nodes and collect data etc. Node-to-node communication would also add resilience by removing dependence on home-assistant/mqtt (and on a wifi access point?). Not by any means a game changer. So extending the reach of the network by meshing would absolutely be the greatest improvement!

I agree

@Ex3mXX
Copy link

Ex3mXX commented Apr 13, 2023

I'm using LoRaWan https://www.helium.com/ with HA.
My device is sending to the helium network and from there I just do a HTTP Post to a webhook on my HA to get the the information that i need.
No need to buy LoRa gateway or receiver device.

@nagyrobi
Copy link
Member

How did you set up Helium webhooks to HA?

@Ex3mXX
Copy link

Ex3mXX commented Apr 13, 2023

In HA you create a Automation with a webhook. Then in Helium you create a http integration and just do a post to your webhook address on your HA with the payload from your device.

@jeffehobbs
Copy link

The killer integration here is ESPHome LoRaWAN devices that can talk to the Amazon Sidewalk network. Information here:

https://www.theverge.com/2023/3/28/23659191/amazon-sidewalk-network-coverage

and here:

https://docs.aws.amazon.com/iot/latest/developerguide/iot-sidewalk.html

This would open up so many cool uses for ESPHome.

@MrSuicideParrot
Copy link

MrSuicideParrot commented Apr 23, 2023 via email

@jeffehobbs
Copy link

jeffehobbs commented Apr 23, 2023

The Sidewalk network white paper refers to "Third-party endpoints" but nothing in the writeup leads me to believe that the device needs to be produced by Amazon.

https://m.media-amazon.com/images/G/01/sidewalk/final_privacy_security_whitepaper.pdf

What Sidewalk offers is non-trivial; a mesh network that extends well beyond a single user's LoRa WAN setup. If you're interested in seeing what coverage looks like in your local area, Amazon offers a "test kit" (a LoRa WAN dongle hardcoded to an online map) here:

https://sidewalk.amazon/testkit

@Sperryfreak01
Copy link

Sidewalk isn't exactly LORA but it is built on CSS like LoRA. I don't think there is a sidewalk stack for ESP yet, SiLAbs, TI, Nordic, Quectel all have one though, Sidewalk devices require a certificate to be loaded onto the device so it can authenticate to the sidewalk network. Also keep in mind that hubs (echos, ring, etc) have a monthly 500MB data cap, share across all devices that connect to that hub. You can do a federation operation to exclude your own devices from your own cap but these are all things that would need to be developed for it to work with ESPhome.

@UrbanTechIO
Copy link

A blast from the past...
I came here to check whether someone have resolved the ESPHome integration of the LORA library or not.
My current approach is to have one Lora sender, and one Lora receiver.
the Receiver module is connected to Firebase via WIFI and update the real-time database after generating some additional information.
Then using Node-Red to read the database into a sensor in HA.
It works for the moment, but i will transform the entire method once the ESPHome start supporting LORA.

@idimou
Copy link

idimou commented Jun 14, 2024

Instead of a raw LoRa integration a more user friendly path could be to
implement a component to leverage the existing TheThingsNetwork (TTN) e.g. using the proven LMIC LoRa TTN library

@IoT-CI-Ltd
Copy link

I would not like to see this tied to TTN at all but a generic LMIC library (that can be used for other LNS as well)

@nagyrobi
Copy link
Member

nagyrobi commented Feb 7, 2025

Making progress in esphome/esphome#8187, and first implementation is for UART: esphome/esphome#8214. This is a generalised approach, which will make possible to develop simpler components for exchanging data directly between nodes by any means, like TCP, ESP-Now, LoRa, etc.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests