David Brooke 2016-09-20 15:43:32 +01:00
commit 3c8a3a7f39
10 zmienionych plików z 1013 dodań i 574 usunięć

30
*.dpa 100644
Wyświetl plik

@ -0,0 +1,30 @@
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,27 @@ Many thanks to David Brooke for coding this feature and the AFC.
Change History
==============
14/09/2016 - V1.8.3
-------------------
Save boolean settings sent by client
Use of atexit() so ncurses is always closed properly on exit
Added an exit-with-message function
Fixed errors where threads were closed on exit even if they hadn't been created (i.e. their functions disabled in the config)
Consistent RSSI calculations that take HF/LF port into account
14/09/2016 - V1.8.2
-------------------
Configuration all in a generic array
Generic code to read/write config array/file
Send configuration values to JSON client
Accept commands and new config settings from client
Fixed SMS folder error
Fixed LDRO setting
03/09/2016 - V1.8
-----------------

394
config.c 100755
Wyświetl plik

@ -0,0 +1,394 @@
//// Generalised configuration manager
// Generalised configuration manager
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include "config.h"
#define MAX_SECTIONS 16
#define SECTION_LENGTH 21
#define MAX_SETTINGS 256
char *ConfigFilename;
int SectionCount=0;
char Sections[MAX_SECTIONS][32];
int SettingsCount=0;
struct TSetting Settings[MAX_SETTINGS];
void RegisterConfigFile(char *Filename)
{
ConfigFilename = Filename;
}
int RegisterConfigSection(char *Section)
{
int i;
for (i=0; i<SectionCount; i++)
{
if (strcmp(Section, Sections[i]) == 0)
{
return i;
}
}
if (SectionCount < MAX_SECTIONS)
{
strcpy(Sections[SectionCount], Section);
return SectionCount++;
}
return -1;
}
int FindSettingIndex(int SectionIndex, int Index, char *Name)
{
// Return existing position for this setting, if it's there, or allocate a new one
int i;
for (i=0; i<SettingsCount; i++)
{
if ((Settings[i].SectionIndex == SectionIndex) &&
(Settings[i].Index == Index) &&
(strcmp(Settings[i].ValueName, Name) == 0))
{
// Found
return i;
}
}
// Room for one more on top ?
if (SettingsCount < MAX_SETTINGS)
{
Settings[SettingsCount].SectionIndex = SectionIndex;
Settings[SettingsCount].Index = Index;
strcpy(Settings[SettingsCount].ValueName, Name);
return SettingsCount++;
}
// Full or can't add, and not found, so return "fail"
return -1;
}
int RegisterConfigDouble(int SectionIndex, int Index, char *Name, double *DoubleValuePtr, void (Callback)(int))
{
if ((SectionIndex >= 0) && (SectionIndex < SectionCount))
{
int SettingIndex;
if ((SettingIndex = FindSettingIndex(SectionIndex, Index, Name)) >= 0)
{
Settings[SettingIndex].SectionIndex = SectionIndex;
Settings[SettingIndex].Index = Index;
strcpy(Settings[SettingIndex].ValueName, Name);
Settings[SettingIndex].SettingType = stDouble;
Settings[SettingIndex].DoubleValuePtr = DoubleValuePtr;
// Settings[SettingIndex].Callback = Callback;
ReadConfigValue(SettingIndex);
}
}
return 0;
}
int RegisterConfigInteger(int SectionIndex, int Index, char *Name, int *IntValuePtr, void (Callback)(int))
{
if ((SectionIndex >= 0) && (SectionIndex < SectionCount))
{
int SettingIndex;
if ((SettingIndex = FindSettingIndex(SectionIndex, Index, Name)) >= 0)
{
Settings[SettingIndex].SectionIndex = SectionIndex;
Settings[SettingIndex].Index = Index;
strcpy(Settings[SettingIndex].ValueName, Name);
Settings[SettingIndex].SettingType = stInteger;
Settings[SettingIndex].IntValuePtr = IntValuePtr;
// Settings[SettingIndex].Callback = Callback;
return ReadConfigValue(SettingIndex);
}
}
return 0;
}
int RegisterConfigBoolean(int SectionIndex, int Index, char *Name, int *BoolValuePtr, void (Callback)(int))
{
if ((SectionIndex >= 0) && (SectionIndex < SectionCount))
{
int SettingIndex;
if ((SettingIndex = FindSettingIndex(SectionIndex, Index, Name)) >= 0)
{
Settings[SettingIndex].SectionIndex = SectionIndex;
Settings[SettingIndex].Index = Index;
strcpy(Settings[SettingIndex].ValueName, Name);
Settings[SettingIndex].SettingType = stBoolean;
Settings[SettingIndex].IntValuePtr = BoolValuePtr;
// Settings[SettingIndex].Callback = Callback;
return ReadConfigValue(SettingIndex);
}
}
return 0;
}
int RegisterConfigString(int SectionIndex, int Index, char *Name, char *StringValuePtr, int MaxValueLength, void (Callback)(int))
{
if ((SectionIndex >= 0) && (SectionIndex < SectionCount))
{
int SettingIndex;
if ((SettingIndex = FindSettingIndex(SectionIndex, Index, Name)) >= 0)
{
Settings[SettingIndex].SectionIndex = SectionIndex;
Settings[SettingIndex].Index = Index;
strcpy(Settings[SettingIndex].ValueName, Name);
Settings[SettingIndex].SettingType = stString;
Settings[SettingIndex].StringValuePtr = StringValuePtr;
Settings[SettingIndex].MaxValueLength = MaxValueLength;
// Settings[SettingIndex].Callback = Callback;
return ReadConfigValue(SettingIndex);
}
}
return 0;
}
void GetLongName(int SettingIndex, char *ValueName, int Length)
{
struct TSetting *Setting;
Setting = &(Settings[SettingIndex]);
// Build string to look for in file
if (Setting->Index >= 0)
{
sprintf(ValueName, "%s%s_%d", Sections[Setting->SectionIndex], Setting->ValueName, Setting->Index);
}
else
{
sprintf(ValueName, "%s%s", Sections[Setting->SectionIndex], Setting->ValueName);
}
}
int ReadConfigValue(int SettingIndex)
{
char line[100], ValueName[64], *token, *temp;
struct TSetting *Setting;
FILE *fp;
GetLongName(SettingIndex, ValueName, sizeof(ValueName));
Setting = &(Settings[SettingIndex]);
if ((fp = fopen(ConfigFilename, "r" ) ) != NULL)
{
while (fgets(line, sizeof(line), fp) != NULL)
{
line[strcspn(line, "\r")] = '\0'; // Get rid of CR if there is one
token = strtok(line, "=" );
if (strcasecmp(ValueName, token ) == 0)
{
temp = strtok( NULL, "\n");
switch (Setting->SettingType)
{
case stString:
strncpy(Setting->StringValuePtr, temp, Setting->MaxValueLength-1);
break;
case stInteger:
*(Setting->IntValuePtr) = atoi(temp);
break;
case stDouble:
// So we can handle bandwidths such as "20K8", convert "K" to decimal point
if (strchr(temp, 'K') != NULL)
{
*strchr(temp, 'K') = '.';
}
*(Setting->DoubleValuePtr) = atof(temp);
break;
case stBoolean:
*(Setting->IntValuePtr) = (*temp == '1') || (*temp == 'Y') || (*temp == 'y') || (*temp == 't') || (*temp == 'T');
break;
case stNone:
break;
}
fclose(fp);
return 1;
}
}
fclose(fp);
}
return 0;
}
int FindSettingByName(char *ValueNameToFind)
{
char ValueName[64];
int SettingIndex;
for (SettingIndex=0; SettingIndex<SettingsCount; SettingIndex++)
{
GetLongName(SettingIndex, ValueName, sizeof(ValueName));
if (strcasecmp(ValueNameToFind, ValueName) == 0)
{
// Found
return SettingIndex;
}
}
return -1;
}
void SaveConfigFile(void)
{
char line[100], original[100], *token;
FILE *src, *dest;
struct TSetting *Setting;
char *TempFileName="gateway.txt.tmp";
char *SavedFileName="gateway.txt.old";
int SettingIndex;
if ((src = fopen(ConfigFilename, "r" ) ) != NULL)
{
if ((dest = fopen(TempFileName, "w" ) ) != NULL)
{
while (fgets(line, sizeof(line), src) != NULL)
{
line[strcspn(line, "\r")] = '\0'; // Get rid of CR if there is one
strcpy(original, line);
token = strtok(line, "=" ); // Name of setting
if (token == NULL)
{
// Write old line
fputs(original, dest);
}
else if ((SettingIndex = FindSettingByName(token)) >= 0)
{
// Found, so write new value instead of old one
// tracker=M0RPI/5
Setting = &(Settings[SettingIndex]);
switch (Setting->SettingType)
{
case stString:
fprintf(dest, "%s=%s\n", token, Setting->StringValuePtr);
break;
case stInteger:
fprintf(dest, "%s=%d\n", token, *(Setting->IntValuePtr));
break;
case stDouble:
fprintf(dest, "%s=%lf\n", token, *(Setting->DoubleValuePtr));
break;
case stBoolean:
fprintf(dest, "%s=%c\n", token, *(Setting->IntValuePtr) ? 'Y' : 'N');
break;
case stNone:
break;
}
}
else
{
// Just write old line
fputs(original, dest);
}
}
fclose(dest);
// Now save original file and replace with new one
remove(SavedFileName);
rename(ConfigFilename, SavedFileName);
rename(TempFileName, ConfigFilename);
}
fclose(src);
}
}
void SetConfigValue(char *Setting, char *Value)
{
int SettingIndex;
if ((SettingIndex = FindSettingByName(Setting)) >= 0)
{
switch (Settings[SettingIndex].SettingType)
{
case stString:
strncpy(Settings[SettingIndex].StringValuePtr, Value, Settings[SettingIndex].MaxValueLength-1);
break;
case stInteger:
*Settings[SettingIndex].IntValuePtr = atoi(Value);
break;
case stDouble:
*Settings[SettingIndex].DoubleValuePtr = atof(Value);
break;
case stBoolean:
*Settings[SettingIndex].IntValuePtr = Value[strcspn(Value, "1YyTt")];
break;
case stNone:
break;
}
}
}
int SettingAsString(int SettingIndex, char *SettingName, int SettingNameSize, char *SettingValue, int SettingValueSize)
{
if ((SettingIndex >= 0) && (SettingIndex < SettingsCount))
{
// strncpy(SettingName, Settings[Index].ValueName, SettingNameSize);
GetLongName(SettingIndex, SettingName, sizeof(SettingNameSize));
switch (Settings[SettingIndex].SettingType)
{
case stString:
snprintf(SettingValue, SettingValueSize-1, "\"%s\"", Settings[SettingIndex].StringValuePtr);
break;
case stInteger:
snprintf(SettingValue, SettingValueSize-1, "%d", *Settings[SettingIndex].IntValuePtr);
break;
case stDouble:
snprintf(SettingValue, SettingValueSize-1, "%lf", *Settings[SettingIndex].DoubleValuePtr);
break;
case stBoolean:
snprintf(SettingValue, SettingValueSize-1, "%d", *Settings[SettingIndex].IntValuePtr ? 1 : 0);
break;
case stNone:
strncpy(SettingValue, "\"?\"", SettingValueSize);
break;
}
return 1;
}
return 0;
}

27
config.h 100755
Wyświetl plik

@ -0,0 +1,27 @@
typedef enum {stNone, stString, stInteger, stDouble, stBoolean} TSettingType;
struct TSetting
{
int SectionIndex;
int Index;
char ValueName[32];
TSettingType SettingType;
char *StringValuePtr;
int *IntValuePtr;
double *DoubleValuePtr;
int MaxValueLength;
// void (Callback)(int);
};
void RegisterConfigFile(char *Filename);
int RegisterConfigSection(char *Section);
int RegisterConfigString(int SectionIndex, int Index, char *Name, char *StringValuePtr, int MaxValueLength, void (Callback)(int));
int RegisterConfigInteger(int SectionIndex, int Index, char *Name, int *IntValuePtr, void (Callback)(int));
int RegisterConfigDouble(int SectionIndex, int Index, char *Name, double *DoubleValuePtr, void (Callback)(int));
int RegisterConfigBoolean(int SectionIndex, int Index, char *Name, int *BoolValuePtr, void (Callback)(int));
int ReadConfigValue(int SettingIndex);
void SetConfigValue(char *Setting, char *Value);
int SettingAsString(int SettingIndex, char *SettingName, int SettingNameSize, char *SettingValue, int SettingValueSize);
void SaveConfigFile(void);

945
gateway.c

Plik diff jest za duży Load Diff

34
gateway.txt.old 100644
Wyświetl plik

@ -0,0 +1,34 @@
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

Wyświetl plik

@ -11,23 +11,23 @@
int HighestPacket;
bool Packets[1024];
};
struct TLoRaDevice {
int InUse;
struct TLoRaDevice {
double Frequency;
double Bandwidth;
double CurrentBandwidth;
int InUse;
int DIO0;
int DIO5;
char Frequency[16];
double activeFreq;
bool AFC;
int AFC;
int SpeedMode;
int Power;
int PayloadLength;
int ImplicitOrExplicit;
int ErrorCoding;
int Bandwidth;
int SpreadingFactor;
int LowDataRateOptimize;
int CurrentBandwidth;
WINDOW * Window;
WINDOW * Window;
unsigned int TelemetryCount, SSDVCount, BadCRCCount, UnknownCount;
int Sending;
char Telemetry[256];
@ -59,8 +59,8 @@ int UplinkMode;
// SSDV Packet Log
struct TSSDVPackets SSDVPackets[3];
};
struct TConfig {
char Tracker[16];
struct TConfig { char Tracker[16]; // Callsign or name of receiver
double latitude, longitude; // Receiver's location
int EnableHabitat;
int EnableSSDV;
int EnableTelemetryLogging;
@ -75,8 +75,7 @@ int UplinkMode;
int NetworkLED;
int InternetLED;
int ServerPort;
float latitude, longitude;
char SMSFolder[64];
char SMSFolder[64];
char antenna[64];
int EnableDev;
};

Wyświetl plik

@ -232,6 +232,7 @@ HabitatLoop( void *vars )
total_packets++;
}
delay(100); // Don't eat too much CPU
}
}

112
server.c
Wyświetl plik

@ -4,8 +4,8 @@
#include <ctype.h>
#include <stdio.h> // Standard input/output definitions
#include <string.h> // String function definitions
#include <unistd.h> // UNIX standard function definitions
#include <fcntl.h> // File control definitions
#include <unistd.h> // UNIX standard function definitions
#include <errno.h> // Error number definitions
#include <termios.h> // POSIX terminal control definitions
#include <stdint.h>
@ -13,24 +13,80 @@
#include <dirent.h>
#include <math.h>
#include <pthread.h>
#include <wiringPi.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include "server.h"
#include "config.h"
#include "global.h"
extern bool run;
extern bool server_closed;
void ProcessClientLine(int connfd, char *line)
{
line[strcspn(line, "\r\n")] = '\0'; // Get rid of CR LF
LogMessage("Received %s from client\n", line);
if (strchr(line, '=') == NULL)
{
// Request or command
if (strcasecmp(line, "settings") == 0)
{
int Index;
char SettingName[64], SettingValue[256], packet[4096];
LogMessage("Responding to settings request\n");
Index = 0;
packet[0] = '\0';
while (SettingAsString(Index, SettingName, sizeof(SettingName), SettingValue, sizeof(SettingValue)))
{
char temp[300];
sprintf(temp, "{\"class\":\"SET\",\"set\":\"%s\",\"val\":%s}\r\n", SettingName, SettingValue);
if ((strlen(temp) + strlen(packet)) < sizeof(packet))
{
strcat(packet, temp);
}
Index++;
}
send(connfd, packet, strlen(packet), MSG_NOSIGNAL);
}
else if (strcasecmp(line, "save") == 0)
{
LogMessage("Saving Settings\n");
SaveConfigFile();
}
}
else
{
// Setting
char *setting, *value, *saveptr;
setting = strtok_r(line, "=", &saveptr);
value = strtok_r( NULL, "\n", &saveptr);
SetConfigValue(setting, value);
}
}
void *ServerLoop( void *some_void_ptr )
{
int listenfd = 0, connfd = 0;
int sockfd = 0;
struct sockaddr_in serv_addr;
char sendBuff[1025];
listenfd = socket( AF_INET, SOCK_STREAM, 0 );
sockfd = socket( AF_INET, SOCK_STREAM, 0 );
memset( &serv_addr, '0', sizeof( serv_addr ) );
memset( sendBuff, '0', sizeof( sendBuff ) );
@ -40,7 +96,7 @@ void *ServerLoop( void *some_void_ptr )
LogMessage( "Listening on port %d\n", Config.ServerPort );
if ( setsockopt( listenfd, SOL_SOCKET, SO_REUSEADDR, &( int )
if ( setsockopt( sockfd, SOL_SOCKET, SO_REUSEADDR, &( int )
{
1}, sizeof( int ) ) < 0 )
{
@ -48,28 +104,58 @@ void *ServerLoop( void *some_void_ptr )
}
if ( bind
( listenfd, ( struct sockaddr * ) &serv_addr,
( sockfd, ( struct sockaddr * ) &serv_addr,
sizeof( serv_addr ) ) < 0 )
{
LogMessage( "Server failed errno %d\n", errno );
exit( -1 );
}
listen( listenfd, 10 );
listen( sockfd, 10 );
while ( run )
{
int port_closed;
int SendEveryMS = 1000;
int MSPerLoop=100;
int ms, port_closed, connfd;
connfd = accept( listenfd, ( struct sockaddr * ) NULL, NULL );
fcntl(sockfd, F_SETFL, fcntl(sockfd, F_GETFL) & ~O_NONBLOCK); // Blocking mode so we wait for a connection
connfd = accept( sockfd, ( struct sockaddr * ) NULL, NULL ); // Wait for connection
LogMessage( "Connected to client\n" );
fcntl(connfd, F_SETFL, fcntl(sockfd, F_GETFL) | O_NONBLOCK); // Non-blocking, so we don't block on receiving any commands from client
for ( port_closed = 0; !port_closed; )
{
int Channel;
// Build json
// sprintf(sendBuff, "{\"class\":\"POSN\",\"time\":\"12:34:56\",\"lat\":54.12345,\"lon\":-2.12345,\"alt\":169}\r\n");
char packet[4096];
// Listen loop
for (ms=0; ms<SendEveryMS; ms+=MSPerLoop)
{
int bytecount;
while ((bytecount = recv(connfd, packet, sizeof(packet), 0)) > 0)
{
char *line, *saveptr;
packet[bytecount] = 0;
line = strtok_r(packet, "\n", &saveptr);
while (line)
{
ProcessClientLine(connfd, line);
line = strtok_r( NULL, "\n", &saveptr);
}
}
delay(MSPerLoop);
}
// Send part
// Build json
for (Channel=0; Channel<=1; Channel++)
{
@ -123,10 +209,6 @@ void *ServerLoop( void *some_void_ptr )
LogMessage( "Disconnected from client\n" );
port_closed = 1;
}
else
{
sleep(1);
}
}
}

2
ssdv.c
Wyświetl plik

@ -195,7 +195,7 @@ SSDVLoop( void *vars )
packets = 0;
}
delay(100); // Don't eat too much CPU
}
}