Browse Source

0.4.3 Finaly all done

master
US1GHQ 1 month ago
parent
commit
beb69a8646
  1. 1
      include/taskTNC.h
  2. 20
      include/version.h
  3. 4
      lib/KISS_TO_TNC2/KISS.h
  4. 120
      lib/KISS_TO_TNC2/KISS_TO_PKT.cpp
  5. 12
      lib/KISS_TO_TNC2/KISS_TO_PKT.h
  6. 50
      lib/KISS_TO_TNC2/KISS_TO_TNC2.cpp
  7. 7
      src/TTGO_T-Beam_LoRa_APRS.ino
  8. 43
      src/taskTNC.cpp
  9. 2
      tools/buildscript_versioning.py

1
include/taskTNC.h

@ -1,5 +1,6 @@
#include <Arduino.h>
#include <KISS_TO_TNC2.h>
#include <KISS_TO_PKT.h>
#if defined(ENABLE_BLUETOOTH)
#include "BluetoothSerial.h"

20
include/version.h

@ -1,10 +1,10 @@
#ifndef BUILD_NUMBER
#define BUILD_NUMBER "201"
#endif
#ifndef VERSION
#define VERSION "v0.4.2.201- - 2021-09-15 23:28:59.739585"
#endif
#ifndef VERSION_SHORT
#define VERSION_SHORT "v0.4.2.201-"
#endif
#ifndef BUILD_NUMBER
#define BUILD_NUMBER "24"
#endif
#ifndef VERSION
#define VERSION "v0.4.3.24- - 2021-09-16 11:30:47.660702"
#endif
#ifndef VERSION_SHORT
#define VERSION_SHORT "v0.4.3.24-"
#endif

4
lib/KISS_TO_TNC2/KISS.h

@ -24,7 +24,3 @@
#define ERROR_INITRADIO 0x01
#define ERROR_TXFAILED 0x02
#define ERROR_QUEUE_FULL 0x04
//Data control frames, ported from Direwolf
#define T_PKT 0x82
#define R_PKT 0x03

120
lib/KISS_TO_TNC2/KISS_TO_PKT.cpp

@ -0,0 +1,120 @@
#include "KISS_TO_PKT.h"
bool validateTNC2Frame_pkt(const String &tnc2FormattedFrame);
bool validateKISSFrame_pkt(const String &kissFormattedFrame);
String decapsulateKISS_pkt(const String &frame);
/*
* https://ham.zmailer.org/oh2mqk/aprx/PROTOCOLS
After successfull login, communication carries "TNC2" format
APRS messages. Namely text encoding of AX.25 UI frames in
what became known as "TNC2 monitor style":
SOURCE>DESTIN:payload
SOURCE>DESTIN,VIA,VIA:payload
The SOURCE, DESTIN, and VIA fields are AX.25 address fields,
and have "-SSID" value annexed if the SSID is not zero.
Also in VIA-fields, if the "HAS BEEN DIGIPEATED" bit is set
(AX.25 v2 protocol feature) a star ('*') character is appended.
VIA-fields are separated by comma (',') from DESTIN, and each
other.
A double-colon (':') separates address data from payload.
The payload is passed _AS_IS_ without altering any message
content bytes, however ending at first CR or LF character
encountered in the packet.
*/
String encode_kiss_pkt(const String &tnc2FormattedFrame, bool &pktFrame)
{
String TNC2Frame = "";
if (!pktFrame) {
String ax25Frame = encapsulateKISS_pkt(tnc2FormattedFrame, CMD_DATA);
TNC2Frame += ax25Frame;
}
return TNC2Frame;
}
String encapsulateKISS_pkt(const String &ax25Frame, uint8_t TNCCmd)
{
String kissFrame = "";
kissFrame += (char) FEND; // start of frame
kissFrame += (char) (0x0f & TNCCmd); // TNC0, cmd
for (int i = 0; i < ax25Frame.length() ; ++i)
{
char currentChar = ax25Frame.charAt(i);
if (currentChar == (char) FEND)
{
kissFrame += (char) FESC;
kissFrame += (char) TFEND;
}
else if (currentChar == (char) FESC)
{
kissFrame += (char) FESC;
kissFrame += (char) TFESC;
}
else
{
kissFrame += currentChar;
}
}
kissFrame += (char) FEND; // end of frame
return kissFrame;
}
String decapsulateKISS_pkt(const String &frame, uint8_t TNCCmd)
{
String ax25Frame = "";
for (int i = 2; i < frame.length() - 1; ++i)
{
char currentChar = frame.charAt(i);
if (currentChar == (char)FESC)
{
char nextChar = frame.charAt(i + 1);
if (nextChar == (char)TFEND)
{
ax25Frame += (char)FEND;
}
else if (nextChar == (char)TFESC)
{
ax25Frame += (char)FESC;
}
++i;
}
else
{
ax25Frame += currentChar;
}
}
return ax25Frame;
}
String decode_kiss_pkt(const String &inputKISSTNCFrame, bool &dataFrame, bool &pktFrame) {
String TNC2Frame = "";
if (validateKISSFrame_pkt(inputKISSTNCFrame)) {
dataFrame = inputKISSTNCFrame.charAt(1) == CMD_DATA;
String ax25Frame = decapsulateKISS_pkt(inputKISSTNCFrame, CMD_DATA);
//END
if (dataFrame && !pktFrame){
String ax25Frame = decapsulateKISS_pkt(inputKISSTNCFrame, CMD_DATA);
delay(250);
TNC2Frame += ax25Frame;
}
}
return TNC2Frame;
}
bool validateTNC2Frame_pkt(const String &tnc2FormattedFrame) {
return (tnc2FormattedFrame.indexOf(':') != -1) &&
(tnc2FormattedFrame.indexOf('>') != -1);
}
bool validateKISSFrame_pkt(const String &kissFormattedFrame) {
return kissFormattedFrame.charAt(0) == (char) FEND &&
kissFormattedFrame.charAt(kissFormattedFrame.length() - 1) == (char) FEND;
}

12
lib/KISS_TO_TNC2/KISS_TO_PKT.h

@ -0,0 +1,12 @@
#include <Arduino.h>
#include "KISS.h"
//Data control frames, ported from Direwolf
#define T_PKT 0xaa
#define R_PKT 0xa6
//END
//PACKET MODE
String encode_kiss_pkt(const String& tnc2FormattedFrame, bool &pktFrame);
String decode_kiss_pkt(const String &inputKISSTNCFrame, bool &dataFrame, bool &pktFrame);
String encapsulateKISS_pkt(const String &ax25Frame, uint8_t TNCCmd);

50
lib/KISS_TO_TNC2/KISS_TO_TNC2.cpp

@ -35,7 +35,6 @@ String decapsulateKISS(const String &frame);
*/
String encode_kiss(const String &tnc2FormattedFrame, bool &pktFrame) {
String TNC2Frame = "";
String ax25Frame = "";
if (validateTNC2Frame(tnc2FormattedFrame)) {
@ -69,16 +68,10 @@ String encode_kiss(const String &tnc2FormattedFrame, bool &pktFrame) {
ax25Frame += (char) APRS_INFORMATION_FIELD;
ax25Frame += tnc2FormattedFrame.substring(tnc2FormattedFrame.indexOf(':') + 1);
}
String kissFrame = encapsulateKISS(ax25Frame, CMD_DATA);
return kissFrame;
}
else
{
String ax25Frame = encapsulateKISS(tnc2FormattedFrame, CMD_DATA);
TNC2Frame += ax25Frame;
return TNC2Frame;
}
}
}
String kissFrame = encapsulateKISS(ax25Frame, CMD_DATA);
return kissFrame;
}
String encapsulateKISS(const String &ax25Frame, uint8_t TNCCmd) {
String kissFrame = "";
@ -130,25 +123,20 @@ String decapsulateKISS(const String &frame) {
String decode_kiss(const String &inputKISSTNCFrame, bool &dataFrame, bool &pktFrame) {
String TNC2Frame = "";
if (validateKISSFrame(inputKISSTNCFrame)) {
dataFrame = inputKISSTNCFrame.charAt(1) == CMD_DATA;
String ax25Frame = decapsulateKISS(inputKISSTNCFrame);
String dest_1 = decode_path_ax25(ax25Frame.substring(14, 56));
for (int p = 0; p <= dest_1.indexOf("WIDE"); p++) { pktFrame = true;}
String dest_2 = decode_path_ax25(ax25Frame.substring(14, 56));
for (int p = 0; p <= dest_2.indexOf("ECHO"); p++) { pktFrame = true;}
String dest_3 = decode_path_ax25(ax25Frame.substring(14, 56));
for (int p = 0; p <= dest_3.indexOf("TRACE"); p++) { pktFrame = true;}
String dest_4 = decode_path_ax25(ax25Frame.substring(14, 56));
for (int p = 0; p <= dest_4.indexOf("RELAY"); p++) { pktFrame = true;}
String dest_5 = decode_path_ax25(ax25Frame.substring(0, 7));
for (int p = 0; p <= dest_5.indexOf("APRS"); p++) { pktFrame = true;}
if (dataFrame && !pktFrame) {
String ax25Frame = decapsulateKISS(inputKISSTNCFrame);
delay(250);
TNC2Frame += ax25Frame;
}
else if (dataFrame && pktFrame){
if (validateKISSFrame(inputKISSTNCFrame)) {
dataFrame = inputKISSTNCFrame.charAt(1) == CMD_DATA;
String ax25Frame = decapsulateKISS(inputKISSTNCFrame);
String dest_1 = decode_path_ax25(ax25Frame.substring(14, 56));
for (int p = 0; p <= dest_1.indexOf("WIDE"); p++) { pktFrame = true;}
String dest_2 = decode_path_ax25(ax25Frame.substring(14, 56));
for (int p = 0; p <= dest_2.indexOf("ECHO"); p++) { pktFrame = true;}
String dest_3 = decode_path_ax25(ax25Frame.substring(14, 56));
for (int p = 0; p <= dest_3.indexOf("TRACE"); p++) { pktFrame = true;}
String dest_4 = decode_path_ax25(ax25Frame.substring(14, 56));
for (int p = 0; p <= dest_4.indexOf("RELAY"); p++) { pktFrame = true;}
String dest_5 = decode_path_ax25(ax25Frame.substring(0, 7));
for (int p = 0; p <= dest_5.indexOf("APRS"); p++) { pktFrame = true;}
if (dataFrame && pktFrame){
String ax25Frame = decapsulateKISS(inputKISSTNCFrame);
bool isLast = false;
String dst_addr = decode_address_ax25(ax25Frame.substring(0, 7), isLast, false);
@ -253,4 +241,4 @@ bool validateTNC2Frame(const String &tnc2FormattedFrame) {
bool validateKISSFrame(const String &kissFormattedFrame) {
return kissFormattedFrame.charAt(0) == (char) FEND &&
kissFormattedFrame.charAt(kissFormattedFrame.length() - 1) == (char) FEND;
}
}

7
src/TTGO_T-Beam_LoRa_APRS.ino

@ -301,10 +301,9 @@ void prepareAPRSFrame(){
outString += Tcall;
if (relay_path){
outString += ">APLO01:!";
outString += ">APLS01," + relay_path + ":!";
}else{
outString += ">APLO01," + relay_path + ":!";
outString += ">APLS01:!";
}
if(gps_state && gps.location.isValid()){
@ -607,7 +606,7 @@ void sendTelemetryFrame() {
String telemetryEquations = String(":") + Tcall + ":EQNS.0,5.1,3000,0,10,0,0,10,0,0,28,3000,0,10,0";
String telemetryData = String("T#MIC") + String(b_volt) + ","+ String(b_in_c) + ","+ String(b_out_c) + ","+ String(ac_volt) + ","+ String(ac_c) + ",00000000";
String telemetryBase = "";
telemetryBase += Tcall + ">APLO01" + ":";
telemetryBase += Tcall + ">APLS01" + ":";
sendToTNC(telemetryBase + telemetryParamsNames);
sendToTNC(telemetryBase + telemetryUnitNames);
sendToTNC(telemetryBase + telemetryEquations);

43
src/taskTNC.cpp

@ -33,28 +33,35 @@ void handleKISSData(char character, int bufferIndex) {
return;
}
inTNCData->concat(character);
if (character == (char) FEND && inTNCData->length() > 3) {
if (character == (char) FEND && inTNCData->length() > 3)
{
bool isDataFrame = false;
bool isPacketFrame = false;
const String &TNC2DataFrame = decode_kiss(*inTNCData, isDataFrame, isPacketFrame);
if (isDataFrame && isPacketFrame) {
auto *buffer = new String();
buffer->concat(TNC2DataFrame);
if (xQueueSend(tncToSendQueue, &buffer, (1000 / portTICK_PERIOD_MS)) != pdPASS) {
if (xQueueSend(tncToSendQueue, &buffer, (1000 / portTICK_PERIOD_MS)) != pdPASS)
{
delete buffer;
}
}
else if (isDataFrame && !isPacketFrame)
{
inTNCData->clear();
}
else if (character == (char) FEND && inTNCData->length() > 3)
{
const String &TNC2DataFrame = decode_kiss_pkt(*inTNCData, isDataFrame, isPacketFrame);
if (isDataFrame && !isPacketFrame) {
auto *buffer = new String();
buffer->concat(TNC2DataFrame);
if (xQueueSend(tncToSendQueue, &buffer, (1000 / portTICK_PERIOD_MS)) != pdPASS) {
if (xQueueSend(tncToSendQueue, &buffer, (1000 / portTICK_PERIOD_MS)) != pdPASS)
{
delete buffer;
}
}
inTNCData->clear();
}
}
if (inTNCData->length() > 255){
// just in case of garbage input reset data
inTNCData->clear();
@ -93,8 +100,10 @@ void handleKISSData(char character, int bufferIndex) {
if (xQueueReceive(tncReceivedQueue, &loraReceivedFrameString, (1 / portTICK_PERIOD_MS)) == pdPASS) {
bool isPacketFrame = false;
const String &kissEncoded_pkt = encode_kiss_pkt(*loraReceivedFrameString, isPacketFrame);
const String &kissEncoded = encode_kiss(*loraReceivedFrameString, isPacketFrame);
// Serial.print(kissEncoded);
if (isPacketFrame) {
Serial.print(kissEncoded);
#ifdef ENABLE_BLUETOOTH
if (SerialBT.hasClient()){
SerialBT.print(kissEncoded);
@ -108,6 +117,24 @@ void handleKISSData(char character, int bufferIndex) {
}
}, &kissEncoded, clients, MAX_WIFI_CLIENTS);
#endif
}
else
{
Serial.print(kissEncoded_pkt);
#ifdef ENABLE_BLUETOOTH
if (SerialBT.hasClient()){
SerialBT.print(kissEncoded_pkt);
}
#endif
#ifdef ENABLE_WIFI
iterateWifiClients([](WiFiClient *client, int clientIdx, const String *data){
if (client->connected()){
client->print(*data);
client->flush();
}
}, &kissEncoded_pkt, clients, MAX_WIFI_CLIENTS);
#endif
}
delete loraReceivedFrameString;
}
vTaskDelay(50 / portTICK_PERIOD_MS);

2
tools/buildscript_versioning.py

@ -1,6 +1,6 @@
FILENAME_BUILDNO = '.pio/versioning'
FILENAME_VERSION_H = 'include/version.h'
version = 'v0.4.2.'
version = 'v0.4.3.'
import datetime
from subprocess import *

Loading…
Cancel
Save