kopia lustrzana https://github.com/PiInTheSky/lora-gateway
V1.10.2: Changes to Sondehub upload to make it more robust
rodzic
9fc3719bbb
commit
648b73fb94
|
@ -296,6 +296,12 @@ Many thanks to David Brooke for coding this feature and the AFC.
|
||||||
Change History
|
Change History
|
||||||
==============
|
==============
|
||||||
|
|
||||||
|
## 24/8/2023 - V1.10.2
|
||||||
|
|
||||||
|
UKHAS Telemetry is CRC16 checked before being used/uploaded, in addition to the existing LoRa CRC check
|
||||||
|
Separation of new incoming telemetry and that already being uploaded to Sondehub
|
||||||
|
Added parsing check on UKHAS telemetry before uploading to Sondehub
|
||||||
|
|
||||||
## 13/8/2023 - V1.10.1
|
## 13/8/2023 - V1.10.1
|
||||||
|
|
||||||
Sondehub upload: For errors, log return code, return text and uploaded JSON to errors.txt
|
Sondehub upload: For errors, log return code, return text and uploaded JSON to errors.txt
|
||||||
|
|
85
gateway.c
85
gateway.c
|
@ -45,7 +45,7 @@
|
||||||
#include "udpclient.h"
|
#include "udpclient.h"
|
||||||
#include "lifo_buffer.h"
|
#include "lifo_buffer.h"
|
||||||
|
|
||||||
#define VERSION "V1.10.1"
|
#define VERSION "V1.10.2"
|
||||||
bool run = TRUE;
|
bool run = TRUE;
|
||||||
|
|
||||||
// RFM98
|
// RFM98
|
||||||
|
@ -1126,39 +1126,47 @@ int ProcessTelemetryMessage(int Channel, received_t *Received)
|
||||||
{
|
{
|
||||||
struct tm *tm;
|
struct tm *tm;
|
||||||
|
|
||||||
|
tm = localtime( &Received->Metadata.Timestamp );
|
||||||
|
|
||||||
*endmessage = '\0';
|
*endmessage = '\0';
|
||||||
|
|
||||||
LogTelemetryPacket(Channel, startmessage);
|
if (ValidCRC16(startmessage))
|
||||||
|
|
||||||
ProcessLineUKHAS(Channel, startmessage);
|
|
||||||
|
|
||||||
if ((Repeated = (*startmessage == '%')))
|
|
||||||
{
|
{
|
||||||
*startmessage = '$';
|
LogTelemetryPacket(Channel, startmessage);
|
||||||
}
|
|
||||||
|
|
||||||
strcpy(Config.LoRaDevices[Channel].Telemetry, startmessage);
|
ProcessLineUKHAS(Channel, startmessage);
|
||||||
Config.LoRaDevices[Channel].TelemetryCount++;
|
|
||||||
|
if ((Repeated = (*startmessage == '%')))
|
||||||
|
{
|
||||||
|
*startmessage = '$';
|
||||||
|
}
|
||||||
|
|
||||||
if (Config.EnableMQTT)
|
strcpy(Config.LoRaDevices[Channel].Telemetry, startmessage);
|
||||||
{
|
Config.LoRaDevices[Channel].TelemetryCount++;
|
||||||
// Add to MQTT upload queue
|
|
||||||
received_t *queueReceived = malloc(sizeof(received_t));
|
if (Config.EnableMQTT)
|
||||||
if(queueReceived != NULL)
|
{
|
||||||
{
|
// Add to MQTT upload queue
|
||||||
memcpy(queueReceived, Received, sizeof(received_t));
|
received_t *queueReceived = malloc(sizeof(received_t));
|
||||||
/* Push pointer onto upload queue */
|
if(queueReceived != NULL)
|
||||||
lifo_buffer_push(&MQTT_Upload_Buffer, (void *)queueReceived);
|
{
|
||||||
}
|
memcpy(queueReceived, Received, sizeof(received_t));
|
||||||
}
|
/* Push pointer onto upload queue */
|
||||||
|
lifo_buffer_push(&MQTT_Upload_Buffer, (void *)queueReceived);
|
||||||
if (Config.EnableSondehub)
|
}
|
||||||
{
|
}
|
||||||
SetSondehubSentence(Channel, startmessage);
|
|
||||||
|
if (Config.EnableSondehub)
|
||||||
|
{
|
||||||
|
SetSondehubSentence(Channel, startmessage);
|
||||||
|
}
|
||||||
|
|
||||||
|
LogMessage("%02d:%02d:%02d Ch%d: %s%s\n", tm->tm_hour, tm->tm_min, tm->tm_sec, Channel, startmessage, Repeated ? " (repeated)" : "");
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
LogMessage("%02d:%02d:%02d Ch%d: %s\n", tm->tm_hour, tm->tm_min, tm->tm_sec, Channel, "Bad UKHAS CRC");
|
||||||
}
|
}
|
||||||
|
|
||||||
tm = localtime( &Received->Metadata.Timestamp );
|
|
||||||
LogMessage("%02d:%02d:%02d Ch%d: %s%s\n", tm->tm_hour, tm->tm_min, tm->tm_sec, Channel, startmessage, Repeated ? " (repeated)" : "");
|
|
||||||
|
|
||||||
startmessage = endmessage + 1;
|
startmessage = endmessage + 1;
|
||||||
endmessage = strchr( startmessage, '\n' );
|
endmessage = strchr( startmessage, '\n' );
|
||||||
|
@ -2325,15 +2333,20 @@ WINDOW *InitDisplay(void)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
uint16_t
|
int ValidCRC16(char *ptr)
|
||||||
CRC16( unsigned char *ptr )
|
|
||||||
{
|
{
|
||||||
uint16_t CRC;
|
uint16_t CRC;
|
||||||
int j;
|
int j;
|
||||||
|
int Valid;
|
||||||
|
char CRCString[5];
|
||||||
|
|
||||||
|
Valid = 0;
|
||||||
CRC = 0xffff; // Seed
|
CRC = 0xffff; // Seed
|
||||||
|
|
||||||
|
// Skip $'s
|
||||||
|
while (*++ptr == '$');
|
||||||
|
|
||||||
for ( ; *ptr; ptr++ )
|
for ( ; *ptr && (*ptr != '*'); ptr++)
|
||||||
{ // For speed, repeat calculation instead of looping for each bit
|
{ // For speed, repeat calculation instead of looping for each bit
|
||||||
CRC ^= ( ( ( unsigned int ) *ptr ) << 8 );
|
CRC ^= ( ( ( unsigned int ) *ptr ) << 8 );
|
||||||
for ( j = 0; j < 8; j++ )
|
for ( j = 0; j < 8; j++ )
|
||||||
|
@ -2345,7 +2358,15 @@ CRC16( unsigned char *ptr )
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return CRC;
|
if (*ptr == '*')
|
||||||
|
{
|
||||||
|
// CRC follows
|
||||||
|
sprintf(CRCString, "%04X", CRC);
|
||||||
|
|
||||||
|
Valid = memcmp(ptr+1, CRCString, 4) == 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
return Valid;
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
|
|
|
@ -12,6 +12,7 @@ void LogError(int ErrorCode, char *Message1, char *Message2);
|
||||||
void LogMessage( const char *format, ... );
|
void LogMessage( const char *format, ... );
|
||||||
void ChannelPrintf( int Channel, int row, int column, const char *format,
|
void ChannelPrintf( int Channel, int row, int column, const char *format,
|
||||||
... );
|
... );
|
||||||
|
int ValidCRC16(char *ptr);
|
||||||
void displayChannel (int Channel);
|
void displayChannel (int Channel);
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
79
sondehub.c
79
sondehub.c
|
@ -24,25 +24,33 @@
|
||||||
#include "gateway.h"
|
#include "gateway.h"
|
||||||
#include "sondehub.h"
|
#include "sondehub.h"
|
||||||
|
|
||||||
struct TPayload SondehubPayloads[2];
|
pthread_mutex_t crit = PTHREAD_MUTEX_INITIALIZER; // To protect IncomingSondehubPayloads
|
||||||
|
|
||||||
|
struct TPayload IncomingSondehubPayloads[2];
|
||||||
|
struct TPayload ActiveSondehubPayloads[2];
|
||||||
|
|
||||||
void SetSondehubSentence(int Channel, char *tmp)
|
void SetSondehubSentence(int Channel, char *tmp)
|
||||||
{
|
{
|
||||||
sscanf(tmp + 2, "%31[^,],%u,%8[^,],%lf,%lf,%d",
|
pthread_mutex_lock(&crit); // lock the critical section
|
||||||
SondehubPayloads[Channel].Payload,
|
|
||||||
&SondehubPayloads[Channel].Counter,
|
|
||||||
SondehubPayloads[Channel].Time,
|
|
||||||
&SondehubPayloads[Channel].Latitude,
|
|
||||||
&SondehubPayloads[Channel].Longitude,
|
|
||||||
&SondehubPayloads[Channel].Altitude);
|
|
||||||
|
|
||||||
SondehubPayloads[Channel].PacketSNR = Config.LoRaDevices[Channel].PacketSNR;
|
if (sscanf(tmp + 2, "%31[^,],%u,%8[^,],%lf,%lf,%d",
|
||||||
SondehubPayloads[Channel].PacketRSSI = Config.LoRaDevices[Channel].PacketRSSI;
|
IncomingSondehubPayloads[Channel].Payload,
|
||||||
SondehubPayloads[Channel].Frequency = Config.LoRaDevices[Channel].Frequency + Config.LoRaDevices[Channel].FrequencyOffset;
|
&IncomingSondehubPayloads[Channel].Counter,
|
||||||
|
IncomingSondehubPayloads[Channel].Time,
|
||||||
|
&IncomingSondehubPayloads[Channel].Latitude,
|
||||||
|
&IncomingSondehubPayloads[Channel].Longitude,
|
||||||
|
&IncomingSondehubPayloads[Channel].Altitude) == 6)
|
||||||
|
{
|
||||||
|
IncomingSondehubPayloads[Channel].PacketSNR = Config.LoRaDevices[Channel].PacketSNR;
|
||||||
|
IncomingSondehubPayloads[Channel].PacketRSSI = Config.LoRaDevices[Channel].PacketRSSI;
|
||||||
|
IncomingSondehubPayloads[Channel].Frequency = Config.LoRaDevices[Channel].Frequency + Config.LoRaDevices[Channel].FrequencyOffset;
|
||||||
|
|
||||||
strcpy(SondehubPayloads[Channel].Telemetry, tmp);
|
strcpy(IncomingSondehubPayloads[Channel].Telemetry, tmp);
|
||||||
|
|
||||||
SondehubPayloads[Channel].InUse = (SondehubPayloads[Channel].Latitude != 0) && (SondehubPayloads[Channel].Longitude != 0);
|
IncomingSondehubPayloads[Channel].InUse = (IncomingSondehubPayloads[Channel].Latitude != 0) && (IncomingSondehubPayloads[Channel].Longitude != 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
pthread_mutex_unlock(&crit); // unlock once you are done
|
||||||
}
|
}
|
||||||
|
|
||||||
size_t sondehub_write_data( void *buffer, size_t size, size_t nmemb, void *userp )
|
size_t sondehub_write_data( void *buffer, size_t size, size_t nmemb, void *userp )
|
||||||
|
@ -108,7 +116,9 @@ int UploadJSONToServer(char *url, char *json)
|
||||||
else if (http_resp == 400)
|
else if (http_resp == 400)
|
||||||
{
|
{
|
||||||
LogMessage("400 response to %s\n", json);
|
LogMessage("400 response to %s\n", json);
|
||||||
result = true;
|
LogError(http_resp, "JSON: ", json);
|
||||||
|
LogError(http_resp, "RESP: ", curl_error);
|
||||||
|
result = true; // Don't retry - this failed due to the uploaded JSON containing something that the server rejected
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
@ -260,7 +270,6 @@ void BuildPayloadTime(char *Result, char *TimeInSentence, struct tm *tm)
|
||||||
|
|
||||||
int UploadSondehubPosition(int Channel)
|
int UploadSondehubPosition(int Channel)
|
||||||
{
|
{
|
||||||
char url[200];
|
|
||||||
char json[1000], now[32], payload_time[32], ExtractedFields[256], uploader_position[256];
|
char json[1000], now[32], payload_time[32], ExtractedFields[256], uploader_position[256];
|
||||||
time_t rawtime;
|
time_t rawtime;
|
||||||
struct tm *tm;
|
struct tm *tm;
|
||||||
|
@ -270,10 +279,10 @@ int UploadSondehubPosition(int Channel)
|
||||||
tm = gmtime(&rawtime);
|
tm = gmtime(&rawtime);
|
||||||
strftime(now, sizeof(now), "%Y-%0m-%0dT%H:%M:%SZ", tm);
|
strftime(now, sizeof(now), "%Y-%0m-%0dT%H:%M:%SZ", tm);
|
||||||
|
|
||||||
BuildPayloadTime(payload_time, SondehubPayloads[Channel].Time, tm);
|
BuildPayloadTime(payload_time, ActiveSondehubPayloads[Channel].Time, tm);
|
||||||
|
|
||||||
// Find field list and extract fields
|
// Find field list and extract fields
|
||||||
ExtractFields(SondehubPayloads[Channel].Telemetry, ExtractedFields);
|
ExtractFields(ActiveSondehubPayloads[Channel].Telemetry, ExtractedFields);
|
||||||
|
|
||||||
if ((Config.latitude >= -90) && (Config.latitude <= 90) && (Config.longitude >= -180) && (Config.longitude <= 180))
|
if ((Config.latitude >= -90) && (Config.latitude <= 90) && (Config.longitude >= -180) && (Config.longitude <= 180))
|
||||||
{
|
{
|
||||||
|
@ -310,20 +319,17 @@ int UploadSondehubPosition(int Channel)
|
||||||
"\"uploader_antenna\": \"%s\""
|
"\"uploader_antenna\": \"%s\""
|
||||||
"}]",
|
"}]",
|
||||||
Config.Version, Config.Tracker, now,
|
Config.Version, Config.Tracker, now,
|
||||||
SondehubPayloads[Channel].Payload, payload_time,
|
ActiveSondehubPayloads[Channel].Payload, payload_time,
|
||||||
SondehubPayloads[Channel].Latitude, SondehubPayloads[Channel].Longitude, SondehubPayloads[Channel].Altitude,
|
ActiveSondehubPayloads[Channel].Latitude, ActiveSondehubPayloads[Channel].Longitude, ActiveSondehubPayloads[Channel].Altitude,
|
||||||
SondehubPayloads[Channel].Frequency,
|
ActiveSondehubPayloads[Channel].Frequency,
|
||||||
Config.LoRaDevices[Channel].SpeedMode,
|
Config.LoRaDevices[Channel].SpeedMode,
|
||||||
SondehubPayloads[Channel].PacketSNR, SondehubPayloads[Channel].PacketRSSI,
|
ActiveSondehubPayloads[Channel].PacketSNR, ActiveSondehubPayloads[Channel].PacketRSSI,
|
||||||
SondehubPayloads[Channel].Telemetry,
|
ActiveSondehubPayloads[Channel].Telemetry,
|
||||||
ExtractedFields,
|
ExtractedFields,
|
||||||
uploader_position,
|
uploader_position,
|
||||||
Config.antenna);
|
Config.antenna);
|
||||||
|
|
||||||
// Set the URL that is about to receive our PUT
|
return UploadJSONToServer("https://api.v2.sondehub.org/amateur/telemetry", json);
|
||||||
strcpy(url, "https://api.v2.sondehub.org/amateur/telemetry");
|
|
||||||
|
|
||||||
return UploadJSONToServer(url, json);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
char *SanitiseCallsignForMQTT(char *Callsign)
|
char *SanitiseCallsignForMQTT(char *Callsign)
|
||||||
|
@ -346,7 +352,6 @@ char *SanitiseCallsignForMQTT(char *Callsign)
|
||||||
|
|
||||||
int UploadListenerToSondehub(void)
|
int UploadListenerToSondehub(void)
|
||||||
{
|
{
|
||||||
char url[200];
|
|
||||||
char json[1000], now[32], doc_time[32];
|
char json[1000], now[32], doc_time[32];
|
||||||
time_t rawtime;
|
time_t rawtime;
|
||||||
struct tm *tm, *doc_tm;
|
struct tm *tm, *doc_tm;
|
||||||
|
@ -376,9 +381,7 @@ int UploadListenerToSondehub(void)
|
||||||
Config.latitude, Config.longitude, Config.altitude,
|
Config.latitude, Config.longitude, Config.altitude,
|
||||||
Config.radio, Config.antenna);
|
Config.radio, Config.antenna);
|
||||||
|
|
||||||
strcpy(url, "https://api.v2.sondehub.org/amateur/listeners");
|
return UploadJSONToServer("https://api.v2.sondehub.org/amateur/listeners", json);
|
||||||
|
|
||||||
return UploadJSONToServer(url, json);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -391,11 +394,23 @@ void *SondehubLoop( void *vars )
|
||||||
|
|
||||||
for (Channel=0; Channel<=1; Channel++)
|
for (Channel=0; Channel<=1; Channel++)
|
||||||
{
|
{
|
||||||
if (SondehubPayloads[Channel].InUse)
|
// Copy new incoming payload, if there is one
|
||||||
|
if (IncomingSondehubPayloads[Channel].InUse)
|
||||||
|
{
|
||||||
|
pthread_mutex_lock(&crit); // lock the critical section
|
||||||
|
|
||||||
|
// copy from incoming to active
|
||||||
|
memcpy(&ActiveSondehubPayloads[Channel], &IncomingSondehubPayloads[Channel], sizeof(struct TPayload));
|
||||||
|
|
||||||
|
pthread_mutex_unlock(&crit); // unlock once you are done
|
||||||
|
}
|
||||||
|
|
||||||
|
// Try to upload active payload, if there is one
|
||||||
|
if (ActiveSondehubPayloads[Channel].InUse)
|
||||||
{
|
{
|
||||||
if (UploadSondehubPosition(Channel))
|
if (UploadSondehubPosition(Channel))
|
||||||
{
|
{
|
||||||
SondehubPayloads[Channel].InUse = 0;
|
ActiveSondehubPayloads[Channel].InUse = 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Ładowanie…
Reference in New Issue