Merge last changes from dev
parent
84a2a4b2f8
commit
e48dd29820
|
@ -227,12 +227,17 @@
|
||||||
</div>
|
</div>
|
||||||
<article>
|
<article>
|
||||||
<div class="grid-container quarters">
|
<div class="grid-container quarters">
|
||||||
<form action="/reboot" method="post">
|
<form action="/shutdown" method="post" onsubmit="return confirmAction('shutdown');">
|
||||||
|
<div>
|
||||||
|
<input class="button-primary" type="submit" value="Shutdown">
|
||||||
|
</div>
|
||||||
|
</form>
|
||||||
|
<form action="/reboot" method="post" onsubmit="return confirmAction('reboot');">
|
||||||
<div>
|
<div>
|
||||||
<input class="button-primary" type="submit" value="Reboot">
|
<input class="button-primary" type="submit" value="Reboot">
|
||||||
</div>
|
</div>
|
||||||
</form>
|
</form>
|
||||||
<form action="/restore" method="post">
|
<form action="/restore" method="post" onsubmit="return confirmAction('do factory reset');">
|
||||||
<div>
|
<div>
|
||||||
<input class="button-primary" type="submit" value="Factory reset">
|
<input class="button-primary" type="submit" value="Factory reset">
|
||||||
</div>
|
</div>
|
||||||
|
|
|
@ -113,4 +113,8 @@ function updateFileUpload(event) {
|
||||||
xhr.open('POST', '/update');
|
xhr.open('POST', '/update');
|
||||||
|
|
||||||
xhr.send(data);
|
xhr.send(data);
|
||||||
|
}
|
||||||
|
|
||||||
|
function confirmAction(actionName) {
|
||||||
|
return window.confirm('Are you shure want to ' + actionName);
|
||||||
}
|
}
|
|
@ -2,4 +2,5 @@
|
||||||
#include <TinyGPS++.h>
|
#include <TinyGPS++.h>
|
||||||
|
|
||||||
extern TinyGPSPlus gps;
|
extern TinyGPSPlus gps;
|
||||||
void taskGPS(void *parameter);
|
|
||||||
|
[[noreturn]] void taskGPS(void *parameter);
|
||||||
|
|
|
@ -1,5 +1,6 @@
|
||||||
#include <Arduino.h>
|
#include <Arduino.h>
|
||||||
#include <KISS_TO_TNC2.h>
|
#include <KISS_TO_TNC2.h>
|
||||||
|
#include <KISS_TO_PKT.h>
|
||||||
|
|
||||||
#if defined(ENABLE_BLUETOOTH)
|
#if defined(ENABLE_BLUETOOTH)
|
||||||
#include "BluetoothSerial.h"
|
#include "BluetoothSerial.h"
|
||||||
|
@ -7,6 +8,7 @@
|
||||||
#endif
|
#endif
|
||||||
#if defined(ENABLE_WIFI)
|
#if defined(ENABLE_WIFI)
|
||||||
#include "taskWebServer.h"
|
#include "taskWebServer.h"
|
||||||
|
#include "wifi_clients.h"
|
||||||
#endif
|
#endif
|
||||||
extern QueueHandle_t tncToSendQueue;
|
extern QueueHandle_t tncToSendQueue;
|
||||||
extern QueueHandle_t tncReceivedQueue;
|
extern QueueHandle_t tncReceivedQueue;
|
||||||
|
|
|
@ -12,6 +12,7 @@ extern BG_RF95 rf95;
|
||||||
#ifdef KISS_PROTOCOL
|
#ifdef KISS_PROTOCOL
|
||||||
extern WiFiServer tncServer;
|
extern WiFiServer tncServer;
|
||||||
#endif
|
#endif
|
||||||
|
extern WiFiServer gpsServer;
|
||||||
typedef struct {
|
typedef struct {
|
||||||
String callsign;
|
String callsign;
|
||||||
} tWebServerCfg;
|
} tWebServerCfg;
|
||||||
|
|
|
@ -0,0 +1,13 @@
|
||||||
|
//
|
||||||
|
// Created by Admin on 11.06.2021.
|
||||||
|
//
|
||||||
|
|
||||||
|
#ifndef TTGO_T_BEAM_LORA_APRS_WIFI_CLIENTS_H
|
||||||
|
#define TTGO_T_BEAM_LORA_APRS_WIFI_CLIENTS_H
|
||||||
|
#include <WiFiClient.h>
|
||||||
|
#include <WiFiServer.h>
|
||||||
|
|
||||||
|
typedef void (*f_connectedClientCallback_t) (WiFiClient *, int, const String *);
|
||||||
|
void iterateWifiClients(f_connectedClientCallback_t callback, const String *data, WiFiClient * wifiClients[], int maxWifiClients);
|
||||||
|
void check_for_new_clients(WiFiServer *wiFiServer, WiFiClient * wifiClients[], int maxWifiClients);
|
||||||
|
#endif //TTGO_T_BEAM_LORA_APRS_WIFI_CLIENTS_H
|
|
@ -116,7 +116,7 @@ bool BG_RF95::init()
|
||||||
// An innocuous ISM frequency, same as RF22's
|
// An innocuous ISM frequency, same as RF22's
|
||||||
setFrequency(433.800);
|
setFrequency(433.800);
|
||||||
// Lowish power
|
// Lowish power
|
||||||
setTxPower(20);
|
setTxPower(23);
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
@ -392,7 +392,7 @@ void BG_RF95::setTxPower(int8_t power, bool useRFO)
|
||||||
// for the transmitter output
|
// for the transmitter output
|
||||||
if (useRFO)
|
if (useRFO)
|
||||||
{
|
{
|
||||||
if (power > 14) power = 14;
|
if (power > 19) power = 19;
|
||||||
if (power < -1) power = -1;
|
if (power < -1) power = -1;
|
||||||
spiWrite(BG_RF95_REG_09_PA_CONFIG, BG_RF95_MAX_POWER | (power + 1));
|
spiWrite(BG_RF95_REG_09_PA_CONFIG, BG_RF95_MAX_POWER | (power + 1));
|
||||||
} else {
|
} else {
|
||||||
|
@ -407,7 +407,7 @@ void BG_RF95::setTxPower(int8_t power, bool useRFO)
|
||||||
spiWrite(BG_RF95_REG_0B_OCP, ( BG_RF95_OCP_ON | BG_RF95_OCP_TRIM ) ); // Trim max current tp 240mA
|
spiWrite(BG_RF95_REG_0B_OCP, ( BG_RF95_OCP_ON | BG_RF95_OCP_TRIM ) ); // Trim max current tp 240mA
|
||||||
spiWrite(BG_RF95_REG_4D_PA_DAC, BG_RF95_PA_DAC_ENABLE);
|
spiWrite(BG_RF95_REG_4D_PA_DAC, BG_RF95_PA_DAC_ENABLE);
|
||||||
//power -= 3;
|
//power -= 3;
|
||||||
power = 20; // and set PA_DAC_ENABLE
|
power = 23; // and set PA_DAC_ENABLE
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
spiWrite(BG_RF95_REG_4D_PA_DAC, BG_RF95_PA_DAC_DISABLE);
|
spiWrite(BG_RF95_REG_4D_PA_DAC, BG_RF95_PA_DAC_DISABLE);
|
||||||
|
|
|
@ -0,0 +1,124 @@
|
||||||
|
#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 = "";
|
||||||
|
// Serial.print(tnc2FormattedFrame);
|
||||||
|
pktFrame = tnc2FormattedFrame.charAt(1) == R_PKT;
|
||||||
|
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;
|
||||||
|
// Auto switch to packet mode if find cmd data.
|
||||||
|
if (inputKISSTNCFrame.charAt(2) == T_PKT) { pktFrame = true;}
|
||||||
|
else { pktFrame = false; }
|
||||||
|
//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);
|
|
@ -7,7 +7,7 @@ String decode_address_ax25(const String &ax25Address, bool &isLast, bool isRelay
|
||||||
|
|
||||||
bool validateKISSFrame(const String &kissFormattedFrame);
|
bool validateKISSFrame(const String &kissFormattedFrame);
|
||||||
|
|
||||||
String decapsulateKISS(const String& frame);
|
String decapsulateKISS(const String &frame);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* https://ham.zmailer.org/oh2mqk/aprx/PROTOCOLS
|
* https://ham.zmailer.org/oh2mqk/aprx/PROTOCOLS
|
||||||
|
@ -33,100 +33,111 @@ String decapsulateKISS(const String& frame);
|
||||||
|
|
||||||
*/
|
*/
|
||||||
|
|
||||||
String encode_kiss(const String& tnc2FormattedFrame) {
|
String encode_kiss(const String &tnc2FormattedFrame) {
|
||||||
String ax25Frame = "";
|
String ax25Frame = "";
|
||||||
|
|
||||||
if (validateTNC2Frame(tnc2FormattedFrame)){
|
if (validateTNC2Frame(tnc2FormattedFrame)) {
|
||||||
String address = "";
|
String address = "";
|
||||||
bool dst_addres_written = false;
|
bool dst_addres_written = false;
|
||||||
for (int p=0;p<=tnc2FormattedFrame.indexOf(':');p++){
|
for (int p = 0; p <= tnc2FormattedFrame.indexOf(':'); p++) {
|
||||||
char currentChar = tnc2FormattedFrame.charAt(p);
|
char currentChar = tnc2FormattedFrame.charAt(p);
|
||||||
if (currentChar == ':' || currentChar == '>' || currentChar == ','){
|
if (currentChar == ':' || currentChar == '>' || currentChar == ',') {
|
||||||
if (!dst_addres_written && (currentChar == ',' || currentChar == ':')){
|
if (!dst_addres_written && (currentChar == ',' || currentChar == ':')) {
|
||||||
// ax25 frame DST SRC
|
// ax25 frame DST SRC
|
||||||
// tnc2 frame SRC DST
|
// tnc2 frame SRC DST
|
||||||
ax25Frame = encode_address_ax25(address) + ax25Frame;
|
ax25Frame = encode_address_ax25(address) + ax25Frame;
|
||||||
dst_addres_written = true;
|
dst_addres_written = true;
|
||||||
} else {
|
} else {
|
||||||
ax25Frame += encode_address_ax25(address);
|
ax25Frame += encode_address_ax25(address);
|
||||||
}
|
|
||||||
address = "";
|
|
||||||
} else {
|
|
||||||
address += currentChar;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
auto lastAddressChar = (uint8_t)ax25Frame.charAt(ax25Frame.length() - 1);
|
address = "";
|
||||||
ax25Frame.setCharAt(ax25Frame.length() - 1, (char)(lastAddressChar | IS_LAST_ADDRESS_POSITION_MASK));
|
} else {
|
||||||
ax25Frame += (char)APRS_CONTROL_FIELD;
|
address += currentChar;
|
||||||
ax25Frame += (char)APRS_INFORMATION_FIELD;
|
}
|
||||||
ax25Frame += tnc2FormattedFrame.substring(tnc2FormattedFrame.indexOf(':')+1);
|
|
||||||
}
|
}
|
||||||
|
auto lastAddressChar = (uint8_t) ax25Frame.charAt(ax25Frame.length() - 1);
|
||||||
|
ax25Frame.setCharAt(ax25Frame.length() - 1, (char) (lastAddressChar | IS_LAST_ADDRESS_POSITION_MASK));
|
||||||
|
ax25Frame += (char) APRS_CONTROL_FIELD;
|
||||||
|
ax25Frame += (char) APRS_INFORMATION_FIELD;
|
||||||
|
ax25Frame += tnc2FormattedFrame.substring(tnc2FormattedFrame.indexOf(':') + 1);
|
||||||
|
}
|
||||||
|
|
||||||
String kissFrame = encapsulateKISS(ax25Frame, CMD_DATA);
|
String kissFrame = encapsulateKISS(ax25Frame, CMD_DATA);
|
||||||
return kissFrame;
|
return kissFrame;
|
||||||
}
|
}
|
||||||
|
|
||||||
String encapsulateKISS(const String &ax25Frame, uint8_t TNCCmd) {
|
String encapsulateKISS(const String &ax25Frame, uint8_t TNCCmd) {
|
||||||
String kissFrame = "";
|
String kissFrame = "";
|
||||||
kissFrame += (char)FEND; // start of frame
|
kissFrame += (char) FEND; // start of frame
|
||||||
kissFrame += (char)(0x0f & TNCCmd); // TNC0, cmd
|
kissFrame += (char) (0x0f & TNCCmd); // TNC0, cmd
|
||||||
for (int i = 0; i < ax25Frame.length(); ++i) {
|
for (int i = 0; i < ax25Frame.length(); ++i) {
|
||||||
char currentChar = ax25Frame.charAt(i);
|
char currentChar = ax25Frame.charAt(i);
|
||||||
if (currentChar == (char)FEND){
|
if (currentChar == (char) FEND) {
|
||||||
kissFrame += (char)FESC;
|
kissFrame += (char) FESC;
|
||||||
kissFrame += (char)TFEND;
|
kissFrame += (char) TFEND;
|
||||||
} else if (currentChar == (char)FESC){
|
} else if (currentChar == (char) FESC) {
|
||||||
kissFrame += (char)FESC;
|
kissFrame += (char) FESC;
|
||||||
kissFrame += (char)TFESC;
|
kissFrame += (char) TFESC;
|
||||||
} else {
|
} else {
|
||||||
kissFrame += currentChar;
|
kissFrame += currentChar;
|
||||||
}
|
|
||||||
}
|
}
|
||||||
kissFrame += (char)FEND; // end of frame
|
}
|
||||||
return kissFrame;
|
kissFrame += (char) FEND; // end of frame
|
||||||
|
return kissFrame;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
String decapsulateKISS(const String& frame) {
|
String decapsulateKISS(const String &frame) {
|
||||||
String ax25Frame = "";
|
String ax25Frame = "";
|
||||||
for (int i = 2; i < frame.length() - 1; ++i) {
|
for (int i = 2; i < frame.length() - 1; ++i) {
|
||||||
char currentChar = frame.charAt(i);
|
char currentChar = frame.charAt(i);
|
||||||
if (currentChar == (char)FESC){
|
if (currentChar == (char) FESC) {
|
||||||
char nextChar = frame.charAt(i+1);
|
char nextChar = frame.charAt(i + 1);
|
||||||
if (nextChar == (char)TFEND){
|
if (nextChar == (char) TFEND) {
|
||||||
ax25Frame += (char)FEND;
|
ax25Frame += (char) FEND;
|
||||||
} else if (nextChar == (char)TFESC){
|
} else if (nextChar == (char) TFESC) {
|
||||||
ax25Frame += (char)FESC;
|
ax25Frame += (char) FESC;
|
||||||
}
|
}
|
||||||
i++;
|
i++;
|
||||||
} else {
|
} else {
|
||||||
ax25Frame += currentChar;
|
ax25Frame += currentChar;
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
return ax25Frame;
|
return ax25Frame;
|
||||||
}
|
}
|
||||||
|
|
||||||
String decode_kiss(const String& kissFormattedFrame) {
|
/**
|
||||||
String TNC2Frame = "";
|
*
|
||||||
|
* @param inputKISSTNCFrame
|
||||||
|
* @param dataFrame
|
||||||
|
* @return Decapsulated TNC2KISS APRS data frame, or raw command data frame
|
||||||
|
*/
|
||||||
|
String decode_kiss(const String &inputKISSTNCFrame, bool &dataFrame) {
|
||||||
|
String TNC2Frame = "";
|
||||||
|
|
||||||
if (validateKISSFrame(kissFormattedFrame)){
|
if (validateKISSFrame(inputKISSTNCFrame)) {
|
||||||
String ax25Frame = decapsulateKISS(kissFormattedFrame);
|
dataFrame = inputKISSTNCFrame.charAt(1) == CMD_DATA;
|
||||||
bool isLast = false;
|
if (dataFrame){
|
||||||
String dst_addr = decode_address_ax25(ax25Frame.substring(0, 7), isLast, false);
|
String ax25Frame = decapsulateKISS(inputKISSTNCFrame);
|
||||||
String src_addr = decode_address_ax25(ax25Frame.substring(7, 14), isLast, false);
|
bool isLast = false;
|
||||||
TNC2Frame = src_addr + ">" + dst_addr;
|
String dst_addr = decode_address_ax25(ax25Frame.substring(0, 7), isLast, false);
|
||||||
int digi_info_index = 14;
|
String src_addr = decode_address_ax25(ax25Frame.substring(7, 14), isLast, false);
|
||||||
while (!isLast && digi_info_index + 7 < ax25Frame.length()){
|
TNC2Frame = src_addr + ">" + dst_addr;
|
||||||
String digi_addr = decode_address_ax25(ax25Frame.substring(digi_info_index, digi_info_index + 7), isLast, true);
|
int digi_info_index = 14;
|
||||||
TNC2Frame += ',' + digi_addr;
|
while (!isLast && digi_info_index + 7 < ax25Frame.length()) {
|
||||||
digi_info_index += 7;
|
String digi_addr = decode_address_ax25(ax25Frame.substring(digi_info_index, digi_info_index + 7), isLast, true);
|
||||||
}
|
TNC2Frame += ',' + digi_addr;
|
||||||
TNC2Frame += ':';
|
digi_info_index += 7;
|
||||||
TNC2Frame += ax25Frame.substring(digi_info_index + 2);
|
}
|
||||||
|
TNC2Frame += ':';
|
||||||
|
TNC2Frame += ax25Frame.substring(digi_info_index + 2);
|
||||||
|
} else {
|
||||||
|
// command frame, currently ignored
|
||||||
|
TNC2Frame += inputKISSTNCFrame;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
return TNC2Frame;
|
return TNC2Frame;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -135,32 +146,32 @@ String decode_kiss(const String& kissFormattedFrame) {
|
||||||
* @return
|
* @return
|
||||||
*/
|
*/
|
||||||
String encode_address_ax25(String tnc2Address) {
|
String encode_address_ax25(String tnc2Address) {
|
||||||
bool hasBeenDigipited = tnc2Address.indexOf('*') != -1;
|
bool hasBeenDigipited = tnc2Address.indexOf('*') != -1;
|
||||||
|
|
||||||
if (tnc2Address.indexOf('-') == -1){
|
if (tnc2Address.indexOf('-') == -1) {
|
||||||
if (hasBeenDigipited){
|
if (hasBeenDigipited) {
|
||||||
// ex. TCPIP* in tnc2Address
|
// ex. TCPIP* in tnc2Address
|
||||||
// so we skip last char
|
// so we skip last char
|
||||||
tnc2Address = tnc2Address.substring(0, tnc2Address.length()-1);
|
tnc2Address = tnc2Address.substring(0, tnc2Address.length() - 1);
|
||||||
}
|
|
||||||
tnc2Address += "-0";
|
|
||||||
}
|
}
|
||||||
|
tnc2Address += "-0";
|
||||||
|
}
|
||||||
|
|
||||||
int separatorIndex = tnc2Address.indexOf('-');
|
int separatorIndex = tnc2Address.indexOf('-');
|
||||||
int ssid = tnc2Address.substring(separatorIndex + 1).toInt();
|
int ssid = tnc2Address.substring(separatorIndex + 1).toInt();
|
||||||
// TODO: SSID should not be > 16
|
// TODO: SSID should not be > 16
|
||||||
String kissAddress = "";
|
String kissAddress = "";
|
||||||
for (int i = 0; i < 6; ++i) {
|
for (int i = 0; i < 6; ++i) {
|
||||||
char addressChar;
|
char addressChar;
|
||||||
if (tnc2Address.length() > i && i < separatorIndex){
|
if (tnc2Address.length() > i && i < separatorIndex) {
|
||||||
addressChar = tnc2Address.charAt(i);
|
addressChar = tnc2Address.charAt(i);
|
||||||
} else {
|
} else {
|
||||||
addressChar = ' ';
|
addressChar = ' ';
|
||||||
}
|
|
||||||
kissAddress += (char)(addressChar << 1);
|
|
||||||
}
|
}
|
||||||
kissAddress += (char)((ssid << 1) | 0b01100000 | (hasBeenDigipited ? HAS_BEEN_DIGIPITED_MASK : 0));
|
kissAddress += (char) (addressChar << 1);
|
||||||
return kissAddress;
|
}
|
||||||
|
kissAddress += (char) ((ssid << 1) | 0b01100000 | (hasBeenDigipited ? HAS_BEEN_DIGIPITED_MASK : 0));
|
||||||
|
return kissAddress;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -169,30 +180,35 @@ String encode_address_ax25(String tnc2Address) {
|
||||||
* @return
|
* @return
|
||||||
*/
|
*/
|
||||||
String decode_address_ax25(const String &ax25Address, bool &isLast, bool isRelay) {
|
String decode_address_ax25(const String &ax25Address, bool &isLast, bool isRelay) {
|
||||||
String TNCAddress = "";
|
String TNCAddress = "";
|
||||||
for (int i = 0; i < 6; ++i) {
|
for (int i = 0; i < 6; ++i) {
|
||||||
uint8_t currentCharacter = ax25Address.charAt(i);
|
uint8_t currentCharacter = ax25Address.charAt(i);
|
||||||
currentCharacter >>= 1;
|
currentCharacter >>= 1;
|
||||||
if (currentCharacter != ' '){
|
if (currentCharacter != ' ') {
|
||||||
TNCAddress += (char)currentCharacter;
|
TNCAddress += (char) currentCharacter;
|
||||||
}
|
|
||||||
}
|
}
|
||||||
auto ssid_char = (uint8_t) ax25Address.charAt(6);
|
}
|
||||||
bool hasBeenDigipited = ssid_char & HAS_BEEN_DIGIPITED_MASK;
|
auto ssid_char = (uint8_t) ax25Address.charAt(6);
|
||||||
isLast = ssid_char & IS_LAST_ADDRESS_POSITION_MASK;
|
bool hasBeenDigipited = ssid_char & HAS_BEEN_DIGIPITED_MASK;
|
||||||
ssid_char >>= 1;
|
isLast = ssid_char & IS_LAST_ADDRESS_POSITION_MASK;
|
||||||
|
ssid_char >>= 1;
|
||||||
|
|
||||||
int ssid = 0b1111 & ssid_char;
|
int ssid = 0b1111 & ssid_char;
|
||||||
if (ssid){
|
if (ssid) {
|
||||||
TNCAddress += '-';
|
TNCAddress += '-';
|
||||||
TNCAddress += ssid;
|
TNCAddress += ssid;
|
||||||
}
|
}
|
||||||
if (isRelay && hasBeenDigipited){
|
if (isRelay && hasBeenDigipited) {
|
||||||
TNCAddress += '*';
|
TNCAddress += '*';
|
||||||
}
|
}
|
||||||
return TNCAddress;
|
return TNCAddress;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool validateTNC2Frame(const String &tnc2FormattedFrame) { return (tnc2FormattedFrame.indexOf(':') != -1) && (tnc2FormattedFrame.indexOf('>') != -1); }
|
bool validateTNC2Frame(const String &tnc2FormattedFrame) {
|
||||||
|
return (tnc2FormattedFrame.indexOf(':') != -1) && (tnc2FormattedFrame.indexOf('>') != -1);
|
||||||
|
}
|
||||||
|
|
||||||
bool validateKISSFrame(const String &kissFormattedFrame) { return kissFormattedFrame.charAt(0) == (char)FEND && kissFormattedFrame.charAt(kissFormattedFrame.length() - 1) == (char)FEND; }
|
bool validateKISSFrame(const String &kissFormattedFrame) {
|
||||||
|
return kissFormattedFrame.charAt(0) == (char) FEND &&
|
||||||
|
kissFormattedFrame.charAt(kissFormattedFrame.length() - 1) == (char) FEND;
|
||||||
|
}
|
|
@ -8,6 +8,6 @@
|
||||||
#define IS_LAST_ADDRESS_POSITION_MASK 0b1
|
#define IS_LAST_ADDRESS_POSITION_MASK 0b1
|
||||||
|
|
||||||
String encode_kiss(const String& tnc2FormattedFrame);
|
String encode_kiss(const String& tnc2FormattedFrame);
|
||||||
String decode_kiss(const String& kissFormattedFrame);
|
String decode_kiss(const String &inputKISSTNCFrame, bool &dataFrame);
|
||||||
|
|
||||||
String encapsulateKISS(const String &ax25Frame, uint8_t TNCCmd);
|
String encapsulateKISS(const String &ax25Frame, uint8_t TNCCmd);
|
|
@ -0,0 +1,27 @@
|
||||||
|
//
|
||||||
|
// Created by Admin on 14.06.2021.
|
||||||
|
//
|
||||||
|
|
||||||
|
#ifndef TTGO_T_BEAM_LORA_APRS_PSRAMJSONDOCUMENT_H
|
||||||
|
#define TTGO_T_BEAM_LORA_APRS_PSRAMJSONDOCUMENT_H
|
||||||
|
|
||||||
|
#include <ArduinoJson.h>
|
||||||
|
|
||||||
|
struct SpiRamAllocator {
|
||||||
|
void* allocate(size_t size) {
|
||||||
|
return heap_caps_malloc(size, MALLOC_CAP_SPIRAM);
|
||||||
|
}
|
||||||
|
|
||||||
|
void deallocate(void* pointer) {
|
||||||
|
heap_caps_free(pointer);
|
||||||
|
}
|
||||||
|
|
||||||
|
void* reallocate(void* ptr, size_t new_size) {
|
||||||
|
return heap_caps_realloc(ptr, new_size, MALLOC_CAP_SPIRAM);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
using PSRAMJsonDocument = BasicJsonDocument<SpiRamAllocator>;
|
||||||
|
|
||||||
|
|
||||||
|
#endif //TTGO_T_BEAM_LORA_APRS_PSRAMJSONDOCUMENT_H
|
|
@ -20,42 +20,47 @@ extra_scripts =
|
||||||
pre:tools/buildscript_versioning.py
|
pre:tools/buildscript_versioning.py
|
||||||
pre:tools/compress_assets.py
|
pre:tools/compress_assets.py
|
||||||
lib_deps =
|
lib_deps =
|
||||||
RadioHead
|
http://git.mis.ks.ua/US1GHQ/RadioHead.git
|
||||||
TinyGPSPlus
|
TinyGPSPlus
|
||||||
Adafruit SSD1306
|
Adafruit SSD1306
|
||||||
Adafruit GFX Library
|
Adafruit GFX Library
|
||||||
Adafruit Unified Sensor
|
Adafruit Unified Sensor
|
||||||
|
adafruit/Adafruit BMP280 Library @ 2.4.0
|
||||||
https://github.com/SQ9MDD/AXP202X_Library.git
|
https://github.com/SQ9MDD/AXP202X_Library.git
|
||||||
SparkFun u-blox Arduino Library
|
SparkFun u-blox Arduino Library
|
||||||
bblanchon/ArduinoJson
|
bblanchon/ArduinoJson
|
||||||
|
DallasTemperature
|
||||||
build_flags =
|
build_flags =
|
||||||
-Wl,--gc-sections,--relax
|
-Wl,--gc-sections,--relax
|
||||||
-D 'KISS_PROTOCOL'
|
-D 'KISS_PROTOCOL' ; leave enabled
|
||||||
-D 'CALLSIGN="N0CALL-0"'
|
-D 'CALLSIGN="NOCALL-0"' ; can be set from www interfeace
|
||||||
-D 'DIGI_PATH="ECHO"'
|
-D 'DIGI_PATH="ECHO"' ; can be set from www interfeace
|
||||||
-D 'FIXED_BEACON_EN'
|
-D 'FIXED_BEACON_EN' ; can be set from www interfeace
|
||||||
-D 'LATIDUDE_PRESET="0000.00N"'
|
-D 'LATIDUDE_PRESET="0000.00N"' ; can be set from www interfeace
|
||||||
-D 'LONGITUDE_PRESET="00000.00E"'
|
-D 'LONGITUDE_PRESET="00000.00E"' ; can be set from www interfeace
|
||||||
-D 'APRS_SYMBOL_TABLE="/"'
|
-D 'APRS_SYMBOL_TABLE="/"' ; can be set from www interfeace
|
||||||
-D 'APRS_SYMBOL="["'
|
-D 'APRS_SYMBOL="["' ; can be set from www interfeace
|
||||||
-D 'MY_COMMENT="Lora Tracker"'
|
-D 'MY_COMMENT="Lora Tracker"' ; can be set from www interfeace
|
||||||
-D 'SHOW_ALT'
|
-D 'SHOW_ALT' ; can be set from www interfeace
|
||||||
-D 'SHOW_BATT'
|
-D 'SHOW_BATT' ; can be set from www interfeace
|
||||||
-D 'SHOW_RX_PACKET'
|
-D 'SHOW_RX_PACKET' ; can be set from www interfeace
|
||||||
-D 'SHOW_RX_TIME=10000'
|
-D 'SHOW_RX_TIME=10000' ; can be set from www interfeace
|
||||||
-D 'TXFREQ=433.775'
|
-D 'TXFREQ=433.775' ; set operating frequency
|
||||||
-D 'SPEED_1200' ; comment out to set 300baud
|
-D 'SPEED_1200' ; comment out to set 300baud
|
||||||
-D 'TXdbmW=20'
|
-D 'TXdbmW=20' ; set power
|
||||||
-D 'ENABLE_OLED'
|
; -D 'ENABLE_OLED' ; can be set from www interfeace
|
||||||
-D 'ENABLE_LED_SIGNALING'
|
-D 'ENABLE_LED_SIGNALING' ; can be set from www interfeace
|
||||||
-D 'NETWORK_TNC_PORT=8001'
|
-D 'NETWORK_TNC_PORT=8001' ; default KISS TCP port
|
||||||
-D 'MAX_TIME_TO_NEXT_TX=360000L'
|
-D 'NETWORK_GPS_PORT=10110' ; GPS NMEA Port
|
||||||
-D 'FIX_BEACON_INTERVAL=1800000L'
|
-D 'MAX_TIME_TO_NEXT_TX=360000L' ; can be set from www interfeace
|
||||||
; -D 'RSSI_SNR_REPORT' ; RSSI and snr report in the KISS PACKET
|
-D 'FIX_BEACON_INTERVAL=1800000L' ; can be set from www interfeace
|
||||||
; -D 'TX_RX_LNA' ; Enable external pins for 1W modules, choose pins in *.ino file (default using D16 for RXEN and D17 for TXEN)
|
; -D 'RSSI_SNR_REPORT' ; RSSI and snr report in the KISS PACKET
|
||||||
|
; -D 'TX_RX_LNA' ; Set external pins for 1W modules
|
||||||
|
; -D 'USE_BME280' ; Temp sensor for simple WX station
|
||||||
|
; -D 'HEIGTH_PRESET=34'
|
||||||
|
|
||||||
[env:ttgo-t-beam-v1.0]
|
[env:ttgo-t-beam-v1.0]
|
||||||
platform = espressif32 @ 3.3.1
|
platform = espressif32 @ 3.3.2
|
||||||
board = ttgo-t-beam
|
board = ttgo-t-beam
|
||||||
build_flags =
|
build_flags =
|
||||||
${env.build_flags}
|
${env.build_flags}
|
||||||
|
@ -64,7 +69,7 @@ build_flags =
|
||||||
; -D ENABLE_BLUETOOTH
|
; -D ENABLE_BLUETOOTH
|
||||||
|
|
||||||
[env:ttgo-t-beam-v0.7]
|
[env:ttgo-t-beam-v0.7]
|
||||||
platform = espressif32 @ 3.3.1
|
platform = espressif32 @ 3.3.2
|
||||||
board = ttgo-t-beam
|
board = ttgo-t-beam
|
||||||
build_flags =
|
build_flags =
|
||||||
${env.build_flags}
|
${env.build_flags}
|
||||||
|
@ -73,7 +78,7 @@ build_flags =
|
||||||
-D T_BEAM_V0_7
|
-D T_BEAM_V0_7
|
||||||
|
|
||||||
[env:ttgo-lora32-v2.1]
|
[env:ttgo-lora32-v2.1]
|
||||||
platform = espressif32 @ 3.3.1
|
platform = espressif32 @ 3.3.2
|
||||||
board = ttgo-lora32-v21
|
board = ttgo-lora32-v21
|
||||||
build_flags =
|
build_flags =
|
||||||
${env.build_flags}
|
${env.build_flags}
|
||||||
|
@ -82,7 +87,7 @@ build_flags =
|
||||||
-D LORA32_21
|
-D LORA32_21
|
||||||
|
|
||||||
[env:ttgo-lora32-v2]
|
[env:ttgo-lora32-v2]
|
||||||
platform = espressif32 @ 3.3.1
|
platform = espressif32 @ 3.3.2
|
||||||
board = ttgo-lora32-v2
|
board = ttgo-lora32-v2
|
||||||
build_flags =
|
build_flags =
|
||||||
${env.build_flags}
|
${env.build_flags}
|
||||||
|
@ -91,7 +96,7 @@ build_flags =
|
||||||
-D LORA32_2
|
-D LORA32_2
|
||||||
|
|
||||||
[env:ttgo-lora32-v1]
|
[env:ttgo-lora32-v1]
|
||||||
platform = espressif32 @ 3.3.1
|
platform = espressif32 @ 3.3.2
|
||||||
board = ttgo-lora32-v1
|
board = ttgo-lora32-v1
|
||||||
build_flags =
|
build_flags =
|
||||||
${env.build_flags}
|
${env.build_flags}
|
||||||
|
@ -100,7 +105,7 @@ build_flags =
|
||||||
-D LORA32_1
|
-D LORA32_1
|
||||||
|
|
||||||
[env:Heltec-WiFi-v1]
|
[env:Heltec-WiFi-v1]
|
||||||
platform = espressif32 @ 3.3.1
|
platform = espressif32 @ 3.3.2
|
||||||
board = heltec_wifi_kit_32
|
board = heltec_wifi_kit_32
|
||||||
build_flags =
|
build_flags =
|
||||||
${env.build_flags}
|
${env.build_flags}
|
||||||
|
@ -109,7 +114,7 @@ build_flags =
|
||||||
-D HELTEC_V1
|
-D HELTEC_V1
|
||||||
|
|
||||||
[env:Heltec-WiFi-v2]
|
[env:Heltec-WiFi-v2]
|
||||||
platform = espressif32 @ 3.3.1
|
platform = espressif32 @ 3.3.2
|
||||||
board = heltec_wifi_kit_32_v2
|
board = heltec_wifi_kit_32_v2
|
||||||
board_build.f_cpu = 80000000L
|
board_build.f_cpu = 80000000L
|
||||||
build_flags =
|
build_flags =
|
||||||
|
@ -119,7 +124,7 @@ build_flags =
|
||||||
-D HELTEC_V2
|
-D HELTEC_V2
|
||||||
|
|
||||||
[env:Esp32-Dev-v1]
|
[env:Esp32-Dev-v1]
|
||||||
platform = espressif32 @ 3.3.1
|
platform = espressif32 @ 3.3.2
|
||||||
board = esp32dev
|
board = esp32dev
|
||||||
; change MCU frequency
|
; change MCU frequency
|
||||||
;board_build.f_cpu = 80000000L
|
;board_build.f_cpu = 80000000L
|
||||||
|
@ -139,7 +144,7 @@ build_flags =
|
||||||
-D ENABLE_BLUETOOTH
|
-D ENABLE_BLUETOOTH
|
||||||
-D ENABLE_SYSLOG
|
-D ENABLE_SYSLOG
|
||||||
-D 'SYSLOG_IP="192.168.0.102"'
|
-D 'SYSLOG_IP="192.168.0.102"'
|
||||||
-D DEVELOPMENT_DEBUG
|
-D DEVELOPMENT_DEBUG
|
||||||
lib_deps =
|
lib_deps =
|
||||||
${env.lib_deps}
|
${env.lib_deps}
|
||||||
arcao/Syslog
|
arcao/Syslog
|
||||||
|
|
|
@ -32,6 +32,10 @@
|
||||||
#include "taskWebServer.h"
|
#include "taskWebServer.h"
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#ifdef USE_BME280
|
||||||
|
#include <Adafruit_BMP280.h> // BME280 Library
|
||||||
|
#endif
|
||||||
|
|
||||||
// oled address
|
// oled address
|
||||||
#define SSD1306_ADDRESS 0x3C
|
#define SSD1306_ADDRESS 0x3C
|
||||||
|
|
||||||
|
@ -149,9 +153,15 @@ boolean show_cmt = true;
|
||||||
#else
|
#else
|
||||||
boolean enabled_oled = false;
|
boolean enabled_oled = false;
|
||||||
#endif
|
#endif
|
||||||
|
#ifdef USE_BME280
|
||||||
|
boolean enable_bme280 = true;
|
||||||
|
#else
|
||||||
|
boolean enable_bme280 = false;
|
||||||
|
#endif
|
||||||
|
|
||||||
// Variables and Constants
|
// Variables and Constants
|
||||||
String loraReceivedFrameString = ""; //data on buff is copied to this string
|
String loraReceivedFrameString = ""; //data on buff is copied to this string
|
||||||
|
String loraSendFrameString = ""; //data on buff is copied to this string
|
||||||
String Outputstring = "";
|
String Outputstring = "";
|
||||||
String outString=""; //The new Output String with GPS Conversion RAW
|
String outString=""; //The new Output String with GPS Conversion RAW
|
||||||
String LongShown="";
|
String LongShown="";
|
||||||
|
@ -203,7 +213,7 @@ ulong time_delay = 0;
|
||||||
ulong shutdown_delay = 0;
|
ulong shutdown_delay = 0;
|
||||||
ulong shutdown_delay_time = 10000;
|
ulong shutdown_delay_time = 10000;
|
||||||
ulong shutdown_countdown_timer = 0;
|
ulong shutdown_countdown_timer = 0;
|
||||||
boolean shutdown_active =true;
|
boolean shutdown_active =false;
|
||||||
boolean shutdown_countdown_timer_enable = false;
|
boolean shutdown_countdown_timer_enable = false;
|
||||||
boolean shutdown_usb_status_bef = false;
|
boolean shutdown_usb_status_bef = false;
|
||||||
#define ANGLE 60 // angle to send packet at smart beaconing
|
#define ANGLE 60 // angle to send packet at smart beaconing
|
||||||
|
@ -211,6 +221,16 @@ boolean shutdown_usb_status_bef = false;
|
||||||
float average_course[ANGLE_AVGS];
|
float average_course[ANGLE_AVGS];
|
||||||
float avg_c_y, avg_c_x;
|
float avg_c_y, avg_c_x;
|
||||||
|
|
||||||
|
//Variables for BME Sensors
|
||||||
|
boolean hum_temp = false;
|
||||||
|
uint8_t hum_temp_ctr, hum_temp_ctr_max = 3;
|
||||||
|
boolean tempsensoravailable=true;
|
||||||
|
float hum=0; //Stores humidity value
|
||||||
|
float temp=99.99; //Stores temperature value
|
||||||
|
float tempf=99.99; //Stores temperature value
|
||||||
|
float pressure=0; //Stores pressure value in hPa
|
||||||
|
int pressure_offset=0; //Stores offset for pressure correction
|
||||||
|
|
||||||
uint8_t txPower = TXdbmW;
|
uint8_t txPower = TXdbmW;
|
||||||
|
|
||||||
#ifdef ENABLE_WIFI
|
#ifdef ENABLE_WIFI
|
||||||
|
@ -239,6 +259,10 @@ uint8_t loraReceivedLength = sizeof(lora_RXBUFF);
|
||||||
#else
|
#else
|
||||||
#define OLED_RESET 16
|
#define OLED_RESET 16
|
||||||
#endif
|
#endif
|
||||||
|
//Temp sensor
|
||||||
|
#ifdef USE_BME280
|
||||||
|
Adafruit_BMP280 bme; // if BME is used
|
||||||
|
#endif
|
||||||
|
|
||||||
Adafruit_SSD1306 display(128, 64, &Wire, OLED_RESET);
|
Adafruit_SSD1306 display(128, 64, &Wire, OLED_RESET);
|
||||||
|
|
||||||
|
@ -277,9 +301,10 @@ void prepareAPRSFrame(){
|
||||||
outString += Tcall;
|
outString += Tcall;
|
||||||
|
|
||||||
if (relay_path){
|
if (relay_path){
|
||||||
outString += ">APLS01," + relay_path + ":!";
|
outString += ">APLO01:!";
|
||||||
|
|
||||||
}else{
|
}else{
|
||||||
outString += ">APLS01:!";
|
outString += ">APLO01," + relay_path + ":!";
|
||||||
}
|
}
|
||||||
|
|
||||||
if(gps_state && gps.location.isValid()){
|
if(gps_state && gps.location.isValid()){
|
||||||
|
@ -308,12 +333,48 @@ void prepareAPRSFrame(){
|
||||||
}
|
}
|
||||||
outString += Talt;
|
outString += Talt;
|
||||||
}
|
}
|
||||||
}else{ //fixed position not compresed
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
//fixed position not compresed
|
||||||
outString += aprsLatPreset;
|
outString += aprsLatPreset;
|
||||||
outString += aprsSymbolTable;
|
outString += aprsSymbolTable;
|
||||||
outString += aprsLonPreset;
|
outString += aprsLonPreset;
|
||||||
outString += aprsSymbol;
|
outString += aprsSymbol;
|
||||||
}
|
#ifdef USE_BME280
|
||||||
|
if(enable_bme280)
|
||||||
|
{
|
||||||
|
// bme.takeForcedMeasurement();
|
||||||
|
tempf = bme.readTemperature()*9/5+29;
|
||||||
|
// hum = bme.readHumidity();
|
||||||
|
pressure = bme.readPressure()/100 + pressure_offset;
|
||||||
|
outString += ".../...g...t";
|
||||||
|
if (tempf < 0) { // negative Werte erstellen
|
||||||
|
outString += "-";
|
||||||
|
if(tempf>-10) {outString += "0"; }
|
||||||
|
tempf = abs(tempf);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{ // positive Werte erstellen
|
||||||
|
if(tempf<100) {outString += "0"; }
|
||||||
|
if(tempf<10) {outString += "0"; }
|
||||||
|
}
|
||||||
|
helper = String(tempf-3,0);
|
||||||
|
helper.trim();
|
||||||
|
outString += helper;
|
||||||
|
outString += "r...p...P...h";
|
||||||
|
if(hum<10) {outString += "0"; }
|
||||||
|
helper = String(hum,0);
|
||||||
|
helper.trim();
|
||||||
|
outString += helper;
|
||||||
|
outString += "b";
|
||||||
|
if(pressure<1000) {outString += "0"; }
|
||||||
|
helper = String(pressure*10,0);
|
||||||
|
helper.trim();
|
||||||
|
outString += helper;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
if(show_cmt){
|
if(show_cmt){
|
||||||
outString += aprsComment;
|
outString += aprsComment;
|
||||||
|
@ -363,7 +424,7 @@ void sendpacket(){
|
||||||
* @param aprsFreq
|
* @param aprsFreq
|
||||||
* @param message
|
* @param message
|
||||||
*/
|
*/
|
||||||
void loraSend(byte txPower, float aprsFreq, const String &message) {
|
void loraSend(byte txPower, float aprsFreq, const String message) {
|
||||||
#ifdef TX_RX_LNA
|
#ifdef TX_RX_LNA
|
||||||
digitalWrite(TXPIN, HIGH);
|
digitalWrite(TXPIN, HIGH);
|
||||||
digitalWrite(RXPIN, LOW);
|
digitalWrite(RXPIN, LOW);
|
||||||
|
@ -375,7 +436,12 @@ void loraSend(byte txPower, float aprsFreq, const String &message) {
|
||||||
lastTX = millis();
|
lastTX = millis();
|
||||||
|
|
||||||
int messageSize = min(message.length(), sizeof(lora_TXBUFF) - 1);
|
int messageSize = min(message.length(), sizeof(lora_TXBUFF) - 1);
|
||||||
message.toCharArray((char*)lora_TXBUFF, messageSize + 1, 0);
|
// message.getBytes(lora_TXBUFF, messageSize + 1, 0);
|
||||||
|
loraSendFrameString = message;
|
||||||
|
for (int i = 0 ; i < messageSize ; i++) {
|
||||||
|
lora_TXBUFF[i] = (char)loraSendFrameString[i];
|
||||||
|
}
|
||||||
|
|
||||||
if (aprsMode == 1200)
|
if (aprsMode == 1200)
|
||||||
{
|
{
|
||||||
rf95.setModemConfig(BG_RF95::Bw125Cr47Sf512);
|
rf95.setModemConfig(BG_RF95::Bw125Cr47Sf512);
|
||||||
|
@ -384,6 +450,7 @@ void loraSend(byte txPower, float aprsFreq, const String &message) {
|
||||||
{
|
{
|
||||||
rf95.setModemConfig(BG_RF95::Bw125Cr45Sf4096);
|
rf95.setModemConfig(BG_RF95::Bw125Cr45Sf4096);
|
||||||
}
|
}
|
||||||
|
|
||||||
rf95.setFrequency(aprsFreq);
|
rf95.setFrequency(aprsFreq);
|
||||||
rf95.setTxPower(txPower);
|
rf95.setTxPower(txPower);
|
||||||
rf95.sendAPRS(lora_TXBUFF, messageSize);
|
rf95.sendAPRS(lora_TXBUFF, messageSize);
|
||||||
|
@ -540,7 +607,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 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 telemetryData = String("T#MIC") + String(b_volt) + ","+ String(b_in_c) + ","+ String(b_out_c) + ","+ String(ac_volt) + ","+ String(ac_c) + ",00000000";
|
||||||
String telemetryBase = "";
|
String telemetryBase = "";
|
||||||
telemetryBase += Tcall + ">APLS01" + ":";
|
telemetryBase += Tcall + ">APLO01" + ":";
|
||||||
sendToTNC(telemetryBase + telemetryParamsNames);
|
sendToTNC(telemetryBase + telemetryParamsNames);
|
||||||
sendToTNC(telemetryBase + telemetryUnitNames);
|
sendToTNC(telemetryBase + telemetryUnitNames);
|
||||||
sendToTNC(telemetryBase + telemetryEquations);
|
sendToTNC(telemetryBase + telemetryEquations);
|
||||||
|
@ -552,7 +619,9 @@ void sendTelemetryFrame() {
|
||||||
// + SETUP --------------------------------------------------------------+//
|
// + SETUP --------------------------------------------------------------+//
|
||||||
void setup(){
|
void setup(){
|
||||||
SPI.begin(SPI_sck,SPI_miso,SPI_mosi,SPI_ss); //DO2JMG Heltec Patch
|
SPI.begin(SPI_sck,SPI_miso,SPI_mosi,SPI_ss); //DO2JMG Heltec Patch
|
||||||
|
|
||||||
|
bool bme_status;
|
||||||
|
|
||||||
#ifdef BUZZER
|
#ifdef BUZZER
|
||||||
ledcSetup(0,1E5,12);
|
ledcSetup(0,1E5,12);
|
||||||
ledcAttachPin(BUZZER,0);
|
ledcAttachPin(BUZZER,0);
|
||||||
|
@ -868,11 +937,28 @@ void setup(){
|
||||||
writedisplaytext("","","","","","");
|
writedisplaytext("","","","","","");
|
||||||
time_to_refresh = millis() + showRXTime;
|
time_to_refresh = millis() + showRXTime;
|
||||||
displayInvalidGPS();
|
displayInvalidGPS();
|
||||||
|
|
||||||
|
#ifdef USE_BME280
|
||||||
|
bme_status = bme.begin(0x76);
|
||||||
|
if (!bme_status)
|
||||||
|
{
|
||||||
|
Serial.println("Could not find a valid BME280 sensor, check wiring!");
|
||||||
|
//writedisplaytext("LoRa-APRS","","Init:","BME280 ERROR!","","",3000);
|
||||||
|
tempsensoravailable = false;
|
||||||
|
}
|
||||||
|
pressure_offset = calc_pressure_offset(HEIGTH_PRESET);
|
||||||
|
// bme.takeForcedMeasurement();
|
||||||
|
temp = bme.readTemperature() - 3; // bme Temperatur auslesen
|
||||||
|
// hum = bme.readHumidity();
|
||||||
|
pressure = bme.readPressure()/100 + pressure_offset;
|
||||||
|
#endif
|
||||||
|
|
||||||
#ifdef TX_RX_LNA
|
#ifdef TX_RX_LNA
|
||||||
digitalWrite(TXPIN, LOW);
|
digitalWrite(TXPIN, LOW);
|
||||||
digitalWrite(RXPIN, HIGH);
|
digitalWrite(RXPIN, HIGH);
|
||||||
#endif
|
#endif
|
||||||
digitalWrite(TXLED, LOW);
|
digitalWrite(TXLED, LOW);
|
||||||
|
hum_temp_ctr = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
// +---------------------------------------------------------------------+//
|
// +---------------------------------------------------------------------+//
|
||||||
|
@ -970,6 +1056,34 @@ void loop() {
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
if (hum_temp)
|
||||||
|
{
|
||||||
|
++hum_temp_ctr;
|
||||||
|
if (hum_temp_ctr>hum_temp_ctr_max)
|
||||||
|
{
|
||||||
|
hum_temp_ctr = 0;
|
||||||
|
hum_temp=false;
|
||||||
|
}
|
||||||
|
#ifdef USE_BME280
|
||||||
|
//bme.takeForcedMeasurement();
|
||||||
|
temp = bme.readTemperature() - 3; // bme Temperatur auslesen
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
++hum_temp_ctr;
|
||||||
|
if (hum_temp_ctr>hum_temp_ctr_max)
|
||||||
|
{
|
||||||
|
hum_temp_ctr = 0;
|
||||||
|
hum_temp=true;
|
||||||
|
}
|
||||||
|
#ifdef USE_BME280
|
||||||
|
//bme.takeForcedMeasurement();
|
||||||
|
//hum = bme.readHumidity();
|
||||||
|
pressure = bme.readPressure()/100 + pressure_offset;
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
if (rf95.waitAvailableTimeout(100)) {
|
if (rf95.waitAvailableTimeout(100)) {
|
||||||
#ifdef T_BEAM_V1_0
|
#ifdef T_BEAM_V1_0
|
||||||
#ifdef ENABLE_LED_SIGNALING
|
#ifdef ENABLE_LED_SIGNALING
|
||||||
|
@ -1112,4 +1226,16 @@ void loop() {
|
||||||
#endif
|
#endif
|
||||||
#endif
|
#endif
|
||||||
vTaskDelay(1);
|
vTaskDelay(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
int calc_pressure_offset(int height) {
|
||||||
|
//
|
||||||
|
// A very simple method to calculate the offset for correcting the measured air pressure
|
||||||
|
// to the pressure at mean sea level (MSL). It is simplificated to "For each 8m change in height
|
||||||
|
// the pressure is changing by 1hPa."
|
||||||
|
// The exact method is described at
|
||||||
|
// https://de.wikipedia.org/wiki/Barometrische_H%C3%B6henformel#Internationale_H%C3%B6henformel
|
||||||
|
//
|
||||||
|
int offset = round(height / 8);
|
||||||
|
return(offset);
|
||||||
}
|
}
|
|
@ -1,8 +1,16 @@
|
||||||
#include <taskGPS.h>
|
#include <taskGPS.h>
|
||||||
#include <SparkFun_Ublox_Arduino_Library.h>
|
#include <SparkFun_Ublox_Arduino_Library.h>
|
||||||
|
#include <taskWebServer.h>
|
||||||
|
|
||||||
|
|
||||||
SFE_UBLOX_GPS myGPS;
|
SFE_UBLOX_GPS myGPS;
|
||||||
|
|
||||||
|
#ifdef ENABLE_WIFI
|
||||||
|
#include "wifi_clients.h"
|
||||||
|
#define MAX_GPS_WIFI_CLIENTS 6
|
||||||
|
WiFiClient * gps_clients[MAX_GPS_WIFI_CLIENTS];
|
||||||
|
#endif
|
||||||
|
|
||||||
// Pins for GPS
|
// Pins for GPS
|
||||||
#ifdef T_BEAM_V1_0
|
#ifdef T_BEAM_V1_0
|
||||||
static const int RXPin = 12, TXPin = 34;
|
static const int RXPin = 12, TXPin = 34;
|
||||||
|
@ -14,7 +22,7 @@ HardwareSerial gpsSerial(1); // TTGO has HW serial
|
||||||
TinyGPSPlus gps; // The TinyGPS++ object
|
TinyGPSPlus gps; // The TinyGPS++ object
|
||||||
bool gpsInitialized = false;
|
bool gpsInitialized = false;
|
||||||
|
|
||||||
void taskGPS(void *parameter) {
|
[[noreturn]] void taskGPS(void *parameter) {
|
||||||
if (!gpsInitialized){
|
if (!gpsInitialized){
|
||||||
gpsSerial.begin(GPSBaud, SERIAL_8N1, TXPin, RXPin); //Startup HW serial for GPS
|
gpsSerial.begin(GPSBaud, SERIAL_8N1, TXPin, RXPin); //Startup HW serial for GPS
|
||||||
|
|
||||||
|
@ -35,9 +43,31 @@ void taskGPS(void *parameter) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
String gpsDataBuffer = " ";
|
||||||
for (;;) {
|
for (;;) {
|
||||||
|
#ifdef ENABLE_WIFI
|
||||||
|
check_for_new_clients(&gpsServer, gps_clients, MAX_GPS_WIFI_CLIENTS);
|
||||||
|
#endif
|
||||||
while (gpsSerial.available() > 0) {
|
while (gpsSerial.available() > 0) {
|
||||||
gps.encode(gpsSerial.read());
|
char gpsChar = (char)gpsSerial.read();
|
||||||
|
gps.encode(gpsChar);
|
||||||
|
#ifdef ENABLE_WIFI
|
||||||
|
if (gpsChar == '$') {
|
||||||
|
gpsDataBuffer = String(gpsChar);
|
||||||
|
} else {
|
||||||
|
gpsDataBuffer += String(gpsChar);
|
||||||
|
|
||||||
|
if (gpsChar == '\n') {
|
||||||
|
iterateWifiClients([](WiFiClient *client, int clientIdx, const String *data){
|
||||||
|
if (client->connected()){
|
||||||
|
client->print(*data);
|
||||||
|
client->flush();
|
||||||
|
}
|
||||||
|
}, &gpsDataBuffer, gps_clients, MAX_GPS_WIFI_CLIENTS);
|
||||||
|
gpsDataBuffer = "";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
vTaskDelay(100 / portTICK_PERIOD_MS);
|
vTaskDelay(100 / portTICK_PERIOD_MS);
|
||||||
}
|
}
|
||||||
|
|
134
src/taskTNC.cpp
134
src/taskTNC.cpp
|
@ -9,25 +9,6 @@ QueueHandle_t tncReceivedQueue = nullptr;
|
||||||
#ifdef ENABLE_WIFI
|
#ifdef ENABLE_WIFI
|
||||||
#define MAX_WIFI_CLIENTS 6
|
#define MAX_WIFI_CLIENTS 6
|
||||||
WiFiClient * clients[MAX_WIFI_CLIENTS];
|
WiFiClient * clients[MAX_WIFI_CLIENTS];
|
||||||
|
|
||||||
typedef void (*f_connectedClientCallback_t) (WiFiClient *, int, const String *);
|
|
||||||
|
|
||||||
void iterateWifiClients(f_connectedClientCallback_t callback, const String *data){
|
|
||||||
for (int i=0; i<MAX_WIFI_CLIENTS; i++) {
|
|
||||||
auto client = clients[i];
|
|
||||||
if (client != nullptr) {
|
|
||||||
if (client->connected()) {
|
|
||||||
callback(client, i, data);
|
|
||||||
} else {
|
|
||||||
#ifdef ENABLE_WIFI_CLIENT_DEBUG
|
|
||||||
Serial.println(String("Disconnected client ") + client->remoteIP().toString() + ":" + client->remotePort());
|
|
||||||
#endif
|
|
||||||
delete client;
|
|
||||||
clients[i] = nullptr;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
#endif
|
#endif
|
||||||
#ifdef ENABLE_WIFI
|
#ifdef ENABLE_WIFI
|
||||||
#define IN_TNC_BUFFERS (2+MAX_WIFI_CLIENTS)
|
#define IN_TNC_BUFFERS (2+MAX_WIFI_CLIENTS)
|
||||||
|
@ -46,37 +27,43 @@ QueueHandle_t tncToSendQueue = nullptr;
|
||||||
*/
|
*/
|
||||||
void handleKISSData(char character, int bufferIndex) {
|
void handleKISSData(char character, int bufferIndex) {
|
||||||
String *inTNCData = &inTNCDataBuffers[bufferIndex];
|
String *inTNCData = &inTNCDataBuffers[bufferIndex];
|
||||||
if (inTNCData->length() == 0 && character != (char) FEND){
|
if (inTNCData->length() == 0 && character != (char) FEND)
|
||||||
|
{
|
||||||
// kiss frame begins with C0
|
// kiss frame begins with C0
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
inTNCData->concat(character);
|
inTNCData->concat(character);
|
||||||
if (character == (char) FEND && inTNCData->length() > 3) {
|
if (character == (char) FEND && inTNCData->length() > 3)
|
||||||
const String &TNC2DataFrame = decode_kiss(*inTNCData);
|
{
|
||||||
|
bool isDataFrame = false;
|
||||||
|
bool isPacketFrame = false;
|
||||||
|
const String &TNC2DataFrame = decode_kiss_pkt(*inTNCData, isDataFrame, isPacketFrame);
|
||||||
|
|
||||||
#ifdef LOCAL_KISS_ECHO
|
if (isDataFrame && isPacketFrame) {
|
||||||
Serial.print(inTNCData);
|
auto *buffer = new String();
|
||||||
#ifdef ENABLE_BLUETOOTH
|
buffer->concat(TNC2DataFrame);
|
||||||
if (SerialBT.hasClient()) {
|
if (xQueueSend(tncToSendQueue, &buffer, (1000 / portTICK_PERIOD_MS)) != pdPASS)
|
||||||
SerialBT.print(inTNCData);
|
{
|
||||||
}
|
delete buffer;
|
||||||
#endif
|
}
|
||||||
#ifdef ENABLE_WIFI
|
inTNCData->clear();
|
||||||
iterateWifiClients([](WiFiClient *client, const String *data){
|
}
|
||||||
if (client->connected()){
|
else if (character == (char) FEND && inTNCData->length() > 3)
|
||||||
client->print(*data);
|
{
|
||||||
client->flush();
|
bool isDataFrame = false;
|
||||||
}
|
const String &TNC2DataFrame = decode_kiss(*inTNCData, isDataFrame);
|
||||||
}, &inTNCData);
|
|
||||||
#endif
|
if (isDataFrame) {
|
||||||
#endif
|
auto *buffer = new String();
|
||||||
auto *buffer = new String();
|
buffer->concat(TNC2DataFrame);
|
||||||
buffer->concat(TNC2DataFrame);
|
if (xQueueSend(tncToSendQueue, &buffer, (1000 / portTICK_PERIOD_MS)) != pdPASS)
|
||||||
if (xQueueSend(tncToSendQueue, &buffer, (1000 / portTICK_PERIOD_MS)) != pdPASS){
|
{
|
||||||
delete buffer;
|
delete buffer;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
inTNCData->clear();
|
inTNCData->clear();
|
||||||
}
|
}
|
||||||
|
}
|
||||||
if (inTNCData->length() > 255){
|
if (inTNCData->length() > 255){
|
||||||
// just in case of garbage input reset data
|
// just in case of garbage input reset data
|
||||||
inTNCData->clear();
|
inTNCData->clear();
|
||||||
|
@ -103,49 +90,38 @@ void handleKISSData(char character, int bufferIndex) {
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
#ifdef ENABLE_WIFI
|
#ifdef ENABLE_WIFI
|
||||||
WiFiClient new_client = tncServer.available();
|
check_for_new_clients(&tncServer, clients, MAX_WIFI_CLIENTS);
|
||||||
if (new_client.connected()){
|
|
||||||
bool new_client_handled = false;
|
|
||||||
for (int i=0; i < MAX_WIFI_CLIENTS; i++) {
|
|
||||||
auto client = clients[i];
|
|
||||||
if (client == nullptr) {
|
|
||||||
client = new WiFiClient(new_client);
|
|
||||||
clients[i] = client;
|
|
||||||
new_client_handled = true;
|
|
||||||
#ifdef ENABLE_WIFI_CLIENT_DEBUG
|
|
||||||
Serial.println(String("New client #") +String(i) + ": " + client->remoteIP().toString() + ":" + client->remotePort());
|
|
||||||
#endif
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
#ifdef ENABLE_WIFI_CLIENT_DEBUG
|
|
||||||
for (int i = 0; i < MAX_WIFI_CLIENTS; ++i) {
|
|
||||||
auto client = clients[i];
|
|
||||||
|
|
||||||
if (client != nullptr){
|
|
||||||
Serial.println(String("Client #") +String(i) + ": " + client->remoteIP().toString() + ":" + client->remotePort());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
|
|
||||||
if (!new_client_handled){
|
|
||||||
#ifdef ENABLE_WIFI_CLIENT_DEBUG
|
|
||||||
Serial.println(String("Refusing client "));
|
|
||||||
#endif
|
|
||||||
new_client.stop();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
iterateWifiClients([](WiFiClient * client, int clientIdx, const String * unused){
|
iterateWifiClients([](WiFiClient * client, int clientIdx, const String * unused){
|
||||||
while (client->available() > 0) {
|
while (client->available() > 0) {
|
||||||
char character = client->read();
|
char character = client->read();
|
||||||
handleKISSData(character, 2+clientIdx);
|
handleKISSData(character, 1);
|
||||||
}
|
}
|
||||||
}, nullptr);
|
}, nullptr, clients, MAX_WIFI_CLIENTS);
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
if (xQueueReceive(tncReceivedQueue, &loraReceivedFrameString, (1 / portTICK_PERIOD_MS)) == pdPASS) {
|
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);
|
const String &kissEncoded = encode_kiss(*loraReceivedFrameString);
|
||||||
|
if (isPacketFrame) {
|
||||||
|
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
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
Serial.print(kissEncoded);
|
Serial.print(kissEncoded);
|
||||||
#ifdef ENABLE_BLUETOOTH
|
#ifdef ENABLE_BLUETOOTH
|
||||||
if (SerialBT.hasClient()){
|
if (SerialBT.hasClient()){
|
||||||
|
@ -158,9 +134,9 @@ void handleKISSData(char character, int bufferIndex) {
|
||||||
client->print(*data);
|
client->print(*data);
|
||||||
client->flush();
|
client->flush();
|
||||||
}
|
}
|
||||||
}, &kissEncoded);
|
}, &kissEncoded, clients, MAX_WIFI_CLIENTS);
|
||||||
#endif
|
#endif
|
||||||
|
}
|
||||||
delete loraReceivedFrameString;
|
delete loraReceivedFrameString;
|
||||||
}
|
}
|
||||||
vTaskDelay(50 / portTICK_PERIOD_MS);
|
vTaskDelay(50 / portTICK_PERIOD_MS);
|
||||||
|
|
|
@ -2,6 +2,7 @@
|
||||||
#include "taskWebServer.h"
|
#include "taskWebServer.h"
|
||||||
#include "preference_storage.h"
|
#include "preference_storage.h"
|
||||||
#include "syslog_log.h"
|
#include "syslog_log.h"
|
||||||
|
#include "PSRAMJsonDocument.h"
|
||||||
#include <time.h>
|
#include <time.h>
|
||||||
#include <ArduinoJson.h>
|
#include <ArduinoJson.h>
|
||||||
|
|
||||||
|
@ -25,6 +26,7 @@ WebServer server(80);
|
||||||
#ifdef KISS_PROTOCOL
|
#ifdef KISS_PROTOCOL
|
||||||
WiFiServer tncServer(NETWORK_TNC_PORT);
|
WiFiServer tncServer(NETWORK_TNC_PORT);
|
||||||
#endif
|
#endif
|
||||||
|
WiFiServer gpsServer(NETWORK_GPS_PORT);
|
||||||
|
|
||||||
#ifdef ENABLE_SYSLOG
|
#ifdef ENABLE_SYSLOG
|
||||||
// A UDP instance to let us send and receive packets over UDP
|
// A UDP instance to let us send and receive packets over UDP
|
||||||
|
@ -34,6 +36,11 @@ WebServer server(80);
|
||||||
Syslog syslog(udpClient, SYSLOG_PROTO_IETF);
|
Syslog syslog(udpClient, SYSLOG_PROTO_IETF);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#ifdef T_BEAM_V1_0
|
||||||
|
#include <axp20x.h>
|
||||||
|
extern AXP20X_Class axp;
|
||||||
|
#endif
|
||||||
|
|
||||||
void sendCacheHeader() { server.sendHeader("Cache-Control", "max-age=3600"); }
|
void sendCacheHeader() { server.sendHeader("Cache-Control", "max-age=3600"); }
|
||||||
void sendGzipHeader() { server.sendHeader("Content-Encoding", "gzip"); }
|
void sendGzipHeader() { server.sendHeader("Content-Encoding", "gzip"); }
|
||||||
|
|
||||||
|
@ -121,9 +128,20 @@ void handle_SaveWifiCfg() {
|
||||||
void handle_Reboot() {
|
void handle_Reboot() {
|
||||||
server.sendHeader("Location", "/");
|
server.sendHeader("Location", "/");
|
||||||
server.send(302,"text/html", "");
|
server.send(302,"text/html", "");
|
||||||
|
server.close();
|
||||||
ESP.restart();
|
ESP.restart();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void handle_Shutdown() {
|
||||||
|
|
||||||
|
#ifdef T_BEAM_V1_0
|
||||||
|
server.send(200,"text/html", "Shutdown");
|
||||||
|
axp.shutdown();
|
||||||
|
#else
|
||||||
|
server.send(404,"text/html", "Not supported");
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
void handle_Restore() {
|
void handle_Restore() {
|
||||||
server.sendHeader("Location", "/");
|
server.sendHeader("Location", "/");
|
||||||
server.send(302,"text/html", "");
|
server.send(302,"text/html", "");
|
||||||
|
@ -163,7 +181,9 @@ void handle_Cfg() {
|
||||||
jsonData += jsonLineFromPreferenceInt(PREF_DEV_AUTO_SHUT_PRESET);
|
jsonData += jsonLineFromPreferenceInt(PREF_DEV_AUTO_SHUT_PRESET);
|
||||||
jsonData += jsonLineFromInt("FreeHeap", ESP.getFreeHeap());
|
jsonData += jsonLineFromInt("FreeHeap", ESP.getFreeHeap());
|
||||||
jsonData += jsonLineFromInt("HeapSize", ESP.getHeapSize());
|
jsonData += jsonLineFromInt("HeapSize", ESP.getHeapSize());
|
||||||
jsonData += jsonLineFromInt("FreeSketchSpace", ESP.getFreeSketchSpace(), true);
|
jsonData += jsonLineFromInt("FreeSketchSpace", ESP.getFreeSketchSpace());
|
||||||
|
jsonData += jsonLineFromInt("PSRAMSize", ESP.getPsramSize());
|
||||||
|
jsonData += jsonLineFromInt("PSRAMFree", ESP.getFreePsram(), true);
|
||||||
|
|
||||||
jsonData += "}";
|
jsonData += "}";
|
||||||
server.send(200,"application/json", jsonData);
|
server.send(200,"application/json", jsonData);
|
||||||
|
@ -247,7 +267,7 @@ void handle_saveDeviceCfg(){
|
||||||
}
|
}
|
||||||
if (server.hasArg(PREF_APRS_FREQ)){
|
if (server.hasArg(PREF_APRS_FREQ)){
|
||||||
preferences.putDouble(PREF_APRS_FREQ, server.arg(PREF_APRS_FREQ).toDouble());
|
preferences.putDouble(PREF_APRS_FREQ, server.arg(PREF_APRS_FREQ).toDouble());
|
||||||
}
|
}
|
||||||
if (server.hasArg(PREF_APRS_MODE)){
|
if (server.hasArg(PREF_APRS_MODE)){
|
||||||
preferences.putInt(PREF_APRS_MODE, server.arg(PREF_APRS_MODE).toInt());
|
preferences.putInt(PREF_APRS_MODE, server.arg(PREF_APRS_MODE).toInt());
|
||||||
}
|
}
|
||||||
|
@ -269,13 +289,14 @@ void handle_saveDeviceCfg(){
|
||||||
server.on("/scan_wifi", handle_ScanWifi);
|
server.on("/scan_wifi", handle_ScanWifi);
|
||||||
server.on("/save_wifi_cfg", handle_SaveWifiCfg);
|
server.on("/save_wifi_cfg", handle_SaveWifiCfg);
|
||||||
server.on("/reboot", handle_Reboot);
|
server.on("/reboot", handle_Reboot);
|
||||||
|
server.on("/shutdown", handle_Shutdown);
|
||||||
server.on("/cfg", handle_Cfg);
|
server.on("/cfg", handle_Cfg);
|
||||||
server.on("/received_list", handle_ReceivedList);
|
server.on("/received_list", handle_ReceivedList);
|
||||||
server.on("/save_aprs_cfg", handle_SaveAPRSCfg);
|
server.on("/save_aprs_cfg", handle_SaveAPRSCfg);
|
||||||
server.on("/save_device_cfg", handle_saveDeviceCfg);
|
server.on("/save_device_cfg", handle_saveDeviceCfg);
|
||||||
server.on("/restore", handle_Restore);
|
server.on("/restore", handle_Restore);
|
||||||
server.on("/update", HTTP_POST, []() {
|
server.on("/update", HTTP_POST, []() {
|
||||||
syslog_log(LOG_WARNING, String("Update finished. Status: ") + (Update.hasError() ? "Ok" : "Error"));
|
syslog_log(LOG_WARNING, String("Update finished. Status: ") + (!Update.hasError() ? "Ok" : "Error"));
|
||||||
server.sendHeader("Connection", "close");
|
server.sendHeader("Connection", "close");
|
||||||
server.send(200, "text/plain", (Update.hasError()) ? "FAIL" : "OK");
|
server.send(200, "text/plain", (Update.hasError()) ? "FAIL" : "OK");
|
||||||
delay(500);
|
delay(500);
|
||||||
|
@ -359,6 +380,7 @@ void handle_saveDeviceCfg(){
|
||||||
#ifdef KISS_PROTOCOL
|
#ifdef KISS_PROTOCOL
|
||||||
tncServer.begin();
|
tncServer.begin();
|
||||||
#endif
|
#endif
|
||||||
|
gpsServer.begin();
|
||||||
if (MDNS.begin(webServerCfg->callsign.c_str())) {
|
if (MDNS.begin(webServerCfg->callsign.c_str())) {
|
||||||
MDNS.setInstanceName(webServerCfg->callsign + " LoRa APRS TNC ");
|
MDNS.setInstanceName(webServerCfg->callsign + " LoRa APRS TNC ");
|
||||||
MDNS.addService("http", "tcp", 80);
|
MDNS.addService("http", "tcp", 80);
|
||||||
|
|
|
@ -0,0 +1,64 @@
|
||||||
|
//
|
||||||
|
// Created by Admin on 11.06.2021.
|
||||||
|
//
|
||||||
|
|
||||||
|
#ifdef ENABLE_WIFI
|
||||||
|
|
||||||
|
#include <wifi_clients.h>
|
||||||
|
|
||||||
|
#include "wifi_clients.h"
|
||||||
|
|
||||||
|
void iterateWifiClients(f_connectedClientCallback_t callback, const String *data, WiFiClient * wifiClients[], int maxWifiClients){
|
||||||
|
for (int i=0; i < maxWifiClients; i++) {
|
||||||
|
auto client = wifiClients[i];
|
||||||
|
if (client != nullptr) {
|
||||||
|
if (client->connected()) {
|
||||||
|
callback(client, i, data);
|
||||||
|
} else {
|
||||||
|
#ifdef ENABLE_WIFI_CLIENT_DEBUG
|
||||||
|
Serial.println(String("Disconnected client ") + client->remoteIP().toString() + ":" + client->remotePort());
|
||||||
|
#endif
|
||||||
|
delete client;
|
||||||
|
wifiClients[i] = nullptr;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void check_for_new_clients(WiFiServer *wiFiServer, WiFiClient *wifiClients[], int maxWifiClients) {
|
||||||
|
WiFiClient new_client = wiFiServer->available();
|
||||||
|
if (new_client.connected()){
|
||||||
|
bool new_client_handled = false;
|
||||||
|
for (int i=0; i < maxWifiClients; i++) {
|
||||||
|
auto client = wifiClients[i];
|
||||||
|
if (client == nullptr) {
|
||||||
|
client = new WiFiClient(new_client);
|
||||||
|
wifiClients[i] = client;
|
||||||
|
new_client_handled = true;
|
||||||
|
#ifdef ENABLE_WIFI_CLIENT_DEBUG
|
||||||
|
Serial.println(String("New client #") +String(i) + ": " + client->remoteIP().toString() + ":" + client->remotePort());
|
||||||
|
#endif
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#ifdef ENABLE_WIFI_CLIENT_DEBUG
|
||||||
|
for (int i = 0; i < maxWifiClients; ++i) {
|
||||||
|
auto client = clients[i];
|
||||||
|
|
||||||
|
if (client != nullptr){
|
||||||
|
Serial.println(String("Client #") +String(i) + ": " + client->remoteIP().toString() + ":" + client->remotePort());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
if (!new_client_handled){
|
||||||
|
#ifdef ENABLE_WIFI_CLIENT_DEBUG
|
||||||
|
Serial.println(String("Refusing client "));
|
||||||
|
#endif
|
||||||
|
new_client.stop();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
|
@ -1,6 +1,6 @@
|
||||||
FILENAME_BUILDNO = '.pio/versioning'
|
FILENAME_BUILDNO = '.pio/versioning'
|
||||||
FILENAME_VERSION_H = 'include/version.h'
|
FILENAME_VERSION_H = 'include/version.h'
|
||||||
version = 'v0.3.1.1.'
|
version = 'v0.4.0.'
|
||||||
|
|
||||||
import datetime
|
import datetime
|
||||||
from subprocess import *
|
from subprocess import *
|
||||||
|
|
Loading…
Reference in New Issue