Metadata-Version: 2.4
Name: loramesh
Version: 1.0.0
Summary: C++ library to communicate with Radioenge LoRaMESH modules via UART, with Python bindings
Author-email: Gustavo Cereza <contato@elcereza.com>
License-Expression: MIT
Project-URL: Homepage, https://elcereza.com
Project-URL: Repository, https://github.com/elcereza/LoRaMESH
Keywords: lora,mesh,loramesh,radioenge,uart,iot,embedded
Classifier: Programming Language :: Python :: 3
Classifier: Programming Language :: C++
Classifier: Operating System :: OS Independent
Description-Content-Type: text/markdown

# 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

```bash
pip install .
```

## 1.2 Instalação futura (PyPI)

```bash
pip install loramesh
```

---

# 2. Inicialização

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

```python
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.

```python
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:

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

---

# 5. Configuração da Rede

## 5.1 Definir Network ID

```python
mesh.setNetworkID(0)
```

## 5.2 Definir senha

```python
mesh.setPassword(123)
```

---

# 6. Configuração de Rádio

## 6.1 Ler configuração atual

```python
mesh.getBPS()

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

## 6.2 Definir configuração

```python
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

```python
mesh.setClass(lora_class=0x02, window=0x00)
```

| Classe   | Valor |
| -------- | ----- |
| Classe A | 0x00  |
| Classe C | 0x02  |

---

# 8. Controle de GPIO Remoto

## 8.1 Configurar pino

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

## 8.2 Escrever pino

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

## 8.3 Ler pino

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

---

# 9. Leitura Analógica

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

---

# 10. Medições e Cálculos

## 10.1 Ruído

```python
noise = mesh.getNoise(id=1)
```

## 10.2 Resistência

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

## 10.3 Temperatura (NTC)

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

---

# 11. Informações do Dispositivo

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

---

# 12. Exemplo Completo

```python
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

```text
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.

```python
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.

```python
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.

```python
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.

```python
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

```python
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)

```python
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

```python
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:

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

Isso permite:

```python
from loramesh import BW500, SF7
```


10. 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)

``` bash
pip install loramesh
```

## 1.2 Instalação local

``` bash
pip install .
```

## 1.3 Dependências

``` bash
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

``` python
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)

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

## 4.2 Spreading Factor (SF)

``` c
#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)

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

## 4.4 Classe

``` c
#define CLASS_A 0x00
#define CLASS_C 0x02
```

## 4.5 Janela de Recepção

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

------------------------------------------------------------------------

# 5. GPIO e IO

``` c
#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:

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

------------------------------------------------------------------------

# 6. Exemplo Completo

``` python
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

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

------------------------------------------------------------------------

# 9. Licença

MIT License



