0.4.3 Finaly all done
parent
e5a30a0687
commit
beb69a8646
|
@ -1,5 +1,6 @@
|
|||
#include <Arduino.h>
|
||||
#include <KISS_TO_TNC2.h>
|
||||
#include <KISS_TO_PKT.h>
|
||||
|
||||
#if defined(ENABLE_BLUETOOTH)
|
||||
#include "BluetoothSerial.h"
|
||||
|
|
|
@ -1,10 +1,10 @@
|
|||
|
||||
#ifndef BUILD_NUMBER
|
||||
#define BUILD_NUMBER "201"
|
||||
#define BUILD_NUMBER "24"
|
||||
#endif
|
||||
#ifndef VERSION
|
||||
#define VERSION "v0.4.2.201- - 2021-09-15 23:28:59.739585"
|
||||
#define VERSION "v0.4.3.24- - 2021-09-16 11:30:47.660702"
|
||||
#endif
|
||||
#ifndef VERSION_SHORT
|
||||
#define VERSION_SHORT "v0.4.2.201-"
|
||||
#define VERSION_SHORT "v0.4.3.24-"
|
||||
#endif
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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;
|
||||
}
|
|
@ -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);
|
|
@ -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,15 +68,9 @@ 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 encapsulateKISS(const String &ax25Frame, uint8_t TNCCmd) {
|
||||
|
@ -130,7 +123,7 @@ String decapsulateKISS(const String &frame) {
|
|||
String decode_kiss(const String &inputKISSTNCFrame, bool &dataFrame, bool &pktFrame) {
|
||||
String TNC2Frame = "";
|
||||
|
||||
if (validateKISSFrame(inputKISSTNCFrame)) {
|
||||
if (validateKISSFrame(inputKISSTNCFrame)) {
|
||||
dataFrame = inputKISSTNCFrame.charAt(1) == CMD_DATA;
|
||||
String ax25Frame = decapsulateKISS(inputKISSTNCFrame);
|
||||
String dest_1 = decode_path_ax25(ax25Frame.substring(14, 56));
|
||||
|
@ -143,12 +136,7 @@ if (validateKISSFrame(inputKISSTNCFrame)) {
|
|||
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 (dataFrame && pktFrame){
|
||||
String ax25Frame = decapsulateKISS(inputKISSTNCFrame);
|
||||
bool isLast = false;
|
||||
String dst_addr = decode_address_ax25(ax25Frame.substring(0, 7), isLast, false);
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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);
|
||||
|
||||
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;
|
||||
}
|
||||
inTNCData->clear();
|
||||
}
|
||||
else if (isDataFrame && !isPacketFrame)
|
||||
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);
|
||||
|
|
|
@ -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…
Reference in New Issue