agrobot_base/Firmware/Modulos/LoRaService.h

677 lines
20 KiB
C
Raw Normal View History

2025-04-30 21:49:17 +00:00
// LoRaService.h
#ifndef LoRaService_h
#define LoRaService_h
#include "SerialService.h"
#include "CanService.h"
#include <Arduino.h>
#include <vector>
#include <map>
class LoRaService {
public:
enum LoRaMode {
NORMAL,
WAKE_UP,
POWER_SAVING,
CONFIG
};
enum CodigosFuncoes {
CfgTx = 0xC0,
CfgRx = 0xC1,
Msg = 0xE1,
WrongMode = 0xFC,
BeginMsg = 0xAA,
EndMsg = 0x55,
};
struct LoRaParametrosModel {
uint8_t address;
uint8_t baudAndAirRate;
uint8_t packetSizeAndPower;
uint8_t channel;
uint8_t tranModeAndWorCycle;
};
LoRaService(CanService* canService) {
_canService = canService;
}
bool Conectado = false;
bool Configurado = false;
byte AddressBase = 0x01;
// Inicializa pinos e UART
void Inicializar(uint8_t baudRate) {
Configurado = false;
_baudRate = encontrarChavePorValor(CodigosBaudRates, baudRate, 9600);
2025-05-09 20:17:28 +00:00
MostrarLog("Iniciando LoRa nos pinos TXD=" + String(_pinTXD) + ", RXD=" + String(_pinRXD) + ", baudRate=" + String(_baudRate) + "...");
2025-04-30 21:49:17 +00:00
// Inicializa GPIOs
pinMode(_pinM0, OUTPUT);
pinMode(_pinM1, OUTPUT);
pinMode(_pinAUX, INPUT);
_serialLoRa = &Serial2;
if (Conectado) {
_serialLoRa->end();
}
_serialLoRa->begin(_baudRate, SERIAL_8N1, _pinTXD, _pinRXD);
// Coloca o módulo em modo normal
setLoRaMode(NORMAL);
vTaskDelay(500); // Aguarda estabilização
// Testa conexão
Conectado = checkLoRaConnected();
if (Conectado) {
2025-05-09 20:17:28 +00:00
MostrarLog("E220 detectado!");
2025-04-30 21:49:17 +00:00
if (LraTaskRxHandle == NULL) {
lraQueueRx = xQueueCreate(50, sizeof(std::vector<uint8_t>));
if (lraQueueRx == NULL) {
2025-05-09 20:17:28 +00:00
MostrarLog("Falha ao criar fila RX!");
2025-04-30 21:49:17 +00:00
}
2025-05-06 18:47:59 +00:00
xTaskCreatePinnedToCore(LoRaService::LraTaskRxWrapper, "LraTaskRx", 4096, this, 14, &LraTaskRxHandle, APP_CPU_NUM);
2025-04-30 21:49:17 +00:00
}
if (LraTaskTxHandle == NULL) {
lraQueueTx = xQueueCreate(50, sizeof(std::vector<uint8_t>));
if (lraQueueTx == NULL) {
2025-05-09 20:17:28 +00:00
MostrarLog("Falha ao criar fila TX!");
2025-04-30 21:49:17 +00:00
}
2025-05-06 18:47:59 +00:00
xTaskCreatePinnedToCore(LoRaService::LraTaskTxWrapper, "LraTaskTx", 4096, this, 13, &LraTaskTxHandle, APP_CPU_NUM);
2025-04-30 21:49:17 +00:00
}
if (LraTaskProcessHandle == NULL) {
2025-05-06 18:47:59 +00:00
xTaskCreatePinnedToCore(LoRaService::LraTaskProcessWrapper, "LraTaskProcess", 4096, this, 15, &LraTaskProcessHandle, APP_CPU_NUM);
2025-04-30 21:49:17 +00:00
}
} else {
2025-05-09 20:17:28 +00:00
MostrarLog("E220 não detectado.");
2025-04-30 21:49:17 +00:00
}
}
std::vector<uint8_t> MontarMensagemCAN(CanMessagePosicaoDados posicao) {
std::vector<uint8_t> data;
data.push_back(static_cast<uint8_t>(posicao));
2025-05-01 18:27:01 +00:00
data.push_back(_canService->ID_Num_sLRA);
2025-04-30 21:49:17 +00:00
switch (posicao) {
case CanMessagePosicaoDados::Status: {
data.push_back(Conectado ? 1 : 0);
data.push_back(Configurado ? 1 : 0);
break;
}
case CanMessagePosicaoDados::Dados1: {
data.push_back(parametrosAtual.address);
data.push_back(parametrosAtual.baudAndAirRate);
data.push_back(parametrosAtual.packetSizeAndPower);
data.push_back(parametrosAtual.channel);
data.push_back(parametrosAtual.tranModeAndWorCycle);
break;
}
}
return data;
}
void EnviarComando(std::vector<uint8_t> dados) {
2025-05-01 18:27:01 +00:00
if (dados.size() < 2) return;
CanMessagePosicaoDados posicao = (CanMessagePosicaoDados)dados[0];
2025-04-30 21:49:17 +00:00
uint8_t idNum = dados[1];
switch (posicao) {
case CanMessagePosicaoDados::Command1: {
bool sucesso = requisitarParametrosLoRa();
EnviarDadosCAN(MontarMensagemCAN(CanMessagePosicaoDados::Dados1));
break;
}
default: {
AdicionarMensagemFilaLoRa(dados);
}
}
}
bool AdicionarMensagemFilaLoRa(std::vector<uint8_t> dados) {
if (xQueueSend(lraQueueTx, &dados, 0) != pdTRUE) {
2025-05-09 20:17:28 +00:00
MostrarLog("Fila TX cheia! Mensagem descartada.");
2025-04-30 21:49:17 +00:00
return false;
}
else {
2025-05-09 20:17:28 +00:00
MostrarLog("Mensagem adicionada na fila TX");
2025-04-30 21:49:17 +00:00
return true;
}
}
std::vector<uint8_t> ConfigurarModulo(std::vector<uint8_t> data) {
std::vector<uint8_t> status;
2025-05-01 18:27:01 +00:00
if (data.size() < 2) return status;
CanMessagePosicaoDados posicao = (CanMessagePosicaoDados)data[0];
2025-04-30 21:49:17 +00:00
uint8_t idNum = data[1];
2025-05-09 20:17:28 +00:00
MostrarLog("Recebido comando ConfigurarModulo: posicao = " + String((int)posicao));
2025-04-30 21:49:17 +00:00
switch (posicao) {
2025-05-01 18:27:01 +00:00
case CanMessagePosicaoDados::Config1: {
2025-05-09 20:17:28 +00:00
if (data.size() < 8) return data;
AddressBase = data[2];
_pinM0 = data[3];
_pinM1 = data[4];
_pinAUX = data[5];
_pinRXD = data[6];
_pinTXD = data[7];
2025-05-01 18:27:01 +00:00
break;
}
case CanMessagePosicaoDados::Config2: {
2025-05-09 20:17:28 +00:00
if (data.size() < 7) return status;
2025-05-01 18:27:01 +00:00
if (_pinRXD == 0 || _pinTXD == 0) {
2025-05-09 20:17:28 +00:00
MostrarLog("Erro ao iniciar E220, pinout ainda nao definido!");
2025-05-01 18:27:01 +00:00
return status;
2025-04-30 21:49:17 +00:00
}
2025-05-01 18:27:01 +00:00
uint8_t addr = data[2]; // address
uint8_t baud = data[3]; // baudAndAirRate
uint8_t packet = data[4]; // packetSizeAndPower
uint8_t channel = data[5]; // channel
uint8_t worCycle = data[6]; // tranModeAndWorCycle
uint8_t baudField = baud & 0xE0; // bits 5,6,7 (baudrate)
Inicializar(baudField);
EnviarDadosCAN(MontarMensagemCAN(CanMessagePosicaoDados::Status));
if (Conectado) {
if (requisitarParametrosLoRa()) {
EnviarDadosCAN(MontarMensagemCAN(CanMessagePosicaoDados::Dados1));
Configurado =
parametrosAtual.address == addr &&
parametrosAtual.baudAndAirRate == baud &&
parametrosAtual.packetSizeAndPower == packet &&
parametrosAtual.channel == channel &&
parametrosAtual.tranModeAndWorCycle == worCycle;
if (!Configurado) {
2025-05-09 20:17:28 +00:00
Configurado = configurarModuloLoRa(addr, baud, packet, channel, worCycle);
if (Configurado) {
EnviarDadosCAN(MontarMensagemCAN(CanMessagePosicaoDados::Dados1));
}
2025-04-30 21:49:17 +00:00
}
2025-05-01 18:27:01 +00:00
}
2025-04-30 21:49:17 +00:00
}
2025-05-01 18:27:01 +00:00
break;
}
2025-04-30 21:49:17 +00:00
}
return status;
}
private:
2025-05-09 20:17:28 +00:00
bool DebugMode = true;
void MostrarLog(String mensagem) {
if (DebugMode) {
PrintTela("[LORA] " + mensagem);
}
}
2025-04-30 21:49:17 +00:00
bool recebendo = false;
int bytesEsperados = -1;
int addrRemetente = -1;
int addrDestinatario = -1;
std::vector<uint8_t> buffer;
unsigned long ultimoByteRecebido = 0;
const unsigned long timeoutRecebimentoMs = 100; // por exemplo, 100ms
void reiniciarEstado() {
recebendo = false;
bytesEsperados = -1;
addrRemetente = -1;
addrDestinatario = -1;
buffer.clear();
}
QueueHandle_t lraQueueRx;
TaskHandle_t LraTaskRxHandle = NULL;
static void LraTaskRxWrapper(void *pvParameters) {
LoRaService *service = static_cast<LoRaService*>(pvParameters);
service->LraTaskRx(pvParameters);
}
void LraTaskRx(void* pvParameters) {
LoRaService* instance = (LoRaService*)pvParameters;
while (true) {
if (!Conectado || !Configurado) {
vTaskDelay(1000);
continue;
}
if (recebendo && (millis() - ultimoByteRecebido > timeoutRecebimentoMs)) {
2025-05-09 20:17:28 +00:00
MostrarLog("Timeout de recebimento. Reiniciando estado.");
2025-04-30 21:49:17 +00:00
reiniciarEstado();
}
while (currentMode == LoRaMode::NORMAL && instance->_serialLoRa->available()) {
uint8_t byteRecebido = instance->_serialLoRa->read();
ultimoByteRecebido = millis(); // <- atualiza o tempo
2025-05-09 20:17:28 +00:00
MostrarLog("byteRecebido=" + String(byteRecebido));
2025-04-30 21:49:17 +00:00
if (!recebendo) {
if (byteRecebido == CodigosFuncoes::BeginMsg) {
reiniciarEstado();
2025-05-09 20:17:28 +00:00
MostrarLog("Iniciou o recebimento dos dados LoRa");
2025-04-30 21:49:17 +00:00
recebendo = true;
}
}
else {
if (bytesEsperados == -1) {
bytesEsperados = byteRecebido;
2025-05-09 20:17:28 +00:00
//MostrarLog("Definindo bytesEsperados = " + String(bytesEsperados));
2025-04-30 21:49:17 +00:00
}
else if (addrRemetente == -1) {
addrRemetente = byteRecebido;
2025-05-09 20:17:28 +00:00
//MostrarLog("Definindo addrRemetente = " + String(addrRemetente));
2025-04-30 21:49:17 +00:00
}
else if (addrDestinatario == -1) {
addrDestinatario = byteRecebido;
2025-05-09 20:17:28 +00:00
//MostrarLog("Definindo addrDestinatario = " + String(addrDestinatario));
2025-04-30 21:49:17 +00:00
if (addrDestinatario != parametrosAtual.address) {
2025-05-09 20:17:28 +00:00
MostrarLog("Mensagem para outro ID, descartando");
2025-04-30 21:49:17 +00:00
reiniciarEstado();
}
}
else {
buffer.push_back(byteRecebido);
bool protocoloCompleto = addrRemetente != -1 && addrDestinatario != -1 && buffer.size() == bytesEsperados + 2; // +2 = checksum + end
2025-05-09 20:17:28 +00:00
MostrarLog("protocoloCompleto = " + String(protocoloCompleto) + ", bufferSize = " + buffer.size() + ", bytesEsperados = " + String(bytesEsperados));
2025-04-30 21:49:17 +00:00
if (protocoloCompleto) {
if (buffer.back() == CodigosFuncoes::EndMsg) {
buffer.pop_back(); // remove 0x55 (EndMsg)
uint8_t checksumRecebido = buffer.back();
buffer.pop_back(); // remove checksum
uint8_t soma = 0;
for (size_t i = 0; i < buffer.size(); ++i) {
soma += buffer[i];
}
if ((soma % 256) == checksumRecebido) {
2025-05-09 20:17:28 +00:00
MostrarLog("Mensagem LoRa recebida de " + String(addrRemetente) + " com checksum válido");
2025-04-30 21:49:17 +00:00
if (buffer.size() >= 2) {
if (xQueueSend(lraQueueRx, &buffer, 0) != pdTRUE) {
2025-05-09 20:17:28 +00:00
MostrarLog("Fila RX cheia! Mensagem descartada.");
2025-04-30 21:49:17 +00:00
}
else {
2025-05-09 20:17:28 +00:00
MostrarLog("Mensagem adicionada na fila RX");
2025-04-30 21:49:17 +00:00
}
}
} else {
2025-05-09 20:17:28 +00:00
MostrarLog("Checksum inválido. Descartando.");
2025-04-30 21:49:17 +00:00
}
}
reiniciarEstado();
}
}
}
}
vTaskDelay(1);
}
}
QueueHandle_t lraQueueTx;
TaskHandle_t LraTaskTxHandle = NULL;
static void LraTaskTxWrapper(void *pvParameters) {
LoRaService *service = static_cast<LoRaService*>(pvParameters);
service->LraTaskTx(pvParameters);
}
void LraTaskTx(void* pvParameters) {
LoRaService *service = static_cast<LoRaService*>(pvParameters);
std::vector<uint8_t> msg;
while (true) {
if (!Conectado || !Configurado) {
vTaskDelay(1000);
continue;
}
if (xQueueReceive(service->lraQueueTx, &msg, portMAX_DELAY) == pdTRUE) {
service->EnviarDadosLoRa(msg);
}
vTaskDelay(1);
}
}
TaskHandle_t LraTaskProcessHandle = NULL;
static void LraTaskProcessWrapper(void *pvParameters) {
LoRaService *service = static_cast<LoRaService*>(pvParameters);
service->LraTaskProcess(pvParameters);
}
void LraTaskProcess(void* pvParameters) {
LoRaService *service = static_cast<LoRaService*>(pvParameters);
std::vector<uint8_t> msg;
while (true) {
if (!Conectado || !Configurado) {
vTaskDelay(1000);
continue;
}
if (xQueueReceive(service->lraQueueRx, &msg, portMAX_DELAY) == pdTRUE) {
service->EnviarDadosCAN(msg);
}
vTaskDelay(1);
}
}
CanService* _canService;
HardwareSerial* _serialLoRa;
uint8_t _pinTXD;
uint8_t _pinRXD;
uint8_t _pinM0;
uint8_t _pinM1;
uint8_t _pinAUX;
int _baudRate = 9600;
LoRaMode currentMode = NORMAL;
LoRaParametrosModel parametrosAtual;
int commandTimeout = 1000;
// Métodos internos
// Define o modo do LoRa
bool setLoRaMode(LoRaMode mode) {
if (mode == currentMode) return true;
// Ajusta os pinos M0 e M1 conforme o modo desejado
switch (mode) {
case NORMAL:
digitalWrite(_pinM0, LOW);
digitalWrite(_pinM1, LOW);
break;
case WAKE_UP:
digitalWrite(_pinM0, HIGH);
digitalWrite(_pinM1, LOW);
break;
case POWER_SAVING:
digitalWrite(_pinM0, LOW);
digitalWrite(_pinM1, HIGH);
break;
case CONFIG:
digitalWrite(_pinM0, HIGH);
digitalWrite(_pinM1, HIGH);
break;
}
2025-05-09 20:17:28 +00:00
MostrarLog("Modo alterado de " + String(currentMode) + " para " + String(mode));
2025-04-30 21:49:17 +00:00
currentMode = mode;
vTaskDelay(100); // Aguarda sinalização inicial de troca
// ESPERA o AUX ir para HIGH, indicando que a troca completou
unsigned long timeout = millis() + commandTimeout;
while (digitalRead(_pinAUX) == LOW) {
if (millis() > timeout) {
2025-05-09 20:17:28 +00:00
MostrarLog("Erro: Timeout aguardando AUX após mudança de modo.");
2025-04-30 21:49:17 +00:00
return false;
}
}
vTaskDelay(100); // Manual pede 2ms após AUX ficar HIGH
return true;
}
// Verifica se o E220 responde
bool checkLoRaConnected() {
2025-05-09 20:17:28 +00:00
MostrarLog("Verificando se o E220 esta conectado...");
2025-04-30 21:49:17 +00:00
if (!setLoRaMode(CONFIG)) {
2025-05-09 20:17:28 +00:00
MostrarLog("Falha ao verificar se o E220 esta conectado, erro ao mudar para CONFIG!");
2025-04-30 21:49:17 +00:00
return false;
}
bool conectado = false;
// Lista de possíveis baud rates (em ordem dos mais prováveis)
const uint32_t baudRates[] = { 9600, 19200, 38400, 57600, 115200, 4800, 2400, 1200 };
const int totalBauds = sizeof(baudRates) / sizeof(baudRates[0]);
int tentativaAtual = -1; // -1 = usar o baudrate já setado primeiro
while (!conectado && tentativaAtual < totalBauds) {
if (tentativaAtual >= 0) {
// Se estamos tentando outra taxa, mudar a serial:
_serialLoRa->end();
_serialLoRa->begin(baudRates[tentativaAtual], SERIAL_8N1, _pinTXD, _pinRXD);
_baudRate = baudRates[tentativaAtual];
2025-05-09 20:17:28 +00:00
MostrarLog("Tentando BaudRate: " + String(_baudRate));
2025-04-30 21:49:17 +00:00
}
// Limpa buffers antes de testar
limparBufferLoRa();
2025-05-09 20:17:28 +00:00
uint8_t command[1] = { CodigosFuncoes::CfgRx };
enviarDadosSerial(command, "Check Conectado");
2025-04-30 21:49:17 +00:00
unsigned long startTime = millis();
while (millis() - startTime < commandTimeout) {
if (_serialLoRa->available()) {
uint8_t dado = _serialLoRa->read();
if (dado == CodigosFuncoes::CfgRx) {
conectado = true;
break;
}
}
vTaskDelay(1);
}
tentativaAtual++;
}
limparBufferLoRa();
setLoRaMode(NORMAL);
if (conectado) {
2025-05-09 20:17:28 +00:00
MostrarLog("E220 conectado com baudRate " + String(_baudRate));
2025-04-30 21:49:17 +00:00
} else {
2025-05-09 20:17:28 +00:00
MostrarLog("Falha ao conectar no E220!");
2025-04-30 21:49:17 +00:00
}
return conectado;
}
// Método que monta o comando de configuração
2025-05-09 20:17:28 +00:00
bool configurarModuloLoRa(byte addr, byte baudAndAir, byte packetAndPower, byte channel, byte tranModeAndworCycle) {
MostrarLog("Configurando modulo...");
2025-04-30 21:49:17 +00:00
if (!setLoRaMode(CONFIG)) {
2025-05-09 20:17:28 +00:00
MostrarLog("Falha ao configurar modulo, erro ao mudar para CONFIG!");
2025-04-30 21:49:17 +00:00
return false;
}
limparBufferLoRa();
uint8_t command[9] = {
CodigosFuncoes::CfgTx, // Código para configurar
0x00, // Registro inicial
0x06, // Quantidade de registros
2025-05-09 20:17:28 +00:00
0x00, // AddrH
addr, // addrL
baudAndAir,
packetAndPower,
2025-04-30 21:49:17 +00:00
channel,
2025-05-09 20:17:28 +00:00
tranModeAndworCycle
2025-04-30 21:49:17 +00:00
};
2025-05-09 20:17:28 +00:00
enviarDadosSerial(command, "Config Modulo");
2025-04-30 21:49:17 +00:00
2025-05-09 20:17:28 +00:00
bool sucesso = receberParametrosModulo(command[1], command[2]);
2025-04-30 21:49:17 +00:00
setLoRaMode(NORMAL);
return sucesso;
}
// Método que requisita a leitura dos parâmetros atuais
bool requisitarParametrosLoRa() {
2025-05-09 20:17:28 +00:00
MostrarLog("Requisitando parametros do modulo...");
2025-04-30 21:49:17 +00:00
if (!setLoRaMode(CONFIG)) {
2025-05-09 20:17:28 +00:00
MostrarLog("Falha ao requisitar parametros do modulo, erro ao mudar para CONFIG!");
2025-04-30 21:49:17 +00:00
return false;
}
limparBufferLoRa();
uint8_t command[3] = { CodigosFuncoes::CfgRx, 0x00, 0x0B };
2025-05-09 20:17:28 +00:00
enviarDadosSerial(command, "Requisitar Parametros");
2025-04-30 21:49:17 +00:00
2025-05-09 20:17:28 +00:00
bool sucesso = receberParametrosModulo(command[1], command[2]);
setLoRaMode(NORMAL);
return sucesso;
}
bool receberParametrosModulo(uint8_t _startAddr, uint8_t _dataLen) {
2025-04-30 21:49:17 +00:00
unsigned long startTime = millis();
bool sucesso = false;
2025-05-09 20:17:28 +00:00
2025-04-30 21:49:17 +00:00
while (!sucesso && millis() - startTime < commandTimeout) {
if (_serialLoRa->available()) {
uint8_t cabecalho = _serialLoRa->read();
if (cabecalho == CodigosFuncoes::CfgRx) { // Cabeçalho de resposta correta
2025-05-09 20:17:28 +00:00
MostrarLog("Cabecalho recebido corretamente.");
uint8_t startAddr = _serialLoRa->read();
uint8_t dataLen = _serialLoRa->read();
2025-04-30 21:49:17 +00:00
2025-05-09 20:17:28 +00:00
if (startAddr == _startAddr && dataLen == _dataLen) {
MostrarLog("Parâmetros recebidos corretamente.");
2025-04-30 21:49:17 +00:00
// Agora ler os registros
uint8_t addh = _serialLoRa->read(); // byte 0
uint8_t addl = _serialLoRa->read(); // byte 1
parametrosAtual.address = addl; // usa só o ADDL (0~255)
parametrosAtual.baudAndAirRate = _serialLoRa->read(); // byte 2
parametrosAtual.packetSizeAndPower = _serialLoRa->read(); // byte 3
parametrosAtual.channel = _serialLoRa->read(); // byte 4
parametrosAtual.tranModeAndWorCycle = _serialLoRa->read(); // byte 5
sucesso = true;
}
else {
2025-05-09 20:17:28 +00:00
MostrarLog("Dados Corrompidos: startAddr=" + String(startAddr) + ", dataLen=" + String(dataLen));
2025-04-30 21:49:17 +00:00
}
} else if (cabecalho == CodigosFuncoes::WrongMode) {
2025-05-09 20:17:28 +00:00
MostrarLog("Modo invalido!");
2025-04-30 21:49:17 +00:00
}
}
vTaskDelay(10);
}
limparBufferLoRa();
return sucesso;
}
2025-05-09 20:17:28 +00:00
void enviarDadosSerial(const uint8_t* dados, const String& descricao = "") {
if (!_serialLoRa) return;
int tamanho = sizeof(dados);
_serialLoRa->write(dados, tamanho);
_serialLoRa->flush();
if (DebugMode) {
String log = "Enviando [" + descricao + "] (" + String(tamanho) + " bytes): ";
for (size_t i = 0; i < tamanho; i++) {
log += "0x" + String(dados[i], HEX) + " ";
}
MostrarLog(log);
}
}
2025-04-30 21:49:17 +00:00
// Limpa buffer anterior
void limparBufferLoRa() {
while (_serialLoRa->available()) {
_serialLoRa->read();
}
}
std::vector<uint8_t> MontarFrameLoRa(uint16_t destino, uint8_t canal, const std::vector<uint8_t>& payloadApp) {
std::vector<uint8_t> frame;
// Cabeçalho fixo LoRa (modo Fixed)
frame.push_back((destino >> 8) & 0xFF); // Addr High (geralmente 0x00)
frame.push_back(destino & 0xFF); // Addr Low
frame.push_back(canal); // Canal
// Estrutura do payload
frame.push_back(CodigosFuncoes::BeginMsg); // 0xAA
frame.push_back(payloadApp.size()); // Tamanho do payload
frame.push_back(parametrosAtual.address); // rementente
frame.push_back(destino); // destinatario
frame.insert(frame.end(), payloadApp.begin(), payloadApp.end());
// Calcula checksum (soma dos dados de payload)
uint8_t soma = 0;
for (uint8_t b : payloadApp) {
soma += b;
}
uint8_t checksum = soma % 256;
frame.push_back(checksum); // Checksum
frame.push_back(CodigosFuncoes::EndMsg); // 0x55
2025-05-09 20:17:28 +00:00
String log = "Frame LoRa montado: ";
2025-04-30 21:49:17 +00:00
for (int i = 0; i < frame.size(); i++) {
2025-05-09 20:17:28 +00:00
log += String(frame[i]) + " ";
2025-04-30 21:49:17 +00:00
}
2025-05-09 20:17:28 +00:00
MostrarLog(log);
2025-04-30 21:49:17 +00:00
return frame;
}
bool EnviarDadosCAN(std::vector<uint8_t> dados) {
_canService->adicionarMensagemFila(dados);
return true;
}
bool EnviarDadosLoRa(std::vector<uint8_t> dados) {
2025-05-09 20:17:28 +00:00
MostrarLog("Enviando dados via LoRa para o endereco " + String(AddressBase) + " no canal " + String(parametrosAtual.channel));
2025-04-30 21:49:17 +00:00
std::vector<uint8_t> dadosLora = MontarFrameLoRa(AddressBase, parametrosAtual.channel, dados);
2025-05-09 20:17:28 +00:00
enviarDadosSerial(dadosLora.data(), "Dados LoRa");
2025-04-30 21:49:17 +00:00
return true;
}
std::map<int, uint8_t> CodigosBaudRates = {
{1200, 0x00},
{2400, 0x20},
{4800, 0x40},
{9600, 0x60},
{19200, 0x80},
{38400, 0xA0},
{57600, 0xC0},
{115200, 0xE0},
};
template<typename K, typename V>
K encontrarChavePorValor(const std::map<K, V>& mapa, V valorProcurado, K valorDefault) {
for (const auto& par : mapa) {
if (par.second == valorProcurado) {
return par.first;
}
}
return valorDefault;
}
};
#endif