ax25 iOS works fine
This commit is contained in:
parent
2ca097e0f7
commit
e2c4d06a77
|
|
@ -186,21 +186,16 @@ void loop() {
|
|||
MSG_Utils::processOutputBuffer();
|
||||
MSG_Utils::clean25SegBuffer();
|
||||
|
||||
if (Config.bluetooth.type == 0 || Config.bluetooth.type == 2) { // always is sended to Phone
|
||||
BLE_Utils::sendToPhone(packet.text.substring(3)); // does not check for 25seg buffer
|
||||
} else {
|
||||
#ifdef HAS_BT_CLASSIC
|
||||
BLUETOOTH_Utils::sendPacket(packet.text.substring(3));
|
||||
#endif
|
||||
}
|
||||
|
||||
if (Config.bluetooth.type == 0 || Config.bluetooth.type == 2) {
|
||||
BLE_Utils::sendToPhone(packet.text.substring(3));
|
||||
BLE_Utils::sendToLoRa();
|
||||
} else {
|
||||
#ifdef HAS_BT_CLASSIC
|
||||
BLUETOOTH_Utils::sendPacket(packet.text.substring(3));
|
||||
BLUETOOTH_Utils::sendToLoRa();
|
||||
#endif
|
||||
}
|
||||
|
||||
MSG_Utils::ledNotification();
|
||||
Utils::checkFlashlight();
|
||||
STATION_Utils::checkListenedTrackersByTimeAndDelete();
|
||||
|
|
|
|||
|
|
@ -4,75 +4,46 @@
|
|||
|
||||
namespace AX25_Utils {
|
||||
|
||||
AX25Frame decodedFrame;
|
||||
String decodeAddressAX25(const String& ax25Address, bool& isLastAddress, bool isRelay) {
|
||||
String address = "";
|
||||
for (int i = 0; i < 6; ++i) {
|
||||
uint8_t currentCharacter = ax25Address.charAt(i);
|
||||
currentCharacter >>= 1;
|
||||
if (currentCharacter != ' ') address += (char)currentCharacter;
|
||||
}
|
||||
auto ssidChar = (uint8_t)ax25Address.charAt(6);
|
||||
bool hasBeenDigipited = ssidChar & HAS_BEEN_DIGIPITED_MASK;
|
||||
isLastAddress = ssidChar & IS_LAST_ADDRESS_POSITION_MASK;
|
||||
ssidChar >>= 1;
|
||||
|
||||
String decodeFrame(const String& frame) {
|
||||
String packet = "";
|
||||
for (int a = 0; a < 6; a ++) {
|
||||
uint16_t shiftedValue = frame[a] >> 1;
|
||||
if (shiftedValue == 32) {
|
||||
a = 10;
|
||||
int ssid = 0b1111 & ssidChar;
|
||||
if (ssid) {
|
||||
address += '-';
|
||||
address += ssid;
|
||||
}
|
||||
if (isRelay && hasBeenDigipited) address += '*';
|
||||
return address;
|
||||
}
|
||||
|
||||
String decapsulateKISS(const String& frame) {
|
||||
String ax25Frame = "";
|
||||
for (int i = 2; i < frame.length() - 1; ++i) {
|
||||
char currentChar = frame.charAt(i);
|
||||
if (currentChar == (char)KissChar::FESC) {
|
||||
char nextChar = frame.charAt(i + 1);
|
||||
if (nextChar == (char)KissChar::TFEND) {
|
||||
ax25Frame += (char)KissChar::FEND;
|
||||
} else if (nextChar == (char)KissChar::TFESC) {
|
||||
ax25Frame += (char)KissChar::FESC;
|
||||
}
|
||||
i++;
|
||||
} else {
|
||||
//Serial.print(char(shiftedValue));
|
||||
packet += char(shiftedValue);
|
||||
ax25Frame += currentChar;
|
||||
}
|
||||
}
|
||||
byte ssid = (frame[6]>>1) & 0x0f;
|
||||
if (String(ssid) != "0") {
|
||||
packet += "-";
|
||||
packet += String(ssid);
|
||||
}
|
||||
return packet;
|
||||
return ax25Frame;
|
||||
}
|
||||
|
||||
bool decodeAX25(const String& frame, int frameSize, AX25Frame* decodedFrame) {
|
||||
if ((frameSize < 14) || (frame[0] != KissChar::FEND && frame[1] != KissCmd::Data && frame[frameSize - 1] != KissChar::FEND)) {
|
||||
return false;
|
||||
}
|
||||
int payloadFrameStart = 0;
|
||||
for (int i = 0; i < frameSize; i++) { // where is CONTROL y PID ?
|
||||
if (frame[i] == 0x03 && frame[i+1] == 0xf0) {
|
||||
payloadFrameStart = i+1;
|
||||
}
|
||||
}
|
||||
decodedFrame->tocall = frame.substring(2, 9); // Extract destination address
|
||||
decodedFrame->sender = frame.substring(9, 16); // Extract source address
|
||||
if (payloadFrameStart >= 21) { // is there path1?
|
||||
decodedFrame->path1 = frame.substring(16, 23);
|
||||
}
|
||||
if (payloadFrameStart >= 28) { // is there path2?
|
||||
decodedFrame->path2 = frame.substring(23, 30);
|
||||
}
|
||||
decodedFrame->control = frame.substring(payloadFrameStart-1, payloadFrameStart); // Extract control information // 0x03
|
||||
decodedFrame->pid = frame.substring(payloadFrameStart, payloadFrameStart + 1); // Extract pid information // 0xF0
|
||||
decodedFrame->payload = frame.substring(payloadFrameStart + 1, frameSize - 1); // Extract payload
|
||||
return true;
|
||||
}
|
||||
|
||||
String AX25FrameToLoRaPacket(const String& frame) {
|
||||
//Serial.println(frame);
|
||||
if (decodeAX25(frame, frame.length(), &decodedFrame)) {
|
||||
//String packetToLoRa = "";
|
||||
String packetToLoRa = decodeFrame(decodedFrame.sender) + ">" + decodeFrame(decodedFrame.tocall);
|
||||
|
||||
if (decodedFrame.path1[0] != 0) {
|
||||
packetToLoRa += ",";
|
||||
packetToLoRa += decodeFrame(decodedFrame.path1);
|
||||
}
|
||||
if (decodedFrame.path2[0] != 0) {
|
||||
packetToLoRa += ",";
|
||||
packetToLoRa += decodeFrame(decodedFrame.path2);
|
||||
}
|
||||
packetToLoRa += ":";
|
||||
packetToLoRa += decodedFrame.payload;
|
||||
return packetToLoRa;
|
||||
} else {
|
||||
return "";
|
||||
}
|
||||
}
|
||||
|
||||
//**************************************
|
||||
|
||||
String encapsulateKISS(const String& ax25Frame, uint8_t command) {
|
||||
String kissFrame = "";
|
||||
kissFrame += (char)KissChar::FEND;
|
||||
|
|
@ -119,6 +90,33 @@ namespace AX25_Utils {
|
|||
return kissAddress;
|
||||
}
|
||||
|
||||
String decodeKISS(const String& inputFrame, bool& dataFrame) {
|
||||
String frame = "";
|
||||
if (KISS_Utils::validateKISSFrame(inputFrame)) {
|
||||
dataFrame = inputFrame.charAt(1) == KissCmd::Data;
|
||||
if (dataFrame) {
|
||||
String ax25Frame = decapsulateKISS(inputFrame);
|
||||
bool isLastAddress = false;
|
||||
String dstAddr = decodeAddressAX25(ax25Frame.substring(0, 7), isLastAddress, false);
|
||||
String srcAddr = decodeAddressAX25(ax25Frame.substring(7, 14), isLastAddress, false);
|
||||
|
||||
frame = srcAddr + ">" + dstAddr;
|
||||
|
||||
int digiInfoIndex = 14;
|
||||
while (!isLastAddress && digiInfoIndex + 7 < ax25Frame.length()) {
|
||||
String digiAddr = decodeAddressAX25(ax25Frame.substring(digiInfoIndex, digiInfoIndex + 7), isLastAddress, true);
|
||||
frame += ',' + digiAddr;
|
||||
digiInfoIndex += 7;
|
||||
}
|
||||
frame += ':';
|
||||
frame += ax25Frame.substring(digiInfoIndex + 2);
|
||||
} else {
|
||||
frame += inputFrame;
|
||||
}
|
||||
}
|
||||
return frame;
|
||||
}
|
||||
|
||||
String encodeKISS(const String& frame) {
|
||||
String ax25Frame = "";
|
||||
|
||||
|
|
|
|||
|
|
@ -3,23 +3,12 @@
|
|||
|
||||
#include <Arduino.h>
|
||||
|
||||
struct AX25Frame { // Define AX.25 frame structure
|
||||
String tocall; // destination
|
||||
String sender; // source
|
||||
String path1; // if present
|
||||
String path2; // if present
|
||||
String control;
|
||||
String pid;
|
||||
String payload;
|
||||
};
|
||||
|
||||
namespace AX25_Utils {
|
||||
|
||||
String decodeFrame(const String& frame);
|
||||
bool decodeAX25(const String& frame, int frameSize, AX25Frame* decodedFrame);
|
||||
String AX25FrameToLoRaPacket(const String& frame);
|
||||
String encodeKISS(const String& frame);
|
||||
String decodeKISS(const String& inputFrame, bool& dataFrame);
|
||||
|
||||
String encodeKISS(const String& frame);
|
||||
}
|
||||
|
||||
#endif
|
||||
|
|
@ -2,6 +2,7 @@
|
|||
#include "configuration.h"
|
||||
#include "ax25_utils.h"
|
||||
#include "lora_utils.h"
|
||||
#include "kiss_utils.h"
|
||||
#include "ble_utils.h"
|
||||
#include "display.h"
|
||||
#include "logger.h"
|
||||
|
|
@ -30,6 +31,8 @@ extern bool sendBleToLoRa;
|
|||
extern bool bluetoothConnected;
|
||||
extern String BLEToLoRaPacket;
|
||||
|
||||
String kissSerialBuffer = "";
|
||||
|
||||
|
||||
class MyServerCallbacks : public NimBLEServerCallbacks {
|
||||
void onConnect(NimBLEServer* pServer) {
|
||||
|
|
@ -46,21 +49,36 @@ class MyServerCallbacks : public NimBLEServerCallbacks {
|
|||
}
|
||||
};
|
||||
|
||||
|
||||
class MyCallbacks : public NimBLECharacteristicCallbacks {
|
||||
void onWrite(NimBLECharacteristic *pCharacteristic) {
|
||||
std::string receivedData = pCharacteristic->getValue();
|
||||
String receivedString = "";
|
||||
for (int i = 0; i < receivedData.length(); i++) {
|
||||
//Serial.print(receivedData[i],HEX); // delete
|
||||
//Serial.print(" ");
|
||||
receivedString += receivedData[i];
|
||||
}
|
||||
if (Config.bluetooth.type == 0) {
|
||||
BLEToLoRaPacket = AX25_Utils::AX25FrameToLoRaPacket(receivedString);
|
||||
} else if (Config.bluetooth.type == 2) {
|
||||
if (Config.bluetooth.type == 0) { // AX25 KISS
|
||||
std::string receivedData = pCharacteristic->getValue();
|
||||
delay(100);
|
||||
for (int i = 0; i < receivedData.length(); i++) {
|
||||
char character = receivedData[i];
|
||||
|
||||
if (kissSerialBuffer.length() == 0 && character != (char)KissChar::FEND) continue;
|
||||
kissSerialBuffer += receivedData[i];
|
||||
|
||||
if (character == (char)KissChar::FEND && kissSerialBuffer.length() > 3) {
|
||||
bool isDataFrame = false;
|
||||
|
||||
BLEToLoRaPacket = AX25_Utils::decodeKISS(kissSerialBuffer, isDataFrame);
|
||||
|
||||
if (isDataFrame) {
|
||||
sendBleToLoRa = true;
|
||||
kissSerialBuffer = "";
|
||||
}
|
||||
}
|
||||
}
|
||||
} else if (Config.bluetooth.type == 2) { // TNC2
|
||||
std::string receivedData = pCharacteristic->getValue();
|
||||
String receivedString = "";
|
||||
for (int i = 0; i < receivedData.length(); i++) receivedString += receivedData[i];
|
||||
BLEToLoRaPacket = receivedString;
|
||||
sendBleToLoRa = true;
|
||||
}
|
||||
sendBleToLoRa = true;
|
||||
}
|
||||
};
|
||||
|
||||
|
|
@ -112,9 +130,7 @@ namespace BLE_Utils {
|
|||
}
|
||||
|
||||
void sendToLoRa() {
|
||||
if (!sendBleToLoRa) {
|
||||
return;
|
||||
}
|
||||
if (!sendBleToLoRa) return;
|
||||
logger.log(logging::LoggerLevel::LOGGER_LEVEL_DEBUG, "BLE Tx", "%s", BLEToLoRaPacket.c_str());
|
||||
displayShow("BLE Tx >>", "", BLEToLoRaPacket, 1000);
|
||||
LoRa_Utils::sendNewPacket(BLEToLoRaPacket);
|
||||
|
|
|
|||
|
|
@ -9,4 +9,8 @@ namespace KISS_Utils {
|
|||
return (colonPos != -1) && (greaterThanPos != -1) && (colonPos > greaterThanPos);
|
||||
}
|
||||
|
||||
bool validateKISSFrame(const String& kissFormattedFrame) {
|
||||
return kissFormattedFrame.charAt(0) == (char)KissChar::FEND && kissFormattedFrame.charAt(kissFormattedFrame.length() - 1) == (char)KissChar::FEND;
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -27,6 +27,7 @@ enum AX25Char {
|
|||
namespace KISS_Utils {
|
||||
|
||||
bool validateTNC2Frame(const String& tnc2FormattedFrame);
|
||||
bool validateKISSFrame(const String& kissFormattedFrame);
|
||||
|
||||
}
|
||||
|
||||
|
|
|
|||
Loading…
Reference in New Issue