From 47eb65b00a7830f0312ca01ffd4c4fd423b1782f Mon Sep 17 00:00:00 2001 From: Dave Akerman Date: Fri, 24 Jul 2015 21:12:47 +0000 Subject: [PATCH 1/2] Separate source files for habitat etc. --- ftp.c | 86 ++++++++++ ftp.h | 1 + gateway | Bin 41474 -> 45007 bytes gateway.c | 453 ++++++++++++++++++++++++---------------------------- gateway.txt | 16 +- global.h | 8 +- habitat.c | 28 ++++ habitat.h | 1 + loop | 5 + makefile | 13 +- network.c | 109 +++++++++++++ network.h | 1 + ssdv.c | 52 ------ 13 files changed, 463 insertions(+), 310 deletions(-) create mode 100755 ftp.c create mode 100755 ftp.h create mode 100755 habitat.c create mode 100755 habitat.h create mode 100755 loop create mode 100755 network.c create mode 100755 network.h diff --git a/ftp.c b/ftp.c new file mode 100755 index 0000000..fa31281 --- /dev/null +++ b/ftp.c @@ -0,0 +1,86 @@ +#include +#include +#include +#include +#include // Standard input/output definitions +#include // String function definitions +#include // UNIX standard function definitions +#include // File control definitions +#include // Error number definitions +#include // POSIX terminal control definitions +#include +#include +#include +#include +#include + +#include "ftp.h" +#include "global.h" + +void ConvertFile(char *FileName) +{ + char TargetFile[100], CommandLine[200], *ptr; + + strcpy(TargetFile, FileName); + ptr = strchr(TargetFile, '.'); + if (ptr) + { + *ptr = '\0'; + strcat(TargetFile, ".JPG"); + + // Now convert the file + sprintf(CommandLine, "ssdv -d /tmp/%s %s 2> /dev/null > /dev/null", FileName, TargetFile); + system(CommandLine); + + LogMessage("Converting %s to %s\n", FileName, TargetFile); + + if (Config.ftpServer[0] && Config.ftpUser[0] && Config.ftpPassword[0]) + { + // Upload to ftp server + sprintf(CommandLine, "curl -T %s %s -Q \"TYPE I\" --user %s:%s 2> /dev/null > /dev/null", TargetFile, Config.ftpServer, Config.ftpUser, Config.ftpPassword); + system(CommandLine); + } + } +} + + +void *FTPLoop(void *some_void_ptr) +{ + while (1) + { + DIR *dp; + struct dirent *ep; + struct stat st; + char *SSDVFolder; + char FileName[100], TempName[100]; + + SSDVFolder = "/tmp"; + + dp = opendir(SSDVFolder); + if (dp != NULL) + { + while (ep = readdir (dp)) + { + if (strstr(ep->d_name, ".bin") != NULL) + { + sprintf(FileName, "%s/%s", SSDVFolder, ep->d_name); + stat(FileName, &st); + // LogMessage("Age of '%s' is %ld seconds\n", FileName, time(0) - st.st_mtime); + if ((time(0) - st.st_mtime) < 20) + { + ConvertFile(ep->d_name); + } + else if ((time(0) - st.st_mtime) > 120) + { + sprintf(TempName, "/tmp/%s", ep->d_name); + LogMessage("Removing %s\n", TempName); + remove(TempName); + } + } + } + } + (void) closedir (dp); + + sleep(5); + } +} diff --git a/ftp.h b/ftp.h new file mode 100755 index 0000000..5eacf46 --- /dev/null +++ b/ftp.h @@ -0,0 +1 @@ +void *FTPLoop(void *some_void_ptr); \ No newline at end of file diff --git a/gateway b/gateway index 1b8bfce8b7d7a9a191152f55974dd00da6cdc6af..c71171d99dfc805436e615ff4642e37b7e30b8d6 100755 GIT binary patch literal 45007 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 SzZ1oDUlS8*mS4dwllZ^S%{OcS literal 41474 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 P*_Ba!XB=x?LqhyN6|R$B diff --git a/gateway.c b/gateway.c index 9c199cd..6b285cd 100755 --- a/gateway.c +++ b/gateway.c @@ -24,6 +24,9 @@ #include "urlencode.h" #include "base64.h" #include "ssdv.h" +#include "ftp.h" +#include "habitat.h" +#include "network.h" #include "global.h" bool run = TRUE; @@ -174,6 +177,14 @@ void LogMessage(const char *format, ...) va_end(args); + if (strlen(Buffer) > 79) + { + Buffer[77] = '.'; + Buffer[78] = '.'; + Buffer[79] = '\n'; + Buffer[80] = 0; + } + waddstr(Window, Buffer); wrefresh(Window); @@ -343,7 +354,7 @@ void startReceiving(int Channel) void ReTune(int Channel, double FreqShift) { setMode(Channel, RF96_MODE_SLEEP); - LogMessage("Retune by %lf\n", FreqShift); + LogMessage("Retune by %lf kHz\n", FreqShift * 1000); setFrequency(Channel, Config.LoRaDevices[Channel].activeFreq + FreqShift); startReceiving(Channel); } @@ -464,7 +475,7 @@ int receiveMessage(int Channel, unsigned char *message) message[Bytes] = '\0'; - if(Config.LoRaDevices[Channel].AFC && fabs(FreqError)>0.5) + if(Config.LoRaDevices[Channel].AFC && (fabs(FreqError)>0.5)) { ReTune(Channel, FreqError/1000); } @@ -1017,34 +1028,6 @@ void DoPositionCalcs(Channel) Config.LoRaDevices[Channel].Altitude); } -int NewBoard(void) -{ - FILE *cpuFd ; - char line [120] ; - char *c ; - static int boardRev = -1 ; - - if (boardRev < 0) - { - if ((cpuFd = fopen ("/proc/cpuinfo", "r")) != NULL) - { - while (fgets (line, 120, cpuFd) != NULL) - if (strncmp (line, "Revision", 8) == 0) - break ; - - fclose (cpuFd) ; - - if (strncmp (line, "Revision", 8) == 0) - { - // printf ("RPi %s", line); - boardRev = ((strstr(line, "0010") != NULL) || (strstr(line, "0012") != NULL)); // B+ or A+ - } - } - } - - return boardRev; -} - uint16_t CRC16(unsigned char *ptr) { uint16_t CRC, xPolynomial; @@ -1122,13 +1105,20 @@ void ProcessKeyPress(int ch) } } +void ProcessUploadMessage(int Channel, char *Message) +{ + // LogMessage("Ch %d: Uploaded message %s\n", Channel, Message); +} + void ProcessCallingMessage(int Channel, char *Message) { char Payload[16]; double Frequency; int ImplicitOrExplicit, ErrorCoding, Bandwidth, SpreadingFactor, LowDataRateOptimize; - if (sscanf(Message, "%15[^,],%lf,%d,%d,%d,%d,%d,%d", + ChannelPrintf(Channel, 4, 1, "Calling message %d bytes ", strlen(Message)); + + if (sscanf(Message+2, "%15[^,],%lf,%d,%d,%d,%d,%d,%d", Payload, &Frequency, &ImplicitOrExplicit, @@ -1158,19 +1148,134 @@ void ProcessCallingMessage(int Channel, char *Message) setMode(Channel, RF96_MODE_RX_CONTINUOUS); + Config.LoRaDevices[Channel].InCallingMode = 1; + // ChannelPrintf(Channel, 1, 1, "Channel %d %7.3lfMHz ", Channel, Frequency); } } +void ProcessTelemetryMessage(int Channel, char *Message) +{ + if (strlen(Message+1) < 150) + { + int i; + unsigned char *startmessage, *endmessage; + + ChannelPrintf(Channel, 4, 1, "Telemetry %d bytes ", strlen(Message+1)); + + endmessage = Message; + + startmessage = endmessage; + endmessage = strchr(startmessage, '\n'); + + if (endmessage != NULL) + { + *endmessage = '\0'; + + LogTelemetryPacket(startmessage); + + UploadTelemetryPacket(startmessage); + + ProcessLine(Channel, startmessage); + + LogMessage("Ch %d: %s\n", Channel, startmessage); + } + + // DoPositionCalcs(Channel); + + Config.LoRaDevices[Channel].TelemetryCount++; + } +} + +void ProcessSSDVMessage(int Channel, char *Message) +{ + // SSDV packet + static uint32_t PreviousCallsignCode=0; + static int PreviousImageNumber=-1, PreviousPacketNumber=0; + uint32_t CallsignCode; + char Callsign[7], *FileMode, *EncodedCallsign, *EncodedEncoding, *Base64Data, *EncodedData, HexString[513], Command[1000]; + int output_length, ImageNumber, PacketNumber; + char filename[100]; + FILE *fp; + + Message[0] = 0x55; + + CallsignCode = Message[2]; CallsignCode <<= 8; + CallsignCode |= Message[3]; CallsignCode <<= 8; + CallsignCode |= Message[4]; CallsignCode <<= 8; + CallsignCode |= Message[5]; + + decode_callsign(Callsign, CallsignCode); + + ImageNumber = Message[6]; + PacketNumber = Message[8]; + + // Create new file ? + if ((ImageNumber != PreviousImageNumber) || (PacketNumber <= PreviousPacketNumber) || (CallsignCode != PreviousCallsignCode)) + { + // New image so new file + // FileMode = "wb"; + FileMode = "ab"; + Config.LoRaDevices[Channel].SSDVMissing = PacketNumber; + } + else + { + FileMode = "ab"; + if (PacketNumber > (PreviousPacketNumber+1)) + { + Config.LoRaDevices[Channel].SSDVMissing += PacketNumber - PreviousPacketNumber - 1; + } + } + + LogMessage("Ch%d: SSDV Packet, Callsign %s, Image %d, Packet %d, %d Missing\n", Channel, Callsign, Message[6], Message[7] * 256 + Message[8], Config.LoRaDevices[Channel].SSDVMissing); + ChannelPrintf(Channel, 4, 1, "SSDV Packet "); + + PreviousImageNumber = ImageNumber; + PreviousPacketNumber = PacketNumber; + PreviousCallsignCode = CallsignCode; + + // Save to file + + sprintf(filename, "/tmp/%s_%d.bin", Callsign, ImageNumber); + + if (fp = fopen(filename, FileMode)) + { + fwrite(Message, 1, 256, fp); + fclose(fp); + } + + // Upload to server + if (Config.EnableSSDV) + { + EncodedCallsign = url_encode(Callsign); + EncodedEncoding = url_encode("hex"); + + // Base64Data = base64_encode(Message, 256, &output_length); + // printf("output_length=%d, byte=%02Xh\n", output_length, Base64Data[output_length]); + // Base64Data[output_length] = '\0'; + // printf ("Base64Data '%s'\n", Base64Data); + ConvertStringToHex(HexString, Message, 256); + EncodedData = url_encode(HexString); + + UploadImagePacket(EncodedCallsign, EncodedEncoding, EncodedData); + + free(EncodedCallsign); + free(EncodedEncoding); + // free(Base64Data); + free(EncodedData); + } + + Config.LoRaDevices[Channel].SSDVCount++; +} int main(int argc, char **argv) { - unsigned char Message[257], Command[200], Telemetry[100], filename[100], *dest, *src; - int Bytes, ImageNumber, PreviousImageNumber, PacketNumber, PreviousPacketNumber, ch; - uint32_t CallsignCode, PreviousCallsignCode, LoopCount[2]; - pthread_t /* CurlThread, */ SSDVThread; - FILE *fp; + unsigned char Message[257], Command[200], Telemetry[100], *dest, *src; + int Bytes, ch; + uint32_t LoopCount[2]; + pthread_t SSDVThread, FTPThread, NetworkThread, HabitatThread; WINDOW * mainwin; + int LEDCounts[2]; mainwin = InitDisplay(); @@ -1179,38 +1284,29 @@ int main(int argc, char **argv) cbreak(); nodelay(stdscr, TRUE); keypad(stdscr, TRUE); - - PreviousImageNumber = -1; - PreviousCallsignCode = 0; - PreviousPacketNumber = 0; - - fp = NULL; - + Config.LoRaDevices[0].InUse = 0; Config.LoRaDevices[1].InUse = 0; - if (NewBoard()) - { - // For dual card. These are for the second prototype (earlier one will need overrides) + LEDCounts[0] = 0; + LEDCounts[1] = 0; + + // Remove any old SSDV files + // system("rm -f /tmp/*.bin"); + + // Default pin allocations - Config.LoRaDevices[0].DIO0 = 6; - Config.LoRaDevices[0].DIO5 = 5; - - Config.LoRaDevices[1].DIO0 = 31; - Config.LoRaDevices[1].DIO5 = 26; - - LogMessage("Pi A+/B+ board\n"); - } - else - { - Config.LoRaDevices[0].DIO0 = 6; - Config.LoRaDevices[0].DIO5 = 5; - - Config.LoRaDevices[1].DIO0 = 3; - Config.LoRaDevices[1].DIO5 = 4; - - LogMessage("Pi A/B board\n"); - } + Config.LoRaDevices[0].DIO0 = 6; + Config.LoRaDevices[0].DIO5 = 5; + + Config.LoRaDevices[1].DIO0 = 27; + Config.LoRaDevices[1].DIO5 = 26; + + Config.NetworkLED = 21; + Config.InternetLED = 22; + + Config.LoRaDevices[0].ActivityLED = 23; + Config.LoRaDevices[1].ActivityLED = 24; LoadConfigFile(); LoadPayloadFiles(); @@ -1221,6 +1317,11 @@ int main(int argc, char **argv) exit(1); } + pinMode(Config.LoRaDevices[0].ActivityLED, OUTPUT); + pinMode(Config.LoRaDevices[1].ActivityLED, OUTPUT); + pinMode(Config.InternetLED, OUTPUT); + pinMode(Config.NetworkLED, OUTPUT); + setupRFM98(0); setupRFM98(1); @@ -1235,8 +1336,25 @@ int main(int argc, char **argv) fprintf(stderr, "Error creating SSDV thread\n"); return 1; } - - + + if (pthread_create(&FTPThread, NULL, FTPLoop, NULL)) + { + fprintf(stderr, "Error creating FTP thread\n"); + return 1; + } + + if (pthread_create(&HabitatThread, NULL, HabitatLoop, NULL)) + { + fprintf(stderr, "Error creating Habitat thread\n"); + return 1; + } + + if (pthread_create(&NetworkThread, NULL, NetworkLoop, NULL)) + { + fprintf(stderr, "Error creating Network thread\n"); + return 1; + } + while (run) { int Channel; @@ -1251,198 +1369,26 @@ int main(int argc, char **argv) if (Bytes > 0) { + digitalWrite(Config.LoRaDevices[Channel].ActivityLED, 1); + LEDCounts[Channel] = 5; // LogMessage("Channel %d data available - %d bytes\n", Channel, Bytes); // LogMessage("Line = '%s'\n", Message); - // Habitat upload - // $$.... if (Message[1] == '!') { - LogMessage("Ch %d: Uploaded message %s\n", Channel, Message+1); + ProcessUploadMessage(Channel, Message+1); } else if (Message[1] == '^') { - ChannelPrintf(Channel, 4, 1, "Calling message %d bytes ", strlen(Message+1)); - - ProcessCallingMessage(Channel, Message+3); - - // Message[strlen(Message+1)] = '\0'; + ProcessCallingMessage(Channel, Message+1); } else if (Message[1] == '$') { - int i; - unsigned char *startmessage, *endmessage; - - ChannelPrintf(Channel, 4, 1, "Telemetry %d bytes ", strlen(Message+1)); - // LogMessage("Telemetry %d bytes\n", strlen(Message)-1); - - endmessage = Message; - - for (i=0; endmessage < &(Message[strlen(Message+1)-8]); i++) - { - startmessage = endmessage + 1; - endmessage = strchr(startmessage, '\n'); - if (endmessage != NULL) - { - *endmessage = '\0'; - - LogTelemetryPacket(startmessage); - - UploadTelemetryPacket(startmessage); - - if (i == 0) - { - ProcessLine(Channel, startmessage); - } - - LogMessage("Ch %d: %s\n", Channel, startmessage); - } - } - - DoPositionCalcs(Channel); - - Config.LoRaDevices[Channel].TelemetryCount++; - - // Message[strlen(Message+1)] = '\0'; - } - else if ((Message[1] & 0xC0) == 0xC0) - { - // Binary telemetry packet - struct TBinaryPacket BinaryPacket; - char Data[100], Sentence[100]; - int SourceID, SenderID; - - SourceID = Message[1] & 0x07; - SenderID = (Message[1] >> 3) & 0x07; - - ChannelPrintf(Channel, 4, 1, "Binary Telemetry"); - - memcpy(&BinaryPacket, Message+1, sizeof(BinaryPacket)); - - strcpy(Config.LoRaDevices[Channel].Payload, "Binary"); - Config.LoRaDevices[Channel].Seconds = (unsigned long) BinaryPacket.BiSeconds * 2L; - Config.LoRaDevices[Channel].Counter = BinaryPacket.Counter; - Config.LoRaDevices[Channel].Latitude = BinaryPacket.Latitude; - Config.LoRaDevices[Channel].Longitude = BinaryPacket.Longitude; - Config.LoRaDevices[Channel].Altitude = BinaryPacket.Altitude; - - sprintf(Data, "%s,%u,%02d:%02d:%02d,%8.5f,%8.5f,%u", - Payloads[SourceID].Payload, - BinaryPacket.Counter, - (int)(Config.LoRaDevices[Channel].Seconds / 3600), - (int)((Config.LoRaDevices[Channel].Seconds / 60) % 60), - (int)(Config.LoRaDevices[Channel].Seconds % 60), - BinaryPacket.Latitude, - BinaryPacket.Longitude, - BinaryPacket.Altitude); - sprintf(Sentence, "$$%s*%04X\n", Data, CRC16(Data)); - - UploadTelemetryPacket(Sentence); - - DoPositionCalcs(Channel); - - Config.LoRaDevices[Channel].TelemetryCount++; - - LogMessage("Ch %d: Sender %d Source %d (%s) Position %8.5lf, %8.5lf, %05u\n", - Channel, - SenderID, - SourceID, - Payloads[SourceID].Payload, - Config.LoRaDevices[Channel].Latitude, - Config.LoRaDevices[Channel].Longitude, - Config.LoRaDevices[Channel].Altitude); - } - else if ((Message[1] & 0xC0) == 0x80) - { - // Binary upload packet - int SenderID, TargetID; - - ChannelPrintf(Channel, 4, 1, "Uplink Message"); - - TargetID = Message[1] & 0x07; - SenderID = (Message[1] >> 3) & 0x07; - - LogMessage("Ch %d: Sender %d Target %d (%s) Message %s\n", - Channel, - SenderID, - TargetID, - Payloads[TargetID].Payload, - Message+2); + ProcessTelemetryMessage(Channel, Message+1); } else if (Message[1] == 0x66) { - // SSDV packet - char Callsign[7], *FileMode, *EncodedCallsign, *EncodedEncoding, *Base64Data, *EncodedData, HexString[513], Command[1000]; - int output_length; - - Message[0] = 0x55; - - CallsignCode = Message[2]; CallsignCode <<= 8; - CallsignCode |= Message[3]; CallsignCode <<= 8; - CallsignCode |= Message[4]; CallsignCode <<= 8; - CallsignCode |= Message[5]; - - decode_callsign(Callsign, CallsignCode); - - ImageNumber = Message[6]; - PacketNumber = Message[8]; - - // Create new file ? - if ((ImageNumber != PreviousImageNumber) || (PacketNumber <= PreviousPacketNumber) || (CallsignCode != PreviousCallsignCode)) - { - // New image so new file - // FileMode = "wb"; - FileMode = "ab"; - Config.LoRaDevices[Channel].SSDVMissing = PacketNumber; - } - else - { - FileMode = "ab"; - if (PacketNumber > (PreviousPacketNumber+1)) - { - Config.LoRaDevices[Channel].SSDVMissing += PacketNumber - PreviousPacketNumber - 1; - } - } - - LogMessage("SSDV Packet, Callsign %s, Image %d, Packet %d, %d Missing\n", Callsign, Message[6], Message[7] * 256 + Message[8], Config.LoRaDevices[Channel].SSDVMissing); - ChannelPrintf(Channel, 4, 1, "SSDV Packet %d bytes ", Bytes); - - PreviousImageNumber = ImageNumber; - PreviousPacketNumber = PacketNumber; - PreviousCallsignCode = CallsignCode; - - // Save to file - - sprintf(filename, "/tmp/%s_%d.bin", Callsign, ImageNumber); - - if (fp = fopen(filename, FileMode)) - { - fwrite(Message, 1, 256, fp); - fclose(fp); - } - - // Upload to server - if (Config.EnableSSDV) - { - EncodedCallsign = url_encode(Callsign); - EncodedEncoding = url_encode("hex"); - - // Base64Data = base64_encode(Message, 256, &output_length); - // printf("output_length=%d, byte=%02Xh\n", output_length, Base64Data[output_length]); - // Base64Data[output_length] = '\0'; - // printf ("Base64Data '%s'\n", Base64Data); - ConvertStringToHex(HexString, Message, 256); - EncodedData = url_encode(HexString); - - UploadImagePacket(EncodedCallsign, EncodedEncoding, EncodedData); - - free(EncodedCallsign); - free(EncodedEncoding); - // free(Base64Data); - free(EncodedData); - } - - Config.LoRaDevices[Channel].SSDVCount++; + ProcessSSDVMessage(Channel, Message); } else { @@ -1453,7 +1399,7 @@ int main(int argc, char **argv) Config.LoRaDevices[Channel].LastPacketAt = time(NULL); - if (Config.CallingTimeout > 0) + if (Config.LoRaDevices[Channel].InCallingMode && (Config.CallingTimeout > 0)) { Config.LoRaDevices[Channel].ReturnToCallingModeAt = time(NULL) + Config.CallingTimeout; } @@ -1474,8 +1420,9 @@ int main(int argc, char **argv) ChannelPrintf(Channel, 6, 1, "%us since last packet ", (unsigned int)(time(NULL) - Config.LoRaDevices[Channel].LastPacketAt)); } - if ((Config.CallingTimeout > 0) && (Config.LoRaDevices[Channel].ReturnToCallingModeAt > 0) && (time(NULL) > Config.LoRaDevices[Channel].ReturnToCallingModeAt)) + if (Config.LoRaDevices[Channel].InCallingMode && (Config.CallingTimeout > 0) && (Config.LoRaDevices[Channel].ReturnToCallingModeAt > 0) && (time(NULL) > Config.LoRaDevices[Channel].ReturnToCallingModeAt)) { + Config.LoRaDevices[Channel].InCallingMode = 0; Config.LoRaDevices[Channel].ReturnToCallingModeAt = 0; LogMessage("Return to calling mode\n"); @@ -1500,6 +1447,14 @@ int main(int argc, char **argv) { ProcessKeyPress(ch); } + + if (LEDCounts[Channel]) + { + if (--LEDCounts[Channel] == 0) + { + digitalWrite(Config.LoRaDevices[Channel].ActivityLED, 0); + } + } } } } @@ -1508,7 +1463,11 @@ int main(int argc, char **argv) CloseDisplay(mainwin); + digitalWrite(Config.NetworkLED, 0); + digitalWrite(Config.InternetLED, 0); + digitalWrite(Config.LoRaDevices[0].ActivityLED, 0); + digitalWrite(Config.LoRaDevices[1].ActivityLED, 0); + return 0; } - diff --git a/gateway.txt b/gateway.txt index 0e651e2..280e557 100755 --- a/gateway.txt +++ b/gateway.txt @@ -1,17 +1,17 @@ tracker=M0RPI -EnableHabitat=N -EnableSSDV=N -LogTelemetry=N -CallingTimeout=0 +EnableHabitat=Y +EnableSSDV=Y +LogTelemetry=Y +CallingTimeout=60 -frequency_0=434.347 +frequency_0=434.450 mode_0=1 DIO0_0=31 DIO5_0=26 -AFC_0=N +AFC_0=Y -frequency_1=434.475 +#frequency_1=434.450 mode_1=1 DIO0_1=6 DIO5_1=5 -AFC_1=N +AFC_1=Y diff --git a/global.h b/global.h index 9819ff5..0901d97 100755 --- a/global.h +++ b/global.h @@ -31,6 +31,8 @@ struct TLoRaDevice time_t LastPacketAt; float AscentRate; time_t ReturnToCallingModeAt; + int InCallingMode; + int ActivityLED; }; struct TConfig @@ -45,6 +47,10 @@ struct TConfig char ftpPassword[32]; char ftpFolder[64]; struct TLoRaDevice LoRaDevices[2]; + int NetworkLED; + int InternetLED; }; -extern struct TConfig Config; \ No newline at end of file +extern struct TConfig Config; + +void LogMessage(const char *format, ...); \ No newline at end of file diff --git a/habitat.c b/habitat.c new file mode 100755 index 0000000..db8e4b5 --- /dev/null +++ b/habitat.c @@ -0,0 +1,28 @@ +#include +#include +#include +#include +#include // Standard input/output definitions +#include // String function definitions +#include // UNIX standard function definitions +#include // File control definitions +#include // Error number definitions +#include // POSIX terminal control definitions +#include +#include +#include +#include +#include + +#include "habitat.h" +#include "global.h" + + +void *HabitatLoop(void *some_void_ptr) +{ + while (1) + { + + sleep(5); + } +} diff --git a/habitat.h b/habitat.h new file mode 100755 index 0000000..a0048ff --- /dev/null +++ b/habitat.h @@ -0,0 +1 @@ +void *HabitatLoop(void *some_void_ptr); \ No newline at end of file diff --git a/loop b/loop new file mode 100755 index 0000000..6bdb9ec --- /dev/null +++ b/loop @@ -0,0 +1,5 @@ +#!/bin/bash +while : +do + sudo ./gateway +done diff --git a/makefile b/makefile index b81d8d6..8ed6a32 100755 --- a/makefile +++ b/makefile @@ -1,12 +1,21 @@ -gateway: gateway.o urlencode.o base64.o ssdv.o ssdv.h global.h - cc -o gateway gateway.o urlencode.o base64.o ssdv.o -lm -lwiringPi -lwiringPiDev -lcurl -lncurses -lpthread +gateway: gateway.o urlencode.o base64.o habitat.o ssdv.o ftp.o network.o + cc -o gateway gateway.o urlencode.o base64.o habitat.o ssdv.o ftp.o network.o -lm -lwiringPi -lwiringPiDev -lcurl -lncurses -lpthread gateway.o: gateway.c global.h gcc -c gateway.c +habitat.o: habitat.c habitat.h global.h + gcc -c habitat.c + ssdv.o: ssdv.c ssdv.h global.h gcc -c ssdv.c +ftp.o: ftp.c ftp.h global.h + gcc -c ftp.c + +network.o: network.c network.h global.h + gcc -c network.c + urlencode.o: urlencode.c gcc -c urlencode.c diff --git a/network.c b/network.c new file mode 100755 index 0000000..0c8a7e5 --- /dev/null +++ b/network.c @@ -0,0 +1,109 @@ +#include +#include +#include +#include +#include // Standard input/output definitions +#include // String function definitions +#include // UNIX standard function definitions +#include // File control definitions +#include // Error number definitions +#include // POSIX terminal control definitions +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "network.h" +#include "global.h" + +int HaveAnIPAddress(void) +{ + struct ifaddrs *ifap, *ifa; + struct sockaddr_in *sa; + char *addr; + int FoundAddress; + + FoundAddress = 0; + + getifaddrs (&ifap); + for (ifa = ifap; ifa; ifa = ifa->ifa_next) + { + if (ifa->ifa_addr->sa_family==AF_INET) + { + sa = (struct sockaddr_in *) ifa->ifa_addr; + addr = inet_ntoa(sa->sin_addr); + if (strcmp(addr, "127.0.0.1") != 0) + { + FoundAddress = 1; + } + } + } + + freeifaddrs(ifap); + + return FoundAddress; +} + +int CanSeeTheInternet(void) +{ + struct addrinfo hints, *res, *p; + int status, sockfd, FoundInternet; + + memset(&hints, 0, sizeof hints); + hints.ai_family = AF_UNSPEC; // AF_INET or AF_INET6 to force version + hints.ai_socktype = SOCK_STREAM; + + if ((status = getaddrinfo("google.com", "80", &hints, &res)) != 0) + { + return 0; + } + + sockfd = socket(res->ai_family, res->ai_socktype, res->ai_protocol); + + FoundInternet = 1; + if(connect(sockfd, res->ai_addr, res->ai_addrlen) == -1) + { + FoundInternet = 0; + } + + close(sockfd); + + freeaddrinfo(res); // free the linked list + + return FoundInternet; +} + +void *NetworkLoop(void *some_void_ptr) +{ + while (1) + { + digitalWrite(Config.NetworkLED, 0); + digitalWrite(Config.InternetLED, 0); + if (HaveAnIPAddress()) + { + digitalWrite(Config.NetworkLED, 1); +// LogMessage("On network :-)\n"); + + if (CanSeeTheInternet()) + { + digitalWrite(Config.InternetLED, 1); +// LogMessage("On the internet :-)\n"); + } + else + { +// LogMessage("Not on internet :-(\n"); + } + } + else + { +// LogMessage("No network :-(\n"); + } + + sleep(5); + } +} diff --git a/network.h b/network.h new file mode 100755 index 0000000..d2df8d6 --- /dev/null +++ b/network.h @@ -0,0 +1 @@ +void *NetworkLoop(void *some_void_ptr); \ No newline at end of file diff --git a/ssdv.c b/ssdv.c index 0e007d2..9dbe9f0 100755 --- a/ssdv.c +++ b/ssdv.c @@ -17,63 +17,11 @@ #include "ssdv.h" #include "global.h" -void ConvertFile(char *FileName) -{ - char TargetFile[100], CommandLine[200], *ptr; - - // printf("Found file %s to convert\n", FileName); - - strcpy(TargetFile, FileName); - ptr = strchr(TargetFile, '.'); - if (ptr) - { - *ptr = '\0'; - strcat(TargetFile, ".JPG"); - - // Now convert the file - sprintf(CommandLine, "ssdv -d /tmp/%s %s 2> /dev/null > /dev/null", FileName, TargetFile); - system(CommandLine); - - if (Config.ftpServer[0] && Config.ftpUser[0] && Config.ftpPassword[0]) - { - // Upload to ftp server - sprintf(CommandLine, "curl -T %s %s -Q \"TYPE I\" --user %s:%s 2> /dev/null > /dev/null", TargetFile, Config.ftpServer, Config.ftpUser, Config.ftpPassword); - system(CommandLine); - } - } -} - void *SSDVLoop(void *some_void_ptr) { while (1) { - DIR *dp; - struct dirent *ep; - struct stat st; - char *SSDVFolder; - char FileName[100]; - - SSDVFolder = "/tmp"; - - dp = opendir(SSDVFolder); - if (dp != NULL) - { - while (ep = readdir (dp)) - { - if (strstr(ep->d_name, ".bin") != NULL) - { - sprintf(FileName, "%s/%s", SSDVFolder, ep->d_name); - stat(FileName, &st); - // printf ("Age of '%s' is %ld seconds\n", FileName, time(0) - st.st_mtime); - if ((time(0) - st.st_mtime) < 20) - { - ConvertFile(ep->d_name); - } - } - } - } - (void) closedir (dp); sleep(5); } From 06839a2eecfd839806fa6d6e9c12d8c68f660614 Mon Sep 17 00:00:00 2001 From: Dave Akerman Date: Tue, 28 Jul 2015 19:52:31 +0000 Subject: [PATCH 2/2] Protect against fault if VPN client active; status LED pins configurable --- ftp.c | 6 +-- gateway | Bin 45007 -> 45953 bytes gateway.c | 107 ++++++++++++++++++++++++++++++++++++++++++---------- gateway.txt | 11 ++++-- network.c | 21 +++++++---- 5 files changed, 112 insertions(+), 33 deletions(-) diff --git a/ftp.c b/ftp.c index fa31281..f4c61c1 100755 --- a/ftp.c +++ b/ftp.c @@ -29,11 +29,11 @@ void ConvertFile(char *FileName) strcat(TargetFile, ".JPG"); // Now convert the file + LogMessage("Converting %s to %s\n", FileName, TargetFile); + sprintf(CommandLine, "ssdv -d /tmp/%s %s 2> /dev/null > /dev/null", FileName, TargetFile); system(CommandLine); - - LogMessage("Converting %s to %s\n", FileName, TargetFile); - + if (Config.ftpServer[0] && Config.ftpUser[0] && Config.ftpPassword[0]) { // Upload to ftp server diff --git a/gateway b/gateway index c71171d99dfc805436e615ff4642e37b7e30b8d6..0becd28480ace28450cb295786d6813147ce2e53 100755 GIT binary patch delta 17767 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 b_8-56{MOrFI^z?m`|sjj{Y-BEP0RlRX3aIA delta 16056 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%0A@5M+4I#NCGwghJUk4t-e6-TRl4RPE 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 a^p9V;D5YT@z0@$j@$U_70rc_Pzy5FUCE`Q? diff --git a/gateway.c b/gateway.c index 6b285cd..c438528 100755 --- a/gateway.c +++ b/gateway.c @@ -17,6 +17,7 @@ #include #include #include +#include #include #include @@ -701,15 +702,26 @@ void LoadConfigFile() exit(1); } + // Receiver config ReadString(fp, "tracker", Config.Tracker, sizeof(Config.Tracker), 1); LogMessage("Tracker = '%s'\n", Config.Tracker); + // Enable uploads ReadBoolean(fp, "EnableHabitat", 0, &Config.EnableHabitat); ReadBoolean(fp, "EnableSSDV", 0, &Config.EnableSSDV); + + // Enable logging ReadBoolean(fp, "LogTelemetry", 0, &Config.EnableTelemetryLogging); + // Calling mode Config.CallingTimeout = ReadInteger(fp, "CallingTimeout", 0, 300); + // LED allocations + Config.NetworkLED = ReadInteger(fp, "NetworkLED", 0, -1); + Config.InternetLED = ReadInteger(fp, "InternetLED", 0, -1); + Config.LoRaDevices[0].ActivityLED = ReadInteger(fp, "ActivityLED_0", 0, -1); + Config.LoRaDevices[1].ActivityLED = ReadInteger(fp, "ActivityLED_1", 0, -1); + ReadString(fp, "ftpserver", Config.ftpServer, sizeof(Config.ftpServer), 0); ReadString(fp, "ftpUser", Config.ftpUser, sizeof(Config.ftpUser), 0); ReadString(fp, "ftpPassword", Config.ftpPassword, sizeof(Config.ftpPassword), 0); @@ -1268,6 +1280,55 @@ void ProcessSSDVMessage(int Channel, char *Message) Config.LoRaDevices[Channel].SSDVCount++; } + +int prog_count(char* name) +{ + DIR* dir; + struct dirent* ent; + char buf[512]; + long pid; + char pname[100] = {0,}; + char state; + FILE *fp=NULL; + int Count=0; + + if (!(dir = opendir("/proc"))) + { + perror("can't open /proc"); + return 0; + } + + while((ent = readdir(dir)) != NULL) + { + long lpid = atol(ent->d_name); + if (lpid < 0) + continue; + snprintf(buf, sizeof(buf), "/proc/%ld/stat", lpid); + fp = fopen(buf, "r"); + + if (fp) + { + if ((fscanf(fp, "%ld (%[^)]) %c", &pid, pname, &state)) != 3 ) + { + printf("fscanf failed \n"); + fclose(fp); + closedir(dir); + return 0; + } + + if (!strcmp(pname, name)) + { + Count++; + } + fclose(fp); + } + } + + closedir(dir); + + return Count; +} + int main(int argc, char **argv) { unsigned char Message[257], Command[200], Telemetry[100], *dest, *src; @@ -1277,6 +1338,12 @@ int main(int argc, char **argv) WINDOW * mainwin; int LEDCounts[2]; + if (prog_count("gateway") > 1) + { + printf("\nThe gateway program is already running!\n\n"); + exit(1); + } + mainwin = InitDisplay(); // Settings for character input @@ -1302,12 +1369,6 @@ int main(int argc, char **argv) Config.LoRaDevices[1].DIO0 = 27; Config.LoRaDevices[1].DIO5 = 26; - Config.NetworkLED = 21; - Config.InternetLED = 22; - - Config.LoRaDevices[0].ActivityLED = 23; - Config.LoRaDevices[1].ActivityLED = 24; - LoadConfigFile(); LoadPayloadFiles(); @@ -1317,10 +1378,10 @@ int main(int argc, char **argv) exit(1); } - pinMode(Config.LoRaDevices[0].ActivityLED, OUTPUT); - pinMode(Config.LoRaDevices[1].ActivityLED, OUTPUT); - pinMode(Config.InternetLED, OUTPUT); - pinMode(Config.NetworkLED, OUTPUT); + if (Config.LoRaDevices[0].ActivityLED >= 0) pinMode(Config.LoRaDevices[0].ActivityLED, OUTPUT); + if (Config.LoRaDevices[1].ActivityLED >= 0) pinMode(Config.LoRaDevices[1].ActivityLED, OUTPUT); + if (Config.InternetLED >= 0) pinMode(Config.InternetLED, OUTPUT); + if (Config.NetworkLED >= 0) pinMode(Config.NetworkLED, OUTPUT); setupRFM98(0); setupRFM98(1); @@ -1349,10 +1410,13 @@ int main(int argc, char **argv) return 1; } - if (pthread_create(&NetworkThread, NULL, NetworkLoop, NULL)) + if ((Config.NetworkLED >= 0) && (Config.InternetLED >= 0)) { - fprintf(stderr, "Error creating Network thread\n"); - return 1; + if (pthread_create(&NetworkThread, NULL, NetworkLoop, NULL)) + { + fprintf(stderr, "Error creating Network thread\n"); + return 1; + } } while (run) @@ -1369,8 +1433,11 @@ int main(int argc, char **argv) if (Bytes > 0) { - digitalWrite(Config.LoRaDevices[Channel].ActivityLED, 1); - LEDCounts[Channel] = 5; + if (Config.LoRaDevices[Channel].ActivityLED >= 0) + { + digitalWrite(Config.LoRaDevices[Channel].ActivityLED, 1); + LEDCounts[Channel] = 5; + } // LogMessage("Channel %d data available - %d bytes\n", Channel, Bytes); // LogMessage("Line = '%s'\n", Message); @@ -1448,7 +1515,7 @@ int main(int argc, char **argv) ProcessKeyPress(ch); } - if (LEDCounts[Channel]) + if (LEDCounts[Channel] && (Config.LoRaDevices[Channel].ActivityLED >= 0)) { if (--LEDCounts[Channel] == 0) { @@ -1463,10 +1530,10 @@ int main(int argc, char **argv) CloseDisplay(mainwin); - digitalWrite(Config.NetworkLED, 0); - digitalWrite(Config.InternetLED, 0); - digitalWrite(Config.LoRaDevices[0].ActivityLED, 0); - digitalWrite(Config.LoRaDevices[1].ActivityLED, 0); + if (Config.NetworkLED >= 0) digitalWrite(Config.NetworkLED, 0); + if (Config.InternetLED >= 0) digitalWrite(Config.InternetLED, 0); + if (Config.LoRaDevices[0].ActivityLED >= 0) digitalWrite(Config.LoRaDevices[0].ActivityLED, 0); + if (Config.LoRaDevices[1].ActivityLED >= 0) digitalWrite(Config.LoRaDevices[1].ActivityLED, 0); return 0; } diff --git a/gateway.txt b/gateway.txt index 280e557..5d40a15 100755 --- a/gateway.txt +++ b/gateway.txt @@ -1,9 +1,14 @@ tracker=M0RPI -EnableHabitat=Y -EnableSSDV=Y -LogTelemetry=Y +EnableHabitat=N +EnableSSDV=N +LogTelemetry=N CallingTimeout=60 +#NetworkLED=21 +#InternetLED=22 +#ActivityLED_0=23 +#ActivityLED_1=24 + frequency_0=434.450 mode_0=1 DIO0_0=31 diff --git a/network.c b/network.c index 0c8a7e5..698b079 100755 --- a/network.c +++ b/network.c @@ -30,16 +30,23 @@ int HaveAnIPAddress(void) FoundAddress = 0; - getifaddrs (&ifap); - for (ifa = ifap; ifa; ifa = ifa->ifa_next) + if (getifaddrs(&ifap) == 0) { - if (ifa->ifa_addr->sa_family==AF_INET) + // Success + for (ifa = ifap; ifa; ifa = ifa->ifa_next) { - sa = (struct sockaddr_in *) ifa->ifa_addr; - addr = inet_ntoa(sa->sin_addr); - if (strcmp(addr, "127.0.0.1") != 0) + if (ifa->ifa_addr != NULL) { - FoundAddress = 1; + // Family is known (which it isn't for a VPN) + if (ifa->ifa_addr->sa_family==AF_INET) + { + sa = (struct sockaddr_in *) ifa->ifa_addr; + addr = inet_ntoa(sa->sin_addr); + if (strcmp(addr, "127.0.0.1") != 0) + { + FoundAddress = 1; + } + } } } }