diff options
6 files changed, 353 insertions, 17 deletions
diff --git a/recipes-connectivity/lora/lora-gateway_1.7.0mts.bb b/recipes-connectivity/lora/lora-gateway_1.7.0mts.bb index 87b48b2..d032f62 100644 --- a/recipes-connectivity/lora/lora-gateway_1.7.0mts.bb +++ b/recipes-connectivity/lora/lora-gateway_1.7.0mts.bb @@ -1,7 +1,7 @@ require lora-gateway.inc -PR = "${INC_PR}.0" +PR = "${INC_PR}.1" -SRCREV = "d6e01b5a566c08c89f17ae4a26d4ef003e39167c" +SRCREV = "631dfedf1b535b6c3861d3c3868e02f48a84fb06" BRANCH = "1.7.0-mts" diff --git a/recipes-connectivity/lora/lora-packet-forwarder/lora-packet-forwarder-add-no-header-option.patch b/recipes-connectivity/lora/lora-packet-forwarder/lora-packet-forwarder-add-no-header-option.patch index ca8d106..fd2fa24 100644 --- a/recipes-connectivity/lora/lora-packet-forwarder/lora-packet-forwarder-add-no-header-option.patch +++ b/recipes-connectivity/lora/lora-packet-forwarder/lora-packet-forwarder-add-no-header-option.patch @@ -25,6 +25,21 @@ index e20dfc1..2223b4a 100644 /* parse target frequency (mandatory) */ val = json_object_get_value(txpk_obj,"freq"); --- -1.7.10.4 - + +diff --git a/gps_pkt_fwd/src/gps_pkt_fwd.c b/gps_pkt_fwd/src/gps_pkt_fwd.c +index 79f7584..d073540 100644 +--- a/gps_pkt_fwd/src/gps_pkt_fwd.c ++++ b/gps_pkt_fwd/src/gps_pkt_fwd.c +@@ -1534,6 +1534,12 @@ void thread_down(void) { + txpkt.no_crc = (bool)json_value_get_boolean(val); + } + ++ /* Parse "No Header" flag (optional field) */ ++ val = json_object_get_value(txpk_obj,"nhdr"); ++ if (val != NULL) { ++ txpkt.no_header = (bool)json_value_get_boolean(val); ++ } ++ + /* parse target frequency (mandatory) */ + val = json_object_get_value(txpk_obj,"freq"); + if (val == NULL) { diff --git a/recipes-connectivity/lora/lora-packet-forwarder/lora-packet-forwarder-add-queue.patch b/recipes-connectivity/lora/lora-packet-forwarder/lora-packet-forwarder-add-queue.patch index 318b6ea..cd9a727 100644 --- a/recipes-connectivity/lora/lora-packet-forwarder/lora-packet-forwarder-add-queue.patch +++ b/recipes-connectivity/lora/lora-packet-forwarder/lora-packet-forwarder-add-queue.patch @@ -159,6 +159,158 @@ index e20dfc1..4d0bb35 100644 } MSG("\nINFO: End of downstream thread\n"); } --- -1.7.10.4 + +iff --git a/gps_pkt_fwd/src/gps_pkt_fwd.c b/gps_pkt_fwd/src/gps_pkt_fwd.c +index 79f7584..3d1cbf8 100644 +--- a/gps_pkt_fwd/src/gps_pkt_fwd.c ++++ b/gps_pkt_fwd/src/gps_pkt_fwd.c +@@ -192,8 +192,18 @@ static int parse_gateway_configuration(const char * conf_file); + + static double difftimespec(struct timespec end, struct timespec beginning); + ++typedef struct tx_queue_s { ++ struct lgw_pkt_tx_s pkt; ++ struct tx_queue_s* next; ++} tx_queue_s; ++ ++ ++struct tx_queue_s* tx_queue = NULL; ++struct tx_queue_s* tx_queue_end = NULL; ++ + /* threads */ + void thread_up(void); ++void thread_queue(void); + void thread_down(void); + void thread_gps(void); + void thread_valid(void); +@@ -546,6 +556,7 @@ int main(void) + + /* threads */ + pthread_t thrid_up; ++ pthread_t thrid_queue; + pthread_t thrid_down; + pthread_t thrid_gps; + pthread_t thrid_valid; +@@ -739,6 +750,12 @@ int main(void) + exit(EXIT_FAILURE); + } + ++ i = pthread_create( &thrid_queue, NULL, (void * (*)(void *))thread_queue, NULL); ++ if (i != 0) { ++ MSG("ERROR: [main] impossible to create queue thread\n"); ++ exit(EXIT_FAILURE); ++ } ++ + /* spawn thread to manage GPS */ + if (gps_enabled == true) { + i = pthread_create( &thrid_gps, NULL, (void * (*)(void *))thread_gps, NULL); +@@ -891,6 +908,7 @@ int main(void) + + /* wait for upstream thread to finish (1 fetch cycle max) */ + pthread_join(thrid_up, NULL); ++ pthread_cancel(thrid_queue); + pthread_cancel(thrid_down); /* don't wait for downstream thread */ + pthread_cancel(thrid_gps); /* don't wait for GPS thread */ + pthread_cancel(thrid_valid); /* don't wait for validation thread */ +@@ -1325,9 +1343,9 @@ void thread_up(void) { + } + + /* -------------------------------------------------------------------------- */ +-/* --- THREAD 2: POLLING SERVER AND EMITTING PACKETS ------------------------ */ ++/* --- THREAD 2: POLLING SERVER AND QUEUE PACKETS ------------------------ */ + +-void thread_down(void) { ++void thread_queue(void) { + int i; /* loop variables */ + + /* configuration and metadata for an outbound packet */ +@@ -1719,11 +1737,49 @@ void thread_down(void) { + meas_dw_dgram_rcv += 1; /* count only datagrams with no JSON errors */ + meas_dw_network_byte += msg_len; /* meas_dw_network_byte */ + meas_dw_payload_byte += txpkt.size; ++ pthread_mutex_unlock(&mx_meas_dw); ++ ++ pthread_mutex_lock(&mx_concent); /* may have to wait for a fetch to finish */ ++ if (tx_queue == NULL) { ++ tx_queue = malloc(sizeof(tx_queue_s)); ++ tx_queue_end = tx_queue; ++ tx_queue->pkt = txpkt; ++ tx_queue->next = NULL; ++ } else { ++ struct tx_queue_s* item = malloc(sizeof(tx_queue_s)); ++ item->next = NULL; ++ item->pkt = txpkt; ++ tx_queue_end->next = item; ++ tx_queue_end = item; ++ } ++ pthread_mutex_unlock(&mx_concent); ++ } ++ wait_ms(1); ++ } ++ MSG("\nINFO: End of queue thread\n"); ++} ++ ++/* -------------------------------------------------------------------------- */ ++/* --- THREAD 3: POLLING QUEUE AND EMITTING PACKETS ------------------------ */ ++ ++void thread_down(void) { ++ MSG("\nINFO: Start of downstream thread\n"); + ++ struct lgw_pkt_tx_s txpkt; ++ ++ while (!exit_sig && !quit_sig) { ++ pthread_mutex_lock(&mx_concent); /* may have to wait for a fetch to finish */ ++ if (tx_queue != NULL) { ++ struct tx_queue_s* del = tx_queue; ++ txpkt = tx_queue->pkt; ++ tx_queue = tx_queue->next; ++ free(del); ++ + /* transfer data and metadata to the concentrator, and schedule TX */ +- pthread_mutex_lock(&mx_concent); /* may have to wait for a fetch to finish */ +- i = lgw_send(txpkt); ++ int i = lgw_send(txpkt); + pthread_mutex_unlock(&mx_concent); /* free concentrator ASAP */ ++ ++ pthread_mutex_lock(&mx_meas_dw); + if (i == LGW_HAL_ERROR) { + meas_nb_tx_fail += 1; + pthread_mutex_unlock(&mx_meas_dw); +@@ -1733,7 +1789,35 @@ void thread_down(void) { + meas_nb_tx_ok += 1; + pthread_mutex_unlock(&mx_meas_dw); + } +- } ++ ++ uint8_t tx_status_var = TX_STATUS_UNKNOWN; ++ // wait for 200 ms and ensure packet is transmitted ++ for (i=0; (i < 20) && (tx_status_var != TX_EMITTING); ++i) { ++ wait_ms(10); ++ pthread_mutex_lock(&mx_concent); ++ lgw_status(TX_STATUS, &tx_status_var); ++ pthread_mutex_unlock(&mx_concent); ++ } ++ if (tx_status_var != TX_EMITTING) { ++ MSG("WARNING: [down] packet was scheduled but failed to TX\n"); ++ } else { ++ // if packet is transmitting then wait for end of TX or timeout after 4 seconds ++ for (i=0; (i < 400) && (tx_status_var != TX_FREE); ++i) { ++ wait_ms(10); ++ pthread_mutex_lock(&mx_concent); ++ lgw_status(TX_STATUS, &tx_status_var); ++ pthread_mutex_unlock(&mx_concent); ++ } ++ ++ if (tx_status_var != TX_FREE) { ++ MSG("WARNING: [down] timedout waiting for end of TX\n"); ++ } ++ } ++ ++ } else { ++ pthread_mutex_unlock(&mx_concent); /* free concentrator ASAP */ ++ } ++ wait_ms(1); + } + MSG("\nINFO: End of downstream thread\n"); + } diff --git a/recipes-connectivity/lora/lora-packet-forwarder/lora-packet-forwarder-mts-enhancements.patch b/recipes-connectivity/lora/lora-packet-forwarder/lora-packet-forwarder-mts-enhancements.patch index 2bf82ff..e1da462 100644 --- a/recipes-connectivity/lora/lora-packet-forwarder/lora-packet-forwarder-mts-enhancements.patch +++ b/recipes-connectivity/lora/lora-packet-forwarder/lora-packet-forwarder-mts-enhancements.patch @@ -105,11 +105,11 @@ Index: git/basic_pkt_fwd/src/basic_pkt_fwd.c /* display version informations */ MSG("*** Basic Packet Forwarder for Lora Gateway ***\nVersion: " VERSION_STRING "\n"); -Index: git/gps_pkt_fwd/src/gps_pkt_fwd.c -=================================================================== ---- git.orig/gps_pkt_fwd/src/gps_pkt_fwd.c 2015-04-01 15:14:12.160933893 -0500 -+++ git/gps_pkt_fwd/src/gps_pkt_fwd.c 2015-04-01 15:14:12.280932001 -0500 -@@ -44,6 +44,8 @@ +diff --git a/gps_pkt_fwd/src/gps_pkt_fwd.c b/gps_pkt_fwd/src/gps_pkt_fwd.c +index 79f7584..3f2f91c 100644 +--- a/gps_pkt_fwd/src/gps_pkt_fwd.c ++++ b/gps_pkt_fwd/src/gps_pkt_fwd.c +@@ -44,6 +44,8 @@ Maintainer: Sylvain Miermont #include <netdb.h> /* gai_strerror */ #include <pthread.h> @@ -118,19 +118,20 @@ Index: git/gps_pkt_fwd/src/gps_pkt_fwd.c #include "parson.h" #include "base64.h" -@@ -539,19 +541,60 @@ +@@ -531,19 +533,65 @@ static double difftimespec(struct timespec end, struct timespec beginning) { return x; } +void usage(char *proc_name) { -+ fprintf(stderr, "Usage: %s [-c config_dir]\n", proc_name); ++ fprintf(stderr, "Usage: %s [-c config_dir] [-l logfile]\n", proc_name); + exit(1); +} + + -+static char *short_options = "c:h"; ++static char *short_options = "c:l:h"; +static struct option long_options[] = { + {"config-dir", 1, 0, 'c'}, ++ {"logfile", 1, 0, 'l'}, + {"help", 0, 0, 'h'}, + {0, 0, 0, 0}, +}; @@ -158,6 +159,7 @@ Index: git/gps_pkt_fwd/src/gps_pkt_fwd.c + char global_cfg_path[PATH_MAX] = {0}; + char local_cfg_path[PATH_MAX] = {0}; + char debug_cfg_path[PATH_MAX] = {0}; ++ char *logfile_path = NULL; + char *proc_name = argv[0]; + + while((i = getopt_long(argc, argv, short_options, long_options, &opt_ind)) >= 0) { @@ -168,6 +170,9 @@ Index: git/gps_pkt_fwd/src/gps_pkt_fwd.c + strncpy(cfg_dir, optarg, sizeof(cfg_dir)-2); + strcat(cfg_dir, "/"); + break; ++ case 'l': ++ logfile_path = optarg; ++ break; + case 'h': + usage(proc_name); + break; @@ -184,6 +189,29 @@ Index: git/gps_pkt_fwd/src/gps_pkt_fwd.c /* threads */ pthread_t thrid_up; pthread_t thrid_down; +@@ -589,6 +637,22 @@ int main(void) + float up_ack_ratio; + float dw_ack_ratio; + ++ /* redirect stdout, stderr to logfile if specified */ ++ int logfile_fd; ++ FILE *logfile = NULL; ++ if (logfile_path) { ++ logfile = fopen(logfile_path, "w"); ++ if (logfile) { ++ logfile_fd = fileno(logfile); ++ dup2(logfile_fd, STDOUT_FILENO); ++ dup2(logfile_fd, STDERR_FILENO); ++ } ++ else { ++ printf("Error opening log file %s\n", logfile_path); ++ exit(1); ++ } ++ } ++ + /* display version informations */ + MSG("*** GPS Packet Forwarder for Lora Gateway ***\nVersion: " VERSION_STRING "\n"); + MSG("*** Lora concentrator HAL library version info ***\n%s\n***\n", lgw_version_info()); Index: git/beacon_pkt_fwd/src/beacon_pkt_fwd.c =================================================================== --- git.orig/beacon_pkt_fwd/src/beacon_pkt_fwd.c 2015-04-01 15:14:12.156933956 -0500 @@ -197,12 +225,12 @@ Index: git/beacon_pkt_fwd/src/beacon_pkt_fwd.c #include "parson.h" #include "base64.h" -@@ -618,19 +620,60 @@ +@@ -618,19 +620,65 @@ return x; } +void usage(char *proc_name) { -+ fprintf(stderr, "Usage: %s [-c config_dir]\n", proc_name); ++ fprintf(stderr, "Usage: %s [-c config_dir] [-l logfile]\n", proc_name); + exit(1); +} + @@ -210,6 +238,7 @@ Index: git/beacon_pkt_fwd/src/beacon_pkt_fwd.c +static char *short_options = "c:h"; +static struct option long_options[] = { + {"config-dir", 1, 0, 'c'}, ++ {"logfile", 1, 0, 'l'}, + {"help", 0, 0, 'h'}, + {0, 0, 0, 0}, +}; @@ -237,6 +266,7 @@ Index: git/beacon_pkt_fwd/src/beacon_pkt_fwd.c + char global_cfg_path[PATH_MAX] = {0}; + char local_cfg_path[PATH_MAX] = {0}; + char debug_cfg_path[PATH_MAX] = {0}; ++ char *logfile_path = NULL; + char *proc_name = argv[0]; + + while((i = getopt_long(argc, argv, short_options, long_options, &opt_ind)) >= 0) { @@ -247,6 +277,9 @@ Index: git/beacon_pkt_fwd/src/beacon_pkt_fwd.c + strncpy(cfg_dir, optarg, sizeof(cfg_dir)-2); + strcat(cfg_dir, "/"); + break; ++ case 'l': ++ logfile_path = optarg; ++ break; + case 'h': + usage(proc_name); + break; @@ -263,3 +296,26 @@ Index: git/beacon_pkt_fwd/src/beacon_pkt_fwd.c /* threads */ pthread_t thrid_up; pthread_t thrid_down; +@@ -767,6 +715,22 @@ + float rx_nocrc_ratio; + float up_ack_ratio; + float dw_ack_ratio; ++ ++ /* redirect stdout, stderr to logfile if specified */ ++ int logfile_fd; ++ FILE *logfile = NULL; ++ if (logfile_path) { ++ logfile = fopen(logfile_path, "w"); ++ if (logfile) { ++ logfile_fd = fileno(logfile); ++ dup2(logfile_fd, STDOUT_FILENO); ++ dup2(logfile_fd, STDERR_FILENO); ++ } ++ else { ++ printf("Error opening log file %s\n", logfile_path); ++ exit(1); ++ } ++ } + + /* display version informations */ + MSG("*** Beacon Packet Forwarder for Lora Gateway ***\nVersion: " VERSION_STRING "\n"); diff --git a/recipes-connectivity/lora/lora-packet-forwarder/lora-packet-forwarder-skip-bad-packets.patch b/recipes-connectivity/lora/lora-packet-forwarder/lora-packet-forwarder-skip-bad-packets.patch index cb12a97..eb9450f 100644 --- a/recipes-connectivity/lora/lora-packet-forwarder/lora-packet-forwarder-skip-bad-packets.patch +++ b/recipes-connectivity/lora/lora-packet-forwarder/lora-packet-forwarder-skip-bad-packets.patch @@ -52,3 +52,58 @@ Index: git/basic_pkt_fwd/src/basic_pkt_fwd.c } /* Packet RSSI, payload size, 18-23 useful chars */ + +diff --git a/gps_pkt_fwd/src/gps_pkt_fwd.c b/gps_pkt_fwd/src/gps_pkt_fwd.c +index 79f7584..933de29 100644 +--- a/gps_pkt_fwd/src/gps_pkt_fwd.c ++++ b/gps_pkt_fwd/src/gps_pkt_fwd.c +@@ -1107,7 +1107,8 @@ void thread_up(void) { + MSG("ERROR: [up] received packet with unknown status\n"); + memcpy((void *)(buff_up + buff_index), (void *)",\"stat\":?", 9); + buff_index += 9; +- exit(EXIT_FAILURE); ++ continue; // skip packet ++ //exit(EXIT_FAILURE); + } + + /* Packet modulation, 13-14 useful chars */ +@@ -1145,7 +1146,8 @@ void thread_up(void) { + MSG("ERROR: [up] lora packet with unknown datarate\n"); + memcpy((void *)(buff_up + buff_index), (void *)",\"datr\":\"SF?", 12); + buff_index += 12; +- exit(EXIT_FAILURE); ++ continue; // skip packet ++ //exit(EXIT_FAILURE); + } + switch (p->bandwidth) { + case BW_125KHZ: +@@ -1164,7 +1166,8 @@ void thread_up(void) { + MSG("ERROR: [up] lora packet with unknown bandwidth\n"); + memcpy((void *)(buff_up + buff_index), (void *)"BW?\"", 4); + buff_index += 4; +- exit(EXIT_FAILURE); ++ continue; // skip packet ++ //exit(EXIT_FAILURE); + } + + /* Packet ECC coding rate, 11-13 useful chars */ +@@ -1193,7 +1196,8 @@ void thread_up(void) { + MSG("ERROR: [up] lora packet with unknown coderate\n"); + memcpy((void *)(buff_up + buff_index), (void *)",\"codr\":\"?\"", 11); + buff_index += 11; +- exit(EXIT_FAILURE); ++ continue; // skip packet ++ //exit(EXIT_FAILURE); + } + + /* Lora SNR, 11-13 useful chars */ +@@ -1218,7 +1222,8 @@ void thread_up(void) { + } + } else { + MSG("ERROR: [up] received packet with unknown modulation\n"); +- exit(EXIT_FAILURE); ++ continue; // skip packet ++ //exit(EXIT_FAILURE); + } + + /* Packet RSSI, payload size, 18-23 useful chars */ diff --git a/recipes-connectivity/lora/lora-packet-forwarder/lora-packet-forwarder-synch-word.patch b/recipes-connectivity/lora/lora-packet-forwarder/lora-packet-forwarder-synch-word.patch index 8da6273..2f04eb1 100644 --- a/recipes-connectivity/lora/lora-packet-forwarder/lora-packet-forwarder-synch-word.patch +++ b/recipes-connectivity/lora/lora-packet-forwarder/lora-packet-forwarder-synch-word.patch @@ -12,6 +12,18 @@ index 2223b4a..2db6e26 100644 static char serv_addr[64] = STR(DEFAULT_SERVER); /* address of the server (host name or IPv4/IPv6) */ static char serv_port_up[8] = STR(DEFAULT_PORT_UP); /* server port for upstream traffic */ static char serv_port_down[8] = STR(DEFAULT_PORT_DW); /* server port for downstream traffic */ +@@ -281,6 +282,11 @@ static int parse_SX1301_configuration(const char * conf_file) { + MSG("INFO: %s does contain a JSON object named %s, parsing SX1301 parameters\n", conf_file, conf_obj_name); + } + ++ val = json_object_get_value(conf_obj, "lorawan_public"); /* fetch value (if possible) */ ++ if (json_value_get_type(val) == JSONBoolean && (bool)json_value_get_boolean(val) == true) { ++ synch_word = 0x34; ++ } ++ + /* set configuration for RF chains */ + for (i = 0; i < LGW_RF_CHAIN_NB; ++i) { + memset(&rfconf, 0, sizeof rfconf); /* initialize configuration structure */ @@ -404,7 +415,14 @@ static int parse_gateway_configuration(const char * conf_file) { snprintf(serv_port_down, sizeof serv_port_down, "%u", (uint16_t)json_value_get_number(val)); MSG("INFO: downstream port is configured to \"%s\"\n", serv_port_down); @@ -39,3 +51,49 @@ index 2223b4a..2db6e26 100644 /* spawn threads to manage upstream and downstream */ i = pthread_create( &thrid_up, NULL, (void * (*)(void *))thread_up, NULL); if (i != 0) { +diff --git a/gps_pkt_fwd/src/gps_pkt_fwd.c b/gps_pkt_fwd/src/gps_pkt_fwd.c +index 79f7584..8addbc0 100644 +--- a/gps_pkt_fwd/src/gps_pkt_fwd.c ++++ b/gps_pkt_fwd/src/gps_pkt_fwd.c +@@ -108,6 +108,7 @@ static bool fwd_error_pkt = false; /* packets with PAYLOAD CRC ERROR are NOT for + static bool fwd_nocrc_pkt = false; /* packets with NO PAYLOAD CRC are NOT forwarded */ + + /* network configuration variables */ ++static uint8_t synch_word = 0x12; + static uint64_t lgwm = 0; /* Lora gateway MAC address */ + static char serv_addr[64] = STR(DEFAULT_SERVER); /* address of the server (host name or IPv4/IPv6) */ + static char serv_port_up[8] = STR(DEFAULT_PORT_UP); /* server port for upstream traffic */ +@@ -237,6 +238,11 @@ static int parse_SX1301_configuration(const char * conf_file) { + MSG("INFO: %s does contain a JSON object named %s, parsing SX1301 parameters\n", conf_file, conf_obj_name); + } + ++ val = json_object_get_value(conf_obj, "lorawan_public"); /* fetch value (if possible) */ ++ if (json_value_get_type(val) == JSONBoolean && (bool)json_value_get_boolean(val) == true) { ++ synch_word = 0x34; ++ } ++ + /* set configuration for RF chains */ + for (i = 0; i < LGW_RF_CHAIN_NB; ++i) { + memset(&rfconf, 0, sizeof rfconf); /* initialize configuration structure */ +@@ -437,6 +443,12 @@ static int parse_gateway_configuration(const char * conf_file) { + MSG("INFO: downstream port is configured to \"%s\"\n", serv_port_down); + } + ++ val = json_object_get_value(conf_obj, "synch_word"); ++ if (val != NULL) { ++ synch_word = (uint8_t)json_value_get_number(val); ++ MSG("INFO: synch word is configured to %02x\n", synch_word); ++ } ++ + /* get keep-alive interval (in seconds) for downstream (optional) */ + val = json_object_get_value(conf_obj, "keepalive_interval"); + if (val != NULL) { +@@ -727,6 +739,8 @@ int main(void) + exit(EXIT_FAILURE); + } + ++ lgw_conf_lora_synch_word(synch_word); ++ + /* spawn threads to manage upstream and downstream */ + i = pthread_create( &thrid_up, NULL, (void * (*)(void *))thread_up, NULL); + if (i != 0) { |