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
- 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
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
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
080d713a3a0903badb3d5f1bea5f0f506dd8c7fb6b5d55efc856007e8a872dc8
|
|
| MD5 |
55c7f40c7b5824d75991a71fa5468702
|
|
| BLAKE2b-256 |
7bc8ffc669f61ff560cbbd37da6441a1f7a86de6eccb5a360693e19664e8d987
|