V1.8.5 - AFC changes; rename config file from sample if missing

pull/27/head
Dave Akerman 2016-09-27 19:23:41 +00:00
rodzic 7b262838e0
commit 1210ec15cf
11 zmienionych plików z 444 dodań i 474 usunięć

30
*.dpa
Wyświetl plik

@ -1,30 +0,0 @@
tracker=LCARS
EnableHabitat=N
EnableSSDV=N
LogTelemetry=Y
LogPackets=Y
CallingTimeout=60
ServerPort=6004
Latitude=51.950230
Longitude=-2.544500
Antenna=MagMount
JPGFolder=SSDV
EnableDev=N
#NetworkLED=21
#InternetLED=22
#ActivityLED_0=23
#ActivityLED_1=24
frequency_0=434.450000
mode_0=1
#mode_0=1
DIO0_0=6
DIO5_0=5
AFC_0=N
frequency_1=869.850000
mode_1=3
DIO0_1=27
DIO5_1=26
AFC_1=N

Wyświetl plik

@ -226,6 +226,22 @@ Many thanks to David Brooke for coding this feature and the AFC.
Change History Change History
============== ==============
27/09/2016 - V1.8.5
-------------------
New config setting - AFCMaxStep - limits AFC delta to this amount in kHz for each new packet
New config setting - AFCTimeout - Resets AFC changes if no packets received in this period (in seconds)
If gateway.txt missing, and gateway-sample.txt present, rename latter as former
Fixed SSDV upload status marker
Fix to frequency format when retuning after calling mode
Some log display messages now only appear if the feature they describe is in use
15/09/2016 - V1.8.4
-------------------
Fix to handle disabled channel
14/09/2016 - V1.8.3 14/09/2016 - V1.8.3
------------------- -------------------

0
config.c 100755 → 100644
Wyświetl plik

0
config.h 100755 → 100644
Wyświetl plik

229
gateway.c
Wyświetl plik

@ -14,7 +14,7 @@
#include <sys/shm.h> #include <sys/shm.h>
#include <errno.h> #include <errno.h>
#include <stdint.h> #include <stdint.h>
#include <stdarg.h> #include <stdarg.h>
#include <pthread.h> #include <pthread.h>
#include <curses.h> #include <curses.h>
#include <math.h> #include <math.h>
@ -34,7 +34,7 @@
#include "gateway.h" #include "gateway.h"
#include "config.h" #include "config.h"
#define VERSION "V1.8.4" #define VERSION "V1.8.5"
bool run = TRUE; bool run = TRUE;
// RFM98 // RFM98
@ -174,8 +174,6 @@ struct TBinaryPacket {
uint16_t Altitude; uint16_t Altitude;
}; };
const char *Modes[6] = { "Slow", "SSDV", "Repeater", "Turbo", "TurboX", "Calling" };
// Create pipes for inter proces communication // Create pipes for inter proces communication
// GLOBAL AS CALLED FROM INTERRRUPT // GLOBAL AS CALLED FROM INTERRRUPT
int telem_pipe_fd[2]; int telem_pipe_fd[2];
@ -458,32 +456,6 @@ void setLoRaMode( int Channel )
setFrequency( Channel, Config.LoRaDevices[Channel].Frequency); setFrequency( Channel, Config.LoRaDevices[Channel].Frequency);
} }
char *BandwidthString( int Bandwidth )
{
if ( Bandwidth == BANDWIDTH_7K8 )
return "7.8k";
if ( Bandwidth == BANDWIDTH_10K4 )
return "10.4k";
if ( Bandwidth == BANDWIDTH_15K6 )
return "15.6k";
if ( Bandwidth == BANDWIDTH_20K8 )
return "20.8k";
if ( Bandwidth == BANDWIDTH_31K25 )
return "31.25k";
if ( Bandwidth == BANDWIDTH_41K7 )
return "41.7k";
if ( Bandwidth == BANDWIDTH_62K5 )
return "62.5k";
if ( Bandwidth == BANDWIDTH_125K )
return "125k";
if ( Bandwidth == BANDWIDTH_250K )
return "250k";
if ( Bandwidth == BANDWIDTH_500K )
return "500k";
return "??k";
}
int IntToSF(int Value) int IntToSF(int Value)
{ {
return Value << 4; return Value << 4;
@ -595,7 +567,7 @@ startReceiving( int Channel )
void ReTune( int Channel, double FreqShift ) void ReTune( int Channel, double FreqShift )
{ {
setMode( Channel, RF98_MODE_SLEEP ); setMode( Channel, RF98_MODE_SLEEP );
LogMessage( "Retune by %lf kHz\n", FreqShift * 1000 ); LogMessage( "Retune by %.1lfkHz\n", FreqShift * 1000 );
setFrequency( Channel, Config.LoRaDevices[Channel].activeFreq + FreqShift ); setFrequency( Channel, Config.LoRaDevices[Channel].activeFreq + FreqShift );
startReceiving( Channel ); startReceiving( Channel );
} }
@ -673,20 +645,15 @@ void ShowPacketCounts(int Channel)
ChannelPrintf( Channel, 9, 1, "Bad CRC = %d Bad Type = %d", ChannelPrintf( Channel, 9, 1, "Bad CRC = %d Bad Type = %d",
Config.LoRaDevices[Channel].BadCRCCount, Config.LoRaDevices[Channel].BadCRCCount,
Config.LoRaDevices[Channel].UnknownCount ); Config.LoRaDevices[Channel].UnknownCount );
ChannelPrintf( Channel, 6, 16, "SSDV %d ",
Config.LoRaDevices[Channel].SSDVCount );
} }
} }
void void ProcessUploadMessage(int Channel, char *Message)
ProcessUploadMessage( int Channel, char *Message )
{ {
// LogMessage("Ch %d: Uploaded message %s\n", Channel, Message); // LogMessage("Ch %d: Uploaded message %s\n", Channel, Message);
} }
void void ProcessCallingMessage(int Channel, char *Message)
ProcessCallingMessage( int Channel, char *Message )
{ {
char Payload[16]; char Payload[16];
double Frequency; double Frequency;
@ -702,7 +669,7 @@ ProcessCallingMessage( int Channel, char *Message )
&ErrorCoding, &ErrorCoding,
&Bandwidth, &SpreadingFactor, &LowDataRateOptimize ) == 7 ) &Bandwidth, &SpreadingFactor, &LowDataRateOptimize ) == 7 )
{ {
if ( Config.LoRaDevices[Channel].AFC ) if (Config.LoRaDevices[Channel].AFC)
{ {
Frequency += (Config.LoRaDevices[Channel].activeFreq - Config.LoRaDevices[Channel].Frequency); Frequency += (Config.LoRaDevices[Channel].activeFreq - Config.LoRaDevices[Channel].Frequency);
} }
@ -726,15 +693,12 @@ ProcessCallingMessage( int Channel, char *Message )
} }
} }
size_t size_t write_data( void *buffer, size_t size, size_t nmemb, void *userp )
write_data( void *buffer, size_t size, size_t nmemb, void *userp )
{ {
return size * nmemb; return size * nmemb;
} }
void void UploadListenerTelemetry( char *callsign, float gps_lat, float gps_lon, char *antenna )
UploadListenerTelemetry( char *callsign, float gps_lat, float gps_lon,
char *antenna )
{ {
int time_epoch = ( int ) time( NULL ); int time_epoch = ( int ) time( NULL );
if ( Config.EnableHabitat ) if ( Config.EnableHabitat )
@ -821,8 +785,7 @@ UploadListenerTelemetry( char *callsign, float gps_lat, float gps_lon,
} }
void void DoPositionCalcs(Channel)
DoPositionCalcs( Channel )
{ {
unsigned long Now; unsigned long Now;
struct tm tm; struct tm tm;
@ -982,8 +945,7 @@ void ProcessTelemetryMessage( int Channel, char *Message)
} }
} }
static char * static char *decode_callsign( char *callsign, uint32_t code )
decode_callsign( char *callsign, uint32_t code )
{ {
char *c, s; char *c, s;
@ -1216,7 +1178,7 @@ void DIO0_Interrupt( int Channel )
if ( Config.LoRaDevices[Channel].Sending ) if ( Config.LoRaDevices[Channel].Sending )
{ {
Config.LoRaDevices[Channel].Sending = 0; Config.LoRaDevices[Channel].Sending = 0;
LogMessage( "Ch%d: End of Tx\n", Channel ); // LogMessage( "Ch%d: End of Tx\n", Channel );
setLoRaMode( Channel ); setLoRaMode( Channel );
SetDefaultLoRaParameters( Channel ); SetDefaultLoRaParameters( Channel );
@ -1229,11 +1191,8 @@ void DIO0_Interrupt( int Channel )
Bytes = receiveMessage( Channel, Message + 1 ); Bytes = receiveMessage( Channel, Message + 1 );
// hexdump_buffer ("Raw Data", Message, 257);
if ( Bytes > 0 ) if ( Bytes > 0 )
{ {
if ( Config.LoRaDevices[Channel].ActivityLED >= 0 ) if ( Config.LoRaDevices[Channel].ActivityLED >= 0 )
{ {
digitalWrite( Config.LoRaDevices[Channel].ActivityLED, 1 ); digitalWrite( Config.LoRaDevices[Channel].ActivityLED, 1 );
@ -1255,12 +1214,11 @@ void DIO0_Interrupt( int Channel )
} }
else if ( Message[1] == '>' ) else if ( Message[1] == '>' )
{ {
LogMessage( "Flight Controller message %d bytes = %s", Bytes, LogMessage( "Flight Controller message %d bytes = %s\n", Bytes, Message + 1 );
Message + 1 );
} }
else if ( Message[1] == '*' ) else if ( Message[1] == '*' )
{ {
LogMessage( "Uplink Command message %d bytes = %s", Bytes, Message + 1 ); LogMessage( "Uplink Command message %d bytes = %s\n", Bytes, Message + 1 );
} }
else if (((Message[1] & 0x7F) == 0x66) || // SSDV JPG format else if (((Message[1] & 0x7F) == 0x66) || // SSDV JPG format
((Message[1] & 0x7F) == 0x67) || // SSDV other formats ((Message[1] & 0x7F) == 0x67) || // SSDV other formats
@ -1284,13 +1242,16 @@ void DIO0_Interrupt( int Channel )
Config.LoRaDevices[Channel].LastPacketAt = time( NULL ); Config.LoRaDevices[Channel].LastPacketAt = time( NULL );
if ( Config.LoRaDevices[Channel].InCallingMode if (Config.LoRaDevices[Channel].InCallingMode && (Config.CallingTimeout > 0))
&& ( Config.CallingTimeout > 0 ) )
{ {
Config.LoRaDevices[Channel].ReturnToCallingModeAt = Config.LoRaDevices[Channel].ReturnToCallingModeAt = time( NULL ) + Config.CallingTimeout;
time( NULL ) + Config.CallingTimeout;
} }
if (!Config.LoRaDevices[Channel].InCallingMode && (Config.LoRaDevices[Channel].AFCTimeout > 0))
{
Config.LoRaDevices[Channel].ReturnToOriginalFrequencyAt = time(NULL) + Config.LoRaDevices[Channel].AFCTimeout;
}
ShowPacketCounts( Channel ); ShowPacketCounts( Channel );
} }
} }
@ -1313,8 +1274,7 @@ DIO0_Interrupt_1( void )
DIO0_Interrupt( 1 ); DIO0_Interrupt( 1 );
} }
void void setupRFM98( int Channel )
setupRFM98( int Channel )
{ {
if ( Config.LoRaDevices[Channel].InUse ) if ( Config.LoRaDevices[Channel].InUse )
{ {
@ -1354,8 +1314,7 @@ double FrequencyError( int Channel )
Temp = Temp - 524288; Temp = Temp - 524288;
} }
return -( ( double ) Temp * ( 1 << 24 ) / 32000000.0 ) * return -( ( double ) Temp * ( 1 << 24 ) / 32000000.0 ) * (Config.LoRaDevices[Channel].CurrentBandwidth / 500.0);
( Config.LoRaDevices[Channel].CurrentBandwidth / 500.0 );
} }
int int
@ -1407,8 +1366,20 @@ receiveMessage( int Channel, char *message )
LogPacket(Channel, PacketSNR(Channel), PacketRSSI(Channel), FreqError, Bytes, message[1]); LogPacket(Channel, PacketSNR(Channel), PacketRSSI(Channel), FreqError, Bytes, message[1]);
if ( Config.LoRaDevices[Channel].AFC && ( fabs( FreqError ) > 0.5 ) ) if (Config.LoRaDevices[Channel].AFC && (fabs( FreqError ) > 0.5))
{ {
if (Config.LoRaDevices[Channel].MaxAFCStep > 0)
{
// Limit step to MaxAFCStep
if (FreqError > Config.LoRaDevices[Channel].MaxAFCStep)
{
FreqError = Config.LoRaDevices[Channel].MaxAFCStep;
}
else if (FreqError < -Config.LoRaDevices[Channel].MaxAFCStep)
{
FreqError = -Config.LoRaDevices[Channel].MaxAFCStep;
}
}
ReTune( Channel, FreqError / 1000 ); ReTune( Channel, FreqError / 1000 );
} }
} }
@ -1436,7 +1407,18 @@ void LoadConfigFile(void)
{ {
FILE *fp; FILE *fp;
char *filename = "gateway.txt"; char *filename = "gateway.txt";
char *sample_filename = "gateway-sample.txt";
int Channel, MainSection; int Channel, MainSection;
if (access(filename, F_OK) != 0)
{
LogMessage("%s missing\n", filename);
if (access(sample_filename, F_OK) == 0)
{
LogMessage("Renaming %s as %s\n", sample_filename, filename);
rename(sample_filename, filename);
}
}
// Default configuration // Default configuration
Config.latitude = -999; Config.latitude = -999;
@ -1489,9 +1471,9 @@ void LoadConfigFile(void)
RegisterConfigInteger(MainSection, -1, "ActivityLED_0", &Config.LoRaDevices[0].ActivityLED, NULL); RegisterConfigInteger(MainSection, -1, "ActivityLED_0", &Config.LoRaDevices[0].ActivityLED, NULL);
RegisterConfigInteger(MainSection, -1, "ActivityLED_1", &Config.LoRaDevices[1].ActivityLED, NULL); RegisterConfigInteger(MainSection, -1, "ActivityLED_1", &Config.LoRaDevices[1].ActivityLED, NULL);
// Server Port // Socket
RegisterConfigInteger(MainSection, -1, "ServerPort", &Config.ServerPort, NULL); RegisterConfigInteger(MainSection, -1, "ServerPort", &Config.ServerPort, NULL); // JSON server
// SSDV Settings // SSDV Settings
RegisterConfigString(MainSection, -1, "JPGFolder", Config.SSDVJpegFolder, sizeof(Config.SSDVJpegFolder), NULL); RegisterConfigString(MainSection, -1, "JPGFolder", Config.SSDVJpegFolder, sizeof(Config.SSDVJpegFolder), NULL);
if ( Config.SSDVJpegFolder[0] ) if ( Config.SSDVJpegFolder[0] )
@ -1553,12 +1535,17 @@ void LoadConfigFile(void)
// Uplink // Uplink
RegisterConfigInteger(MainSection, Channel, "UplinkTime", &Config.LoRaDevices[Channel].UplinkTime, NULL); RegisterConfigInteger(MainSection, Channel, "UplinkTime", &Config.LoRaDevices[Channel].UplinkTime, NULL);
RegisterConfigInteger(MainSection, Channel, "UplinkCycle", &Config.LoRaDevices[Channel].UplinkCycle, NULL); RegisterConfigInteger(MainSection, Channel, "UplinkCycle", &Config.LoRaDevices[Channel].UplinkCycle, NULL);
LogMessage( "Channel %d UplinkTime %d Uplink Cycle %d\n", Channel, Config.LoRaDevices[Channel].UplinkTime, Config.LoRaDevices[Channel].UplinkCycle); if ((Config.LoRaDevices[Channel].UplinkTime > 0) && (Config.LoRaDevices[Channel].UplinkCycle))
{
LogMessage( "Channel %d UplinkTime %d Uplink Cycle %d\n", Channel, Config.LoRaDevices[Channel].UplinkTime, Config.LoRaDevices[Channel].UplinkCycle);
}
RegisterConfigInteger(MainSection, Channel, "Power", &Config.LoRaDevices[Channel].Power, NULL); RegisterConfigInteger(MainSection, Channel, "Power", &Config.LoRaDevices[Channel].Power, NULL);
LogMessage( "Channel %d power set to %02Xh\n", Channel, Config.LoRaDevices[Channel].Power ); if ((Config.LoRaDevices[Channel].UplinkTime > 0) && (Config.LoRaDevices[Channel].UplinkCycle))
{
LogMessage( "Channel %d power set to %02Xh\n", Channel, Config.LoRaDevices[Channel].Power );
}
RegisterConfigInteger(MainSection, Channel, "UplinkMode", &Config.LoRaDevices[Channel].UplinkMode, NULL); RegisterConfigInteger(MainSection, Channel, "UplinkMode", &Config.LoRaDevices[Channel].UplinkMode, NULL);
if (Config.LoRaDevices[Channel].UplinkMode >= 0) if (Config.LoRaDevices[Channel].UplinkMode >= 0)
@ -1608,6 +1595,18 @@ void LoadConfigFile(void)
if (Config.LoRaDevices[Channel].AFC) if (Config.LoRaDevices[Channel].AFC)
{ {
ChannelPrintf( Channel, 11, 24, "AFC" ); ChannelPrintf( Channel, 11, 24, "AFC" );
RegisterConfigDouble(MainSection, Channel, "MaxAFCStep", &Config.LoRaDevices[Channel].MaxAFCStep, NULL);
if (Config.LoRaDevices[Channel].MaxAFCStep > 0)
{
LogMessage("Maximum AFC Step = %.0lfkHz\n", Config.LoRaDevices[Channel].MaxAFCStep);
}
RegisterConfigInteger(MainSection, Channel, "AFCTimeout", &Config.LoRaDevices[Channel].AFCTimeout, NULL);
if (Config.LoRaDevices[Channel].AFCTimeout > 0)
{
LogMessage("AFC Timeout = %.0ds\n", Config.LoRaDevices[Channel].AFCTimeout);
}
} }
// Clear any flags left over from a previous run // Clear any flags left over from a previous run
@ -1615,10 +1614,10 @@ void LoadConfigFile(void)
} }
} }
fclose( fp ); fclose(fp);
} }
WINDOW *InitDisplay( void ) WINDOW *InitDisplay(void)
{ {
WINDOW *mainwin; WINDOW *mainwin;
int Channel; int Channel;
@ -1982,13 +1981,6 @@ rjh_post_message( int Channel, char *buffer )
Config.LoRaDevices[Channel].LastPacketAt = time( NULL ); Config.LoRaDevices[Channel].LastPacketAt = time( NULL );
if ( Config.LoRaDevices[Channel].InCallingMode
&& ( Config.CallingTimeout > 0 ) )
{
Config.LoRaDevices[Channel].ReturnToCallingModeAt =
time( NULL ) + Config.CallingTimeout;
}
ShowPacketCounts( Channel ); ShowPacketCounts( Channel );
} }
} }
@ -1998,9 +1990,10 @@ rjh_post_message( int Channel, char *buffer )
int main( int argc, char **argv ) int main( int argc, char **argv )
{ {
int ch; int ch;
int LoopPeriod; int LoopPeriod, MSPerLoop;
int Channel; int Channel;
pthread_t SSDVThread, FTPThread, NetworkThread, HabitatThread, ServerThread; pthread_t SSDVThread, FTPThread, NetworkThread, HabitatThread, ServerThread;
struct TServerInfo JSONInfo;
atexit(bye); atexit(bye);
@ -2064,6 +2057,7 @@ int main( int argc, char **argv )
LoopPeriod = 0; LoopPeriod = 0;
MSPerLoop = 10;
// Initialise the vars // Initialise the vars
stsv.parent_status = RUNNING; stsv.parent_status = RUNNING;
@ -2101,15 +2095,18 @@ int main( int argc, char **argv )
// RJH close (telem_pipe_fd[0]); // Close the read side of the pipe as we are writing here // RJH close (telem_pipe_fd[0]); // Close the read side of the pipe as we are writing here
if ( Config.ServerPort > 0 ) if (Config.ServerPort > 0)
{ {
if ( pthread_create( &ServerThread, NULL, ServerLoop, NULL ) ) JSONInfo.Port = Config.ServerPort;
JSONInfo.Connected = 0;
if (pthread_create(&ServerThread, NULL, ServerLoop, (void *)(&JSONInfo)))
{ {
fprintf( stderr, "Error creating server thread\n" ); fprintf( stderr, "Error creating JSON server thread\n" );
return 1; return 1;
} }
} }
if ( ( Config.NetworkLED >= 0 ) && ( Config.InternetLED >= 0 ) ) if ( ( Config.NetworkLED >= 0 ) && ( Config.InternetLED >= 0 ) )
{ {
if ( pthread_create( &NetworkThread, NULL, NetworkLoop, NULL ) ) if ( pthread_create( &NetworkThread, NULL, NetworkLoop, NULL ) )
@ -2139,12 +2136,13 @@ int main( int argc, char **argv )
while ( run ) // && message_count< 9) // RJH Used for debug while ( run ) // && message_count< 9) // RJH Used for debug
{ {
if ( ( ch = getch( ) ) != ERR ) // Keypress tests
if ((ch = getch()) != ERR )
{ {
ProcessKeyPress( ch ); ProcessKeyPress( ch );
} }
/* RJH TEST */ // RJH Test mode
if ( message_count % 10 == 9 ) if ( message_count % 10 == 9 )
{ {
if ( file_telem ) if ( file_telem )
@ -2169,9 +2167,8 @@ int main( int argc, char **argv )
message_count++; // We need to increment this here or we will lock message_count++; // We need to increment this here or we will lock
} }
/* RJH TEST */ if (LoopPeriod > 1000)
if ( LoopPeriod > 1000 )
{ {
// Every 1 second // Every 1 second
time_t now; time_t now;
@ -2182,8 +2179,7 @@ int main( int argc, char **argv )
LoopPeriod = 0; LoopPeriod = 0;
for (Channel=0; Channel<=1; Channel++)
for ( Channel = 0; Channel <= 1; Channel++ )
{ {
if ( Config.LoRaDevices[Channel].InUse ) if ( Config.LoRaDevices[Channel].InUse )
{ {
@ -2191,11 +2187,7 @@ int main( int argc, char **argv )
ChannelPrintf( Channel, 12, 1, "Current RSSI = %4d ", CurrentRSSI(Channel)); ChannelPrintf( Channel, 12, 1, "Current RSSI = %4d ", CurrentRSSI(Channel));
// if (Config.LoRaDevices[Channel].LastPacketAt > 0) // Calling mode timeout?
// {
// ChannelPrintf(Channel, 6, 1, "%us since last packet ", (unsigned int)(time(NULL) - Config.LoRaDevices[Channel].LastPacketAt));
// }
if ( Config.LoRaDevices[Channel].InCallingMode if ( Config.LoRaDevices[Channel].InCallingMode
&& ( Config.CallingTimeout > 0 ) && ( Config.CallingTimeout > 0 )
&& ( Config.LoRaDevices[Channel].ReturnToCallingModeAt > 0 ) && ( Config.LoRaDevices[Channel].ReturnToCallingModeAt > 0 )
@ -2211,45 +2203,52 @@ int main( int argc, char **argv )
SetDefaultLoRaParameters( Channel ); SetDefaultLoRaParameters( Channel );
setMode( Channel, RF98_MODE_RX_CONTINUOUS ); setMode( Channel, RF98_MODE_RX_CONTINUOUS );
ChannelPrintf( Channel, 1, 1, "Channel %d %.3lfMHz %s mode", Channel, Config.LoRaDevices[Channel].Frequency, Modes[Config.LoRaDevices[Channel].SpeedMode]);
} }
// AFC Timeout ?
if (!Config.LoRaDevices[Channel].InCallingMode &&
(Config.LoRaDevices[Channel].AFCTimeout > 0) &&
(Config.LoRaDevices[Channel].ReturnToOriginalFrequencyAt > 0) &&
(time(NULL) > Config.LoRaDevices[Channel].ReturnToOriginalFrequencyAt))
{
Config.LoRaDevices[Channel].ReturnToOriginalFrequencyAt = 0;
if ( ( Config.LoRaDevices[Channel].UplinkTime > 0 ) LogMessage("AFC timeout - return to original frequency\n");
&& ( Config.LoRaDevices[Channel].UplinkCycle > 0 ) )
setMode(Channel, RF98_MODE_SLEEP);
setFrequency(Channel, Config.LoRaDevices[Channel].Frequency);
startReceiving(Channel);
}
// Uplink cycle time ?
if ((Config.LoRaDevices[Channel].UplinkTime > 0) && (Config.LoRaDevices[Channel].UplinkCycle > 0))
{ {
long CycleSeconds; long CycleSeconds;
CycleSeconds = (tm->tm_hour * 3600 + tm->tm_min * 60 + tm->tm_sec ) % Config.LoRaDevices[Channel].UplinkCycle;
CycleSeconds = if ( CycleSeconds == Config.LoRaDevices[Channel].UplinkTime )
( tm->tm_hour * 3600 + tm->tm_min * 60 +
tm->tm_sec ) %
Config.LoRaDevices[Channel].UplinkCycle;
if ( CycleSeconds ==
Config.LoRaDevices[Channel].UplinkTime )
{ {
// LogMessage("%02d:%02d:%02d - Time to send uplink message\n", tm->tm_hour, tm->tm_min, tm->tm_sec); LogMessage("%02d:%02d:%02d - Time to send uplink message\n", tm->tm_hour, tm->tm_min, tm->tm_sec);
SendUplinkMessage( Channel ); SendUplinkMessage( Channel );
} }
} }
if ( LEDCounts[Channel] // LEDs
&& ( Config.LoRaDevices[Channel].ActivityLED >= 0 ) ) if (LEDCounts[Channel] && ( Config.LoRaDevices[Channel].ActivityLED >= 0))
{ {
if ( --LEDCounts[Channel] == 0 ) if ( --LEDCounts[Channel] == 0 )
{ {
digitalWrite( Config.LoRaDevices[Channel]. digitalWrite(Config.LoRaDevices[Channel].ActivityLED, 0);
ActivityLED, 0 );
} }
} }
} }
} }
} }
delay( 10 ); delay(MSPerLoop);
LoopPeriod += 10; LoopPeriod += MSPerLoop;
} }
LogMessage("Disabling DIO0 ISRs\n"); LogMessage("Disabling DIO0 ISRs\n");

Wyświetl plik

@ -1,34 +0,0 @@
tracker=LCARS
EnableHabitat=N
EnableSSDV=N
LogTelemetry=Y
LogPackets=Y
CallingTimeout=60
ServerPort=6004
Latitude=51.950230
Longitude=-2.544500
Antenna=MagMount
JPGFolder=SSDV
EnableDev=N
#NetworkLED=21
#InternetLED=22
#ActivityLED_0=23
#ActivityLED_1=24
frequency_0=434.450000
mode_0=0
#frequency_0=434.447
#mode_0=1
DIO0_0=6
DIO5_0=5
AFC_0=N
frequency_1=869.850000
mode_1=3
#bandwidth_1=125K
#implicit_1=n
#coding_1=5
DIO0_1=27
DIO5_1=26
AFC_1=N

134
global.h
Wyświetl plik

@ -2,83 +2,70 @@
#define RUNNING 1 // The main program is running #define RUNNING 1 // The main program is running
#define STOPPED 0 // The main program has stopped #define STOPPED 0 // The main program has stopped
struct TSSDVPacket {
char Packet[256];
char Callsign[7];
};
struct TSSDVPackets {
int ImageNumber;
int HighestPacket;
bool Packets[1024];
};
struct TLoRaDevice { struct TLoRaDevice {
double Frequency; double Frequency;
double Bandwidth; double Bandwidth;
double CurrentBandwidth; double CurrentBandwidth;
int InUse; int InUse; int DIO0; int DIO5; double activeFreq;
int DIO0;
int DIO5; int AFC; // Enable Automatic Frequency Control
double activeFreq; double MaxAFCStep; // Maximum adjustment, in kHz, per packet
int AFC; int AFCTimeout; // Revert to original frequency if no packets for this period (in seconds)
int SpeedMode;
int Power; int SpeedMode;
int PayloadLength; int Power;
int ImplicitOrExplicit; int PayloadLength;
int ErrorCoding; int ImplicitOrExplicit;
int SpreadingFactor; int ErrorCoding;
int LowDataRateOptimize; int SpreadingFactor;
WINDOW * Window; int LowDataRateOptimize;
unsigned int TelemetryCount, SSDVCount, BadCRCCount, UnknownCount; WINDOW * Window;
int Sending; unsigned int TelemetryCount, SSDVCount, BadCRCCount, UnknownCount;
char Telemetry[256]; int Sending;
char Payload[16], Time[12]; char Telemetry[256];
unsigned int Counter, LastCounter; char Payload[16], Time[12];
unsigned long Seconds; unsigned int Counter, LastCounter;
double PredictedLongitude, PredictedLatitude; unsigned long Seconds;
double Longitude, Latitude; double PredictedLongitude, PredictedLatitude;
unsigned int Altitude, PreviousAltitude; double Longitude, Latitude;
unsigned int Satellites; unsigned int Altitude, PreviousAltitude;
unsigned long LastPositionAt; unsigned int Satellites;
time_t LastPacketAt, LastSSDVPacketAt, LastTelemetryPacketAt; unsigned long LastPositionAt;
float AscentRate; time_t LastPacketAt, LastSSDVPacketAt, LastTelemetryPacketAt;
time_t ReturnToCallingModeAt; float AscentRate;
int InCallingMode; time_t ReturnToCallingModeAt;
int ActivityLED; time_t ReturnToOriginalFrequencyAt;
int InCallingMode;
int ActivityLED;
double UplinkFrequency;
int UplinkMode;
int Speed, Heading, PredictedTime, CompassActual, CompassTarget, AirDirection, ServoLeft, ServoRight, ServoTime, FlightMode;
double cda, PredictedLandingSpeed, AirSpeed, GlideRatio;
double UplinkFrequency; // Normal (non TDM) uplink
int UplinkTime;
int UplinkMode; int UplinkCycle;
int Speed, Heading, PredictedTime, CompassActual, CompassTarget, };
AirDirection, ServoLeft, ServoRight, ServoTime, FlightMode;
double cda, PredictedLandingSpeed, AirSpeed, GlideRatio;
// Normal (non TDM) uplink
int UplinkTime;
int UplinkCycle;
// SSDV Packet Log
struct TSSDVPackets SSDVPackets[3];
};
struct TConfig { char Tracker[16]; // Callsign or name of receiver struct TConfig { char Tracker[16]; // Callsign or name of receiver
double latitude, longitude; // Receiver's location double latitude, longitude; // Receiver's location
int EnableHabitat; int EnableHabitat;
int EnableSSDV; int EnableSSDV;
int EnableTelemetryLogging; int EnableTelemetryLogging;
int EnablePacketLogging; int EnablePacketLogging;
int CallingTimeout; int CallingTimeout;
char SSDVJpegFolder[100]; char SSDVJpegFolder[100];
char ftpServer[100]; char ftpServer[100];
char ftpUser[32]; char ftpUser[32];
char ftpPassword[32]; char ftpPassword[32];
char ftpFolder[64]; char ftpFolder[64];
struct TLoRaDevice LoRaDevices[2]; struct TLoRaDevice LoRaDevices[2];
int NetworkLED; int NetworkLED;
int InternetLED; int InternetLED;
int ServerPort; int ServerPort; // JSON port for telemetry, settings
char SMSFolder[64]; char SMSFolder[64];
char antenna[64]; char antenna[64];
int EnableDev; int EnableDev;
}; };
typedef struct { typedef struct {
int parent_status; int parent_status;
unsigned long packet_count; unsigned long packet_count;
@ -95,6 +82,13 @@ typedef struct {
char SSDV_Packet[257]; char SSDV_Packet[257];
int Packet_Number; int Packet_Number;
} ssdv_t; } ssdv_t;
struct TServerInfo
{
int Port;
int Connected;
int sockfd;
};
extern struct TConfig Config; extern struct TConfig Config;
extern int SSDVSendArrayIndex; extern int SSDVSendArrayIndex;

Wyświetl plik

@ -145,10 +145,19 @@ UploadTelemetryPacket( telemetry_t * t )
} }
else else
{ {
LogMessage( "Failed for URL '%s'\n", url ); long http_code = 0;
LogMessage( "curl_easy_perform() failed: %s\n",
curl_easy_strerror( res ) ); // Get http return code
LogMessage( "error: %s\n", curl_error ); curl_easy_getinfo (curl, CURLINFO_RESPONSE_CODE, &http_code);
if (http_code != 403)
{
// Because 403 happens normally if we receive the same telemetry twice, which happens for example with airborne repeaters
LogMessage( "Failed for URL '%s'\n", url );
LogMessage( "curl_easy_perform() failed: %s\n",
curl_easy_strerror( res ) );
LogMessage( "error: %s\n", curl_error );
}
} }
// always cleanup // always cleanup

222
server.c
Wyświetl plik

@ -23,13 +23,12 @@
#include "global.h" #include "global.h"
extern bool run; extern bool run;
extern bool server_closed;
void ProcessClientLine(int connfd, char *line) void ProcessJSONClientLine(int connfd, char *line)
{ {
line[strcspn(line, "\r\n")] = '\0'; // Get rid of CR LF line[strcspn(line, "\r\n")] = '\0'; // Get rid of CR LF
LogMessage("Received %s from client\n", line); LogMessage("Received %s from JSON client\n", line);
if (strchr(line, '=') == NULL) if (strchr(line, '=') == NULL)
{ {
@ -79,140 +78,165 @@ void ProcessClientLine(int connfd, char *line)
} }
} }
int SendJSON(int connfd)
{
int Channel, port_closed;
char sendBuff[1025];
port_closed = 0;
memset( sendBuff, '0', sizeof( sendBuff ) );
for (Channel=0; Channel<=1; Channel++)
{
if ( Config.EnableDev )
{
sprintf(sendBuff, "{\"class\":\"POSN\",\"index\":%d,\"payload\":\"%s\",\"time\":\"%s\",\"lat\":%.5lf,\"lon\":%.5lf,\"alt\":%d,\"rate\":%.1lf,\"predlat\":%.5lf,\"predlon\":%.5lf,\"speed\":%d,"
"\"head\":%d,\"cda\":%.2lf,\"pls\":%.1lf,\"pt\":%d,\"ca\":%d,\"ct\":%d,\"as\":%.1lf,\"ad\":%d,\"sl\":%d,\"sr\":%d,\"st\":%d,\"gr\":%.2lf,\"fm\":%d}\r\n",
Channel,
Config.LoRaDevices[Channel].Payload,
Config.LoRaDevices[Channel].Time,
Config.LoRaDevices[Channel].Latitude,
Config.LoRaDevices[Channel].Longitude,
Config.LoRaDevices[Channel].Altitude,
Config.LoRaDevices[Channel].AscentRate,
Config.LoRaDevices[Channel].PredictedLatitude,
Config.LoRaDevices[Channel].PredictedLongitude,
Config.LoRaDevices[Channel].Speed,
Config.LoRaDevices[Channel].Heading,
Config.LoRaDevices[Channel].cda,
Config.LoRaDevices[Channel].PredictedLandingSpeed,
Config.LoRaDevices[Channel].PredictedTime,
Config.LoRaDevices[Channel].CompassActual,
Config.LoRaDevices[Channel].CompassTarget,
Config.LoRaDevices[Channel].AirSpeed,
Config.LoRaDevices[Channel].AirDirection,
Config.LoRaDevices[Channel].ServoLeft,
Config.LoRaDevices[Channel].ServoRight,
Config.LoRaDevices[Channel].ServoTime,
Config.LoRaDevices[Channel].GlideRatio,
Config.LoRaDevices[Channel].FlightMode);
}
else
{
sprintf(sendBuff, "{\"class\":\"POSN\",\"index\":%d,\"payload\":\"%s\",\"time\":\"%s\",\"lat\":%.5lf,\"lon\":%.5lf,\"alt\":%d,\"rate\":%.1lf}\r\n",
Channel,
Config.LoRaDevices[Channel].Payload,
Config.LoRaDevices[Channel].Time,
Config.LoRaDevices[Channel].Latitude,
Config.LoRaDevices[Channel].Longitude,
Config.LoRaDevices[Channel].Altitude,
Config.LoRaDevices[Channel].AscentRate);
}
if ( !run )
{
port_closed = 1;
}
else if ( send(connfd, sendBuff, strlen(sendBuff), MSG_NOSIGNAL ) <= 0 )
{
LogMessage( "Disconnected from client\n" );
port_closed = 1;
}
}
return port_closed;
}
void *ServerLoop( void *some_void_ptr ) void *ServerLoop( void *some_void_ptr )
{ {
int sockfd = 0;
struct sockaddr_in serv_addr; struct sockaddr_in serv_addr;
struct TServerInfo *ServerInfo;
ServerInfo = (struct TServerInfo *)some_void_ptr;
char sendBuff[1025]; ServerInfo->sockfd = socket( AF_INET, SOCK_STREAM, 0 );
sockfd = socket( AF_INET, SOCK_STREAM, 0 );
memset( &serv_addr, '0', sizeof( serv_addr ) ); memset( &serv_addr, '0', sizeof( serv_addr ) );
memset( sendBuff, '0', sizeof( sendBuff ) );
serv_addr.sin_family = AF_INET; serv_addr.sin_family = AF_INET;
serv_addr.sin_addr.s_addr = htonl( INADDR_ANY ); serv_addr.sin_addr.s_addr = htonl( INADDR_ANY );
serv_addr.sin_port = htons( Config.ServerPort ); serv_addr.sin_port = htons(ServerInfo->Port);
LogMessage( "Listening on port %d\n", Config.ServerPort ); LogMessage( "Listening on JSON port %d\n", ServerInfo->Port);
if ( setsockopt( sockfd, SOL_SOCKET, SO_REUSEADDR, &( int ) if (setsockopt(ServerInfo->sockfd, SOL_SOCKET, SO_REUSEADDR, &(int){1}, sizeof(int)) < 0)
{ {
1}, sizeof( int ) ) < 0 )
{
LogMessage( "setsockopt(SO_REUSEADDR) failed" ); LogMessage( "setsockopt(SO_REUSEADDR) failed" );
} }
if ( bind if (bind(ServerInfo->sockfd, (struct sockaddr *) &serv_addr, sizeof(serv_addr)) < 0)
( sockfd, ( struct sockaddr * ) &serv_addr,
sizeof( serv_addr ) ) < 0 )
{ {
LogMessage( "Server failed errno %d\n", errno ); LogMessage( "Server failed errno %d\n", errno );
exit( -1 ); exit( -1 );
} }
listen( sockfd, 10 ); listen(ServerInfo->sockfd, 10);
while ( run ) while (run)
{ {
int SendEveryMS = 1000; int SendEveryMS = 1000;
int MSPerLoop=100; int MSPerLoop=100;
int ms, port_closed, connfd; int ms=0;
int connfd;
Config.EnableDev=1;
fcntl(sockfd, F_SETFL, fcntl(sockfd, F_GETFL) & ~O_NONBLOCK); // Blocking mode so we wait for a connection fcntl(ServerInfo->sockfd, F_SETFL, fcntl(ServerInfo->sockfd, F_GETFL) & ~O_NONBLOCK); // Blocking mode so we wait for a connection
connfd = accept( sockfd, ( struct sockaddr * ) NULL, NULL ); // Wait for connection connfd = accept(ServerInfo->sockfd, ( struct sockaddr * ) NULL, NULL ); // Wait for connection
LogMessage( "Connected to client\n" ); LogMessage( "Connected to client\n");
ServerInfo->Connected = 1;
fcntl(connfd, F_SETFL, fcntl(sockfd, F_GETFL) | O_NONBLOCK); // Non-blocking, so we don't block on receiving any commands from client fcntl(connfd, F_SETFL, fcntl(ServerInfo->sockfd, F_GETFL) | O_NONBLOCK); // Non-blocking, so we don't block on receiving any commands from client
for ( port_closed = 0; !port_closed; ) while (ServerInfo->Connected)
{ {
int Channel;
char packet[4096]; char packet[4096];
int bytecount;
// Listen loop ms += MSPerLoop;
for (ms=0; ms<SendEveryMS; ms+=MSPerLoop)
{ // Listen part
int bytecount; bytecount = -1;
while ((bytecount = recv(connfd, packet, sizeof(packet), 0)) > 0) while ((bytecount = recv(connfd, packet, sizeof(packet), 0)) > 0)
{
char *line, *saveptr;
packet[bytecount] = 0;
// JSON server
line = strtok_r(packet, "\n", &saveptr);
while (line)
{ {
char *line, *saveptr; ProcessJSONClientLine(connfd, line);
line = strtok_r( NULL, "\n", &saveptr);
packet[bytecount] = 0; }
}
line = strtok_r(packet, "\n", &saveptr);
while (line) if (bytecount == 0)
{
// -1 is no more data, 0 means port closed
LogMessage("Disconnected from client\n");
ServerInfo->Connected = 0;
}
if (ServerInfo->Connected)
{
// Send to JSON client
if (ms >= SendEveryMS)
{
if (SendJSON(connfd))
{ {
ProcessClientLine(connfd, line); ServerInfo->Connected = 0;
line = strtok_r( NULL, "\n", &saveptr);
} }
} }
delay(MSPerLoop);
}
// Send part
// Build json
for (Channel=0; Channel<=1; Channel++)
{
if ( Config.EnableDev )
{
sprintf(sendBuff, "{\"class\":\"POSN\",\"index\":%d,\"payload\":\"%s\",\"time\":\"%s\",\"lat\":%.5lf,\"lon\":%.5lf,\"alt\":%d,\"rate\":%.1lf,\"predlat\":%.5lf,\"predlon\":%.5lf,\"speed\":%d,"
"\"head\":%d,\"cda\":%.2lf,\"pls\":%.1lf,\"pt\":%d,\"ca\":%d,\"ct\":%d,\"as\":%.1lf,\"ad\":%d,\"sl\":%d,\"sr\":%d,\"st\":%d,\"gr\":%.2lf,\"fm\":%d}\r\n",
Channel,
Config.LoRaDevices[Channel].Payload,
Config.LoRaDevices[Channel].Time,
Config.LoRaDevices[Channel].Latitude,
Config.LoRaDevices[Channel].Longitude,
Config.LoRaDevices[Channel].Altitude,
Config.LoRaDevices[Channel].AscentRate,
Config.LoRaDevices[Channel].PredictedLatitude,
Config.LoRaDevices[Channel].PredictedLongitude,
Config.LoRaDevices[Channel].Speed,
Config.LoRaDevices[Channel].Heading,
Config.LoRaDevices[Channel].cda,
Config.LoRaDevices[Channel].PredictedLandingSpeed,
Config.LoRaDevices[Channel].PredictedTime,
Config.LoRaDevices[Channel].CompassActual,
Config.LoRaDevices[Channel].CompassTarget,
Config.LoRaDevices[Channel].AirSpeed,
Config.LoRaDevices[Channel].AirDirection,
Config.LoRaDevices[Channel].ServoLeft,
Config.LoRaDevices[Channel].ServoRight,
Config.LoRaDevices[Channel].ServoTime,
Config.LoRaDevices[Channel].GlideRatio,
Config.LoRaDevices[Channel].FlightMode);
}
else
{
sprintf(sendBuff, "{\"class\":\"POSN\",\"index\":%d,\"payload\":\"%s\",\"time\":\"%s\",\"lat\":%.5lf,\"lon\":%.5lf,\"alt\":%d,\"rate\":%.1lf}\r\n",
Channel,
Config.LoRaDevices[Channel].Payload,
Config.LoRaDevices[Channel].Time,
Config.LoRaDevices[Channel].Latitude,
Config.LoRaDevices[Channel].Longitude,
Config.LoRaDevices[Channel].Altitude,
Config.LoRaDevices[Channel].AscentRate);
}
if ( !run )
{
port_closed = 1;
}
else if ( send(connfd, sendBuff, strlen(sendBuff), MSG_NOSIGNAL ) <= 0 )
{
LogMessage( "Disconnected from client\n" );
port_closed = 1;
}
} }
delay(MSPerLoop);
} }
close( connfd ); close(connfd);
} }
return NULL; return NULL;

32
ssdv.c
Wyświetl plik

@ -66,7 +66,6 @@ UploadImagePacket( ssdv_t * s, unsigned int packets )
curl = curl_easy_init( ); curl = curl_easy_init( );
if ( curl ) if ( curl )
{ {
// So that the response to the curl POST doesn;'t mess up my finely crafted display! // So that the response to the curl POST doesn;'t mess up my finely crafted display!
curl_easy_setopt( curl, CURLOPT_WRITEFUNCTION, write_ssdv_data ); curl_easy_setopt( curl, CURLOPT_WRITEFUNCTION, write_ssdv_data );
@ -90,25 +89,22 @@ UploadImagePacket( ssdv_t * s, unsigned int packets )
// Create json with the base64 data in hex, the tracker callsign and the current timestamp // Create json with the base64 data in hex, the tracker callsign and the current timestamp
strcpy( json, "{\"type\": \"packets\",\"packets\":[" ); strcpy( json, "{\"type\": \"packets\",\"packets\":[" );
for ( PacketIndex = 0; PacketIndex < packets; PacketIndex++ ) for (PacketIndex = 0; PacketIndex < packets; PacketIndex++)
{ {
base64_encode( s[PacketIndex].SSDV_Packet, 256, &base64_length, base64_encode(s[PacketIndex].SSDV_Packet, 256, &base64_length, base64_data);
base64_data );
base64_data[base64_length] = '\0'; base64_data[base64_length] = '\0';
sprintf( packet_json, sprintf(packet_json,
"{\"type\": \"packet\", \"packet\": \"%s\", \"encoding\": \"base64\", \"received\": \"%s\", \"receiver\": \"%s\"}%s", "{\"type\": \"packet\", \"packet\": \"%s\", \"encoding\": \"base64\", \"received\": \"%s\", \"receiver\": \"%s\"}%s",
base64_data, now, Config.Tracker, base64_data, now, Config.Tracker,
PacketIndex == ( packets - 1 ) ? "" : "," ); PacketIndex == ( packets - 1 ) ? "" : ",");
strcat( json, packet_json ); strcat(json, packet_json);
} }
strcat( json, "]}" ); strcat(json, "]}");
// LogTelemetryPacket(json); // LogTelemetryPacket(json);
strcpy( url, "http://ssdv.habhub.org/api/v0/packets" ); strcpy( url, "http://ssdv.habhub.org/api/v0/packets" );
// strcpy(url,"http://ext.hgf.com/ssdv/rjh.php");
// strcpy(url,"http://ext.hgf.com/ssdv/apiv0.php?q=packets");
// Set the headers // Set the headers
headers = NULL; headers = NULL;
@ -144,10 +140,8 @@ UploadImagePacket( ssdv_t * s, unsigned int packets )
} }
} }
void * void *SSDVLoop( void *vars )
SSDVLoop( void *vars )
{ {
if ( Config.EnableSSDV ) if ( Config.EnableSSDV )
{ {
const int max_packets = 51; const int max_packets = 51;
@ -185,11 +179,11 @@ SSDVLoop( void *vars )
if ( j == 50 || ( ( packets == 0 ) && ( j > 0 ) ) ) if ( j == 50 || ( ( packets == 0 ) && ( j > 0 ) ) )
{ {
ChannelPrintf( s[0].Channel, 6, 1, "Habitat" ); ChannelPrintf(s[0].Channel, 6, 16, "SSDV");
UploadImagePacket( s, j ); UploadImagePacket( s, j );
ChannelPrintf( s[0].Channel, 6, 1, " " ); ChannelPrintf(s[0].Channel, 6, 16, " ");
j = 0; j = 0;

Wyświetl plik

@ -1,103 +1,101 @@
import urllib.parse import urllib.parse
import urllib.request import urllib.request
import json import json
from datetime import datetime, timedelta from datetime import datetime, timedelta
import sys import sys
import os.path import os.path
import time import time
def get_list_of_missing_packets(PayloadID, Minutes): def get_list_of_missing_packets(PayloadID, Minutes):
result = '' result = ''
# url = 'http://ssdv.habhub.org/api/v0/images?callsign=PI868&from=2016-01-22T11:00:00Z&missing_packets' time_limit = datetime.utcnow() - timedelta(0,Minutes*60) # n minutes ago
time_limit = datetime.utcnow() - timedelta(0,Minutes*60) # n minutes ago url = 'http://ssdv.habhub.org/api/v0/images?callsign=' + PayloadID + '&from=' + time_limit.strftime('%Y-%m-%dT%H:%M:%SZ') + '&missing_packets'
url = 'http://ssdv.habhub.org/api/v0/images?callsign=' + PayloadID + '&from=' + time_limit.strftime('%Y-%m-%dT%H:%M:%SZ') + '&missing_packets'
print("url", url)
print("url", url)
req = urllib.request.Request(url)
req = urllib.request.Request(url) with urllib.request.urlopen(req) as response:
with urllib.request.urlopen(req) as response: the_page = response.read() # content = urllib.request.urlopen(url=url, data=data).read()
the_page = response.read() # content = urllib.request.urlopen(url=url, data=data).read() # print(the_page)
# print(the_page)
temp = the_page.decode('utf-8')
temp = the_page.decode('utf-8') j = json.loads(temp)
j = json.loads(temp) # print(j)
# print(j)
line = ""
line = "" for index, item in enumerate(j):
for index, item in enumerate(j): # only interested in latest 2 images
# only interested in latest 2 images if index >= (len(j) - 2):
if index >= (len(j) - 2): # only interested in images that have missing packets
# only interested in images that have missing packets if len(item['missing_packets']) > 0:
if len(item['missing_packets']) > 0: print(item['id'], item['image_id'], len(item['missing_packets']))
print(item['id'], item['image_id'], len(item['missing_packets'])) print(item['missing_packets'])
print(item['missing_packets']) pl = item['packets']
pl = item['packets'] # print("highest_packet_id = ", item['last_packet'])
# print("highest_packet_id = ", item['last_packet']) first_missing_packet = -1
first_missing_packet = -1 last_missing_packet = -1
last_missing_packet = -1 missing_packets = item['missing_packets'] + [9999]
missing_packets = item['missing_packets'] + [9999]
# Header for this image
# Header for this image if line != "":
if line != "": line = line + ","
line = line + "," line = line + str(item['image_id']) + ":" + str(item['last_packet']) + "="
line = line + str(item['image_id']) + ":" + str(item['last_packet']) + "=" image_line = ""
image_line = ""
for mp_index, mp in enumerate(missing_packets):
for mp_index, mp in enumerate(missing_packets): if mp_index == 0:
if mp_index == 0: first_missing_packet = mp
first_missing_packet = mp last_missing_packet = mp
last_missing_packet = mp
if (mp > (last_missing_packet+1)): # or (mp_index == len(item['missing_packets'])-1):
if (mp > (last_missing_packet+1)): # or (mp_index == len(item['missing_packets'])-1): # emit section
# emit section if image_line != "":
if image_line != "": image_line = image_line + ","
image_line = image_line + "," if last_missing_packet == first_missing_packet:
if last_missing_packet == first_missing_packet: image_line = image_line + str(last_missing_packet)
image_line = image_line + str(last_missing_packet) else:
else: image_line = image_line + str(first_missing_packet) + "-" + str(last_missing_packet)
image_line = image_line + str(first_missing_packet) + "-" + str(last_missing_packet) first_missing_packet = mp
first_missing_packet = mp
last_missing_packet = mp
last_missing_packet = mp line = line + image_line
line = line + image_line
result = "!" + line + "\n"
if line != '':
result = "!" + line + "\n" return result
return result
if len(sys.argv) <= 1:
print ("Usage: ssdv_resend <payload_id> [folder]\n")
if len(sys.argv) <= 1: quit()
print ("Usage: ssdv_resend <payload_id> [folder]\n")
quit() payload_id = sys.argv[1]
payload_id = sys.argv[1] if len(sys.argv) >= 3:
folder = sys.argv[2]
if len(sys.argv) >= 3: else:
folder = sys.argv[2] folder = './'
else:
folder = './' print('Payload = ' + payload_id)
print('Folder = ' + folder)
print('Payload = ' + payload_id)
print('Folder = ' + folder) while True:
# if os.path.isfile(folder + 'get_list.txt'):
while True: if (datetime.utcnow().second < 0) or (datetime.utcnow().second > 50):
# if os.path.isfile(folder + 'get_list.txt'): print("Checking ...")
if (datetime.utcnow().second < 0) or (datetime.utcnow().second > 50): # os.remove(folder + 'get_list.txt')
print("Checking ...") line = get_list_of_missing_packets(payload_id, 5)
# os.remove(folder + 'get_list.txt') if len(line) <= 2:
line = get_list_of_missing_packets(payload_id, 5) print("No missing packets")
if line == '': else:
print("No missing packets") print("Missing Packets:", line)
line = "Nothing" with open(folder + 'uplink.txt', "w") as text_file:
else: if line != '':
print("Missing Packets:", line) print(line, file=text_file)
with open(folder + 'uplink.txt', "w") as text_file: time.sleep(1)
if line != '': else:
print(line, file=text_file) print('.',end="")
time.sleep(1) sys.stdout.flush()
else: time.sleep(1)
print('.',end="",flush=True)
time.sleep(1)