esp32_loraprs/loraprs_service.cpp

745 wiersze
18 KiB
C++
Czysty Zwykły widok Historia

2020-06-14 18:55:27 +00:00
#include "loraprs_service.h"
2020-06-14 18:55:27 +00:00
namespace LoraPrs {
byte Service::rxBuf_[256];
#ifdef USE_RADIOLIB
#pragma message("Using RadioLib")
bool Service::interruptEnabled_ = true;
2021-10-25 13:53:52 +00:00
std::shared_ptr<MODULE_NAME> Service::radio_;
#else
#pragma message("Using arduino-LoRa")
#endif
Service::Service()
: Kiss::Processor()
, csmaP_(CfgCsmaPersistence)
, csmaSlotTime_(CfgCsmaSlotTimeMs)
, csmaSlotTimePrev_(0)
, serialBt_()
, serialBLE_()
2021-10-21 12:18:11 +00:00
, kissServer_(new WiFiServer(CfgKissPort))
2021-10-21 18:25:35 +00:00
, isKissConn_(false)
{
#ifdef USE_RADIOLIB
interruptEnabled_ = true;
#endif
}
2020-06-14 18:55:27 +00:00
void Service::setup(const Config &conf)
{
config_ = conf;
previousBeaconMs_ = 0;
disableKiss_ = conf.EnableTextPackets;
LOG_SET_OPTION(false, false, true); // disable file, line, enable func
// disable logging when USB is used for data transfer
if (config_.UsbSerialEnable) {
LOG_SET_LEVEL(DebugLogLevel::LVL_NONE);
}
2021-10-22 18:30:09 +00:00
#ifdef USE_RADIOLIB
LOG_INFO("Built with RadioLib library");
2021-10-22 18:30:09 +00:00
#else
LOG_INFO("Built with arduino-LoRa library");
2021-10-22 18:30:09 +00:00
#endif
2021-10-26 12:07:27 +00:00
LOG_INFO(disableKiss_ ? "Using TNC2 text mode" : "Using TNC KISS and AX.25 mode");
2021-10-26 12:15:02 +00:00
// KISS extensions are disabled in TNC2 mode
if (disableKiss_) {
LOG_INFO("KISS extensions are disabled in TNC2 mode");
config_.KissEnableExtensions = false;
}
// APRS-IS loging callsign validity
ownCallsign_ = AX25::Callsign(config_.AprsLogin);
if (!ownCallsign_.IsValid()) {
LOG_ERROR("Own callsign", config_.AprsLogin, "is not valid");
}
2021-10-26 12:15:02 +00:00
// APRS-IS login command
aprsLoginCommand_ = String("user ") + config_.AprsLogin + String(" pass ") +
config_.AprsPass + String(" vers ") + CfgLoraprsVersion;
if (config_.EnableIsToRf && config_.AprsFilter.length() > 0) {
aprsLoginCommand_ += String(" filter ") + config_.AprsFilter;
}
aprsLoginCommand_ += String("\n");
2021-10-26 12:15:02 +00:00
// peripherals, LoRa
setupLora(config_.LoraFreq, config_.LoraBw, config_.LoraSf,
config_.LoraCodingRate, config_.LoraPower, config_.LoraSync, config_.LoraEnableCrc);
2021-10-26 12:15:02 +00:00
// peripherls, WiFi
if (needsWifi()) {
setupWifi(config_.WifiSsid, config_.WifiKey);
}
2021-10-26 12:15:02 +00:00
// peripherals, Bluetooth/BLE
if (needsBt()) {
setupBt(config_.BtName);
}
2021-10-26 12:15:02 +00:00
// APRS-IS
if (needsAprsis() && config_.EnablePersistentAprsConnection) {
reconnectAprsis();
}
2021-05-26 16:11:33 +00:00
2021-10-26 12:15:02 +00:00
// peripherals, PTT
2021-05-26 16:11:33 +00:00
if (config_.PttEnable) {
LOG_INFO("External PTT is enabled");
2021-05-26 16:11:33 +00:00
pinMode(config_.PttPin, OUTPUT);
}
}
2020-06-14 18:55:27 +00:00
void Service::setupWifi(const String &wifiName, const String &wifiKey)
{
2021-10-21 10:14:14 +00:00
WiFi.setHostname("loraprs");
// AP mode
2021-10-21 12:18:11 +00:00
if (config_.WifiEnableAp) {
LOG_INFO("WIFI is running in AP mode", wifiName);
2021-10-21 17:56:52 +00:00
WiFi.softAP(wifiName.c_str(), wifiKey.c_str());
LOG_INFO("IP address:", WiFi.softAPIP());
// Client/STA mode
2021-10-21 17:56:52 +00:00
} else {
LOG_INFO("WIFI connecting to", wifiName);
2021-10-21 12:18:11 +00:00
WiFi.mode(WIFI_STA);
WiFi.begin(wifiName.c_str(), wifiKey.c_str());
int retryCnt = 0;
while (WiFi.status() != WL_CONNECTED) {
delay(CfgConnRetryMs);
LOG_WARN("WIFI retrying", retryCnt);
2021-10-21 12:18:11 +00:00
if (retryCnt++ >= CfgConnRetryMaxTimes) {
LOG_ERROR("WIFI connect failed");
2021-10-21 12:18:11 +00:00
return;
}
}
LOG_INFO("WIFI connected to", wifiName);
LOG_INFO("IP address:", WiFi.localIP());
2021-10-21 12:18:11 +00:00
}
// Run KISS server if enabled
2021-10-21 12:18:11 +00:00
if (config_.KissEnableTcpIp) {
LOG_INFO("KISS TCP/IP server started on port", CfgKissPort);
2021-10-21 12:18:11 +00:00
kissServer_->begin();
}
2021-10-21 10:14:14 +00:00
}
2021-02-02 09:18:46 +00:00
void Service::reconnectWifi() const
{
2021-10-21 12:38:33 +00:00
// AP mode does not require re-connection
if (config_.WifiEnableAp) return;
LOG_WARN("WIFI re-connecting...");
2019-05-02 16:09:04 +00:00
int retryCnt = 0;
2019-05-02 16:09:04 +00:00
while (WiFi.status() != WL_CONNECTED || WiFi.localIP() == IPAddress(0,0,0,0)) {
WiFi.reconnect();
delay(CfgConnRetryMs);
LOG_WARN("WIFI re-connecting", retryCnt);
2021-10-20 09:58:43 +00:00
if (retryCnt++ >= CfgConnRetryMaxTimes) {
LOG_ERROR("WIFI re-connect failed");
return;
}
2019-05-02 16:09:04 +00:00
}
LOG_INFO("WIFI reconnected, IP address", WiFi.localIP());
2021-10-21 12:18:11 +00:00
if (config_.KissEnableTcpIp) {
LOG_INFO("KISS TCP/IP server started on port", CfgKissPort);
2021-10-21 12:18:11 +00:00
kissServer_->begin();
}
2019-05-02 16:09:04 +00:00
}
2020-06-14 18:55:27 +00:00
bool Service::reconnectAprsis()
{
LOG_INFO("APRSIS connecting to", config_.AprsHost);
if (!aprsisConn_.connect(config_.AprsHost.c_str(), config_.AprsPort)) {
LOG_ERROR("Failed to connect to", config_.AprsHost, ":", config_.AprsPort);
return false;
}
LOG_INFO("APRSIS connected");
aprsisConn_.print(aprsLoginCommand_);
LOG_INFO("APRSIS logged in");
return true;
}
void Service::setupLora(long loraFreq, long bw, int sf, int cr, int pwr, int sync, bool enableCrc)
{
LOG_INFO("Initializing LoRa");
LOG_INFO("Frequency:", loraFreq, "Hz");
LOG_INFO("Bandwidth:", bw, "Hz");
LOG_INFO("Spreading:", sf);
LOG_INFO("Coding rate:", cr);
LOG_INFO("Power:", pwr, "dBm");
LOG_INFO("Sync:", "0x" + String(sync, 16));
LOG_INFO("CRC:", enableCrc ? "enabled" : "disabled");
2021-10-16 06:45:02 +00:00
isImplicitHeaderMode_ = sf == 6;
#ifdef USE_RADIOLIB
2021-10-25 13:53:52 +00:00
radio_ = std::make_shared<MODULE_NAME>(new Module(config_.LoraPinSs, config_.LoraPinDio0, config_.LoraPinRst, RADIOLIB_NC));
int state = radio_->begin((float)loraFreq / 1e6, (float)bw / 1e3, sf, cr, sync, pwr);
if (state != ERR_NONE) {
LOG_ERROR("Radio start error:", state);
}
radio_->setCRC(enableCrc);
//radio_->forceLDRO(false);
//radio_->setRfSwitchPins(4, 5);
radio_->clearDio0Action();
radio_->setDio0Action(onLoraDataAvailableIsr);
2021-10-25 14:39:10 +00:00
state = radio_->startReceive();
if (state != ERR_NONE) {
LOG_ERROR("Receive start error:", state);
}
#else // USE_RADIOLIB
LoRa.setPins(config_.LoraPinSs, config_.LoraPinRst, config_.LoraPinDio0);
2021-10-20 09:58:43 +00:00
int retryCnt = 0;
while (!LoRa.begin(loraFreq)) {
LOG_WARN("LoRa init retry", retryCnt);
delay(CfgConnRetryMs);
2021-10-20 09:58:43 +00:00
if (retryCnt++ >= CfgConnRetryMaxTimes) {
LOG_ERROR("LoRa init failed");
2021-10-20 09:58:43 +00:00
return;
}
}
LoRa.setSyncWord(sync);
LoRa.setSpreadingFactor(sf);
LoRa.setSignalBandwidth(bw);
LoRa.setCodingRate4(cr);
LoRa.setTxPower(pwr);
if (enableCrc) {
LoRa.enableCrc();
}
if (config_.LoraUseIsr) {
LoRa.onReceive(onLoraDataAvailableIsr);
LoRa.receive();
}
#endif // USE_RADIOLIB
LOG_INFO("LoRa initialized");
}
2020-06-14 18:55:27 +00:00
void Service::setupBt(const String &btName)
{
String btType = config_.BtEnableBle ? "BLE" : "BT";
LOG_INFO(btType, "init", btName);
bool btOk = config_.BtEnableBle
? serialBLE_.begin(btName.c_str())
: serialBt_.begin(btName);
if (btOk) {
LOG_INFO(btType, "initialized");
}
else {
LOG_ERROR(btType, "failed");
}
}
2020-06-14 18:55:27 +00:00
void Service::loop()
2021-10-21 17:27:49 +00:00
{
if (needsWifi() && WiFi.status() != WL_CONNECTED) {
reconnectWifi();
}
if (needsAprsis() && !aprsisConn_.connected() && config_.EnablePersistentAprsConnection) {
reconnectAprsis();
}
2021-10-21 18:25:35 +00:00
if (config_.KissEnableTcpIp) {
attachKissNetworkClient();
}
// RX path, Rig -> Serial
bool isRigToSerialProcessed = false;
#ifdef USE_RADIOLIB
isRigToSerialProcessed = processRigToSerial();
#else
if (config_.LoraUseIsr) {
isRigToSerialProcessed = processRigToSerial();
} else {
if (int packetSize = LoRa.parsePacket()) {
loraReceive(packetSize);
isRigToSerialProcessed = true;
}
}
#endif
// TX path, Serial -> Rig
if (!isRigToSerialProcessed) {
2021-02-03 08:54:17 +00:00
long currentTime = millis();
2021-10-20 17:53:50 +00:00
if (!isLoraRxBusy() && currentTime > csmaSlotTimePrev_ + csmaSlotTime_ && random(0, 255) < csmaP_) {
if (aprsisConn_.available() > 0) {
2020-12-08 13:26:14 +00:00
onAprsisDataAvailable();
}
2021-02-12 15:30:41 +00:00
if (needsBeacon()) {
2020-12-08 13:26:14 +00:00
sendPeriodicBeacon();
2021-02-12 15:30:41 +00:00
}
bool allTxProcessed = processSerialToRig();
if (allTxProcessed) {
#ifdef USE_RADIOLIB
int state = radio_->startReceive();
if (state != ERR_NONE) {
LOG_ERROR("Start receive error: ", state);
}
#else
if (config_.LoraUseIsr) {
LoRa.receive();
}
#endif
2020-12-08 13:26:14 +00:00
}
2021-02-03 08:54:17 +00:00
csmaSlotTimePrev_ = currentTime;
2020-06-20 09:50:57 +00:00
}
}
2020-06-19 07:39:49 +00:00
delay(CfgPollDelayMs);
}
2021-10-20 17:53:50 +00:00
bool Service::isLoraRxBusy() {
#ifdef USE_RADIOLIB
2021-10-22 18:30:09 +00:00
return config_.LoraUseCad && (radio_->getModemStatus() & 0x01); // SX1278_STATUS_SIG_DETECT
2021-10-20 17:53:50 +00:00
#else
return false;
#endif
}
#ifdef USE_RADIOLIB
ICACHE_RAM_ATTR void Service::onLoraDataAvailableIsr() {
if (interruptEnabled_) {
int packetSize = radio_->getPacketLength();
if (packetSize > 0) {
int state = radio_->readData(rxBuf_, packetSize);
if (state == ERR_NONE) {
queueRigToSerialIsr(Cmd::Data, rxBuf_, packetSize);
} else {
LOG_ERROR("Read data error: ", state);
}
state = radio_->startReceive();
if (state != ERR_NONE) {
LOG_ERROR("Start receive error: ", state);
}
}
}
}
#else // USE_RADIOLIB
ICACHE_RAM_ATTR void Service::onLoraDataAvailableIsr(int packetSize)
{
int rxBufIndex = 0;
for (int i = 0; i < packetSize; i++) {
rxBuf_[rxBufIndex++] = LoRa.read();
}
queueRigToSerialIsr(Cmd::Data, rxBuf_, rxBufIndex);
}
#endif // USE_RADIOLIB
2020-06-19 07:39:49 +00:00
void Service::sendPeriodicBeacon()
{
long currentMs = millis();
if (previousBeaconMs_ == 0 || currentMs - previousBeaconMs_ >= config_.AprsRawBeaconPeriodMinutes * 60 * 1000) {
AX25::Payload payload(config_.AprsRawBeacon);
if (payload.IsValid()) {
sendAX25ToLora(payload);
if (config_.EnableRfToIs) {
2020-06-17 10:32:00 +00:00
sendToAprsis(payload.ToString());
}
LOG_INFO("Periodic beacon is sent");
}
else {
LOG_ERROR("Beacon payload is invalid");
}
previousBeaconMs_ = currentMs;
}
}
2020-06-17 10:32:00 +00:00
void Service::sendToAprsis(const String &aprsMessage)
{
if (needsWifi() && WiFi.status() != WL_CONNECTED) {
reconnectWifi();
2019-05-09 16:13:08 +00:00
}
if (needsAprsis() && !aprsisConn_.connected()) {
reconnectAprsis();
2019-05-09 16:13:08 +00:00
}
2020-06-17 10:32:00 +00:00
aprsisConn_.println(aprsMessage);
2019-05-09 16:13:08 +00:00
if (!config_.EnablePersistentAprsConnection) {
aprsisConn_.stop();
2019-05-09 16:13:08 +00:00
}
}
2020-06-14 18:55:27 +00:00
void Service::onAprsisDataAvailable()
{
String aprsisData;
while (aprsisConn_.available() > 0) {
char c = aprsisConn_.read();
if (c == '\r') continue;
if (c == '\n') break;
aprsisData += c;
if (aprsisData.length() >= CfgMaxAprsInMessageSize) {
LOG_WARN("APRS-IS incoming message is too long, skipping tail");
break;
}
}
LOG_INFO(aprsisData);
if (config_.EnableIsToRf && aprsisData.length() > 0) {
AX25::Payload payload(aprsisData);
if (payload.IsValid()) {
sendAX25ToLora(payload);
}
else {
LOG_WARN("Unknown payload from APRSIS, ignoring");
}
}
}
void Service::sendSignalReportEvent(int rssi, float snr)
{
struct SignalReport signalReport;
signalReport.rssi = htobe16(rssi);
signalReport.snr = htobe16(snr * 100);
2021-02-12 14:43:18 +00:00
sendRigToSerial(Cmd::SignalReport, (const byte *)&signalReport, sizeof(SignalReport));
}
bool Service::sendAX25ToLora(const AX25::Payload &payload)
{
int bytesWritten;
2021-02-02 09:21:13 +00:00
byte buf[CfgMaxAX25PayloadSize];
if (config_.EnableTextPackets) {
String textPayload = payload.ToString();
bytesWritten = textPayload.length();
if (bytesWritten > CfgMaxAX25PayloadSize) {
bytesWritten = CfgMaxAX25PayloadSize;
}
textPayload.getBytes(buf, bytesWritten);
buf[bytesWritten-1] = '\0';
} else {
bytesWritten = payload.ToBinary(buf, sizeof(buf));
if (bytesWritten <= 0) {
LOG_WARN("Failed to serialize payload");
return false;
}
}
2021-02-12 14:43:18 +00:00
queueSerialToRig(Cmd::Data, buf, bytesWritten);
return true;
}
void Service::onRigPacket(void *packet, int packetLength)
2021-10-26 12:34:08 +00:00
{
if (config_.EnableAutoFreqCorrection) {
performFrequencyCorrection();
}
if (config_.KissEnableExtensions) {
#ifdef USE_RADIOLIB
sendSignalReportEvent(radio_->getRSSI(), radio_->getSNR());
#else
sendSignalReportEvent(LoRa.packetRssi(), LoRa.packetSnr());
#endif
}
if (!config_.IsClientMode) {
processIncomingRawPacketAsServer((const byte*)packet, packetLength);
}
}
void Service::performFrequencyCorrection() {
#ifdef USE_RADIOLIB
long frequencyErrorHz = radio_->getFrequencyError();
#else
long frequencyErrorHz = LoRa.packetFrequencyError();
#endif
2021-10-26 12:34:08 +00:00
if (abs(frequencyErrorHz) > config_.AutoFreqCorrectionDeltaHz) {
config_.LoraFreq -= frequencyErrorHz;
LOG_INFO("Correcting frequency:", frequencyErrorHz);
#ifdef USE_RADIOLIB
radio_->setFrequency((float)config_.LoraFreq / 1e6);
int state = radio_->startReceive();
if (state != ERR_NONE) {
LOG_ERROR("Start receive error:", state);
}
#else
LoRa.setFrequency(config_.LoraFreq);
if (config_.LoraUseIsr) {
LoRa.idle();
LoRa.receive();
}
#endif
2020-06-05 13:19:36 +00:00
}
2021-02-02 09:18:46 +00:00
}
2019-05-09 16:13:08 +00:00
#ifndef USE_RADIOLIB
void Service::loraReceive(int packetSize)
{
int rxBufIndex = 0;
byte rxBuf[packetSize];
while (LoRa.available()) {
rxBuf[rxBufIndex++] = LoRa.read();
}
2021-02-12 14:43:18 +00:00
sendRigToSerial(Cmd::Data, rxBuf, rxBufIndex);
onRigPacket(rxBuf, rxBufIndex);
}
#endif
void Service::processIncomingRawPacketAsServer(const byte *packet, int packetLength) {
2021-02-02 09:18:46 +00:00
// create from binary AX25
2021-02-02 09:18:46 +00:00
AX25::Payload payload(packet, packetLength);
// try to parse as text for clients, who submit plain text
2021-10-26 13:18:49 +00:00
if (!payload.IsValid() && config_.EnableTextPackets) {
char buf[CfgMaxAX25PayloadSize];
int cpySize = packetLength > CfgMaxAX25PayloadSize ? CfgMaxAX25PayloadSize : packetLength;
memcpy(buf, packet, cpySize);
buf[cpySize-1] = '\0';
payload = AX25::Payload(String((char*)buf));
}
2021-02-02 09:18:46 +00:00
if (payload.IsValid()) {
#ifdef USE_RADIOLIB
float snr = radio_->getSNR();
int rssi = radio_->getRSSI();
long frequencyError = radio_->getFrequencyError();
#else
float snr = LoRa.packetSnr();
int rssi = LoRa.packetRssi();
long frequencyError = LoRa.packetFrequencyError();
#endif
String signalReport = String(" ") +
String("rssi: ") +
String(snr < 0 ? rssi + snr : rssi) +
String("dBm, ") +
String("snr: ") +
String(snr) +
String("dB, ") +
String("err: ") +
String(frequencyError) +
String("Hz");
2021-02-02 09:18:46 +00:00
String textPayload = payload.ToString(config_.EnableSignalReport ? signalReport : String());
LOG_INFO(textPayload);
2021-02-02 09:18:46 +00:00
if (config_.EnableRfToIs) {
sendToAprsis(textPayload);
LOG_INFO("Packet sent to APRS-IS");
}
2021-02-02 09:18:46 +00:00
if (config_.EnableRepeater && payload.Digirepeat(ownCallsign_)) {
sendAX25ToLora(payload);
LOG_INFO("Packet digirepeated");
}
2021-02-02 09:18:46 +00:00
} else {
LOG_WARN("Skipping non-AX25 payload");
}
}
bool Service::onRigTxBegin()
{
2021-05-26 16:11:33 +00:00
if (config_.PttEnable) {
digitalWrite(config_.PttPin, HIGH);
delay(config_.PttTxDelayMs);
} else {
delay(CfgPollDelayMs);
}
#ifdef USE_RADIOLIB
return true;
#else
2021-10-16 06:45:02 +00:00
return (LoRa.beginPacket(isImplicitHeaderMode_) == 1);
#endif
}
2021-02-02 15:57:36 +00:00
void Service::onRigTx(byte b)
{
#ifdef USE_RADIOLIB
txQueue_.push(b);
#else
2021-02-02 15:57:36 +00:00
LoRa.write(b);
#endif
2019-05-09 16:13:08 +00:00
}
void Service::onRigTxEnd()
{
#ifdef USE_RADIOLIB
int txPacketSize = txQueue_.size();
byte txBuf[txPacketSize];
for (int i = 0; i < txPacketSize; i++) {
txBuf[i] = txQueue_.shift();
}
interruptEnabled_ = false;
int state = radio_->transmit(txBuf, txPacketSize);
if (state != ERR_NONE) {
LOG_ERROR("TX error: ", state);
}
interruptEnabled_ = true;
#endif
2021-05-26 16:11:33 +00:00
if (config_.PttEnable) {
#ifndef USE_RADIOLIB
2021-05-26 16:11:33 +00:00
LoRa.endPacket(false);
#endif
2021-05-26 16:11:33 +00:00
delay(config_.PttTxTailMs);
digitalWrite(config_.PttPin, LOW);
} else {
#ifndef USE_RADIOLIB
2021-05-26 16:11:33 +00:00
LoRa.endPacket(true);
#endif
2021-05-26 16:11:33 +00:00
}
}
2021-10-21 18:25:35 +00:00
void Service::attachKissNetworkClient()
2021-10-21 12:18:11 +00:00
{
2021-10-21 18:25:35 +00:00
// connected, client dropped off
if (isKissConn_) {
if (!kissConn_.connected()) {
LOG_INFO("KISS TCP/IP client disconnected");
2021-10-21 18:25:35 +00:00
isKissConn_ = false;
kissConn_.stop();
}
}
WiFiClient wifiClient = kissServer_->available();
// new client connected
if (wifiClient && wifiClient.connected()) {
// drop off current one
if (isKissConn_) {
kissConn_.stop();
2021-10-21 12:18:11 +00:00
}
LOG_INFO("New KISS TCP/IP client connected");
kissConn_ = wifiClient;
isKissConn_ = true;
2021-10-21 12:18:11 +00:00
}
}
2021-02-02 15:57:36 +00:00
void Service::onSerialTx(byte b)
{
if (config_.UsbSerialEnable) {
Serial.write(b);
}
else if (isKissConn_) {
2021-10-21 18:25:35 +00:00
kissConn_.write(b);
2021-10-21 12:18:11 +00:00
}
else if (config_.BtEnableBle) {
serialBLE_.write(b);
}
else {
serialBt_.write(b);
}
}
bool Service::onSerialRxHasData()
{
if (config_.UsbSerialEnable) {
return Serial.available();
}
else if (isKissConn_) {
2021-10-21 18:25:35 +00:00
return kissConn_.available();
2021-10-21 12:18:11 +00:00
}
else if (config_.BtEnableBle) {
return serialBLE_.available();
}
else {
return serialBt_.available();
}
}
2021-02-02 15:57:36 +00:00
bool Service::onSerialRx(byte *b)
{
2021-10-21 12:18:11 +00:00
int rxResult;
if (config_.UsbSerialEnable) {
rxResult = Serial.read();
}
else if (isKissConn_) {
2021-10-21 18:25:35 +00:00
rxResult = kissConn_.read();
// client dropped off
if (rxResult == -1) {
kissConn_.stop();
isKissConn_ = false;
}
2021-10-21 12:18:11 +00:00
}
else {
rxResult = config_.BtEnableBle
? serialBLE_.read()
: serialBt_.read();
}
2021-06-08 14:36:02 +00:00
if (rxResult == -1) {
return false;
}
2021-06-08 14:36:02 +00:00
*b = (byte)rxResult;
return true;
}
void Service::onControlCommand(Cmd cmd, byte value)
{
switch (cmd) {
case Cmd::P:
LOG_INFO("CSMA P:", value);
csmaP_ = value;
break;
case Cmd::SlotTime:
LOG_INFO("CSMA SlotTime:", value);
csmaSlotTime_ = (long)value * 10;
break;
2021-05-26 16:11:33 +00:00
case Cmd::TxDelay:
LOG_INFO("TX delay:", value);
2021-05-26 16:11:33 +00:00
config_.PttTxDelayMs = (long)value * 10;
break;
case Cmd::TxTail:
LOG_INFO("TX tail:", value);
2021-05-26 16:11:33 +00:00
config_.PttTxTailMs = (long)value * 10;
break;
default:
break;
}
}
void Service::onRadioControlCommand(const std::vector<byte> &rawCommand) {
if (config_.KissEnableExtensions && rawCommand.size() == sizeof(SetHardware)) {
const struct SetHardware * setHardware = reinterpret_cast<const struct SetHardware*>(rawCommand.data());
config_.LoraFreq = be32toh(setHardware->freq);
config_.LoraBw = be32toh(setHardware->bw);
config_.LoraSf = be16toh(setHardware->sf);
config_.LoraCodingRate = be16toh(setHardware->cr);
config_.LoraPower = be16toh(setHardware->pwr);
config_.LoraSync = be16toh(setHardware->sync);
config_.LoraEnableCrc = setHardware->crc;
setupLora(config_.LoraFreq, config_.LoraBw, config_.LoraSf,
config_.LoraCodingRate, config_.LoraPower, config_.LoraSync, config_.LoraEnableCrc);
} else {
LOG_ERROR("Radio control command of wrong size");
}
}
2021-10-20 09:58:43 +00:00
void Service::onRebootCommand()
{
LOG_INFO("Reboot requested");
2021-10-20 09:58:43 +00:00
ESP.restart();
}
2020-06-14 18:55:27 +00:00
} // LoraPrs