Skip to main content

C++ library to communicate with Radioenge LoRaMESH modules via UART, with Python bindings

Project description

LoRaMESH Python SDK

Biblioteca Python para comunicação com módulos LoRaMESH via interface serial, utilizando bindings em C++ com pybind11.

Esta biblioteca permite controlar dispositivos em rede LoRa de forma direta, com suporte a configuração de rádio, GPIO remoto, leitura analógica e debug completo da comunicação.


1. Instalação

1.1 Instalação local

pip install .

1.2 Instalação futura (PyPI)

pip install loramesh

2. Inicialização

A biblioteca utiliza comunicação serial com o módulo LoRa.

from loramesh import LoRaMESH

mesh = LoRaMESH("/dev/ttyACM0", 9600)
mesh.begin()

Parâmetros

Parâmetro Tipo Descrição
device str Porta serial (/dev/ttyACM0, /dev/ttyUSB0, etc)
baud int Baudrate da comunicação

3. Debug da Comunicação

O debug mostra todos os frames TX/RX da rede.

mesh.begin(debug=True, hex_dump=True)

Saída esperada

TX CMD: 00 00 E2 ...
RX CMD: ...

Modos

Modo Descrição
debug=True Ativa debug
hex_dump=True Mostra payload em hexadecimal

4. Leitura do módulo

Antes de qualquer operação, é necessário garantir que o módulo respondeu:

while not mesh.localRead():
    print("Aguardando módulo...")

5. Configuração da Rede

5.1 Definir Network ID

mesh.setNetworkID(0)

5.2 Definir senha

mesh.setPassword(123)

6. Configuração de Rádio

6.1 Ler configuração atual

mesh.getBPS()

bw = mesh.getBW()
sf = mesh.getSF()
cr = mesh.getCR()

6.2 Definir configuração

mesh.setBPS(bw=0x02, sf=0x07, cr=0x01)

Parâmetros típicos

Parâmetro Valor Descrição
BW 0x02 500 kHz
SF 0x07 Spreading Factor 7
CR 0x01 Coding Rate 4/5

7. Classe LoRa

mesh.setClass(lora_class=0x02, window=0x00)
Classe Valor
Classe A 0x00
Classe C 0x02

8. Controle de GPIO Remoto

8.1 Configurar pino

mesh.pinMode(id=1, gpio=0, mode=1)

8.2 Escrever pino

mesh.digitalWrite(id=1, gpio=0, val=1)

8.3 Ler pino

value = mesh.digitalRead(id=1, gpio=0)

9. Leitura Analógica

adc = mesh.analogRead(id=1, gpio=0)

10. Medições e Cálculos

10.1 Ruído

noise = mesh.getNoise(id=1)

10.2 Resistência

r1 = mesh.getR1(rawADC=adc, R2=10000)

10.3 Temperatura (NTC)

temp = mesh.getTemp(rawADC=adc, beta=3950)

11. Informações do Dispositivo

mesh.getLocalID()
mesh.getUniqueID()
mesh.getBW()
mesh.getSF()
mesh.getCR()
mesh.getClassValue()
mesh.getWindow()

12. Exemplo Completo

from loramesh import LoRaMESH
import time

mesh = LoRaMESH("/dev/ttyACM0", 9600)

mesh.begin(debug=True)

# Aguarda módulo
while not mesh.localRead():
    print("Aguardando módulo...")
    time.sleep(0.5)

print("Módulo pronto")

# Configuração
mesh.setNetworkID(0)
mesh.setPassword(123)

# Rádio
mesh.setBPS(0x02, 0x07, 0x01)

# GPIO remoto
mesh.pinMode(1, 0, 1)
mesh.digitalWrite(1, 0, 1)

# Leitura
value = mesh.digitalRead(1, 0)
adc = mesh.analogRead(1, 0)

print("GPIO:", value)
print("ADC:", adc)

13. Arquitetura

A biblioteca é composta por:

  • Core em C++ (LoRaMESH)
  • Transporte serial (LinuxSerialTransport)
  • Binding Python via pybind11
Python → pybind11 → C++ → Serial → LoRa Module

14. Observações Importantes

  • O módulo deve estar conectado corretamente via serial
  • O baudrate deve coincidir com o firmware do rádio (padrão é de 9600)
  • Sempre executar localRead() antes de qualquer comando
  • O debug depende de begin(debug=True)

18.1 Largura de Banda (Bandwidth)

Define a largura de banda do rádio LoRa.

BW125 = 0x00
BW250 = 0x01
BW500 = 0x02
Constante Valor Descrição
BW125 0x00 125 kHz (maior alcance, menor taxa)
BW250 0x01 250 kHz
BW500 0x02 500 kHz (maior taxa, menor alcance)

18.2 Spreading Factor (SF)

Define a robustez do sinal e tempo de transmissão.

SF7  = 0x07
SF8  = 0x08
SF9  = 0x09
SF10 = 0x0A
SF11 = 0x0B
SF12 = 0x0C

SF_FSK = 0x00
Constante Descrição
SF7 Alta velocidade, menor alcance
SF8
SF9
SF10
SF11
SF12 Maior alcance, menor velocidade
SF_FSK Modo FSK (não LoRa)

18.3 Coding Rate (CR)

Define redundância para correção de erro.

CR4_5 = 0x01
CR4_6 = 0x02
CR4_7 = 0x03
CR4_8 = 0x04
Constante Descrição
CR4_5 Menor redundância, mais rápido
CR4_6
CR4_7
CR4_8 Maior redundância, mais robusto

18.4 Classe LoRa

Define comportamento de recepção.

CLASS_A = 0x00
CLASS_C = 0x02
Classe Descrição
CLASS_A Baixo consumo, janela após TX
CLASS_C Recepção contínua

18.5 Janela de Recepção

WINDOW_5s  = 0x00
WINDOW_10s = 0x01
WINDOW_15s = 0x02
Constante Descrição
WINDOW_5s Janela de 5 segundos
WINDOW_10s Janela de 10 segundos
WINDOW_15s Janela de 15 segundos

18.6 Configuração de Pull (GPIO)

LoRa_NOT_PULL = 0x00
LoRa_PULLUP   = 0x01
LoRa_PULLDOWN = 0x02
Constante Descrição
LoRa_NOT_PULL Sem pull
LoRa_PULLUP Pull-up interno
LoRa_PULLDOWN Pull-down interno

19. Exemplo utilizando constantes

from loramesh import LoRaMESH

mesh = LoRaMESH("/dev/ttyACM0", 9600)

mesh.begin()

mesh.setBPS(
    bw=BW500,
    sf=SF7,
    cr=CR4_5
)

mesh.setClass(
    lora_class=CLASS_C,
    window=WINDOW_5s
)

mesh.pinMode(
    id=1,
    gpio=0,
    mode=LoRa_PULLUP
)

20. Observação importante

Atualmente, essas constantes são definidas no core em C++. Para uso direto em Python, recomenda-se:

  • Criar um módulo constants.py
  • Ou expor via binding (recomendado)

21. Sugestão (melhoria futura)

Expor constantes diretamente no Python:

m.attr("BW500") = 0x02;
m.attr("SF7") = 0x07;

Isso permite:

from loramesh import BW500, SF7
  1. Controle de GPIO

O módulo LoRaMESH permite controlar GPIOs remotamente, o que é um dos principais diferenciais da rede.

10.1 Configuração de Pino

Antes de usar um pino, é necessário configurá-lo:

mesh.pinMode(device_id, pin, mode) Modos disponíveis #define INOUT_DIGITAL_INPUT 0x00 #define INOUT_DIGITAL_OUTPUT 0x01 #define INOUT_ANALOG_INPUT 0x03 Exemplo

Configura pino 3 como saída em um dispositivo remoto (ID = 1)

mesh.pinMode(1, 3, loramesh.INOUT_DIGITAL_OUTPUT) 10.2 Escrita Digital (Digital Write)

Permite ligar/desligar um pino remoto.

mesh.digitalWrite(device_id, pin, value) Valores LOW = 0 HIGH = 1 Exemplo

Liga o pino 3 no dispositivo 1

mesh.digitalWrite(1, 3, 1)

Desliga

mesh.digitalWrite(1, 3, 0) 10.3 Leitura Digital (Digital Read) value = mesh.digitalRead(device_id, pin) Exemplo estado = mesh.digitalRead(1, 4)

print("Estado do pino:", estado) 10.4 Leitura Analógica value = mesh.analogRead(device_id, pin) Observações importantes O valor retornado depende da resolução do ADC do módulo Normalmente retorna um inteiro (ex: 0–1023 ou 0–4095) Exemplo valor = mesh.analogRead(1, 2)

print("Valor analógico:", valor) 11. Controle Remoto de Dispositivos (Slave)

A rede LoRaMESH funciona com endereçamento por device_id.

Você pode controlar qualquer nó remoto diretamente.

11.1 Envio de Comando para Slave mesh.digitalWrite(2, 1, 1)

Nesse caso:

2 → ID do dispositivo remoto 1 → pino 1 → HIGH 11.2 Comunicação Transparente

Permite enviar payload arbitrário para outro nó:

mesh.sendTransparent(device_id, payload) Exemplo mesh.sendTransparent(2, b"START_PUMP") 11.3 Recebimento de Dados

Você pode verificar se há dados recebidos:

if mesh.available(): data = mesh.receive() print("Recebido:", data) 12. Fluxo Real de Uso (Exemplo Completo)

Aqui está um exemplo prático de controle de um dispositivo remoto:

Cenário Gateway (ID = 0) Slave (ID = 1) Slave controla uma bomba via GPIO Código import loramesh import time

mesh = loramesh.LoRaMESH("/dev/ttyACM0", 115200)

Aguarda módulo

while not mesh.localRead(): time.sleep(0.5)

print("Módulo pronto")

Configura slave

mesh.pinMode(1, 3, loramesh.INOUT_DIGITAL_OUTPUT)

Liga bomba

print("Ligando bomba...") mesh.digitalWrite(1, 3, 1)

time.sleep(5)

Desliga bomba

print("Desligando bomba...") mesh.digitalWrite(1, 3, 0) 13. Boas Práticas 13.1 Delay entre comandos

Evite enviar comandos muito rápido:

time.sleep(0.1)

A rede LoRa possui latência natural.

13.2 Retry

Implemente tentativas:

for _ in range(3): if mesh.digitalWrite(1, 3, 1): break 13.3 Monitoramento de rede

Sempre valide:

if not mesh.localRead(): print("Módulo desconectado") 14. Observações Importantes Comunicação LoRa não é tempo real Latência depende de: SF (Spreading Factor) BW Número de hops Quanto maior o SF → maior alcance, menor velocidade 15. Casos de Uso

Essa biblioteca permite construir:

Automação rural (bombas, válvulas) Sensoriamento distribuído Redes industriais Monitoramento remoto Controle de dispositivos sem internet

LoRaMESH Python

Biblioteca Python para comunicação com módulos LoRaMESH (Radioenge) via interface serial.

Esta biblioteca utiliza bindings em C++ com pybind11 para fornecer alto desempenho e acesso direto ao protocolo do módulo, mantendo uma interface simples e objetiva em Python.


1. Instalação

1.1 Via pip (quando publicado)

pip install loramesh

1.2 Instalação local

pip install .

1.3 Dependências

pip install pybind11 setuptools

2. Arquitetura

A biblioteca segue uma arquitetura em camadas:

Python API
    ↓
Bindings (pybind11)
    ↓
Core C++ (LoRaMESH)
    ↓
Transport (LinuxSerialTransport)
    ↓
UART (/dev/ttyACM0, /dev/ttyUSB0, etc)
    ↓
Módulo LoRaMESH

3. Inicialização

import loramesh
import time

mesh = loramesh.LoRaMESH("/dev/ttyACM0", 115200)

print("Aguardando módulo...")

while not mesh.localRead():
    print("Módulo não respondeu ainda...")
    time.sleep(0.5)

print("Módulo pronto")

4. Configurações do Rádio

4.1 Bandwidth (BW)

#define BW125 0x00
#define BW250 0x01
#define BW500 0x02

4.2 Spreading Factor (SF)

#define SF7  0x07
#define SF8  0x08
#define SF9  0x09
#define SF10 0x0A
#define SF11 0x0B
#define SF12 0x0C
#define SF_FSK 0x00

4.3 Coding Rate (CR)

#define CR4_5 0x01
#define CR4_6 0x02
#define CR4_7 0x03
#define CR4_8 0x04

4.4 Classe

#define CLASS_A 0x00
#define CLASS_C 0x02

4.5 Janela de Recepção

#define WINDOW_5s  0x00
#define WINDOW_10s 0x01
#define WINDOW_15s 0x02

5. GPIO e IO

#define LNOT_PULL  0x00
#define LPULLUP    0x01
#define LPULLDOWN  0x02

#define INOUT_DIGITAL_INPUT  0x00
#define INOUT_DIGITAL_OUTPUT 0x01
#define INOUT_ANALOG_INPUT   0x03

Compatibilidade com Arduino:

#define INPUT            0
#define OUTPUT           1
#define INPUT_PULLUP     7
#define INPUT_PULLDOWN   8

6. Exemplo Completo

import loramesh
import time

mesh = loramesh.LoRaMESH("/dev/ttyACM0", 115200)

while not mesh.localRead():
    time.sleep(0.5)

mesh.setNetworkID(0)

mesh.getBPS()

print("BW:", mesh.getBW())
print("SF:", mesh.getSF())
print("CR:", mesh.getCR())

payload = b"Hello LoRa"

mesh.sendTransparent(1, payload)

7. Estrutura do Projeto

python/
├── setup.py
├── bindings.cpp
├── src/
│   ├── core/
│   │   ├── LoRaMESH.cpp
│   │   └── LoRaMESH.h
│   ├── adapters/
│   │   └── linux/
│   │       └── LinuxSerialTransport.cpp

8. Publicação no PyPI

pip install build twine
python -m build
twine upload dist/*

9. Licença

MIT License

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

loramesh-1.0.0.tar.gz (17.0 kB view details)

Uploaded Source

File details

Details for the file loramesh-1.0.0.tar.gz.

File metadata

  • Download URL: loramesh-1.0.0.tar.gz
  • Upload date:
  • Size: 17.0 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.2.0 CPython/3.10.12

File hashes

Hashes for loramesh-1.0.0.tar.gz
Algorithm Hash digest
SHA256 080d713a3a0903badb3d5f1bea5f0f506dd8c7fb6b5d55efc856007e8a872dc8
MD5 55c7f40c7b5824d75991a71fa5468702
BLAKE2b-256 7bc8ffc669f61ff560cbbd37da6441a1f7a86de6eccb5a360693e19664e8d987

See more details on using hashes here.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page