v0.3: merging some changes (axupd support, partial/readonly config web page)

pull/4/head
Hans P. Reiser 2019-04-15 21:02:50 +02:00
rodzic 69cb203a4f
commit 791a6bdb75
7 zmienionych plików z 161 dodań i 59 usunięć

Wyświetl plik

@ -9,8 +9,6 @@
#include <Sonde.h>
#include <Scanner.h>
#include <aprs.h>
//#include <RS41.h>
//#include <DFM.h>
#define LORA_LED 9
@ -28,8 +26,11 @@ int e;
AsyncWebServer server(80);
const char * udpAddress = "192.168.179.21";
const int udpPort = 9002;
#define LOCALUDPPORT 9002
// moved to sonde.config
//const char * udpAddress = "192.168.42.20";
//const int udpPort = 9002;
boolean connected = false;
WiFiUDP udp;
@ -268,11 +269,85 @@ const char *createStatusForm() {
return message;
}
///////////////////// Config form
struct st_configitems {
const char *label;
int type; // 0: numeric; i>0 string of length i; -1: separator; -2: type selector
void *data;
};
#define N_CONFIG 16
struct st_configitems config_list[N_CONFIG] = {
{"Call", 8, sonde.config.call},
{"Passcode", 8, sonde.config.passcode},
{"---", -1, NULL},
{"AXUDP active", -3, &sonde.config.udpfeed.active},
{"AXUDP Host", 63, sonde.config.udpfeed.host},
{"AXUDP Port", 0, &sonde.config.udpfeed.port},
{"DFM ID Format", -2, &sonde.config.udpfeed.idformat},
{"Rate limit", 0, &sonde.config.udpfeed.highrate},
{"---", -1, NULL},
{"APRS TCP active", -3, &sonde.config.tcpfeed.active},
{"ARPS TCP Host", 63, sonde.config.tcpfeed.host},
{"APRS TCP Port", 0, &sonde.config.tcpfeed.port},
{"DFM ID Format", -2, &sonde.config.tcpfeed.idformat},
{"Rate limit", 0, &sonde.config.tcpfeed.highrate},
{"---", -1, NULL},
{"Spectrum noise floor", 0, &sonde.config.noisefloor}
};
void addConfigStringEntry(char *ptr, int idx, const char *label, int len, char *field) {
sprintf(ptr+strlen(ptr), "<tr><td>%s</td><td><input name=\"CFG%d\" type=\"text\" value=\"%s\"/></td></tr>\n",
label, idx, field);
}
void addConfigNumEntry(char *ptr, int idx, const char *label, int *value) {
sprintf(ptr+strlen(ptr), "<tr><td>%s</td><td><input name=\"CFG%d\" type=\"text\" value=\"%d\"/></td></tr>\n",
label, idx, *value);
}
void addConfigTypeEntry(char *ptr, int idx, const char *label, int *value) {
// TODO
}
void addConfigOnOffEntry(char *ptr, int idx, const char *label, int *value) {
// TODO
}
void addConfigSeparatorEntry(char *ptr) {
strcat(ptr, "<tr><td colspan=\"2\" class=\"divider\"><hr /></td></tr>\n");
}
const char *createConfigForm() {
char *ptr = message;
char tmp[4];
strcpy(ptr,"<html><head><link rel=\"stylesheet\" type=\"text/css\" href=\"style.css\"></head><body><form action=\"config.html\" method=\"post\"><table><tr><th>Option</th><th>Value</th></tr>");
for(int i=0; i<N_CONFIG; i++) {
switch(config_list[i].type) {
case -3: // in/offt
addConfigOnOffEntry(ptr, i, config_list[i].label, (int *)config_list[i].data);
break;
case -2: // DFM format
addConfigTypeEntry(ptr, i, config_list[i].label, (int *)config_list[i].data);
break;
case -1:
addConfigSeparatorEntry(ptr);
break;
case 0:
addConfigNumEntry(ptr, i, config_list[i].label, (int *)config_list[i].data);
break;
default:
addConfigStringEntry(ptr, i, config_list[i].label, config_list[i].type, (char *)config_list[i].data);
break;
}
}
strcat(ptr,"</table><input type=\"submit\" value=\"Update not yet implemented\"></input></form></body></html>");
return message;
}
const char* PARAM_MESSAGE = "message";
void SetupAsyncServer() {
// Route for root / web page
server.on("/", HTTP_GET, [](AsyncWebServerRequest *request){
request->send(200, "text/plain", "Hello, world");
request->send(SPIFFS, "/index.html", String(), false, processor);
});
server.on("/index.html", HTTP_GET, [](AsyncWebServerRequest *request){
@ -299,6 +374,10 @@ void SetupAsyncServer() {
request->send(200, "text/html", createWIFIForm());
});
server.on("/config.html", HTTP_GET, [](AsyncWebServerRequest *request){
request->send(200, "text/html", createConfigForm());
});
server.on("/status.html", HTTP_GET, [](AsyncWebServerRequest *request){
request->send(200, "text/html", createStatusForm());
});
@ -308,29 +387,11 @@ void SetupAsyncServer() {
request->send(SPIFFS, "/style.css", "text/css");
});
// Route to set GPIO to HIGH
server.on("/on", HTTP_GET, [](AsyncWebServerRequest *request){
digitalWrite(ledPin, HIGH);
request->send(SPIFFS, "/index.html", String(), false, processor);
});
// Route to set GPIO to HIGH
server.on("/test.php", HTTP_POST, [](AsyncWebServerRequest *request){
//digitalWrite(ledPin, HIGH);
request->send(SPIFFS, "/index.html", String(), false, processor);
});
// Route to set GPIO to LOW
server.on("/off", HTTP_GET, [](AsyncWebServerRequest *request){
digitalWrite(ledPin, LOW);
request->send(SPIFFS, "/index.html", String(), false, processor);
});
// Send a POST request to <IP>/post with a form field message set to <message>
server.on("/post", HTTP_POST, [](AsyncWebServerRequest *request){
handleQRGPost(request);
request->send(200, "text/plain", "Hello, POST done");
});
// Start server
server.begin();
@ -422,7 +483,9 @@ void setup()
Serial.println(f);
#endif
sx1278.setLNAGain(0); //-48);
//sx1278.setLNAGain(-48);
sx1278.setLNAGain(0);
int gain = sx1278.getLNAGain();
Serial.print("RX LNA Gain is ");
Serial.println(gain);
@ -489,9 +552,9 @@ void loopDecoder() {
SondeInfo *s = sonde.si();
char raw[201];
const char *str = aprs_senddata(s->lat, s->lon, s->hei, s->hs, s->dir, s->vs, sondeTypeStr[s->type], s->id, "TE0ST", "EO");
int rawlen = aprsstr_mon2raw(str, raw, MAXLEN);
int rawlen = aprsstr_mon2raw(str, raw, APRS_MAXLEN);
Serial.print("Sending: "); Serial.println(raw);
udp.beginPacket(udpAddress,udpPort);
udp.beginPacket(sonde.config.udpfeed.host,sonde.config.udpfeed.port);
udp.write((const uint8_t *)raw,rawlen);
udp.endPacket();
}
@ -572,7 +635,7 @@ void WiFiEvent(WiFiEvent_t event){
Serial.println(WiFi.localIP());
//initializes the UDP state
//This initializes the transfer buffer
udp.begin(WiFi.localIP(),udpPort);
udp.begin(WiFi.localIP(),LOCALUDPPORT);
connected = true;
break;
case SYSTEM_EVENT_STA_DISCONNECTED:
@ -582,6 +645,7 @@ void WiFiEvent(WiFiEvent_t event){
}
}
static char* _scan[2]={"/","\\"};
void loopWifiScan() {
u8x8.setFont(u8x8_font_chroma48medium8_r);
@ -623,12 +687,14 @@ void loopWifiScan() {
Serial.print(".");
u8x8.drawString(15,7,_scan[cnt&1]);
cnt++;
#if 0
if(cnt==4) {
WiFi.disconnect(true); // retry, for my buggy FritzBox
WiFi.onEvent(WiFiEvent);
WiFi.begin(id, pw);
}
if(cnt==10) {
#endif
if(cnt==15) {
WiFi.disconnect(true);
delay(1000);
WiFi.softAP(networks[0].id.c_str(),networks[0].pw.c_str());
@ -666,11 +732,7 @@ void loop() {
case ST_SPECTRUM: loopSpectrum(); break;
case ST_WIFISCAN: loopWifiScan(); break;
}
#if 0
//wifiloop(NULL);
//e = dfm.receiveFrame();
//e = rs41.receiveFrame();
delay(1000);
#if 1
int rssi = sx1278.getRSSI();
Serial.print(" RSSI: ");
Serial.print(rssi);
@ -678,6 +740,5 @@ void loop() {
int gain = sx1278.getLNAGain();
Serial.print(" LNA Gain: "),
Serial.println(gain);
#endif
#endif
}

Wyświetl plik

@ -18,6 +18,7 @@
<button class="tablinks" onclick="selTab(event,'QRG')" id="defaultTab">QRG</button>
<button class="tablinks" onclick="selTab(event,'WIFI')">WLAN</button>
<button class="tablinks" onclick="selTab(event,'Data')">Data</button>
<button class="tablinks" onclick="selTab(event,'Config')">Config</button>
<button class="tablinks" onclick="selTab(event,'About')">About</button>
</div>
@ -36,6 +37,11 @@
<iframe src="status.html" style="border:none;" width="100%%" height="100%%"></iframe>
</div>
<div id="Config" class="tabcontent">
<h3>Config</h3>
<iframe src="config.html" style="border:none;" width="100%%" height="100%%"></iframe>
</div>
<div id="About" class="tabcontent">
<h3>About</h3>
RDZSonde

Wyświetl plik

@ -357,7 +357,7 @@ static void posrs41(const byte b[], uint32_t b_len, uint32_t p)
void RS41::decode41(byte *data, int MAXLEN)
void RS41::decode41(byte *data, int maxlen)
{
char buf[128];
@ -369,10 +369,10 @@ void RS41::decode41(byte *data, int MAXLEN)
Serial.print(corr);
Serial.println();
int p = 57; // 8 byte header, 48 byte RS
while(p<MAXLEN) { /* why 555? */
while(p<maxlen) { /* why 555? */
uint8_t typ = data[p++];
uint32_t len = data[p++]+2UL;
if(p+len>MAXLEN) break;
if(p+len>maxlen) break;
#if 1
// DEBUG OUTPUT
@ -459,20 +459,20 @@ static uint8_t scramble[64] = {150U,131U,62U,81U,177U,73U,8U,152U,50U,5U,89U,
static byte data[800];
#define MAXLEN (320)
#define RS41MAXLEN (320)
int RS41::receiveFrame() {
//sx1278.setPayloadLength(518-8); // Expect 320-8 bytes or 518-8 bytes (8 byte header)
sx1278.setPayloadLength(MAXLEN-8); // Expect 320-8 bytes or 518-8 bytes (8 byte header)
sx1278.setPayloadLength(RS41MAXLEN-8); // Expect 320-8 bytes or 518-8 bytes (8 byte header)
sx1278.writeRegister(REG_OP_MODE, FSK_RX_MODE);
int e = sx1278.receivePacketTimeout(1000, data+8);
if(e) { Serial.println("TIMEOUT"); return RX_TIMEOUT; } //if timeout... return 1
for(int i=0; i<MAXLEN; i++) { data[i] = reverse(data[i]); }
for(int i=0; i<RS41MAXLEN; i++) { data[i] = reverse(data[i]); }
//printRaw(data, MAXLEN);
for(int i=0; i<MAXLEN; i++) { data[i] = data[i] ^ scramble[i&0x3F]; }
for(int i=0; i<RS41MAXLEN; i++) { data[i] = data[i] ^ scramble[i&0x3F]; }
//printRaw(data, MAXLEN);
decode41(data, MAXLEN);
decode41(data, RS41MAXLEN);
return RX_OK;
}

Wyświetl plik

@ -47,6 +47,23 @@ static uint8_t empty_tile1[8]={0x00, 0xF0, 0x88, 0x48, 0x28, 0xF0, 0x00, 0x00};
static uint8_t empty_tile2[8]={0x00, 0x11, 0x02, 0x02, 0x02, 0x01, 0x00, 0x00};
static uint8_t ap_tile[8]={0x00,0x04,0x22,0x92, 0x92, 0x22, 0x04, 0x00};
Sonde::Sonde() {
config.noisefloor = -130;
strcpy(config.call,"NOCALL");
strcpy(config.passcode, "---");
config.udpfeed.active = 1;
config.udpfeed.type = 0;
strcpy(config.udpfeed.host, "192.168.42.20");
config.udpfeed.port = 9002;
config.udpfeed.highrate = 1;
config.udpfeed.idformat = ID_DFMGRAW;
config.tcpfeed.active = 0;
config.tcpfeed.type = 1;
strcpy(config.tcpfeed.host, "radiosondy.info");
config.tcpfeed.port = 12345;
config.tcpfeed.highrate = 10;
config.tcpfeed.idformat = ID_DFMDXL;
}
void Sonde::setIP(const char *ip, bool AP) {
memset(myIP_tiles, 0, 11*8);
@ -153,11 +170,11 @@ void Sonde::updateDisplayPos2() {
u8x8.drawString(10,4," ");
return;
}
snprintf(buf, 16, si()->hei>999?"%5.0fm":"%3.1fm", si()->hei);
snprintf(buf, 16, si()->hei>999?" %5.0fm":" %3.1fm", si()->hei);
u8x8.drawString((10+6-strlen(buf)),2,buf);
snprintf(buf, 16, si()->hs>99?"%3.0f":"%2.1f", si()->hs);
snprintf(buf, 16, si()->hs>99?" %3.0f":" %2.1f", si()->hs);
u8x8.drawString((10+4-strlen(buf)),3,buf);
snprintf(buf, 16, "%+2.1f", si()->vs);
snprintf(buf, 16, " %+2.1f", si()->vs);
u8x8.drawString((10+4-strlen(buf)),4,buf);
u8x8.drawTile(14,3,2,kmh_tiles);
u8x8.drawTile(14,4,2,ms_tiles);

Wyświetl plik

@ -2,6 +2,8 @@
#ifndef Sonde_h
#define Sonde_H
#include "aprs.h"
// RX_TIMEOUT: no header detected
// RX_ERROR: header detected, but data not decoded (crc error, etc.)
// RX_OK: header and data ok
@ -10,6 +12,15 @@ enum RxResult { RX_OK, RX_TIMEOUT, RX_ERROR };
enum SondeType { STYPE_DFM06, STYPE_DFM09, STYPE_RS41 };
extern const char *sondeTypeStr[5];
typedef struct st_rdzconfig {
int noisefloor; // for spectrum display
char call[9];
char passcode[9];
// for now, one feed for each type is enough, but might get extended to more?
struct st_feedinfo udpfeed; // target for AXUDP messages
struct st_feedinfo tcpfeed; // target for APRS-IS TCP connections
} RDZConfig;
typedef struct st_sondeinfo {
// receiver configuration
bool active;
@ -39,10 +50,13 @@ class Sonde
{
private:
public:
RDZConfig config;
int currentSonde = 0;
int nSonde;
SondeInfo sondeList[MAXSONDE+1];
Sonde();
void clearSonde();
void addSonde(float frequency, SondeType type, int active);
void nextConfig();

Wyświetl plik

@ -45,7 +45,7 @@ void aprsstr_append(char *b, const char *data)
{
int blen=strlen(b);
int len=strlen(data);
if(blen+len>MAXLEN) len=MAXLEN-blen;
if(blen+len>APRS_MAXLEN) len=APRS_MAXLEN-blen;
strncat(b, data, len);
}
@ -233,26 +233,26 @@ char * aprs_senddata(float lat, float lon, float hei, float speed, float dir, fl
int i = strlen(b);
int lati = abs((int)lat);
int latm = (fabs(lat)-lati)*6000;
snprintf(b+i, MAXLEN-i, "%02d%02d.%02d%c%c", lati, latm/100, latm%100, lat<0?'S':'N', sym[0]);
snprintf(b+i, APRS_MAXLEN-i, "%02d%02d.%02d%c%c", lati, latm/100, latm%100, lat<0?'S':'N', sym[0]);
i = strlen(b);
int loni = abs((int)lon);
int lonm = (fabs(lon)-loni)*6000;
snprintf(b+i, MAXLEN-i, "%03d%02d.%02d%c%c", loni, lonm/100, lonm%100, lon<0?'W':'E', sym[1]);
snprintf(b+i, APRS_MAXLEN-i, "%03d%02d.%02d%c%c", loni, lonm/100, lonm%100, lon<0?'W':'E', sym[1]);
#if 1
if(speed>0.5) {
i=strlen(b);
snprintf(b+i, MAXLEN-i, "%03d/%03d", realcard(dir+1.5), realcard(speed*1.0/KNOTS+0.5));
snprintf(b+i, APRS_MAXLEN-i, "%03d/%03d", realcard(dir+1.5), realcard(speed*1.0/KNOTS+0.5));
}
#endif
if(hei>0.5) {
i=strlen(b);
snprintf(b+i, MAXLEN-i, "/A=%06d", realcard(hei*FEET+0.5));
snprintf(b+i, APRS_MAXLEN-i, "/A=%06d", realcard(hei*FEET+0.5));
}
#if 0
int dao=1;
if(dao) {
i=strlen(b);
snprintf(b+i, MAXLEN-i, "!w%c%c!", 33+dao91(lat), 33+dao91(lon));
snprintf(b+i, APRS_MAXLEN-i, "!w%c%c!", 33+dao91(lat), 33+dao91(lon));
}
#endif
const char *comm="&test";
@ -273,11 +273,11 @@ int main(int argc, char *argv[])
float lat=48, lon=10;
while(1) {
const char *str = aprs_senddata(lat, lon, 543, 5, 180, 1.5, "RS41", "TE0ST", "TE1ST", "EO");
int rawlen = aprsstr_mon2raw(str, raw, MAXLEN);
int rawlen = aprsstr_mon2raw(str, raw, APRS_MAXLEN);
sendudp(fd, raw, rawlen);
str = "OE3XKC>APMI06,qAR,OE3XLR:;ER-341109*111111z4803.61NE01532.39E0145.650MHz R15k OE3XPA";
rawlen = aprsstr_mon2raw(str, raw, MAXLEN);
rawlen = aprsstr_mon2raw(str, raw, APRS_MAXLEN);
sendudp(fd, &si, raw, rawlen);
lat += 0.002; lon += 0.01;
sleep(5);

Wyświetl plik

@ -2,17 +2,21 @@
#ifndef _aprs_h
#define _aprs_h
enum IDTYPE { ID_DFMDXL, ID_DFMREAL, ID_DFMAUTO };
enum IDTYPE { ID_DFMDXL, ID_DFMGRAW, ID_DFMAUTO };
typedef struct st_feedinfo {
bool active;
int type; // 0:UDP(axudp), 1:TCP(aprs.fi)
char *host;
char host[64];
int port;
int rate;
int lowrate;
int highrate;
int lowlimit;
int idformat; // 0: dxl 1: real 2: auto
}
#define MAXLEN 201
};
#define APRS_MAXLEN 201
void aprs_gencrctab(void);
int aprsstr_mon2raw(const char *mon, char raw[], int raw_len);
char * aprs_senddata(float lat, float lon, float hei, float speed, float dir, float climb, const char *type, const char *objname, const char *usercall, const char *sym);