lora, etc: add stuff from multitec, add missing layers to README

This commit is contained in:
Stefan Eichenberger 2016-11-10 19:27:22 +01:00
parent 5a98ee7cca
commit d596febd66
25 changed files with 1696 additions and 0 deletions

10
README
View File

@ -9,6 +9,16 @@ branch: jethro
revision: HEAD
layers: meta-python, meta-oe, meta-networking
For images that contain NodeJS extensions:
URI: https://github.com/imyller/meta-nodejs.git
branch : jethro
revision: HEAD
URI: https://github.com/imyller/meta-nodejs-contrib.git
branch: jethro
revision: HEAD
To get an image that is compatible with the NetModule router, build an nmrouter-image. Set the MACHINE in conf/local.conf to
MACHINE ??= "armada-385-nbhw17-nb2800" or
MACHINE ??= "am335x-nbhw16"

View File

@ -0,0 +1,72 @@
# That file will be included in the Makefile files that have hardware dependencies
### SPI interface to the concentrator ###
# Accepted values:
# native Linux native SPI driver (/dev/spidev32766.0)
# ftdi FTDI SPI-over-USB bridge using libmpsse/libftdi/libusb
CFG_SPI= ftdi
### Concentrator chip ###
# Accepted values:
# sx1301 Semtech SX1301 production chip
# fpga1301 FPGA containing the SX1301 IP
CFG_CHIP= sx1301
### Radio chip(s) ###
# Accepted values:
# sx1257 Dual SX1257 transceivers, covering 860-1000 MHz
# sx1255 Dual SX1255 transceivers, covering 400-510 MHz
CFG_RADIO= sx1257
### RF band configuration ###
# Used to configured frequency restrictions (eg. if a SAW filter is installed)
# Accepted values:
# full Full range supported by the radio(s)
# eu868 ETSI 868 (866) MHz band
# us915 FCC 915 MHz band
# cn470 China 470 MHz band
# eu433 ETSI 433 MHz band
# cn780 China 780 MHz band
CFG_BAND= full
### Board misc parameters & calibration ###
# Used to configure misc board options.
# RX RSSI indication and TX power are highly dependant on radio, band, filter
# and RF front-ends, and must be calibrated for each new board design.
# Available calibration parameters:
# dev_nano_868 FPGA-based nano-concentrator, with 868 MHz SAW filter
# ref_1301_868 SX1301 reference board with SX1257 radios, 868 MHz filters
# ref_1301_433 SX1301 reference board with SX1255 radios, 433 MHz filters
# kerlink_868 Kerlink LoRa 868MHz gateway
# kerlink_433 Kerlink LoRa 433MHz gateway
# cisco_433 Cisco LoRa 433MHz gateway
# cisco_470 Cisco LoRa 470MHz gateway
# cisco_780 Cisco LoRa 780MHz gateway
# Keep empty for no calibration parameters (neutral values will be used).
# MTAC-LORA 900MHz
CFG_BRD= mtaclora
### Network Type ###
# Accepted values:
# private Default
# lora_mac Only compliant with devices running LoRa MAC
CFG_NET= private
### Debug options ###
# Set the DEBUG_* to 1 to activate debug mode in individual modules.
# Warning: that makes the module *very verbose*, do not use for production
DEBUG_AUX= 0
DEBUG_SPI= 0
DEBUG_REG= 0
# jjg - turning this on is useful to get HAL-related error messages that
# don't print out otherwise. It doesn't seem to add that much printing
# under normal operation.
DEBUG_HAL= 1
DEBUG_GPS= 0

View File

@ -0,0 +1,13 @@
diff --git a/libloragw/src/loragw_reg.c b/libloragw/src/loragw_reg.c
index 7fe0f67..dc90d93 100644
--- a/libloragw/src/loragw_reg.c
+++ b/libloragw/src/loragw_reg.c
@@ -48,7 +48,7 @@ Maintainer: Sylvain Miermont
#define PAGE_ADDR 0x00
#define PAGE_MASK 0x03
-const uint8_t FPGA_VERSION[] = { 27 }; /* several versions could be supported */
+const uint8_t FPGA_VERSION[] = { 27, 28 }; /* several versions could be supported */
/*
auto generated register mapping for C code : 11-Jul-2013 13:20:40

View File

@ -0,0 +1,13 @@
Index: git/libloragw/src/loragw_hal.c
===================================================================
--- git.orig/libloragw/src/loragw_hal.c 2014-12-16 16:07:20.812506157 -0600
+++ git/libloragw/src/loragw_hal.c 2014-12-16 16:18:34.427454833 -0600
@@ -1626,6 +1626,8 @@
break;
}
}
+
+ DEBUG_PRINTF("DEBUG: Tx pow_index %d, rf_power %d\n", pow_index, tx_pow_table[pow_index].rf_power);
/* loading TX imbalance correction */
target_mix_gain = tx_pow_table[pow_index].mix_gain;

View File

@ -0,0 +1,40 @@
diff --git a/libloragw/inc/loragw_hal.h b/libloragw/inc/loragw_hal.h
index 1516b65..24c5969 100644
--- a/libloragw/inc/loragw_hal.h
+++ b/libloragw/inc/loragw_hal.h
@@ -302,6 +312,11 @@ struct lgw_pkt_tx_s {
/* -------------------------------------------------------------------------- */
/* --- PUBLIC FUNCTIONS PROTOTYPES ------------------------------------------ */
+/**
+ * @brief Configure the lora synch word
+ * @param word for synch
+ */
+void lgw_conf_lora_synch_word(uint8_t word);
/**
@brief Configure an RF chain (must configure before start)
diff --git a/libloragw/src/loragw_hal.c b/libloragw/src/loragw_hal.c
index 5dbdf45..d0fe288 100644
--- a/libloragw/src/loragw_hal.c
+++ b/libloragw/src/loragw_hal.c
@@ -827,6 +851,19 @@ void lgw_constant_adjust(void) {
/* -------------------------------------------------------------------------- */
/* --- PUBLIC FUNCTIONS DEFINITION ------------------------------------------ */
+void lgw_conf_lora_synch_word(uint8_t word) {
+ uint8_t peak1 = word >> 4;
+ uint8_t peak2 = word & 0x0F;
+
+ lgw_reg_w(LGW_FRAME_SYNCH_PEAK1_POS, peak1); /* default 1 */
+ lgw_reg_w(LGW_FRAME_SYNCH_PEAK2_POS, peak2); /* default 2 */
+ lgw_reg_w(LGW_MBWSSF_FRAME_SYNCH_PEAK1_POS, peak1); /* default 1 */
+ lgw_reg_w(LGW_MBWSSF_FRAME_SYNCH_PEAK2_POS, peak2); /* default 2 */
+ lgw_reg_w(LGW_TX_FRAME_SYNCH_PEAK1_POS, peak1); /* default 1 */
+ lgw_reg_w(LGW_TX_FRAME_SYNCH_PEAK2_POS, peak2); /* default 2 */
+}
+
+
int lgw_rxrf_setconf(uint8_t rf_chain, struct lgw_conf_rxrf_s conf) {
/* check if the concentrator is running */

View File

@ -0,0 +1,59 @@
DESCRIPTION = "LoRa Gateway library"
HOMEPAGE = "https://www.semtech.com/"
PRIORITY = "optional"
SECTION = "console/utils"
# Semtech license is a modified BSD-style license
LICENSE = "SEMTECH"
LIC_FILES_CHKSUM = "file://LICENSE;md5=a2bdef95625509f821ba00460e3ae0eb"
DEPENDS = "libftdi libmpsse libusb1"
INC_PR = "r9"
PR = "${INC_PR}.1"
BRANCH = "1.7.0-mts"
SRCREV = "631dfedf1b535b6c3861d3c3868e02f48a84fb06"
SRC_URI = "git://git.multitech.net/lora_gateway;protocol=git;branch=${BRANCH} \
file://lora-gateway-debug.patch \
file://lora-gateway-sync-word.patch \
file://library.cfg \
"
S = "${WORKDIR}/git"
CFLAGS += "-Iinc -I. -DLIBFTDI1=1"
do_configure_append() {
# copy over custom library.cfg
cp ${WORKDIR}/library.cfg ${S}/libloragw/
}
do_compile() {
oe_runmake
}
do_install() {
install -d ${D}${includedir}/lora
install -d ${D}${libdir}/lora
install -m 0644 libloragw/libloragw.a ${D}${libdir}/lora
install -m 0644 libloragw/library.cfg ${D}${libdir}/lora
install -m 0644 libloragw/inc/* ${D}${includedir}/lora
install -d ${D}/opt/lora
install -m 0755 libloragw/test_* ${D}/opt/lora/
install -m 0755 util_pkt_logger/util_pkt_logger ${D}/opt/lora/
install -m 0755 util_band_survey/util_band_survey ${D}/opt/lora/
install -m 0755 util_spi_stress/util_spi_stress ${D}/opt/lora/
install -m 0755 util_tx_test/util_tx_test ${D}/opt/lora/
}
PACKAGES += "${PN}-utils ${PN}-utils-dbg"
FILES_${PN}-utils = "/opt/lora/*"
FILES_${PN}-utils-dbg = "/opt/lora/.debug"
FILES_${PN}-dev = "${includedir}/lora ${libdir}/lora/library.cfg"
FILES_${PN}-staticdev = "${libdir}/lora/libloragw.a"
# disable this on purpose for dev purposes
do_rm_work() {
echo "skipping"
}

View File

@ -0,0 +1,2 @@
# set to "yes" or "no" to control starting on boot
ENABLED="yes"

View File

@ -0,0 +1,80 @@
#!/bin/bash
NAME="lora-network-server"
ENABLED="yes"
START_STOP_DAEMON="/usr/sbin/start-stop-daemon"
[ -f /etc/default/$NAME ] && source /etc/default/$NAME
run_dir=/var/run/lora
conf_dir=/var/config/lora
conf_file=/opt/lora/lora-network-server.conf
conf_db=$conf_dir/lora-network-server.db
net_server=/opt/lora/lora-network-server
net_server_log=/var/log/lora-network-server.log
net_server_pidfile=$run_dir/$NAME.pid
pkt_fwd=/opt/lora/lora_pkt_fwd
pkt_fwd_pidfile=$run_dir/lora-pkt-fwd-1.pid
do_start() {
if ! [ -f $conf_file ]; then
echo "$0: $conf_file missing"
exit 1
fi
echo -n "Starting $NAME: "
mkdir -p $run_dir/1
# start network server
$START_STOP_DAEMON --start --background --make-pidfile \
--pidfile $net_server_pidfile --startas /bin/bash \
--chdir "/opt/lora" -- -c "exec $net_server \
-c $conf_file --lora-path $run_dir --db $conf_db \
--noconsole -l $net_server_log >> $net_server_log 2>&1"
sleep 2
# start packet forwarder
$START_STOP_DAEMON --start --background --make-pidfile \
--pidfile $pkt_fwd_pidfile --exec $pkt_fwd --chdir "/opt/lora/"
renice -n -20 -p $(pgrep lora-network-se)
renice -n -20 -p $(pgrep $(basename $pkt_fwd))
echo "OK"
}
do_stop() {
echo -n "Stopping $NAME: "
$START_STOP_DAEMON --stop --quiet --oknodo --pidfile $net_server_pidfile --retry 15
$START_STOP_DAEMON --stop --quiet --oknodo --pidfile $pkt_fwd_pidfile --retry 5
rm -f $net_server_pidfile $pkt_fwd_pidfile
echo "OK"
}
if [ "$ENABLED" != "yes" ]; then
echo "$NAME: disabled in /etc/default"
exit
fi
case "$1" in
"start")
do_start
;;
"stop")
do_stop
;;
"restart")
## Stop the service and regardless of whether it was
## running or not, start it again.
do_stop
do_start
;;
*)
## If no parameters are given, print which are avaiable.
echo "Usage: $0 {start|stop|restart}"
exit 1
;;
esac

View File

@ -0,0 +1,7 @@
/var/log/lora-pkt-fwd*.log /var/log/lora-network-server.log {
size 512k
rotate 4
compress
copytruncate
missingok
}

View File

@ -0,0 +1,46 @@
# THIS RECIPE FOR PICOCELL USES PATCHED LORA NETWORK SERVER THAT SUPPORTS
# MTP HARDWARE AND V2 PACKET FORWARDER PROTOCOL
DESCRIPTION = "MultiTech LoRa Network Server"
PRIORITY = "optional"
SECTION = "console/utils"
LICENSE = "Proprietary"
LIC_FILES_CHKSUM = "file://LICENSE;md5=7ffae4666a986c4ccf45e99e464f8402"
DEPENDS = "jsoncpp libmts mosquitto sqlite3"
RDEPENDS_${PN} += "lora-packet-forwarder logrotate"
PR = "r0"
SRC_URI = "http://multitech.net/downloads/lora-network-server_${TUNE_PKGARCH}_${PV}-mtp.tar.gz \
file://lora-network-server.init \
file://lora-network-server.default \
file://lora-network-server.logrotate.conf \
"
SRC_URI[md5sum] = "1fdcc48e8d62d4f8896e707f28596bfd"
SRC_URI[sha256sum] = "10ba082ad309b2b4bec0835ecf0741463020d962707942e5bb3e8598181591f1"
# binaries are already stripped, so suppress warning
INSANE_SKIP_${PN} = "already-stripped"
S = "${WORKDIR}"
LORA_DIR = "/opt/lora"
do_compile() {
}
do_install() {
install -d ${D}${LORA_DIR}
install -m 0755 lora-network-server ${D}${LORA_DIR}/
install -m 0644 lora-network-server.conf ${D}${LORA_DIR}/
install -d ${D}${sysconfdir}/default
install -m 0644 ${WORKDIR}/lora-network-server.default ${D}${sysconfdir}/default/lora-network-server
install -d ${D}${sysconfdir}/init.d
install -m 0755 ${WORKDIR}/lora-network-server.init ${D}${sysconfdir}/init.d/lora-network-server
install -d ${D}${sysconfdir}/logrotate.d
install -m 0644 ${WORKDIR}/lora-network-server.logrotate.conf ${D}${sysconfdir}/logrotate.d/lora-network-server.conf
}
CONFFILES_${PN} = "${sysconfdir}/default/lora-network-server"
FILES_${PN} += "${LORA_DIR}"
FILES_${PN}-dbg += "${LORA_DIR}/.debug"

View File

@ -0,0 +1,2 @@
# set to "yes" or "no" to control starting on boot
ENABLED="yes"

View File

@ -0,0 +1,105 @@
#!/bin/bash
NAME="lora-network-server"
ENABLED="yes"
[ -f /etc/default/$NAME ] && source /etc/default/$NAME
run_dir=/var/run/lora
conf_dir=/var/config/lora
conf_file=$conf_dir/lora-network-server.conf
conf_db=$conf_dir/lora-network-server.db
net_server=/opt/lora/lora-network-server
net_server_log=/var/log/lora-network-server.log
net_server_pidfile=$run_dir/$NAME.pid
pkt_fwd=/opt/lora/basic_pkt_fwd
pkt_fwd_log=/var/log/lora-pkt-fwd-1.log
pkt_fwd_pidfile=$run_dir/lora-pkt-fwd-1.pid
lora_us_id="MTAC-LORA-915"
lora_eu_id="MTAC-LORA-868"
read_card_info() {
# product-id of first lora card
lora_id=$(mts-io-sysfs show lora/product-id 2> /dev/null)
lora_eui=$(mts-io-sysfs show lora/eui 2> /dev/null)
# remove all colons
lora_eui_raw=${lora_eui//:/}
}
card_found() {
if [ "$lora_id" = "$lora_us_id" ] || [ "$lora_id" = "$lora_eu_id" ]; then
echo "Found lora card $lora_id"
return 0
else
return 1
fi
}
do_start() {
read_card_info
if ! [ -f $conf_file ]; then
echo "$0: $conf_file missing"
exit 1
fi
if ! card_found; then
echo "$0: MTAC-LORA not detected"
exit 1
fi
echo -n "Starting $NAME: "
mkdir -p $run_dir/1
# start network server
start-stop-daemon --start --background --make-pidfile \
--pidfile $net_server_pidfile --startas /bin/bash -- -c "exec $net_server \
-c $conf_file --lora-eui $lora_eui --lora-path $run_dir --db $conf_db \
--noconsole -l $net_server_log >> $net_server_log 2>&1"
sleep 2
# start packet forwarder
start-stop-daemon --start --background --make-pidfile \
--pidfile $pkt_fwd_pidfile --exec $pkt_fwd -- \
-c $run_dir/1
renice -n -20 -p $(pgrep lora-network-se)
renice -n -20 -p $(pgrep $(basename $pkt_fwd))
echo "OK"
}
do_stop() {
echo -n "Stopping $NAME: "
start-stop-daemon --stop --quiet --oknodo --pidfile $net_server_pidfile --retry 15
start-stop-daemon --stop --quiet --oknodo --pidfile $pkt_fwd_pidfile --retry 5
rm -f $net_server_pidfile $pkt_fwd_pidfile
echo "OK"
}
if [ "$ENABLED" != "yes" ]; then
echo "$NAME: disabled in /etc/default"
exit
fi
case "$1" in
"start")
do_start
;;
"stop")
do_stop
;;
"restart")
## Stop the service and regardless of whether it was
## running or not, start it again.
do_stop
do_start
;;
*)
## If no parameters are given, print which are avaiable.
echo "Usage: $0 {start|stop|restart}"
exit 1
;;
esac

View File

@ -0,0 +1,7 @@
/var/log/lora-pkt-fwd*.log /var/log/lora-network-server.log {
size 512k
rotate 4
compress
copytruncate
missingok
}

View File

@ -0,0 +1,49 @@
DESCRIPTION = "MultiTech LoRa Network Server"
PRIORITY = "optional"
SECTION = "console/utils"
LICENSE = "Proprietary"
LIC_FILES_CHKSUM = "file://LICENSE;md5=7ffae4666a986c4ccf45e99e464f8402"
DEPENDS = "jsoncpp libmts mosquitto sqlite3"
RDEPENDS_${PN} += "lora-packet-forwarder logrotate"
PR = "r0"
SRC_URI = "http://multitech.net/downloads/lora-network-server_${TUNE_PKGARCH}_${PV}.tar.gz \
file://lora-network-server.init \
file://lora-network-server.default \
file://lora-network-server.logrotate.conf \
"
SRC_URI[md5sum] = "8785cbe4a70ee288fa09f00593b1fdb1"
SRC_URI[sha256sum] = "5e6450244f21b4c28e780f36b3d1e7bf502ab25f835a0c21295caac11faec69b"
# binaries are already stripped, so suppress warning
INSANE_SKIP_${PN} = "already-stripped"
S = "${WORKDIR}"
LORA_DIR = "/opt/lora"
do_compile() {
}
inherit update-rc.d
INITSCRIPT_NAME = "lora-network-server"
INITSCRIPT_PARAMS = "defaults 80 30"
do_install() {
install -d ${D}${LORA_DIR}
install -m 0755 lora-network-server ${D}${LORA_DIR}/
install -m 0644 lora-network-server.conf.sample ${D}${LORA_DIR}/lora-network-server.conf.sample
install -d ${D}${sysconfdir}/default
install -m 0644 ${WORKDIR}/lora-network-server.default ${D}${sysconfdir}/default/lora-network-server
install -d ${D}${sysconfdir}/init.d
install -m 0755 ${WORKDIR}/lora-network-server.init ${D}${sysconfdir}/init.d/lora-network-server
install -d ${D}${sysconfdir}/logrotate.d
install -m 0644 ${WORKDIR}/lora-network-server.logrotate.conf ${D}${sysconfdir}/logrotate.d/lora-network-server.conf
}
CONFFILES_${PN} = "${sysconfdir}/default/lora-network-server"
FILES_${PN} += "${LORA_DIR}"
FILES_${PN}-dbg += "${LORA_DIR}/.debug"

View File

@ -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.

View File

@ -0,0 +1,7 @@
{
"gateway_conf": {
"server_address": "localhost",
"serv_port_up": 1780,
"serv_port_down": 1782
}
}

View File

@ -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) {

View File

@ -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");
}

View File

@ -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;

View File

@ -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");

View File

@ -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();

View File

@ -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 */

View File

@ -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) {

View File

@ -0,0 +1,58 @@
DESCRIPTION = "LoRa Packet Forwarder"
HOMEPAGE = "https://github.com/Lora-net"
PRIORITY = "optional"
SECTION = "console/utils"
# Semtech license is a modified BSD-style license
LICENSE = "SEMTECH"
LIC_FILES_CHKSUM = "file://LICENSE;md5=22af7693d7b76ef0fc76161c4be76c45"
DEPENDS = "lora-gateway"
PR = "r10"
# tag v1.4.1
SRCREV = "0011a60759a7d81656a5393e97089daab1ff1a81"
SRC_URI = "git://github.com/Lora-net/packet_forwarder.git;protocol=git \
file://lora-packet-forwarder-add-no-header-option.patch \
file://lora-packet-forwarder-set-spi-path.patch \
file://lora-packet-forwarder-skip-bad-packets.patch \
file://lora-packet-forwarder-fixb64.patch \
file://lora-packet-forwarder-mts-enhancements.patch \
file://lora-packet-forwarder-synch-word.patch \
file://lora-packet-forwarder-add-queue.patch \
file://README.md \
"
S = "${WORKDIR}/git"
LORA_DIR = "/opt/lora"
export LGW_PATH = "${STAGING_LIBDIR}/lora"
export LGW_INC = "${STAGING_INCDIR}/lora"
CFLAGS += "-I${LGW_INC} -Iinc -I."
do_compile() {
oe_runmake
}
do_install() {
install -d ${D}${LORA_DIR}
install -m 755 gps_pkt_fwd/gps_pkt_fwd ${D}${LORA_DIR}/
install -m 755 basic_pkt_fwd/basic_pkt_fwd ${D}${LORA_DIR}/
install -m 755 beacon_pkt_fwd/beacon_pkt_fwd ${D}${LORA_DIR}/
install -m 755 util_sink/util_sink ${D}${LORA_DIR}/
install -m 755 util_ack/util_ack ${D}${LORA_DIR}/
install -m 755 ${WORKDIR}/README.md ${D}${LORA_DIR}/
# skip util_tx_test since it conflicts with one in lora-gateway
# install -m 755 util_tx_test/util_tx_test ${D}${LORA_DIR}/
}
FILES_${PN} += "${LORA_DIR}"
FILES_${PN}-dbg += "${LORA_DIR}/.debug"
# disable this on purpose for dev purposes
do_rm_work() {
echo "skipping"
}

View File

@ -0,0 +1,21 @@
DESCRIPTION = "LoRa network server query tool"
HOMEPAGE = "http://www.multitech.net/"
LICENSE = "GPL-2.0"
LIC_FILES_CHKSUM = "file://LICENSE;md5=94d55d512a9ba36caa9b7df079bae19f"
DEPENDS = "jsoncpp libmts"
PR = "r1"
SRCREV = "${PV}"
SRC_URI = "git://git.multitech.net/lora-query;branch=master"
S = "${WORKDIR}/git"
do_compile() {
oe_runmake
}
do_install() {
oe_runmake install DESTDIR=${D}
}