diff options
author | Jason Reiss <jreiss@multitech.com> | 2016-10-14 10:05:23 -0500 |
---|---|---|
committer | Jason Reiss <jreiss@multitech.com> | 2016-10-14 10:05:23 -0500 |
commit | 5ebcefe167c398e98567bb4c05d7e9fb5bcbcfe7 (patch) | |
tree | 8cc4ae39c1ccf1bfac3c09397687e0808bbcba0b /recipes-connectivity/lora/lora-packet-forwarder-usb | |
parent | e84694799fe3301529c1b2b5661233af8a02f94c (diff) | |
download | meta-mlinux-5ebcefe167c398e98567bb4c05d7e9fb5bcbcfe7.tar.gz meta-mlinux-5ebcefe167c398e98567bb4c05d7e9fb5bcbcfe7.tar.bz2 meta-mlinux-5ebcefe167c398e98567bb4c05d7e9fb5bcbcfe7.zip |
lora: move old usb packet forwarder and library utilities to new recipes
add spi device path option to packet forwarder and library
Diffstat (limited to 'recipes-connectivity/lora/lora-packet-forwarder-usb')
9 files changed, 1112 insertions, 0 deletions
diff --git a/recipes-connectivity/lora/lora-packet-forwarder-usb/README.md b/recipes-connectivity/lora/lora-packet-forwarder-usb/README.md new file mode 100644 index 0000000..c927c60 --- /dev/null +++ b/recipes-connectivity/lora/lora-packet-forwarder-usb/README.md @@ -0,0 +1,38 @@ + + +(c) Senet, Inc 2016 + + + +3rd Party Licenses +------------------ + +This software incorporates the lora_gateway software which requires the +following statement to be included in its distribution. + +Copyright (c) 2013, SEMTECH S.A. +All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + * Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + * Neither the name of the Semtech corporation nor the + names of its contributors may be used to endorse or promote products + derived from this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND +ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL SEMTECH S.A. BE LIABLE FOR ANY +DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND +ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + + diff --git a/recipes-connectivity/lora/lora-packet-forwarder-usb/local_conf.json b/recipes-connectivity/lora/lora-packet-forwarder-usb/local_conf.json new file mode 100644 index 0000000..3c2af80 --- /dev/null +++ b/recipes-connectivity/lora/lora-packet-forwarder-usb/local_conf.json @@ -0,0 +1,7 @@ +{ + "gateway_conf": { + "server_address": "localhost", + "serv_port_up": 1780, + "serv_port_down": 1782 + } +} diff --git a/recipes-connectivity/lora/lora-packet-forwarder-usb/lora-packet-forwarder-add-no-header-option.patch b/recipes-connectivity/lora/lora-packet-forwarder-usb/lora-packet-forwarder-add-no-header-option.patch new file mode 100644 index 0000000..fd2fa24 --- /dev/null +++ b/recipes-connectivity/lora/lora-packet-forwarder-usb/lora-packet-forwarder-add-no-header-option.patch @@ -0,0 +1,45 @@ +From 03c697f2bcf538407ca6a0821dbbb65ab7679aff Mon Sep 17 00:00:00 2001 +From: Jason Reiss <jreiss@multitech.com> +Date: Thu, 16 Jul 2015 13:31:20 -0500 +Subject: [PATCH] feature: add option to send packets with no header + +--- + basic_pkt_fwd/src/basic_pkt_fwd.c | 7 +++++++ + 1 file changed, 7 insertions(+) + +diff --git a/basic_pkt_fwd/src/basic_pkt_fwd.c b/basic_pkt_fwd/src/basic_pkt_fwd.c +index e20dfc1..2223b4a 100644 +--- a/basic_pkt_fwd/src/basic_pkt_fwd.c ++++ b/basic_pkt_fwd/src/basic_pkt_fwd.c +@@ -1276,6 +1276,13 @@ void thread_down(void) { + if (val != NULL) { + 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"); + +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-usb/lora-packet-forwarder-add-queue.patch b/recipes-connectivity/lora/lora-packet-forwarder-usb/lora-packet-forwarder-add-queue.patch new file mode 100644 index 0000000..cd9a727 --- /dev/null +++ b/recipes-connectivity/lora/lora-packet-forwarder-usb/lora-packet-forwarder-add-queue.patch @@ -0,0 +1,316 @@ +From fdf5d6669d5132da9016840dfe2c1c99f525e4bc Mon Sep 17 00:00:00 2001 +From: Jason Reiss <jreiss@multitech.com> +Date: Tue, 29 Sep 2015 12:01:12 -0500 +Subject: [PATCH] add-queue to pkt-fwd + +--- + basic_pkt_fwd/src/basic_pkt_fwd.c | 93 +++++++++++++++++++++++++++++++++++-- + 1 file changed, 88 insertions(+), 5 deletions(-) + +diff --git a/basic_pkt_fwd/src/basic_pkt_fwd.c b/basic_pkt_fwd/src/basic_pkt_fwd.c +index e20dfc1..4d0bb35 100644 +--- a/basic_pkt_fwd/src/basic_pkt_fwd.c ++++ b/basic_pkt_fwd/src/basic_pkt_fwd.c +@@ -162,8 +162,19 @@ 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); + + /* -------------------------------------------------------------------------- */ +@@ -479,6 +490,7 @@ int main(void) + + /* threads */ + pthread_t thrid_up; ++ pthread_t thrid_queue; + pthread_t thrid_down; + + /* network socket creation */ +@@ -649,6 +661,11 @@ int main(void) + MSG("ERROR: [main] impossible to create downstream thread\n"); + 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); ++ } + + /* configure signal handling */ + sigemptyset(&sigact.sa_mask); +@@ -744,6 +761,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 */ + + /* if an exit signal was received, try to quit properly */ +@@ -1121,9 +1139,9 @@ void thread_up(void) { + } + + /* -------------------------------------------------------------------------- */ +-/* --- THREAD 2: POLLING SERVER AND EMITTING PACKETS ------------------------ */ ++/* --- THREAD 2: POLLING SERVER AND QUEUEING PACKETS ------------------------ */ + +-void thread_down(void) { ++void thread_queue(void) { + int i; /* loop variables */ + + /* configuration and metadata for an outbound packet */ +@@ -1462,11 +1480,48 @@ 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); +@@ -1476,7 +1531,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"); + } + +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-usb/lora-packet-forwarder-fixb64.patch b/recipes-connectivity/lora/lora-packet-forwarder-usb/lora-packet-forwarder-fixb64.patch new file mode 100644 index 0000000..dc0df42 --- /dev/null +++ b/recipes-connectivity/lora/lora-packet-forwarder-usb/lora-packet-forwarder-fixb64.patch @@ -0,0 +1,66 @@ +Index: git/basic_pkt_fwd/src/base64.c +=================================================================== +--- git.orig/basic_pkt_fwd/src/base64.c 2015-03-31 16:00:39.479058735 -0500 ++++ git/basic_pkt_fwd/src/base64.c 2015-03-31 16:02:18.529580540 -0500 +@@ -263,7 +263,7 @@ + DEBUG("ERROR: INVALID UNPADDED BASE64 STRING\n"); + return -1; + case 2: /* 2 chars in last block, must add 2 padding char */ +- if (max_len > (ret + 2 + 1)) { ++ if (max_len >= (ret + 2 + 1)) { + out[ret] = code_pad; + out[ret+1] = code_pad; + out[ret+2] = 0; +@@ -273,7 +273,7 @@ + return -1; + } + case 3: /* 3 chars in last block, must add 1 padding char */ +- if (max_len > (ret + 1 + 1)) { ++ if (max_len >= (ret + 1 + 1)) { + out[ret] = code_pad; + out[ret+1] = 0; + return ret+1; +Index: git/beacon_pkt_fwd/src/base64.c +=================================================================== +--- git.orig/beacon_pkt_fwd/src/base64.c 2015-03-31 16:00:39.479058735 -0500 ++++ git/beacon_pkt_fwd/src/base64.c 2015-03-31 16:03:26.040561508 -0500 +@@ -263,7 +263,7 @@ + DEBUG("ERROR: INVALID UNPADDED BASE64 STRING\n"); + return -1; + case 2: /* 2 chars in last block, must add 2 padding char */ +- if (max_len > (ret + 2 + 1)) { ++ if (max_len >= (ret + 2 + 1)) { + out[ret] = code_pad; + out[ret+1] = code_pad; + out[ret+2] = 0; +@@ -273,7 +273,7 @@ + return -1; + } + case 3: /* 3 chars in last block, must add 1 padding char */ +- if (max_len > (ret + 1 + 1)) { ++ if (max_len >= (ret + 1 + 1)) { + out[ret] = code_pad; + out[ret+1] = 0; + return ret+1; +Index: git/gps_pkt_fwd/src/base64.c +=================================================================== +--- git.orig/gps_pkt_fwd/src/base64.c 2015-03-31 16:02:59.344965478 -0500 ++++ git/gps_pkt_fwd/src/base64.c 2015-03-31 16:03:13.208755845 -0500 +@@ -263,7 +263,7 @@ + DEBUG("ERROR: INVALID UNPADDED BASE64 STRING\n"); + return -1; + case 2: /* 2 chars in last block, must add 2 padding char */ +- if (max_len > (ret + 2 + 1)) { ++ if (max_len >= (ret + 2 + 1)) { + out[ret] = code_pad; + out[ret+1] = code_pad; + out[ret+2] = 0; +@@ -273,7 +273,7 @@ + return -1; + } + case 3: /* 3 chars in last block, must add 1 padding char */ +- if (max_len > (ret + 1 + 1)) { ++ if (max_len >= (ret + 1 + 1)) { + out[ret] = code_pad; + out[ret+1] = 0; + return ret+1; diff --git a/recipes-connectivity/lora/lora-packet-forwarder-usb/lora-packet-forwarder-mts-enhancements.patch b/recipes-connectivity/lora/lora-packet-forwarder-usb/lora-packet-forwarder-mts-enhancements.patch new file mode 100644 index 0000000..e1da462 --- /dev/null +++ b/recipes-connectivity/lora/lora-packet-forwarder-usb/lora-packet-forwarder-mts-enhancements.patch @@ -0,0 +1,321 @@ +Index: git/basic_pkt_fwd/src/basic_pkt_fwd.c +=================================================================== +--- git.orig/basic_pkt_fwd/src/basic_pkt_fwd.c 2015-04-01 15:14:12.192933389 -0500 ++++ git/basic_pkt_fwd/src/basic_pkt_fwd.c 2015-04-01 15:36:38.731731561 -0500 +@@ -42,6 +42,8 @@ + #include <netdb.h> /* gai_strerror */ + + #include <pthread.h> ++#include <getopt.h> ++#include <linux/limits.h> + + #include "parson.h" + #include "base64.h" +@@ -472,19 +474,65 @@ + return x; + } + ++void usage(char *proc_name) { ++ fprintf(stderr, "Usage: %s [-c config_dir] [-l logfile]\n", proc_name); ++ exit(1); ++} ++ ++ ++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}, ++}; ++ + /* -------------------------------------------------------------------------- */ + /* --- MAIN FUNCTION -------------------------------------------------------- */ + +-int main(void) ++int main(int argc, char *argv[]) + { + struct sigaction sigact; /* SIGQUIT&SIGINT&SIGTERM signal handling */ + int i; /* loop variable and temporary variable for return value */ + + /* configuration file related */ +- char *global_cfg_path= "global_conf.json"; /* contain global (typ. network-wide) configuration */ +- char *local_cfg_path = "local_conf.json"; /* contain node specific configuration, overwrite global parameters for parameters that are defined in both */ +- char *debug_cfg_path = "debug_conf.json"; /* if present, all other configuration files are ignored */ +- ++ char *global_cfg_name = "global_conf.json"; /* contain global (typ. network-wide) configuration */ ++ char *local_cfg_name = "local_conf.json"; /* contain node specific configuration, overwrite global parameters for parameters that are defined in both */ ++ char *debug_cfg_name = "debug_conf.json"; /* if present, all other configuration files are ignored */ ++ ++ int opt_ind = 0; ++ char cfg_dir[PATH_MAX] = {0}; ++ 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) { ++ switch(i) { ++ case 0: ++ break; ++ case '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; ++ default: ++ usage(proc_name); ++ break; ++ } ++ } ++ ++ snprintf(global_cfg_path, sizeof(global_cfg_path), "%s%s", cfg_dir, global_cfg_name); ++ snprintf(local_cfg_path, sizeof(local_cfg_path), "%s%s", cfg_dir, local_cfg_name); ++ snprintf(debug_cfg_path, sizeof(debug_cfg_path), "%s%s", cfg_dir, debug_cfg_name); ++ + /* threads */ + pthread_t thrid_up; + pthread_t thrid_down; +@@ -522,6 +570,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("*** Basic Packet Forwarder for Lora Gateway ***\nVersion: " VERSION_STRING "\n"); +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> ++#include <getopt.h> ++#include <linux/limits.h> + + #include "parson.h" + #include "base64.h" +@@ -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] [-l logfile]\n", proc_name); ++ exit(1); ++} ++ ++ ++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}, ++}; ++ + /* -------------------------------------------------------------------------- */ + /* --- MAIN FUNCTION -------------------------------------------------------- */ + +-int main(void) ++int main(int argc, char *argv[]) + { + struct sigaction sigact; /* SIGQUIT&SIGINT&SIGTERM signal handling */ + int i; /* loop variable and temporary variable for return value */ + + /* configuration file related */ +- char *global_cfg_path= "global_conf.json"; /* contain global (typ. network-wide) configuration */ +- char *local_cfg_path = "local_conf.json"; /* contain node specific configuration, overwrite global parameters for parameters that are defined in both */ +- char *debug_cfg_path = "debug_conf.json"; /* if present, all other configuration files are ignored */ +- ++ char *global_cfg_name = "global_conf.json"; /* contain global (typ. network-wide) configuration */ ++ char *local_cfg_name = "local_conf.json"; /* contain node specific configuration, overwrite global parameters for parameters that are defined in both */ ++ char *debug_cfg_name = "debug_conf.json"; /* if present, all other configuration files are ignored */ ++ ++ int opt_ind = 0; ++ char cfg_dir[PATH_MAX] = {0}; ++ 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) { ++ switch(i) { ++ case 0: ++ break; ++ case '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; ++ default: ++ usage(proc_name); ++ break; ++ } ++ } ++ ++ snprintf(global_cfg_path, sizeof(global_cfg_path), "%s%s", cfg_dir, global_cfg_name); ++ snprintf(local_cfg_path, sizeof(local_cfg_path), "%s%s", cfg_dir, local_cfg_name); ++ snprintf(debug_cfg_path, sizeof(debug_cfg_path), "%s%s", cfg_dir, debug_cfg_name); ++ + /* 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 ++++ git/beacon_pkt_fwd/src/beacon_pkt_fwd.c 2015-04-01 15:14:12.284931938 -0500 +@@ -45,6 +45,8 @@ + #include <netdb.h> /* gai_strerror */ + + #include <pthread.h> ++#include <getopt.h> ++#include <linux/limits.h> + + #include "parson.h" + #include "base64.h" +@@ -618,19 +620,65 @@ + return x; + } + ++void usage(char *proc_name) { ++ fprintf(stderr, "Usage: %s [-c config_dir] [-l logfile]\n", proc_name); ++ exit(1); ++} ++ ++ ++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}, ++}; ++ + /* -------------------------------------------------------------------------- */ + /* --- MAIN FUNCTION -------------------------------------------------------- */ + +-int main(void) ++int main(int argc, char *argv[]) + { + struct sigaction sigact; /* SIGQUIT&SIGINT&SIGTERM signal handling */ + int i; /* loop variable and temporary variable for return value */ + + /* configuration file related */ +- char *global_cfg_path= "global_conf.json"; /* contain global (typ. network-wide) configuration */ +- char *local_cfg_path = "local_conf.json"; /* contain node specific configuration, overwrite global parameters for parameters that are defined in both */ +- char *debug_cfg_path = "debug_conf.json"; /* if present, all other configuration files are ignored */ +- ++ char *global_cfg_name = "global_conf.json"; /* contain global (typ. network-wide) configuration */ ++ char *local_cfg_name = "local_conf.json"; /* contain node specific configuration, overwrite global parameters for parameters that are defined in both */ ++ char *debug_cfg_name = "debug_conf.json"; /* if present, all other configuration files are ignored */ ++ ++ int opt_ind = 0; ++ char cfg_dir[PATH_MAX] = {0}; ++ 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) { ++ switch(i) { ++ case 0: ++ break; ++ case '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; ++ default: ++ usage(proc_name); ++ break; ++ } ++ } ++ ++ snprintf(global_cfg_path, sizeof(global_cfg_path), "%s%s", cfg_dir, global_cfg_name); ++ snprintf(local_cfg_path, sizeof(local_cfg_path), "%s%s", cfg_dir, local_cfg_name); ++ snprintf(debug_cfg_path, sizeof(debug_cfg_path), "%s%s", cfg_dir, debug_cfg_name); ++ + /* 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-usb/lora-packet-forwarder-set-spi-path.patch b/recipes-connectivity/lora/lora-packet-forwarder-usb/lora-packet-forwarder-set-spi-path.patch new file mode 100644 index 0000000..01ce509 --- /dev/null +++ b/recipes-connectivity/lora/lora-packet-forwarder-usb/lora-packet-forwarder-set-spi-path.patch @@ -0,0 +1,111 @@ +Index: git/basic_pkt_fwd/src/basic_pkt_fwd.c +=================================================================== +--- git.orig/basic_pkt_fwd/src/basic_pkt_fwd.c 2015-01-07 14:38:10.016886785 -0600 ++++ git/basic_pkt_fwd/src/basic_pkt_fwd.c 2015-01-07 14:49:57.823412026 -0600 +@@ -106,6 +106,7 @@ + /* network configuration variables */ + 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 spi_device_path[64] = {0} ; /* custom SPI device path */ + 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 */ + static int keepalive_time = DEFAULT_KEEPALIVE; /* send a PULL_DATA request every X seconds, negative = disabled */ +@@ -393,6 +394,13 @@ + strncpy(serv_addr, str, sizeof serv_addr); + MSG("INFO: server hostname or IP address is configured to \"%s\"\n", serv_addr); + } ++ ++ /* spi device path (optional) */ ++ str = json_object_get_string(conf_obj, "spi_device"); ++ if (str != NULL) { ++ strncpy(spi_device_path, str, sizeof(spi_device_path)-1); ++ MSG("INFO: SPI device is configured to \"%s\"\n", spi_device_path); ++ } + + /* get up and down ports (optional) */ + val = json_object_get_value(conf_obj, "serv_port_up"); +@@ -629,6 +637,10 @@ + exit(EXIT_FAILURE); + } + freeaddrinfo(result); ++ ++ /* set custom SPI device path if configured */ ++ if (strlen(spi_device_path) > 0) ++ lgw_spi_set_path(spi_device_path); + + /* starting the concentrator */ + i = lgw_start(); +Index: git/beacon_pkt_fwd/src/beacon_pkt_fwd.c +=================================================================== +--- git.orig/beacon_pkt_fwd/src/beacon_pkt_fwd.c 2015-01-05 11:29:12.946020392 -0600 ++++ git/beacon_pkt_fwd/src/beacon_pkt_fwd.c 2015-01-07 14:57:00.338533303 -0600 +@@ -115,6 +115,7 @@ + /* network configuration variables */ + 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 spi_device_path[64] = {0} ; /* custom SPI device path */ + 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 */ + static int keepalive_time = DEFAULT_KEEPALIVE; /* send a PULL_DATA request every X seconds, negative = disabled */ +@@ -440,6 +441,13 @@ + strncpy(serv_addr, str, sizeof serv_addr); + MSG("INFO: server hostname or IP address is configured to \"%s\"\n", serv_addr); + } ++ ++ /* spi device path (optional) */ ++ str = json_object_get_string(conf_obj, "spi_device"); ++ if (str != NULL) { ++ strncpy(spi_device_path, str, sizeof(spi_device_path)-1); ++ MSG("INFO: SPI device is configured to \"%s\"\n", spi_device_path); ++ } + + /* get up and down ports (optional) */ + val = json_object_get_value(conf_obj, "serv_port_up"); +@@ -774,6 +782,10 @@ + exit(EXIT_FAILURE); + } + freeaddrinfo(result); ++ ++ /* set custom SPI device path if configured */ ++ if (strlen(spi_device_path) > 0) ++ lgw_spi_set_path(spi_device_path); + + /* starting the concentrator */ + i = lgw_start(); +Index: git/gps_pkt_fwd/src/gps_pkt_fwd.c +=================================================================== +--- git.orig/gps_pkt_fwd/src/gps_pkt_fwd.c 2015-01-05 11:29:12.946020392 -0600 ++++ git/gps_pkt_fwd/src/gps_pkt_fwd.c 2015-01-07 14:56:03.320278543 -0600 +@@ -110,6 +110,7 @@ + /* network configuration variables */ + 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 spi_device_path[64] = {0} ; /* custom SPI device path */ + 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 */ + static int keepalive_time = DEFAULT_KEEPALIVE; /* send a PULL_DATA request every X seconds, negative = disabled */ +@@ -424,6 +425,13 @@ + strncpy(serv_addr, str, sizeof serv_addr); + MSG("INFO: server hostname or IP address is configured to \"%s\"\n", serv_addr); + } ++ ++ /* spi device path (optional) */ ++ str = json_object_get_string(conf_obj, "spi_device"); ++ if (str != NULL) { ++ strncpy(spi_device_path, str, sizeof(spi_device_path)-1); ++ MSG("INFO: SPI device is configured to \"%s\"\n", spi_device_path); ++ } + + /* get up and down ports (optional) */ + val = json_object_get_value(conf_obj, "serv_port_up"); +@@ -717,6 +725,10 @@ + exit(EXIT_FAILURE); + } + freeaddrinfo(result); ++ ++ /* set custom SPI device path if configured */ ++ if (strlen(spi_device_path) > 0) ++ lgw_spi_set_path(spi_device_path); + + /* starting the concentrator */ + i = lgw_start(); diff --git a/recipes-connectivity/lora/lora-packet-forwarder-usb/lora-packet-forwarder-skip-bad-packets.patch b/recipes-connectivity/lora/lora-packet-forwarder-usb/lora-packet-forwarder-skip-bad-packets.patch new file mode 100644 index 0000000..eb9450f --- /dev/null +++ b/recipes-connectivity/lora/lora-packet-forwarder-usb/lora-packet-forwarder-skip-bad-packets.patch @@ -0,0 +1,109 @@ +Index: git/basic_pkt_fwd/src/basic_pkt_fwd.c +=================================================================== +--- git.orig/basic_pkt_fwd/src/basic_pkt_fwd.c 2014-12-16 17:03:32.891297739 -0600 ++++ git/basic_pkt_fwd/src/basic_pkt_fwd.c 2014-12-18 10:49:22.379916372 -0600 +@@ -928,7 +928,8 @@ + 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 */ +@@ -966,7 +967,8 @@ + 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: +@@ -985,7 +987,8 @@ + 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 */ +@@ -1014,7 +1017,8 @@ + 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 */ +@@ -1039,7 +1043,8 @@ + } + } 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/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-usb/lora-packet-forwarder-synch-word.patch b/recipes-connectivity/lora/lora-packet-forwarder-usb/lora-packet-forwarder-synch-word.patch new file mode 100644 index 0000000..2f04eb1 --- /dev/null +++ b/recipes-connectivity/lora/lora-packet-forwarder-usb/lora-packet-forwarder-synch-word.patch @@ -0,0 +1,99 @@ + +diff --git a/basic_pkt_fwd/src/basic_pkt_fwd.c b/basic_pkt_fwd/src/basic_pkt_fwd.c +index 2223b4a..2db6e26 100644 +--- a/basic_pkt_fwd/src/basic_pkt_fwd.c ++++ b/basic_pkt_fwd/src/basic_pkt_fwd.c +@@ -103,7 +104,8 @@ 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 */ + 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); + } +- ++ ++ 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) { +@@ -637,7 +721,9 @@ int main(void) + MSG("ERROR: [main] failed to start the concentrator\n"); + 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) { +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) { |