Product

Build a Long‑Range LoRa Gateway for Home Assistant with M5Stack

If you've been wanting to use your devices remotely for a while, today you'll learn how to do it by integrating LoRa into Home Assistant.

Index

l  What is LoRa and how does it work?

l  Prerequisites

l  Mounting and configuring the LoRa Gateway

l  LoRa node configuration

l  Check the communication

l  Sending information

l  Customize your Gateway

l  Acknowledgments

What is LoRa and how does it work?

LoRa (an acronym for "Long Range") is a radio frequency communication protocol that enables long-distance data transmission (up to 10 km in open fields) with very low power consumption. Therefore, it offers two major advantages:

  • It has a much greater range than the protocols we commonly use (WiFi, Bluetooth, Zigbee, etc.). This makes it the ideal choice for remote sensors (storage rooms, mailboxes, large gardens, etc.).
  • It doesn't rely on the telephone or electrical network to transmit information, so different LoRa devices can communicate even during a power outage.

However, it also has its limitations, as its data transfer speed is slow. In practice, this means it's perfect for sending simple data (commands to our devices, numbers, or text strings), but it's not a suitable protocol for transmitting photos or videos.

Additionally, you should consider the frequency LoRa uses in your geographic area. For example, in Europe it's 868 MHz, while in the US and most of Latin America it's 915 MHz.

Prerequisites

To integrate LoRa into Home Assistant, you will need the following components:

  • A LoRa gateway that receives information from the various nodes and transmits it to Home Assistant. In this case, we're going to create a gateway with the M5Stack Core S3 SE (yes, the same one we already used to Activate Assist ), combined with the LoRa868 modules and an external battery (this is optional).
  • A LoRa node that collects and sends information (e.g., a connected sensor). In this case, we're going to use a board with the integrated SX1276 chip (which would also be a valid device to act as a LoRa gateway).
  • A  USB cable to power the DATA board  (  with a charging cable, you will not be able to install the software).
  • Having installed  ESPHome in Home Assistant.

Mounting and configuring the LoRa Gateway

We are going to be using the M5Stack Core S3 SE along with the LoRa868 V1.1 module (now the LoRa868 v1.2 module is available). This is a modular device that's very easy to expand by simply assembling the components.

Something important to keep in mind is that the LoRa module has some small switches on the back ('DIP switches') that modify the pin assignment, and logically, it must match what we indicate in the ESPHome code.

To do this, make sure the switches are in the following position (2, 6 and 7 on and the rest off).

From here, the process will be similar for any compatible motherboard (adapting the steps and connection diagram to the specifications of your device). The steps we followed are as follows:

1.      In Home Assistant, go to your ESPHome plugin  , tap “New device” and “Continue.”

2.    Give your device a name  (for example, “LoRa Gateway” )  and click “Next”.

3.    Select “ESP32-S3” as the device type . You'll notice that a new block has been created for your device in the background.

4.   Click “Skip” and click “Edit” above your device block.

5.    Add the following lines to the end of your code (which come directly from the ESPHome SX127x component, adapted to our device).

captive_portal:

spi:
  clk_pin: GPIO36 
  mosi_pin: GPIO37 
  miso_pin: GPIO35 

sx127x:
  cs_pin: GPIO6 
  rst_pin: GPIO7 
  dio0_pin: GPIO10 
  pa_pin: BOOST
  pa_power: 14
  bandwidth: 125_0kHz
  crc_enable: true
  frequency: 868920000
  modulation: LORA
  rx_start: true
  sync_value: 0x12
  spreading_factor: 7
  coding_rate: CR_4_5
  preamble_size: 8
  on_packet:
    then:
      - lambda: |-
          ESP_LOGD("lambda", "packet %s", format_hex(x).c_str());
          ESP_LOGD("lambda", "rssi %.2f", rssi);
          ESP_LOGD("lambda", "snr %.2f", snr);

button:
  - platform: template
    name: "Transmit Packet"
    on_press:
      then:
        - sx127x.send_packet:
            data: [0xC5, 0x51, 0x78, 0x82, 0xB7, 0xF9, 0x9C, 0x5C]

6.   Click “Save” and “Install.” Select “Manual download” and wait for the code to compile. 

7.   When finished, select the “Modern format” option to download the corresponding '.bin' file.

8.   Connect the M5Stack Core S3 SE to your computer using the USB-C data cable via the port on the side.

9.   Now go to the ESPHome page   and click "Connect." In the pop-up window,  select your board  and click "Connect."

10.   Now click on “Install” and select the '.bin' file obtained in step 7. Again, click on  “Install”.

11.  Return to Home Assistant and go to  Settings > Devices & Services. Your device should have been discovered and appear at the top, waiting for you to press the  "Configure" button. Otherwise, click the "Add integration" button, search for "ESPHome," and enter your board's IP address in the "Host" field. As always, we recommend assigning a static IP address to your router to avoid future issues if it changes.

LoRa node configuration

Now that we have our LoRa gateway, let's configure a node to send information to it. To do this, we'll follow steps very similar to those in the previous section:

1.      In Home Assistant, go to your ESPHome plugin  , tap  “New device”  and “Continue.”

2.    Give your device a name  (for example,  “LoRa Node” )  and click “Next”.

3.    Select “ESP32” as the device type  . You'll notice a new block has been created for your device in the background.

4.   Click “Skip” and click “Edit” above your device block.

5.    Add the following lines to the end of your code  (which in this case match the example of the  SX127x component of ESPHome).

captive_portal:

spi:
  clk_pin: GPIO5
  mosi_pin: GPIO27
  miso_pin: GPIO19

# Example configuration entry
sx127x:
  cs_pin: GPIO18
  rst_pin: GPIO23
  dio0_pin: GPIO26
  pa_pin: BOOST
  pa_power: 14
  bandwidth: 125_0kHz
  crc_enable: true
  frequency: 868920000
  modulation: LORA
  rx_start: true
  sync_value: 0x12
  spreading_factor: 7
  coding_rate: CR_4_5
  preamble_size: 8
  on_packet:
    then:
      - lambda: |-
          ESP_LOGD("lambda", "packet %s", format_hex(x).c_str());
          ESP_LOGD("lambda", "rssi %.2f", rssi);
          ESP_LOGD("lambda", "snr %.2f", snr);

button:
  - platform: template
    name: "Transmit Packet"
    on_press:
      then:
        - sx127x.send_packet:
            data: [0xC5, 0x51, 0x78, 0x82, 0xB7, 0xF9, 0x9C, 0x5C]

6.   Note that the pin assignment is different (because we're using a different device than the one we used for the Gateway), but the rest of the configuration is exactly the same as in the previous section. This is important so they can communicate with each other.

7.   Click “Save” and “Install.” Select  “Manual download”  and wait for the code to compile. 

8.   When finished, select the “Modern format” option to download the corresponding '.bin' file.

9.   Connect the board to your computer using the Micro USB data cable through the port on the side.

10.   Now go to the ESPHome page   and click "Connect." In the pop-up window,  select your board  and click "Connect."

11.  Now click on “Install” and select the '.bin' file obtained in step 8. Again, click on  “Install”.

12.    Return to Home Assistant and go to  Settings > Devices & Services . Your device should have been discovered and appear at the top, waiting for you to press the  "Configure" button . Otherwise, click the "Add integration" button, search for "ESPHome," and enter your board's IP address in the "Host" field. As always, we recommend assigning a static IP address to your router to avoid future issues if it changes.

Check the communication

Let's do a little test to check that both devices are communicating correctly (the Gateway and the node) .

1.      Make sure both devices are turned on and are online in Home Assistant and ESPHome.

2.    From Home Assistant, go to Settings > Devices & Services > ESPHome and access one of them (for example, the Gateway).

3.    Open a new window (without closing the previous one), enter the ESPHome plugin and access the logs of the other device (in this case, the node).

4.   In the Home Assistant window, click the "Transmit Packet" button. You'll immediately see the logs from the second device recording the incoming packet.

You can perform a reverse test to verify that communication is working both ways. If everything went well, your devices are now communicating.

Sending information

Logically, the point of integrating LoRa into Home Assistant is to send some kind of useful information (such as the value of a sensor connected to the node).

1.      The first step is to add the sensor you're interested in to the node board. For example, we're going to add a PIR sensor to get the long-awaited motion sensor on the mailbox. To do this, we've added the following code snippet:

binary_sensor:
  - platform: gpio
    pin: GPIO34
    name: "PIR Sensor"
    device_class: motion
    id: pir_sensor

2.    If you look at the code above, it's the same one we would use in any "normal" scenario. However, to send the information to our LoRa Gateway, we need to add something extra using the 'Packet Transport' component.

packet_transport:
  platform: sx127x
  update_interval: 5s
  encryption: "password"
  rolling_code_enable: true
  binary_sensors:
    - pir_sensor

3.    Analyze the code above and observe the following:

·        In the 'encryption' attribute, you have to indicate the encryption key for your message (whatever you want), so that it cannot be received by anyone on the same frequency.

·        We've identified the ID of the sensor we want to send (in this case, the binary sensor with the ID "pir_sensor") . You can add any other sensors you're interested in here.

4.   Now we are going to add the following to the code of our LoRa Gateway, so that it receives the information.

packet_transport:
  platform: sx127x
  update_interval: 5s
  providers:
    - name: lora-node
      encryption: "password"

binary_sensor:
  - platform: packet_transport
    id: pir_sensor
    provider: lora-node

  - platform: template
    name: "Buzón"
    device_class: motion
    lambda: return id(pir_sensor).state;

5.    Now we’re going to add the following to the code of our LoRa Gateway, so it can receive the information.

Again, analyze the code and note the following:

l We have specified the ESPHome device name of our LoRa node as the data provider.

l In the ‘encryption’ attribute, we have indicated exactly the same key as in the node.

l To transform the information received into a gateway sensor, we used the “packet_transport” platform. We assigned it an “id” (you can choose any) and again indicated the LoRa node name as the provider. This is an internal ESPHome sensor.

l To display this information in Home Assistant, we created a template sensor of the same type, assigning it the value of the internal sensor created in the previous step.

6.   And that's it! If you now check your gateway device in Home Assistant, you’ll see that it already shows the information from the node.

Customize your Gateway

Since we used the M5Stack Core S3 SE to integrate LoRa into Home Assistant, we can take advantage of its other features to customize it! Below, we're leaving you the full code to create a screen that notifies you when you receive letters in your mailbox!

esphome:
  name: lora-gateway
  friendly_name: LoRa Gateway
  libraries:
    - m5stack/M5GFX@^0.1.11
    - m5stack/M5Unified@^0.1.11

esp32:
  board: esp32-s3-devkitc-1
  framework:
    type: esp-idf

psram:
  mode: octal
  speed: 80MHz

external_components:
  - source:
      type: git
      url: https://github.com/m5stack/M5CoreS3-Esphome
    components: [ m5cores3_display ]
    refresh: 0s

# Enable logging
logger:

# Enable Home Assistant API
api:
  encryption:
    key: "1QrsXUgryxlF6OGsIwLj7eijyy/OMhSobQQHYWPvpb0="

ota:
  - platform: esphome
    password: "4844c4205ab6ab665c2d1a4be82deb57"

wifi:
  ssid: !secret wifi_ssid
  password: !secret wifi_password

  # Enable fallback hotspot (captive portal) in case wifi connection fails
  ap:
    ssid: "Lora-Gateway Fallback Hotspot"
    password: "6BRaaV17Iebb"

captive_portal:

spi:
  clk_pin: GPIO36 
  mosi_pin: GPIO37 
  miso_pin: GPIO35 

sx127x:
  cs_pin: GPIO6 
  rst_pin: GPIO7 
  dio0_pin: GPIO10 
  pa_pin: BOOST
  pa_power: 14
  bandwidth: 125_0kHz
  crc_enable: true
  frequency: 868920000
  modulation: LORA
  rx_start: true
  sync_value: 0x12
  spreading_factor: 7
  coding_rate: CR_4_5
  preamble_size: 8
  on_packet:
    then:
      - lambda: |-
          ESP_LOGD("lambda", "packet %s", format_hex(x).c_str());
          ESP_LOGD("lambda", "rssi %.2f", rssi);
          ESP_LOGD("lambda", "snr %.2f", snr);

packet_transport:
  platform: sx127x
  update_interval: 5s
  providers:
    - name: lora-node
      encryption: "password"

binary_sensor:
  - platform: packet_transport
    id: pir_sensor
    provider: lora-node

  - platform: template
    name: "Buzón"
    device_class: motion
    lambda: return id(pir_sensor).state;

color:
  - id: green
    hex: 'bfea11'
  - id: red
    hex: 'ff0000'

font:
  - file: "gfonts://Roboto"
    id: font_title
    size: 18
  - file: "gfonts://Roboto"
    id: font_text
    size: 16

image:
  - file: mdi:mailbox
    id: buzon_off
    resize: 100x100
    type: grayscale
    transparency: alpha_channel
  - file: mdi:email-alert
    id: buzon_on
    resize: 100x100
    type: grayscale
    transparency: alpha_channel

display:
  - platform: m5cores3_display
    model: ILI9342
    dc_pin: 15
    update_interval: 1s
    id: m5cores3_lcd
    lambda: |-
      // Obtener dimensiones de la pantalla
      int screen_width = it.get_width();
      int screen_height = it.get_height();
      
      // Título en la parte superior con margen de 20px
      it.print(screen_width/2, 20, id(font_title), id(green), TextAlign::TOP_CENTER, "LoRa Gateway by Aguacatec");
      
      // Obtener estado del sensor del buzón
      bool mailbox_open = id(pir_sensor).state;
            
      if (mailbox_open) {
        // Buzón abierto - icono rojo
        it.image(110, 70, id(buzon_on), id(red));
        it.print(screen_width/2, 200, id(font_text), id(red), TextAlign::CENTER, "Carta recibida!!");
      } else {
        // Buzón cerrado - icono verde
        it.image(110, 70, id(buzon_off), id(green));
        it.print(screen_width/2, 200, id(font_text), id(green), TextAlign::CENTER, "No hay correspondencia");
      }

Acknowledgements

To prepare this post, this video by our friend Miguel Ángel (from La Choza Digital) was extremely helpful! 

Source: AguacaTEC

Author: TitoTB

0 comments

  • There are no comments yet. Be the first one to post a comment on this article!

Leave a comment

Please note, comments must be approved before they are published

Liquid error (layout/theme line 224): Could not find asset snippets/pe-disco-countdown-timer.liquid