kopia lustrzana https://github.com/sh123/esp32_loraprs
Switched over to KISS usage
rodzic
0d19b3cb44
commit
66a0c65c18
21
LICENSE
21
LICENSE
|
@ -1,21 +0,0 @@
|
|||
MIT License
|
||||
|
||||
Copyright (c) 2019 sh123
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
SOFTWARE.
|
|
@ -13,7 +13,7 @@ Can be used in two modes:
|
|||
- Arduino Timer library: https://github.com/contrem/arduino-timer
|
||||
|
||||
# Software Setup
|
||||
- when setting up APRSDroid, use **"TNC (plaintext TNC2)"** connection protocol in Connection Preferences -> Connection Protocol
|
||||
- when setting up APRSDroid, use **"TNC (KISS)"** connection protocol in Connection Preferences -> Connection Protocol
|
||||
- go to esp32_loraprs.ino and make next changes based on your requirements
|
||||
- comment out / remove **LORAPRS_CLIENT** define if you are planning to run server mode for APRS-IS iGate
|
||||
- for server mode fill **LORAPRS_WIFI_SSID** and **LORAPRS_WIFI_KEY** with your WiFI AP data
|
||||
|
|
|
@ -7,7 +7,11 @@
|
|||
|
||||
#define LORAPRS_CLIENT
|
||||
|
||||
#ifdef LORAPRS_CLIENT
|
||||
#define LORAPRS_FREQ 432.499E6
|
||||
#else
|
||||
#define LORAPRS_FREQ 432.5E6
|
||||
#endif
|
||||
|
||||
#ifdef LORAPRS_CLIENT
|
||||
#define LORAPRS_BT_NAME "loraprs_client"
|
||||
|
|
216
loraprs.cpp
216
loraprs.cpp
|
@ -1,12 +1,14 @@
|
|||
#include "loraprs.h"
|
||||
|
||||
LoraPrs::LoraPrs(int loraFreq, String btName, String wifiName,
|
||||
String wifiKey, String aprsLoginCallsign, String aprsPass)
|
||||
LoraPrs::LoraPrs(int loraFreq, const String & btName, const String & wifiName,
|
||||
const String & wifiKey, const String & aprsLoginCallsign, const String & aprsPass)
|
||||
: serialBt_()
|
||||
, loraFreq_(loraFreq)
|
||||
, btName_(btName)
|
||||
, wifiName_(wifiName)
|
||||
, wifiKey_(wifiKey)
|
||||
, kissState_(KissState::Void)
|
||||
, kissCmd_(KissCmd::NoCmd)
|
||||
{
|
||||
aprsLogin_ = "";
|
||||
aprsLogin_ += "user ";
|
||||
|
@ -25,7 +27,7 @@ void LoraPrs::setup()
|
|||
setupBt(btName_);
|
||||
}
|
||||
|
||||
void LoraPrs::setupWifi(String wifiName, String wifiKey)
|
||||
void LoraPrs::setupWifi(const String & wifiName, const String & wifiKey)
|
||||
{
|
||||
if (wifiName.length() != 0) {
|
||||
Serial.print("WIFI connecting to " + wifiName);
|
||||
|
@ -71,11 +73,12 @@ void LoraPrs::setupLora(int loraFreq)
|
|||
LoRa.setSignalBandwidth(CfgBw);
|
||||
LoRa.setCodingRate4(CfgCodingRate);
|
||||
LoRa.setTxPower(CfgPower);
|
||||
LoRa.enableCrc();
|
||||
|
||||
Serial.println("ok");
|
||||
}
|
||||
|
||||
void LoraPrs::setupBt(String btName)
|
||||
void LoraPrs::setupBt(const String & btName)
|
||||
{
|
||||
if (btName.length() != 0) {
|
||||
Serial.print("BT init " + btName + "...");
|
||||
|
@ -98,16 +101,14 @@ void LoraPrs::loop()
|
|||
if (serialBt_.available()) {
|
||||
onBtReceived();
|
||||
}
|
||||
if (LoRa.parsePacket()) {
|
||||
onLoraReceived();
|
||||
if (int packetSize = LoRa.parsePacket()) {
|
||||
onLoraReceived(packetSize);
|
||||
}
|
||||
delay(10);
|
||||
}
|
||||
|
||||
void LoraPrs::onAprsReceived(String aprsMessage)
|
||||
void LoraPrs::onAprsReceived(const String & aprsMessage)
|
||||
{
|
||||
Serial.print(aprsMessage);
|
||||
|
||||
if (WiFi.status() == WL_CONNECTED) {
|
||||
WiFiClient wifiClient;
|
||||
|
||||
|
@ -116,35 +117,196 @@ void LoraPrs::onAprsReceived(String aprsMessage)
|
|||
return;
|
||||
}
|
||||
wifiClient.print(aprsLogin_);
|
||||
Serial.print(aprsMessage);
|
||||
wifiClient.print(aprsMessage);
|
||||
wifiClient.stop();
|
||||
}
|
||||
else {
|
||||
Serial.println("Wifi not connected, not sent");
|
||||
}
|
||||
}
|
||||
|
||||
void LoraPrs::onLoraReceived()
|
||||
String LoraPrs::decodeCall(byte *rxPtr)
|
||||
{
|
||||
String buf;
|
||||
byte callsign[7];
|
||||
char ssid;
|
||||
|
||||
byte *ptr = rxPtr;
|
||||
|
||||
memset(callsign, 0, sizeof(callsign));
|
||||
|
||||
for (int i = 0; i < 6; i++) {
|
||||
char c = *(ptr++) >> 1;
|
||||
callsign[i] = (c == ' ') ? '\0' : c;
|
||||
}
|
||||
callsign[6] = '\0';
|
||||
ssid = (*ptr >> 1);
|
||||
|
||||
String result = String((char*)callsign);
|
||||
if (ssid >= '0' && ssid <= '9') {
|
||||
result += String("-") + String(ssid);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
String LoraPrs::convertAX25ToAprs(byte *rxPayload, int payloadLength, const String & signalReport)
|
||||
{
|
||||
byte *rxPtr = rxPayload;
|
||||
String srcCall, dstCall, rptFirst, rptSecond, result;
|
||||
|
||||
dstCall = decodeCall(rxPtr);
|
||||
rxPtr += 7;
|
||||
|
||||
srcCall = decodeCall(rxPtr);
|
||||
rxPtr += 7;
|
||||
|
||||
if ((rxPayload[13] & 1) == 0) {
|
||||
rptFirst = decodeCall(rxPtr);
|
||||
rxPtr += 7;
|
||||
|
||||
if ((rxPayload[20] & 1) == 0) {
|
||||
rptSecond = decodeCall(rxPtr);
|
||||
rxPtr += 7;
|
||||
}
|
||||
}
|
||||
|
||||
if (*(rxPtr++) != AX25Ctrl::UI) return result;
|
||||
if (*(rxPtr++) != AX25Pid::NoLayer3) return result;
|
||||
|
||||
result += srcCall + String(">") + dstCall;
|
||||
|
||||
if (rptFirst.length() > 0) {
|
||||
result += String(",") + rptFirst;
|
||||
}
|
||||
if (rptSecond.length() > 0) {
|
||||
result += String(",") + rptSecond;
|
||||
}
|
||||
|
||||
result += ":";
|
||||
|
||||
bool appendReport = ((char)*rxPtr == '=');
|
||||
|
||||
while (rxPtr < rxPayload + payloadLength) {
|
||||
result += String((char)*(rxPtr++));
|
||||
}
|
||||
|
||||
if (appendReport) {
|
||||
result += signalReport;
|
||||
}
|
||||
else {
|
||||
result += "\n";
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
void LoraPrs::onLoraReceived(int packetSize)
|
||||
{
|
||||
int rxBufIndex = 0;
|
||||
byte rxBuf[packetSize];
|
||||
|
||||
serialBt_.write(KissMarker::Fend);
|
||||
serialBt_.write(KissCmd::Data);
|
||||
|
||||
while (LoRa.available()) {
|
||||
char c = (char)LoRa.read();
|
||||
if (c != '\n')
|
||||
buf += c;
|
||||
byte rxByte = LoRa.read();
|
||||
|
||||
if (rxByte == KissMarker::Fend) {
|
||||
serialBt_.write(KissMarker::Fesc);
|
||||
serialBt_.write(KissMarker::Tfend);
|
||||
}
|
||||
else if (rxByte == KissMarker::Fesc) {
|
||||
serialBt_.write(KissMarker::Fesc);
|
||||
serialBt_.write(KissMarker::Tfesc);
|
||||
}
|
||||
else {
|
||||
rxBuf[rxBufIndex++] = rxByte;
|
||||
serialBt_.write(rxByte);
|
||||
}
|
||||
}
|
||||
for (int i; i < buf.length(); i++) {
|
||||
serialBt_.write((uint8_t)buf[i]);
|
||||
|
||||
serialBt_.write(KissMarker::Fend);
|
||||
|
||||
String signalReport = String(" ") +
|
||||
String("RSSI: ") +
|
||||
String(LoRa.packetRssi()) +
|
||||
String(", ") +
|
||||
String("SNR: ") +
|
||||
String(LoRa.packetSnr()) +
|
||||
String("dB, ") +
|
||||
String("ERR: ") +
|
||||
String(LoRa.packetFrequencyError()) +
|
||||
String("Hz\n");
|
||||
|
||||
String aprsMsg = convertAX25ToAprs(rxBuf, rxBufIndex, signalReport);
|
||||
|
||||
if (aprsMsg.length() != 0) {
|
||||
onAprsReceived(aprsMsg);
|
||||
}
|
||||
onAprsReceived(buf + " " +
|
||||
"RSSI: " + String(LoRa.packetRssi()) + ", " +
|
||||
"SNR: " + String(LoRa.packetSnr()) + "dB, " +
|
||||
"ERR: " + String(LoRa.packetFrequencyError()) + "Hz\n");
|
||||
|
||||
delay(50);
|
||||
}
|
||||
|
||||
void LoraPrs::onBtReceived()
|
||||
void LoraPrs::kissResetState()
|
||||
{
|
||||
LoRa.beginPacket();
|
||||
while (serialBt_.available()) {
|
||||
char c = (char)serialBt_.read();
|
||||
LoRa.print(c);
|
||||
}
|
||||
LoRa.endPacket();
|
||||
kissCmd_ = KissCmd::NoCmd;
|
||||
kissState_ = KissState::Void;
|
||||
}
|
||||
|
||||
void LoraPrs::onBtReceived()
|
||||
{
|
||||
while (serialBt_.available()) {
|
||||
byte txByte = serialBt_.read();
|
||||
|
||||
switch (kissState_) {
|
||||
case KissState::Void:
|
||||
if (txByte == KissMarker::Fend) {
|
||||
kissCmd_ = KissCmd::NoCmd;
|
||||
kissState_ = KissState::GetCmd;
|
||||
}
|
||||
break;
|
||||
case KissState::GetCmd:
|
||||
if (txByte != KissMarker::Fend) {
|
||||
if (txByte == KissCmd::Data) {
|
||||
LoRa.beginPacket();
|
||||
kissCmd_ = (KissCmd)txByte;
|
||||
kissState_ = KissState::GetData;
|
||||
}
|
||||
else {
|
||||
kissResetState();
|
||||
}
|
||||
}
|
||||
break;
|
||||
case KissState::GetData:
|
||||
if (txByte == KissMarker::Fesc) {
|
||||
kissState_ = KissState::Escape;
|
||||
}
|
||||
else if (txByte == KissMarker::Fend) {
|
||||
if (kissCmd_ == KissCmd::Data) {
|
||||
LoRa.endPacket();
|
||||
}
|
||||
kissResetState();
|
||||
}
|
||||
else {
|
||||
LoRa.write(txByte);
|
||||
}
|
||||
break;
|
||||
case KissState::Escape:
|
||||
if (txByte == KissMarker::Tfend) {
|
||||
LoRa.write(KissMarker::Fend);
|
||||
kissState_ = KissState::GetData;
|
||||
}
|
||||
else if (txByte == KissMarker::Tfesc) {
|
||||
LoRa.write(KissMarker::Fesc);
|
||||
kissState_ = KissState::GetData;
|
||||
}
|
||||
else {
|
||||
kissResetState();
|
||||
}
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
delay(20);
|
||||
}
|
||||
|
|
79
loraprs.h
79
loraprs.h
|
@ -11,6 +11,60 @@
|
|||
class LoraPrs
|
||||
{
|
||||
public:
|
||||
LoraPrs(int loraFreq, const String & btName, const String & wifiName,
|
||||
const String & wifiKey, const String & aprsLoginCallsign, const String & aprsPass);
|
||||
|
||||
void setup();
|
||||
void loop();
|
||||
|
||||
private:
|
||||
void setupWifi(const String & wifiName, const String & wifiKey);
|
||||
void setupLora(int loraFreq);
|
||||
void setupBt(const String & btName);
|
||||
|
||||
void reconnectWifi();
|
||||
|
||||
void onLoraReceived(int packetSize);
|
||||
void onBtReceived();
|
||||
|
||||
void kissResetState();
|
||||
|
||||
void onAprsReceived(const String & aprsMessage);
|
||||
|
||||
bool isAX25CrcValid(byte *rxPayload, int payloadLength);
|
||||
String convertAX25ToAprs(byte *rxPayload, int payloadLength, const String & signalReport);
|
||||
String decodeCall(byte *rxPtr);
|
||||
|
||||
uint16_t updateCrcCcit(uint8_t newByte, uint16_t prevCrc);
|
||||
|
||||
private:
|
||||
enum KissMarker {
|
||||
Fend = 0xc0,
|
||||
Fesc = 0xdb,
|
||||
Tfend = 0xdc,
|
||||
Tfesc = 0xdd
|
||||
};
|
||||
|
||||
enum KissState {
|
||||
Void = 0,
|
||||
GetCmd,
|
||||
GetData,
|
||||
Escape
|
||||
};
|
||||
|
||||
enum KissCmd {
|
||||
Data = 0x00,
|
||||
NoCmd = 0x80
|
||||
};
|
||||
|
||||
enum AX25Ctrl {
|
||||
UI = 0x03
|
||||
};
|
||||
|
||||
enum AX25Pid {
|
||||
NoLayer3 = 0xf0
|
||||
};
|
||||
|
||||
const String CfgLoraprsVersion = "LoRAPRS 0.1";
|
||||
|
||||
const byte CfgPinSs = 5;
|
||||
|
@ -26,32 +80,17 @@ public:
|
|||
const int CfgAprsPort = 14580;
|
||||
const String CfgAprsHost = "rotate.aprs2.net";
|
||||
|
||||
public:
|
||||
LoraPrs(int loraFreq, String btName, String wifiName,
|
||||
String wifiKey, String aprsLoginCallsign, String aprsPass);
|
||||
|
||||
void setup();
|
||||
void loop();
|
||||
|
||||
private:
|
||||
void setupWifi(String wifiName, String wifiKey);
|
||||
void setupLora(int loraFreq);
|
||||
void setupBt(String btName);
|
||||
|
||||
void reconnectWifi();
|
||||
|
||||
void onLoraReceived();
|
||||
void onBtReceived();
|
||||
void onAprsReceived(String aprsMessage);
|
||||
|
||||
private:
|
||||
BluetoothSerial serialBt_;
|
||||
|
||||
int loraFreq_;
|
||||
String btName_;
|
||||
String wifiName_;
|
||||
String wifiKey_;
|
||||
String aprsLogin_;
|
||||
|
||||
KissCmd kissCmd_;
|
||||
KissState kissState_;
|
||||
|
||||
BluetoothSerial serialBt_;
|
||||
};
|
||||
|
||||
#endif // LORAPRS_H
|
||||
|
|
Ładowanie…
Reference in New Issue