Switched over to KISS usage

pull/5/head
sh123 2019-05-09 19:13:08 +03:00
rodzic 0d19b3cb44
commit 66a0c65c18
5 zmienionych plików z 253 dodań i 69 usunięć

21
LICENSE
Wyświetl plik

@ -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.

Wyświetl plik

@ -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

Wyświetl plik

@ -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"

Wyświetl plik

@ -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);
}

Wyświetl plik

@ -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