V1.8 - Various fixes; extra uplink config; JSON changes

pull/26/head
Dave Akerman 2016-09-03 06:32:10 +00:00
rodzic 97e532d58e
commit c92f0cac24
25 zmienionych plików z 3321 dodań i 2625 usunięć

30
Makefile 100644
Wyświetl plik

@ -0,0 +1,30 @@
# RJH Generic makefile
SRC=$(wildcard *.c)
HED=$(wildcard *.h)
OBJ=$(SRC:.c=.o) # replaces the .c from SRC with .o
EXE=gateway
INDOPT= -bap -bl -blf -bli0 -brs -cbi0 -cdw -cs -ci4 -cli4 -i4 -ip0 -nbc -nce -lp -npcs -nut -pmt -psl -prs -ts4
CC=gcc
CFLAGS=-Wall -O3 #-std=c99
LDFLAGS= -lm -lwiringPi -lwiringPiDev -lcurl -lncurses -lpthread
RM=rm
%.o: %.c # combined w/ next line will compile recently changed .c files
$(CC) $(CFLAGS) -o $@ -c $<
.PHONY : all # .PHONY ignores files named all
all: $(EXE) # all is dependent on $(EXE) to be complete
$(EXE): $(OBJ) # $(EXE) is dependent on all of the files in $(OBJ) to exist
$(CC) $(OBJ) $(LDFLAGS) -o $@
.PHONY : clean # .PHONY ignores files named clean
clean:
-$(RM) $(OBJ)
tidy:
indent $(INDOPT) $(SRC) $(HED)
rm *~

Wyświetl plik

@ -46,9 +46,7 @@ Install the LoRa gateway
2. git clone https://github.com/PiInTheSky/lora-gateway.git
3. cd lora-gateway
4. make
5. cp gateway_sample.txt gateway.txt
** That last step is new - to prevent overwriting existing configurations, gateway.txt is supplied as a sample file that you need to copy first **
5. cp gateway-sample.txt gateway.txt
@ -228,6 +226,47 @@ Many thanks to David Brooke for coding this feature and the AFC.
Change History
==============
03/09/2016 - V1.8
-----------------
Add configuration of uplink frequency, mode and power
LoRa modes now in array so easier to add new ones
Added LoRa mode for uplink
Re-instated logging to telemetry.txt
Fixed pipe errors which happened if packets arrived during program exit
Merged in changes to JSON format
Sends data both LoRa channels in JSON
Config disables CE0 by default (most cards have CE1 only)
Fixed typos in gateway-sample.txt
Accept new SSDV types
25/08/2016 - V1.7
-----------------
Robert Harrison (RJH) has made numerous changes.
Highlights include :-
Changed makefile to include -Wall and fixed all warnings generated
Added pipes for Inter-Process Communication
Moved none thread safe curl funtions from threads and into main()
Added reporting of curl errors to habitat and ssdv threads
Changed color to green but requires 256 color support in your terminal
For putty users please set your terminal as shown
![Alt text](http://i.imgur.com/B81bvEQ.png "Putty config")
when you are connected to your pi
# echo $TERM # should show something with 256 in
or
# tpu colors # Should show 256
27/06/2016 - V1.6
-----------------

Wyświetl plik

@ -9,15 +9,17 @@ static char encoding_table[] = {'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H',
'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n',
'o', 'p', 'q', 'r', 's', 't', 'u', 'v',
'w', 'x', 'y', 'z', '0', '1', '2', '3',
'4', '5', '6', '7', '8', '9', '+', '/'};
'4', '5', '6', '7', '8', '9', '+', '/'
};
static char *decoding_table = NULL;
static int mod_table[] = { 0, 2, 1 };
void *base64_encode(const unsigned char *data,
char *
base64_encode( const char *data,
size_t input_length,
size_t *output_length,
char *encoded_data)
size_t * output_length, char *encoded_data )
{
int i, j;
@ -44,11 +46,13 @@ void *base64_encode(const unsigned char *data,
for ( i = 0; i < mod_table[input_length % 3]; i++ )
encoded_data[*output_length - 1 - i] = '=';
// return encoded_data;
return encoded_data;
}
void build_decoding_table() {
void
build_decoding_table( )
{
int i;
@ -58,37 +62,49 @@ void build_decoding_table() {
decoding_table[( unsigned char ) encoding_table[i]] = i;
}
unsigned char *base64_decode(const char *data,
size_t input_length,
size_t *output_length) {
char *
base64_decode( const char *data, size_t input_length, size_t * output_length )
{
int i, j;
if (decoding_table == NULL) build_decoding_table();
if ( decoding_table == NULL )
build_decoding_table( );
if (input_length % 4 != 0) return NULL;
if ( input_length % 4 != 0 )
return NULL;
*output_length = input_length / 4 * 3;
if (data[input_length - 1] == '=') (*output_length)--;
if (data[input_length - 2] == '=') (*output_length)--;
if ( data[input_length - 1] == '=' )
( *output_length )--;
if ( data[input_length - 2] == '=' )
( *output_length )--;
unsigned char *decoded_data = malloc(*output_length);
if (decoded_data == NULL) return NULL;
char *decoded_data = malloc( *output_length );
if ( decoded_data == NULL )
return NULL;
for (i = 0, j = 0; i < input_length;) {
for ( i = 0, j = 0; i < input_length; )
{
uint32_t sextet_a = data[i] == '=' ? 0 & i++ : decoding_table[data[i++]];
uint32_t sextet_b = data[i] == '=' ? 0 & i++ : decoding_table[data[i++]];
uint32_t sextet_c = data[i] == '=' ? 0 & i++ : decoding_table[data[i++]];
uint32_t sextet_d = data[i] == '=' ? 0 & i++ : decoding_table[data[i++]];
uint32_t sextet_a =
data[i] == '=' ? 0 & i++ : decoding_table[( int ) data[i++]];
uint32_t sextet_b =
data[i] == '=' ? 0 & i++ : decoding_table[( int ) data[i++]];
uint32_t sextet_c =
data[i] == '=' ? 0 & i++ : decoding_table[( int ) data[i++]];
uint32_t sextet_d =
data[i] == '=' ? 0 & i++ : decoding_table[( int ) data[i++]];
uint32_t triple = ( sextet_a << 3 * 6 )
+ ( sextet_b << 2 * 6 )
+ (sextet_c << 1 * 6)
+ (sextet_d << 0 * 6);
+ ( sextet_c << 1 * 6 ) + ( sextet_d << 0 * 6 );
if (j < *output_length) decoded_data[j++] = (triple >> 2 * 8) & 0xFF;
if (j < *output_length) decoded_data[j++] = (triple >> 1 * 8) & 0xFF;
if (j < *output_length) decoded_data[j++] = (triple >> 0 * 8) & 0xFF;
if ( j < *output_length )
decoded_data[j++] = ( triple >> 2 * 8 ) & 0xFF;
if ( j < *output_length )
decoded_data[j++] = ( triple >> 1 * 8 ) & 0xFF;
if ( j < *output_length )
decoded_data[j++] = ( triple >> 0 * 8 ) & 0xFF;
}
return decoded_data;
@ -96,6 +112,8 @@ unsigned char *base64_decode(const char *data,
void base64_cleanup() {
void
base64_cleanup( )
{
free( decoding_table );
}

Wyświetl plik

@ -1,3 +1,8 @@
#include <stdint.h>
void base64_encode(const unsigned char *data, size_t input_length, size_t *output_length, char *encoded_data);
void build_decoding_table( );
char *base64_encode( const char *data, size_t input_length,
size_t * output_length, char *encoded_data );
char *base64_decode( const char *data, size_t input_length,
size_t * output_length );
void base64_cleanup( );

20
ftp.c
Wyświetl plik

@ -17,7 +17,8 @@
#include "ftp.h"
#include "global.h"
void ConvertFile(char *FileName)
void
ConvertFile( char *FileName )
{
char TargetFile[100], CommandLine[200], *ptr;
@ -31,21 +32,28 @@ void ConvertFile(char *FileName)
// Now convert the file
// LogMessage("Converting %s to %s\n", FileName, TargetFile);
sprintf(CommandLine, "ssdv -d /tmp/%s %s/%s 2> /dev/null > /dev/null", FileName, Config.SSDVJpegFolder, TargetFile);
sprintf( CommandLine,
"ssdv -d /tmp/%s %s/%s 2> /dev/null > /dev/null", FileName,
Config.SSDVJpegFolder, TargetFile );
// LogMessage("COMMAND %s\n", CommandLine);
system( CommandLine );
if (Config.ftpServer[0] && Config.ftpUser[0] && Config.ftpPassword[0])
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);
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)
void *
FTPLoop( void *some_void_ptr )
{
while ( 1 )
{
@ -60,7 +68,7 @@ void *FTPLoop(void *some_void_ptr)
dp = opendir( SSDVFolder );
if ( dp != NULL )
{
while (ep = readdir (dp))
while ( ( ep = readdir( dp ) ) )
{
if ( strstr( ep->d_name, ".bin" ) != NULL )
{

58
gateway-sample.txt 100644
Wyświetl plik

@ -0,0 +1,58 @@
##### Your details #####
tracker=YOUR_CALLSIGN
Latitude=0.0
Longitude=0.0
Antenna=Watson W-50
##### Config Options #####
EnableHabitat=Y
EnableSSDV=Y
JPGFolder=ssdv
LogTelemetry=Y
LogPackets=Y
CallingTimeout=60
ServerPort=6004
#SMSFolder=./
EnableDev=N
NetworkLED=22
InternetLED=23
ActivityLED_0=21
ActivityLED_1=29
##### Config CE0 #####
#frequency_0=434.250
#mode_0=1
#AFC_0=Y
#bandwidth_0=125K
#implicit_0=0
#coding_0=5
#sf_0=8
#lowopt_0=0
#power_0=255
#DIO0_0=31
#DIO5_0=26
#UplinkTime_0=2
#UplinkCycle_0=60
##### Config CE1 #####
frequency_1=434.500
mode_1=1
AFC_1=Y
#bandwidth_1=125K
#implicit_1=0
#coding_1=5
#sf_1=8
#lowopt_1=0
#power_1=255
#DIO0_1=6
#DIO5_1=5
#UplinkTime_1=5
#UplinkCycle_1=60

1199
gateway.c

Plik diff jest za duży Load Diff

14
gateway.h 100644
Wyświetl plik

@ -0,0 +1,14 @@
#ifndef _H_Gateway
#define _H_Gateway
int receiveMessage( int Channel, char *message );
void hexdump_buffer( const char *title, const char *buffer,
const int len_buffer );
void LogPacket( int Channel, int8_t SNR, int RSSI, double FreqError,
int Bytes, unsigned char MessageType );
void LogTelemetryPacket( char *Telemetry );
void LogMessage( const char *format, ... );
void ChannelPrintf( int Channel, int row, int column, const char *format,
... );
#endif

Wyświetl plik

@ -1,4 +1,14 @@
##### Your details #####
tracker=M0RPI/5
Latitude=51.95023
Longitude=-2.5445
Antenna=Watso W-50
##### Config Options #####
EnableHabitat=Y
EnableSSDV=Y
JPGFolder=ssdv
@ -6,41 +16,40 @@ LogTelemetry=Y
LogPackets=Y
CallingTimeout=60
ServerPort=6004
Latitude=51.95023
Longitude=-2.5445
Antenna=868MHz Yagi
#SMSFolder=./
EnableDev=Y
SMSFolder=./
EnableDev=N
#NetworkLED=21
#InternetLED=22
#ActivityLED_0=23
#ActivityLED_1=24
NetworkLED=22
InternetLED=23
ActivityLED_0=21
ActivityLED_1=29
frequency_0=869.860
mode_0=3
#implicit_0=1
#coding_0=5
#sf_0=6
##### Config CE0 #####
#frequency_0=869.500
#mode_0=
#bandwidth_0=125K
#implicit_0=0
#coding_0=5
#sf_0=8
#lowopt_0=0
#power_0=255
frequency_0=869.870
mode_0=4
AFC_0=N
DIO0_0=31
DIO5_0=26
AFC_0=N
UplinkTime_0=2
UplinkCycle_0=60
UplinkMode_0=6
UplinkFrequency_0=869.490
#Power_0=255
frequency_1=434.455
mode_1=2
##### Config CE1 #####
frequency_1=434.454
mode_1=1
AFC_1=N
#bandwidth_1=125K
#implicit_1=0
#coding_1=5
#sf_1=8
#lowopt_1=0
#power_1=255
DIO0_1=6
DIO5_1=5
#AFC_1=Y
#UplinkTime_1=5
#UplinkCycle_1=60

Wyświetl plik

@ -1,29 +1,17 @@
#include <curses.h>
#define SSDV_PACKETS 64
struct TSSDVPacket
{
unsigned char Packet[256];
#define RUNNING 1 // The main program is running
#define STOPPED 0 // The main program has stopped
struct TSSDVPacket {
char Packet[256];
char Callsign[7];
};
struct TSSDVPacketArray
{
struct TSSDVPacket Packets[SSDV_PACKETS];
int Count;
int Sending;
};
struct TSSDVPackets
{
struct TSSDVPackets {
int ImageNumber;
int HighestPacket;
bool Packets[1024];
};
struct TLoRaDevice
{
struct TLoRaDevice {
int InUse;
int DIO0;
int DIO5;
@ -39,13 +27,9 @@ struct TLoRaDevice
int SpreadingFactor;
int LowDataRateOptimize;
int CurrentBandwidth;
WINDOW * Window;
unsigned int TelemetryCount, SSDVCount, BadCRCCount, UnknownCount;
int Sending;
char Telemetry[256];
char Payload[16], Time[12];
unsigned int Counter, LastCounter;
@ -61,7 +45,11 @@ struct TLoRaDevice
int InCallingMode;
int ActivityLED;
int Speed, Heading, PredictedTime, CompassActual, CompassTarget, AirDirection, ServoLeft, ServoRight, ServoTime, FlightMode;
double UplinkFrequency;
int UplinkMode;
int Speed, Heading, PredictedTime, CompassActual, CompassTarget,
AirDirection, ServoLeft, ServoRight, ServoTime, FlightMode;
double cda, PredictedLandingSpeed, AirSpeed, GlideRatio;
// Normal (non TDM) uplink
@ -71,9 +59,7 @@ struct TLoRaDevice
// SSDV Packet Log
struct TSSDVPackets SSDVPackets[3];
};
struct TConfig
{
struct TConfig {
char Tracker[16];
int EnableHabitat;
int EnableSSDV;
@ -94,10 +80,24 @@ struct TConfig
char antenna[64];
int EnableDev;
};
typedef struct {
int parent_status;
unsigned long packet_count;
} thread_shared_vars_t;
typedef struct {
short int Channel;
char Telemetry[257];
int Packet_Number;
} telemetry_t;
typedef struct {
short int Channel;
char SSDV_Packet[257];
int Packet_Number;
} ssdv_t;
extern struct TConfig Config;
extern struct TSSDVPacketArray SSDVPacketArrays[];
extern int SSDVSendArrayIndex;
extern pthread_mutex_t ssdv_mutex;
void LogMessage( const char *format, ... );

125
habitat.c
Wyświetl plik

@ -13,25 +13,31 @@
#include <stddef.h>
#include <dirent.h>
#include <math.h>
#include <time.h>
#include <pthread.h>
#include <curl/curl.h>
#include <wiringPi.h>
#include "base64.h"
#include "habitat.h"
#include "global.h"
#include "sha256.h"
#include "wiringPi.h"
#include "gateway.h"
extern int telem_pipe_fd[2];
extern pthread_mutex_t var;
extern void ChannelPrintf( int Channel, int row, int column,
const char *format, ... );
extern void ChannelPrintf(int Channel, int row, int column, const char *format, ...);
size_t habitat_write_data(void *buffer, size_t size, size_t nmemb, void *userp)
size_t
habitat_write_data( void *buffer, size_t size, size_t nmemb, void *userp )
{
// LogMessage("%s\n", (char *)buffer);
return size * nmemb;
}
void hash_to_hex(unsigned char *hash, char *line)
void
hash_to_hex( unsigned char *hash, char *line )
{
int idx;
@ -44,13 +50,12 @@ void hash_to_hex(unsigned char *hash, char *line)
// LogMessage(line);
}
void UploadTelemetryPacket(int Channel)
void
UploadTelemetryPacket( telemetry_t * t )
{
CURL *curl;
CURLcode res;
/* In windows, this will init the winsock stuff */
// curl_global_init(CURL_GLOBAL_ALL); // RJH moved to main in gateway.c not thread safe
char curl_error[CURL_ERROR_SIZE];
/* get a curl handle */
curl = curl_easy_init( );
@ -63,7 +68,7 @@ void UploadTelemetryPacket(int Channel)
unsigned char hash[32];
char doc_id[100];
char json[1000], now[32];
char PostFields[400], Sentence[512];
char Sentence[512];
struct curl_slist *headers = NULL;
time_t rawtime;
struct tm *tm;
@ -77,19 +82,21 @@ void UploadTelemetryPacket(int Channel)
curl_easy_setopt( curl, CURLOPT_WRITEFUNCTION, habitat_write_data );
// Set the timeout
curl_easy_setopt(curl, CURLOPT_TIMEOUT, 5);
curl_easy_setopt( curl, CURLOPT_TIMEOUT, 15 );
// RJH capture http errors and report
curl_easy_setopt( curl, CURLOPT_FAILONERROR, 1 );
curl_easy_setopt( curl, CURLOPT_ERRORBUFFER, curl_error );
// Avoid curl library bug that happens if above timeout occurs (sigh)
curl_easy_setopt( curl, CURLOPT_NOSIGNAL, 1 );
// Grab current telemetry string and append a linefeed
sprintf(Sentence, "%s\n", Config.LoRaDevices[Channel].Telemetry);
sprintf( Sentence, "%s\n", t->Telemetry );
// Convert sentence to base64
base64_encode(Sentence, strlen(Sentence), &base64_length, base64_data);
base64_encode( Sentence, strlen( Sentence ), &base64_length,
base64_data );
base64_data[base64_length] = '\0';
// Take SHA256 hash of the base64 version and express as hex. This will be the document ID
@ -98,21 +105,28 @@ void UploadTelemetryPacket(int Channel)
sha256_final( &ctx, hash );
hash_to_hex( hash, doc_id );
char counter[10];
sprintf( counter, "%d", t->Packet_Number );
// Create json with the base64 data in hex, the tracker callsign and the current timestamp
sprintf( json,
"{\"data\": {\"_raw\": \"%s\"},\"receivers\": {\"%s\": {\"time_created\": \"%s\",\"time_uploaded\": \"%s\"}}}",
base64_data,
Config.Tracker,
now,
now);
base64_data, Config.Tracker, now, now );
// LogTelemetryPacket(json);
// Set the URL that is about to receive our PUT
sprintf(url, "http://habitat.habhub.org/habitat/_design/payload_telemetry/_update/add_listener/%s", doc_id);
sprintf( url,
"http://habitat.habhub.org/habitat/_design/payload_telemetry/_update/add_listener/%s",
doc_id );
// sprintf(url, "http://ext.hgf.com/ssdv/rjh.php");
// Set the headers
headers = NULL;
headers = curl_slist_append( headers, "Accept: application/json" );
headers = curl_slist_append(headers, "Content-Type: application/json");
headers =
curl_slist_append( headers, "Content-Type: application/json" );
headers = curl_slist_append( headers, "charsets: utf-8" );
// PUT to http://habitat.habhub.org/habitat/_design/payload_telemetry/_update/add_listener/<doc_id> with content-type application/json
@ -121,8 +135,6 @@ void UploadTelemetryPacket(int Channel)
curl_easy_setopt( curl, CURLOPT_CUSTOMREQUEST, "PUT" );
curl_easy_setopt( curl, CURLOPT_POSTFIELDS, json );
// LogMessage("%s\n", Config.LoRaDevices[Channel].Telemetry);
// Perform the request, res will get the return code
res = curl_easy_perform( curl );
@ -133,7 +145,10 @@ void UploadTelemetryPacket(int Channel)
}
else
{
LogMessage("curl_easy_perform() failed: %s\n", curl_easy_strerror(res));
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
@ -142,35 +157,73 @@ void UploadTelemetryPacket(int Channel)
// free(base64_data);
}
// curl_global_cleanup(); // RJH moved to main in gateway.c not thread safe
}
void *HabitatLoop(void *some_void_ptr)
{
while (1)
void *
HabitatLoop( void *vars )
{
if ( Config.EnableHabitat )
{
int Channel;
thread_shared_vars_t *htsv;
htsv = vars;
telemetry_t t;
int packets = 0;
unsigned long total_packets = 0;
for (Channel=0; Channel<=1; Channel++)
int i = 1;
// Keep looping until the parent quits and there are no more packets to
// send to habitat.
while ( ( htsv->parent_status == RUNNING ) || ( packets > 0 ) )
{
if (Config.LoRaDevices[Channel].Counter != Config.LoRaDevices[Channel].LastCounter)
//THis is neded for some reason habitat thread has a pthread_mutex_lock set
// and this removes it
if ( i )
{
ChannelPrintf(Channel, 6, 1, "Habitat");
// pthread_mutex_lock(&var);
pthread_mutex_unlock( &var );
i = 0;
}
if ( htsv->packet_count > total_packets )
{
packets = read( telem_pipe_fd[0], &t, sizeof( t ) );
}
else
{
packets = 0;
// pthread_mutex_unlock(&var);
UploadTelemetryPacket(Channel);
// If we have have a rollover after processing 4294967295 packets
if ( htsv->packet_count < total_packets )
total_packets = 0;
Config.LoRaDevices[Channel].LastCounter = Config.LoRaDevices[Channel].Counter;
}
delay(100);
if ( packets )
{
// LogMessage ("%s\n", t.Telemetry);
ChannelPrintf( t.Channel, 6, 1, "Habitat" );
LogTelemetryPacket( t.Telemetry );
UploadTelemetryPacket( &t );
ChannelPrintf( t.Channel, 6, 1, " " );
total_packets++;
ChannelPrintf(Channel, 6, 1, " ");
}
}
}
delay(100);
}
close( telem_pipe_fd[0] );
close( telem_pipe_fd[1] );
LogMessage( "Habitat thread closing\n" );
return NULL;
}

Wyświetl plik

@ -1,30 +0,0 @@
gateway: gateway.o urlencode.o base64.o sha256.o habitat.o ssdv.o ftp.o network.o server.o
cc -o gateway gateway.o urlencode.o base64.o sha256.o habitat.o ssdv.o ftp.o network.o server.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
server.o: server.c server.h global.h
gcc -c server.c
network.o: network.c network.h global.h
gcc -c network.c
urlencode.o: urlencode.c
gcc -c urlencode.c
base64.o: base64.c
gcc -c base64.c
sha256.o: sha256.c
gcc -c sha256.c

Wyświetl plik

@ -18,10 +18,12 @@
#include <netinet/in.h>
#include <arpa/inet.h>
#include <netdb.h>
#include <wiringPi.h> // Include WiringPi library!
#include "network.h"
#include "global.h"
int HaveAnIPAddress(void)
int
HaveAnIPAddress( void )
{
struct ifaddrs *ifap, *ifa;
struct sockaddr_in *sa;
@ -56,9 +58,10 @@ int HaveAnIPAddress(void)
return FoundAddress;
}
int CanSeeTheInternet(void)
int
CanSeeTheInternet( void )
{
struct addrinfo hints, *res, *p;
struct addrinfo hints, *res;
int status, sockfd, FoundInternet;
memset( &hints, 0, sizeof hints );
@ -85,12 +88,11 @@ int CanSeeTheInternet(void)
return FoundInternet;
}
void *NetworkLoop(void *some_void_ptr)
void *
NetworkLoop( void *some_void_ptr )
{
while ( 1 )
{
digitalWrite(Config.NetworkLED, 0);
digitalWrite(Config.InternetLED, 0);
if ( HaveAnIPAddress( ) )
{
digitalWrite( Config.NetworkLED, 1 );
@ -103,11 +105,13 @@ void *NetworkLoop(void *some_void_ptr)
}
else
{
digitalWrite( Config.InternetLED, 0 );
// LogMessage("Not on internet :-(\n");
}
}
else
{
digitalWrite( Config.NetworkLED, 0 );
// LogMessage("No network :-(\n");
}

Wyświetl plik

@ -29,7 +29,6 @@ void *ServerLoop(void *some_void_ptr)
struct sockaddr_in serv_addr;
char sendBuff[1025];
time_t ticks;
listenfd = socket( AF_INET, SOCK_STREAM, 0 );
memset( &serv_addr, '0', sizeof( serv_addr ) );
@ -41,15 +40,19 @@ void *ServerLoop(void *some_void_ptr)
LogMessage( "Listening on port %d\n", Config.ServerPort );
if (setsockopt(listenfd, SOL_SOCKET, SO_REUSEADDR, &(int){ 1 }, sizeof(int)) < 0)
if ( setsockopt( listenfd, SOL_SOCKET, SO_REUSEADDR, &( int )
{
1}, sizeof( int ) ) < 0 )
{
LogMessage( "setsockopt(SO_REUSEADDR) failed" );
}
if (bind(listenfd, (struct sockaddr*)&serv_addr, sizeof(serv_addr)) < 0)
if ( bind
( listenfd, ( struct sockaddr * ) &serv_addr,
sizeof( serv_addr ) ) < 0 )
{
LogMessage( "Server failed errno %d\n", errno );
return;
exit( -1 );
}
listen( listenfd, 10 );
@ -68,16 +71,19 @@ void *ServerLoop(void *some_void_ptr)
// Build json
// sprintf(sendBuff, "{\"class\":\"POSN\",\"time\":\"12:34:56\",\"lat\":54.12345,\"lon\":-2.12345,\"alt\":169}\r\n");
Channel = 1;
for (Channel=0; Channel<=1; Channel++)
{
if ( Config.EnableDev )
{
sprintf(sendBuff, "{\"class\":\"POSN\",\"payload\":\"%s\",\"time\":\"%s\",\"lat\":%.5lf,\"lon\":%.5lf,\"alt\":%d,\"predlat\":%.5lf,\"predlon\":%.5lf,\"speed\":%d,"
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,
@ -98,8 +104,8 @@ void *ServerLoop(void *some_void_ptr)
}
else
{
sprintf(sendBuff, "{\"class\":\"POSN\",\"payload\":\"%s\",\"time\":\"%s\",\"lat\":%.5lf,\"lon\":%.5lf,\"alt\":%d,\"rate\":%.1lf}\r\n",
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,
@ -122,8 +128,10 @@ void *ServerLoop(void *some_void_ptr)
sleep(1);
}
}
}
close( connfd );
}
return NULL;
}

Wyświetl plik

@ -1 +1,2 @@
void *ServerLoop( void *some_void_ptr );

60
sha256.c 100755 → 100644
Wyświetl plik

@ -21,23 +21,34 @@
uint32_t k[64] = {
0x428a2f98,0x71374491,0xb5c0fbcf,0xe9b5dba5,0x3956c25b,0x59f111f1,0x923f82a4,0xab1c5ed5,
0xd807aa98,0x12835b01,0x243185be,0x550c7dc3,0x72be5d74,0x80deb1fe,0x9bdc06a7,0xc19bf174,
0xe49b69c1,0xefbe4786,0x0fc19dc6,0x240ca1cc,0x2de92c6f,0x4a7484aa,0x5cb0a9dc,0x76f988da,
0x983e5152,0xa831c66d,0xb00327c8,0xbf597fc7,0xc6e00bf3,0xd5a79147,0x06ca6351,0x14292967,
0x27b70a85,0x2e1b2138,0x4d2c6dfc,0x53380d13,0x650a7354,0x766a0abb,0x81c2c92e,0x92722c85,
0xa2bfe8a1,0xa81a664b,0xc24b8b70,0xc76c51a3,0xd192e819,0xd6990624,0xf40e3585,0x106aa070,
0x19a4c116,0x1e376c08,0x2748774c,0x34b0bcb5,0x391c0cb3,0x4ed8aa4a,0x5b9cca4f,0x682e6ff3,
0x748f82ee,0x78a5636f,0x84c87814,0x8cc70208,0x90befffa,0xa4506ceb,0xbef9a3f7,0xc67178f2
0x428a2f98, 0x71374491, 0xb5c0fbcf, 0xe9b5dba5, 0x3956c25b, 0x59f111f1,
0x923f82a4, 0xab1c5ed5,
0xd807aa98, 0x12835b01, 0x243185be, 0x550c7dc3, 0x72be5d74, 0x80deb1fe,
0x9bdc06a7, 0xc19bf174,
0xe49b69c1, 0xefbe4786, 0x0fc19dc6, 0x240ca1cc, 0x2de92c6f, 0x4a7484aa,
0x5cb0a9dc, 0x76f988da,
0x983e5152, 0xa831c66d, 0xb00327c8, 0xbf597fc7, 0xc6e00bf3, 0xd5a79147,
0x06ca6351, 0x14292967,
0x27b70a85, 0x2e1b2138, 0x4d2c6dfc, 0x53380d13, 0x650a7354, 0x766a0abb,
0x81c2c92e, 0x92722c85,
0xa2bfe8a1, 0xa81a664b, 0xc24b8b70, 0xc76c51a3, 0xd192e819, 0xd6990624,
0xf40e3585, 0x106aa070,
0x19a4c116, 0x1e376c08, 0x2748774c, 0x34b0bcb5, 0x391c0cb3, 0x4ed8aa4a,
0x5b9cca4f, 0x682e6ff3,
0x748f82ee, 0x78a5636f, 0x84c87814, 0x8cc70208, 0x90befffa, 0xa4506ceb,
0xbef9a3f7, 0xc67178f2
};
void sha256_transform(SHA256_CTX *ctx, uint8_t data[])
void
sha256_transform( SHA256_CTX * ctx, uint8_t data[] )
{
uint32_t a, b, c, d, e, f, g, h, i, j, t1, t2, m[64];
for ( i = 0, j = 0; i < 16; ++i, j += 4 )
m[i] = (data[j] << 24) | (data[j+1] << 16) | (data[j+2] << 8) | (data[j+3]);
m[i] =
( data[j] << 24 ) | ( data[j + 1] << 16 ) | ( data[j + 2] << 8 ) |
( data[j + 3] );
for ( ; i < 64; ++i )
m[i] = SIG1( m[i - 2] ) + m[i - 7] + SIG0( m[i - 15] ) + m[i - 16];
@ -50,7 +61,8 @@ void sha256_transform(SHA256_CTX *ctx, uint8_t data[])
g = ctx->state[6];
h = ctx->state[7];
for (i = 0; i < 64; ++i) {
for ( i = 0; i < 64; ++i )
{
t1 = h + EP1( e ) + CH( e, f, g ) + k[i] + m[i];
t2 = EP0( a ) + MAJ( a, b, c );
h = g;
@ -73,7 +85,8 @@ void sha256_transform(SHA256_CTX *ctx, uint8_t data[])
ctx->state[7] += h;
}
void sha256_init(SHA256_CTX *ctx)
void
sha256_init( SHA256_CTX * ctx )
{
ctx->datalen = 0;
ctx->bitlen[0] = 0;
@ -88,14 +101,17 @@ void sha256_init(SHA256_CTX *ctx)
ctx->state[7] = 0x5be0cd19;
}
void sha256_update(SHA256_CTX *ctx, uint8_t data[], uint32_t len)
void
sha256_update( SHA256_CTX * ctx, char data[], uint32_t len )
{
uint32_t t,i;
uint32_t i;
for (i=0; i < len; ++i) {
for ( i = 0; i < len; ++i )
{
ctx->data[ctx->datalen] = data[i];
ctx->datalen++;
if (ctx->datalen == 64) {
if ( ctx->datalen == 64 )
{
sha256_transform( ctx, ctx->data );
DBL_INT_ADD( ctx->bitlen[0], ctx->bitlen[1], 512 );
ctx->datalen = 0;
@ -103,19 +119,22 @@ void sha256_update(SHA256_CTX *ctx, uint8_t data[], uint32_t len)
}
}
void sha256_final(SHA256_CTX *ctx, uint8_t hash[])
void
sha256_final( SHA256_CTX * ctx, uint8_t hash[] )
{
uint32_t i;
i = ctx->datalen;
// Pad whatever data is left in the buffer.
if (ctx->datalen < 56) {
if ( ctx->datalen < 56 )
{
ctx->data[i++] = 0x80;
while ( i < 56 )
ctx->data[i++] = 0x00;
}
else {
else
{
ctx->data[i++] = 0x80;
while ( i < 64 )
ctx->data[i++] = 0x00;
@ -137,7 +156,8 @@ void sha256_final(SHA256_CTX *ctx, uint8_t hash[])
// Since this implementation uses little endian byte ordering and SHA uses big endian,
// reverse all the bytes when copying the final state to the output hash.
for (i=0; i < 4; ++i) {
for ( i = 0; i < 4; ++i )
{
hash[i] = ( ctx->state[0] >> ( 24 - i * 8 ) ) & 0x000000ff;
hash[i + 4] = ( ctx->state[1] >> ( 24 - i * 8 ) ) & 0x000000ff;
hash[i + 8] = ( ctx->state[2] >> ( 24 - i * 8 ) ) & 0x000000ff;

4
sha256.h 100755 → 100644
Wyświetl plik

@ -4,3 +4,7 @@ typedef struct {
uint32_t bitlen[2];
uint32_t state[8];
} SHA256_CTX;
void sha256_transform( SHA256_CTX * ctx, uint8_t data[] );
void sha256_init( SHA256_CTX * ctx );
void sha256_update( SHA256_CTX * ctx, char data[], uint32_t len );
void sha256_final( SHA256_CTX * ctx, uint8_t hash[] );

131
ssdv.c
Wyświetl plik

@ -14,19 +14,26 @@
#include <math.h>
#include <pthread.h>
#include <curl/curl.h>
#include <wiringPi.h>
#include "urlencode.h"
#include "base64.h"
#include "ssdv.h"
#include "gateway.h"
#include "global.h"
size_t write_ssdv_data(void *buffer, size_t size, size_t nmemb, void *userp)
extern int ssdv_pipe_fd[2];
extern pthread_mutex_t var;
size_t
write_ssdv_data( void *buffer, size_t size, size_t nmemb, void *userp )
{
return size * nmemb;
}
void ConvertStringToHex(unsigned char *Target, unsigned char *Source, int Length)
void
ConvertStringToHex( unsigned char *Target, unsigned char *Source, int Length )
{
const char Hex[16] = "0123456789ABCDEF";
int i;
@ -41,36 +48,34 @@ void ConvertStringToHex(unsigned char *Target, unsigned char *Source, int Length
}
int UploadImagePackets(void)
void
UploadImagePacket( ssdv_t * s, unsigned int packets )
{
CURL *curl;
CURLcode res;
char PostFields[1000], base64_data[512], json[32768], packet_json[1000];
char curl_error[CURL_ERROR_SIZE];
char base64_data[512], json[32768], packet_json[1000];
struct curl_slist *headers = NULL;
int UploadedOK, base64_length;
size_t base64_length;
char now[32];
time_t rawtime;
struct tm *tm;
UploadedOK = 0;
/* In windows, this will init the winsock stuff */
// curl_global_init(CURL_GLOBAL_ALL); // RJH moved to main in gateway.c not thread safe
char url[250];
/* get a curl handle */
curl = curl_easy_init( );
if ( curl )
{
int PacketIndex;
// 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 );
// Set the timeout
curl_easy_setopt(curl, CURLOPT_TIMEOUT, 5);
curl_easy_setopt( curl, CURLOPT_TIMEOUT, 15 );
// RJH capture http errors and report
curl_easy_setopt( curl, CURLOPT_FAILONERROR, 1 );
curl_easy_setopt( curl, CURLOPT_ERRORBUFFER, curl_error );
// Avoid curl library bug that happens if above timeout occurs (sigh)
curl_easy_setopt( curl, CURLOPT_NOSIGNAL, 1 );
@ -80,27 +85,41 @@ int UploadImagePackets(void)
tm = gmtime( &rawtime );
strftime( now, sizeof( now ), "%Y-%0m-%0dT%H:%M:%SZ", tm );
int PacketIndex;
// Create json with the base64 data in hex, the tracker callsign and the current timestamp
strcpy( json, "{\"type\": \"packets\",\"packets\":[" );
for (PacketIndex = 0; PacketIndex < SSDVPacketArrays[SSDVSendArrayIndex].Count; PacketIndex++)
for ( PacketIndex = 0; PacketIndex < packets; PacketIndex++ )
{
base64_encode(SSDVPacketArrays[SSDVSendArrayIndex].Packets[PacketIndex].Packet, 256, &base64_length, base64_data);
base64_encode( s[PacketIndex].SSDV_Packet, 256, &base64_length,
base64_data );
base64_data[base64_length] = '\0';
sprintf(packet_json, "{\"type\": \"packet\", \"packet\": \"%s\", \"encoding\": \"base64\", \"received\": \"%s\", \"receiver\": \"%s\"}%s",
base64_data, now, Config.Tracker, PacketIndex == (SSDVPacketArrays[SSDVSendArrayIndex].Count-1) ? "" : ",");
sprintf( packet_json,
"{\"type\": \"packet\", \"packet\": \"%s\", \"encoding\": \"base64\", \"received\": \"%s\", \"receiver\": \"%s\"}%s",
base64_data, now, Config.Tracker,
PacketIndex == ( packets - 1 ) ? "" : "," );
strcat( json, packet_json );
}
strcat( json, "]}" );
// LogTelemetryPacket(json);
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
headers = NULL;
headers = curl_slist_append( headers, "Accept: application/json" );
headers = curl_slist_append(headers, "Content-Type: application/json");
headers =
curl_slist_append( headers, "Content-Type: application/json" );
headers = curl_slist_append( headers, "charsets: utf-8" );
curl_easy_setopt( curl, CURLOPT_HTTPHEADER, headers );
curl_easy_setopt(curl, CURLOPT_URL, "http://ssdv.habhub.org/api/v0/packets");
curl_easy_setopt( curl, CURLOPT_URL, url );
curl_easy_setopt( curl, CURLOPT_CUSTOMREQUEST, "POST" );
curl_easy_setopt( curl, CURLOPT_POSTFIELDS, json );
@ -110,59 +129,81 @@ int UploadImagePackets(void)
/* Check for errors */
if ( res == CURLE_OK )
{
UploadedOK = 1;
}
else
{
LogMessage("curl_easy_perform() failed: %s\n", curl_easy_strerror(res));
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 */
curl_slist_free_all( headers ); // RJH Added this from habitat.c as was missing
curl_easy_cleanup( curl );
}
// curl_global_cleanup(); // RJH moved to main in gateway.c not thread safe
return UploadedOK;
}
void *SSDVLoop(void *arguments)
void *
SSDVLoop( void *vars )
{
char HexString[513];
while (1)
if ( Config.EnableSSDV )
{
int ArrayIndex;
const int max_packets = 51;
thread_shared_vars_t *stsv;
stsv = vars;
ssdv_t s[max_packets];
unsigned int j = 0;
unsigned int packets = 0;
unsigned long total_packets = 0;
pthread_mutex_lock(&ssdv_mutex);
// Keep looping until the parent quits and there are no more packets to
// send to ssdv.
while ( ( stsv->parent_status == RUNNING ) || ( packets > 0 ) )
{
if (SSDVPacketArrays[0].Count > 0)
if ( stsv->packet_count > total_packets )
{
SSDVSendArrayIndex = 0;
}
else if (SSDVPacketArrays[1].Count > 0)
{
SSDVSendArrayIndex = 1;
packets = read( ssdv_pipe_fd[0], &s[j], sizeof( ssdv_t ) );
}
else
{
SSDVSendArrayIndex = -1;
packets = 0;
// If we have have a rollover after processing 4294967295 packets
if ( stsv->packet_count < total_packets )
total_packets = 0;
}
pthread_mutex_unlock(&ssdv_mutex);
if (SSDVSendArrayIndex >= 0)
if ( packets )
{
if (UploadImagePackets())
j++;
total_packets++;
}
if ( j == 50 || ( ( packets == 0 ) && ( j > 0 ) ) )
{
// Mark packets as sent
SSDVPacketArrays[SSDVSendArrayIndex].Count = 0;
ChannelPrintf( s[0].Channel, 6, 1, "Habitat" );
UploadImagePacket( s, j );
ChannelPrintf( s[0].Channel, 6, 1, " " );
j = 0;
packets = 0;
}
SSDVSendArrayIndex = -1;
}
}
delay(100);
}
close( ssdv_pipe_fd[0] );
close( ssdv_pipe_fd[1] );
LogMessage( "SSDV thread closing\n" );
return NULL;
}

1
ssdv.h
Wyświetl plik

@ -1 +1,2 @@
void *SSDVLoop( void *some_void_ptr );

0
ssdv_resend.py 100755 → 100644
Wyświetl plik

Wyświetl plik

@ -1,29 +1,39 @@
#include <stdlib.h>
#include <string.h>
#include <ctype.h>
/* Converts a hex character to its integer value */
char from_hex(char ch) {
char
from_hex( char ch )
{
return isdigit( ch ) ? ch - '0' : tolower( ch ) - 'a' + 10;
}
/* Converts an integer value to its hex character*/
char to_hex(char code) {
char
to_hex( char code )
{
static char hex[] = "0123456789abcdef";
return hex[code & 15];
}
/* Returns a url-encoded version of str */
/* IMPORTANT: be sure to free() the returned string after use */
char *url_encode(char *str) {
char *
url_encode( char *str )
{
char *pstr = str, *buf = malloc( strlen( str ) * 3 + 1 ), *pbuf = buf;
while (*pstr) {
if (isalnum(*pstr) || *pstr == '-' || *pstr == '_' || *pstr == '.' || *pstr == '~')
while ( *pstr )
{
if ( isalnum( *pstr ) || *pstr == '-' || *pstr == '_' || *pstr == '.'
|| *pstr == '~' )
*pbuf++ = *pstr;
else if ( *pstr == ' ' )
*pbuf++ = '+';
else
*pbuf++ = '%', *pbuf++ = to_hex(*pstr >> 4), *pbuf++ = to_hex(*pstr & 15);
*pbuf++ = '%', *pbuf++ = to_hex( *pstr >> 4 ), *pbuf++ =
to_hex( *pstr & 15 );
pstr++;
}
*pbuf = '\0';
@ -32,17 +42,26 @@ char *url_encode(char *str) {
/* Returns a url-decoded version of str */
/* IMPORTANT: be sure to free() the returned string after use */
char *url_decode(char *str) {
char *
url_decode( char *str )
{
char *pstr = str, *buf = malloc( strlen( str ) + 1 ), *pbuf = buf;
while (*pstr) {
if (*pstr == '%') {
if (pstr[1] && pstr[2]) {
while ( *pstr )
{
if ( *pstr == '%' )
{
if ( pstr[1] && pstr[2] )
{
*pbuf++ = from_hex( pstr[1] ) << 4 | from_hex( pstr[2] );
pstr += 2;
}
} else if (*pstr == '+') {
}
else if ( *pstr == '+' )
{
*pbuf++ = ' ';
} else {
}
else
{
*pbuf++ = *pstr;
}
pstr++;

Wyświetl plik

@ -1 +1,2 @@
char *url_encode( char *str );