diff --git a/README.md b/README.md index 5f73cc1..fc9c1b9 100644 --- a/README.md +++ b/README.md @@ -1 +1,48 @@ -# rak_common_for_gateway \ No newline at end of file +# rak_common_for_gateway + +## Introduction + +The aim of this project is to help users set up a LoRa network easily. The User Guide can be get from our Web. + +## Supported platforms + +This project currently provides support for the below platforms. +* RAK831 +* RAK833 +* RAK2245 +* RAK2247 +* RAK7243 + +## Changelog + +2019-05-24 V2.9 + +* 1.Multiple models are integrated with one common version. +* 2.Upgrade LoRa server to 3.0. + +## Installation procedure + +step1 : Download and install [Raspbian Stretch LITE](https://www.raspberrypi.org/downloads/raspbian/) + +step2 : Use "sudo raspi-config" command, enable spi and i2c interface. + +step3 : Clone the installer and start the installation. + + $ sudo apt update; sudo apt install git -y + $ git clone https://github.com/RAKWireless/rak_common_for_gateway.git ~/rak_common_for_gateway + $ cd ~/rak_common_for_gateway + $ sudo ./install.sh + +step4 : Next you will see some messages as follow. Please select the corresponding hardware model. + + Please select your gateway model: + * 1.RAK831 + * 2.RAK833 + * 3.RAK2245 + * 4.RAK2247 + * 5.RAK7243 + Please enter 1-5 to select the model: + +step5 : Wait a moment and the installation is complete.If your gateway uses a wired connection, please reconfigure the LAN's IP address using "sudo gateway-config" after the installation is complete. + +step6 : For more other features, please use "sudo gateway-config". diff --git a/ap/Makefile_ap b/ap/Makefile_ap new file mode 100644 index 0000000..a704972 --- /dev/null +++ b/ap/Makefile_ap @@ -0,0 +1,21 @@ +PREFIX=/usr/local/rak/ap +MANDIR=$(PREFIX)/share/man +BINDIR=$(PREFIX)/bin + +all: + @echo "Run 'make install' for installation." + @echo "Run 'make uninstall' for uninstallation." + +install: + install -Dm755 create_ap $(DESTDIR)$(BINDIR)/create_ap + install -Dm644 create_ap.conf $(DESTDIR)/etc/create_ap.conf + [ ! -d /lib/systemd/system ] || install -Dm644 create_ap.service $(DESTDIR)$(PREFIX)/lib/systemd/system/create_ap.service + install -Dm644 bash_completion $(DESTDIR)$(PREFIX)/share/bash-completion/completions/create_ap + install -Dm644 README.md $(DESTDIR)$(PREFIX)/share/doc/create_ap/README.md + +uninstall: + rm -f $(DESTDIR)$(BINDIR)/create_ap + rm -f $(DESTDIR)/etc/create_ap.conf + [ ! -f /lib/systemd/system/create_ap.service ] || rm -f $(DESTDIR)$(PREFIX)/lib/systemd/system/create_ap.service + rm -f $(DESTDIR)$(PREFIX)/share/bash-completion/completions/create_ap + rm -f $(DESTDIR)$(PREFIX)/share/doc/create_ap/README.md diff --git a/ap/create_ap.conf b/ap/create_ap.conf new file mode 100644 index 0000000..4bf9738 --- /dev/null +++ b/ap/create_ap.conf @@ -0,0 +1,28 @@ +CHANNEL=default +GATEWAY=192.168.12.1 +WPA_VERSION=2 +ETC_HOSTS=0 +DHCP_DNS=gateway +NO_DNS=0 +NO_DNSMASQ=0 +HIDDEN=0 +MAC_FILTER=0 +MAC_FILTER_ACCEPT=/etc/hostapd/hostapd.accept +ISOLATE_CLIENTS=0 +SHARE_METHOD=nat +IEEE80211N=0 +IEEE80211AC=0 +HT_CAPAB=[HT40+] +VHT_CAPAB= +DRIVER=nl80211 +NO_VIRT=0 +COUNTRY= +FREQ_BAND=2.4 +NEW_MACADDR= +DAEMONIZE=0 +NO_HAVEGED=0 +WIFI_IFACE=wlan0 +INTERNET_IFACE=eth0 +SSID=Rakwireless_XXXX +PASSPHRASE=rakwireless +USE_PSK=0 diff --git a/ap/create_ap.service b/ap/create_ap.service new file mode 100644 index 0000000..e660889 --- /dev/null +++ b/ap/create_ap.service @@ -0,0 +1,13 @@ +[Unit] +Description=Create AP Service +After=network.target + +[Service] +Type=simple +ExecStart=/usr/local/rak/ap/bin/create_ap --config /usr/local/rak/ap/create_ap.conf +KillSignal=SIGINT +Restart=on-failure +RestartSec=5 + +[Install] +WantedBy=multi-user.target diff --git a/ap/install.sh b/ap/install.sh new file mode 100755 index 0000000..43b7e04 --- /dev/null +++ b/ap/install.sh @@ -0,0 +1,29 @@ +#!/bin/bash +# script needs to be run with super privilege +if [ $(id -u) -ne 0 ]; then + printf "Script must be run with superuser privilege. Try 'sudo ./install.sh'\n" + exit 1 +fi + +set -e + +SCRIPT_COMMON_FILE=$(pwd)/../rak/rak/shell_script/rak_common.sh +source $SCRIPT_COMMON_FILE + +apt-get install util-linux procps hostapd iproute2 iw haveged dnsmasq + +if [ ! -d create_ap ]; then + git clone https://github.com/oblique/create_ap +fi +cp Makefile_ap create_ap/Makefile +pushd create_ap +make install +popd +cp create_ap.service /lib/systemd/system/ +cp create_ap.conf /usr/local/rak/ap + +./set_ssid +#systemctl enable create_ap +#mv /sbin/wpa_supplicant /sbin/wpa_supplicant_bak + +echo_success "Install ap success!" diff --git a/ap/set_ssid b/ap/set_ssid new file mode 100755 index 0000000..24f3d82 --- /dev/null +++ b/ap/set_ssid @@ -0,0 +1,9 @@ +#!/bin/bash + +GATEWAY_EUI_NIC="wlan0" + +GATEWAY_EUI=$(ip link show $GATEWAY_EUI_NIC | awk '/ether/ {print $2}' | awk -F\: '{print $5$6}') +GATEWAY_EUI=${GATEWAY_EUI^^} + +sed -i "26c SSID=Rakwireless_$GATEWAY_EUI" /usr/local/rak/ap/create_ap.conf +sed -i "s/^.*ap_ssid.*$/\\t\\t\"ap_ssid\":\"Rakwireless_$GATEWAY_EUI\",/" /usr/local/rak/gateway-config-info.json diff --git a/choose_model.sh b/choose_model.sh new file mode 100755 index 0000000..51a47bc --- /dev/null +++ b/choose_model.sh @@ -0,0 +1,98 @@ +#!/bin/bash + +# Stop on the first sign of trouble +#set -e + +if [ $UID != 0 ]; then + echo "ERROR: Operation not permitted. Forgot sudo?" + exit 1 +fi + +function echo_yellow() +{ + echo -e "\033[1;33m$1\033[0m" +} + +do_check_variable_type(){ + local a="$1" + printf "%d" "$a" &>/dev/null && return 0 + printf "%d" "$(echo $a|sed 's/^[+-]\?0\+//')" &>/dev/null && return 0 + printf "%f" "$a" &>/dev/null && return 1 + [ ${#a} -eq 1 ] && return 2 + return 3 +} + +do_check_variable_type_echo(){ + local a="$1" + printf "%d" "$a" &>/dev/null && echo "integer, return 0" && return 0 + printf "%d" "$(echo $a|sed 's/^[+-]\?0\+//')" &>/dev/null && echo "integer,return 0" && return 0 + printf "%f" "$a" &>/dev/null && echo "number,return 1" && return 1 + [ ${#a} -eq 1 ] && echo "char, return 2" && return 2 + echo "string, return 3" && return 3 +} + +function echo_model_info() +{ + echo_yellow "Please select your gateway model:" + echo_yellow "*\t1.RAK831" + echo_yellow "*\t2.RAK833" + echo_yellow "*\t3.RAK2245" + echo_yellow "*\t4.RAK2247" + echo_yellow "*\t5.RAK7243" + echo_yellow "Please enter 1-5 to select the model:\c" +} + +function do_set_model_to_json() +{ + JSON_FILE=./rak/rak/rak_gw_model.json + if [ $1 -eq 1 ]; then + GW_MODEL=RAK831 + elif [ $1 -eq 2 ]; then + GW_MODEL=RAK833 + elif [ $1 -eq 3 ]; then + GW_MODEL=RAK2245 + elif [ $1 -eq 4 ]; then + GW_MODEL=RAK2247 + elif [ $1 -eq 5 ]; then + GW_MODEL=RAK7243 + else + # Never come here + echo "error" + return 1 + fi + linenum=`sed -n "/gw_model/=" $JSON_FILE` + sed -i "${linenum}c\\\\t\"gw_model\": \"$GW_MODEL\"," $JSON_FILE +} + +function do_set_model() +{ + echo_model_info + while [ 1 -eq 1 ] + do + read RAK_MODEL + if [ -z "$RAK_MODEL" ]; then + echo_yellow "IF Please enter 1-5 to select the model:\c" + continue + fi + + do_check_variable_type $RAK_MODEL + RET=$? + + if [ $RET -eq 0 ]; then + if [ $RAK_MODEL -lt 1 ] || [ $RAK_MODEL -gt 5 ]; then + echo_yellow "IF Please enter 1-5 to select the model:\c" + continue + else + do_set_model_to_json $RAK_MODEL + return 0 + fi + else + echo_yellow "IF Please enter 1-5 to select the model:\c" + continue + + fi + done +} + +do_set_model + diff --git a/first_boot/expand_rootfs.sh b/first_boot/expand_rootfs.sh new file mode 100755 index 0000000..8766b3d --- /dev/null +++ b/first_boot/expand_rootfs.sh @@ -0,0 +1,80 @@ +#!/bin/sh + +do_expand_rootfs() { + ROOT_PART=$(mount | sed -n 's|^/dev/\(.*\) on / .*|\1|p') + + PART_NUM=${ROOT_PART#mmcblk0p} + if [ "$PART_NUM" = "$ROOT_PART" ]; then + whiptail --msgbox "$ROOT_PART is not an SD card. Don't know how to expand" 20 60 2 + return 0 + fi + + # NOTE: the NOOBS partition layout confuses parted. For now, let's only + # agree to work with a sufficiently simple partition layout + if [ "$PART_NUM" -ne 2 ]; then + whiptail --msgbox "Your partition layout is not currently supported by this tool. You are probably using NOOBS, in which case your root filesystem is already expanded anyway." 20 60 2 + return 0 + fi + + LAST_PART_NUM=$(parted /dev/mmcblk0 -ms unit s p | tail -n 1 | cut -f 1 -d:) + if [ $LAST_PART_NUM -ne $PART_NUM ]; then + whiptail --msgbox "$ROOT_PART is not the last partition. Don't know how to expand" 20 60 2 + return 0 + fi + + # Get the starting offset of the root partition + PART_START=$(parted /dev/mmcblk0 -ms unit s p | grep "^${PART_NUM}" | cut -f 2 -d: | sed 's/[^0-9]//g') + [ "$PART_START" ] || return 1 + # Return value will likely be error for fdisk as it fails to reload the + # partition table because the root fs is mounted + fdisk /dev/mmcblk0 < /etc/init.d/resize2fs_once && +#!/bin/sh +### BEGIN INIT INFO +# Provides: resize2fs_once +# Required-Start: +# Required-Stop: +# Default-Start: 3 +# Default-Stop: +# Short-Description: Resize the root filesystem to fill partition +# Description: +### END INIT INFO + +. /lib/lsb/init-functions + +case "\$1" in + start) + log_daemon_msg "Starting resize2fs_once" && + resize2fs /dev/$ROOT_PART && + update-rc.d resize2fs_once remove && + rm /etc/init.d/resize2fs_once && + log_end_msg \$? + ;; + *) + echo "Usage: \$0 start" >&2 + exit 3 + ;; +esac +EOF + chmod +x /etc/init.d/resize2fs_once && + update-rc.d resize2fs_once defaults && + if [ "$INTERACTIVE" = True ]; then + whiptail --msgbox "Root partition has been resized.\nThe filesystem will be enlarged upon the next reboot" 20 60 2 + fi +} + +do_expand_rootfs diff --git a/first_boot/init_loraserver_db b/first_boot/init_loraserver_db new file mode 100755 index 0000000..61b69a0 --- /dev/null +++ b/first_boot/init_loraserver_db @@ -0,0 +1,19 @@ +#!/bin/bash + +# Try to get gateway ID from MAC address +# First try eth0, if that does not exist, try wlan0 (for RPi Zero) +GATEWAY_EUI_NIC="eth0" +if [[ `grep "$GATEWAY_EUI_NIC" /proc/net/dev` == "" ]]; then + GATEWAY_EUI_NIC="wlan0" +fi + +if [[ `grep "$GATEWAY_EUI_NIC" /proc/net/dev` == "" ]]; then + echo "ERROR: No network interface found. Cannot set gateway ID." + exit 1 +fi + +GATEWAY_EUI=$(ip link show $GATEWAY_EUI_NIC | awk '/ether/ {print $2}' | awk -F\: '{print $1$2$3"FFFE"$4$5$6}') +GATEWAY_EUI=${GATEWAY_EUI^^} + +sudo -u postgres psql loraserver_as -c "update gateway set mac='\x$GATEWAY_EUI';" +sudo -u postgres psql loraserver_ns -c "update gateway set gateway_id='\x$GATEWAY_EUI';" diff --git a/first_boot/install.sh b/first_boot/install.sh new file mode 100755 index 0000000..8225f43 --- /dev/null +++ b/first_boot/install.sh @@ -0,0 +1,16 @@ +#!/bin/bash + +# Stop on the first sign of trouble +set -e + +SCRIPT_COMMON_FILE=$(pwd)/../rak/rak/shell_script/rak_common.sh +source $SCRIPT_COMMON_FILE + +if [ $UID != 0 ]; then + echo_error "Operation not permitted. Forgot sudo?" + exit 1 +fi + + +cp ../first_boot /usr/local/rak/ -rf +rm /usr/local/rak/first_boot/install.sh diff --git a/first_boot/set_ssid b/first_boot/set_ssid new file mode 100755 index 0000000..7dd1563 --- /dev/null +++ b/first_boot/set_ssid @@ -0,0 +1,18 @@ +#!/bin/bash + +GATEWAY_EUI_NIC="wlan0" +if [[ `grep "$GATEWAY_EUI_NIC" /proc/net/dev` == "" ]]; then + GATEWAY_EUI_NIC="eth0" +fi +if [[ `grep "$GATEWAY_EUI_NIC" /proc/net/dev` == "" ]]; then + echo "ERROR: No network interface found. Cannot set gateway ID." + exit +fi +GATEWAY_EUI=$(ip link show $GATEWAY_EUI_NIC | awk '/ether/ {print $2}' | awk -F\: '{print $5$6}') +GATEWAY_EUI=${GATEWAY_EUI^^} + +sed -i "26c SSID=Rakwireless_$GATEWAY_EUI" /usr/local/rak/ap/create_ap.conf + +sed -i "s/^.*ap_ssid.*$/\"ap_ssid\":\"Rakwireless_$GATEWAY_EUI\",/" /usr/local/rak/gateway-config-info.json +sed -i "s/^.*ap_pwd.*$/\"ap_pwd\":\"rakwireless\"/" /usr/local/rak/gateway-config-info.json + diff --git a/install.sh b/install.sh new file mode 100755 index 0000000..1040b9a --- /dev/null +++ b/install.sh @@ -0,0 +1,54 @@ +#!/bin/bash + +# Stop on the first sign of trouble +set -e + +if [ $UID != 0 ]; then + echo "ERROR: Operation not permitted. Forgot sudo?" + exit 1 +fi + +SCRIPT_COMMON_FILE=$(pwd)/rak/rak/shell_script/rak_common.sh +source $SCRIPT_COMMON_FILE + +# select gw model +./choose_model.sh + +apt update +pushd rak +./install.sh +sleep 1 +popd + +pushd ap +./install.sh +sleep 1 +popd + +pushd sysconf +./install.sh +sleep 1 +popd + +pushd loraserver +./install.sh +sleep 1 +popd + +#pushd lorawan +#./install.sh +#sleep 1 +#popd + +pushd lte +./install.sh +sleep 1 +popd + +pushd lora +./install.sh +sleep 1 + +echo_success "*********************************************************" +echo_success "* The RAKwireless gateway is successfully installed! *" +echo_success "*********************************************************" diff --git a/lora/global_conf/i2c/global_conf.as_923.json b/lora/global_conf/i2c/global_conf.as_923.json new file mode 100644 index 0000000..afcae83 --- /dev/null +++ b/lora/global_conf/i2c/global_conf.as_923.json @@ -0,0 +1,225 @@ +{ + "SX1301_conf": { + "lorawan_public": true, + "clksrc": 1, + "clksrc_desc": "radio_1 provides clock to concentrator for most devices except MultiTech. For MultiTech set to 0.", + "antenna_gain": 0, + "antenna_gain_desc": "antenna gain, in dBi", + "radio_0": { + "enable": true, + "type": "SX1257", + "freq": 923600000, + "rssi_offset": -166.0, + "tx_enable": true, + "tx_freq_min": 923200000, + "tx_freq_max": 925000000 + }, + "radio_1": { + "enable": true, + "type": "SX1257", + "freq": 924600000, + "rssi_offset": -166.0, + "tx_enable": false + }, + "chan_multiSF_0": { + "desc": "Lora MAC, 125kHz, all SF, 923.2 MHz", + "enable": true, + "radio": 0, + "if": -400000 + }, + "chan_multiSF_1": { + "desc": "Lora MAC, 125kHz, all SF, 923.4 MHz", + "enable": true, + "radio": 0, + "if": -200000 + }, + "chan_multiSF_2": { + "desc": "Lora MAC, 125kHz, all SF, 923.6 MHz", + "enable": true, + "radio": 0, + "if": 0 + }, + "chan_multiSF_3": { + "desc": "Lora MAC, 125kHz, all SF, 923.8 MHz", + "enable": true, + "radio": 0, + "if": 200000 + }, + "chan_multiSF_4": { + "desc": "Lora MAC, 125kHz, all SF, 924.0 MHz", + "enable": true, + "radio": 0, + "if": 400000 + }, + "chan_multiSF_5": { + "desc": "Lora MAC, 125kHz, all SF, 924.2 MHz", + "enable": true, + "radio": 1, + "if": -400000 + }, + "chan_multiSF_6": { + "desc": "Lora MAC, 125kHz, all SF, 924.4 MHz", + "enable": true, + "radio": 1, + "if": -200000 + }, + "chan_multiSF_7": { + "desc": "Lora MAC, 125kHz, all SF, 924.6 MHz", + "enable": true, + "radio": 1, + "if": 0 + }, + "chan_Lora_std": { + "desc": "Lora MAC, 250kHz, SF7, 924.5 MHz", + "enable": true, + "radio": 1, + "if": -100000, + "bandwidth": 250000, + "spread_factor": 7 + }, + "chan_FSK": { + "desc": "FSK 50kbps, 924.8 MHz", + "enable": true, + "radio": 1, + "if": 200000, + "bandwidth": 125000, + "datarate": 50000 + }, + "tx_lut_0": { + "desc": "TX gain table, index 0", + "pa_gain": 0, + "mix_gain": 8, + "rf_power": -6, + "dig_gain": 0 + }, + "tx_lut_1": { + "desc": "TX gain table, index 1", + "pa_gain": 0, + "mix_gain": 10, + "rf_power": -3, + "dig_gain": 0 + }, + "tx_lut_2": { + "desc": "TX gain table, index 2", + "pa_gain": 0, + "mix_gain": 12, + "rf_power": 0, + "dig_gain": 0 + }, + "tx_lut_3": { + "desc": "TX gain table, index 3", + "pa_gain": 1, + "mix_gain": 8, + "rf_power": 3, + "dig_gain": 0 + }, + "tx_lut_4": { + "desc": "TX gain table, index 4", + "pa_gain": 1, + "mix_gain": 10, + "rf_power": 6, + "dig_gain": 0 + }, + "tx_lut_5": { + "desc": "TX gain table, index 5", + "pa_gain": 1, + "mix_gain": 12, + "rf_power": 10, + "dig_gain": 0 + }, + "tx_lut_6": { + "desc": "TX gain table, index 6", + "pa_gain": 1, + "mix_gain": 13, + "rf_power": 11, + "dig_gain": 0 + }, + "tx_lut_7": { + "desc": "TX gain table, index 7", + "pa_gain": 2, + "mix_gain": 9, + "rf_power": 12, + "dig_gain": 0 + }, + "tx_lut_8": { + "desc": "TX gain table, index 8", + "pa_gain": 1, + "mix_gain": 15, + "rf_power": 13, + "dig_gain": 0 + }, + "tx_lut_9": { + "desc": "TX gain table, index 9", + "pa_gain": 2, + "mix_gain": 10, + "rf_power": 14, + "dig_gain": 0 + }, + "tx_lut_10": { + "desc": "TX gain table, index 10", + "pa_gain": 2, + "mix_gain": 11, + "rf_power": 16, + "dig_gain": 0 + }, + "tx_lut_11": { + "desc": "TX gain table, index 11", + "pa_gain": 3, + "mix_gain": 9, + "rf_power": 20, + "dig_gain": 0 + }, + "tx_lut_12": { + "desc": "TX gain table, index 12", + "pa_gain": 3, + "mix_gain": 10, + "rf_power": 23, + "dig_gain": 0 + }, + "tx_lut_13": { + "desc": "TX gain table, index 13", + "pa_gain": 3, + "mix_gain": 11, + "rf_power": 25, + "dig_gain": 0 + }, + "tx_lut_14": { + "desc": "TX gain table, index 14", + "pa_gain": 3, + "mix_gain": 12, + "rf_power": 26, + "dig_gain": 0 + }, + "tx_lut_15": { + "desc": "TX gain table, index 15", + "pa_gain": 3, + "mix_gain": 14, + "rf_power": 27, + "dig_gain": 0 + } + }, + "gateway_conf": { + "gateway_ID": "0000000000000000", + /* change with default server address/ports, or overwrite in local_conf.json */ + "server_address": "router.as2.thethings.network", + "serv_port_up": 1700, + "serv_port_down": 1700, + /* adjust the following parameters for your network */ + "keepalive_interval": 10, + "stat_interval": 30, + "push_timeout_ms": 100, + /* forward only valid packets */ + "forward_crc_valid": true, + "forward_crc_error": false, + "forward_crc_disabled": false, + /* gps enable */ + "gps": true, + "gps_tty_path": "/dev/i2c-1", + "fake_gps": false, + "ref_latitude": 10, + "ref_longitude": 20, + "ref_altitude": -1, + "autoquit_threshold": 6 + } + +} diff --git a/lora/global_conf/i2c/global_conf.au_915_928.json b/lora/global_conf/i2c/global_conf.au_915_928.json new file mode 100644 index 0000000..55d9c70 --- /dev/null +++ b/lora/global_conf/i2c/global_conf.au_915_928.json @@ -0,0 +1,222 @@ +{ + "SX1301_conf": { + "lorawan_public": true, + "clksrc": 1, + "clksrc_desc": "radio_1 provides clock to concentrator for most devices except MultiTech. For MultiTech set to 0.", + "antenna_gain": 0, + "antenna_gain_desc": "antenna gain, in dBi", + "radio_0": { + "enable": true, + "type": "SX1257", + "freq": 917200000, + "rssi_offset": -166.0, + "tx_enable": true, + "tx_freq_min": 915000000, + "tx_freq_max": 928000000 + }, + "radio_1": { + "enable": true, + "type": "SX1257", + "freq": 917900000, + "rssi_offset": -166.0, + "tx_enable": false + }, + "chan_multiSF_0": { + "desc": "Lora MAC, 125kHz, all SF, 916.8 MHz", + "enable": true, + "radio": 0, + "if": -400000 + }, + "chan_multiSF_1": { + "desc": "Lora MAC, 125kHz, all SF, 917.0 MHz", + "enable": true, + "radio": 0, + "if": -200000 + }, + "chan_multiSF_2": { + "desc": "Lora MAC, 125kHz, all SF, 917.2 MHz", + "enable": true, + "radio": 0, + "if": 0 + }, + "chan_multiSF_3": { + "desc": "Lora MAC, 125kHz, all SF, 917.4 MHz", + "enable": true, + "radio": 0, + "if": 200000 + }, + "chan_multiSF_4": { + "desc": "Lora MAC, 125kHz, all SF, 917.6 MHz", + "enable": true, + "radio": 1, + "if": -300000 + }, + "chan_multiSF_5": { + "desc": "Lora MAC, 125kHz, all SF, 917.8 MHz", + "enable": true, + "radio": 1, + "if": -100000 + }, + "chan_multiSF_6": { + "desc": "Lora MAC, 125kHz, all SF, 918.0 MHz", + "enable": true, + "radio": 1, + "if": 100000 + }, + "chan_multiSF_7": { + "desc": "Lora MAC, 125kHz, all SF, 918.2 MHz", + "enable": true, + "radio": 1, + "if": 300000 + }, + "chan_Lora_std": { + "desc": "Lora MAC, 500kHz, SF8, 917.5 MHz", + "enable": true, + "radio": 0, + "if": 300000, + "bandwidth": 500000, + "spread_factor": 8 + }, + "chan_FSK": { + "desc": "disabled", + "enable": false + }, + "tx_lut_0": { + "desc": "TX gain table, index 0", + "pa_gain": 0, + "mix_gain": 8, + "rf_power": -6, + "dig_gain": 0 + }, + "tx_lut_1": { + "desc": "TX gain table, index 1", + "pa_gain": 0, + "mix_gain": 10, + "rf_power": -3, + "dig_gain": 0 + }, + "tx_lut_2": { + "desc": "TX gain table, index 2", + "pa_gain": 0, + "mix_gain": 12, + "rf_power": 0, + "dig_gain": 0 + }, + "tx_lut_3": { + "desc": "TX gain table, index 3", + "pa_gain": 1, + "mix_gain": 8, + "rf_power": 3, + "dig_gain": 0 + }, + "tx_lut_4": { + "desc": "TX gain table, index 4", + "pa_gain": 1, + "mix_gain": 10, + "rf_power": 6, + "dig_gain": 0 + }, + "tx_lut_5": { + "desc": "TX gain table, index 5", + "pa_gain": 1, + "mix_gain": 12, + "rf_power": 10, + "dig_gain": 0 + }, + "tx_lut_6": { + "desc": "TX gain table, index 6", + "pa_gain": 1, + "mix_gain": 13, + "rf_power": 11, + "dig_gain": 0 + }, + "tx_lut_7": { + "desc": "TX gain table, index 7", + "pa_gain": 2, + "mix_gain": 9, + "rf_power": 12, + "dig_gain": 0 + }, + "tx_lut_8": { + "desc": "TX gain table, index 8", + "pa_gain": 1, + "mix_gain": 15, + "rf_power": 13, + "dig_gain": 0 + }, + "tx_lut_9": { + "desc": "TX gain table, index 9", + "pa_gain": 2, + "mix_gain": 10, + "rf_power": 14, + "dig_gain": 0 + }, + "tx_lut_10": { + "desc": "TX gain table, index 10", + "pa_gain": 2, + "mix_gain": 11, + "rf_power": 16, + "dig_gain": 0 + }, + "tx_lut_11": { + "desc": "TX gain table, index 11", + "pa_gain": 3, + "mix_gain": 9, + "rf_power": 20, + "dig_gain": 0 + }, + "tx_lut_12": { + "desc": "TX gain table, index 12", + "pa_gain": 3, + "mix_gain": 10, + "rf_power": 23, + "dig_gain": 0 + }, + "tx_lut_13": { + "desc": "TX gain table, index 13", + "pa_gain": 3, + "mix_gain": 11, + "rf_power": 25, + "dig_gain": 0 + }, + "tx_lut_14": { + "desc": "TX gain table, index 14", + "pa_gain": 3, + "mix_gain": 12, + "rf_power": 26, + "dig_gain": 0 + }, + "tx_lut_15": { + "desc": "TX gain table, index 15", + "pa_gain": 3, + "mix_gain": 14, + "rf_power": 27, + "dig_gain": 0 + } + }, + "gateway_conf": { + "gateway_ID": "0000000000000000", + /* change with default server address/ports, or overwrite in local_conf.json */ + "server_address": "router.au.thethings.network", + "serv_port_up": 1700, + "serv_port_down": 1700, + /* adjust the following parameters for your network */ + "keepalive_interval": 10, + "stat_interval": 30, + "push_timeout_ms": 100, + /* forward only valid packets */ + "forward_crc_valid": true, + "forward_crc_error": false, + "forward_crc_disabled": false, + /* gps enable */ + "gps": true, + "gps_tty_path": "/dev/i2c-1", + "fake_gps": false, + "ref_latitude": 10, + "ref_longitude": 20, + "ref_altitude": -1, + "autoquit_threshold": 6 + } + +} + diff --git a/lora/global_conf/i2c/global_conf.cn_470_510.json b/lora/global_conf/i2c/global_conf.cn_470_510.json new file mode 100644 index 0000000..7dafb4a --- /dev/null +++ b/lora/global_conf/i2c/global_conf.cn_470_510.json @@ -0,0 +1,217 @@ +{ + "SX1301_conf": { + "lorawan_public": true, + "clksrc": 1, + "clksrc_desc": "radio_1 provides clock to concentrator for most devices except MultiTech. For MultiTech set to 0.", + "antenna_gain": 0, + "antenna_gain_desc": "antenna gain, in dBi", + "radio_0": { + "enable": true, + "type": "SX1255", + "freq": 486600000, + "rssi_offset": -176.0, + "tx_enable": true, + "tx_freq_min": 470000000, + "tx_freq_max": 510000000 + }, + "radio_1": { + "enable": true, + "type": "SX1255", + "freq": 487400000, + "rssi_offset": -176.0, + "tx_enable": false + }, + "chan_multiSF_0": { + "desc": "Lora MAC, 125kHz, all SF, 487.1 MHz", + "enable": true, + "radio": 1, + "if": -300000 + }, + "chan_multiSF_1": { + "desc": "Lora MAC, 125kHz, all SF, 487.3 MHz", + "enable": true, + "radio": 1, + "if": -100000 + }, + "chan_multiSF_2": { + "desc": "Lora MAC, 125kHz, all SF, 487.5 MHz", + "enable": true, + "radio": 1, + "if": 100000 + }, + "chan_multiSF_3": { + "desc": "Lora MAC, 125kHz, all SF, 487.7 MHz", + "enable": true, + "radio": 1, + "if": 300000 + }, + "chan_multiSF_4": { + "desc": "Lora MAC, 125kHz, all SF, 486.3 MHz", + "enable": true, + "radio": 0, + "if": -300000 + }, + "chan_multiSF_5": { + "desc": "Lora MAC, 125kHz, all SF, 486.5 MHz", + "enable": true, + "radio": 0, + "if": -100000 + }, + "chan_multiSF_6": { + "desc": "Lora MAC, 125kHz, all SF, 486.7 MHz", + "enable": true, + "radio": 0, + "if": 100000 + }, + "chan_multiSF_7": { + "desc": "Lora MAC, 125kHz, all SF, 486.9 MHz", + "enable": true, + "radio": 0, + "if": 300000 + }, + "chan_Lora_std": { + "desc": "disabled", + "enable": false + }, + "chan_FSK": { + "desc": "disabled", + "enable": false + }, + "tx_lut_0": { + "desc": "TX gain table, index 0", + "pa_gain": 0, + "mix_gain": 8, + "rf_power": -6, + "dig_gain": 0 + }, + "tx_lut_1": { + "desc": "TX gain table, index 1", + "pa_gain": 0, + "mix_gain": 10, + "rf_power": -3, + "dig_gain": 0 + }, + "tx_lut_2": { + "desc": "TX gain table, index 2", + "pa_gain": 0, + "mix_gain": 12, + "rf_power": 0, + "dig_gain": 0 + }, + "tx_lut_3": { + "desc": "TX gain table, index 3", + "pa_gain": 1, + "mix_gain": 8, + "rf_power": 3, + "dig_gain": 0 + }, + "tx_lut_4": { + "desc": "TX gain table, index 4", + "pa_gain": 1, + "mix_gain": 10, + "rf_power": 6, + "dig_gain": 0 + }, + "tx_lut_5": { + "desc": "TX gain table, index 5", + "pa_gain": 1, + "mix_gain": 12, + "rf_power": 10, + "dig_gain": 0 + }, + "tx_lut_6": { + "desc": "TX gain table, index 6", + "pa_gain": 1, + "mix_gain": 13, + "rf_power": 11, + "dig_gain": 0 + }, + "tx_lut_7": { + "desc": "TX gain table, index 7", + "pa_gain": 2, + "mix_gain": 9, + "rf_power": 12, + "dig_gain": 0 + }, + "tx_lut_8": { + "desc": "TX gain table, index 8", + "pa_gain": 1, + "mix_gain": 15, + "rf_power": 13, + "dig_gain": 0 + }, + "tx_lut_9": { + "desc": "TX gain table, index 9", + "pa_gain": 2, + "mix_gain": 10, + "rf_power": 14, + "dig_gain": 0 + }, + "tx_lut_10": { + "desc": "TX gain table, index 10", + "pa_gain": 2, + "mix_gain": 11, + "rf_power": 16, + "dig_gain": 0 + }, + "tx_lut_11": { + "desc": "TX gain table, index 11", + "pa_gain": 3, + "mix_gain": 9, + "rf_power": 20, + "dig_gain": 0 + }, + "tx_lut_12": { + "desc": "TX gain table, index 12", + "pa_gain": 3, + "mix_gain": 10, + "rf_power": 23, + "dig_gain": 0 + }, + "tx_lut_13": { + "desc": "TX gain table, index 13", + "pa_gain": 3, + "mix_gain": 11, + "rf_power": 25, + "dig_gain": 0 + }, + "tx_lut_14": { + "desc": "TX gain table, index 14", + "pa_gain": 3, + "mix_gain": 12, + "rf_power": 26, + "dig_gain": 0 + }, + "tx_lut_15": { + "desc": "TX gain table, index 15", + "pa_gain": 3, + "mix_gain": 14, + "rf_power": 27, + "dig_gain": 0 + } + }, + "gateway_conf": { + "gateway_ID": "0000000000000000", + /* change with default server address/ports, or overwrite in local_conf.json */ + "server_address": "router.cn.thethings.network", + "serv_port_up": 1700, + "serv_port_down": 1700, + /* adjust the following parameters for your network */ + "keepalive_interval": 10, + "stat_interval": 30, + "push_timeout_ms": 100, + /* forward only valid packets */ + "forward_crc_valid": true, + "forward_crc_error": false, + "forward_crc_disabled": false, + /* gps enable */ + "gps": true, + "gps_tty_path": "/dev/i2c-1", + "fake_gps": false, + "ref_latitude": 10, + "ref_longitude": 20, + "ref_altitude": -1, + "autoquit_threshold": 6 + } +} + diff --git a/lora/global_conf/i2c/global_conf.eu_433.json b/lora/global_conf/i2c/global_conf.eu_433.json new file mode 100644 index 0000000..91238c6 --- /dev/null +++ b/lora/global_conf/i2c/global_conf.eu_433.json @@ -0,0 +1,224 @@ +{ + + "SX1301_conf": { + "lorawan_public": true, + "clksrc": 1, /* radio_1 provides clock to concentrator */ + "antenna_gain": 0, /* antenna gain, in dBi */ + "radio_0": { + "enable": true, + "type": "SX1255", + "freq": 434375000, + "rssi_offset": -166.0, + "tx_enable": true, + "tx_freq_min": 433050000, + "tx_freq_max": 434900000 + }, + "radio_1": { + "enable": true, + "type": "SX1255", + "freq": 433575000, + "rssi_offset": -166.0, + "tx_enable": false + }, + "chan_multiSF_0": { + /* Lora MAC channel, 125kHz, all SF, 433.175 MHz */ + "enable": true, + "radio": 1, + "if": -400000 + }, + "chan_multiSF_1": { + /* Lora MAC channel, 125kHz, all SF, 433.375 MHz */ + "enable": true, + "radio": 1, + "if": -200000 + }, + "chan_multiSF_2": { + /* Lora MAC channel, 125kHz, all SF, 433.575 MHz */ + "enable": true, + "radio": 1, + "if": 0 + }, + "chan_multiSF_3": { + /* Lora MAC channel, 125kHz, all SF, 433.975 MHz */ + "enable": true, + "radio": 0, + "if": -400000 + }, + "chan_multiSF_4": { + /* Lora MAC channel, 125kHz, all SF, 434.175 MHz */ + "enable": true, + "radio": 0, + "if": -200000 + }, + "chan_multiSF_5": { + /* Lora MAC channel, 125kHz, all SF, 434.375 MHz */ + "enable": true, + "radio": 0, + "if": 0 + }, + "chan_multiSF_6": { + /* Lora MAC channel, 125kHz, all SF, 434.575 MHz */ + "enable": true, + "radio": 0, + "if": 200000 + }, + "chan_multiSF_7": { + /* Lora MAC channel, 125kHz, all SF, 434.775 MHz */ + "enable": true, + "radio": 0, + "if": 400000 + }, + "chan_Lora_std": { + /* Lora MAC channel, 250kHz, SF7, 434.175 MHz */ + "enable": true, + "radio": 1, + "if": -200000, + "bandwidth": 250000, + "spread_factor": 7 + }, + "chan_FSK": { + /* FSK 50kbps channel, 434.675 MHz */ + "enable": true, + "radio": 1, + "if": 300000, + "bandwidth": 125000, + "datarate": 50000 + }, + "tx_lut_0": { + /* TX gain table, index 0 */ + "pa_gain": 0, + "mix_gain": 8, + "rf_power": -6, + "dig_gain": 0 + }, + "tx_lut_1": { + /* TX gain table, index 1 */ + "pa_gain": 0, + "mix_gain": 10, + "rf_power": -3, + "dig_gain": 0 + }, + "tx_lut_2": { + /* TX gain table, index 2 */ + "pa_gain": 0, + "mix_gain": 12, + "rf_power": 0, + "dig_gain": 0 + }, + "tx_lut_3": { + /* TX gain table, index 3 */ + "pa_gain": 1, + "mix_gain": 8, + "rf_power": 3, + "dig_gain": 0 + }, + "tx_lut_4": { + /* TX gain table, index 4 */ + "pa_gain": 1, + "mix_gain": 10, + "rf_power": 6, + "dig_gain": 0 + }, + "tx_lut_5": { + /* TX gain table, index 5 */ + "pa_gain": 1, + "mix_gain": 12, + "rf_power": 10, + "dig_gain": 0 + }, + "tx_lut_6": { + /* TX gain table, index 6 */ + "pa_gain": 1, + "mix_gain": 13, + "rf_power": 11, + "dig_gain": 0 + }, + "tx_lut_7": { + /* TX gain table, index 7 */ + "pa_gain": 2, + "mix_gain": 9, + "rf_power": 12, + "dig_gain": 0 + }, + "tx_lut_8": { + /* TX gain table, index 8 */ + "pa_gain": 1, + "mix_gain": 15, + "rf_power": 13, + "dig_gain": 0 + }, + "tx_lut_9": { + /* TX gain table, index 9 */ + "pa_gain": 2, + "mix_gain": 10, + "rf_power": 14, + "dig_gain": 0 + }, + "tx_lut_10": { + /* TX gain table, index 10 */ + "pa_gain": 2, + "mix_gain": 11, + "rf_power": 16, + "dig_gain": 0 + }, + "tx_lut_11": { + /* TX gain table, index 11 */ + "pa_gain": 3, + "mix_gain": 9, + "rf_power": 20, + "dig_gain": 0 + }, + "tx_lut_12": { + "desc": "TX gain table, index 12", + "pa_gain": 3, + "mix_gain": 10, + "rf_power": 23, + "dig_gain": 0 + }, + "tx_lut_13": { + "desc": "TX gain table, index 13", + "pa_gain": 3, + "mix_gain": 11, + "rf_power": 25, + "dig_gain": 0 + }, + "tx_lut_14": { + "desc": "TX gain table, index 14", + "pa_gain": 3, + "mix_gain": 12, + "rf_power": 26, + "dig_gain": 0 + }, + "tx_lut_15": { + "desc": "TX gain table, index 15", + "pa_gain": 3, + "mix_gain": 14, + "rf_power": 27, + "dig_gain": 0 + } + }, + "gateway_conf": { + "gateway_ID": "0000000000000000", + /* change with default server address/ports, or overwrite in local_conf.json */ + "server_address": "router.eu.thethings.network", + "serv_port_up": 1700, + "serv_port_down": 1700, + /* adjust the following parameters for your network */ + "keepalive_interval": 10, + "stat_interval": 30, + "push_timeout_ms": 100, + /* forward only valid packets */ + "forward_crc_valid": true, + "forward_crc_error": false, + "forward_crc_disabled": false, + /* gps enable */ + "gps": true, + "gps_tty_path": "/dev/i2c-1", + "fake_gps": false, + "ref_latitude": 10, + "ref_longitude": 20, + "ref_altitude": -1, + "autoquit_threshold": 6 + } +} + diff --git a/lora/global_conf/i2c/global_conf.eu_863_870.json b/lora/global_conf/i2c/global_conf.eu_863_870.json new file mode 100644 index 0000000..1914d44 --- /dev/null +++ b/lora/global_conf/i2c/global_conf.eu_863_870.json @@ -0,0 +1,200 @@ +{ + "SX1301_conf": { + "lorawan_public": true, + "clksrc": 1, + "antenna_gain": 0, + "radio_0": { + "enable": true, + "type": "SX1257", + "freq": 867500000, + "rssi_offset": -166.0, + "tx_enable": true, + "tx_freq_min": 863000000, + "tx_freq_max": 870000000 + }, + "radio_1": { + "enable": true, + "type": "SX1257", + "freq": 868500000, + "rssi_offset": -166.0, + "tx_enable": false + }, + "chan_multiSF_0": { + "enable": true, + "radio": 1, + "if": -400000 + }, + "chan_multiSF_1": { + "enable": true, + "radio": 1, + "if": -200000 + }, + "chan_multiSF_2": { + "enable": true, + "radio": 1, + "if": 0 + }, + "chan_multiSF_3": { + "enable": true, + "radio": 0, + "if": -400000 + }, + "chan_multiSF_4": { + "enable": true, + "radio": 0, + "if": -200000 + }, + "chan_multiSF_5": { + "enable": true, + "radio": 0, + "if": 0 + }, + "chan_multiSF_6": { + "enable": true, + "radio": 0, + "if": 200000 + }, + "chan_multiSF_7": { + "enable": true, + "radio": 0, + "if": 400000 + }, + "chan_Lora_std": { + "enable": true, + "radio": 1, + "if": -200000, + "bandwidth": 250000, + "spread_factor": 7 + }, + "chan_FSK": { + "enable": true, + "radio": 1, + "if": 300000, + "bandwidth": 125000, + "datarate": 50000 + }, + "tx_lut_0": { + "pa_gain": 0, + "mix_gain": 8, + "rf_power": -6, + "dig_gain": 0 + }, + "tx_lut_1": { + "pa_gain": 0, + "mix_gain": 10, + "rf_power": -3, + "dig_gain": 0 + }, + "tx_lut_2": { + "pa_gain": 0, + "mix_gain": 12, + "rf_power": 0, + "dig_gain": 0 + }, + "tx_lut_3": { + "pa_gain": 1, + "mix_gain": 8, + "rf_power": 3, + "dig_gain": 0 + }, + "tx_lut_4": { + "pa_gain": 1, + "mix_gain": 10, + "rf_power": 6, + "dig_gain": 0 + }, + "tx_lut_5": { + "pa_gain": 1, + "mix_gain": 12, + "rf_power": 10, + "dig_gain": 0 + }, + "tx_lut_6": { + "pa_gain": 1, + "mix_gain": 13, + "rf_power": 11, + "dig_gain": 0 + }, + "tx_lut_7": { + "pa_gain": 2, + "mix_gain": 9, + "rf_power": 12, + "dig_gain": 0 + }, + "tx_lut_8": { + "pa_gain": 1, + "mix_gain": 15, + "rf_power": 13, + "dig_gain": 0 + }, + "tx_lut_9": { + "pa_gain": 2, + "mix_gain": 10, + "rf_power": 14, + "dig_gain": 0 + }, + "tx_lut_10": { + "pa_gain": 2, + "mix_gain": 11, + "rf_power": 16, + "dig_gain": 0 + }, + "tx_lut_11": { + "pa_gain": 3, + "mix_gain": 9, + "rf_power": 20, + "dig_gain": 0 + }, + "tx_lut_12": { + "desc": "TX gain table, index 12", + "pa_gain": 3, + "mix_gain": 10, + "rf_power": 23, + "dig_gain": 0 + }, + "tx_lut_13": { + "desc": "TX gain table, index 13", + "pa_gain": 3, + "mix_gain": 11, + "rf_power": 25, + "dig_gain": 0 + }, + "tx_lut_14": { + "desc": "TX gain table, index 14", + "pa_gain": 3, + "mix_gain": 12, + "rf_power": 26, + "dig_gain": 0 + }, + "tx_lut_15": { + "desc": "TX gain table, index 15", + "pa_gain": 3, + "mix_gain": 14, + "rf_power": 27, + "dig_gain": 0 + } + }, + "gateway_conf": { + "gateway_ID": "0000000000000000", + /* change with default server address/ports, or overwrite in local_conf.json */ + "server_address": "router.eu.thethings.network", + "serv_port_up": 1700, + "serv_port_down": 1700, + /* adjust the following parameters for your network */ + "keepalive_interval": 10, + "stat_interval": 30, + "push_timeout_ms": 100, + /* forward only valid packets */ + "forward_crc_valid": true, + "forward_crc_error": false, + "forward_crc_disabled": false, + /* gps enable */ + "gps": true, + "gps_tty_path": "/dev/i2c-1", + "fake_gps": false, + "ref_latitude": 10, + "ref_longitude": 20, + "ref_altitude": -1, + "autoquit_threshold": 6 + } +} diff --git a/lora/global_conf/i2c/global_conf.in_865_867.json b/lora/global_conf/i2c/global_conf.in_865_867.json new file mode 100644 index 0000000..107afec --- /dev/null +++ b/lora/global_conf/i2c/global_conf.in_865_867.json @@ -0,0 +1,209 @@ +{ + "SX1301_conf": { + "lorawan_public": true, + "clksrc": 1, + "clksrc_desc": "radio_1 provides clock to concentrator for most devices except MultiTech. For MultiTech set to 0.", + "antenna_gain": 0, + "antenna_gain_desc": "antenna gain, in dBi", + "radio_0": { + "enable": true, + "type": "SX1257", + "freq": 865200000, + "rssi_offset": -166.0, + "tx_enable": true, + "tx_freq_min": 865000000, + "tx_freq_max": 867000000, + "tx_notch_freq": 129000 + }, + "radio_1": { + "enable": true, + "type": "SX1257", + "freq": 866385000, + "rssi_offset": -166.0, + "tx_enable": false + }, + "chan_multiSF_0": { + "desc": "Lora MAC, 125kHz, all SF, 865.0625 MHz", + "enable": true, + "radio": 0, + "if": -137500 + }, + "chan_multiSF_1": { + "desc": "Lora MAC, 125kHz, all SF, 865.4025 MHz", + "enable": true, + "radio": 0, + "if": 202500 + }, + "chan_multiSF_2": { + "desc": "Lora MAC, 125kHz, all SF, 865.9850 MHz", + "enable": true, + "radio": 1, + "if": -400000 + }, + "chan_multiSF_3": { + "desc": "disabled", + "enable": false + }, + "chan_multiSF_4": { + "desc": "disabled", + "enable": false + }, + "chan_multiSF_5": { + "desc": "disabled", + "enable": false + }, + "chan_multiSF_6": { + "desc": "disabled", + "enable": false + }, + "chan_multiSF_7": { + "desc": "disabled", + "enable": false + }, + "chan_Lora_std": { + "desc": "disabled", + "enable": false + }, + "chan_FSK": { + "desc": "disabled", + "enable": false + }, + "tx_lut_0": { + "desc": "TX gain table, index 0", + "pa_gain": 0, + "mix_gain": 8, + "rf_power": -6, + "dig_gain": 0 + }, + "tx_lut_1": { + "desc": "TX gain table, index 1", + "pa_gain": 0, + "mix_gain": 10, + "rf_power": -3, + "dig_gain": 0 + }, + "tx_lut_2": { + "desc": "TX gain table, index 2", + "pa_gain": 0, + "mix_gain": 12, + "rf_power": 0, + "dig_gain": 0 + }, + "tx_lut_3": { + "desc": "TX gain table, index 3", + "pa_gain": 1, + "mix_gain": 8, + "rf_power": 3, + "dig_gain": 0 + }, + "tx_lut_4": { + "desc": "TX gain table, index 4", + "pa_gain": 1, + "mix_gain": 10, + "rf_power": 6, + "dig_gain": 0 + }, + "tx_lut_5": { + "desc": "TX gain table, index 5", + "pa_gain": 1, + "mix_gain": 12, + "rf_power": 10, + "dig_gain": 0 + }, + "tx_lut_6": { + "desc": "TX gain table, index 6", + "pa_gain": 1, + "mix_gain": 13, + "rf_power": 11, + "dig_gain": 0 + }, + "tx_lut_7": { + "desc": "TX gain table, index 7", + "pa_gain": 2, + "mix_gain": 9, + "rf_power": 12, + "dig_gain": 0 + }, + "tx_lut_8": { + "desc": "TX gain table, index 8", + "pa_gain": 1, + "mix_gain": 15, + "rf_power": 13, + "dig_gain": 0 + }, + "tx_lut_9": { + "desc": "TX gain table, index 9", + "pa_gain": 2, + "mix_gain": 10, + "rf_power": 14, + "dig_gain": 0 + }, + "tx_lut_10": { + "desc": "TX gain table, index 10", + "pa_gain": 2, + "mix_gain": 11, + "rf_power": 16, + "dig_gain": 0 + }, + "tx_lut_11": { + "desc": "TX gain table, index 11", + "pa_gain": 3, + "mix_gain": 9, + "rf_power": 20, + "dig_gain": 0 + }, + "tx_lut_12": { + "desc": "TX gain table, index 12", + "pa_gain": 3, + "mix_gain": 10, + "rf_power": 23, + "dig_gain": 0 + }, + "tx_lut_13": { + "desc": "TX gain table, index 13", + "pa_gain": 3, + "mix_gain": 11, + "rf_power": 25, + "dig_gain": 0 + }, + "tx_lut_14": { + "desc": "TX gain table, index 14", + "pa_gain": 3, + "mix_gain": 12, + "rf_power": 26, + "dig_gain": 0 + }, + "tx_lut_15": { + "desc": "TX gain table, index 15", + "pa_gain": 3, + "mix_gain": 14, + "rf_power": 27, + "dig_gain": 0 + } + }, + "gateway_conf": { + "gateway_ID": "0000000000000000", + /* change with default server address/ports, or overwrite in local_conf.json */ + "server_address": "router.as.thethings.network", + "serv_port_up": 1700, + "serv_port_down": 1700, + /* adjust the following parameters for your network */ + "keepalive_interval": 10, + "stat_interval": 30, + "push_timeout_ms": 100, + /* forward only valid packets */ + "forward_crc_valid": true, + "forward_crc_error": false, + "forward_crc_disabled": false, + /* gps enable */ + "gps": true, + "gps_tty_path": "/dev/i2c-1", + "fake_gps": false, + "ref_latitude": 10, + "ref_longitude": 20, + "ref_altitude": -1, + "autoquit_threshold": 6 + } + +} + diff --git a/lora/global_conf/i2c/global_conf.kr_920_923.json b/lora/global_conf/i2c/global_conf.kr_920_923.json new file mode 100644 index 0000000..0beae57 --- /dev/null +++ b/lora/global_conf/i2c/global_conf.kr_920_923.json @@ -0,0 +1,217 @@ +{ + "SX1301_conf": { + "lorawan_public": true, + "clksrc": 1, + "clksrc_desc": "radio_1 provides clock to concentrator for most devices except MultiTech. For MultiTech set to 0.", + "antenna_gain": 0, + "antenna_gain_desc": "antenna gain, in dBi", + "radio_0": { + "enable": true, + "type": "SX1257", + "freq": 922400000, + "rssi_offset": -166.0, + "tx_enable": true, + "tx_freq_min": 920900000, + "tx_freq_max": 923300000 + }, + "radio_1": { + "enable": true, + "type": "SX1257", + "freq": 923000000, + "rssi_offset": -166.0, + "tx_enable": false + }, + "chan_multiSF_0": { + "desc": "Lora MAC, 125kHz, all SF, 922.1 MHz", + "enable": true, + "radio": 0, + "if": -300000 + }, + "chan_multiSF_1": { + "desc": "Lora MAC, 125kHz, all SF, 922.3 MHz", + "enable": true, + "radio": 0, + "if": -100000 + }, + "chan_multiSF_2": { + "desc": "Lora MAC, 125kHz, all SF, 922.5 MHz", + "enable": true, + "radio": 0, + "if": 100000 + }, + "chan_multiSF_3": { + "desc": "Lora MAC, 125kHz, all SF, 922.7 MHz", + "enable": true, + "radio": 0, + "if": 300000 + }, + "chan_multiSF_4": { + "desc": "Lora MAC, 125kHz, all SF, 922.9 MHz", + "enable": true, + "radio": 1, + "if": -100000 + }, + "chan_multiSF_5": { + "desc": "Lora MAC, 125kHz, all SF, 923.1 MHz", + "enable": true, + "radio": 1, + "if": 100000 + }, + "chan_multiSF_6": { + "desc": "Lora MAC, 125kHz, all SF, 923.3 MHz", + "enable": true, + "radio": 1, + "if": 300000 + }, + "chan_multiSF_7": { + "desc": "disabled", + "enable": false + }, + "chan_Lora_std": { + "desc": "disabled", + "enable": false + }, + "chan_FSK": { + "desc": "disabled", + "enable": false + }, + "tx_lut_0": { + "desc": "TX gain table, index 0", + "pa_gain": 0, + "mix_gain": 8, + "rf_power": -6, + "dig_gain": 0 + }, + "tx_lut_1": { + "desc": "TX gain table, index 1", + "pa_gain": 0, + "mix_gain": 10, + "rf_power": -3, + "dig_gain": 0 + }, + "tx_lut_2": { + "desc": "TX gain table, index 2", + "pa_gain": 0, + "mix_gain": 12, + "rf_power": 0, + "dig_gain": 0 + }, + "tx_lut_3": { + "desc": "TX gain table, index 3", + "pa_gain": 1, + "mix_gain": 8, + "rf_power": 3, + "dig_gain": 0 + }, + "tx_lut_4": { + "desc": "TX gain table, index 4", + "pa_gain": 1, + "mix_gain": 10, + "rf_power": 6, + "dig_gain": 0 + }, + "tx_lut_5": { + "desc": "TX gain table, index 5", + "pa_gain": 1, + "mix_gain": 12, + "rf_power": 10, + "dig_gain": 0 + }, + "tx_lut_6": { + "desc": "TX gain table, index 6", + "pa_gain": 1, + "mix_gain": 13, + "rf_power": 11, + "dig_gain": 0 + }, + "tx_lut_7": { + "desc": "TX gain table, index 7", + "pa_gain": 2, + "mix_gain": 9, + "rf_power": 12, + "dig_gain": 0 + }, + "tx_lut_8": { + "desc": "TX gain table, index 8", + "pa_gain": 1, + "mix_gain": 15, + "rf_power": 13, + "dig_gain": 0 + }, + "tx_lut_9": { + "desc": "TX gain table, index 9", + "pa_gain": 2, + "mix_gain": 10, + "rf_power": 14, + "dig_gain": 0 + }, + "tx_lut_10": { + "desc": "TX gain table, index 10", + "pa_gain": 2, + "mix_gain": 11, + "rf_power": 16, + "dig_gain": 0 + }, + "tx_lut_11": { + "desc": "TX gain table, index 11", + "pa_gain": 3, + "mix_gain": 9, + "rf_power": 20, + "dig_gain": 0 + }, + "tx_lut_12": { + "desc": "TX gain table, index 12", + "pa_gain": 3, + "mix_gain": 10, + "rf_power": 23, + "dig_gain": 0 + }, + "tx_lut_13": { + "desc": "TX gain table, index 13", + "pa_gain": 3, + "mix_gain": 11, + "rf_power": 25, + "dig_gain": 0 + }, + "tx_lut_14": { + "desc": "TX gain table, index 14", + "pa_gain": 3, + "mix_gain": 12, + "rf_power": 26, + "dig_gain": 0 + }, + "tx_lut_15": { + "desc": "TX gain table, index 15", + "pa_gain": 3, + "mix_gain": 14, + "rf_power": 27, + "dig_gain": 0 + } + }, + "gateway_conf": { + "gateway_ID": "0000000000000000", + /* change with default server address/ports, or overwrite in local_conf.json */ + "server_address": "router.kr.thethings.network", + "serv_port_up": 1700, + "serv_port_down": 1700, + /* adjust the following parameters for your network */ + "keepalive_interval": 10, + "stat_interval": 30, + "push_timeout_ms": 100, + /* forward only valid packets */ + "forward_crc_valid": true, + "forward_crc_error": false, + "forward_crc_disabled": false, + /* gps enable */ + "gps": true, + "gps_tty_path": "/dev/i2c-1", + "fake_gps": false, + "ref_latitude": 10, + "ref_longitude": 20, + "ref_altitude": -1, + "autoquit_threshold": 6 + } + +} + + diff --git a/lora/global_conf/i2c/global_conf.ru_864_870.json b/lora/global_conf/i2c/global_conf.ru_864_870.json new file mode 100644 index 0000000..7f5a957 --- /dev/null +++ b/lora/global_conf/i2c/global_conf.ru_864_870.json @@ -0,0 +1,216 @@ +{ + "SX1301_conf": { + "lorawan_public": true, + "clksrc": 1, + "clksrc_desc": "radio_1 provides clock to concentrator for most devices except MultiTech. For MultiTech set to 0.", + "antenna_gain": 0, + "antenna_gain_desc": "antenna gain, in dBi", + "radio_0": { + "enable": true, + "type": "SX1257", + "freq": 864500000, + "rssi_offset": -166.0, + "tx_enable": true, + "tx_freq_min": 863000000, + "tx_freq_max": 870000000 + }, + "radio_1": { + "enable": true, + "type": "SX1257", + "freq": 869000000, + "rssi_offset": -166.0, + "tx_enable": false + }, + "chan_multiSF_0": { + "desc": "Lora MAC, 125kHz, all SF, 864.1 MHz", + "enable": true, + "radio": 0, + "if": -400000 + }, + "chan_multiSF_1": { + "desc": "Lora MAC, 125kHz, all SF, 864.3 MHz", + "enable": true, + "radio": 0, + "if": -200000 + }, + "chan_multiSF_2": { + "desc": "Lora MAC, 125kHz, all SF, 864.5 MHz", + "enable": true, + "radio": 0, + "if": 0 + }, + "chan_multiSF_3": { + "desc": "Lora MAC, 125kHz, all SF, 864.7 MHz", + "enable": true, + "radio": 0, + "if": 200000 + }, + "chan_multiSF_4": { + "desc": "Lora MAC, 125kHz, all SF, 864.9 MHz", + "enable": true, + "radio": 0, + "if": 400000 + }, + "chan_multiSF_5": { + "desc": "Lora MAC, 125kHz, all SF, 868.9 MHz", + "enable": true, + "radio": 1, + "if": -100000 + }, + "chan_multiSF_6": { + "desc": "Lora MAC, 125kHz, all SF, 869.1 MHz", + "enable": true, + "radio": 1, + "if": 100000 + }, + "chan_multiSF_7": { + "desc": "disabled", + "enable": false + }, + "chan_Lora_std": { + "desc": "disabled", + "enable": false + }, + "chan_FSK": { + "desc": "disabled", + "enable": false + }, + "tx_lut_0": { + "desc": "TX gain table, index 0", + "pa_gain": 0, + "mix_gain": 8, + "rf_power": -6, + "dig_gain": 0 + }, + "tx_lut_1": { + "desc": "TX gain table, index 1", + "pa_gain": 0, + "mix_gain": 10, + "rf_power": -3, + "dig_gain": 0 + }, + "tx_lut_2": { + "desc": "TX gain table, index 2", + "pa_gain": 0, + "mix_gain": 12, + "rf_power": 0, + "dig_gain": 0 + }, + "tx_lut_3": { + "desc": "TX gain table, index 3", + "pa_gain": 1, + "mix_gain": 8, + "rf_power": 3, + "dig_gain": 0 + }, + "tx_lut_4": { + "desc": "TX gain table, index 4", + "pa_gain": 1, + "mix_gain": 10, + "rf_power": 6, + "dig_gain": 0 + }, + "tx_lut_5": { + "desc": "TX gain table, index 5", + "pa_gain": 1, + "mix_gain": 12, + "rf_power": 10, + "dig_gain": 0 + }, + "tx_lut_6": { + "desc": "TX gain table, index 6", + "pa_gain": 1, + "mix_gain": 13, + "rf_power": 11, + "dig_gain": 0 + }, + "tx_lut_7": { + "desc": "TX gain table, index 7", + "pa_gain": 2, + "mix_gain": 9, + "rf_power": 12, + "dig_gain": 0 + }, + "tx_lut_8": { + "desc": "TX gain table, index 8", + "pa_gain": 1, + "mix_gain": 15, + "rf_power": 13, + "dig_gain": 0 + }, + "tx_lut_9": { + "desc": "TX gain table, index 9", + "pa_gain": 2, + "mix_gain": 10, + "rf_power": 14, + "dig_gain": 0 + }, + "tx_lut_10": { + "desc": "TX gain table, index 10", + "pa_gain": 2, + "mix_gain": 11, + "rf_power": 16, + "dig_gain": 0 + }, + "tx_lut_11": { + "desc": "TX gain table, index 11", + "pa_gain": 3, + "mix_gain": 9, + "rf_power": 20, + "dig_gain": 0 + }, + "tx_lut_12": { + "desc": "TX gain table, index 12", + "pa_gain": 3, + "mix_gain": 10, + "rf_power": 23, + "dig_gain": 0 + }, + "tx_lut_13": { + "desc": "TX gain table, index 13", + "pa_gain": 3, + "mix_gain": 11, + "rf_power": 25, + "dig_gain": 0 + }, + "tx_lut_14": { + "desc": "TX gain table, index 14", + "pa_gain": 3, + "mix_gain": 12, + "rf_power": 26, + "dig_gain": 0 + }, + "tx_lut_15": { + "desc": "TX gain table, index 15", + "pa_gain": 3, + "mix_gain": 14, + "rf_power": 27, + "dig_gain": 0 + } + }, + "gateway_conf": { + "gateway_ID": "0000000000000000", + /* change with default server address/ports, or overwrite in local_conf.json */ + "server_address": "router.ru.thethings.network", + "serv_port_up": 1700, + "serv_port_down": 1700, + /* adjust the following parameters for your network */ + "keepalive_interval": 10, + "stat_interval": 30, + "push_timeout_ms": 100, + /* forward only valid packets */ + "forward_crc_valid": true, + "forward_crc_error": false, + "forward_crc_disabled": false, + /* gps enable */ + "gps": true, + "gps_tty_path": "/dev/i2c-1", + "fake_gps": false, + "ref_latitude": 10, + "ref_longitude": 20, + "ref_altitude": -1, + "autoquit_threshold": 6 + } + +} + diff --git a/lora/global_conf/i2c/global_conf.us_902_928.json b/lora/global_conf/i2c/global_conf.us_902_928.json new file mode 100644 index 0000000..9e85858 --- /dev/null +++ b/lora/global_conf/i2c/global_conf.us_902_928.json @@ -0,0 +1,212 @@ +{ + "SX1301_conf": { + "lorawan_public": true, + "clksrc": 1, + "antenna_gain": 0, + "radio_0": { + "enable": true, + "type": "SX1257", + "freq": 904300000, + "rssi_offset": -166.0, + "tx_enable": true, + "tx_freq_min": 902000000, + "tx_freq_max": 928000000 + }, + "radio_1": { + "enable": true, + "type": "SX1257", + "freq": 905000000, + "rssi_offset": -166.0, + "tx_enable": false + }, + "chan_multiSF_0": { + "enable": true, + "radio": 0, + "if": -400000 + }, + "chan_multiSF_1": { + "enable": true, + "radio": 0, + "if": -200000 + }, + "chan_multiSF_2": { + "enable": true, + "radio": 0, + "if": 0 + }, + "chan_multiSF_3": { + "enable": true, + "radio": 0, + "if": 200000 + }, + "chan_multiSF_4": { + "enable": true, + "radio": 1, + "if": -300000 + }, + "chan_multiSF_5": { + "enable": true, + "radio": 1, + "if": -100000 + }, + "chan_multiSF_6": { + "enable": true, + "radio": 1, + "if": 100000 + }, + "chan_multiSF_7": { + "enable": true, + "radio": 1, + "if": 300000 + }, + "chan_Lora_std": { + "enable": true, + "radio": 0, + "if": 300000, + "bandwidth": 500000, + "spread_factor": 8 + }, + "chan_FSK": { + "enable": false, + "radio": 0, + "if": 300000, + "bandwidth": 250000, + "datarate": 100000 + }, + "tx_lut_0": { + "desc": "TX gain table, index 0", + "pa_gain": 0, + "mix_gain": 8, + "rf_power": -6, + "dig_gain": 0 + }, + "tx_lut_1": { + "desc": "TX gain table, index 1", + "pa_gain": 0, + "mix_gain": 10, + "rf_power": -3, + "dig_gain": 0 + }, + "tx_lut_2": { + "desc": "TX gain table, index 2", + "pa_gain": 0, + "mix_gain": 12, + "rf_power": 0, + "dig_gain": 0 + }, + "tx_lut_3": { + "desc": "TX gain table, index 3", + "pa_gain": 1, + "mix_gain": 8, + "rf_power": 3, + "dig_gain": 0 + }, + "tx_lut_4": { + "desc": "TX gain table, index 4", + "pa_gain": 1, + "mix_gain": 10, + "rf_power": 6, + "dig_gain": 0 + }, + "tx_lut_5": { + "desc": "TX gain table, index 5", + "pa_gain": 1, + "mix_gain": 12, + "rf_power": 10, + "dig_gain": 0 + }, + "tx_lut_6": { + "desc": "TX gain table, index 6", + "pa_gain": 1, + "mix_gain": 13, + "rf_power": 11, + "dig_gain": 0 + }, + "tx_lut_7": { + "desc": "TX gain table, index 7", + "pa_gain": 2, + "mix_gain": 9, + "rf_power": 12, + "dig_gain": 0 + }, + "tx_lut_8": { + "desc": "TX gain table, index 8", + "pa_gain": 1, + "mix_gain": 15, + "rf_power": 13, + "dig_gain": 0 + }, + "tx_lut_9": { + "desc": "TX gain table, index 9", + "pa_gain": 2, + "mix_gain": 10, + "rf_power": 14, + "dig_gain": 0 + }, + "tx_lut_10": { + "desc": "TX gain table, index 10", + "pa_gain": 2, + "mix_gain": 11, + "rf_power": 16, + "dig_gain": 0 + }, + "tx_lut_11": { + "desc": "TX gain table, index 11", + "pa_gain": 3, + "mix_gain": 9, + "rf_power": 20, + "dig_gain": 0 + }, + "tx_lut_12": { + "desc": "TX gain table, index 12", + "pa_gain": 3, + "mix_gain": 10, + "rf_power": 23, + "dig_gain": 0 + }, + "tx_lut_13": { + "desc": "TX gain table, index 13", + "pa_gain": 3, + "mix_gain": 11, + "rf_power": 25, + "dig_gain": 0 + }, + "tx_lut_14": { + "desc": "TX gain table, index 14", + "pa_gain": 3, + "mix_gain": 12, + "rf_power": 26, + "dig_gain": 0 + }, + "tx_lut_15": { + "desc": "TX gain table, index 15", + "pa_gain": 3, + "mix_gain": 14, + "rf_power": 27, + "dig_gain": 0 + } + }, + "gateway_conf": { + "gateway_ID": "0000000000000000", + /* change with default server address/ports, or overwrite in local_conf.json */ + "server_address": "router.us.thethings.network", + "serv_port_up": 1700, + "serv_port_down": 1700, + /* adjust the following parameters for your network */ + "keepalive_interval": 10, + "stat_interval": 30, + "push_timeout_ms": 100, + /* forward only valid packets */ + "forward_crc_valid": true, + "forward_crc_error": false, + "forward_crc_disabled": false, + /* gps enable */ + "gps": true, + "gps_tty_path": "/dev/i2c-1", + "fake_gps": false, + "ref_latitude": 10, + "ref_longitude": 20, + "ref_altitude": -1, + "autoquit_threshold": 6 + } +} diff --git a/lora/global_conf/no_gps/global_conf.as_923.json b/lora/global_conf/no_gps/global_conf.as_923.json new file mode 100644 index 0000000..5127049 --- /dev/null +++ b/lora/global_conf/no_gps/global_conf.as_923.json @@ -0,0 +1,218 @@ +{ + "SX1301_conf": { + "lorawan_public": true, + "clksrc": 1, + "clksrc_desc": "radio_1 provides clock to concentrator for most devices except MultiTech. For MultiTech set to 0.", + "antenna_gain": 0, + "antenna_gain_desc": "antenna gain, in dBi", + "radio_0": { + "enable": true, + "type": "SX1257", + "freq": 923600000, + "rssi_offset": -166.0, + "tx_enable": true, + "tx_freq_min": 923200000, + "tx_freq_max": 925000000 + }, + "radio_1": { + "enable": true, + "type": "SX1257", + "freq": 924600000, + "rssi_offset": -166.0, + "tx_enable": false + }, + "chan_multiSF_0": { + "desc": "Lora MAC, 125kHz, all SF, 923.2 MHz", + "enable": true, + "radio": 0, + "if": -400000 + }, + "chan_multiSF_1": { + "desc": "Lora MAC, 125kHz, all SF, 923.4 MHz", + "enable": true, + "radio": 0, + "if": -200000 + }, + "chan_multiSF_2": { + "desc": "Lora MAC, 125kHz, all SF, 923.6 MHz", + "enable": true, + "radio": 0, + "if": 0 + }, + "chan_multiSF_3": { + "desc": "Lora MAC, 125kHz, all SF, 923.8 MHz", + "enable": true, + "radio": 0, + "if": 200000 + }, + "chan_multiSF_4": { + "desc": "Lora MAC, 125kHz, all SF, 924.0 MHz", + "enable": true, + "radio": 0, + "if": 400000 + }, + "chan_multiSF_5": { + "desc": "Lora MAC, 125kHz, all SF, 924.2 MHz", + "enable": true, + "radio": 1, + "if": -400000 + }, + "chan_multiSF_6": { + "desc": "Lora MAC, 125kHz, all SF, 924.4 MHz", + "enable": true, + "radio": 1, + "if": -200000 + }, + "chan_multiSF_7": { + "desc": "Lora MAC, 125kHz, all SF, 924.6 MHz", + "enable": true, + "radio": 1, + "if": 0 + }, + "chan_Lora_std": { + "desc": "Lora MAC, 250kHz, SF7, 924.5 MHz", + "enable": true, + "radio": 1, + "if": -100000, + "bandwidth": 250000, + "spread_factor": 7 + }, + "chan_FSK": { + "desc": "FSK 50kbps, 924.8 MHz", + "enable": true, + "radio": 1, + "if": 200000, + "bandwidth": 125000, + "datarate": 50000 + }, + "tx_lut_0": { + "desc": "TX gain table, index 0", + "pa_gain": 0, + "mix_gain": 8, + "rf_power": -6, + "dig_gain": 0 + }, + "tx_lut_1": { + "desc": "TX gain table, index 1", + "pa_gain": 0, + "mix_gain": 10, + "rf_power": -3, + "dig_gain": 0 + }, + "tx_lut_2": { + "desc": "TX gain table, index 2", + "pa_gain": 0, + "mix_gain": 12, + "rf_power": 0, + "dig_gain": 0 + }, + "tx_lut_3": { + "desc": "TX gain table, index 3", + "pa_gain": 1, + "mix_gain": 8, + "rf_power": 3, + "dig_gain": 0 + }, + "tx_lut_4": { + "desc": "TX gain table, index 4", + "pa_gain": 1, + "mix_gain": 10, + "rf_power": 6, + "dig_gain": 0 + }, + "tx_lut_5": { + "desc": "TX gain table, index 5", + "pa_gain": 1, + "mix_gain": 12, + "rf_power": 10, + "dig_gain": 0 + }, + "tx_lut_6": { + "desc": "TX gain table, index 6", + "pa_gain": 1, + "mix_gain": 13, + "rf_power": 11, + "dig_gain": 0 + }, + "tx_lut_7": { + "desc": "TX gain table, index 7", + "pa_gain": 2, + "mix_gain": 9, + "rf_power": 12, + "dig_gain": 0 + }, + "tx_lut_8": { + "desc": "TX gain table, index 8", + "pa_gain": 1, + "mix_gain": 15, + "rf_power": 13, + "dig_gain": 0 + }, + "tx_lut_9": { + "desc": "TX gain table, index 9", + "pa_gain": 2, + "mix_gain": 10, + "rf_power": 14, + "dig_gain": 0 + }, + "tx_lut_10": { + "desc": "TX gain table, index 10", + "pa_gain": 2, + "mix_gain": 11, + "rf_power": 16, + "dig_gain": 0 + }, + "tx_lut_11": { + "desc": "TX gain table, index 11", + "pa_gain": 3, + "mix_gain": 9, + "rf_power": 20, + "dig_gain": 0 + }, + "tx_lut_12": { + "desc": "TX gain table, index 12", + "pa_gain": 3, + "mix_gain": 10, + "rf_power": 23, + "dig_gain": 0 + }, + "tx_lut_13": { + "desc": "TX gain table, index 13", + "pa_gain": 3, + "mix_gain": 11, + "rf_power": 25, + "dig_gain": 0 + }, + "tx_lut_14": { + "desc": "TX gain table, index 14", + "pa_gain": 3, + "mix_gain": 12, + "rf_power": 26, + "dig_gain": 0 + }, + "tx_lut_15": { + "desc": "TX gain table, index 15", + "pa_gain": 3, + "mix_gain": 14, + "rf_power": 27, + "dig_gain": 0 + } + }, + "gateway_conf": { + "gateway_ID": "0000000000000000", + /* change with default server address/ports, or overwrite in local_conf.json */ + "server_address": "router.as2.thethings.network", + "serv_port_up": 1700, + "serv_port_down": 1700, + /* adjust the following parameters for your network */ + "keepalive_interval": 10, + "stat_interval": 30, + "push_timeout_ms": 100, + /* forward only valid packets */ + "forward_crc_valid": true, + "forward_crc_error": false, + "forward_crc_disabled": false, + "autoquit_threshold": 6 + } + +} diff --git a/lora/global_conf/no_gps/global_conf.au_915_928.json b/lora/global_conf/no_gps/global_conf.au_915_928.json new file mode 100644 index 0000000..e3764fd --- /dev/null +++ b/lora/global_conf/no_gps/global_conf.au_915_928.json @@ -0,0 +1,215 @@ +{ + "SX1301_conf": { + "lorawan_public": true, + "clksrc": 1, + "clksrc_desc": "radio_1 provides clock to concentrator for most devices except MultiTech. For MultiTech set to 0.", + "antenna_gain": 0, + "antenna_gain_desc": "antenna gain, in dBi", + "radio_0": { + "enable": true, + "type": "SX1257", + "freq": 917200000, + "rssi_offset": -166.0, + "tx_enable": true, + "tx_freq_min": 915000000, + "tx_freq_max": 928000000 + }, + "radio_1": { + "enable": true, + "type": "SX1257", + "freq": 917900000, + "rssi_offset": -166.0, + "tx_enable": false + }, + "chan_multiSF_0": { + "desc": "Lora MAC, 125kHz, all SF, 916.8 MHz", + "enable": true, + "radio": 0, + "if": -400000 + }, + "chan_multiSF_1": { + "desc": "Lora MAC, 125kHz, all SF, 917.0 MHz", + "enable": true, + "radio": 0, + "if": -200000 + }, + "chan_multiSF_2": { + "desc": "Lora MAC, 125kHz, all SF, 917.2 MHz", + "enable": true, + "radio": 0, + "if": 0 + }, + "chan_multiSF_3": { + "desc": "Lora MAC, 125kHz, all SF, 917.4 MHz", + "enable": true, + "radio": 0, + "if": 200000 + }, + "chan_multiSF_4": { + "desc": "Lora MAC, 125kHz, all SF, 917.6 MHz", + "enable": true, + "radio": 1, + "if": -300000 + }, + "chan_multiSF_5": { + "desc": "Lora MAC, 125kHz, all SF, 917.8 MHz", + "enable": true, + "radio": 1, + "if": -100000 + }, + "chan_multiSF_6": { + "desc": "Lora MAC, 125kHz, all SF, 918.0 MHz", + "enable": true, + "radio": 1, + "if": 100000 + }, + "chan_multiSF_7": { + "desc": "Lora MAC, 125kHz, all SF, 918.2 MHz", + "enable": true, + "radio": 1, + "if": 300000 + }, + "chan_Lora_std": { + "desc": "Lora MAC, 500kHz, SF8, 917.5 MHz", + "enable": true, + "radio": 0, + "if": 300000, + "bandwidth": 500000, + "spread_factor": 8 + }, + "chan_FSK": { + "desc": "disabled", + "enable": false + }, + "tx_lut_0": { + "desc": "TX gain table, index 0", + "pa_gain": 0, + "mix_gain": 8, + "rf_power": -6, + "dig_gain": 0 + }, + "tx_lut_1": { + "desc": "TX gain table, index 1", + "pa_gain": 0, + "mix_gain": 10, + "rf_power": -3, + "dig_gain": 0 + }, + "tx_lut_2": { + "desc": "TX gain table, index 2", + "pa_gain": 0, + "mix_gain": 12, + "rf_power": 0, + "dig_gain": 0 + }, + "tx_lut_3": { + "desc": "TX gain table, index 3", + "pa_gain": 1, + "mix_gain": 8, + "rf_power": 3, + "dig_gain": 0 + }, + "tx_lut_4": { + "desc": "TX gain table, index 4", + "pa_gain": 1, + "mix_gain": 10, + "rf_power": 6, + "dig_gain": 0 + }, + "tx_lut_5": { + "desc": "TX gain table, index 5", + "pa_gain": 1, + "mix_gain": 12, + "rf_power": 10, + "dig_gain": 0 + }, + "tx_lut_6": { + "desc": "TX gain table, index 6", + "pa_gain": 1, + "mix_gain": 13, + "rf_power": 11, + "dig_gain": 0 + }, + "tx_lut_7": { + "desc": "TX gain table, index 7", + "pa_gain": 2, + "mix_gain": 9, + "rf_power": 12, + "dig_gain": 0 + }, + "tx_lut_8": { + "desc": "TX gain table, index 8", + "pa_gain": 1, + "mix_gain": 15, + "rf_power": 13, + "dig_gain": 0 + }, + "tx_lut_9": { + "desc": "TX gain table, index 9", + "pa_gain": 2, + "mix_gain": 10, + "rf_power": 14, + "dig_gain": 0 + }, + "tx_lut_10": { + "desc": "TX gain table, index 10", + "pa_gain": 2, + "mix_gain": 11, + "rf_power": 16, + "dig_gain": 0 + }, + "tx_lut_11": { + "desc": "TX gain table, index 11", + "pa_gain": 3, + "mix_gain": 9, + "rf_power": 20, + "dig_gain": 0 + }, + "tx_lut_12": { + "desc": "TX gain table, index 12", + "pa_gain": 3, + "mix_gain": 10, + "rf_power": 23, + "dig_gain": 0 + }, + "tx_lut_13": { + "desc": "TX gain table, index 13", + "pa_gain": 3, + "mix_gain": 11, + "rf_power": 25, + "dig_gain": 0 + }, + "tx_lut_14": { + "desc": "TX gain table, index 14", + "pa_gain": 3, + "mix_gain": 12, + "rf_power": 26, + "dig_gain": 0 + }, + "tx_lut_15": { + "desc": "TX gain table, index 15", + "pa_gain": 3, + "mix_gain": 14, + "rf_power": 27, + "dig_gain": 0 + } + }, + "gateway_conf": { + "gateway_ID": "0000000000000000", + /* change with default server address/ports, or overwrite in local_conf.json */ + "server_address": "router.au.thethings.network", + "serv_port_up": 1700, + "serv_port_down": 1700, + /* adjust the following parameters for your network */ + "keepalive_interval": 10, + "stat_interval": 30, + "push_timeout_ms": 100, + /* forward only valid packets */ + "forward_crc_valid": true, + "forward_crc_error": false, + "forward_crc_disabled": false, + "autoquit_threshold": 6 + } + +} + diff --git a/lora/global_conf/no_gps/global_conf.cn_470_510.json b/lora/global_conf/no_gps/global_conf.cn_470_510.json new file mode 100644 index 0000000..222e020 --- /dev/null +++ b/lora/global_conf/no_gps/global_conf.cn_470_510.json @@ -0,0 +1,210 @@ +{ + "SX1301_conf": { + "lorawan_public": true, + "clksrc": 1, + "clksrc_desc": "radio_1 provides clock to concentrator for most devices except MultiTech. For MultiTech set to 0.", + "antenna_gain": 0, + "antenna_gain_desc": "antenna gain, in dBi", + "radio_0": { + "enable": true, + "type": "SX1255", + "freq": 486600000, + "rssi_offset": -176.0, + "tx_enable": true, + "tx_freq_min": 470000000, + "tx_freq_max": 510000000 + }, + "radio_1": { + "enable": true, + "type": "SX1255", + "freq": 487400000, + "rssi_offset": -176.0, + "tx_enable": false + }, + "chan_multiSF_0": { + "desc": "Lora MAC, 125kHz, all SF, 487.1 MHz", + "enable": true, + "radio": 1, + "if": -300000 + }, + "chan_multiSF_1": { + "desc": "Lora MAC, 125kHz, all SF, 487.3 MHz", + "enable": true, + "radio": 1, + "if": -100000 + }, + "chan_multiSF_2": { + "desc": "Lora MAC, 125kHz, all SF, 487.5 MHz", + "enable": true, + "radio": 1, + "if": 100000 + }, + "chan_multiSF_3": { + "desc": "Lora MAC, 125kHz, all SF, 487.7 MHz", + "enable": true, + "radio": 1, + "if": 300000 + }, + "chan_multiSF_4": { + "desc": "Lora MAC, 125kHz, all SF, 486.3 MHz", + "enable": true, + "radio": 0, + "if": -300000 + }, + "chan_multiSF_5": { + "desc": "Lora MAC, 125kHz, all SF, 486.5 MHz", + "enable": true, + "radio": 0, + "if": -100000 + }, + "chan_multiSF_6": { + "desc": "Lora MAC, 125kHz, all SF, 486.7 MHz", + "enable": true, + "radio": 0, + "if": 100000 + }, + "chan_multiSF_7": { + "desc": "Lora MAC, 125kHz, all SF, 486.9 MHz", + "enable": true, + "radio": 0, + "if": 300000 + }, + "chan_Lora_std": { + "desc": "disabled", + "enable": false + }, + "chan_FSK": { + "desc": "disabled", + "enable": false + }, + "tx_lut_0": { + "desc": "TX gain table, index 0", + "pa_gain": 0, + "mix_gain": 8, + "rf_power": -6, + "dig_gain": 0 + }, + "tx_lut_1": { + "desc": "TX gain table, index 1", + "pa_gain": 0, + "mix_gain": 10, + "rf_power": -3, + "dig_gain": 0 + }, + "tx_lut_2": { + "desc": "TX gain table, index 2", + "pa_gain": 0, + "mix_gain": 12, + "rf_power": 0, + "dig_gain": 0 + }, + "tx_lut_3": { + "desc": "TX gain table, index 3", + "pa_gain": 1, + "mix_gain": 8, + "rf_power": 3, + "dig_gain": 0 + }, + "tx_lut_4": { + "desc": "TX gain table, index 4", + "pa_gain": 1, + "mix_gain": 10, + "rf_power": 6, + "dig_gain": 0 + }, + "tx_lut_5": { + "desc": "TX gain table, index 5", + "pa_gain": 1, + "mix_gain": 12, + "rf_power": 10, + "dig_gain": 0 + }, + "tx_lut_6": { + "desc": "TX gain table, index 6", + "pa_gain": 1, + "mix_gain": 13, + "rf_power": 11, + "dig_gain": 0 + }, + "tx_lut_7": { + "desc": "TX gain table, index 7", + "pa_gain": 2, + "mix_gain": 9, + "rf_power": 12, + "dig_gain": 0 + }, + "tx_lut_8": { + "desc": "TX gain table, index 8", + "pa_gain": 1, + "mix_gain": 15, + "rf_power": 13, + "dig_gain": 0 + }, + "tx_lut_9": { + "desc": "TX gain table, index 9", + "pa_gain": 2, + "mix_gain": 10, + "rf_power": 14, + "dig_gain": 0 + }, + "tx_lut_10": { + "desc": "TX gain table, index 10", + "pa_gain": 2, + "mix_gain": 11, + "rf_power": 16, + "dig_gain": 0 + }, + "tx_lut_11": { + "desc": "TX gain table, index 11", + "pa_gain": 3, + "mix_gain": 9, + "rf_power": 20, + "dig_gain": 0 + }, + "tx_lut_12": { + "desc": "TX gain table, index 12", + "pa_gain": 3, + "mix_gain": 10, + "rf_power": 23, + "dig_gain": 0 + }, + "tx_lut_13": { + "desc": "TX gain table, index 13", + "pa_gain": 3, + "mix_gain": 11, + "rf_power": 25, + "dig_gain": 0 + }, + "tx_lut_14": { + "desc": "TX gain table, index 14", + "pa_gain": 3, + "mix_gain": 12, + "rf_power": 26, + "dig_gain": 0 + }, + "tx_lut_15": { + "desc": "TX gain table, index 15", + "pa_gain": 3, + "mix_gain": 14, + "rf_power": 27, + "dig_gain": 0 + } + }, + "gateway_conf": { + "gateway_ID": "0000000000000000", + /* change with default server address/ports, or overwrite in local_conf.json */ + "server_address": "router.cn.thethings.network", + "serv_port_up": 1700, + "serv_port_down": 1700, + /* adjust the following parameters for your network */ + "keepalive_interval": 10, + "stat_interval": 30, + "push_timeout_ms": 100, + /* forward only valid packets */ + "forward_crc_valid": true, + "forward_crc_error": false, + "forward_crc_disabled": false, + "autoquit_threshold": 6 + } +} + diff --git a/lora/global_conf/no_gps/global_conf.eu_433.json b/lora/global_conf/no_gps/global_conf.eu_433.json new file mode 100644 index 0000000..8fbf0e9 --- /dev/null +++ b/lora/global_conf/no_gps/global_conf.eu_433.json @@ -0,0 +1,217 @@ +{ + + "SX1301_conf": { + "lorawan_public": true, + "clksrc": 1, /* radio_1 provides clock to concentrator */ + "antenna_gain": 0, /* antenna gain, in dBi */ + "radio_0": { + "enable": true, + "type": "SX1255", + "freq": 434375000, + "rssi_offset": -166.0, + "tx_enable": true, + "tx_freq_min": 433050000, + "tx_freq_max": 434900000 + }, + "radio_1": { + "enable": true, + "type": "SX1255", + "freq": 433575000, + "rssi_offset": -166.0, + "tx_enable": false + }, + "chan_multiSF_0": { + /* Lora MAC channel, 125kHz, all SF, 433.175 MHz */ + "enable": true, + "radio": 1, + "if": -400000 + }, + "chan_multiSF_1": { + /* Lora MAC channel, 125kHz, all SF, 433.375 MHz */ + "enable": true, + "radio": 1, + "if": -200000 + }, + "chan_multiSF_2": { + /* Lora MAC channel, 125kHz, all SF, 433.575 MHz */ + "enable": true, + "radio": 1, + "if": 0 + }, + "chan_multiSF_3": { + /* Lora MAC channel, 125kHz, all SF, 433.975 MHz */ + "enable": true, + "radio": 0, + "if": -400000 + }, + "chan_multiSF_4": { + /* Lora MAC channel, 125kHz, all SF, 434.175 MHz */ + "enable": true, + "radio": 0, + "if": -200000 + }, + "chan_multiSF_5": { + /* Lora MAC channel, 125kHz, all SF, 434.375 MHz */ + "enable": true, + "radio": 0, + "if": 0 + }, + "chan_multiSF_6": { + /* Lora MAC channel, 125kHz, all SF, 434.575 MHz */ + "enable": true, + "radio": 0, + "if": 200000 + }, + "chan_multiSF_7": { + /* Lora MAC channel, 125kHz, all SF, 434.775 MHz */ + "enable": true, + "radio": 0, + "if": 400000 + }, + "chan_Lora_std": { + /* Lora MAC channel, 250kHz, SF7, 434.175 MHz */ + "enable": true, + "radio": 1, + "if": -200000, + "bandwidth": 250000, + "spread_factor": 7 + }, + "chan_FSK": { + /* FSK 50kbps channel, 434.675 MHz */ + "enable": true, + "radio": 1, + "if": 300000, + "bandwidth": 125000, + "datarate": 50000 + }, + "tx_lut_0": { + /* TX gain table, index 0 */ + "pa_gain": 0, + "mix_gain": 8, + "rf_power": -6, + "dig_gain": 0 + }, + "tx_lut_1": { + /* TX gain table, index 1 */ + "pa_gain": 0, + "mix_gain": 10, + "rf_power": -3, + "dig_gain": 0 + }, + "tx_lut_2": { + /* TX gain table, index 2 */ + "pa_gain": 0, + "mix_gain": 12, + "rf_power": 0, + "dig_gain": 0 + }, + "tx_lut_3": { + /* TX gain table, index 3 */ + "pa_gain": 1, + "mix_gain": 8, + "rf_power": 3, + "dig_gain": 0 + }, + "tx_lut_4": { + /* TX gain table, index 4 */ + "pa_gain": 1, + "mix_gain": 10, + "rf_power": 6, + "dig_gain": 0 + }, + "tx_lut_5": { + /* TX gain table, index 5 */ + "pa_gain": 1, + "mix_gain": 12, + "rf_power": 10, + "dig_gain": 0 + }, + "tx_lut_6": { + /* TX gain table, index 6 */ + "pa_gain": 1, + "mix_gain": 13, + "rf_power": 11, + "dig_gain": 0 + }, + "tx_lut_7": { + /* TX gain table, index 7 */ + "pa_gain": 2, + "mix_gain": 9, + "rf_power": 12, + "dig_gain": 0 + }, + "tx_lut_8": { + /* TX gain table, index 8 */ + "pa_gain": 1, + "mix_gain": 15, + "rf_power": 13, + "dig_gain": 0 + }, + "tx_lut_9": { + /* TX gain table, index 9 */ + "pa_gain": 2, + "mix_gain": 10, + "rf_power": 14, + "dig_gain": 0 + }, + "tx_lut_10": { + /* TX gain table, index 10 */ + "pa_gain": 2, + "mix_gain": 11, + "rf_power": 16, + "dig_gain": 0 + }, + "tx_lut_11": { + /* TX gain table, index 11 */ + "pa_gain": 3, + "mix_gain": 9, + "rf_power": 20, + "dig_gain": 0 + }, + "tx_lut_12": { + "desc": "TX gain table, index 12", + "pa_gain": 3, + "mix_gain": 10, + "rf_power": 23, + "dig_gain": 0 + }, + "tx_lut_13": { + "desc": "TX gain table, index 13", + "pa_gain": 3, + "mix_gain": 11, + "rf_power": 25, + "dig_gain": 0 + }, + "tx_lut_14": { + "desc": "TX gain table, index 14", + "pa_gain": 3, + "mix_gain": 12, + "rf_power": 26, + "dig_gain": 0 + }, + "tx_lut_15": { + "desc": "TX gain table, index 15", + "pa_gain": 3, + "mix_gain": 14, + "rf_power": 27, + "dig_gain": 0 + } + }, + "gateway_conf": { + "gateway_ID": "0000000000000000", + /* change with default server address/ports, or overwrite in local_conf.json */ + "server_address": "localhost", + "serv_port_up": 1700, + "serv_port_down": 1700, + /* adjust the following parameters for your network */ + "keepalive_interval": 10, + "stat_interval": 30, + "push_timeout_ms": 100, + /* forward only valid packets */ + "forward_crc_valid": true, + "forward_crc_error": false, + "forward_crc_disabled": false, + "autoquit_threshold": 6 + } +} + diff --git a/lora/global_conf/no_gps/global_conf.eu_863_870.json b/lora/global_conf/no_gps/global_conf.eu_863_870.json new file mode 100644 index 0000000..3cfd8a7 --- /dev/null +++ b/lora/global_conf/no_gps/global_conf.eu_863_870.json @@ -0,0 +1,193 @@ +{ + "SX1301_conf": { + "lorawan_public": true, + "clksrc": 1, + "antenna_gain": 0, + "radio_0": { + "enable": true, + "type": "SX1257", + "freq": 867500000, + "rssi_offset": -166.0, + "tx_enable": true, + "tx_freq_min": 863000000, + "tx_freq_max": 870000000 + }, + "radio_1": { + "enable": true, + "type": "SX1257", + "freq": 868500000, + "rssi_offset": -166.0, + "tx_enable": false + }, + "chan_multiSF_0": { + "enable": true, + "radio": 1, + "if": -400000 + }, + "chan_multiSF_1": { + "enable": true, + "radio": 1, + "if": -200000 + }, + "chan_multiSF_2": { + "enable": true, + "radio": 1, + "if": 0 + }, + "chan_multiSF_3": { + "enable": true, + "radio": 0, + "if": -400000 + }, + "chan_multiSF_4": { + "enable": true, + "radio": 0, + "if": -200000 + }, + "chan_multiSF_5": { + "enable": true, + "radio": 0, + "if": 0 + }, + "chan_multiSF_6": { + "enable": true, + "radio": 0, + "if": 200000 + }, + "chan_multiSF_7": { + "enable": true, + "radio": 0, + "if": 400000 + }, + "chan_Lora_std": { + "enable": true, + "radio": 1, + "if": -200000, + "bandwidth": 250000, + "spread_factor": 7 + }, + "chan_FSK": { + "enable": true, + "radio": 1, + "if": 300000, + "bandwidth": 125000, + "datarate": 50000 + }, + "tx_lut_0": { + "pa_gain": 0, + "mix_gain": 8, + "rf_power": -6, + "dig_gain": 0 + }, + "tx_lut_1": { + "pa_gain": 0, + "mix_gain": 10, + "rf_power": -3, + "dig_gain": 0 + }, + "tx_lut_2": { + "pa_gain": 0, + "mix_gain": 12, + "rf_power": 0, + "dig_gain": 0 + }, + "tx_lut_3": { + "pa_gain": 1, + "mix_gain": 8, + "rf_power": 3, + "dig_gain": 0 + }, + "tx_lut_4": { + "pa_gain": 1, + "mix_gain": 10, + "rf_power": 6, + "dig_gain": 0 + }, + "tx_lut_5": { + "pa_gain": 1, + "mix_gain": 12, + "rf_power": 10, + "dig_gain": 0 + }, + "tx_lut_6": { + "pa_gain": 1, + "mix_gain": 13, + "rf_power": 11, + "dig_gain": 0 + }, + "tx_lut_7": { + "pa_gain": 2, + "mix_gain": 9, + "rf_power": 12, + "dig_gain": 0 + }, + "tx_lut_8": { + "pa_gain": 1, + "mix_gain": 15, + "rf_power": 13, + "dig_gain": 0 + }, + "tx_lut_9": { + "pa_gain": 2, + "mix_gain": 10, + "rf_power": 14, + "dig_gain": 0 + }, + "tx_lut_10": { + "pa_gain": 2, + "mix_gain": 11, + "rf_power": 16, + "dig_gain": 0 + }, + "tx_lut_11": { + "pa_gain": 3, + "mix_gain": 9, + "rf_power": 20, + "dig_gain": 0 + }, + "tx_lut_12": { + "desc": "TX gain table, index 12", + "pa_gain": 3, + "mix_gain": 10, + "rf_power": 23, + "dig_gain": 0 + }, + "tx_lut_13": { + "desc": "TX gain table, index 13", + "pa_gain": 3, + "mix_gain": 11, + "rf_power": 25, + "dig_gain": 0 + }, + "tx_lut_14": { + "desc": "TX gain table, index 14", + "pa_gain": 3, + "mix_gain": 12, + "rf_power": 26, + "dig_gain": 0 + }, + "tx_lut_15": { + "desc": "TX gain table, index 15", + "pa_gain": 3, + "mix_gain": 14, + "rf_power": 27, + "dig_gain": 0 + } + }, + "gateway_conf": { + "gateway_ID": "0000000000000000", + /* change with default server address/ports, or overwrite in local_conf.json */ + "server_address": "router.eu.thethings.network", + "serv_port_up": 1700, + "serv_port_down": 1700, + /* adjust the following parameters for your network */ + "keepalive_interval": 10, + "stat_interval": 30, + "push_timeout_ms": 100, + /* forward only valid packets */ + "forward_crc_valid": true, + "forward_crc_error": false, + "forward_crc_disabled": false, + "autoquit_threshold": 6 + } +} diff --git a/lora/global_conf/no_gps/global_conf.in_865_867.json b/lora/global_conf/no_gps/global_conf.in_865_867.json new file mode 100644 index 0000000..f024127 --- /dev/null +++ b/lora/global_conf/no_gps/global_conf.in_865_867.json @@ -0,0 +1,202 @@ +{ + "SX1301_conf": { + "lorawan_public": true, + "clksrc": 1, + "clksrc_desc": "radio_1 provides clock to concentrator for most devices except MultiTech. For MultiTech set to 0.", + "antenna_gain": 0, + "antenna_gain_desc": "antenna gain, in dBi", + "radio_0": { + "enable": true, + "type": "SX1257", + "freq": 865200000, + "rssi_offset": -166.0, + "tx_enable": true, + "tx_freq_min": 865000000, + "tx_freq_max": 867000000, + "tx_notch_freq": 129000 + }, + "radio_1": { + "enable": true, + "type": "SX1257", + "freq": 866385000, + "rssi_offset": -166.0, + "tx_enable": false + }, + "chan_multiSF_0": { + "desc": "Lora MAC, 125kHz, all SF, 865.0625 MHz", + "enable": true, + "radio": 0, + "if": -137500 + }, + "chan_multiSF_1": { + "desc": "Lora MAC, 125kHz, all SF, 865.4025 MHz", + "enable": true, + "radio": 0, + "if": 202500 + }, + "chan_multiSF_2": { + "desc": "Lora MAC, 125kHz, all SF, 865.9850 MHz", + "enable": true, + "radio": 1, + "if": -400000 + }, + "chan_multiSF_3": { + "desc": "disabled", + "enable": false + }, + "chan_multiSF_4": { + "desc": "disabled", + "enable": false + }, + "chan_multiSF_5": { + "desc": "disabled", + "enable": false + }, + "chan_multiSF_6": { + "desc": "disabled", + "enable": false + }, + "chan_multiSF_7": { + "desc": "disabled", + "enable": false + }, + "chan_Lora_std": { + "desc": "disabled", + "enable": false + }, + "chan_FSK": { + "desc": "disabled", + "enable": false + }, + "tx_lut_0": { + "desc": "TX gain table, index 0", + "pa_gain": 0, + "mix_gain": 8, + "rf_power": -6, + "dig_gain": 0 + }, + "tx_lut_1": { + "desc": "TX gain table, index 1", + "pa_gain": 0, + "mix_gain": 10, + "rf_power": -3, + "dig_gain": 0 + }, + "tx_lut_2": { + "desc": "TX gain table, index 2", + "pa_gain": 0, + "mix_gain": 12, + "rf_power": 0, + "dig_gain": 0 + }, + "tx_lut_3": { + "desc": "TX gain table, index 3", + "pa_gain": 1, + "mix_gain": 8, + "rf_power": 3, + "dig_gain": 0 + }, + "tx_lut_4": { + "desc": "TX gain table, index 4", + "pa_gain": 1, + "mix_gain": 10, + "rf_power": 6, + "dig_gain": 0 + }, + "tx_lut_5": { + "desc": "TX gain table, index 5", + "pa_gain": 1, + "mix_gain": 12, + "rf_power": 10, + "dig_gain": 0 + }, + "tx_lut_6": { + "desc": "TX gain table, index 6", + "pa_gain": 1, + "mix_gain": 13, + "rf_power": 11, + "dig_gain": 0 + }, + "tx_lut_7": { + "desc": "TX gain table, index 7", + "pa_gain": 2, + "mix_gain": 9, + "rf_power": 12, + "dig_gain": 0 + }, + "tx_lut_8": { + "desc": "TX gain table, index 8", + "pa_gain": 1, + "mix_gain": 15, + "rf_power": 13, + "dig_gain": 0 + }, + "tx_lut_9": { + "desc": "TX gain table, index 9", + "pa_gain": 2, + "mix_gain": 10, + "rf_power": 14, + "dig_gain": 0 + }, + "tx_lut_10": { + "desc": "TX gain table, index 10", + "pa_gain": 2, + "mix_gain": 11, + "rf_power": 16, + "dig_gain": 0 + }, + "tx_lut_11": { + "desc": "TX gain table, index 11", + "pa_gain": 3, + "mix_gain": 9, + "rf_power": 20, + "dig_gain": 0 + }, + "tx_lut_12": { + "desc": "TX gain table, index 12", + "pa_gain": 3, + "mix_gain": 10, + "rf_power": 23, + "dig_gain": 0 + }, + "tx_lut_13": { + "desc": "TX gain table, index 13", + "pa_gain": 3, + "mix_gain": 11, + "rf_power": 25, + "dig_gain": 0 + }, + "tx_lut_14": { + "desc": "TX gain table, index 14", + "pa_gain": 3, + "mix_gain": 12, + "rf_power": 26, + "dig_gain": 0 + }, + "tx_lut_15": { + "desc": "TX gain table, index 15", + "pa_gain": 3, + "mix_gain": 14, + "rf_power": 27, + "dig_gain": 0 + } + }, + "gateway_conf": { + "gateway_ID": "0000000000000000", + /* change with default server address/ports, or overwrite in local_conf.json */ + "server_address": "router.as.thethings.network", + "serv_port_up": 1700, + "serv_port_down": 1700, + /* adjust the following parameters for your network */ + "keepalive_interval": 10, + "stat_interval": 30, + "push_timeout_ms": 100, + /* forward only valid packets */ + "forward_crc_valid": true, + "forward_crc_error": false, + "forward_crc_disabled": false, + "autoquit_threshold": 6 + } + +} + diff --git a/lora/global_conf/no_gps/global_conf.kr_920_923.json b/lora/global_conf/no_gps/global_conf.kr_920_923.json new file mode 100644 index 0000000..0fcb6e5 --- /dev/null +++ b/lora/global_conf/no_gps/global_conf.kr_920_923.json @@ -0,0 +1,210 @@ +{ + "SX1301_conf": { + "lorawan_public": true, + "clksrc": 1, + "clksrc_desc": "radio_1 provides clock to concentrator for most devices except MultiTech. For MultiTech set to 0.", + "antenna_gain": 0, + "antenna_gain_desc": "antenna gain, in dBi", + "radio_0": { + "enable": true, + "type": "SX1257", + "freq": 922400000, + "rssi_offset": -166.0, + "tx_enable": true, + "tx_freq_min": 920900000, + "tx_freq_max": 923300000 + }, + "radio_1": { + "enable": true, + "type": "SX1257", + "freq": 923000000, + "rssi_offset": -166.0, + "tx_enable": false + }, + "chan_multiSF_0": { + "desc": "Lora MAC, 125kHz, all SF, 922.1 MHz", + "enable": true, + "radio": 0, + "if": -300000 + }, + "chan_multiSF_1": { + "desc": "Lora MAC, 125kHz, all SF, 922.3 MHz", + "enable": true, + "radio": 0, + "if": -100000 + }, + "chan_multiSF_2": { + "desc": "Lora MAC, 125kHz, all SF, 922.5 MHz", + "enable": true, + "radio": 0, + "if": 100000 + }, + "chan_multiSF_3": { + "desc": "Lora MAC, 125kHz, all SF, 922.7 MHz", + "enable": true, + "radio": 0, + "if": 300000 + }, + "chan_multiSF_4": { + "desc": "Lora MAC, 125kHz, all SF, 922.9 MHz", + "enable": true, + "radio": 1, + "if": -100000 + }, + "chan_multiSF_5": { + "desc": "Lora MAC, 125kHz, all SF, 923.1 MHz", + "enable": true, + "radio": 1, + "if": 100000 + }, + "chan_multiSF_6": { + "desc": "Lora MAC, 125kHz, all SF, 923.3 MHz", + "enable": true, + "radio": 1, + "if": 300000 + }, + "chan_multiSF_7": { + "desc": "disabled", + "enable": false + }, + "chan_Lora_std": { + "desc": "disabled", + "enable": false + }, + "chan_FSK": { + "desc": "disabled", + "enable": false + }, + "tx_lut_0": { + "desc": "TX gain table, index 0", + "pa_gain": 0, + "mix_gain": 8, + "rf_power": -6, + "dig_gain": 0 + }, + "tx_lut_1": { + "desc": "TX gain table, index 1", + "pa_gain": 0, + "mix_gain": 10, + "rf_power": -3, + "dig_gain": 0 + }, + "tx_lut_2": { + "desc": "TX gain table, index 2", + "pa_gain": 0, + "mix_gain": 12, + "rf_power": 0, + "dig_gain": 0 + }, + "tx_lut_3": { + "desc": "TX gain table, index 3", + "pa_gain": 1, + "mix_gain": 8, + "rf_power": 3, + "dig_gain": 0 + }, + "tx_lut_4": { + "desc": "TX gain table, index 4", + "pa_gain": 1, + "mix_gain": 10, + "rf_power": 6, + "dig_gain": 0 + }, + "tx_lut_5": { + "desc": "TX gain table, index 5", + "pa_gain": 1, + "mix_gain": 12, + "rf_power": 10, + "dig_gain": 0 + }, + "tx_lut_6": { + "desc": "TX gain table, index 6", + "pa_gain": 1, + "mix_gain": 13, + "rf_power": 11, + "dig_gain": 0 + }, + "tx_lut_7": { + "desc": "TX gain table, index 7", + "pa_gain": 2, + "mix_gain": 9, + "rf_power": 12, + "dig_gain": 0 + }, + "tx_lut_8": { + "desc": "TX gain table, index 8", + "pa_gain": 1, + "mix_gain": 15, + "rf_power": 13, + "dig_gain": 0 + }, + "tx_lut_9": { + "desc": "TX gain table, index 9", + "pa_gain": 2, + "mix_gain": 10, + "rf_power": 14, + "dig_gain": 0 + }, + "tx_lut_10": { + "desc": "TX gain table, index 10", + "pa_gain": 2, + "mix_gain": 11, + "rf_power": 16, + "dig_gain": 0 + }, + "tx_lut_11": { + "desc": "TX gain table, index 11", + "pa_gain": 3, + "mix_gain": 9, + "rf_power": 20, + "dig_gain": 0 + }, + "tx_lut_12": { + "desc": "TX gain table, index 12", + "pa_gain": 3, + "mix_gain": 10, + "rf_power": 23, + "dig_gain": 0 + }, + "tx_lut_13": { + "desc": "TX gain table, index 13", + "pa_gain": 3, + "mix_gain": 11, + "rf_power": 25, + "dig_gain": 0 + }, + "tx_lut_14": { + "desc": "TX gain table, index 14", + "pa_gain": 3, + "mix_gain": 12, + "rf_power": 26, + "dig_gain": 0 + }, + "tx_lut_15": { + "desc": "TX gain table, index 15", + "pa_gain": 3, + "mix_gain": 14, + "rf_power": 27, + "dig_gain": 0 + } + }, + "gateway_conf": { + "gateway_ID": "0000000000000000", + /* change with default server address/ports, or overwrite in local_conf.json */ + "server_address": "router.kr.thethings.network", + "serv_port_up": 1700, + "serv_port_down": 1700, + /* adjust the following parameters for your network */ + "keepalive_interval": 10, + "stat_interval": 30, + "push_timeout_ms": 100, + /* forward only valid packets */ + "forward_crc_valid": true, + "forward_crc_error": false, + "forward_crc_disabled": false, + "autoquit_threshold": 6 + } + +} + + diff --git a/lora/global_conf/no_gps/global_conf.ru_864_870.json b/lora/global_conf/no_gps/global_conf.ru_864_870.json new file mode 100644 index 0000000..631afa5 --- /dev/null +++ b/lora/global_conf/no_gps/global_conf.ru_864_870.json @@ -0,0 +1,209 @@ +{ + "SX1301_conf": { + "lorawan_public": true, + "clksrc": 1, + "clksrc_desc": "radio_1 provides clock to concentrator for most devices except MultiTech. For MultiTech set to 0.", + "antenna_gain": 0, + "antenna_gain_desc": "antenna gain, in dBi", + "radio_0": { + "enable": true, + "type": "SX1257", + "freq": 864500000, + "rssi_offset": -166.0, + "tx_enable": true, + "tx_freq_min": 863000000, + "tx_freq_max": 870000000 + }, + "radio_1": { + "enable": true, + "type": "SX1257", + "freq": 869000000, + "rssi_offset": -166.0, + "tx_enable": false + }, + "chan_multiSF_0": { + "desc": "Lora MAC, 125kHz, all SF, 864.1 MHz", + "enable": true, + "radio": 0, + "if": -400000 + }, + "chan_multiSF_1": { + "desc": "Lora MAC, 125kHz, all SF, 864.3 MHz", + "enable": true, + "radio": 0, + "if": -200000 + }, + "chan_multiSF_2": { + "desc": "Lora MAC, 125kHz, all SF, 864.5 MHz", + "enable": true, + "radio": 0, + "if": 0 + }, + "chan_multiSF_3": { + "desc": "Lora MAC, 125kHz, all SF, 864.7 MHz", + "enable": true, + "radio": 0, + "if": 200000 + }, + "chan_multiSF_4": { + "desc": "Lora MAC, 125kHz, all SF, 864.9 MHz", + "enable": true, + "radio": 0, + "if": 400000 + }, + "chan_multiSF_5": { + "desc": "Lora MAC, 125kHz, all SF, 868.9 MHz", + "enable": true, + "radio": 1, + "if": -100000 + }, + "chan_multiSF_6": { + "desc": "Lora MAC, 125kHz, all SF, 869.1 MHz", + "enable": true, + "radio": 1, + "if": 100000 + }, + "chan_multiSF_7": { + "desc": "disabled", + "enable": false + }, + "chan_Lora_std": { + "desc": "disabled", + "enable": false + }, + "chan_FSK": { + "desc": "disabled", + "enable": false + }, + "tx_lut_0": { + "desc": "TX gain table, index 0", + "pa_gain": 0, + "mix_gain": 8, + "rf_power": -6, + "dig_gain": 0 + }, + "tx_lut_1": { + "desc": "TX gain table, index 1", + "pa_gain": 0, + "mix_gain": 10, + "rf_power": -3, + "dig_gain": 0 + }, + "tx_lut_2": { + "desc": "TX gain table, index 2", + "pa_gain": 0, + "mix_gain": 12, + "rf_power": 0, + "dig_gain": 0 + }, + "tx_lut_3": { + "desc": "TX gain table, index 3", + "pa_gain": 1, + "mix_gain": 8, + "rf_power": 3, + "dig_gain": 0 + }, + "tx_lut_4": { + "desc": "TX gain table, index 4", + "pa_gain": 1, + "mix_gain": 10, + "rf_power": 6, + "dig_gain": 0 + }, + "tx_lut_5": { + "desc": "TX gain table, index 5", + "pa_gain": 1, + "mix_gain": 12, + "rf_power": 10, + "dig_gain": 0 + }, + "tx_lut_6": { + "desc": "TX gain table, index 6", + "pa_gain": 1, + "mix_gain": 13, + "rf_power": 11, + "dig_gain": 0 + }, + "tx_lut_7": { + "desc": "TX gain table, index 7", + "pa_gain": 2, + "mix_gain": 9, + "rf_power": 12, + "dig_gain": 0 + }, + "tx_lut_8": { + "desc": "TX gain table, index 8", + "pa_gain": 1, + "mix_gain": 15, + "rf_power": 13, + "dig_gain": 0 + }, + "tx_lut_9": { + "desc": "TX gain table, index 9", + "pa_gain": 2, + "mix_gain": 10, + "rf_power": 14, + "dig_gain": 0 + }, + "tx_lut_10": { + "desc": "TX gain table, index 10", + "pa_gain": 2, + "mix_gain": 11, + "rf_power": 16, + "dig_gain": 0 + }, + "tx_lut_11": { + "desc": "TX gain table, index 11", + "pa_gain": 3, + "mix_gain": 9, + "rf_power": 20, + "dig_gain": 0 + }, + "tx_lut_12": { + "desc": "TX gain table, index 12", + "pa_gain": 3, + "mix_gain": 10, + "rf_power": 23, + "dig_gain": 0 + }, + "tx_lut_13": { + "desc": "TX gain table, index 13", + "pa_gain": 3, + "mix_gain": 11, + "rf_power": 25, + "dig_gain": 0 + }, + "tx_lut_14": { + "desc": "TX gain table, index 14", + "pa_gain": 3, + "mix_gain": 12, + "rf_power": 26, + "dig_gain": 0 + }, + "tx_lut_15": { + "desc": "TX gain table, index 15", + "pa_gain": 3, + "mix_gain": 14, + "rf_power": 27, + "dig_gain": 0 + } + }, + "gateway_conf": { + "gateway_ID": "0000000000000000", + /* change with default server address/ports, or overwrite in local_conf.json */ + "server_address": "router.ru.thethings.network", + "serv_port_up": 1700, + "serv_port_down": 1700, + /* adjust the following parameters for your network */ + "keepalive_interval": 10, + "stat_interval": 30, + "push_timeout_ms": 100, + /* forward only valid packets */ + "forward_crc_valid": true, + "forward_crc_error": false, + "forward_crc_disabled": false, + "autoquit_threshold": 6 + } + +} + diff --git a/lora/global_conf/no_gps/global_conf.us_902_928.json b/lora/global_conf/no_gps/global_conf.us_902_928.json new file mode 100644 index 0000000..6da7245 --- /dev/null +++ b/lora/global_conf/no_gps/global_conf.us_902_928.json @@ -0,0 +1,205 @@ +{ + "SX1301_conf": { + "lorawan_public": true, + "clksrc": 1, + "antenna_gain": 0, + "radio_0": { + "enable": true, + "type": "SX1257", + "freq": 904300000, + "rssi_offset": -166.0, + "tx_enable": true, + "tx_freq_min": 902000000, + "tx_freq_max": 928000000 + }, + "radio_1": { + "enable": true, + "type": "SX1257", + "freq": 905000000, + "rssi_offset": -166.0, + "tx_enable": false + }, + "chan_multiSF_0": { + "enable": true, + "radio": 0, + "if": -400000 + }, + "chan_multiSF_1": { + "enable": true, + "radio": 0, + "if": -200000 + }, + "chan_multiSF_2": { + "enable": true, + "radio": 0, + "if": 0 + }, + "chan_multiSF_3": { + "enable": true, + "radio": 0, + "if": 200000 + }, + "chan_multiSF_4": { + "enable": true, + "radio": 1, + "if": -300000 + }, + "chan_multiSF_5": { + "enable": true, + "radio": 1, + "if": -100000 + }, + "chan_multiSF_6": { + "enable": true, + "radio": 1, + "if": 100000 + }, + "chan_multiSF_7": { + "enable": true, + "radio": 1, + "if": 300000 + }, + "chan_Lora_std": { + "enable": true, + "radio": 0, + "if": 300000, + "bandwidth": 500000, + "spread_factor": 8 + }, + "chan_FSK": { + "enable": false, + "radio": 0, + "if": 300000, + "bandwidth": 250000, + "datarate": 100000 + }, + "tx_lut_0": { + "desc": "TX gain table, index 0", + "pa_gain": 0, + "mix_gain": 8, + "rf_power": -6, + "dig_gain": 0 + }, + "tx_lut_1": { + "desc": "TX gain table, index 1", + "pa_gain": 0, + "mix_gain": 10, + "rf_power": -3, + "dig_gain": 0 + }, + "tx_lut_2": { + "desc": "TX gain table, index 2", + "pa_gain": 0, + "mix_gain": 12, + "rf_power": 0, + "dig_gain": 0 + }, + "tx_lut_3": { + "desc": "TX gain table, index 3", + "pa_gain": 1, + "mix_gain": 8, + "rf_power": 3, + "dig_gain": 0 + }, + "tx_lut_4": { + "desc": "TX gain table, index 4", + "pa_gain": 1, + "mix_gain": 10, + "rf_power": 6, + "dig_gain": 0 + }, + "tx_lut_5": { + "desc": "TX gain table, index 5", + "pa_gain": 1, + "mix_gain": 12, + "rf_power": 10, + "dig_gain": 0 + }, + "tx_lut_6": { + "desc": "TX gain table, index 6", + "pa_gain": 1, + "mix_gain": 13, + "rf_power": 11, + "dig_gain": 0 + }, + "tx_lut_7": { + "desc": "TX gain table, index 7", + "pa_gain": 2, + "mix_gain": 9, + "rf_power": 12, + "dig_gain": 0 + }, + "tx_lut_8": { + "desc": "TX gain table, index 8", + "pa_gain": 1, + "mix_gain": 15, + "rf_power": 13, + "dig_gain": 0 + }, + "tx_lut_9": { + "desc": "TX gain table, index 9", + "pa_gain": 2, + "mix_gain": 10, + "rf_power": 14, + "dig_gain": 0 + }, + "tx_lut_10": { + "desc": "TX gain table, index 10", + "pa_gain": 2, + "mix_gain": 11, + "rf_power": 16, + "dig_gain": 0 + }, + "tx_lut_11": { + "desc": "TX gain table, index 11", + "pa_gain": 3, + "mix_gain": 9, + "rf_power": 20, + "dig_gain": 0 + }, + "tx_lut_12": { + "desc": "TX gain table, index 12", + "pa_gain": 3, + "mix_gain": 10, + "rf_power": 23, + "dig_gain": 0 + }, + "tx_lut_13": { + "desc": "TX gain table, index 13", + "pa_gain": 3, + "mix_gain": 11, + "rf_power": 25, + "dig_gain": 0 + }, + "tx_lut_14": { + "desc": "TX gain table, index 14", + "pa_gain": 3, + "mix_gain": 12, + "rf_power": 26, + "dig_gain": 0 + }, + "tx_lut_15": { + "desc": "TX gain table, index 15", + "pa_gain": 3, + "mix_gain": 14, + "rf_power": 27, + "dig_gain": 0 + } + }, + "gateway_conf": { + "gateway_ID": "0000000000000000", + /* change with default server address/ports, or overwrite in local_conf.json */ + "server_address": "router.us.thethings.network", + "serv_port_up": 1700, + "serv_port_down": 1700, + /* adjust the following parameters for your network */ + "keepalive_interval": 10, + "stat_interval": 30, + "push_timeout_ms": 100, + /* forward only valid packets */ + "forward_crc_valid": true, + "forward_crc_error": false, + "forward_crc_disabled": false, + "autoquit_threshold": 6 + } +} diff --git a/lora/global_conf/serial/global_conf.as_923.json b/lora/global_conf/serial/global_conf.as_923.json new file mode 100644 index 0000000..59e98ff --- /dev/null +++ b/lora/global_conf/serial/global_conf.as_923.json @@ -0,0 +1,225 @@ +{ + "SX1301_conf": { + "lorawan_public": true, + "clksrc": 1, + "clksrc_desc": "radio_1 provides clock to concentrator for most devices except MultiTech. For MultiTech set to 0.", + "antenna_gain": 0, + "antenna_gain_desc": "antenna gain, in dBi", + "radio_0": { + "enable": true, + "type": "SX1257", + "freq": 923600000, + "rssi_offset": -166.0, + "tx_enable": true, + "tx_freq_min": 923200000, + "tx_freq_max": 925000000 + }, + "radio_1": { + "enable": true, + "type": "SX1257", + "freq": 924600000, + "rssi_offset": -166.0, + "tx_enable": false + }, + "chan_multiSF_0": { + "desc": "Lora MAC, 125kHz, all SF, 923.2 MHz", + "enable": true, + "radio": 0, + "if": -400000 + }, + "chan_multiSF_1": { + "desc": "Lora MAC, 125kHz, all SF, 923.4 MHz", + "enable": true, + "radio": 0, + "if": -200000 + }, + "chan_multiSF_2": { + "desc": "Lora MAC, 125kHz, all SF, 923.6 MHz", + "enable": true, + "radio": 0, + "if": 0 + }, + "chan_multiSF_3": { + "desc": "Lora MAC, 125kHz, all SF, 923.8 MHz", + "enable": true, + "radio": 0, + "if": 200000 + }, + "chan_multiSF_4": { + "desc": "Lora MAC, 125kHz, all SF, 924.0 MHz", + "enable": true, + "radio": 0, + "if": 400000 + }, + "chan_multiSF_5": { + "desc": "Lora MAC, 125kHz, all SF, 924.2 MHz", + "enable": true, + "radio": 1, + "if": -400000 + }, + "chan_multiSF_6": { + "desc": "Lora MAC, 125kHz, all SF, 924.4 MHz", + "enable": true, + "radio": 1, + "if": -200000 + }, + "chan_multiSF_7": { + "desc": "Lora MAC, 125kHz, all SF, 924.6 MHz", + "enable": true, + "radio": 1, + "if": 0 + }, + "chan_Lora_std": { + "desc": "Lora MAC, 250kHz, SF7, 924.5 MHz", + "enable": true, + "radio": 1, + "if": -100000, + "bandwidth": 250000, + "spread_factor": 7 + }, + "chan_FSK": { + "desc": "FSK 50kbps, 924.8 MHz", + "enable": true, + "radio": 1, + "if": 200000, + "bandwidth": 125000, + "datarate": 50000 + }, + "tx_lut_0": { + "desc": "TX gain table, index 0", + "pa_gain": 0, + "mix_gain": 8, + "rf_power": -6, + "dig_gain": 0 + }, + "tx_lut_1": { + "desc": "TX gain table, index 1", + "pa_gain": 0, + "mix_gain": 10, + "rf_power": -3, + "dig_gain": 0 + }, + "tx_lut_2": { + "desc": "TX gain table, index 2", + "pa_gain": 0, + "mix_gain": 12, + "rf_power": 0, + "dig_gain": 0 + }, + "tx_lut_3": { + "desc": "TX gain table, index 3", + "pa_gain": 1, + "mix_gain": 8, + "rf_power": 3, + "dig_gain": 0 + }, + "tx_lut_4": { + "desc": "TX gain table, index 4", + "pa_gain": 1, + "mix_gain": 10, + "rf_power": 6, + "dig_gain": 0 + }, + "tx_lut_5": { + "desc": "TX gain table, index 5", + "pa_gain": 1, + "mix_gain": 12, + "rf_power": 10, + "dig_gain": 0 + }, + "tx_lut_6": { + "desc": "TX gain table, index 6", + "pa_gain": 1, + "mix_gain": 13, + "rf_power": 11, + "dig_gain": 0 + }, + "tx_lut_7": { + "desc": "TX gain table, index 7", + "pa_gain": 2, + "mix_gain": 9, + "rf_power": 12, + "dig_gain": 0 + }, + "tx_lut_8": { + "desc": "TX gain table, index 8", + "pa_gain": 1, + "mix_gain": 15, + "rf_power": 13, + "dig_gain": 0 + }, + "tx_lut_9": { + "desc": "TX gain table, index 9", + "pa_gain": 2, + "mix_gain": 10, + "rf_power": 14, + "dig_gain": 0 + }, + "tx_lut_10": { + "desc": "TX gain table, index 10", + "pa_gain": 2, + "mix_gain": 11, + "rf_power": 16, + "dig_gain": 0 + }, + "tx_lut_11": { + "desc": "TX gain table, index 11", + "pa_gain": 3, + "mix_gain": 9, + "rf_power": 20, + "dig_gain": 0 + }, + "tx_lut_12": { + "desc": "TX gain table, index 12", + "pa_gain": 3, + "mix_gain": 10, + "rf_power": 23, + "dig_gain": 0 + }, + "tx_lut_13": { + "desc": "TX gain table, index 13", + "pa_gain": 3, + "mix_gain": 11, + "rf_power": 25, + "dig_gain": 0 + }, + "tx_lut_14": { + "desc": "TX gain table, index 14", + "pa_gain": 3, + "mix_gain": 12, + "rf_power": 26, + "dig_gain": 0 + }, + "tx_lut_15": { + "desc": "TX gain table, index 15", + "pa_gain": 3, + "mix_gain": 14, + "rf_power": 27, + "dig_gain": 0 + } + }, + "gateway_conf": { + "gateway_ID": "0000000000000000", + /* change with default server address/ports, or overwrite in local_conf.json */ + "server_address": "router.as2.thethings.network", + "serv_port_up": 1700, + "serv_port_down": 1700, + /* adjust the following parameters for your network */ + "keepalive_interval": 10, + "stat_interval": 30, + "push_timeout_ms": 100, + /* forward only valid packets */ + "forward_crc_valid": true, + "forward_crc_error": false, + "forward_crc_disabled": false, + /* gps enable */ + "gps": true, + "gps_tty_path": "/dev/ttyAMA0", + "fake_gps": false, + "ref_latitude": 10, + "ref_longitude": 20, + "ref_altitude": -1, + "autoquit_threshold": 6 + } + +} diff --git a/lora/global_conf/serial/global_conf.au_915_928.json b/lora/global_conf/serial/global_conf.au_915_928.json new file mode 100644 index 0000000..2147f05 --- /dev/null +++ b/lora/global_conf/serial/global_conf.au_915_928.json @@ -0,0 +1,222 @@ +{ + "SX1301_conf": { + "lorawan_public": true, + "clksrc": 1, + "clksrc_desc": "radio_1 provides clock to concentrator for most devices except MultiTech. For MultiTech set to 0.", + "antenna_gain": 0, + "antenna_gain_desc": "antenna gain, in dBi", + "radio_0": { + "enable": true, + "type": "SX1257", + "freq": 917200000, + "rssi_offset": -166.0, + "tx_enable": true, + "tx_freq_min": 915000000, + "tx_freq_max": 928000000 + }, + "radio_1": { + "enable": true, + "type": "SX1257", + "freq": 917900000, + "rssi_offset": -166.0, + "tx_enable": false + }, + "chan_multiSF_0": { + "desc": "Lora MAC, 125kHz, all SF, 916.8 MHz", + "enable": true, + "radio": 0, + "if": -400000 + }, + "chan_multiSF_1": { + "desc": "Lora MAC, 125kHz, all SF, 917.0 MHz", + "enable": true, + "radio": 0, + "if": -200000 + }, + "chan_multiSF_2": { + "desc": "Lora MAC, 125kHz, all SF, 917.2 MHz", + "enable": true, + "radio": 0, + "if": 0 + }, + "chan_multiSF_3": { + "desc": "Lora MAC, 125kHz, all SF, 917.4 MHz", + "enable": true, + "radio": 0, + "if": 200000 + }, + "chan_multiSF_4": { + "desc": "Lora MAC, 125kHz, all SF, 917.6 MHz", + "enable": true, + "radio": 1, + "if": -300000 + }, + "chan_multiSF_5": { + "desc": "Lora MAC, 125kHz, all SF, 917.8 MHz", + "enable": true, + "radio": 1, + "if": -100000 + }, + "chan_multiSF_6": { + "desc": "Lora MAC, 125kHz, all SF, 918.0 MHz", + "enable": true, + "radio": 1, + "if": 100000 + }, + "chan_multiSF_7": { + "desc": "Lora MAC, 125kHz, all SF, 918.2 MHz", + "enable": true, + "radio": 1, + "if": 300000 + }, + "chan_Lora_std": { + "desc": "Lora MAC, 500kHz, SF8, 917.5 MHz", + "enable": true, + "radio": 0, + "if": 300000, + "bandwidth": 500000, + "spread_factor": 8 + }, + "chan_FSK": { + "desc": "disabled", + "enable": false + }, + "tx_lut_0": { + "desc": "TX gain table, index 0", + "pa_gain": 0, + "mix_gain": 8, + "rf_power": -6, + "dig_gain": 0 + }, + "tx_lut_1": { + "desc": "TX gain table, index 1", + "pa_gain": 0, + "mix_gain": 10, + "rf_power": -3, + "dig_gain": 0 + }, + "tx_lut_2": { + "desc": "TX gain table, index 2", + "pa_gain": 0, + "mix_gain": 12, + "rf_power": 0, + "dig_gain": 0 + }, + "tx_lut_3": { + "desc": "TX gain table, index 3", + "pa_gain": 1, + "mix_gain": 8, + "rf_power": 3, + "dig_gain": 0 + }, + "tx_lut_4": { + "desc": "TX gain table, index 4", + "pa_gain": 1, + "mix_gain": 10, + "rf_power": 6, + "dig_gain": 0 + }, + "tx_lut_5": { + "desc": "TX gain table, index 5", + "pa_gain": 1, + "mix_gain": 12, + "rf_power": 10, + "dig_gain": 0 + }, + "tx_lut_6": { + "desc": "TX gain table, index 6", + "pa_gain": 1, + "mix_gain": 13, + "rf_power": 11, + "dig_gain": 0 + }, + "tx_lut_7": { + "desc": "TX gain table, index 7", + "pa_gain": 2, + "mix_gain": 9, + "rf_power": 12, + "dig_gain": 0 + }, + "tx_lut_8": { + "desc": "TX gain table, index 8", + "pa_gain": 1, + "mix_gain": 15, + "rf_power": 13, + "dig_gain": 0 + }, + "tx_lut_9": { + "desc": "TX gain table, index 9", + "pa_gain": 2, + "mix_gain": 10, + "rf_power": 14, + "dig_gain": 0 + }, + "tx_lut_10": { + "desc": "TX gain table, index 10", + "pa_gain": 2, + "mix_gain": 11, + "rf_power": 16, + "dig_gain": 0 + }, + "tx_lut_11": { + "desc": "TX gain table, index 11", + "pa_gain": 3, + "mix_gain": 9, + "rf_power": 20, + "dig_gain": 0 + }, + "tx_lut_12": { + "desc": "TX gain table, index 12", + "pa_gain": 3, + "mix_gain": 10, + "rf_power": 23, + "dig_gain": 0 + }, + "tx_lut_13": { + "desc": "TX gain table, index 13", + "pa_gain": 3, + "mix_gain": 11, + "rf_power": 25, + "dig_gain": 0 + }, + "tx_lut_14": { + "desc": "TX gain table, index 14", + "pa_gain": 3, + "mix_gain": 12, + "rf_power": 26, + "dig_gain": 0 + }, + "tx_lut_15": { + "desc": "TX gain table, index 15", + "pa_gain": 3, + "mix_gain": 14, + "rf_power": 27, + "dig_gain": 0 + } + }, + "gateway_conf": { + "gateway_ID": "0000000000000000", + /* change with default server address/ports, or overwrite in local_conf.json */ + "server_address": "router.au.thethings.network", + "serv_port_up": 1700, + "serv_port_down": 1700, + /* adjust the following parameters for your network */ + "keepalive_interval": 10, + "stat_interval": 30, + "push_timeout_ms": 100, + /* forward only valid packets */ + "forward_crc_valid": true, + "forward_crc_error": false, + "forward_crc_disabled": false, + /* gps enable */ + "gps": true, + "gps_tty_path": "/dev/ttyAMA0", + "fake_gps": false, + "ref_latitude": 10, + "ref_longitude": 20, + "ref_altitude": -1, + "autoquit_threshold": 6 + } + +} + diff --git a/lora/global_conf/serial/global_conf.cn_470_510.json b/lora/global_conf/serial/global_conf.cn_470_510.json new file mode 100644 index 0000000..4fd248c --- /dev/null +++ b/lora/global_conf/serial/global_conf.cn_470_510.json @@ -0,0 +1,217 @@ +{ + "SX1301_conf": { + "lorawan_public": true, + "clksrc": 1, + "clksrc_desc": "radio_1 provides clock to concentrator for most devices except MultiTech. For MultiTech set to 0.", + "antenna_gain": 0, + "antenna_gain_desc": "antenna gain, in dBi", + "radio_0": { + "enable": true, + "type": "SX1255", + "freq": 486600000, + "rssi_offset": -176.0, + "tx_enable": true, + "tx_freq_min": 470000000, + "tx_freq_max": 510000000 + }, + "radio_1": { + "enable": true, + "type": "SX1255", + "freq": 487400000, + "rssi_offset": -176.0, + "tx_enable": false + }, + "chan_multiSF_0": { + "desc": "Lora MAC, 125kHz, all SF, 487.1 MHz", + "enable": true, + "radio": 1, + "if": -300000 + }, + "chan_multiSF_1": { + "desc": "Lora MAC, 125kHz, all SF, 487.3 MHz", + "enable": true, + "radio": 1, + "if": -100000 + }, + "chan_multiSF_2": { + "desc": "Lora MAC, 125kHz, all SF, 487.5 MHz", + "enable": true, + "radio": 1, + "if": 100000 + }, + "chan_multiSF_3": { + "desc": "Lora MAC, 125kHz, all SF, 487.7 MHz", + "enable": true, + "radio": 1, + "if": 300000 + }, + "chan_multiSF_4": { + "desc": "Lora MAC, 125kHz, all SF, 486.3 MHz", + "enable": true, + "radio": 0, + "if": -300000 + }, + "chan_multiSF_5": { + "desc": "Lora MAC, 125kHz, all SF, 486.5 MHz", + "enable": true, + "radio": 0, + "if": -100000 + }, + "chan_multiSF_6": { + "desc": "Lora MAC, 125kHz, all SF, 486.7 MHz", + "enable": true, + "radio": 0, + "if": 100000 + }, + "chan_multiSF_7": { + "desc": "Lora MAC, 125kHz, all SF, 486.9 MHz", + "enable": true, + "radio": 0, + "if": 300000 + }, + "chan_Lora_std": { + "desc": "disabled", + "enable": false + }, + "chan_FSK": { + "desc": "disabled", + "enable": false + }, + "tx_lut_0": { + "desc": "TX gain table, index 0", + "pa_gain": 0, + "mix_gain": 8, + "rf_power": -6, + "dig_gain": 0 + }, + "tx_lut_1": { + "desc": "TX gain table, index 1", + "pa_gain": 0, + "mix_gain": 10, + "rf_power": -3, + "dig_gain": 0 + }, + "tx_lut_2": { + "desc": "TX gain table, index 2", + "pa_gain": 0, + "mix_gain": 12, + "rf_power": 0, + "dig_gain": 0 + }, + "tx_lut_3": { + "desc": "TX gain table, index 3", + "pa_gain": 1, + "mix_gain": 8, + "rf_power": 3, + "dig_gain": 0 + }, + "tx_lut_4": { + "desc": "TX gain table, index 4", + "pa_gain": 1, + "mix_gain": 10, + "rf_power": 6, + "dig_gain": 0 + }, + "tx_lut_5": { + "desc": "TX gain table, index 5", + "pa_gain": 1, + "mix_gain": 12, + "rf_power": 10, + "dig_gain": 0 + }, + "tx_lut_6": { + "desc": "TX gain table, index 6", + "pa_gain": 1, + "mix_gain": 13, + "rf_power": 11, + "dig_gain": 0 + }, + "tx_lut_7": { + "desc": "TX gain table, index 7", + "pa_gain": 2, + "mix_gain": 9, + "rf_power": 12, + "dig_gain": 0 + }, + "tx_lut_8": { + "desc": "TX gain table, index 8", + "pa_gain": 1, + "mix_gain": 15, + "rf_power": 13, + "dig_gain": 0 + }, + "tx_lut_9": { + "desc": "TX gain table, index 9", + "pa_gain": 2, + "mix_gain": 10, + "rf_power": 14, + "dig_gain": 0 + }, + "tx_lut_10": { + "desc": "TX gain table, index 10", + "pa_gain": 2, + "mix_gain": 11, + "rf_power": 16, + "dig_gain": 0 + }, + "tx_lut_11": { + "desc": "TX gain table, index 11", + "pa_gain": 3, + "mix_gain": 9, + "rf_power": 20, + "dig_gain": 0 + }, + "tx_lut_12": { + "desc": "TX gain table, index 12", + "pa_gain": 3, + "mix_gain": 10, + "rf_power": 23, + "dig_gain": 0 + }, + "tx_lut_13": { + "desc": "TX gain table, index 13", + "pa_gain": 3, + "mix_gain": 11, + "rf_power": 25, + "dig_gain": 0 + }, + "tx_lut_14": { + "desc": "TX gain table, index 14", + "pa_gain": 3, + "mix_gain": 12, + "rf_power": 26, + "dig_gain": 0 + }, + "tx_lut_15": { + "desc": "TX gain table, index 15", + "pa_gain": 3, + "mix_gain": 14, + "rf_power": 27, + "dig_gain": 0 + } + }, + "gateway_conf": { + "gateway_ID": "0000000000000000", + /* change with default server address/ports, or overwrite in local_conf.json */ + "server_address": "router.cn.thethings.network", + "serv_port_up": 1700, + "serv_port_down": 1700, + /* adjust the following parameters for your network */ + "keepalive_interval": 10, + "stat_interval": 30, + "push_timeout_ms": 100, + /* forward only valid packets */ + "forward_crc_valid": true, + "forward_crc_error": false, + "forward_crc_disabled": false, + /* gps enable */ + "gps": true, + "gps_tty_path": "/dev/ttyAMA0", + "fake_gps": false, + "ref_latitude": 10, + "ref_longitude": 20, + "ref_altitude": -1, + "autoquit_threshold": 6 + } +} + diff --git a/lora/global_conf/serial/global_conf.eu_433.json b/lora/global_conf/serial/global_conf.eu_433.json new file mode 100644 index 0000000..a44eb75 --- /dev/null +++ b/lora/global_conf/serial/global_conf.eu_433.json @@ -0,0 +1,224 @@ +{ + + "SX1301_conf": { + "lorawan_public": true, + "clksrc": 1, /* radio_1 provides clock to concentrator */ + "antenna_gain": 0, /* antenna gain, in dBi */ + "radio_0": { + "enable": true, + "type": "SX1255", + "freq": 434375000, + "rssi_offset": -166.0, + "tx_enable": true, + "tx_freq_min": 433050000, + "tx_freq_max": 434900000 + }, + "radio_1": { + "enable": true, + "type": "SX1255", + "freq": 433575000, + "rssi_offset": -166.0, + "tx_enable": false + }, + "chan_multiSF_0": { + /* Lora MAC channel, 125kHz, all SF, 433.175 MHz */ + "enable": true, + "radio": 1, + "if": -400000 + }, + "chan_multiSF_1": { + /* Lora MAC channel, 125kHz, all SF, 433.375 MHz */ + "enable": true, + "radio": 1, + "if": -200000 + }, + "chan_multiSF_2": { + /* Lora MAC channel, 125kHz, all SF, 433.575 MHz */ + "enable": true, + "radio": 1, + "if": 0 + }, + "chan_multiSF_3": { + /* Lora MAC channel, 125kHz, all SF, 433.975 MHz */ + "enable": true, + "radio": 0, + "if": -400000 + }, + "chan_multiSF_4": { + /* Lora MAC channel, 125kHz, all SF, 434.175 MHz */ + "enable": true, + "radio": 0, + "if": -200000 + }, + "chan_multiSF_5": { + /* Lora MAC channel, 125kHz, all SF, 434.375 MHz */ + "enable": true, + "radio": 0, + "if": 0 + }, + "chan_multiSF_6": { + /* Lora MAC channel, 125kHz, all SF, 434.575 MHz */ + "enable": true, + "radio": 0, + "if": 200000 + }, + "chan_multiSF_7": { + /* Lora MAC channel, 125kHz, all SF, 434.775 MHz */ + "enable": true, + "radio": 0, + "if": 400000 + }, + "chan_Lora_std": { + /* Lora MAC channel, 250kHz, SF7, 434.175 MHz */ + "enable": true, + "radio": 1, + "if": -200000, + "bandwidth": 250000, + "spread_factor": 7 + }, + "chan_FSK": { + /* FSK 50kbps channel, 434.675 MHz */ + "enable": true, + "radio": 1, + "if": 300000, + "bandwidth": 125000, + "datarate": 50000 + }, + "tx_lut_0": { + /* TX gain table, index 0 */ + "pa_gain": 0, + "mix_gain": 8, + "rf_power": -6, + "dig_gain": 0 + }, + "tx_lut_1": { + /* TX gain table, index 1 */ + "pa_gain": 0, + "mix_gain": 10, + "rf_power": -3, + "dig_gain": 0 + }, + "tx_lut_2": { + /* TX gain table, index 2 */ + "pa_gain": 0, + "mix_gain": 12, + "rf_power": 0, + "dig_gain": 0 + }, + "tx_lut_3": { + /* TX gain table, index 3 */ + "pa_gain": 1, + "mix_gain": 8, + "rf_power": 3, + "dig_gain": 0 + }, + "tx_lut_4": { + /* TX gain table, index 4 */ + "pa_gain": 1, + "mix_gain": 10, + "rf_power": 6, + "dig_gain": 0 + }, + "tx_lut_5": { + /* TX gain table, index 5 */ + "pa_gain": 1, + "mix_gain": 12, + "rf_power": 10, + "dig_gain": 0 + }, + "tx_lut_6": { + /* TX gain table, index 6 */ + "pa_gain": 1, + "mix_gain": 13, + "rf_power": 11, + "dig_gain": 0 + }, + "tx_lut_7": { + /* TX gain table, index 7 */ + "pa_gain": 2, + "mix_gain": 9, + "rf_power": 12, + "dig_gain": 0 + }, + "tx_lut_8": { + /* TX gain table, index 8 */ + "pa_gain": 1, + "mix_gain": 15, + "rf_power": 13, + "dig_gain": 0 + }, + "tx_lut_9": { + /* TX gain table, index 9 */ + "pa_gain": 2, + "mix_gain": 10, + "rf_power": 14, + "dig_gain": 0 + }, + "tx_lut_10": { + /* TX gain table, index 10 */ + "pa_gain": 2, + "mix_gain": 11, + "rf_power": 16, + "dig_gain": 0 + }, + "tx_lut_11": { + /* TX gain table, index 11 */ + "pa_gain": 3, + "mix_gain": 9, + "rf_power": 20, + "dig_gain": 0 + }, + "tx_lut_12": { + "desc": "TX gain table, index 12", + "pa_gain": 3, + "mix_gain": 10, + "rf_power": 23, + "dig_gain": 0 + }, + "tx_lut_13": { + "desc": "TX gain table, index 13", + "pa_gain": 3, + "mix_gain": 11, + "rf_power": 25, + "dig_gain": 0 + }, + "tx_lut_14": { + "desc": "TX gain table, index 14", + "pa_gain": 3, + "mix_gain": 12, + "rf_power": 26, + "dig_gain": 0 + }, + "tx_lut_15": { + "desc": "TX gain table, index 15", + "pa_gain": 3, + "mix_gain": 14, + "rf_power": 27, + "dig_gain": 0 + } + }, + "gateway_conf": { + "gateway_ID": "0000000000000000", + /* change with default server address/ports, or overwrite in local_conf.json */ + "server_address": "localhost", + "serv_port_up": 1700, + "serv_port_down": 1700, + /* adjust the following parameters for your network */ + "keepalive_interval": 10, + "stat_interval": 30, + "push_timeout_ms": 100, + /* forward only valid packets */ + "forward_crc_valid": true, + "forward_crc_error": false, + "forward_crc_disabled": false, + /* gps enable */ + "gps": true, + "gps_tty_path": "/dev/ttyAMA0", + "fake_gps": false, + "ref_latitude": 10, + "ref_longitude": 20, + "ref_altitude": -1, + "autoquit_threshold": 6 + } +} + diff --git a/lora/global_conf/serial/global_conf.eu_863_870.json b/lora/global_conf/serial/global_conf.eu_863_870.json new file mode 100644 index 0000000..2383035 --- /dev/null +++ b/lora/global_conf/serial/global_conf.eu_863_870.json @@ -0,0 +1,200 @@ +{ + "SX1301_conf": { + "lorawan_public": true, + "clksrc": 1, + "antenna_gain": 0, + "radio_0": { + "enable": true, + "type": "SX1257", + "freq": 867500000, + "rssi_offset": -166.0, + "tx_enable": true, + "tx_freq_min": 863000000, + "tx_freq_max": 870000000 + }, + "radio_1": { + "enable": true, + "type": "SX1257", + "freq": 868500000, + "rssi_offset": -166.0, + "tx_enable": false + }, + "chan_multiSF_0": { + "enable": true, + "radio": 1, + "if": -400000 + }, + "chan_multiSF_1": { + "enable": true, + "radio": 1, + "if": -200000 + }, + "chan_multiSF_2": { + "enable": true, + "radio": 1, + "if": 0 + }, + "chan_multiSF_3": { + "enable": true, + "radio": 0, + "if": -400000 + }, + "chan_multiSF_4": { + "enable": true, + "radio": 0, + "if": -200000 + }, + "chan_multiSF_5": { + "enable": true, + "radio": 0, + "if": 0 + }, + "chan_multiSF_6": { + "enable": true, + "radio": 0, + "if": 200000 + }, + "chan_multiSF_7": { + "enable": true, + "radio": 0, + "if": 400000 + }, + "chan_Lora_std": { + "enable": true, + "radio": 1, + "if": -200000, + "bandwidth": 250000, + "spread_factor": 7 + }, + "chan_FSK": { + "enable": true, + "radio": 1, + "if": 300000, + "bandwidth": 125000, + "datarate": 50000 + }, + "tx_lut_0": { + "pa_gain": 0, + "mix_gain": 8, + "rf_power": -6, + "dig_gain": 0 + }, + "tx_lut_1": { + "pa_gain": 0, + "mix_gain": 10, + "rf_power": -3, + "dig_gain": 0 + }, + "tx_lut_2": { + "pa_gain": 0, + "mix_gain": 12, + "rf_power": 0, + "dig_gain": 0 + }, + "tx_lut_3": { + "pa_gain": 1, + "mix_gain": 8, + "rf_power": 3, + "dig_gain": 0 + }, + "tx_lut_4": { + "pa_gain": 1, + "mix_gain": 10, + "rf_power": 6, + "dig_gain": 0 + }, + "tx_lut_5": { + "pa_gain": 1, + "mix_gain": 12, + "rf_power": 10, + "dig_gain": 0 + }, + "tx_lut_6": { + "pa_gain": 1, + "mix_gain": 13, + "rf_power": 11, + "dig_gain": 0 + }, + "tx_lut_7": { + "pa_gain": 2, + "mix_gain": 9, + "rf_power": 12, + "dig_gain": 0 + }, + "tx_lut_8": { + "pa_gain": 1, + "mix_gain": 15, + "rf_power": 13, + "dig_gain": 0 + }, + "tx_lut_9": { + "pa_gain": 2, + "mix_gain": 10, + "rf_power": 14, + "dig_gain": 0 + }, + "tx_lut_10": { + "pa_gain": 2, + "mix_gain": 11, + "rf_power": 16, + "dig_gain": 0 + }, + "tx_lut_11": { + "pa_gain": 3, + "mix_gain": 9, + "rf_power": 20, + "dig_gain": 0 + }, + "tx_lut_12": { + "desc": "TX gain table, index 12", + "pa_gain": 3, + "mix_gain": 10, + "rf_power": 23, + "dig_gain": 0 + }, + "tx_lut_13": { + "desc": "TX gain table, index 13", + "pa_gain": 3, + "mix_gain": 11, + "rf_power": 25, + "dig_gain": 0 + }, + "tx_lut_14": { + "desc": "TX gain table, index 14", + "pa_gain": 3, + "mix_gain": 12, + "rf_power": 26, + "dig_gain": 0 + }, + "tx_lut_15": { + "desc": "TX gain table, index 15", + "pa_gain": 3, + "mix_gain": 14, + "rf_power": 27, + "dig_gain": 0 + } + }, + "gateway_conf": { + "gateway_ID": "0000000000000000", + /* change with default server address/ports, or overwrite in local_conf.json */ + "server_address": "router.eu.thethings.network", + "serv_port_up": 1700, + "serv_port_down": 1700, + /* adjust the following parameters for your network */ + "keepalive_interval": 10, + "stat_interval": 30, + "push_timeout_ms": 100, + /* forward only valid packets */ + "forward_crc_valid": true, + "forward_crc_error": false, + "forward_crc_disabled": false, + /* gps enable */ + "gps": true, + "gps_tty_path": "/dev/ttyAMA0", + "fake_gps": false, + "ref_latitude": 10, + "ref_longitude": 20, + "ref_altitude": -1, + "autoquit_threshold": 6 + } +} diff --git a/lora/global_conf/serial/global_conf.in_865_867.json b/lora/global_conf/serial/global_conf.in_865_867.json new file mode 100644 index 0000000..4d6559e --- /dev/null +++ b/lora/global_conf/serial/global_conf.in_865_867.json @@ -0,0 +1,209 @@ +{ + "SX1301_conf": { + "lorawan_public": true, + "clksrc": 1, + "clksrc_desc": "radio_1 provides clock to concentrator for most devices except MultiTech. For MultiTech set to 0.", + "antenna_gain": 0, + "antenna_gain_desc": "antenna gain, in dBi", + "radio_0": { + "enable": true, + "type": "SX1257", + "freq": 865200000, + "rssi_offset": -166.0, + "tx_enable": true, + "tx_freq_min": 865000000, + "tx_freq_max": 867000000, + "tx_notch_freq": 129000 + }, + "radio_1": { + "enable": true, + "type": "SX1257", + "freq": 866385000, + "rssi_offset": -166.0, + "tx_enable": false + }, + "chan_multiSF_0": { + "desc": "Lora MAC, 125kHz, all SF, 865.0625 MHz", + "enable": true, + "radio": 0, + "if": -137500 + }, + "chan_multiSF_1": { + "desc": "Lora MAC, 125kHz, all SF, 865.4025 MHz", + "enable": true, + "radio": 0, + "if": 202500 + }, + "chan_multiSF_2": { + "desc": "Lora MAC, 125kHz, all SF, 865.9850 MHz", + "enable": true, + "radio": 1, + "if": -400000 + }, + "chan_multiSF_3": { + "desc": "disabled", + "enable": false + }, + "chan_multiSF_4": { + "desc": "disabled", + "enable": false + }, + "chan_multiSF_5": { + "desc": "disabled", + "enable": false + }, + "chan_multiSF_6": { + "desc": "disabled", + "enable": false + }, + "chan_multiSF_7": { + "desc": "disabled", + "enable": false + }, + "chan_Lora_std": { + "desc": "disabled", + "enable": false + }, + "chan_FSK": { + "desc": "disabled", + "enable": false + }, + "tx_lut_0": { + "desc": "TX gain table, index 0", + "pa_gain": 0, + "mix_gain": 8, + "rf_power": -6, + "dig_gain": 0 + }, + "tx_lut_1": { + "desc": "TX gain table, index 1", + "pa_gain": 0, + "mix_gain": 10, + "rf_power": -3, + "dig_gain": 0 + }, + "tx_lut_2": { + "desc": "TX gain table, index 2", + "pa_gain": 0, + "mix_gain": 12, + "rf_power": 0, + "dig_gain": 0 + }, + "tx_lut_3": { + "desc": "TX gain table, index 3", + "pa_gain": 1, + "mix_gain": 8, + "rf_power": 3, + "dig_gain": 0 + }, + "tx_lut_4": { + "desc": "TX gain table, index 4", + "pa_gain": 1, + "mix_gain": 10, + "rf_power": 6, + "dig_gain": 0 + }, + "tx_lut_5": { + "desc": "TX gain table, index 5", + "pa_gain": 1, + "mix_gain": 12, + "rf_power": 10, + "dig_gain": 0 + }, + "tx_lut_6": { + "desc": "TX gain table, index 6", + "pa_gain": 1, + "mix_gain": 13, + "rf_power": 11, + "dig_gain": 0 + }, + "tx_lut_7": { + "desc": "TX gain table, index 7", + "pa_gain": 2, + "mix_gain": 9, + "rf_power": 12, + "dig_gain": 0 + }, + "tx_lut_8": { + "desc": "TX gain table, index 8", + "pa_gain": 1, + "mix_gain": 15, + "rf_power": 13, + "dig_gain": 0 + }, + "tx_lut_9": { + "desc": "TX gain table, index 9", + "pa_gain": 2, + "mix_gain": 10, + "rf_power": 14, + "dig_gain": 0 + }, + "tx_lut_10": { + "desc": "TX gain table, index 10", + "pa_gain": 2, + "mix_gain": 11, + "rf_power": 16, + "dig_gain": 0 + }, + "tx_lut_11": { + "desc": "TX gain table, index 11", + "pa_gain": 3, + "mix_gain": 9, + "rf_power": 20, + "dig_gain": 0 + }, + "tx_lut_12": { + "desc": "TX gain table, index 12", + "pa_gain": 3, + "mix_gain": 10, + "rf_power": 23, + "dig_gain": 0 + }, + "tx_lut_13": { + "desc": "TX gain table, index 13", + "pa_gain": 3, + "mix_gain": 11, + "rf_power": 25, + "dig_gain": 0 + }, + "tx_lut_14": { + "desc": "TX gain table, index 14", + "pa_gain": 3, + "mix_gain": 12, + "rf_power": 26, + "dig_gain": 0 + }, + "tx_lut_15": { + "desc": "TX gain table, index 15", + "pa_gain": 3, + "mix_gain": 14, + "rf_power": 27, + "dig_gain": 0 + } + }, + "gateway_conf": { + "gateway_ID": "0000000000000000", + /* change with default server address/ports, or overwrite in local_conf.json */ + "server_address": "router.as.thethings.network", + "serv_port_up": 1700, + "serv_port_down": 1700, + /* adjust the following parameters for your network */ + "keepalive_interval": 10, + "stat_interval": 30, + "push_timeout_ms": 100, + /* forward only valid packets */ + "forward_crc_valid": true, + "forward_crc_error": false, + "forward_crc_disabled": false, + /* gps enable */ + "gps": true, + "gps_tty_path": "/dev/ttyAMA0", + "fake_gps": false, + "ref_latitude": 10, + "ref_longitude": 20, + "ref_altitude": -1, + "autoquit_threshold": 6 + } + +} + diff --git a/lora/global_conf/serial/global_conf.kr_920_923.json b/lora/global_conf/serial/global_conf.kr_920_923.json new file mode 100644 index 0000000..0de1f78 --- /dev/null +++ b/lora/global_conf/serial/global_conf.kr_920_923.json @@ -0,0 +1,217 @@ +{ + "SX1301_conf": { + "lorawan_public": true, + "clksrc": 1, + "clksrc_desc": "radio_1 provides clock to concentrator for most devices except MultiTech. For MultiTech set to 0.", + "antenna_gain": 0, + "antenna_gain_desc": "antenna gain, in dBi", + "radio_0": { + "enable": true, + "type": "SX1257", + "freq": 922400000, + "rssi_offset": -166.0, + "tx_enable": true, + "tx_freq_min": 920900000, + "tx_freq_max": 923300000 + }, + "radio_1": { + "enable": true, + "type": "SX1257", + "freq": 923000000, + "rssi_offset": -166.0, + "tx_enable": false + }, + "chan_multiSF_0": { + "desc": "Lora MAC, 125kHz, all SF, 922.1 MHz", + "enable": true, + "radio": 0, + "if": -300000 + }, + "chan_multiSF_1": { + "desc": "Lora MAC, 125kHz, all SF, 922.3 MHz", + "enable": true, + "radio": 0, + "if": -100000 + }, + "chan_multiSF_2": { + "desc": "Lora MAC, 125kHz, all SF, 922.5 MHz", + "enable": true, + "radio": 0, + "if": 100000 + }, + "chan_multiSF_3": { + "desc": "Lora MAC, 125kHz, all SF, 922.7 MHz", + "enable": true, + "radio": 0, + "if": 300000 + }, + "chan_multiSF_4": { + "desc": "Lora MAC, 125kHz, all SF, 922.9 MHz", + "enable": true, + "radio": 1, + "if": -100000 + }, + "chan_multiSF_5": { + "desc": "Lora MAC, 125kHz, all SF, 923.1 MHz", + "enable": true, + "radio": 1, + "if": 100000 + }, + "chan_multiSF_6": { + "desc": "Lora MAC, 125kHz, all SF, 923.3 MHz", + "enable": true, + "radio": 1, + "if": 300000 + }, + "chan_multiSF_7": { + "desc": "disabled", + "enable": false + }, + "chan_Lora_std": { + "desc": "disabled", + "enable": false + }, + "chan_FSK": { + "desc": "disabled", + "enable": false + }, + "tx_lut_0": { + "desc": "TX gain table, index 0", + "pa_gain": 0, + "mix_gain": 8, + "rf_power": -6, + "dig_gain": 0 + }, + "tx_lut_1": { + "desc": "TX gain table, index 1", + "pa_gain": 0, + "mix_gain": 10, + "rf_power": -3, + "dig_gain": 0 + }, + "tx_lut_2": { + "desc": "TX gain table, index 2", + "pa_gain": 0, + "mix_gain": 12, + "rf_power": 0, + "dig_gain": 0 + }, + "tx_lut_3": { + "desc": "TX gain table, index 3", + "pa_gain": 1, + "mix_gain": 8, + "rf_power": 3, + "dig_gain": 0 + }, + "tx_lut_4": { + "desc": "TX gain table, index 4", + "pa_gain": 1, + "mix_gain": 10, + "rf_power": 6, + "dig_gain": 0 + }, + "tx_lut_5": { + "desc": "TX gain table, index 5", + "pa_gain": 1, + "mix_gain": 12, + "rf_power": 10, + "dig_gain": 0 + }, + "tx_lut_6": { + "desc": "TX gain table, index 6", + "pa_gain": 1, + "mix_gain": 13, + "rf_power": 11, + "dig_gain": 0 + }, + "tx_lut_7": { + "desc": "TX gain table, index 7", + "pa_gain": 2, + "mix_gain": 9, + "rf_power": 12, + "dig_gain": 0 + }, + "tx_lut_8": { + "desc": "TX gain table, index 8", + "pa_gain": 1, + "mix_gain": 15, + "rf_power": 13, + "dig_gain": 0 + }, + "tx_lut_9": { + "desc": "TX gain table, index 9", + "pa_gain": 2, + "mix_gain": 10, + "rf_power": 14, + "dig_gain": 0 + }, + "tx_lut_10": { + "desc": "TX gain table, index 10", + "pa_gain": 2, + "mix_gain": 11, + "rf_power": 16, + "dig_gain": 0 + }, + "tx_lut_11": { + "desc": "TX gain table, index 11", + "pa_gain": 3, + "mix_gain": 9, + "rf_power": 20, + "dig_gain": 0 + }, + "tx_lut_12": { + "desc": "TX gain table, index 12", + "pa_gain": 3, + "mix_gain": 10, + "rf_power": 23, + "dig_gain": 0 + }, + "tx_lut_13": { + "desc": "TX gain table, index 13", + "pa_gain": 3, + "mix_gain": 11, + "rf_power": 25, + "dig_gain": 0 + }, + "tx_lut_14": { + "desc": "TX gain table, index 14", + "pa_gain": 3, + "mix_gain": 12, + "rf_power": 26, + "dig_gain": 0 + }, + "tx_lut_15": { + "desc": "TX gain table, index 15", + "pa_gain": 3, + "mix_gain": 14, + "rf_power": 27, + "dig_gain": 0 + } + }, + "gateway_conf": { + "gateway_ID": "0000000000000000", + /* change with default server address/ports, or overwrite in local_conf.json */ + "server_address": "router.kr.thethings.network", + "serv_port_up": 1700, + "serv_port_down": 1700, + /* adjust the following parameters for your network */ + "keepalive_interval": 10, + "stat_interval": 30, + "push_timeout_ms": 100, + /* forward only valid packets */ + "forward_crc_valid": true, + "forward_crc_error": false, + "forward_crc_disabled": false, + /* gps enable */ + "gps": true, + "gps_tty_path": "/dev/ttyAMA0", + "fake_gps": false, + "ref_latitude": 10, + "ref_longitude": 20, + "ref_altitude": -1, + "autoquit_threshold": 6 + } + +} + + diff --git a/lora/global_conf/serial/global_conf.ru_864_870.json b/lora/global_conf/serial/global_conf.ru_864_870.json new file mode 100644 index 0000000..16c54ae --- /dev/null +++ b/lora/global_conf/serial/global_conf.ru_864_870.json @@ -0,0 +1,216 @@ +{ + "SX1301_conf": { + "lorawan_public": true, + "clksrc": 1, + "clksrc_desc": "radio_1 provides clock to concentrator for most devices except MultiTech. For MultiTech set to 0.", + "antenna_gain": 0, + "antenna_gain_desc": "antenna gain, in dBi", + "radio_0": { + "enable": true, + "type": "SX1257", + "freq": 864500000, + "rssi_offset": -166.0, + "tx_enable": true, + "tx_freq_min": 863000000, + "tx_freq_max": 870000000 + }, + "radio_1": { + "enable": true, + "type": "SX1257", + "freq": 869000000, + "rssi_offset": -166.0, + "tx_enable": false + }, + "chan_multiSF_0": { + "desc": "Lora MAC, 125kHz, all SF, 864.1 MHz", + "enable": true, + "radio": 0, + "if": -400000 + }, + "chan_multiSF_1": { + "desc": "Lora MAC, 125kHz, all SF, 864.3 MHz", + "enable": true, + "radio": 0, + "if": -200000 + }, + "chan_multiSF_2": { + "desc": "Lora MAC, 125kHz, all SF, 864.5 MHz", + "enable": true, + "radio": 0, + "if": 0 + }, + "chan_multiSF_3": { + "desc": "Lora MAC, 125kHz, all SF, 864.7 MHz", + "enable": true, + "radio": 0, + "if": 200000 + }, + "chan_multiSF_4": { + "desc": "Lora MAC, 125kHz, all SF, 864.9 MHz", + "enable": true, + "radio": 0, + "if": 400000 + }, + "chan_multiSF_5": { + "desc": "Lora MAC, 125kHz, all SF, 868.9 MHz", + "enable": true, + "radio": 1, + "if": -100000 + }, + "chan_multiSF_6": { + "desc": "Lora MAC, 125kHz, all SF, 869.1 MHz", + "enable": true, + "radio": 1, + "if": 100000 + }, + "chan_multiSF_7": { + "desc": "disabled", + "enable": false + }, + "chan_Lora_std": { + "desc": "disabled", + "enable": false + }, + "chan_FSK": { + "desc": "disabled", + "enable": false + }, + "tx_lut_0": { + "desc": "TX gain table, index 0", + "pa_gain": 0, + "mix_gain": 8, + "rf_power": -6, + "dig_gain": 0 + }, + "tx_lut_1": { + "desc": "TX gain table, index 1", + "pa_gain": 0, + "mix_gain": 10, + "rf_power": -3, + "dig_gain": 0 + }, + "tx_lut_2": { + "desc": "TX gain table, index 2", + "pa_gain": 0, + "mix_gain": 12, + "rf_power": 0, + "dig_gain": 0 + }, + "tx_lut_3": { + "desc": "TX gain table, index 3", + "pa_gain": 1, + "mix_gain": 8, + "rf_power": 3, + "dig_gain": 0 + }, + "tx_lut_4": { + "desc": "TX gain table, index 4", + "pa_gain": 1, + "mix_gain": 10, + "rf_power": 6, + "dig_gain": 0 + }, + "tx_lut_5": { + "desc": "TX gain table, index 5", + "pa_gain": 1, + "mix_gain": 12, + "rf_power": 10, + "dig_gain": 0 + }, + "tx_lut_6": { + "desc": "TX gain table, index 6", + "pa_gain": 1, + "mix_gain": 13, + "rf_power": 11, + "dig_gain": 0 + }, + "tx_lut_7": { + "desc": "TX gain table, index 7", + "pa_gain": 2, + "mix_gain": 9, + "rf_power": 12, + "dig_gain": 0 + }, + "tx_lut_8": { + "desc": "TX gain table, index 8", + "pa_gain": 1, + "mix_gain": 15, + "rf_power": 13, + "dig_gain": 0 + }, + "tx_lut_9": { + "desc": "TX gain table, index 9", + "pa_gain": 2, + "mix_gain": 10, + "rf_power": 14, + "dig_gain": 0 + }, + "tx_lut_10": { + "desc": "TX gain table, index 10", + "pa_gain": 2, + "mix_gain": 11, + "rf_power": 16, + "dig_gain": 0 + }, + "tx_lut_11": { + "desc": "TX gain table, index 11", + "pa_gain": 3, + "mix_gain": 9, + "rf_power": 20, + "dig_gain": 0 + }, + "tx_lut_12": { + "desc": "TX gain table, index 12", + "pa_gain": 3, + "mix_gain": 10, + "rf_power": 23, + "dig_gain": 0 + }, + "tx_lut_13": { + "desc": "TX gain table, index 13", + "pa_gain": 3, + "mix_gain": 11, + "rf_power": 25, + "dig_gain": 0 + }, + "tx_lut_14": { + "desc": "TX gain table, index 14", + "pa_gain": 3, + "mix_gain": 12, + "rf_power": 26, + "dig_gain": 0 + }, + "tx_lut_15": { + "desc": "TX gain table, index 15", + "pa_gain": 3, + "mix_gain": 14, + "rf_power": 27, + "dig_gain": 0 + } + }, + "gateway_conf": { + "gateway_ID": "0000000000000000", + /* change with default server address/ports, or overwrite in local_conf.json */ + "server_address": "router.ru.thethings.network", + "serv_port_up": 1700, + "serv_port_down": 1700, + /* adjust the following parameters for your network */ + "keepalive_interval": 10, + "stat_interval": 30, + "push_timeout_ms": 100, + /* forward only valid packets */ + "forward_crc_valid": true, + "forward_crc_error": false, + "forward_crc_disabled": false, + /* gps enable */ + "gps": true, + "gps_tty_path": "/dev/ttyAMA0", + "fake_gps": false, + "ref_latitude": 10, + "ref_longitude": 20, + "ref_altitude": -1, + "autoquit_threshold": 6 + } + +} + diff --git a/lora/global_conf/serial/global_conf.us_902_928.json b/lora/global_conf/serial/global_conf.us_902_928.json new file mode 100644 index 0000000..3e3308d --- /dev/null +++ b/lora/global_conf/serial/global_conf.us_902_928.json @@ -0,0 +1,212 @@ +{ + "SX1301_conf": { + "lorawan_public": true, + "clksrc": 1, + "antenna_gain": 0, + "radio_0": { + "enable": true, + "type": "SX1257", + "freq": 904300000, + "rssi_offset": -166.0, + "tx_enable": true, + "tx_freq_min": 902000000, + "tx_freq_max": 928000000 + }, + "radio_1": { + "enable": true, + "type": "SX1257", + "freq": 905000000, + "rssi_offset": -166.0, + "tx_enable": false + }, + "chan_multiSF_0": { + "enable": true, + "radio": 0, + "if": -400000 + }, + "chan_multiSF_1": { + "enable": true, + "radio": 0, + "if": -200000 + }, + "chan_multiSF_2": { + "enable": true, + "radio": 0, + "if": 0 + }, + "chan_multiSF_3": { + "enable": true, + "radio": 0, + "if": 200000 + }, + "chan_multiSF_4": { + "enable": true, + "radio": 1, + "if": -300000 + }, + "chan_multiSF_5": { + "enable": true, + "radio": 1, + "if": -100000 + }, + "chan_multiSF_6": { + "enable": true, + "radio": 1, + "if": 100000 + }, + "chan_multiSF_7": { + "enable": true, + "radio": 1, + "if": 300000 + }, + "chan_Lora_std": { + "enable": true, + "radio": 0, + "if": 300000, + "bandwidth": 500000, + "spread_factor": 8 + }, + "chan_FSK": { + "enable": false, + "radio": 0, + "if": 300000, + "bandwidth": 250000, + "datarate": 100000 + }, + "tx_lut_0": { + "desc": "TX gain table, index 0", + "pa_gain": 0, + "mix_gain": 8, + "rf_power": -6, + "dig_gain": 0 + }, + "tx_lut_1": { + "desc": "TX gain table, index 1", + "pa_gain": 0, + "mix_gain": 10, + "rf_power": -3, + "dig_gain": 0 + }, + "tx_lut_2": { + "desc": "TX gain table, index 2", + "pa_gain": 0, + "mix_gain": 12, + "rf_power": 0, + "dig_gain": 0 + }, + "tx_lut_3": { + "desc": "TX gain table, index 3", + "pa_gain": 1, + "mix_gain": 8, + "rf_power": 3, + "dig_gain": 0 + }, + "tx_lut_4": { + "desc": "TX gain table, index 4", + "pa_gain": 1, + "mix_gain": 10, + "rf_power": 6, + "dig_gain": 0 + }, + "tx_lut_5": { + "desc": "TX gain table, index 5", + "pa_gain": 1, + "mix_gain": 12, + "rf_power": 10, + "dig_gain": 0 + }, + "tx_lut_6": { + "desc": "TX gain table, index 6", + "pa_gain": 1, + "mix_gain": 13, + "rf_power": 11, + "dig_gain": 0 + }, + "tx_lut_7": { + "desc": "TX gain table, index 7", + "pa_gain": 2, + "mix_gain": 9, + "rf_power": 12, + "dig_gain": 0 + }, + "tx_lut_8": { + "desc": "TX gain table, index 8", + "pa_gain": 1, + "mix_gain": 15, + "rf_power": 13, + "dig_gain": 0 + }, + "tx_lut_9": { + "desc": "TX gain table, index 9", + "pa_gain": 2, + "mix_gain": 10, + "rf_power": 14, + "dig_gain": 0 + }, + "tx_lut_10": { + "desc": "TX gain table, index 10", + "pa_gain": 2, + "mix_gain": 11, + "rf_power": 16, + "dig_gain": 0 + }, + "tx_lut_11": { + "desc": "TX gain table, index 11", + "pa_gain": 3, + "mix_gain": 9, + "rf_power": 20, + "dig_gain": 0 + }, + "tx_lut_12": { + "desc": "TX gain table, index 12", + "pa_gain": 3, + "mix_gain": 10, + "rf_power": 23, + "dig_gain": 0 + }, + "tx_lut_13": { + "desc": "TX gain table, index 13", + "pa_gain": 3, + "mix_gain": 11, + "rf_power": 25, + "dig_gain": 0 + }, + "tx_lut_14": { + "desc": "TX gain table, index 14", + "pa_gain": 3, + "mix_gain": 12, + "rf_power": 26, + "dig_gain": 0 + }, + "tx_lut_15": { + "desc": "TX gain table, index 15", + "pa_gain": 3, + "mix_gain": 14, + "rf_power": 27, + "dig_gain": 0 + } + }, + "gateway_conf": { + "gateway_ID": "0000000000000000", + /* change with default server address/ports, or overwrite in local_conf.json */ + "server_address": "router.us.thethings.network", + "serv_port_up": 1700, + "serv_port_down": 1700, + /* adjust the following parameters for your network */ + "keepalive_interval": 10, + "stat_interval": 30, + "push_timeout_ms": 100, + /* forward only valid packets */ + "forward_crc_valid": true, + "forward_crc_error": false, + "forward_crc_disabled": false, + /* gps enable */ + "gps": true, + "gps_tty_path": "/dev/ttyAMA0", + "fake_gps": false, + "ref_latitude": 10, + "ref_longitude": 20, + "ref_altitude": -1, + "autoquit_threshold": 6 + } +} diff --git a/lora/install.sh b/lora/install.sh new file mode 100755 index 0000000..57e882d --- /dev/null +++ b/lora/install.sh @@ -0,0 +1,54 @@ +#!/bin/bash + +# Stop on the first sign of trouble +set -e + +SCRIPT_COMMON_FILE=$(pwd)/../rak/rak/shell_script/rak_common.sh + +if [ $UID != 0 ]; then + echo_error "Operation not permitted. Forgot sudo?" + exit 1 +fi + +source $SCRIPT_COMMON_FILE + +mkdir -p /usr/local/rak/lora + +RAK_GW_MODEL=`do_get_gw_model` + +mkdir /opt/ttn-gateway -p + +if [ "${RAK_GW_MODEL}" = "RAK7243" ]; then + pushd rak7243 + ./install.sh + LORA_DIR_TMP=rak7243 + popd +elif [ "${RAK_GW_MODEL}" = "RAK2245" ] || [ "${RAK_GW_MODEL}" = "RAK831" ]; then + pushd rak2245 + ./install.sh + LORA_DIR_TMP=rak2245 + popd +elif [ "${RAK_GW_MODEL}" = "RAK2247" ] || [ "${RAK_GW_MODEL}" = "RAK833" ]; then + pushd rak2247 + ./install.sh + LORA_DIR_TMP=rak2247 + popd +else + : +fi + +cp $LORA_DIR_TMP/lora_gateway /opt/ttn-gateway/ -rf +cp $LORA_DIR_TMP/packet_forwarder /opt/ttn-gateway/ -rf + + +cp ./update_gwid.sh /opt/ttn-gateway/packet_forwarder/lora_pkt_fwd/update_gwid.sh +cp ./start.sh /opt/ttn-gateway/packet_forwarder/lora_pkt_fwd/start.sh +cp ./set_eui.sh /opt/ttn-gateway/packet_forwarder/lora_pkt_fwd/set_eui.sh +cp ttn-gateway.service /lib/systemd/system/ttn-gateway.service +cp /opt/ttn-gateway/packet_forwarder/lora_pkt_fwd/global_conf/global_conf.eu_863_870.json \ + /opt/ttn-gateway/packet_forwarder/lora_pkt_fwd/global_conf.json +sed -i "s/^.*server_address.*$/\t\"server_address\": \"127.0.0.1\",/" \ + /opt/ttn-gateway/packet_forwarder/lora_pkt_fwd/global_conf.json + +systemctl enable ttn-gateway.service + diff --git a/lora/print_lora_log.sh b/lora/print_lora_log.sh new file mode 100755 index 0000000..0111a7e --- /dev/null +++ b/lora/print_lora_log.sh @@ -0,0 +1,16 @@ +#!/bin/bash +cd /opt/ttn-gateway/lora_gateway/util_pkt_logger + +cp /opt/ttn-gateway/packet_forwarder/lora_pkt_fwd/*.json . + +rm *.csv -rf + +./util_pkt_logger & + +sleep 5 + +log_filename=`find ./ -name "*.csv" -type f` + +echo "------------------------log file name: ${log_filename}-----------------" +echo "---------------------------log------------------------------" +tail -n 100 -f ${log_filename} diff --git a/lora/rak2245/global_conf/global_conf.as_923.json b/lora/rak2245/global_conf/global_conf.as_923.json new file mode 100644 index 0000000..59e98ff --- /dev/null +++ b/lora/rak2245/global_conf/global_conf.as_923.json @@ -0,0 +1,225 @@ +{ + "SX1301_conf": { + "lorawan_public": true, + "clksrc": 1, + "clksrc_desc": "radio_1 provides clock to concentrator for most devices except MultiTech. For MultiTech set to 0.", + "antenna_gain": 0, + "antenna_gain_desc": "antenna gain, in dBi", + "radio_0": { + "enable": true, + "type": "SX1257", + "freq": 923600000, + "rssi_offset": -166.0, + "tx_enable": true, + "tx_freq_min": 923200000, + "tx_freq_max": 925000000 + }, + "radio_1": { + "enable": true, + "type": "SX1257", + "freq": 924600000, + "rssi_offset": -166.0, + "tx_enable": false + }, + "chan_multiSF_0": { + "desc": "Lora MAC, 125kHz, all SF, 923.2 MHz", + "enable": true, + "radio": 0, + "if": -400000 + }, + "chan_multiSF_1": { + "desc": "Lora MAC, 125kHz, all SF, 923.4 MHz", + "enable": true, + "radio": 0, + "if": -200000 + }, + "chan_multiSF_2": { + "desc": "Lora MAC, 125kHz, all SF, 923.6 MHz", + "enable": true, + "radio": 0, + "if": 0 + }, + "chan_multiSF_3": { + "desc": "Lora MAC, 125kHz, all SF, 923.8 MHz", + "enable": true, + "radio": 0, + "if": 200000 + }, + "chan_multiSF_4": { + "desc": "Lora MAC, 125kHz, all SF, 924.0 MHz", + "enable": true, + "radio": 0, + "if": 400000 + }, + "chan_multiSF_5": { + "desc": "Lora MAC, 125kHz, all SF, 924.2 MHz", + "enable": true, + "radio": 1, + "if": -400000 + }, + "chan_multiSF_6": { + "desc": "Lora MAC, 125kHz, all SF, 924.4 MHz", + "enable": true, + "radio": 1, + "if": -200000 + }, + "chan_multiSF_7": { + "desc": "Lora MAC, 125kHz, all SF, 924.6 MHz", + "enable": true, + "radio": 1, + "if": 0 + }, + "chan_Lora_std": { + "desc": "Lora MAC, 250kHz, SF7, 924.5 MHz", + "enable": true, + "radio": 1, + "if": -100000, + "bandwidth": 250000, + "spread_factor": 7 + }, + "chan_FSK": { + "desc": "FSK 50kbps, 924.8 MHz", + "enable": true, + "radio": 1, + "if": 200000, + "bandwidth": 125000, + "datarate": 50000 + }, + "tx_lut_0": { + "desc": "TX gain table, index 0", + "pa_gain": 0, + "mix_gain": 8, + "rf_power": -6, + "dig_gain": 0 + }, + "tx_lut_1": { + "desc": "TX gain table, index 1", + "pa_gain": 0, + "mix_gain": 10, + "rf_power": -3, + "dig_gain": 0 + }, + "tx_lut_2": { + "desc": "TX gain table, index 2", + "pa_gain": 0, + "mix_gain": 12, + "rf_power": 0, + "dig_gain": 0 + }, + "tx_lut_3": { + "desc": "TX gain table, index 3", + "pa_gain": 1, + "mix_gain": 8, + "rf_power": 3, + "dig_gain": 0 + }, + "tx_lut_4": { + "desc": "TX gain table, index 4", + "pa_gain": 1, + "mix_gain": 10, + "rf_power": 6, + "dig_gain": 0 + }, + "tx_lut_5": { + "desc": "TX gain table, index 5", + "pa_gain": 1, + "mix_gain": 12, + "rf_power": 10, + "dig_gain": 0 + }, + "tx_lut_6": { + "desc": "TX gain table, index 6", + "pa_gain": 1, + "mix_gain": 13, + "rf_power": 11, + "dig_gain": 0 + }, + "tx_lut_7": { + "desc": "TX gain table, index 7", + "pa_gain": 2, + "mix_gain": 9, + "rf_power": 12, + "dig_gain": 0 + }, + "tx_lut_8": { + "desc": "TX gain table, index 8", + "pa_gain": 1, + "mix_gain": 15, + "rf_power": 13, + "dig_gain": 0 + }, + "tx_lut_9": { + "desc": "TX gain table, index 9", + "pa_gain": 2, + "mix_gain": 10, + "rf_power": 14, + "dig_gain": 0 + }, + "tx_lut_10": { + "desc": "TX gain table, index 10", + "pa_gain": 2, + "mix_gain": 11, + "rf_power": 16, + "dig_gain": 0 + }, + "tx_lut_11": { + "desc": "TX gain table, index 11", + "pa_gain": 3, + "mix_gain": 9, + "rf_power": 20, + "dig_gain": 0 + }, + "tx_lut_12": { + "desc": "TX gain table, index 12", + "pa_gain": 3, + "mix_gain": 10, + "rf_power": 23, + "dig_gain": 0 + }, + "tx_lut_13": { + "desc": "TX gain table, index 13", + "pa_gain": 3, + "mix_gain": 11, + "rf_power": 25, + "dig_gain": 0 + }, + "tx_lut_14": { + "desc": "TX gain table, index 14", + "pa_gain": 3, + "mix_gain": 12, + "rf_power": 26, + "dig_gain": 0 + }, + "tx_lut_15": { + "desc": "TX gain table, index 15", + "pa_gain": 3, + "mix_gain": 14, + "rf_power": 27, + "dig_gain": 0 + } + }, + "gateway_conf": { + "gateway_ID": "0000000000000000", + /* change with default server address/ports, or overwrite in local_conf.json */ + "server_address": "router.as2.thethings.network", + "serv_port_up": 1700, + "serv_port_down": 1700, + /* adjust the following parameters for your network */ + "keepalive_interval": 10, + "stat_interval": 30, + "push_timeout_ms": 100, + /* forward only valid packets */ + "forward_crc_valid": true, + "forward_crc_error": false, + "forward_crc_disabled": false, + /* gps enable */ + "gps": true, + "gps_tty_path": "/dev/ttyAMA0", + "fake_gps": false, + "ref_latitude": 10, + "ref_longitude": 20, + "ref_altitude": -1, + "autoquit_threshold": 6 + } + +} diff --git a/lora/rak2245/global_conf/global_conf.au_915_928.json b/lora/rak2245/global_conf/global_conf.au_915_928.json new file mode 100644 index 0000000..2147f05 --- /dev/null +++ b/lora/rak2245/global_conf/global_conf.au_915_928.json @@ -0,0 +1,222 @@ +{ + "SX1301_conf": { + "lorawan_public": true, + "clksrc": 1, + "clksrc_desc": "radio_1 provides clock to concentrator for most devices except MultiTech. For MultiTech set to 0.", + "antenna_gain": 0, + "antenna_gain_desc": "antenna gain, in dBi", + "radio_0": { + "enable": true, + "type": "SX1257", + "freq": 917200000, + "rssi_offset": -166.0, + "tx_enable": true, + "tx_freq_min": 915000000, + "tx_freq_max": 928000000 + }, + "radio_1": { + "enable": true, + "type": "SX1257", + "freq": 917900000, + "rssi_offset": -166.0, + "tx_enable": false + }, + "chan_multiSF_0": { + "desc": "Lora MAC, 125kHz, all SF, 916.8 MHz", + "enable": true, + "radio": 0, + "if": -400000 + }, + "chan_multiSF_1": { + "desc": "Lora MAC, 125kHz, all SF, 917.0 MHz", + "enable": true, + "radio": 0, + "if": -200000 + }, + "chan_multiSF_2": { + "desc": "Lora MAC, 125kHz, all SF, 917.2 MHz", + "enable": true, + "radio": 0, + "if": 0 + }, + "chan_multiSF_3": { + "desc": "Lora MAC, 125kHz, all SF, 917.4 MHz", + "enable": true, + "radio": 0, + "if": 200000 + }, + "chan_multiSF_4": { + "desc": "Lora MAC, 125kHz, all SF, 917.6 MHz", + "enable": true, + "radio": 1, + "if": -300000 + }, + "chan_multiSF_5": { + "desc": "Lora MAC, 125kHz, all SF, 917.8 MHz", + "enable": true, + "radio": 1, + "if": -100000 + }, + "chan_multiSF_6": { + "desc": "Lora MAC, 125kHz, all SF, 918.0 MHz", + "enable": true, + "radio": 1, + "if": 100000 + }, + "chan_multiSF_7": { + "desc": "Lora MAC, 125kHz, all SF, 918.2 MHz", + "enable": true, + "radio": 1, + "if": 300000 + }, + "chan_Lora_std": { + "desc": "Lora MAC, 500kHz, SF8, 917.5 MHz", + "enable": true, + "radio": 0, + "if": 300000, + "bandwidth": 500000, + "spread_factor": 8 + }, + "chan_FSK": { + "desc": "disabled", + "enable": false + }, + "tx_lut_0": { + "desc": "TX gain table, index 0", + "pa_gain": 0, + "mix_gain": 8, + "rf_power": -6, + "dig_gain": 0 + }, + "tx_lut_1": { + "desc": "TX gain table, index 1", + "pa_gain": 0, + "mix_gain": 10, + "rf_power": -3, + "dig_gain": 0 + }, + "tx_lut_2": { + "desc": "TX gain table, index 2", + "pa_gain": 0, + "mix_gain": 12, + "rf_power": 0, + "dig_gain": 0 + }, + "tx_lut_3": { + "desc": "TX gain table, index 3", + "pa_gain": 1, + "mix_gain": 8, + "rf_power": 3, + "dig_gain": 0 + }, + "tx_lut_4": { + "desc": "TX gain table, index 4", + "pa_gain": 1, + "mix_gain": 10, + "rf_power": 6, + "dig_gain": 0 + }, + "tx_lut_5": { + "desc": "TX gain table, index 5", + "pa_gain": 1, + "mix_gain": 12, + "rf_power": 10, + "dig_gain": 0 + }, + "tx_lut_6": { + "desc": "TX gain table, index 6", + "pa_gain": 1, + "mix_gain": 13, + "rf_power": 11, + "dig_gain": 0 + }, + "tx_lut_7": { + "desc": "TX gain table, index 7", + "pa_gain": 2, + "mix_gain": 9, + "rf_power": 12, + "dig_gain": 0 + }, + "tx_lut_8": { + "desc": "TX gain table, index 8", + "pa_gain": 1, + "mix_gain": 15, + "rf_power": 13, + "dig_gain": 0 + }, + "tx_lut_9": { + "desc": "TX gain table, index 9", + "pa_gain": 2, + "mix_gain": 10, + "rf_power": 14, + "dig_gain": 0 + }, + "tx_lut_10": { + "desc": "TX gain table, index 10", + "pa_gain": 2, + "mix_gain": 11, + "rf_power": 16, + "dig_gain": 0 + }, + "tx_lut_11": { + "desc": "TX gain table, index 11", + "pa_gain": 3, + "mix_gain": 9, + "rf_power": 20, + "dig_gain": 0 + }, + "tx_lut_12": { + "desc": "TX gain table, index 12", + "pa_gain": 3, + "mix_gain": 10, + "rf_power": 23, + "dig_gain": 0 + }, + "tx_lut_13": { + "desc": "TX gain table, index 13", + "pa_gain": 3, + "mix_gain": 11, + "rf_power": 25, + "dig_gain": 0 + }, + "tx_lut_14": { + "desc": "TX gain table, index 14", + "pa_gain": 3, + "mix_gain": 12, + "rf_power": 26, + "dig_gain": 0 + }, + "tx_lut_15": { + "desc": "TX gain table, index 15", + "pa_gain": 3, + "mix_gain": 14, + "rf_power": 27, + "dig_gain": 0 + } + }, + "gateway_conf": { + "gateway_ID": "0000000000000000", + /* change with default server address/ports, or overwrite in local_conf.json */ + "server_address": "router.au.thethings.network", + "serv_port_up": 1700, + "serv_port_down": 1700, + /* adjust the following parameters for your network */ + "keepalive_interval": 10, + "stat_interval": 30, + "push_timeout_ms": 100, + /* forward only valid packets */ + "forward_crc_valid": true, + "forward_crc_error": false, + "forward_crc_disabled": false, + /* gps enable */ + "gps": true, + "gps_tty_path": "/dev/ttyAMA0", + "fake_gps": false, + "ref_latitude": 10, + "ref_longitude": 20, + "ref_altitude": -1, + "autoquit_threshold": 6 + } + +} + diff --git a/lora/rak2245/global_conf/global_conf.cn_470_510.json b/lora/rak2245/global_conf/global_conf.cn_470_510.json new file mode 100644 index 0000000..4fd248c --- /dev/null +++ b/lora/rak2245/global_conf/global_conf.cn_470_510.json @@ -0,0 +1,217 @@ +{ + "SX1301_conf": { + "lorawan_public": true, + "clksrc": 1, + "clksrc_desc": "radio_1 provides clock to concentrator for most devices except MultiTech. For MultiTech set to 0.", + "antenna_gain": 0, + "antenna_gain_desc": "antenna gain, in dBi", + "radio_0": { + "enable": true, + "type": "SX1255", + "freq": 486600000, + "rssi_offset": -176.0, + "tx_enable": true, + "tx_freq_min": 470000000, + "tx_freq_max": 510000000 + }, + "radio_1": { + "enable": true, + "type": "SX1255", + "freq": 487400000, + "rssi_offset": -176.0, + "tx_enable": false + }, + "chan_multiSF_0": { + "desc": "Lora MAC, 125kHz, all SF, 487.1 MHz", + "enable": true, + "radio": 1, + "if": -300000 + }, + "chan_multiSF_1": { + "desc": "Lora MAC, 125kHz, all SF, 487.3 MHz", + "enable": true, + "radio": 1, + "if": -100000 + }, + "chan_multiSF_2": { + "desc": "Lora MAC, 125kHz, all SF, 487.5 MHz", + "enable": true, + "radio": 1, + "if": 100000 + }, + "chan_multiSF_3": { + "desc": "Lora MAC, 125kHz, all SF, 487.7 MHz", + "enable": true, + "radio": 1, + "if": 300000 + }, + "chan_multiSF_4": { + "desc": "Lora MAC, 125kHz, all SF, 486.3 MHz", + "enable": true, + "radio": 0, + "if": -300000 + }, + "chan_multiSF_5": { + "desc": "Lora MAC, 125kHz, all SF, 486.5 MHz", + "enable": true, + "radio": 0, + "if": -100000 + }, + "chan_multiSF_6": { + "desc": "Lora MAC, 125kHz, all SF, 486.7 MHz", + "enable": true, + "radio": 0, + "if": 100000 + }, + "chan_multiSF_7": { + "desc": "Lora MAC, 125kHz, all SF, 486.9 MHz", + "enable": true, + "radio": 0, + "if": 300000 + }, + "chan_Lora_std": { + "desc": "disabled", + "enable": false + }, + "chan_FSK": { + "desc": "disabled", + "enable": false + }, + "tx_lut_0": { + "desc": "TX gain table, index 0", + "pa_gain": 0, + "mix_gain": 8, + "rf_power": -6, + "dig_gain": 0 + }, + "tx_lut_1": { + "desc": "TX gain table, index 1", + "pa_gain": 0, + "mix_gain": 10, + "rf_power": -3, + "dig_gain": 0 + }, + "tx_lut_2": { + "desc": "TX gain table, index 2", + "pa_gain": 0, + "mix_gain": 12, + "rf_power": 0, + "dig_gain": 0 + }, + "tx_lut_3": { + "desc": "TX gain table, index 3", + "pa_gain": 1, + "mix_gain": 8, + "rf_power": 3, + "dig_gain": 0 + }, + "tx_lut_4": { + "desc": "TX gain table, index 4", + "pa_gain": 1, + "mix_gain": 10, + "rf_power": 6, + "dig_gain": 0 + }, + "tx_lut_5": { + "desc": "TX gain table, index 5", + "pa_gain": 1, + "mix_gain": 12, + "rf_power": 10, + "dig_gain": 0 + }, + "tx_lut_6": { + "desc": "TX gain table, index 6", + "pa_gain": 1, + "mix_gain": 13, + "rf_power": 11, + "dig_gain": 0 + }, + "tx_lut_7": { + "desc": "TX gain table, index 7", + "pa_gain": 2, + "mix_gain": 9, + "rf_power": 12, + "dig_gain": 0 + }, + "tx_lut_8": { + "desc": "TX gain table, index 8", + "pa_gain": 1, + "mix_gain": 15, + "rf_power": 13, + "dig_gain": 0 + }, + "tx_lut_9": { + "desc": "TX gain table, index 9", + "pa_gain": 2, + "mix_gain": 10, + "rf_power": 14, + "dig_gain": 0 + }, + "tx_lut_10": { + "desc": "TX gain table, index 10", + "pa_gain": 2, + "mix_gain": 11, + "rf_power": 16, + "dig_gain": 0 + }, + "tx_lut_11": { + "desc": "TX gain table, index 11", + "pa_gain": 3, + "mix_gain": 9, + "rf_power": 20, + "dig_gain": 0 + }, + "tx_lut_12": { + "desc": "TX gain table, index 12", + "pa_gain": 3, + "mix_gain": 10, + "rf_power": 23, + "dig_gain": 0 + }, + "tx_lut_13": { + "desc": "TX gain table, index 13", + "pa_gain": 3, + "mix_gain": 11, + "rf_power": 25, + "dig_gain": 0 + }, + "tx_lut_14": { + "desc": "TX gain table, index 14", + "pa_gain": 3, + "mix_gain": 12, + "rf_power": 26, + "dig_gain": 0 + }, + "tx_lut_15": { + "desc": "TX gain table, index 15", + "pa_gain": 3, + "mix_gain": 14, + "rf_power": 27, + "dig_gain": 0 + } + }, + "gateway_conf": { + "gateway_ID": "0000000000000000", + /* change with default server address/ports, or overwrite in local_conf.json */ + "server_address": "router.cn.thethings.network", + "serv_port_up": 1700, + "serv_port_down": 1700, + /* adjust the following parameters for your network */ + "keepalive_interval": 10, + "stat_interval": 30, + "push_timeout_ms": 100, + /* forward only valid packets */ + "forward_crc_valid": true, + "forward_crc_error": false, + "forward_crc_disabled": false, + /* gps enable */ + "gps": true, + "gps_tty_path": "/dev/ttyAMA0", + "fake_gps": false, + "ref_latitude": 10, + "ref_longitude": 20, + "ref_altitude": -1, + "autoquit_threshold": 6 + } +} + diff --git a/lora/rak2245/global_conf/global_conf.eu_433.json b/lora/rak2245/global_conf/global_conf.eu_433.json new file mode 100644 index 0000000..a44eb75 --- /dev/null +++ b/lora/rak2245/global_conf/global_conf.eu_433.json @@ -0,0 +1,224 @@ +{ + + "SX1301_conf": { + "lorawan_public": true, + "clksrc": 1, /* radio_1 provides clock to concentrator */ + "antenna_gain": 0, /* antenna gain, in dBi */ + "radio_0": { + "enable": true, + "type": "SX1255", + "freq": 434375000, + "rssi_offset": -166.0, + "tx_enable": true, + "tx_freq_min": 433050000, + "tx_freq_max": 434900000 + }, + "radio_1": { + "enable": true, + "type": "SX1255", + "freq": 433575000, + "rssi_offset": -166.0, + "tx_enable": false + }, + "chan_multiSF_0": { + /* Lora MAC channel, 125kHz, all SF, 433.175 MHz */ + "enable": true, + "radio": 1, + "if": -400000 + }, + "chan_multiSF_1": { + /* Lora MAC channel, 125kHz, all SF, 433.375 MHz */ + "enable": true, + "radio": 1, + "if": -200000 + }, + "chan_multiSF_2": { + /* Lora MAC channel, 125kHz, all SF, 433.575 MHz */ + "enable": true, + "radio": 1, + "if": 0 + }, + "chan_multiSF_3": { + /* Lora MAC channel, 125kHz, all SF, 433.975 MHz */ + "enable": true, + "radio": 0, + "if": -400000 + }, + "chan_multiSF_4": { + /* Lora MAC channel, 125kHz, all SF, 434.175 MHz */ + "enable": true, + "radio": 0, + "if": -200000 + }, + "chan_multiSF_5": { + /* Lora MAC channel, 125kHz, all SF, 434.375 MHz */ + "enable": true, + "radio": 0, + "if": 0 + }, + "chan_multiSF_6": { + /* Lora MAC channel, 125kHz, all SF, 434.575 MHz */ + "enable": true, + "radio": 0, + "if": 200000 + }, + "chan_multiSF_7": { + /* Lora MAC channel, 125kHz, all SF, 434.775 MHz */ + "enable": true, + "radio": 0, + "if": 400000 + }, + "chan_Lora_std": { + /* Lora MAC channel, 250kHz, SF7, 434.175 MHz */ + "enable": true, + "radio": 1, + "if": -200000, + "bandwidth": 250000, + "spread_factor": 7 + }, + "chan_FSK": { + /* FSK 50kbps channel, 434.675 MHz */ + "enable": true, + "radio": 1, + "if": 300000, + "bandwidth": 125000, + "datarate": 50000 + }, + "tx_lut_0": { + /* TX gain table, index 0 */ + "pa_gain": 0, + "mix_gain": 8, + "rf_power": -6, + "dig_gain": 0 + }, + "tx_lut_1": { + /* TX gain table, index 1 */ + "pa_gain": 0, + "mix_gain": 10, + "rf_power": -3, + "dig_gain": 0 + }, + "tx_lut_2": { + /* TX gain table, index 2 */ + "pa_gain": 0, + "mix_gain": 12, + "rf_power": 0, + "dig_gain": 0 + }, + "tx_lut_3": { + /* TX gain table, index 3 */ + "pa_gain": 1, + "mix_gain": 8, + "rf_power": 3, + "dig_gain": 0 + }, + "tx_lut_4": { + /* TX gain table, index 4 */ + "pa_gain": 1, + "mix_gain": 10, + "rf_power": 6, + "dig_gain": 0 + }, + "tx_lut_5": { + /* TX gain table, index 5 */ + "pa_gain": 1, + "mix_gain": 12, + "rf_power": 10, + "dig_gain": 0 + }, + "tx_lut_6": { + /* TX gain table, index 6 */ + "pa_gain": 1, + "mix_gain": 13, + "rf_power": 11, + "dig_gain": 0 + }, + "tx_lut_7": { + /* TX gain table, index 7 */ + "pa_gain": 2, + "mix_gain": 9, + "rf_power": 12, + "dig_gain": 0 + }, + "tx_lut_8": { + /* TX gain table, index 8 */ + "pa_gain": 1, + "mix_gain": 15, + "rf_power": 13, + "dig_gain": 0 + }, + "tx_lut_9": { + /* TX gain table, index 9 */ + "pa_gain": 2, + "mix_gain": 10, + "rf_power": 14, + "dig_gain": 0 + }, + "tx_lut_10": { + /* TX gain table, index 10 */ + "pa_gain": 2, + "mix_gain": 11, + "rf_power": 16, + "dig_gain": 0 + }, + "tx_lut_11": { + /* TX gain table, index 11 */ + "pa_gain": 3, + "mix_gain": 9, + "rf_power": 20, + "dig_gain": 0 + }, + "tx_lut_12": { + "desc": "TX gain table, index 12", + "pa_gain": 3, + "mix_gain": 10, + "rf_power": 23, + "dig_gain": 0 + }, + "tx_lut_13": { + "desc": "TX gain table, index 13", + "pa_gain": 3, + "mix_gain": 11, + "rf_power": 25, + "dig_gain": 0 + }, + "tx_lut_14": { + "desc": "TX gain table, index 14", + "pa_gain": 3, + "mix_gain": 12, + "rf_power": 26, + "dig_gain": 0 + }, + "tx_lut_15": { + "desc": "TX gain table, index 15", + "pa_gain": 3, + "mix_gain": 14, + "rf_power": 27, + "dig_gain": 0 + } + }, + "gateway_conf": { + "gateway_ID": "0000000000000000", + /* change with default server address/ports, or overwrite in local_conf.json */ + "server_address": "localhost", + "serv_port_up": 1700, + "serv_port_down": 1700, + /* adjust the following parameters for your network */ + "keepalive_interval": 10, + "stat_interval": 30, + "push_timeout_ms": 100, + /* forward only valid packets */ + "forward_crc_valid": true, + "forward_crc_error": false, + "forward_crc_disabled": false, + /* gps enable */ + "gps": true, + "gps_tty_path": "/dev/ttyAMA0", + "fake_gps": false, + "ref_latitude": 10, + "ref_longitude": 20, + "ref_altitude": -1, + "autoquit_threshold": 6 + } +} + diff --git a/lora/rak2245/global_conf/global_conf.eu_863_870.json b/lora/rak2245/global_conf/global_conf.eu_863_870.json new file mode 100644 index 0000000..2383035 --- /dev/null +++ b/lora/rak2245/global_conf/global_conf.eu_863_870.json @@ -0,0 +1,200 @@ +{ + "SX1301_conf": { + "lorawan_public": true, + "clksrc": 1, + "antenna_gain": 0, + "radio_0": { + "enable": true, + "type": "SX1257", + "freq": 867500000, + "rssi_offset": -166.0, + "tx_enable": true, + "tx_freq_min": 863000000, + "tx_freq_max": 870000000 + }, + "radio_1": { + "enable": true, + "type": "SX1257", + "freq": 868500000, + "rssi_offset": -166.0, + "tx_enable": false + }, + "chan_multiSF_0": { + "enable": true, + "radio": 1, + "if": -400000 + }, + "chan_multiSF_1": { + "enable": true, + "radio": 1, + "if": -200000 + }, + "chan_multiSF_2": { + "enable": true, + "radio": 1, + "if": 0 + }, + "chan_multiSF_3": { + "enable": true, + "radio": 0, + "if": -400000 + }, + "chan_multiSF_4": { + "enable": true, + "radio": 0, + "if": -200000 + }, + "chan_multiSF_5": { + "enable": true, + "radio": 0, + "if": 0 + }, + "chan_multiSF_6": { + "enable": true, + "radio": 0, + "if": 200000 + }, + "chan_multiSF_7": { + "enable": true, + "radio": 0, + "if": 400000 + }, + "chan_Lora_std": { + "enable": true, + "radio": 1, + "if": -200000, + "bandwidth": 250000, + "spread_factor": 7 + }, + "chan_FSK": { + "enable": true, + "radio": 1, + "if": 300000, + "bandwidth": 125000, + "datarate": 50000 + }, + "tx_lut_0": { + "pa_gain": 0, + "mix_gain": 8, + "rf_power": -6, + "dig_gain": 0 + }, + "tx_lut_1": { + "pa_gain": 0, + "mix_gain": 10, + "rf_power": -3, + "dig_gain": 0 + }, + "tx_lut_2": { + "pa_gain": 0, + "mix_gain": 12, + "rf_power": 0, + "dig_gain": 0 + }, + "tx_lut_3": { + "pa_gain": 1, + "mix_gain": 8, + "rf_power": 3, + "dig_gain": 0 + }, + "tx_lut_4": { + "pa_gain": 1, + "mix_gain": 10, + "rf_power": 6, + "dig_gain": 0 + }, + "tx_lut_5": { + "pa_gain": 1, + "mix_gain": 12, + "rf_power": 10, + "dig_gain": 0 + }, + "tx_lut_6": { + "pa_gain": 1, + "mix_gain": 13, + "rf_power": 11, + "dig_gain": 0 + }, + "tx_lut_7": { + "pa_gain": 2, + "mix_gain": 9, + "rf_power": 12, + "dig_gain": 0 + }, + "tx_lut_8": { + "pa_gain": 1, + "mix_gain": 15, + "rf_power": 13, + "dig_gain": 0 + }, + "tx_lut_9": { + "pa_gain": 2, + "mix_gain": 10, + "rf_power": 14, + "dig_gain": 0 + }, + "tx_lut_10": { + "pa_gain": 2, + "mix_gain": 11, + "rf_power": 16, + "dig_gain": 0 + }, + "tx_lut_11": { + "pa_gain": 3, + "mix_gain": 9, + "rf_power": 20, + "dig_gain": 0 + }, + "tx_lut_12": { + "desc": "TX gain table, index 12", + "pa_gain": 3, + "mix_gain": 10, + "rf_power": 23, + "dig_gain": 0 + }, + "tx_lut_13": { + "desc": "TX gain table, index 13", + "pa_gain": 3, + "mix_gain": 11, + "rf_power": 25, + "dig_gain": 0 + }, + "tx_lut_14": { + "desc": "TX gain table, index 14", + "pa_gain": 3, + "mix_gain": 12, + "rf_power": 26, + "dig_gain": 0 + }, + "tx_lut_15": { + "desc": "TX gain table, index 15", + "pa_gain": 3, + "mix_gain": 14, + "rf_power": 27, + "dig_gain": 0 + } + }, + "gateway_conf": { + "gateway_ID": "0000000000000000", + /* change with default server address/ports, or overwrite in local_conf.json */ + "server_address": "router.eu.thethings.network", + "serv_port_up": 1700, + "serv_port_down": 1700, + /* adjust the following parameters for your network */ + "keepalive_interval": 10, + "stat_interval": 30, + "push_timeout_ms": 100, + /* forward only valid packets */ + "forward_crc_valid": true, + "forward_crc_error": false, + "forward_crc_disabled": false, + /* gps enable */ + "gps": true, + "gps_tty_path": "/dev/ttyAMA0", + "fake_gps": false, + "ref_latitude": 10, + "ref_longitude": 20, + "ref_altitude": -1, + "autoquit_threshold": 6 + } +} diff --git a/lora/rak2245/global_conf/global_conf.in_865_867.json b/lora/rak2245/global_conf/global_conf.in_865_867.json new file mode 100644 index 0000000..4d6559e --- /dev/null +++ b/lora/rak2245/global_conf/global_conf.in_865_867.json @@ -0,0 +1,209 @@ +{ + "SX1301_conf": { + "lorawan_public": true, + "clksrc": 1, + "clksrc_desc": "radio_1 provides clock to concentrator for most devices except MultiTech. For MultiTech set to 0.", + "antenna_gain": 0, + "antenna_gain_desc": "antenna gain, in dBi", + "radio_0": { + "enable": true, + "type": "SX1257", + "freq": 865200000, + "rssi_offset": -166.0, + "tx_enable": true, + "tx_freq_min": 865000000, + "tx_freq_max": 867000000, + "tx_notch_freq": 129000 + }, + "radio_1": { + "enable": true, + "type": "SX1257", + "freq": 866385000, + "rssi_offset": -166.0, + "tx_enable": false + }, + "chan_multiSF_0": { + "desc": "Lora MAC, 125kHz, all SF, 865.0625 MHz", + "enable": true, + "radio": 0, + "if": -137500 + }, + "chan_multiSF_1": { + "desc": "Lora MAC, 125kHz, all SF, 865.4025 MHz", + "enable": true, + "radio": 0, + "if": 202500 + }, + "chan_multiSF_2": { + "desc": "Lora MAC, 125kHz, all SF, 865.9850 MHz", + "enable": true, + "radio": 1, + "if": -400000 + }, + "chan_multiSF_3": { + "desc": "disabled", + "enable": false + }, + "chan_multiSF_4": { + "desc": "disabled", + "enable": false + }, + "chan_multiSF_5": { + "desc": "disabled", + "enable": false + }, + "chan_multiSF_6": { + "desc": "disabled", + "enable": false + }, + "chan_multiSF_7": { + "desc": "disabled", + "enable": false + }, + "chan_Lora_std": { + "desc": "disabled", + "enable": false + }, + "chan_FSK": { + "desc": "disabled", + "enable": false + }, + "tx_lut_0": { + "desc": "TX gain table, index 0", + "pa_gain": 0, + "mix_gain": 8, + "rf_power": -6, + "dig_gain": 0 + }, + "tx_lut_1": { + "desc": "TX gain table, index 1", + "pa_gain": 0, + "mix_gain": 10, + "rf_power": -3, + "dig_gain": 0 + }, + "tx_lut_2": { + "desc": "TX gain table, index 2", + "pa_gain": 0, + "mix_gain": 12, + "rf_power": 0, + "dig_gain": 0 + }, + "tx_lut_3": { + "desc": "TX gain table, index 3", + "pa_gain": 1, + "mix_gain": 8, + "rf_power": 3, + "dig_gain": 0 + }, + "tx_lut_4": { + "desc": "TX gain table, index 4", + "pa_gain": 1, + "mix_gain": 10, + "rf_power": 6, + "dig_gain": 0 + }, + "tx_lut_5": { + "desc": "TX gain table, index 5", + "pa_gain": 1, + "mix_gain": 12, + "rf_power": 10, + "dig_gain": 0 + }, + "tx_lut_6": { + "desc": "TX gain table, index 6", + "pa_gain": 1, + "mix_gain": 13, + "rf_power": 11, + "dig_gain": 0 + }, + "tx_lut_7": { + "desc": "TX gain table, index 7", + "pa_gain": 2, + "mix_gain": 9, + "rf_power": 12, + "dig_gain": 0 + }, + "tx_lut_8": { + "desc": "TX gain table, index 8", + "pa_gain": 1, + "mix_gain": 15, + "rf_power": 13, + "dig_gain": 0 + }, + "tx_lut_9": { + "desc": "TX gain table, index 9", + "pa_gain": 2, + "mix_gain": 10, + "rf_power": 14, + "dig_gain": 0 + }, + "tx_lut_10": { + "desc": "TX gain table, index 10", + "pa_gain": 2, + "mix_gain": 11, + "rf_power": 16, + "dig_gain": 0 + }, + "tx_lut_11": { + "desc": "TX gain table, index 11", + "pa_gain": 3, + "mix_gain": 9, + "rf_power": 20, + "dig_gain": 0 + }, + "tx_lut_12": { + "desc": "TX gain table, index 12", + "pa_gain": 3, + "mix_gain": 10, + "rf_power": 23, + "dig_gain": 0 + }, + "tx_lut_13": { + "desc": "TX gain table, index 13", + "pa_gain": 3, + "mix_gain": 11, + "rf_power": 25, + "dig_gain": 0 + }, + "tx_lut_14": { + "desc": "TX gain table, index 14", + "pa_gain": 3, + "mix_gain": 12, + "rf_power": 26, + "dig_gain": 0 + }, + "tx_lut_15": { + "desc": "TX gain table, index 15", + "pa_gain": 3, + "mix_gain": 14, + "rf_power": 27, + "dig_gain": 0 + } + }, + "gateway_conf": { + "gateway_ID": "0000000000000000", + /* change with default server address/ports, or overwrite in local_conf.json */ + "server_address": "router.as.thethings.network", + "serv_port_up": 1700, + "serv_port_down": 1700, + /* adjust the following parameters for your network */ + "keepalive_interval": 10, + "stat_interval": 30, + "push_timeout_ms": 100, + /* forward only valid packets */ + "forward_crc_valid": true, + "forward_crc_error": false, + "forward_crc_disabled": false, + /* gps enable */ + "gps": true, + "gps_tty_path": "/dev/ttyAMA0", + "fake_gps": false, + "ref_latitude": 10, + "ref_longitude": 20, + "ref_altitude": -1, + "autoquit_threshold": 6 + } + +} + diff --git a/lora/rak2245/global_conf/global_conf.kr_920_923.json b/lora/rak2245/global_conf/global_conf.kr_920_923.json new file mode 100644 index 0000000..0de1f78 --- /dev/null +++ b/lora/rak2245/global_conf/global_conf.kr_920_923.json @@ -0,0 +1,217 @@ +{ + "SX1301_conf": { + "lorawan_public": true, + "clksrc": 1, + "clksrc_desc": "radio_1 provides clock to concentrator for most devices except MultiTech. For MultiTech set to 0.", + "antenna_gain": 0, + "antenna_gain_desc": "antenna gain, in dBi", + "radio_0": { + "enable": true, + "type": "SX1257", + "freq": 922400000, + "rssi_offset": -166.0, + "tx_enable": true, + "tx_freq_min": 920900000, + "tx_freq_max": 923300000 + }, + "radio_1": { + "enable": true, + "type": "SX1257", + "freq": 923000000, + "rssi_offset": -166.0, + "tx_enable": false + }, + "chan_multiSF_0": { + "desc": "Lora MAC, 125kHz, all SF, 922.1 MHz", + "enable": true, + "radio": 0, + "if": -300000 + }, + "chan_multiSF_1": { + "desc": "Lora MAC, 125kHz, all SF, 922.3 MHz", + "enable": true, + "radio": 0, + "if": -100000 + }, + "chan_multiSF_2": { + "desc": "Lora MAC, 125kHz, all SF, 922.5 MHz", + "enable": true, + "radio": 0, + "if": 100000 + }, + "chan_multiSF_3": { + "desc": "Lora MAC, 125kHz, all SF, 922.7 MHz", + "enable": true, + "radio": 0, + "if": 300000 + }, + "chan_multiSF_4": { + "desc": "Lora MAC, 125kHz, all SF, 922.9 MHz", + "enable": true, + "radio": 1, + "if": -100000 + }, + "chan_multiSF_5": { + "desc": "Lora MAC, 125kHz, all SF, 923.1 MHz", + "enable": true, + "radio": 1, + "if": 100000 + }, + "chan_multiSF_6": { + "desc": "Lora MAC, 125kHz, all SF, 923.3 MHz", + "enable": true, + "radio": 1, + "if": 300000 + }, + "chan_multiSF_7": { + "desc": "disabled", + "enable": false + }, + "chan_Lora_std": { + "desc": "disabled", + "enable": false + }, + "chan_FSK": { + "desc": "disabled", + "enable": false + }, + "tx_lut_0": { + "desc": "TX gain table, index 0", + "pa_gain": 0, + "mix_gain": 8, + "rf_power": -6, + "dig_gain": 0 + }, + "tx_lut_1": { + "desc": "TX gain table, index 1", + "pa_gain": 0, + "mix_gain": 10, + "rf_power": -3, + "dig_gain": 0 + }, + "tx_lut_2": { + "desc": "TX gain table, index 2", + "pa_gain": 0, + "mix_gain": 12, + "rf_power": 0, + "dig_gain": 0 + }, + "tx_lut_3": { + "desc": "TX gain table, index 3", + "pa_gain": 1, + "mix_gain": 8, + "rf_power": 3, + "dig_gain": 0 + }, + "tx_lut_4": { + "desc": "TX gain table, index 4", + "pa_gain": 1, + "mix_gain": 10, + "rf_power": 6, + "dig_gain": 0 + }, + "tx_lut_5": { + "desc": "TX gain table, index 5", + "pa_gain": 1, + "mix_gain": 12, + "rf_power": 10, + "dig_gain": 0 + }, + "tx_lut_6": { + "desc": "TX gain table, index 6", + "pa_gain": 1, + "mix_gain": 13, + "rf_power": 11, + "dig_gain": 0 + }, + "tx_lut_7": { + "desc": "TX gain table, index 7", + "pa_gain": 2, + "mix_gain": 9, + "rf_power": 12, + "dig_gain": 0 + }, + "tx_lut_8": { + "desc": "TX gain table, index 8", + "pa_gain": 1, + "mix_gain": 15, + "rf_power": 13, + "dig_gain": 0 + }, + "tx_lut_9": { + "desc": "TX gain table, index 9", + "pa_gain": 2, + "mix_gain": 10, + "rf_power": 14, + "dig_gain": 0 + }, + "tx_lut_10": { + "desc": "TX gain table, index 10", + "pa_gain": 2, + "mix_gain": 11, + "rf_power": 16, + "dig_gain": 0 + }, + "tx_lut_11": { + "desc": "TX gain table, index 11", + "pa_gain": 3, + "mix_gain": 9, + "rf_power": 20, + "dig_gain": 0 + }, + "tx_lut_12": { + "desc": "TX gain table, index 12", + "pa_gain": 3, + "mix_gain": 10, + "rf_power": 23, + "dig_gain": 0 + }, + "tx_lut_13": { + "desc": "TX gain table, index 13", + "pa_gain": 3, + "mix_gain": 11, + "rf_power": 25, + "dig_gain": 0 + }, + "tx_lut_14": { + "desc": "TX gain table, index 14", + "pa_gain": 3, + "mix_gain": 12, + "rf_power": 26, + "dig_gain": 0 + }, + "tx_lut_15": { + "desc": "TX gain table, index 15", + "pa_gain": 3, + "mix_gain": 14, + "rf_power": 27, + "dig_gain": 0 + } + }, + "gateway_conf": { + "gateway_ID": "0000000000000000", + /* change with default server address/ports, or overwrite in local_conf.json */ + "server_address": "router.kr.thethings.network", + "serv_port_up": 1700, + "serv_port_down": 1700, + /* adjust the following parameters for your network */ + "keepalive_interval": 10, + "stat_interval": 30, + "push_timeout_ms": 100, + /* forward only valid packets */ + "forward_crc_valid": true, + "forward_crc_error": false, + "forward_crc_disabled": false, + /* gps enable */ + "gps": true, + "gps_tty_path": "/dev/ttyAMA0", + "fake_gps": false, + "ref_latitude": 10, + "ref_longitude": 20, + "ref_altitude": -1, + "autoquit_threshold": 6 + } + +} + + diff --git a/lora/rak2245/global_conf/global_conf.ru_864_870.json b/lora/rak2245/global_conf/global_conf.ru_864_870.json new file mode 100644 index 0000000..16c54ae --- /dev/null +++ b/lora/rak2245/global_conf/global_conf.ru_864_870.json @@ -0,0 +1,216 @@ +{ + "SX1301_conf": { + "lorawan_public": true, + "clksrc": 1, + "clksrc_desc": "radio_1 provides clock to concentrator for most devices except MultiTech. For MultiTech set to 0.", + "antenna_gain": 0, + "antenna_gain_desc": "antenna gain, in dBi", + "radio_0": { + "enable": true, + "type": "SX1257", + "freq": 864500000, + "rssi_offset": -166.0, + "tx_enable": true, + "tx_freq_min": 863000000, + "tx_freq_max": 870000000 + }, + "radio_1": { + "enable": true, + "type": "SX1257", + "freq": 869000000, + "rssi_offset": -166.0, + "tx_enable": false + }, + "chan_multiSF_0": { + "desc": "Lora MAC, 125kHz, all SF, 864.1 MHz", + "enable": true, + "radio": 0, + "if": -400000 + }, + "chan_multiSF_1": { + "desc": "Lora MAC, 125kHz, all SF, 864.3 MHz", + "enable": true, + "radio": 0, + "if": -200000 + }, + "chan_multiSF_2": { + "desc": "Lora MAC, 125kHz, all SF, 864.5 MHz", + "enable": true, + "radio": 0, + "if": 0 + }, + "chan_multiSF_3": { + "desc": "Lora MAC, 125kHz, all SF, 864.7 MHz", + "enable": true, + "radio": 0, + "if": 200000 + }, + "chan_multiSF_4": { + "desc": "Lora MAC, 125kHz, all SF, 864.9 MHz", + "enable": true, + "radio": 0, + "if": 400000 + }, + "chan_multiSF_5": { + "desc": "Lora MAC, 125kHz, all SF, 868.9 MHz", + "enable": true, + "radio": 1, + "if": -100000 + }, + "chan_multiSF_6": { + "desc": "Lora MAC, 125kHz, all SF, 869.1 MHz", + "enable": true, + "radio": 1, + "if": 100000 + }, + "chan_multiSF_7": { + "desc": "disabled", + "enable": false + }, + "chan_Lora_std": { + "desc": "disabled", + "enable": false + }, + "chan_FSK": { + "desc": "disabled", + "enable": false + }, + "tx_lut_0": { + "desc": "TX gain table, index 0", + "pa_gain": 0, + "mix_gain": 8, + "rf_power": -6, + "dig_gain": 0 + }, + "tx_lut_1": { + "desc": "TX gain table, index 1", + "pa_gain": 0, + "mix_gain": 10, + "rf_power": -3, + "dig_gain": 0 + }, + "tx_lut_2": { + "desc": "TX gain table, index 2", + "pa_gain": 0, + "mix_gain": 12, + "rf_power": 0, + "dig_gain": 0 + }, + "tx_lut_3": { + "desc": "TX gain table, index 3", + "pa_gain": 1, + "mix_gain": 8, + "rf_power": 3, + "dig_gain": 0 + }, + "tx_lut_4": { + "desc": "TX gain table, index 4", + "pa_gain": 1, + "mix_gain": 10, + "rf_power": 6, + "dig_gain": 0 + }, + "tx_lut_5": { + "desc": "TX gain table, index 5", + "pa_gain": 1, + "mix_gain": 12, + "rf_power": 10, + "dig_gain": 0 + }, + "tx_lut_6": { + "desc": "TX gain table, index 6", + "pa_gain": 1, + "mix_gain": 13, + "rf_power": 11, + "dig_gain": 0 + }, + "tx_lut_7": { + "desc": "TX gain table, index 7", + "pa_gain": 2, + "mix_gain": 9, + "rf_power": 12, + "dig_gain": 0 + }, + "tx_lut_8": { + "desc": "TX gain table, index 8", + "pa_gain": 1, + "mix_gain": 15, + "rf_power": 13, + "dig_gain": 0 + }, + "tx_lut_9": { + "desc": "TX gain table, index 9", + "pa_gain": 2, + "mix_gain": 10, + "rf_power": 14, + "dig_gain": 0 + }, + "tx_lut_10": { + "desc": "TX gain table, index 10", + "pa_gain": 2, + "mix_gain": 11, + "rf_power": 16, + "dig_gain": 0 + }, + "tx_lut_11": { + "desc": "TX gain table, index 11", + "pa_gain": 3, + "mix_gain": 9, + "rf_power": 20, + "dig_gain": 0 + }, + "tx_lut_12": { + "desc": "TX gain table, index 12", + "pa_gain": 3, + "mix_gain": 10, + "rf_power": 23, + "dig_gain": 0 + }, + "tx_lut_13": { + "desc": "TX gain table, index 13", + "pa_gain": 3, + "mix_gain": 11, + "rf_power": 25, + "dig_gain": 0 + }, + "tx_lut_14": { + "desc": "TX gain table, index 14", + "pa_gain": 3, + "mix_gain": 12, + "rf_power": 26, + "dig_gain": 0 + }, + "tx_lut_15": { + "desc": "TX gain table, index 15", + "pa_gain": 3, + "mix_gain": 14, + "rf_power": 27, + "dig_gain": 0 + } + }, + "gateway_conf": { + "gateway_ID": "0000000000000000", + /* change with default server address/ports, or overwrite in local_conf.json */ + "server_address": "router.ru.thethings.network", + "serv_port_up": 1700, + "serv_port_down": 1700, + /* adjust the following parameters for your network */ + "keepalive_interval": 10, + "stat_interval": 30, + "push_timeout_ms": 100, + /* forward only valid packets */ + "forward_crc_valid": true, + "forward_crc_error": false, + "forward_crc_disabled": false, + /* gps enable */ + "gps": true, + "gps_tty_path": "/dev/ttyAMA0", + "fake_gps": false, + "ref_latitude": 10, + "ref_longitude": 20, + "ref_altitude": -1, + "autoquit_threshold": 6 + } + +} + diff --git a/lora/rak2245/global_conf/global_conf.us_902_928.json b/lora/rak2245/global_conf/global_conf.us_902_928.json new file mode 100644 index 0000000..3e3308d --- /dev/null +++ b/lora/rak2245/global_conf/global_conf.us_902_928.json @@ -0,0 +1,212 @@ +{ + "SX1301_conf": { + "lorawan_public": true, + "clksrc": 1, + "antenna_gain": 0, + "radio_0": { + "enable": true, + "type": "SX1257", + "freq": 904300000, + "rssi_offset": -166.0, + "tx_enable": true, + "tx_freq_min": 902000000, + "tx_freq_max": 928000000 + }, + "radio_1": { + "enable": true, + "type": "SX1257", + "freq": 905000000, + "rssi_offset": -166.0, + "tx_enable": false + }, + "chan_multiSF_0": { + "enable": true, + "radio": 0, + "if": -400000 + }, + "chan_multiSF_1": { + "enable": true, + "radio": 0, + "if": -200000 + }, + "chan_multiSF_2": { + "enable": true, + "radio": 0, + "if": 0 + }, + "chan_multiSF_3": { + "enable": true, + "radio": 0, + "if": 200000 + }, + "chan_multiSF_4": { + "enable": true, + "radio": 1, + "if": -300000 + }, + "chan_multiSF_5": { + "enable": true, + "radio": 1, + "if": -100000 + }, + "chan_multiSF_6": { + "enable": true, + "radio": 1, + "if": 100000 + }, + "chan_multiSF_7": { + "enable": true, + "radio": 1, + "if": 300000 + }, + "chan_Lora_std": { + "enable": true, + "radio": 0, + "if": 300000, + "bandwidth": 500000, + "spread_factor": 8 + }, + "chan_FSK": { + "enable": false, + "radio": 0, + "if": 300000, + "bandwidth": 250000, + "datarate": 100000 + }, + "tx_lut_0": { + "desc": "TX gain table, index 0", + "pa_gain": 0, + "mix_gain": 8, + "rf_power": -6, + "dig_gain": 0 + }, + "tx_lut_1": { + "desc": "TX gain table, index 1", + "pa_gain": 0, + "mix_gain": 10, + "rf_power": -3, + "dig_gain": 0 + }, + "tx_lut_2": { + "desc": "TX gain table, index 2", + "pa_gain": 0, + "mix_gain": 12, + "rf_power": 0, + "dig_gain": 0 + }, + "tx_lut_3": { + "desc": "TX gain table, index 3", + "pa_gain": 1, + "mix_gain": 8, + "rf_power": 3, + "dig_gain": 0 + }, + "tx_lut_4": { + "desc": "TX gain table, index 4", + "pa_gain": 1, + "mix_gain": 10, + "rf_power": 6, + "dig_gain": 0 + }, + "tx_lut_5": { + "desc": "TX gain table, index 5", + "pa_gain": 1, + "mix_gain": 12, + "rf_power": 10, + "dig_gain": 0 + }, + "tx_lut_6": { + "desc": "TX gain table, index 6", + "pa_gain": 1, + "mix_gain": 13, + "rf_power": 11, + "dig_gain": 0 + }, + "tx_lut_7": { + "desc": "TX gain table, index 7", + "pa_gain": 2, + "mix_gain": 9, + "rf_power": 12, + "dig_gain": 0 + }, + "tx_lut_8": { + "desc": "TX gain table, index 8", + "pa_gain": 1, + "mix_gain": 15, + "rf_power": 13, + "dig_gain": 0 + }, + "tx_lut_9": { + "desc": "TX gain table, index 9", + "pa_gain": 2, + "mix_gain": 10, + "rf_power": 14, + "dig_gain": 0 + }, + "tx_lut_10": { + "desc": "TX gain table, index 10", + "pa_gain": 2, + "mix_gain": 11, + "rf_power": 16, + "dig_gain": 0 + }, + "tx_lut_11": { + "desc": "TX gain table, index 11", + "pa_gain": 3, + "mix_gain": 9, + "rf_power": 20, + "dig_gain": 0 + }, + "tx_lut_12": { + "desc": "TX gain table, index 12", + "pa_gain": 3, + "mix_gain": 10, + "rf_power": 23, + "dig_gain": 0 + }, + "tx_lut_13": { + "desc": "TX gain table, index 13", + "pa_gain": 3, + "mix_gain": 11, + "rf_power": 25, + "dig_gain": 0 + }, + "tx_lut_14": { + "desc": "TX gain table, index 14", + "pa_gain": 3, + "mix_gain": 12, + "rf_power": 26, + "dig_gain": 0 + }, + "tx_lut_15": { + "desc": "TX gain table, index 15", + "pa_gain": 3, + "mix_gain": 14, + "rf_power": 27, + "dig_gain": 0 + } + }, + "gateway_conf": { + "gateway_ID": "0000000000000000", + /* change with default server address/ports, or overwrite in local_conf.json */ + "server_address": "router.us.thethings.network", + "serv_port_up": 1700, + "serv_port_down": 1700, + /* adjust the following parameters for your network */ + "keepalive_interval": 10, + "stat_interval": 30, + "push_timeout_ms": 100, + /* forward only valid packets */ + "forward_crc_valid": true, + "forward_crc_error": false, + "forward_crc_disabled": false, + /* gps enable */ + "gps": true, + "gps_tty_path": "/dev/ttyAMA0", + "fake_gps": false, + "ref_latitude": 10, + "ref_longitude": 20, + "ref_altitude": -1, + "autoquit_threshold": 6 + } +} diff --git a/lora/rak2245/install.sh b/lora/rak2245/install.sh new file mode 100755 index 0000000..9c1d27c --- /dev/null +++ b/lora/rak2245/install.sh @@ -0,0 +1,96 @@ +#!/bin/bash + +# Stop on the first sign of trouble +set -e + +if [ $UID != 0 ]; then + echo "ERROR: Operation not permitted. Forgot sudo?" + exit 1 +fi + +SCRIPT_DIR=$(pwd) + +# Request gateway configuration data +# There are two ways to do it, manually specify everything +# or rely on the gateway EUI and retrieve settings files from remote (recommended) +echo "Gateway configuration:" + +# Try to get gateway ID from MAC address +# First try eth0, if that does not exist, try wlan0 (for RPi Zero) +GATEWAY_EUI_NIC="eth0" +if [[ `grep "$GATEWAY_EUI_NIC" /proc/net/dev` == "" ]]; then + GATEWAY_EUI_NIC="wlan0" +fi + +if [[ `grep "$GATEWAY_EUI_NIC" /proc/net/dev` == "" ]]; then + echo "ERROR: No network interface found. Cannot set gateway ID." + exit 1 +fi + +if [ ! -d "/usr/local/rak/bin" ]; then mkdir "/usr/local/rak/bin" -p ; fi + +GATEWAY_EUI=$(ip link show $GATEWAY_EUI_NIC | awk '/ether/ {print $2}' | awk -F\: '{print $1$2$3"FFFE"$4$5$6}') +GATEWAY_EUI=${GATEWAY_EUI^^} # toupper + +echo "Detected EUI $GATEWAY_EUI from $GATEWAY_EUI_NIC" + +if [[ $NEW_HOSTNAME == "" ]]; then NEW_HOSTNAME="rak-gateway"; fi + +if [[ $GATEWAY_LAT == "" ]]; then GATEWAY_LAT=0; fi + +if [[ $GATEWAY_LON == "" ]]; then GATEWAY_LON=0; fi + +if [[ $GATEWAY_ALT == "" ]]; then GATEWAY_ALT=0; fi + + +# Change hostname if needed +CURRENT_HOSTNAME=$(hostname) + +if [[ $NEW_HOSTNAME != $CURRENT_HOSTNAME ]]; then + echo "Updating hostname to '$NEW_HOSTNAME'..." + hostname $NEW_HOSTNAME + echo $NEW_HOSTNAME > /etc/hostname + sed -i "s/$CURRENT_HOSTNAME/$NEW_HOSTNAME/" /etc/hosts +fi + +# Install LoRaWAN packet forwarder repositories +INSTALL_DIR="./" +if [ ! -d "$INSTALL_DIR" ]; then mkdir $INSTALL_DIR; fi +pushd $INSTALL_DIR + +# Build LoRa gateway app + +if [ ! -d lora_gateway ]; then + git clone https://github.com/Lora-net/lora_gateway.git +fi + +pushd lora_gateway + +cp $SCRIPT_DIR/library.cfg ./libloragw/library.cfg +cp $SCRIPT_DIR/loragw_spi.native.c ./libloragw/src/loragw_spi.native.c +make + +popd + +# Build packet forwarder + +if [ ! -d packet_forwarder ]; then + git clone https://github.com/Lora-net/packet_forwarder.git +fi + +pushd packet_forwarder + +cp $SCRIPT_DIR/lora_pkt_fwd.c ./lora_pkt_fwd/src/lora_pkt_fwd.c + +make + +popd + +LOCAL_CONFIG_FILE=$INSTALL_DIR/packet_forwarder/lora_pkt_fwd/local_conf.json +echo -e "{\n\t\"gateway_conf\": {\n\t\t\"gateway_ID\": \"$GATEWAY_EUI\" \n\t}\n}" >$LOCAL_CONFIG_FILE + +echo "Gateway EUI is: $GATEWAY_EUI" +echo "The hostname is: $NEW_HOSTNAME" + +cp global_conf $INSTALL_DIR/packet_forwarder/lora_pkt_fwd/ -rf + diff --git a/lora/rak2245/library.cfg b/lora/rak2245/library.cfg new file mode 100644 index 0000000..9455ee6 --- /dev/null +++ b/lora/rak2245/library.cfg @@ -0,0 +1,18 @@ +# That file will be included in the Makefile files that have hardware dependencies + +### 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 + +CFG_SPI= native + +PLATFORM= imst_rpi + +#CFG_BAND= au915 + +DEBUG_AUX= 0 +DEBUG_SPI= 0 +DEBUG_REG= 0 +DEBUG_HAL= 0 +DEBUG_LBT= 0 +DEBUG_GPS= 0 diff --git a/lora/rak2245/lora_pkt_fwd.c b/lora/rak2245/lora_pkt_fwd.c new file mode 100644 index 0000000..2671b02 --- /dev/null +++ b/lora/rak2245/lora_pkt_fwd.c @@ -0,0 +1,2893 @@ +/* + / _____) _ | | +( (____ _____ ____ _| |_ _____ ____| |__ + \____ \| ___ | (_ _) ___ |/ ___) _ \ + _____) ) ____| | | || |_| ____( (___| | | | +(______/|_____)_|_|_| \__)_____)\____)_| |_| + (C)2013 Semtech-Cycleo + +Description: + Configure Lora concentrator and forward packets to a server + Use GPS for packet timestamping. + Send a becon at a regular interval without server intervention + +License: Revised BSD License, see LICENSE.TXT file include in the project +Maintainer: Michael Coracin +*/ + + +/* -------------------------------------------------------------------------- */ +/* --- DEPENDANCIES --------------------------------------------------------- */ + +/* fix an issue between POSIX and C99 */ +#if __STDC_VERSION__ >= 199901L + #define _XOPEN_SOURCE 600 +#else + #define _XOPEN_SOURCE 500 +#endif + +#include /* C99 types */ +#include /* bool type */ +#include /* printf, fprintf, snprintf, fopen, fputs */ + +#include /* memset */ +#include /* sigaction */ +#include /* time, clock_gettime, strftime, gmtime */ +#include /* timeval */ +#include /* getopt, access */ +#include /* atoi, exit */ +#include /* error messages */ +#include /* modf */ +#include + +#include /* socket specific definitions */ +#include /* INET constants and stuff */ +#include /* IP address conversion stuff */ +#include /* gai_strerror */ + +#include + +#include "trace.h" +#include "jitqueue.h" +#include "timersync.h" +#include "parson.h" +#include "base64.h" +#include "loragw_hal.h" +#include "loragw_gps.h" +#include "loragw_aux.h" +#include "loragw_reg.h" + +/* -------------------------------------------------------------------------- */ +/* --- PRIVATE MACROS ------------------------------------------------------- */ + +#define ARRAY_SIZE(a) (sizeof(a) / sizeof((a)[0])) +#define STRINGIFY(x) #x +#define STR(x) STRINGIFY(x) + +/* -------------------------------------------------------------------------- */ +/* --- PRIVATE CONSTANTS ---------------------------------------------------- */ + +#ifndef VERSION_STRING + #define VERSION_STRING "undefined" +#endif + +#define DEFAULT_SERVER 127.0.0.1 /* hostname also supported */ +#define DEFAULT_PORT_UP 1780 +#define DEFAULT_PORT_DW 1782 +#define DEFAULT_KEEPALIVE 5 /* default time interval for downstream keep-alive packet */ +#define DEFAULT_STAT 30 /* default time interval for statistics */ +#define PUSH_TIMEOUT_MS 100 +#define PULL_TIMEOUT_MS 200 +#define GPS_REF_MAX_AGE 30 /* maximum admitted delay in seconds of GPS loss before considering latest GPS sync unusable */ +#define FETCH_SLEEP_MS 10 /* nb of ms waited when a fetch return no packets */ +#define BEACON_POLL_MS 50 /* time in ms between polling of beacon TX status */ + +#define PROTOCOL_VERSION 2 /* v1.3 */ + +#define XERR_INIT_AVG 128 /* nb of measurements the XTAL correction is averaged on as initial value */ +#define XERR_FILT_COEF 256 /* coefficient for low-pass XTAL error tracking */ + +#define PKT_PUSH_DATA 0 +#define PKT_PUSH_ACK 1 +#define PKT_PULL_DATA 2 +#define PKT_PULL_RESP 3 +#define PKT_PULL_ACK 4 +#define PKT_TX_ACK 5 + +#define NB_PKT_MAX 8 /* max number of packets per fetch/send cycle */ + +#define MIN_LORA_PREAMB 6 /* minimum Lora preamble length for this application */ +#define STD_LORA_PREAMB 8 +#define MIN_FSK_PREAMB 3 /* minimum FSK preamble length for this application */ +#define STD_FSK_PREAMB 5 + +#define STATUS_SIZE 200 +#define TX_BUFF_SIZE ((540 * NB_PKT_MAX) + 30 + STATUS_SIZE) + +#define UNIX_GPS_EPOCH_OFFSET 315964800 /* Number of seconds ellapsed between 01.Jan.1970 00:00:00 + and 06.Jan.1980 00:00:00 */ + +#define DEFAULT_BEACON_FREQ_HZ 869525000 +#define DEFAULT_BEACON_FREQ_NB 1 +#define DEFAULT_BEACON_FREQ_STEP 0 +#define DEFAULT_BEACON_DATARATE 9 +#define DEFAULT_BEACON_BW_HZ 125000 +#define DEFAULT_BEACON_POWER 14 +#define DEFAULT_BEACON_INFODESC 0 + +/* -------------------------------------------------------------------------- */ +/* --- PRIVATE VARIABLES (GLOBAL) ------------------------------------------- */ + +/* signal handling variables */ +volatile bool exit_sig = false; /* 1 -> application terminates cleanly (shut down hardware, close open files, etc) */ +volatile bool quit_sig = false; /* 1 -> application terminates without shutting down the hardware */ + +/* packets filtering configuration variables */ +static bool fwd_valid_pkt = true; /* packets with PAYLOAD CRC OK are forwarded */ +static bool fwd_error_pkt = false; /* packets with PAYLOAD CRC ERROR are NOT forwarded */ +static bool fwd_nocrc_pkt = false; /* packets with NO PAYLOAD CRC are NOT forwarded */ + +/* 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 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 */ + +/* statistics collection configuration variables */ +static unsigned stat_interval = DEFAULT_STAT; /* time interval (in sec) at which statistics are collected and displayed */ + +/* gateway <-> MAC protocol variables */ +static uint32_t net_mac_h; /* Most Significant Nibble, network order */ +static uint32_t net_mac_l; /* Least Significant Nibble, network order */ + +/* network sockets */ +static int sock_up; /* socket for upstream traffic */ +static int sock_down; /* socket for downstream traffic */ + +/* network protocol variables */ +static struct timeval push_timeout_half = {0, (PUSH_TIMEOUT_MS * 500)}; /* cut in half, critical for throughput */ +static struct timeval pull_timeout = {0, (PULL_TIMEOUT_MS * 1000)}; /* non critical for throughput */ + +/* hardware access control and correction */ +pthread_mutex_t mx_concent = PTHREAD_MUTEX_INITIALIZER; /* control access to the concentrator */ +static pthread_mutex_t mx_xcorr = PTHREAD_MUTEX_INITIALIZER; /* control access to the XTAL correction */ +static bool xtal_correct_ok = false; /* set true when XTAL correction is stable enough */ +static double xtal_correct = 1.0; + +/* GPS configuration and synchronization */ +static char gps_tty_path[64] = "\0"; /* path of the TTY port GPS is connected on */ +static int gps_tty_fd = -1; /* file descriptor of the GPS TTY port */ +static bool gps_enabled = false; /* is GPS enabled on that gateway ? */ + +/* GPS time reference */ +static pthread_mutex_t mx_timeref = PTHREAD_MUTEX_INITIALIZER; /* control access to GPS time reference */ +static bool gps_ref_valid; /* is GPS reference acceptable (ie. not too old) */ +static struct tref time_reference_gps; /* time reference used for GPS <-> timestamp conversion */ + +/* Reference coordinates, for broadcasting (beacon) */ +static struct coord_s reference_coord; + +/* Enable faking the GPS coordinates of the gateway */ +static bool gps_fake_enable; /* enable the feature */ + +/* measurements to establish statistics */ +static pthread_mutex_t mx_meas_up = PTHREAD_MUTEX_INITIALIZER; /* control access to the upstream measurements */ +static uint32_t meas_nb_rx_rcv = 0; /* count packets received */ +static uint32_t meas_nb_rx_ok = 0; /* count packets received with PAYLOAD CRC OK */ +static uint32_t meas_nb_rx_bad = 0; /* count packets received with PAYLOAD CRC ERROR */ +static uint32_t meas_nb_rx_nocrc = 0; /* count packets received with NO PAYLOAD CRC */ +static uint32_t meas_up_pkt_fwd = 0; /* number of radio packet forwarded to the server */ +static uint32_t meas_up_network_byte = 0; /* sum of UDP bytes sent for upstream traffic */ +static uint32_t meas_up_payload_byte = 0; /* sum of radio payload bytes sent for upstream traffic */ +static uint32_t meas_up_dgram_sent = 0; /* number of datagrams sent for upstream traffic */ +static uint32_t meas_up_ack_rcv = 0; /* number of datagrams acknowledged for upstream traffic */ + +static pthread_mutex_t mx_meas_dw = PTHREAD_MUTEX_INITIALIZER; /* control access to the downstream measurements */ +static uint32_t meas_dw_pull_sent = 0; /* number of PULL requests sent for downstream traffic */ +static uint32_t meas_dw_ack_rcv = 0; /* number of PULL requests acknowledged for downstream traffic */ +static uint32_t meas_dw_dgram_rcv = 0; /* count PULL response packets received for downstream traffic */ +static uint32_t meas_dw_network_byte = 0; /* sum of UDP bytes sent for upstream traffic */ +static uint32_t meas_dw_payload_byte = 0; /* sum of radio payload bytes sent for upstream traffic */ +static uint32_t meas_nb_tx_ok = 0; /* count packets emitted successfully */ +static uint32_t meas_nb_tx_fail = 0; /* count packets were TX failed for other reasons */ +static uint32_t meas_nb_tx_requested = 0; /* count TX request from server (downlinks) */ +static uint32_t meas_nb_tx_rejected_collision_packet = 0; /* count packets were TX request were rejected due to collision with another packet already programmed */ +static uint32_t meas_nb_tx_rejected_collision_beacon = 0; /* count packets were TX request were rejected due to collision with a beacon already programmed */ +static uint32_t meas_nb_tx_rejected_too_late = 0; /* count packets were TX request were rejected because it is too late to program it */ +static uint32_t meas_nb_tx_rejected_too_early = 0; /* count packets were TX request were rejected because timestamp is too much in advance */ +static uint32_t meas_nb_beacon_queued = 0; /* count beacon inserted in jit queue */ +static uint32_t meas_nb_beacon_sent = 0; /* count beacon actually sent to concentrator */ +static uint32_t meas_nb_beacon_rejected = 0; /* count beacon rejected for queuing */ + +static pthread_mutex_t mx_meas_gps = PTHREAD_MUTEX_INITIALIZER; /* control access to the GPS statistics */ +static bool gps_coord_valid; /* could we get valid GPS coordinates ? */ +static struct coord_s meas_gps_coord; /* GPS position of the gateway */ +static struct coord_s meas_gps_err; /* GPS position of the gateway */ + +static pthread_mutex_t mx_stat_rep = PTHREAD_MUTEX_INITIALIZER; /* control access to the status report */ +static bool report_ready = false; /* true when there is a new report to send to the server */ +static char status_report[STATUS_SIZE]; /* status report as a JSON object */ + +/* beacon parameters */ +static uint32_t beacon_period = 0; /* set beaconing period, must be a sub-multiple of 86400, the nb of sec in a day */ +static uint32_t beacon_freq_hz = DEFAULT_BEACON_FREQ_HZ; /* set beacon TX frequency, in Hz */ +static uint8_t beacon_freq_nb = DEFAULT_BEACON_FREQ_NB; /* set number of beaconing channels beacon */ +static uint32_t beacon_freq_step = DEFAULT_BEACON_FREQ_STEP; /* set frequency step between beacon channels, in Hz */ +static uint8_t beacon_datarate = DEFAULT_BEACON_DATARATE; /* set beacon datarate (SF) */ +static uint32_t beacon_bw_hz = DEFAULT_BEACON_BW_HZ; /* set beacon bandwidth, in Hz */ +static int8_t beacon_power = DEFAULT_BEACON_POWER; /* set beacon TX power, in dBm */ +static uint8_t beacon_infodesc = DEFAULT_BEACON_INFODESC; /* set beacon information descriptor */ + +/* auto-quit function */ +static uint32_t autoquit_threshold = 0; /* enable auto-quit after a number of non-acknowledged PULL_DATA (0 = disabled)*/ + +/* Just In Time TX scheduling */ +static struct jit_queue_s jit_queue; + +/* Gateway specificities */ +static int8_t antenna_gain = 0; + +/* TX capabilities */ +static struct lgw_tx_gain_lut_s txlut; /* TX gain table */ +static uint32_t tx_freq_min[LGW_RF_CHAIN_NB]; /* lowest frequency supported by TX chain */ +static uint32_t tx_freq_max[LGW_RF_CHAIN_NB]; /* highest frequency supported by TX chain */ + +/* -------------------------------------------------------------------------- */ +/* --- PRIVATE FUNCTIONS DECLARATION ---------------------------------------- */ + +static void sig_handler(int sigio); + +static int parse_SX1301_configuration(const char * conf_file); + +static int parse_gateway_configuration(const char * conf_file); + +static uint16_t crc16(const uint8_t * data, unsigned size); + +static double difftimespec(struct timespec end, struct timespec beginning); + +static void gps_process_sync(void); + +static void gps_process_coords(void); + +/* threads */ +void thread_up(void); +void thread_down(void); +void thread_gps(void); +void thread_valid(void); +void thread_jit(void); +void thread_timersync(void); + +/* -------------------------------------------------------------------------- */ +/* --- PRIVATE FUNCTIONS DEFINITION ----------------------------------------- */ + +static void sig_handler(int sigio) { + if (sigio == SIGQUIT) { + quit_sig = true; + } else if ((sigio == SIGINT) || (sigio == SIGTERM)) { + exit_sig = true; + } + return; +} + +static int parse_SX1301_configuration(const char * conf_file) { + int i; + char param_name[32]; /* used to generate variable parameter names */ + const char *str; /* used to store string value from JSON object */ + const char conf_obj_name[] = "SX1301_conf"; + JSON_Value *root_val = NULL; + JSON_Object *conf_obj = NULL; + JSON_Object *conf_lbt_obj = NULL; + JSON_Object *conf_lbtchan_obj = NULL; + JSON_Value *val = NULL; + JSON_Array *conf_array = NULL; + struct lgw_conf_board_s boardconf; + struct lgw_conf_lbt_s lbtconf; + struct lgw_conf_rxrf_s rfconf; + struct lgw_conf_rxif_s ifconf; + uint32_t sf, bw, fdev; + + /* try to parse JSON */ + root_val = json_parse_file_with_comments(conf_file); + if (root_val == NULL) { + MSG("ERROR: %s is not a valid JSON file\n", conf_file); + exit(EXIT_FAILURE); + } + + /* point to the gateway configuration object */ + conf_obj = json_object_get_object(json_value_get_object(root_val), conf_obj_name); + if (conf_obj == NULL) { + MSG("INFO: %s does not contain a JSON object named %s\n", conf_file, conf_obj_name); + return -1; + } else { + MSG("INFO: %s does contain a JSON object named %s, parsing SX1301 parameters\n", conf_file, conf_obj_name); + } + + /* set board configuration */ + memset(&boardconf, 0, sizeof boardconf); /* initialize configuration structure */ + val = json_object_get_value(conf_obj, "lorawan_public"); /* fetch value (if possible) */ + if (json_value_get_type(val) == JSONBoolean) { + boardconf.lorawan_public = (bool)json_value_get_boolean(val); + } else { + MSG("WARNING: Data type for lorawan_public seems wrong, please check\n"); + boardconf.lorawan_public = false; + } + val = json_object_get_value(conf_obj, "clksrc"); /* fetch value (if possible) */ + if (json_value_get_type(val) == JSONNumber) { + boardconf.clksrc = (uint8_t)json_value_get_number(val); + } else { + MSG("WARNING: Data type for clksrc seems wrong, please check\n"); + boardconf.clksrc = 0; + } + MSG("INFO: lorawan_public %d, clksrc %d\n", boardconf.lorawan_public, boardconf.clksrc); + /* all parameters parsed, submitting configuration to the HAL */ + if (lgw_board_setconf(boardconf) != LGW_HAL_SUCCESS) { + MSG("ERROR: Failed to configure board\n"); + return -1; + } + + /* set LBT configuration */ + memset(&lbtconf, 0, sizeof lbtconf); /* initialize configuration structure */ + conf_lbt_obj = json_object_get_object(conf_obj, "lbt_cfg"); /* fetch value (if possible) */ + if (conf_lbt_obj == NULL) { + MSG("INFO: no configuration for LBT\n"); + } else { + val = json_object_get_value(conf_lbt_obj, "enable"); /* fetch value (if possible) */ + if (json_value_get_type(val) == JSONBoolean) { + lbtconf.enable = (bool)json_value_get_boolean(val); + } else { + MSG("WARNING: Data type for lbt_cfg.enable seems wrong, please check\n"); + lbtconf.enable = false; + } + if (lbtconf.enable == true) { + val = json_object_get_value(conf_lbt_obj, "rssi_target"); /* fetch value (if possible) */ + if (json_value_get_type(val) == JSONNumber) { + lbtconf.rssi_target = (int8_t)json_value_get_number(val); + } else { + MSG("WARNING: Data type for lbt_cfg.rssi_target seems wrong, please check\n"); + lbtconf.rssi_target = 0; + } + val = json_object_get_value(conf_lbt_obj, "sx127x_rssi_offset"); /* fetch value (if possible) */ + if (json_value_get_type(val) == JSONNumber) { + lbtconf.rssi_offset = (int8_t)json_value_get_number(val); + } else { + MSG("WARNING: Data type for lbt_cfg.sx127x_rssi_offset seems wrong, please check\n"); + lbtconf.rssi_offset = 0; + } + /* set LBT channels configuration */ + conf_array = json_object_get_array(conf_lbt_obj, "chan_cfg"); + if (conf_array != NULL) { + lbtconf.nb_channel = json_array_get_count( conf_array ); + MSG("INFO: %u LBT channels configured\n", lbtconf.nb_channel); + } + for (i = 0; i < (int)lbtconf.nb_channel; i++) { + /* Sanity check */ + if (i >= LBT_CHANNEL_FREQ_NB) + { + MSG("ERROR: LBT channel %d not supported, skip it\n", i ); + break; + } + /* Get LBT channel configuration object from array */ + conf_lbtchan_obj = json_array_get_object(conf_array, i); + + /* Channel frequency */ + val = json_object_dotget_value(conf_lbtchan_obj, "freq_hz"); /* fetch value (if possible) */ + if (json_value_get_type(val) == JSONNumber) { + lbtconf.channels[i].freq_hz = (uint32_t)json_value_get_number(val); + } else { + MSG("WARNING: Data type for lbt_cfg.channels[%d].freq_hz seems wrong, please check\n", i); + lbtconf.channels[i].freq_hz = 0; + } + + /* Channel scan time */ + val = json_object_dotget_value(conf_lbtchan_obj, "scan_time_us"); /* fetch value (if possible) */ + if (json_value_get_type(val) == JSONNumber) { + lbtconf.channels[i].scan_time_us = (uint16_t)json_value_get_number(val); + } else { + MSG("WARNING: Data type for lbt_cfg.channels[%d].scan_time_us seems wrong, please check\n", i); + lbtconf.channels[i].scan_time_us = 0; + } + } + + /* all parameters parsed, submitting configuration to the HAL */ + if (lgw_lbt_setconf(lbtconf) != LGW_HAL_SUCCESS) { + MSG("ERROR: Failed to configure LBT\n"); + return -1; + } + } else { + MSG("INFO: LBT is disabled\n"); + } + } + + /* set antenna gain configuration */ + val = json_object_get_value(conf_obj, "antenna_gain"); /* fetch value (if possible) */ + if (val != NULL) { + if (json_value_get_type(val) == JSONNumber) { + antenna_gain = (int8_t)json_value_get_number(val); + } else { + MSG("WARNING: Data type for antenna_gain seems wrong, please check\n"); + antenna_gain = 0; + } + } + MSG("INFO: antenna_gain %d dBi\n", antenna_gain); + + /* set configuration for tx gains */ + memset(&txlut, 0, sizeof txlut); /* initialize configuration structure */ + for (i = 0; i < TX_GAIN_LUT_SIZE_MAX; i++) { + snprintf(param_name, sizeof param_name, "tx_lut_%i", i); /* compose parameter path inside JSON structure */ + val = json_object_get_value(conf_obj, param_name); /* fetch value (if possible) */ + if (json_value_get_type(val) != JSONObject) { + MSG("INFO: no configuration for tx gain lut %i\n", i); + continue; + } + txlut.size++; /* update TX LUT size based on JSON object found in configuration file */ + /* there is an object to configure that TX gain index, let's parse it */ + snprintf(param_name, sizeof param_name, "tx_lut_%i.pa_gain", i); + val = json_object_dotget_value(conf_obj, param_name); + if (json_value_get_type(val) == JSONNumber) { + txlut.lut[i].pa_gain = (uint8_t)json_value_get_number(val); + } else { + MSG("WARNING: Data type for %s[%d] seems wrong, please check\n", param_name, i); + txlut.lut[i].pa_gain = 0; + } + snprintf(param_name, sizeof param_name, "tx_lut_%i.dac_gain", i); + val = json_object_dotget_value(conf_obj, param_name); + if (json_value_get_type(val) == JSONNumber) { + txlut.lut[i].dac_gain = (uint8_t)json_value_get_number(val); + } else { + txlut.lut[i].dac_gain = 3; /* This is the only dac_gain supported for now */ + } + snprintf(param_name, sizeof param_name, "tx_lut_%i.dig_gain", i); + val = json_object_dotget_value(conf_obj, param_name); + if (json_value_get_type(val) == JSONNumber) { + txlut.lut[i].dig_gain = (uint8_t)json_value_get_number(val); + } else { + MSG("WARNING: Data type for %s[%d] seems wrong, please check\n", param_name, i); + txlut.lut[i].dig_gain = 0; + } + snprintf(param_name, sizeof param_name, "tx_lut_%i.mix_gain", i); + val = json_object_dotget_value(conf_obj, param_name); + if (json_value_get_type(val) == JSONNumber) { + txlut.lut[i].mix_gain = (uint8_t)json_value_get_number(val); + } else { + MSG("WARNING: Data type for %s[%d] seems wrong, please check\n", param_name, i); + txlut.lut[i].mix_gain = 0; + } + snprintf(param_name, sizeof param_name, "tx_lut_%i.rf_power", i); + val = json_object_dotget_value(conf_obj, param_name); + if (json_value_get_type(val) == JSONNumber) { + txlut.lut[i].rf_power = (int8_t)json_value_get_number(val); + } else { + MSG("WARNING: Data type for %s[%d] seems wrong, please check\n", param_name, i); + txlut.lut[i].rf_power = 0; + } + } + /* all parameters parsed, submitting configuration to the HAL */ + if (txlut.size > 0) { + MSG("INFO: Configuring TX LUT with %u indexes\n", txlut.size); + if (lgw_txgain_setconf(&txlut) != LGW_HAL_SUCCESS) { + MSG("ERROR: Failed to configure concentrator TX Gain LUT\n"); + return -1; + } + } else { + MSG("WARNING: No TX gain LUT defined\n"); + } + + /* set configuration for RF chains */ + for (i = 0; i < LGW_RF_CHAIN_NB; ++i) { + memset(&rfconf, 0, sizeof rfconf); /* initialize configuration structure */ + snprintf(param_name, sizeof param_name, "radio_%i", i); /* compose parameter path inside JSON structure */ + val = json_object_get_value(conf_obj, param_name); /* fetch value (if possible) */ + if (json_value_get_type(val) != JSONObject) { + MSG("INFO: no configuration for radio %i\n", i); + continue; + } + /* there is an object to configure that radio, let's parse it */ + snprintf(param_name, sizeof param_name, "radio_%i.enable", i); + val = json_object_dotget_value(conf_obj, param_name); + if (json_value_get_type(val) == JSONBoolean) { + rfconf.enable = (bool)json_value_get_boolean(val); + } else { + rfconf.enable = false; + } + if (rfconf.enable == false) { /* radio disabled, nothing else to parse */ + MSG("INFO: radio %i disabled\n", i); + } else { /* radio enabled, will parse the other parameters */ + snprintf(param_name, sizeof param_name, "radio_%i.freq", i); + rfconf.freq_hz = (uint32_t)json_object_dotget_number(conf_obj, param_name); + snprintf(param_name, sizeof param_name, "radio_%i.rssi_offset", i); + rfconf.rssi_offset = (float)json_object_dotget_number(conf_obj, param_name); + snprintf(param_name, sizeof param_name, "radio_%i.type", i); + str = json_object_dotget_string(conf_obj, param_name); + if (!strncmp(str, "SX1255", 6)) { + rfconf.type = LGW_RADIO_TYPE_SX1255; + } else if (!strncmp(str, "SX1257", 6)) { + rfconf.type = LGW_RADIO_TYPE_SX1257; + } else { + MSG("WARNING: invalid radio type: %s (should be SX1255 or SX1257)\n", str); + } + snprintf(param_name, sizeof param_name, "radio_%i.tx_enable", i); + val = json_object_dotget_value(conf_obj, param_name); + if (json_value_get_type(val) == JSONBoolean) { + rfconf.tx_enable = (bool)json_value_get_boolean(val); + if (rfconf.tx_enable == true) { + /* tx is enabled on this rf chain, we need its frequency range */ + snprintf(param_name, sizeof param_name, "radio_%i.tx_freq_min", i); + tx_freq_min[i] = (uint32_t)json_object_dotget_number(conf_obj, param_name); + snprintf(param_name, sizeof param_name, "radio_%i.tx_freq_max", i); + tx_freq_max[i] = (uint32_t)json_object_dotget_number(conf_obj, param_name); + if ((tx_freq_min[i] == 0) || (tx_freq_max[i] == 0)) { + MSG("WARNING: no frequency range specified for TX rf chain %d\n", i); + } + /* ... and the notch filter frequency to be set */ + snprintf(param_name, sizeof param_name, "radio_%i.tx_notch_freq", i); + rfconf.tx_notch_freq = (uint32_t)json_object_dotget_number(conf_obj, param_name); + } + } else { + rfconf.tx_enable = false; + } + MSG("INFO: radio %i enabled (type %s), center frequency %u, RSSI offset %f, tx enabled %d, tx_notch_freq %u\n", i, str, rfconf.freq_hz, rfconf.rssi_offset, rfconf.tx_enable, rfconf.tx_notch_freq); + } + /* all parameters parsed, submitting configuration to the HAL */ + if (lgw_rxrf_setconf(i, rfconf) != LGW_HAL_SUCCESS) { + MSG("ERROR: invalid configuration for radio %i\n", i); + return -1; + } + } + + /* set configuration for Lora multi-SF channels (bandwidth cannot be set) */ + for (i = 0; i < LGW_MULTI_NB; ++i) { + memset(&ifconf, 0, sizeof ifconf); /* initialize configuration structure */ + snprintf(param_name, sizeof param_name, "chan_multiSF_%i", i); /* compose parameter path inside JSON structure */ + val = json_object_get_value(conf_obj, param_name); /* fetch value (if possible) */ + if (json_value_get_type(val) != JSONObject) { + MSG("INFO: no configuration for Lora multi-SF channel %i\n", i); + continue; + } + /* there is an object to configure that Lora multi-SF channel, let's parse it */ + snprintf(param_name, sizeof param_name, "chan_multiSF_%i.enable", i); + val = json_object_dotget_value(conf_obj, param_name); + if (json_value_get_type(val) == JSONBoolean) { + ifconf.enable = (bool)json_value_get_boolean(val); + } else { + ifconf.enable = false; + } + if (ifconf.enable == false) { /* Lora multi-SF channel disabled, nothing else to parse */ + MSG("INFO: Lora multi-SF channel %i disabled\n", i); + } else { /* Lora multi-SF channel enabled, will parse the other parameters */ + snprintf(param_name, sizeof param_name, "chan_multiSF_%i.radio", i); + ifconf.rf_chain = (uint32_t)json_object_dotget_number(conf_obj, param_name); + snprintf(param_name, sizeof param_name, "chan_multiSF_%i.if", i); + ifconf.freq_hz = (int32_t)json_object_dotget_number(conf_obj, param_name); + // TODO: handle individual SF enabling and disabling (spread_factor) + MSG("INFO: Lora multi-SF channel %i> radio %i, IF %i Hz, 125 kHz bw, SF 7 to 12\n", i, ifconf.rf_chain, ifconf.freq_hz); + } + /* all parameters parsed, submitting configuration to the HAL */ + if (lgw_rxif_setconf(i, ifconf) != LGW_HAL_SUCCESS) { + MSG("ERROR: invalid configuration for Lora multi-SF channel %i\n", i); + return -1; + } + } + + /* set configuration for Lora standard channel */ + memset(&ifconf, 0, sizeof ifconf); /* initialize configuration structure */ + val = json_object_get_value(conf_obj, "chan_Lora_std"); /* fetch value (if possible) */ + if (json_value_get_type(val) != JSONObject) { + MSG("INFO: no configuration for Lora standard channel\n"); + } else { + val = json_object_dotget_value(conf_obj, "chan_Lora_std.enable"); + if (json_value_get_type(val) == JSONBoolean) { + ifconf.enable = (bool)json_value_get_boolean(val); + } else { + ifconf.enable = false; + } + if (ifconf.enable == false) { + MSG("INFO: Lora standard channel %i disabled\n", i); + } else { + ifconf.rf_chain = (uint32_t)json_object_dotget_number(conf_obj, "chan_Lora_std.radio"); + ifconf.freq_hz = (int32_t)json_object_dotget_number(conf_obj, "chan_Lora_std.if"); + bw = (uint32_t)json_object_dotget_number(conf_obj, "chan_Lora_std.bandwidth"); + switch(bw) { + case 500000: ifconf.bandwidth = BW_500KHZ; break; + case 250000: ifconf.bandwidth = BW_250KHZ; break; + case 125000: ifconf.bandwidth = BW_125KHZ; break; + default: ifconf.bandwidth = BW_UNDEFINED; + } + sf = (uint32_t)json_object_dotget_number(conf_obj, "chan_Lora_std.spread_factor"); + switch(sf) { + case 7: ifconf.datarate = DR_LORA_SF7; break; + case 8: ifconf.datarate = DR_LORA_SF8; break; + case 9: ifconf.datarate = DR_LORA_SF9; break; + case 10: ifconf.datarate = DR_LORA_SF10; break; + case 11: ifconf.datarate = DR_LORA_SF11; break; + case 12: ifconf.datarate = DR_LORA_SF12; break; + default: ifconf.datarate = DR_UNDEFINED; + } + MSG("INFO: Lora std channel> radio %i, IF %i Hz, %u Hz bw, SF %u\n", ifconf.rf_chain, ifconf.freq_hz, bw, sf); + } + if (lgw_rxif_setconf(8, ifconf) != LGW_HAL_SUCCESS) { + MSG("ERROR: invalid configuration for Lora standard channel\n"); + return -1; + } + } + + /* set configuration for FSK channel */ + memset(&ifconf, 0, sizeof ifconf); /* initialize configuration structure */ + val = json_object_get_value(conf_obj, "chan_FSK"); /* fetch value (if possible) */ + if (json_value_get_type(val) != JSONObject) { + MSG("INFO: no configuration for FSK channel\n"); + } else { + val = json_object_dotget_value(conf_obj, "chan_FSK.enable"); + if (json_value_get_type(val) == JSONBoolean) { + ifconf.enable = (bool)json_value_get_boolean(val); + } else { + ifconf.enable = false; + } + if (ifconf.enable == false) { + MSG("INFO: FSK channel %i disabled\n", i); + } else { + ifconf.rf_chain = (uint32_t)json_object_dotget_number(conf_obj, "chan_FSK.radio"); + ifconf.freq_hz = (int32_t)json_object_dotget_number(conf_obj, "chan_FSK.if"); + bw = (uint32_t)json_object_dotget_number(conf_obj, "chan_FSK.bandwidth"); + fdev = (uint32_t)json_object_dotget_number(conf_obj, "chan_FSK.freq_deviation"); + ifconf.datarate = (uint32_t)json_object_dotget_number(conf_obj, "chan_FSK.datarate"); + + /* if chan_FSK.bandwidth is set, it has priority over chan_FSK.freq_deviation */ + if ((bw == 0) && (fdev != 0)) { + bw = 2 * fdev + ifconf.datarate; + } + if (bw == 0) ifconf.bandwidth = BW_UNDEFINED; + else if (bw <= 7800) ifconf.bandwidth = BW_7K8HZ; + else if (bw <= 15600) ifconf.bandwidth = BW_15K6HZ; + else if (bw <= 31200) ifconf.bandwidth = BW_31K2HZ; + else if (bw <= 62500) ifconf.bandwidth = BW_62K5HZ; + else if (bw <= 125000) ifconf.bandwidth = BW_125KHZ; + else if (bw <= 250000) ifconf.bandwidth = BW_250KHZ; + else if (bw <= 500000) ifconf.bandwidth = BW_500KHZ; + else ifconf.bandwidth = BW_UNDEFINED; + + MSG("INFO: FSK channel> radio %i, IF %i Hz, %u Hz bw, %u bps datarate\n", ifconf.rf_chain, ifconf.freq_hz, bw, ifconf.datarate); + } + if (lgw_rxif_setconf(9, ifconf) != LGW_HAL_SUCCESS) { + MSG("ERROR: invalid configuration for FSK channel\n"); + return -1; + } + } + json_value_free(root_val); + + return 0; +} + +static int parse_gateway_configuration(const char * conf_file) { + const char conf_obj_name[] = "gateway_conf"; + JSON_Value *root_val; + JSON_Object *conf_obj = NULL; + JSON_Value *val = NULL; /* needed to detect the absence of some fields */ + const char *str; /* pointer to sub-strings in the JSON data */ + unsigned long long ull = 0; + + /* try to parse JSON */ + root_val = json_parse_file_with_comments(conf_file); + if (root_val == NULL) { + MSG("ERROR: %s is not a valid JSON file\n", conf_file); + exit(EXIT_FAILURE); + } + + /* point to the gateway configuration object */ + conf_obj = json_object_get_object(json_value_get_object(root_val), conf_obj_name); + if (conf_obj == NULL) { + MSG("INFO: %s does not contain a JSON object named %s\n", conf_file, conf_obj_name); + return -1; + } else { + MSG("INFO: %s does contain a JSON object named %s, parsing gateway parameters\n", conf_file, conf_obj_name); + } + + /* gateway unique identifier (aka MAC address) (optional) */ + str = json_object_get_string(conf_obj, "gateway_ID"); + if (str != NULL) { + sscanf(str, "%llx", &ull); + lgwm = ull; + MSG("INFO: gateway MAC address is configured to %016llX\n", ull); + } + + /* server hostname or IP address (optional) */ + str = json_object_get_string(conf_obj, "server_address"); + if (str != NULL) { + strncpy(serv_addr, str, sizeof serv_addr); + MSG("INFO: server hostname or IP address is configured to \"%s\"\n", serv_addr); + } + + /* get up and down ports (optional) */ + val = json_object_get_value(conf_obj, "serv_port_up"); + if (val != NULL) { + snprintf(serv_port_up, sizeof serv_port_up, "%u", (uint16_t)json_value_get_number(val)); + MSG("INFO: upstream port is configured to \"%s\"\n", serv_port_up); + } + val = json_object_get_value(conf_obj, "serv_port_down"); + if (val != NULL) { + 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); + } + + /* get keep-alive interval (in seconds) for downstream (optional) */ + val = json_object_get_value(conf_obj, "keepalive_interval"); + if (val != NULL) { + keepalive_time = (int)json_value_get_number(val); + MSG("INFO: downstream keep-alive interval is configured to %u seconds\n", keepalive_time); + } + + /* get interval (in seconds) for statistics display (optional) */ + val = json_object_get_value(conf_obj, "stat_interval"); + if (val != NULL) { + stat_interval = (unsigned)json_value_get_number(val); + MSG("INFO: statistics display interval is configured to %u seconds\n", stat_interval); + } + + /* get time-out value (in ms) for upstream datagrams (optional) */ + val = json_object_get_value(conf_obj, "push_timeout_ms"); + if (val != NULL) { + push_timeout_half.tv_usec = 500 * (long int)json_value_get_number(val); + MSG("INFO: upstream PUSH_DATA time-out is configured to %u ms\n", (unsigned)(push_timeout_half.tv_usec / 500)); + } + + /* packet filtering parameters */ + val = json_object_get_value(conf_obj, "forward_crc_valid"); + if (json_value_get_type(val) == JSONBoolean) { + fwd_valid_pkt = (bool)json_value_get_boolean(val); + } + MSG("INFO: packets received with a valid CRC will%s be forwarded\n", (fwd_valid_pkt ? "" : " NOT")); + val = json_object_get_value(conf_obj, "forward_crc_error"); + if (json_value_get_type(val) == JSONBoolean) { + fwd_error_pkt = (bool)json_value_get_boolean(val); + } + MSG("INFO: packets received with a CRC error will%s be forwarded\n", (fwd_error_pkt ? "" : " NOT")); + val = json_object_get_value(conf_obj, "forward_crc_disabled"); + if (json_value_get_type(val) == JSONBoolean) { + fwd_nocrc_pkt = (bool)json_value_get_boolean(val); + } + MSG("INFO: packets received with no CRC will%s be forwarded\n", (fwd_nocrc_pkt ? "" : " NOT")); + + /* GPS module TTY path (optional) */ + str = json_object_get_string(conf_obj, "gps_tty_path"); + if (str != NULL) { + strncpy(gps_tty_path, str, sizeof gps_tty_path); + MSG("INFO: GPS serial port path is configured to \"%s\"\n", gps_tty_path); + } + + /* get reference coordinates */ + val = json_object_get_value(conf_obj, "ref_latitude"); + if (val != NULL) { + reference_coord.lat = (double)json_value_get_number(val); + MSG("INFO: Reference latitude is configured to %f deg\n", reference_coord.lat); + } + val = json_object_get_value(conf_obj, "ref_longitude"); + if (val != NULL) { + reference_coord.lon = (double)json_value_get_number(val); + MSG("INFO: Reference longitude is configured to %f deg\n", reference_coord.lon); + } + val = json_object_get_value(conf_obj, "ref_altitude"); + if (val != NULL) { + reference_coord.alt = (short)json_value_get_number(val); + MSG("INFO: Reference altitude is configured to %i meters\n", reference_coord.alt); + } + + /* Gateway GPS coordinates hardcoding (aka. faking) option */ + val = json_object_get_value(conf_obj, "fake_gps"); + if (json_value_get_type(val) == JSONBoolean) { + gps_fake_enable = (bool)json_value_get_boolean(val); + if (gps_fake_enable == true) { + MSG("INFO: fake GPS is enabled\n"); + } else { + MSG("INFO: fake GPS is disabled\n"); + } + } + + /* Beacon signal period (optional) */ + val = json_object_get_value(conf_obj, "beacon_period"); + if (val != NULL) { + beacon_period = (uint32_t)json_value_get_number(val); + if ((beacon_period > 0) && (beacon_period < 6)) { + MSG("ERROR: invalid configuration for Beacon period, must be >= 6s\n"); + return -1; + } else { + MSG("INFO: Beaconing period is configured to %u seconds\n", beacon_period); + } + } + + /* Beacon TX frequency (optional) */ + val = json_object_get_value(conf_obj, "beacon_freq_hz"); + if (val != NULL) { + beacon_freq_hz = (uint32_t)json_value_get_number(val); + MSG("INFO: Beaconing signal will be emitted at %u Hz\n", beacon_freq_hz); + } + + /* Number of beacon channels (optional) */ + val = json_object_get_value(conf_obj, "beacon_freq_nb"); + if (val != NULL) { + beacon_freq_nb = (uint8_t)json_value_get_number(val); + MSG("INFO: Beaconing channel number is set to %u\n", beacon_freq_nb); + } + + /* Frequency step between beacon channels (optional) */ + val = json_object_get_value(conf_obj, "beacon_freq_step"); + if (val != NULL) { + beacon_freq_step = (uint32_t)json_value_get_number(val); + MSG("INFO: Beaconing channel frequency step is set to %uHz\n", beacon_freq_step); + } + + /* Beacon datarate (optional) */ + val = json_object_get_value(conf_obj, "beacon_datarate"); + if (val != NULL) { + beacon_datarate = (uint8_t)json_value_get_number(val); + MSG("INFO: Beaconing datarate is set to SF%d\n", beacon_datarate); + } + + /* Beacon modulation bandwidth (optional) */ + val = json_object_get_value(conf_obj, "beacon_bw_hz"); + if (val != NULL) { + beacon_bw_hz = (uint32_t)json_value_get_number(val); + MSG("INFO: Beaconing modulation bandwidth is set to %dHz\n", beacon_bw_hz); + } + + /* Beacon TX power (optional) */ + val = json_object_get_value(conf_obj, "beacon_power"); + if (val != NULL) { + beacon_power = (int8_t)json_value_get_number(val); + MSG("INFO: Beaconing TX power is set to %ddBm\n", beacon_power); + } + + /* Beacon information descriptor (optional) */ + val = json_object_get_value(conf_obj, "beacon_infodesc"); + if (val != NULL) { + beacon_infodesc = (uint8_t)json_value_get_number(val); + MSG("INFO: Beaconing information descriptor is set to %u\n", beacon_infodesc); + } + + /* Auto-quit threshold (optional) */ + val = json_object_get_value(conf_obj, "autoquit_threshold"); + if (val != NULL) { + autoquit_threshold = (uint32_t)json_value_get_number(val); + MSG("INFO: Auto-quit after %u non-acknowledged PULL_DATA\n", autoquit_threshold); + } + + /* free JSON parsing data structure */ + json_value_free(root_val); + return 0; +} + +static uint16_t crc16(const uint8_t * data, unsigned size) { + const uint16_t crc_poly = 0x1021; + const uint16_t init_val = 0x0000; + uint16_t x = init_val; + unsigned i, j; + + if (data == NULL) { + return 0; + } + + for (i=0; i>32))); + net_mac_l = htonl((uint32_t)(0xFFFFFFFF & lgwm )); + + /* prepare hints to open network sockets */ + memset(&hints, 0, sizeof hints); + hints.ai_family = AF_INET; /* WA: Forcing IPv4 as AF_UNSPEC makes connection on localhost to fail */ + hints.ai_socktype = SOCK_DGRAM; + + /* look for server address w/ upstream port */ + i = getaddrinfo(serv_addr, serv_port_up, &hints, &result); + if (i != 0) { + MSG("ERROR: [up] getaddrinfo on address %s (PORT %s) returned %s\n", serv_addr, serv_port_up, gai_strerror(i)); + exit(EXIT_FAILURE); + } + + /* try to open socket for upstream traffic */ + for (q=result; q!=NULL; q=q->ai_next) { + sock_up = socket(q->ai_family, q->ai_socktype,q->ai_protocol); + if (sock_up == -1) continue; /* try next field */ + else break; /* success, get out of loop */ + } + if (q == NULL) { + MSG("ERROR: [up] failed to open socket to any of server %s addresses (port %s)\n", serv_addr, serv_port_up); + i = 1; + for (q=result; q!=NULL; q=q->ai_next) { + getnameinfo(q->ai_addr, q->ai_addrlen, host_name, sizeof host_name, port_name, sizeof port_name, NI_NUMERICHOST); + MSG("INFO: [up] result %i host:%s service:%s\n", i, host_name, port_name); + ++i; + } + exit(EXIT_FAILURE); + } + + /* connect so we can send/receive packet with the server only */ + i = connect(sock_up, q->ai_addr, q->ai_addrlen); + if (i != 0) { + MSG("ERROR: [up] connect returned %s\n", strerror(errno)); + exit(EXIT_FAILURE); + } + freeaddrinfo(result); + + /* look for server address w/ downstream port */ + i = getaddrinfo(serv_addr, serv_port_down, &hints, &result); + if (i != 0) { + MSG("ERROR: [down] getaddrinfo on address %s (port %s) returned %s\n", serv_addr, serv_port_up, gai_strerror(i)); + exit(EXIT_FAILURE); + } + + /* try to open socket for downstream traffic */ + for (q=result; q!=NULL; q=q->ai_next) { + sock_down = socket(q->ai_family, q->ai_socktype,q->ai_protocol); + if (sock_down == -1) continue; /* try next field */ + else break; /* success, get out of loop */ + } + if (q == NULL) { + MSG("ERROR: [down] failed to open socket to any of server %s addresses (port %s)\n", serv_addr, serv_port_up); + i = 1; + for (q=result; q!=NULL; q=q->ai_next) { + getnameinfo(q->ai_addr, q->ai_addrlen, host_name, sizeof host_name, port_name, sizeof port_name, NI_NUMERICHOST); + MSG("INFO: [down] result %i host:%s service:%s\n", i, host_name, port_name); + ++i; + } + exit(EXIT_FAILURE); + } + + /* connect so we can send/receive packet with the server only */ + i = connect(sock_down, q->ai_addr, q->ai_addrlen); + if (i != 0) { + MSG("ERROR: [down] connect returned %s\n", strerror(errno)); + exit(EXIT_FAILURE); + } + freeaddrinfo(result); + + /* starting the concentrator */ + i = lgw_start(); + if (i == LGW_HAL_SUCCESS) { + MSG("INFO: [main] concentrator started, packet can now be received\n"); + } else { + MSG("ERROR: [main] failed to start the concentrator\n"); + exit(EXIT_FAILURE); + } + + /* spawn threads to manage upstream and downstream */ + i = pthread_create( &thrid_up, NULL, (void * (*)(void *))thread_up, NULL); + if (i != 0) { + MSG("ERROR: [main] impossible to create upstream thread\n"); + exit(EXIT_FAILURE); + } + i = pthread_create( &thrid_down, NULL, (void * (*)(void *))thread_down, NULL); + if (i != 0) { + MSG("ERROR: [main] impossible to create downstream thread\n"); + exit(EXIT_FAILURE); + } + i = pthread_create( &thrid_jit, NULL, (void * (*)(void *))thread_jit, NULL); + if (i != 0) { + MSG("ERROR: [main] impossible to create JIT thread\n"); + exit(EXIT_FAILURE); + } + i = pthread_create( &thrid_timersync, NULL, (void * (*)(void *))thread_timersync, NULL); + if (i != 0) { + MSG("ERROR: [main] impossible to create Timer Sync 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); + if (i != 0) { + MSG("ERROR: [main] impossible to create GPS thread\n"); + exit(EXIT_FAILURE); + } + i = pthread_create( &thrid_valid, NULL, (void * (*)(void *))thread_valid, NULL); + if (i != 0) { + MSG("ERROR: [main] impossible to create validation thread\n"); + exit(EXIT_FAILURE); + } + } + + /* configure signal handling */ + sigemptyset(&sigact.sa_mask); + sigact.sa_flags = 0; + sigact.sa_handler = sig_handler; + sigaction(SIGQUIT, &sigact, NULL); /* Ctrl-\ */ + sigaction(SIGINT, &sigact, NULL); /* Ctrl-C */ + sigaction(SIGTERM, &sigact, NULL); /* default "kill" command */ + + /* main loop task : statistics collection */ + while (!exit_sig && !quit_sig) { + /* wait for next reporting interval */ + wait_ms(1000 * stat_interval); + + /* get timestamp for statistics */ + t = time(NULL); + strftime(stat_timestamp, sizeof stat_timestamp, "%F %T %Z", gmtime(&t)); + + /* access upstream statistics, copy and reset them */ + pthread_mutex_lock(&mx_meas_up); + cp_nb_rx_rcv = meas_nb_rx_rcv; + cp_nb_rx_ok = meas_nb_rx_ok; + cp_nb_rx_bad = meas_nb_rx_bad; + cp_nb_rx_nocrc = meas_nb_rx_nocrc; + cp_up_pkt_fwd = meas_up_pkt_fwd; + cp_up_network_byte = meas_up_network_byte; + cp_up_payload_byte = meas_up_payload_byte; + cp_up_dgram_sent = meas_up_dgram_sent; + cp_up_ack_rcv = meas_up_ack_rcv; + meas_nb_rx_rcv = 0; + meas_nb_rx_ok = 0; + meas_nb_rx_bad = 0; + meas_nb_rx_nocrc = 0; + meas_up_pkt_fwd = 0; + meas_up_network_byte = 0; + meas_up_payload_byte = 0; + meas_up_dgram_sent = 0; + meas_up_ack_rcv = 0; + pthread_mutex_unlock(&mx_meas_up); + if (cp_nb_rx_rcv > 0) { + rx_ok_ratio = (float)cp_nb_rx_ok / (float)cp_nb_rx_rcv; + rx_bad_ratio = (float)cp_nb_rx_bad / (float)cp_nb_rx_rcv; + rx_nocrc_ratio = (float)cp_nb_rx_nocrc / (float)cp_nb_rx_rcv; + } else { + rx_ok_ratio = 0.0; + rx_bad_ratio = 0.0; + rx_nocrc_ratio = 0.0; + } + if (cp_up_dgram_sent > 0) { + up_ack_ratio = (float)cp_up_ack_rcv / (float)cp_up_dgram_sent; + } else { + up_ack_ratio = 0.0; + } + + /* access downstream statistics, copy and reset them */ + pthread_mutex_lock(&mx_meas_dw); + cp_dw_pull_sent = meas_dw_pull_sent; + cp_dw_ack_rcv = meas_dw_ack_rcv; + cp_dw_dgram_rcv = meas_dw_dgram_rcv; + cp_dw_network_byte = meas_dw_network_byte; + cp_dw_payload_byte = meas_dw_payload_byte; + cp_nb_tx_ok = meas_nb_tx_ok; + cp_nb_tx_fail = meas_nb_tx_fail; + cp_nb_tx_requested += meas_nb_tx_requested; + cp_nb_tx_rejected_collision_packet += meas_nb_tx_rejected_collision_packet; + cp_nb_tx_rejected_collision_beacon += meas_nb_tx_rejected_collision_beacon; + cp_nb_tx_rejected_too_late += meas_nb_tx_rejected_too_late; + cp_nb_tx_rejected_too_early += meas_nb_tx_rejected_too_early; + cp_nb_beacon_queued += meas_nb_beacon_queued; + cp_nb_beacon_sent += meas_nb_beacon_sent; + cp_nb_beacon_rejected += meas_nb_beacon_rejected; + meas_dw_pull_sent = 0; + meas_dw_ack_rcv = 0; + meas_dw_dgram_rcv = 0; + meas_dw_network_byte = 0; + meas_dw_payload_byte = 0; + meas_nb_tx_ok = 0; + meas_nb_tx_fail = 0; + meas_nb_tx_requested = 0; + meas_nb_tx_rejected_collision_packet = 0; + meas_nb_tx_rejected_collision_beacon = 0; + meas_nb_tx_rejected_too_late = 0; + meas_nb_tx_rejected_too_early = 0; + meas_nb_beacon_queued = 0; + meas_nb_beacon_sent = 0; + meas_nb_beacon_rejected = 0; + pthread_mutex_unlock(&mx_meas_dw); + if (cp_dw_pull_sent > 0) { + dw_ack_ratio = (float)cp_dw_ack_rcv / (float)cp_dw_pull_sent; + } else { + dw_ack_ratio = 0.0; + } + + /* access GPS statistics, copy them */ + if (gps_enabled == true) { + pthread_mutex_lock(&mx_meas_gps); + coord_ok = gps_coord_valid; + cp_gps_coord = meas_gps_coord; + pthread_mutex_unlock(&mx_meas_gps); + } + + /* overwrite with reference coordinates if function is enabled */ + if (gps_fake_enable == true) { + cp_gps_coord = reference_coord; + } + + /* display a report */ + printf("\n##### %s #####\n", stat_timestamp); + printf("### [UPSTREAM] ###\n"); + printf("# RF packets received by concentrator: %u\n", cp_nb_rx_rcv); + printf("# CRC_OK: %.2f%%, CRC_FAIL: %.2f%%, NO_CRC: %.2f%%\n", 100.0 * rx_ok_ratio, 100.0 * rx_bad_ratio, 100.0 * rx_nocrc_ratio); + printf("# RF packets forwarded: %u (%u bytes)\n", cp_up_pkt_fwd, cp_up_payload_byte); + printf("# PUSH_DATA datagrams sent: %u (%u bytes)\n", cp_up_dgram_sent, cp_up_network_byte); + printf("# PUSH_DATA acknowledged: %.2f%%\n", 100.0 * up_ack_ratio); + printf("### [DOWNSTREAM] ###\n"); + printf("# PULL_DATA sent: %u (%.2f%% acknowledged)\n", cp_dw_pull_sent, 100.0 * dw_ack_ratio); + printf("# PULL_RESP(onse) datagrams received: %u (%u bytes)\n", cp_dw_dgram_rcv, cp_dw_network_byte); + printf("# RF packets sent to concentrator: %u (%u bytes)\n", (cp_nb_tx_ok+cp_nb_tx_fail), cp_dw_payload_byte); + printf("# TX errors: %u\n", cp_nb_tx_fail); + if (cp_nb_tx_requested != 0 ) { + printf("# TX rejected (collision packet): %.2f%% (req:%u, rej:%u)\n", 100.0 * cp_nb_tx_rejected_collision_packet / cp_nb_tx_requested, cp_nb_tx_requested, cp_nb_tx_rejected_collision_packet); + printf("# TX rejected (collision beacon): %.2f%% (req:%u, rej:%u)\n", 100.0 * cp_nb_tx_rejected_collision_beacon / cp_nb_tx_requested, cp_nb_tx_requested, cp_nb_tx_rejected_collision_beacon); + printf("# TX rejected (too late): %.2f%% (req:%u, rej:%u)\n", 100.0 * cp_nb_tx_rejected_too_late / cp_nb_tx_requested, cp_nb_tx_requested, cp_nb_tx_rejected_too_late); + printf("# TX rejected (too early): %.2f%% (req:%u, rej:%u)\n", 100.0 * cp_nb_tx_rejected_too_early / cp_nb_tx_requested, cp_nb_tx_requested, cp_nb_tx_rejected_too_early); + } + printf("# BEACON queued: %u\n", cp_nb_beacon_queued); + printf("# BEACON sent so far: %u\n", cp_nb_beacon_sent); + printf("# BEACON rejected: %u\n", cp_nb_beacon_rejected); + printf("### [JIT] ###\n"); + /* get timestamp captured on PPM pulse */ + pthread_mutex_lock(&mx_concent); + i = lgw_get_trigcnt(&trig_tstamp); + pthread_mutex_unlock(&mx_concent); + if (i != LGW_HAL_SUCCESS) { + printf("# SX1301 time (PPS): unknown\n"); + } else { + printf("# SX1301 time (PPS): %u\n", trig_tstamp); + } + jit_print_queue (&jit_queue, false, DEBUG_LOG); + printf("### [GPS] ###\n"); + if (gps_enabled == true) { + /* no need for mutex, display is not critical */ + if (gps_ref_valid == true) { + printf("# Valid time reference (age: %li sec)\n", (long)difftime(time(NULL), time_reference_gps.systime)); + } else { + printf("# Invalid time reference (age: %li sec)\n", (long)difftime(time(NULL), time_reference_gps.systime)); + } + if (coord_ok == true) { + printf("# GPS coordinates: latitude %.5f, longitude %.5f, altitude %i m\n", cp_gps_coord.lat, cp_gps_coord.lon, cp_gps_coord.alt); + } else { + printf("# no valid GPS coordinates available yet\n"); + } + } else if (gps_fake_enable == true) { + printf("# GPS *FAKE* coordinates: latitude %.5f, longitude %.5f, altitude %i m\n", cp_gps_coord.lat, cp_gps_coord.lon, cp_gps_coord.alt); + } else { + printf("# GPS sync is disabled\n"); + } + printf("##### END #####\n"); + + /* generate a JSON report (will be sent to server by upstream thread) */ + pthread_mutex_lock(&mx_stat_rep); + if (((gps_enabled == true) && (coord_ok == true)) || (gps_fake_enable == true)) { + snprintf(status_report, STATUS_SIZE, "\"stat\":{\"time\":\"%s\",\"lati\":%.5f,\"long\":%.5f,\"alti\":%i,\"rxnb\":%u,\"rxok\":%u,\"rxfw\":%u,\"ackr\":%.1f,\"dwnb\":%u,\"txnb\":%u}", stat_timestamp, cp_gps_coord.lat, cp_gps_coord.lon, cp_gps_coord.alt, cp_nb_rx_rcv, cp_nb_rx_ok, cp_up_pkt_fwd, 100.0 * up_ack_ratio, cp_dw_dgram_rcv, cp_nb_tx_ok); + } else { + snprintf(status_report, STATUS_SIZE, "\"stat\":{\"time\":\"%s\",\"rxnb\":%u,\"rxok\":%u,\"rxfw\":%u,\"ackr\":%.1f,\"dwnb\":%u,\"txnb\":%u}", stat_timestamp, cp_nb_rx_rcv, cp_nb_rx_ok, cp_up_pkt_fwd, 100.0 * up_ack_ratio, cp_dw_dgram_rcv, cp_nb_tx_ok); + } + report_ready = true; + pthread_mutex_unlock(&mx_stat_rep); + } + + /* wait for upstream thread to finish (1 fetch cycle max) */ + pthread_join(thrid_up, NULL); + pthread_cancel(thrid_down); /* don't wait for downstream thread */ + pthread_cancel(thrid_jit); /* don't wait for jit thread */ + pthread_cancel(thrid_timersync); /* don't wait for timer sync thread */ + if (gps_enabled == true) { + pthread_cancel(thrid_gps); /* don't wait for GPS thread */ + pthread_cancel(thrid_valid); /* don't wait for validation thread */ + + i = lgw_gps_disable(gps_tty_fd); + if (i == LGW_HAL_SUCCESS) { + MSG("INFO: GPS closed successfully\n"); + } else { + MSG("WARNING: failed to close GPS successfully\n"); + } + } + + /* if an exit signal was received, try to quit properly */ + if (exit_sig) { + /* shut down network sockets */ + shutdown(sock_up, SHUT_RDWR); + shutdown(sock_down, SHUT_RDWR); + /* stop the hardware */ + i = lgw_stop(); + if (i == LGW_HAL_SUCCESS) { + MSG("INFO: concentrator stopped successfully\n"); + } else { + MSG("WARNING: failed to stop concentrator successfully\n"); + } + } + + MSG("INFO: Exiting packet forwarder program\n"); + exit(EXIT_SUCCESS); +} + +/* -------------------------------------------------------------------------- */ +/* --- THREAD 1: RECEIVING PACKETS AND FORWARDING THEM ---------------------- */ + +void thread_up(void) { + int i, j; /* loop variables */ + unsigned pkt_in_dgram; /* nb on Lora packet in the current datagram */ + + /* allocate memory for packet fetching and processing */ + struct lgw_pkt_rx_s rxpkt[NB_PKT_MAX]; /* array containing inbound packets + metadata */ + struct lgw_pkt_rx_s *p; /* pointer on a RX packet */ + int nb_pkt; + + /* local copy of GPS time reference */ + bool ref_ok = false; /* determine if GPS time reference must be used or not */ + struct tref local_ref; /* time reference used for UTC <-> timestamp conversion */ + + /* data buffers */ + uint8_t buff_up[TX_BUFF_SIZE]; /* buffer to compose the upstream packet */ + int buff_index; + uint8_t buff_ack[32]; /* buffer to receive acknowledges */ + + /* protocol variables */ + uint8_t token_h; /* random token for acknowledgement matching */ + uint8_t token_l; /* random token for acknowledgement matching */ + + /* ping measurement variables */ + struct timespec send_time; + struct timespec recv_time; + + /* GPS synchronization variables */ + struct timespec pkt_utc_time; + struct tm * x; /* broken-up UTC time */ + struct timespec pkt_gps_time; + uint64_t pkt_gps_time_ms; + + /* report management variable */ + bool send_report = false; + + /* mote info variables */ + uint32_t mote_addr = 0; + uint16_t mote_fcnt = 0; + + /* set upstream socket RX timeout */ + i = setsockopt(sock_up, SOL_SOCKET, SO_RCVTIMEO, (void *)&push_timeout_half, sizeof push_timeout_half); + if (i != 0) { + MSG("ERROR: [up] setsockopt returned %s\n", strerror(errno)); + exit(EXIT_FAILURE); + } + + /* pre-fill the data buffer with fixed fields */ + buff_up[0] = PROTOCOL_VERSION; + buff_up[3] = PKT_PUSH_DATA; + *(uint32_t *)(buff_up + 4) = net_mac_h; + *(uint32_t *)(buff_up + 8) = net_mac_l; + + while (!exit_sig && !quit_sig) { + + /* fetch packets */ + pthread_mutex_lock(&mx_concent); + nb_pkt = lgw_receive(NB_PKT_MAX, rxpkt); + pthread_mutex_unlock(&mx_concent); + if (nb_pkt == LGW_HAL_ERROR) { + MSG("ERROR: [up] failed packet fetch, exiting\n"); + exit(EXIT_FAILURE); + } + + /* check if there are status report to send */ + send_report = report_ready; /* copy the variable so it doesn't change mid-function */ + /* no mutex, we're only reading */ + + /* wait a short time if no packets, nor status report */ + if ((nb_pkt == 0) && (send_report == false)) { + wait_ms(FETCH_SLEEP_MS); + continue; + } + + /* get a copy of GPS time reference (avoid 1 mutex per packet) */ + if ((nb_pkt > 0) && (gps_enabled == true)) { + pthread_mutex_lock(&mx_timeref); + ref_ok = gps_ref_valid; + local_ref = time_reference_gps; + pthread_mutex_unlock(&mx_timeref); + } else { + ref_ok = false; + } + + /* start composing datagram with the header */ + token_h = (uint8_t)rand(); /* random token */ + token_l = (uint8_t)rand(); /* random token */ + buff_up[1] = token_h; + buff_up[2] = token_l; + buff_index = 12; /* 12-byte header */ + + /* start of JSON structure */ + memcpy((void *)(buff_up + buff_index), (void *)"{\"rxpk\":[", 9); + buff_index += 9; + + /* serialize Lora packets metadata and payload */ + pkt_in_dgram = 0; + for (i=0; i < nb_pkt; ++i) { + p = &rxpkt[i]; + + /* Get mote information from current packet (addr, fcnt) */ + /* FHDR - DevAddr */ + mote_addr = p->payload[1]; + mote_addr |= p->payload[2] << 8; + mote_addr |= p->payload[3] << 16; + mote_addr |= p->payload[4] << 24; + /* FHDR - FCnt */ + mote_fcnt = p->payload[6]; + mote_fcnt |= p->payload[7] << 8; + + /* basic packet filtering */ + pthread_mutex_lock(&mx_meas_up); + meas_nb_rx_rcv += 1; + switch(p->status) { + case STAT_CRC_OK: + meas_nb_rx_ok += 1; + printf( "\nINFO: Received pkt from mote: %08X (fcnt=%u)\n", mote_addr, mote_fcnt ); + if (!fwd_valid_pkt) { + pthread_mutex_unlock(&mx_meas_up); + continue; /* skip that packet */ + } + break; + case STAT_CRC_BAD: + meas_nb_rx_bad += 1; + if (!fwd_error_pkt) { + pthread_mutex_unlock(&mx_meas_up); + continue; /* skip that packet */ + } + break; + case STAT_NO_CRC: + meas_nb_rx_nocrc += 1; + if (!fwd_nocrc_pkt) { + pthread_mutex_unlock(&mx_meas_up); + continue; /* skip that packet */ + } + break; + default: + MSG("WARNING: [up] received packet with unknown status %u (size %u, modulation %u, BW %u, DR %u, RSSI %.1f)\n", p->status, p->size, p->modulation, p->bandwidth, p->datarate, p->rssi); + pthread_mutex_unlock(&mx_meas_up); + continue; /* skip that packet */ + // exit(EXIT_FAILURE); + } + meas_up_pkt_fwd += 1; + meas_up_payload_byte += p->size; + pthread_mutex_unlock(&mx_meas_up); + + /* Start of packet, add inter-packet separator if necessary */ + if (pkt_in_dgram == 0) { + buff_up[buff_index] = '{'; + ++buff_index; + } else { + buff_up[buff_index] = ','; + buff_up[buff_index+1] = '{'; + buff_index += 2; + } + + /* RAW timestamp, 8-17 useful chars */ + j = snprintf((char *)(buff_up + buff_index), TX_BUFF_SIZE-buff_index, "\"tmst\":%u", p->count_us); + if (j > 0) { + buff_index += j; + } else { + MSG("ERROR: [up] snprintf failed line %u\n", (__LINE__ - 4)); + exit(EXIT_FAILURE); + } + + /* Packet RX time (GPS based), 37 useful chars */ + if (ref_ok == true) { + /* convert packet timestamp to UTC absolute time */ + j = lgw_cnt2utc(local_ref, p->count_us, &pkt_utc_time); + if (j == LGW_GPS_SUCCESS) { + /* split the UNIX timestamp to its calendar components */ + x = gmtime(&(pkt_utc_time.tv_sec)); + j = snprintf((char *)(buff_up + buff_index), TX_BUFF_SIZE-buff_index, ",\"time\":\"%04i-%02i-%02iT%02i:%02i:%02i.%06liZ\"", (x->tm_year)+1900, (x->tm_mon)+1, x->tm_mday, x->tm_hour, x->tm_min, x->tm_sec, (pkt_utc_time.tv_nsec)/1000); /* ISO 8601 format */ + if (j > 0) { + buff_index += j; + } else { + MSG("ERROR: [up] snprintf failed line %u\n", (__LINE__ - 4)); + exit(EXIT_FAILURE); + } + } + /* convert packet timestamp to GPS absolute time */ + j = lgw_cnt2gps(local_ref, p->count_us, &pkt_gps_time); + if (j == LGW_GPS_SUCCESS) { + pkt_gps_time_ms = pkt_gps_time.tv_sec * 1E3 + pkt_gps_time.tv_nsec / 1E6; + j = snprintf((char *)(buff_up + buff_index), TX_BUFF_SIZE-buff_index, ",\"tmms\":%llu", + pkt_gps_time_ms); /* GPS time in milliseconds since 06.Jan.1980 */ + if (j > 0) { + buff_index += j; + } else { + MSG("ERROR: [up] snprintf failed line %u\n", (__LINE__ - 4)); + exit(EXIT_FAILURE); + } + } + } + + /* Packet concentrator channel, RF chain & RX frequency, 34-36 useful chars */ + j = snprintf((char *)(buff_up + buff_index), TX_BUFF_SIZE-buff_index, ",\"chan\":%1u,\"rfch\":%1u,\"freq\":%.6lf", p->if_chain, p->rf_chain, ((double)p->freq_hz / 1e6)); + if (j > 0) { + buff_index += j; + } else { + MSG("ERROR: [up] snprintf failed line %u\n", (__LINE__ - 4)); + exit(EXIT_FAILURE); + } + + /* Packet status, 9-10 useful chars */ + switch (p->status) { + case STAT_CRC_OK: + memcpy((void *)(buff_up + buff_index), (void *)",\"stat\":1", 9); + buff_index += 9; + break; + case STAT_CRC_BAD: + memcpy((void *)(buff_up + buff_index), (void *)",\"stat\":-1", 10); + buff_index += 10; + break; + case STAT_NO_CRC: + memcpy((void *)(buff_up + buff_index), (void *)",\"stat\":0", 9); + buff_index += 9; + break; + default: + MSG("ERROR: [up] received packet with unknown status\n"); + memcpy((void *)(buff_up + buff_index), (void *)",\"stat\":?", 9); + buff_index += 9; + exit(EXIT_FAILURE); + } + + /* Packet modulation, 13-14 useful chars */ + if (p->modulation == MOD_LORA) { + memcpy((void *)(buff_up + buff_index), (void *)",\"modu\":\"LORA\"", 14); + buff_index += 14; + + /* Lora datarate & bandwidth, 16-19 useful chars */ + switch (p->datarate) { + case DR_LORA_SF7: + memcpy((void *)(buff_up + buff_index), (void *)",\"datr\":\"SF7", 12); + buff_index += 12; + break; + case DR_LORA_SF8: + memcpy((void *)(buff_up + buff_index), (void *)",\"datr\":\"SF8", 12); + buff_index += 12; + break; + case DR_LORA_SF9: + memcpy((void *)(buff_up + buff_index), (void *)",\"datr\":\"SF9", 12); + buff_index += 12; + break; + case DR_LORA_SF10: + memcpy((void *)(buff_up + buff_index), (void *)",\"datr\":\"SF10", 13); + buff_index += 13; + break; + case DR_LORA_SF11: + memcpy((void *)(buff_up + buff_index), (void *)",\"datr\":\"SF11", 13); + buff_index += 13; + break; + case DR_LORA_SF12: + memcpy((void *)(buff_up + buff_index), (void *)",\"datr\":\"SF12", 13); + buff_index += 13; + break; + default: + 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); + } + switch (p->bandwidth) { + case BW_125KHZ: + memcpy((void *)(buff_up + buff_index), (void *)"BW125\"", 6); + buff_index += 6; + break; + case BW_250KHZ: + memcpy((void *)(buff_up + buff_index), (void *)"BW250\"", 6); + buff_index += 6; + break; + case BW_500KHZ: + memcpy((void *)(buff_up + buff_index), (void *)"BW500\"", 6); + buff_index += 6; + break; + default: + MSG("ERROR: [up] lora packet with unknown bandwidth\n"); + memcpy((void *)(buff_up + buff_index), (void *)"BW?\"", 4); + buff_index += 4; + exit(EXIT_FAILURE); + } + + /* Packet ECC coding rate, 11-13 useful chars */ + switch (p->coderate) { + case CR_LORA_4_5: + memcpy((void *)(buff_up + buff_index), (void *)",\"codr\":\"4/5\"", 13); + buff_index += 13; + break; + case CR_LORA_4_6: + memcpy((void *)(buff_up + buff_index), (void *)",\"codr\":\"4/6\"", 13); + buff_index += 13; + break; + case CR_LORA_4_7: + memcpy((void *)(buff_up + buff_index), (void *)",\"codr\":\"4/7\"", 13); + buff_index += 13; + break; + case CR_LORA_4_8: + memcpy((void *)(buff_up + buff_index), (void *)",\"codr\":\"4/8\"", 13); + buff_index += 13; + break; + case 0: /* treat the CR0 case (mostly false sync) */ + memcpy((void *)(buff_up + buff_index), (void *)",\"codr\":\"OFF\"", 13); + buff_index += 13; + break; + default: + MSG("ERROR: [up] lora packet with unknown coderate\n"); + memcpy((void *)(buff_up + buff_index), (void *)",\"codr\":\"?\"", 11); + buff_index += 11; + exit(EXIT_FAILURE); + } + + /* Lora SNR, 11-13 useful chars */ + j = snprintf((char *)(buff_up + buff_index), TX_BUFF_SIZE-buff_index, ",\"lsnr\":%.1f", p->snr); + if (j > 0) { + buff_index += j; + } else { + MSG("ERROR: [up] snprintf failed line %u\n", (__LINE__ - 4)); + exit(EXIT_FAILURE); + } + } else if (p->modulation == MOD_FSK) { + memcpy((void *)(buff_up + buff_index), (void *)",\"modu\":\"FSK\"", 13); + buff_index += 13; + + /* FSK datarate, 11-14 useful chars */ + j = snprintf((char *)(buff_up + buff_index), TX_BUFF_SIZE-buff_index, ",\"datr\":%u", p->datarate); + if (j > 0) { + buff_index += j; + } else { + MSG("ERROR: [up] snprintf failed line %u\n", (__LINE__ - 4)); + exit(EXIT_FAILURE); + } + } else { + MSG("ERROR: [up] received packet with unknown modulation\n"); + exit(EXIT_FAILURE); + } + + /* Packet RSSI, payload size, 18-23 useful chars */ + j = snprintf((char *)(buff_up + buff_index), TX_BUFF_SIZE-buff_index, ",\"rssi\":%.0f,\"size\":%u", p->rssi, p->size); + if (j > 0) { + buff_index += j; + } else { + MSG("ERROR: [up] snprintf failed line %u\n", (__LINE__ - 4)); + exit(EXIT_FAILURE); + } + + /* Packet base64-encoded payload, 14-350 useful chars */ + memcpy((void *)(buff_up + buff_index), (void *)",\"data\":\"", 9); + buff_index += 9; + j = bin_to_b64(p->payload, p->size, (char *)(buff_up + buff_index), 341); /* 255 bytes = 340 chars in b64 + null char */ + if (j>=0) { + buff_index += j; + } else { + MSG("ERROR: [up] bin_to_b64 failed line %u\n", (__LINE__ - 5)); + exit(EXIT_FAILURE); + } + buff_up[buff_index] = '"'; + ++buff_index; + + /* End of packet serialization */ + buff_up[buff_index] = '}'; + ++buff_index; + ++pkt_in_dgram; + } + + /* restart fetch sequence without sending empty JSON if all packets have been filtered out */ + if (pkt_in_dgram == 0) { + if (send_report == true) { + /* need to clean up the beginning of the payload */ + buff_index -= 8; /* removes "rxpk":[ */ + } else { + /* all packet have been filtered out and no report, restart loop */ + continue; + } + } else { + /* end of packet array */ + buff_up[buff_index] = ']'; + ++buff_index; + /* add separator if needed */ + if (send_report == true) { + buff_up[buff_index] = ','; + ++buff_index; + } + } + + /* add status report if a new one is available */ + if (send_report == true) { + pthread_mutex_lock(&mx_stat_rep); + report_ready = false; + j = snprintf((char *)(buff_up + buff_index), TX_BUFF_SIZE-buff_index, "%s", status_report); + pthread_mutex_unlock(&mx_stat_rep); + if (j > 0) { + buff_index += j; + } else { + MSG("ERROR: [up] snprintf failed line %u\n", (__LINE__ - 5)); + exit(EXIT_FAILURE); + } + } + + /* end of JSON datagram payload */ + buff_up[buff_index] = '}'; + ++buff_index; + buff_up[buff_index] = 0; /* add string terminator, for safety */ + + printf("\nJSON up: %s\n", (char *)(buff_up + 12)); /* DEBUG: display JSON payload */ + + /* send datagram to server */ + send(sock_up, (void *)buff_up, buff_index, 0); + clock_gettime(CLOCK_MONOTONIC, &send_time); + pthread_mutex_lock(&mx_meas_up); + meas_up_dgram_sent += 1; + meas_up_network_byte += buff_index; + + /* wait for acknowledge (in 2 times, to catch extra packets) */ + for (i=0; i<2; ++i) { + j = recv(sock_up, (void *)buff_ack, sizeof buff_ack, 0); + clock_gettime(CLOCK_MONOTONIC, &recv_time); + if (j == -1) { + if (errno == EAGAIN) { /* timeout */ + continue; + } else { /* server connection error */ + break; + } + } else if ((j < 4) || (buff_ack[0] != PROTOCOL_VERSION) || (buff_ack[3] != PKT_PUSH_ACK)) { + //MSG("WARNING: [up] ignored invalid non-ACL packet\n"); + continue; + } else if ((buff_ack[1] != token_h) || (buff_ack[2] != token_l)) { + //MSG("WARNING: [up] ignored out-of sync ACK packet\n"); + continue; + } else { + MSG("INFO: [up] PUSH_ACK received in %i ms\n", (int)(1000 * difftimespec(recv_time, send_time))); + meas_up_ack_rcv += 1; + break; + } + } + pthread_mutex_unlock(&mx_meas_up); + } + MSG("\nINFO: End of upstream thread\n"); +} + +/* -------------------------------------------------------------------------- */ +/* --- THREAD 2: POLLING SERVER AND ENQUEUING PACKETS IN JIT QUEUE ---------- */ + +void thread_down(void) { + int i; /* loop variables */ + + /* configuration and metadata for an outbound packet */ + struct lgw_pkt_tx_s txpkt; + bool sent_immediate = false; /* option to sent the packet immediately */ + + /* local timekeeping variables */ + struct timespec send_time; /* time of the pull request */ + struct timespec recv_time; /* time of return from recv socket call */ + + /* data buffers */ + uint8_t buff_down[1000]; /* buffer to receive downstream packets */ + uint8_t buff_req[12]; /* buffer to compose pull requests */ + int msg_len; + + /* protocol variables */ + uint8_t token_h; /* random token for acknowledgement matching */ + uint8_t token_l; /* random token for acknowledgement matching */ + bool req_ack = false; /* keep track of whether PULL_DATA was acknowledged or not */ + + /* JSON parsing variables */ + JSON_Value *root_val = NULL; + JSON_Object *txpk_obj = NULL; + JSON_Value *val = NULL; /* needed to detect the absence of some fields */ + const char *str; /* pointer to sub-strings in the JSON data */ + short x0, x1; + uint64_t x2; + double x3, x4; + + /* variables to send on GPS timestamp */ + struct tref local_ref; /* time reference used for GPS <-> timestamp conversion */ + struct timespec gps_tx; /* GPS time that needs to be converted to timestamp */ + + /* beacon variables */ + struct lgw_pkt_tx_s beacon_pkt; + uint8_t beacon_chan; + uint8_t beacon_loop; + size_t beacon_RFU1_size = 0; + size_t beacon_RFU2_size = 0; + uint8_t beacon_pyld_idx = 0; + time_t diff_beacon_time; + struct timespec next_beacon_gps_time; /* gps time of next beacon packet */ + struct timespec last_beacon_gps_time; /* gps time of last enqueued beacon packet */ + int retry; + + /* beacon data fields, byte 0 is Least Significant Byte */ + int32_t field_latitude; /* 3 bytes, derived from reference latitude */ + int32_t field_longitude; /* 3 bytes, derived from reference longitude */ + uint16_t field_crc1, field_crc2; + + /* auto-quit variable */ + uint32_t autoquit_cnt = 0; /* count the number of PULL_DATA sent since the latest PULL_ACK */ + + /* Just In Time downlink */ + struct timeval current_unix_time; + struct timeval current_concentrator_time; + enum jit_error_e jit_result = JIT_ERROR_OK; + enum jit_pkt_type_e downlink_type; + + /* set downstream socket RX timeout */ + i = setsockopt(sock_down, SOL_SOCKET, SO_RCVTIMEO, (void *)&pull_timeout, sizeof pull_timeout); + if (i != 0) { + MSG("ERROR: [down] setsockopt returned %s\n", strerror(errno)); + exit(EXIT_FAILURE); + } + + /* pre-fill the pull request buffer with fixed fields */ + buff_req[0] = PROTOCOL_VERSION; + buff_req[3] = PKT_PULL_DATA; + *(uint32_t *)(buff_req + 4) = net_mac_h; + *(uint32_t *)(buff_req + 8) = net_mac_l; + + /* beacon variables initialization */ + last_beacon_gps_time.tv_sec = 0; + last_beacon_gps_time.tv_nsec = 0; + + /* beacon packet parameters */ + beacon_pkt.tx_mode = ON_GPS; /* send on PPS pulse */ + beacon_pkt.rf_chain = 0; /* antenna A */ + beacon_pkt.rf_power = beacon_power; + beacon_pkt.modulation = MOD_LORA; + switch (beacon_bw_hz) { + case 125000: + beacon_pkt.bandwidth = BW_125KHZ; + break; + case 500000: + beacon_pkt.bandwidth = BW_500KHZ; + break; + default: + /* should not happen */ + MSG("ERROR: unsupported bandwidth for beacon\n"); + exit(EXIT_FAILURE); + } + switch (beacon_datarate) { + case 8: + beacon_pkt.datarate = DR_LORA_SF8; + beacon_RFU1_size = 1; + beacon_RFU2_size = 3; + break; + case 9: + beacon_pkt.datarate = DR_LORA_SF9; + beacon_RFU1_size = 2; + beacon_RFU2_size = 0; + break; + case 10: + beacon_pkt.datarate = DR_LORA_SF10; + beacon_RFU1_size = 3; + beacon_RFU2_size = 1; + break; + case 12: + beacon_pkt.datarate = DR_LORA_SF12; + beacon_RFU1_size = 5; + beacon_RFU2_size = 3; + break; + default: + /* should not happen */ + MSG("ERROR: unsupported datarate for beacon\n"); + exit(EXIT_FAILURE); + } + beacon_pkt.size = beacon_RFU1_size + 4 + 2 + 7 + beacon_RFU2_size + 2; + beacon_pkt.coderate = CR_LORA_4_5; + beacon_pkt.invert_pol = false; + beacon_pkt.preamble = 10; + beacon_pkt.no_crc = true; + beacon_pkt.no_header = true; + + /* network common part beacon fields (little endian) */ + for (i = 0; i < (int)beacon_RFU1_size; i++) { + beacon_pkt.payload[beacon_pyld_idx++] = 0x0; + } + + /* network common part beacon fields (little endian) */ + beacon_pyld_idx += 4; /* time (variable), filled later */ + beacon_pyld_idx += 2; /* crc1 (variable), filled later */ + + /* calculate the latitude and longitude that must be publicly reported */ + field_latitude = (int32_t)((reference_coord.lat / 90.0) * (double)(1<<23)); + if (field_latitude > (int32_t)0x007FFFFF) { + field_latitude = (int32_t)0x007FFFFF; /* +90 N is represented as 89.99999 N */ + } else if (field_latitude < (int32_t)0xFF800000) { + field_latitude = (int32_t)0xFF800000; + } + field_longitude = (int32_t)((reference_coord.lon / 180.0) * (double)(1<<23)); + if (field_longitude > (int32_t)0x007FFFFF) { + field_longitude = (int32_t)0x007FFFFF; /* +180 E is represented as 179.99999 E */ + } else if (field_longitude < (int32_t)0xFF800000) { + field_longitude = (int32_t)0xFF800000; + } + + /* gateway specific beacon fields */ + beacon_pkt.payload[beacon_pyld_idx++] = beacon_infodesc; + beacon_pkt.payload[beacon_pyld_idx++] = 0xFF & field_latitude; + beacon_pkt.payload[beacon_pyld_idx++] = 0xFF & (field_latitude >> 8); + beacon_pkt.payload[beacon_pyld_idx++] = 0xFF & (field_latitude >> 16); + beacon_pkt.payload[beacon_pyld_idx++] = 0xFF & field_longitude; + beacon_pkt.payload[beacon_pyld_idx++] = 0xFF & (field_longitude >> 8); + beacon_pkt.payload[beacon_pyld_idx++] = 0xFF & (field_longitude >> 16); + + /* RFU */ + for (i = 0; i < (int)beacon_RFU2_size; i++) { + beacon_pkt.payload[beacon_pyld_idx++] = 0x0; + } + + /* CRC of the beacon gateway specific part fields */ + field_crc2 = crc16((beacon_pkt.payload + 6 + beacon_RFU1_size), 7 + beacon_RFU2_size); + beacon_pkt.payload[beacon_pyld_idx++] = 0xFF & field_crc2; + beacon_pkt.payload[beacon_pyld_idx++] = 0xFF & (field_crc2 >> 8); + + /* JIT queue initialization */ + jit_queue_init(&jit_queue); + + while (!exit_sig && !quit_sig) { + + /* auto-quit if the threshold is crossed */ + if ((autoquit_threshold > 0) && (autoquit_cnt >= autoquit_threshold)) { + exit_sig = true; + MSG("INFO: [down] the last %u PULL_DATA were not ACKed, exiting application\n", autoquit_threshold); + break; + } + + /* generate random token for request */ + token_h = (uint8_t)rand(); /* random token */ + token_l = (uint8_t)rand(); /* random token */ + buff_req[1] = token_h; + buff_req[2] = token_l; + + /* send PULL request and record time */ + send(sock_down, (void *)buff_req, sizeof buff_req, 0); + clock_gettime(CLOCK_MONOTONIC, &send_time); + pthread_mutex_lock(&mx_meas_dw); + meas_dw_pull_sent += 1; + pthread_mutex_unlock(&mx_meas_dw); + req_ack = false; + autoquit_cnt++; + + /* listen to packets and process them until a new PULL request must be sent */ + recv_time = send_time; + while ((int)difftimespec(recv_time, send_time) < keepalive_time) { + + /* try to receive a datagram */ + msg_len = recv(sock_down, (void *)buff_down, (sizeof buff_down)-1, 0); + clock_gettime(CLOCK_MONOTONIC, &recv_time); + + /* Pre-allocate beacon slots in JiT queue, to check downlink collisions */ + beacon_loop = JIT_NUM_BEACON_IN_QUEUE - jit_queue.num_beacon; + retry = 0; + while (beacon_loop && (beacon_period != 0)) { + pthread_mutex_lock(&mx_timeref); + /* Wait for GPS to be ready before inserting beacons in JiT queue */ + if ((gps_ref_valid == true) && (xtal_correct_ok == true)) { + + /* compute GPS time for next beacon to come */ + /* LoRaWAN: T = k*beacon_period + TBeaconDelay */ + /* with TBeaconDelay = [1.5ms +/- 1µs]*/ + if (last_beacon_gps_time.tv_sec == 0) { + /* if no beacon has been queued, get next slot from current GPS time */ + diff_beacon_time = time_reference_gps.gps.tv_sec % ((time_t)beacon_period); + next_beacon_gps_time.tv_sec = time_reference_gps.gps.tv_sec + + ((time_t)beacon_period - diff_beacon_time); + } else { + /* if there is already a beacon, take it as reference */ + next_beacon_gps_time.tv_sec = last_beacon_gps_time.tv_sec + beacon_period; + } + /* now we can add a beacon_period to the reference to get next beacon GPS time */ + next_beacon_gps_time.tv_sec += (retry * beacon_period); + next_beacon_gps_time.tv_nsec = 0; + +#if DEBUG_BEACON + { + time_t time_unix; + + time_unix = time_reference_gps.gps.tv_sec + UNIX_GPS_EPOCH_OFFSET; + MSG_DEBUG(DEBUG_BEACON, "GPS-now : %s", ctime(&time_unix)); + time_unix = last_beacon_gps_time.tv_sec + UNIX_GPS_EPOCH_OFFSET; + MSG_DEBUG(DEBUG_BEACON, "GPS-last: %s", ctime(&time_unix)); + time_unix = next_beacon_gps_time.tv_sec + UNIX_GPS_EPOCH_OFFSET; + MSG_DEBUG(DEBUG_BEACON, "GPS-next: %s", ctime(&time_unix)); + } +#endif + + /* convert GPS time to concentrator time, and set packet counter for JiT trigger */ + lgw_gps2cnt(time_reference_gps, next_beacon_gps_time, &(beacon_pkt.count_us)); + pthread_mutex_unlock(&mx_timeref); + + /* apply frequency correction to beacon TX frequency */ + if (beacon_freq_nb > 1) { + beacon_chan = (next_beacon_gps_time.tv_sec / beacon_period) % beacon_freq_nb; /* floor rounding */ + } else { + beacon_chan = 0; + } + /* Compute beacon frequency */ + beacon_pkt.freq_hz = beacon_freq_hz + (beacon_chan * beacon_freq_step); + + /* load time in beacon payload */ + beacon_pyld_idx = beacon_RFU1_size; + beacon_pkt.payload[beacon_pyld_idx++] = 0xFF & next_beacon_gps_time.tv_sec; + beacon_pkt.payload[beacon_pyld_idx++] = 0xFF & (next_beacon_gps_time.tv_sec >> 8); + beacon_pkt.payload[beacon_pyld_idx++] = 0xFF & (next_beacon_gps_time.tv_sec >> 16); + beacon_pkt.payload[beacon_pyld_idx++] = 0xFF & (next_beacon_gps_time.tv_sec >> 24); + + /* calculate CRC */ + field_crc1 = crc16(beacon_pkt.payload, 4 + beacon_RFU1_size); /* CRC for the network common part */ + beacon_pkt.payload[beacon_pyld_idx++] = 0xFF & field_crc1; + beacon_pkt.payload[beacon_pyld_idx++] = 0xFF & (field_crc1 >> 8); + + /* Insert beacon packet in JiT queue */ + gettimeofday(¤t_unix_time, NULL); + get_concentrator_time(¤t_concentrator_time, current_unix_time); + jit_result = jit_enqueue(&jit_queue, ¤t_concentrator_time, &beacon_pkt, JIT_PKT_TYPE_BEACON); + if (jit_result == JIT_ERROR_OK) { + /* update stats */ + pthread_mutex_lock(&mx_meas_dw); + meas_nb_beacon_queued += 1; + pthread_mutex_unlock(&mx_meas_dw); + + /* One more beacon in the queue */ + beacon_loop--; + retry = 0; + last_beacon_gps_time.tv_sec = next_beacon_gps_time.tv_sec; /* keep this beacon time as reference for next one to be programmed */ + + /* display beacon payload */ + MSG("INFO: Beacon queued (count_us=%u, freq_hz=%u, size=%u):\n", beacon_pkt.count_us, beacon_pkt.freq_hz, beacon_pkt.size); + printf( " => " ); + for (i = 0; i < beacon_pkt.size; ++i) { + MSG("%02X ", beacon_pkt.payload[i]); + } + MSG("\n"); + } else { + MSG_DEBUG(DEBUG_BEACON, "--> beacon queuing failed with %d\n", jit_result); + /* update stats */ + pthread_mutex_lock(&mx_meas_dw); + if (jit_result != JIT_ERROR_COLLISION_BEACON) { + meas_nb_beacon_rejected += 1; + } + pthread_mutex_unlock(&mx_meas_dw); + /* In case previous enqueue failed, we retry one period later until it succeeds */ + /* Note: In case the GPS has been unlocked for a while, there can be lots of retries */ + /* to be done from last beacon time to a new valid one */ + retry++; + MSG_DEBUG(DEBUG_BEACON, "--> beacon queuing retry=%d\n", retry); + } + } else { + pthread_mutex_unlock(&mx_timeref); + break; + } + } + + /* if no network message was received, got back to listening sock_down socket */ + if (msg_len == -1) { + //MSG("WARNING: [down] recv returned %s\n", strerror(errno)); /* too verbose */ + continue; + } + + /* if the datagram does not respect protocol, just ignore it */ + if ((msg_len < 4) || (buff_down[0] != PROTOCOL_VERSION) || ((buff_down[3] != PKT_PULL_RESP) && (buff_down[3] != PKT_PULL_ACK))) { + MSG("WARNING: [down] ignoring invalid packet len=%d, protocol_version=%d, id=%d\n", + msg_len, buff_down[0], buff_down[3]); + continue; + } + + /* if the datagram is an ACK, check token */ + if (buff_down[3] == PKT_PULL_ACK) { + if ((buff_down[1] == token_h) && (buff_down[2] == token_l)) { + if (req_ack) { + MSG("INFO: [down] duplicate ACK received :)\n"); + } else { /* if that packet was not already acknowledged */ + req_ack = true; + autoquit_cnt = 0; + pthread_mutex_lock(&mx_meas_dw); + meas_dw_ack_rcv += 1; + pthread_mutex_unlock(&mx_meas_dw); + MSG("INFO: [down] PULL_ACK received in %i ms\n", (int)(1000 * difftimespec(recv_time, send_time))); + } + } else { /* out-of-sync token */ + MSG("INFO: [down] received out-of-sync ACK\n"); + } + continue; + } + + /* the datagram is a PULL_RESP */ + buff_down[msg_len] = 0; /* add string terminator, just to be safe */ + MSG("INFO: [down] PULL_RESP received - token[%d:%d] :)\n", buff_down[1], buff_down[2]); /* very verbose */ + printf("\nJSON down: %s\n", (char *)(buff_down + 4)); /* DEBUG: display JSON payload */ + + /* initialize TX struct and try to parse JSON */ + memset(&txpkt, 0, sizeof txpkt); + root_val = json_parse_string_with_comments((const char *)(buff_down + 4)); /* JSON offset */ + if (root_val == NULL) { + MSG("WARNING: [down] invalid JSON, TX aborted\n"); + continue; + } + + /* look for JSON sub-object 'txpk' */ + txpk_obj = json_object_get_object(json_value_get_object(root_val), "txpk"); + if (txpk_obj == NULL) { + MSG("WARNING: [down] no \"txpk\" object in JSON, TX aborted\n"); + json_value_free(root_val); + continue; + } + + /* Parse "immediate" tag, or target timestamp, or UTC time to be converted by GPS (mandatory) */ + i = json_object_get_boolean(txpk_obj,"imme"); /* can be 1 if true, 0 if false, or -1 if not a JSON boolean */ + if (i == 1) { + /* TX procedure: send immediately */ + sent_immediate = true; + downlink_type = JIT_PKT_TYPE_DOWNLINK_CLASS_C; + MSG("INFO: [down] a packet will be sent in \"immediate\" mode\n"); + } else { + sent_immediate = false; + val = json_object_get_value(txpk_obj,"tmst"); + if (val != NULL) { + /* TX procedure: send on timestamp value */ + txpkt.count_us = (uint32_t)json_value_get_number(val); + + /* Concentrator timestamp is given, we consider it is a Class A downlink */ + downlink_type = JIT_PKT_TYPE_DOWNLINK_CLASS_A; + } else { + /* TX procedure: send on GPS time (converted to timestamp value) */ + val = json_object_get_value(txpk_obj, "tmms"); + if (val == NULL) { + MSG("WARNING: [down] no mandatory \"txpk.tmst\" or \"txpk.tmms\" objects in JSON, TX aborted\n"); + json_value_free(root_val); + continue; + } + if (gps_enabled == true) { + pthread_mutex_lock(&mx_timeref); + if (gps_ref_valid == true) { + local_ref = time_reference_gps; + pthread_mutex_unlock(&mx_timeref); + } else { + pthread_mutex_unlock(&mx_timeref); + MSG("WARNING: [down] no valid GPS time reference yet, impossible to send packet on specific GPS time, TX aborted\n"); + json_value_free(root_val); + + /* send acknoledge datagram to server */ + send_tx_ack(buff_down[1], buff_down[2], JIT_ERROR_GPS_UNLOCKED); + continue; + } + } else { + MSG("WARNING: [down] GPS disabled, impossible to send packet on specific GPS time, TX aborted\n"); + json_value_free(root_val); + + /* send acknoledge datagram to server */ + send_tx_ack(buff_down[1], buff_down[2], JIT_ERROR_GPS_UNLOCKED); + continue; + } + + /* Get GPS time from JSON */ + x2 = (uint64_t)json_value_get_number(val); + + /* Convert GPS time from milliseconds to timespec */ + x3 = modf((double)x2/1E3, &x4); + gps_tx.tv_sec = (time_t)x4; /* get seconds from integer part */ + gps_tx.tv_nsec = (long)(x3 * 1E9); /* get nanoseconds from fractional part */ + + /* transform GPS time to timestamp */ + i = lgw_gps2cnt(local_ref, gps_tx, &(txpkt.count_us)); + if (i != LGW_GPS_SUCCESS) { + MSG("WARNING: [down] could not convert GPS time to timestamp, TX aborted\n"); + json_value_free(root_val); + continue; + } else { + MSG("INFO: [down] a packet will be sent on timestamp value %u (calculated from GPS time)\n", txpkt.count_us); + } + + /* GPS timestamp is given, we consider it is a Class B downlink */ + downlink_type = JIT_PKT_TYPE_DOWNLINK_CLASS_B; + } + } + + /* Parse "No CRC" flag (optional field) */ + val = json_object_get_value(txpk_obj,"ncrc"); + if (val != NULL) { + txpkt.no_crc = (bool)json_value_get_boolean(val); + } + + /* parse target frequency (mandatory) */ + val = json_object_get_value(txpk_obj,"freq"); + if (val == NULL) { + MSG("WARNING: [down] no mandatory \"txpk.freq\" object in JSON, TX aborted\n"); + json_value_free(root_val); + continue; + } + txpkt.freq_hz = (uint32_t)((double)(1.0e6) * json_value_get_number(val)); + + /* parse RF chain used for TX (mandatory) */ + val = json_object_get_value(txpk_obj,"rfch"); + if (val == NULL) { + MSG("WARNING: [down] no mandatory \"txpk.rfch\" object in JSON, TX aborted\n"); + json_value_free(root_val); + continue; + } + txpkt.rf_chain = (uint8_t)json_value_get_number(val); + + /* parse TX power (optional field) */ + val = json_object_get_value(txpk_obj,"powe"); + if (val != NULL) { + txpkt.rf_power = (int8_t)json_value_get_number(val) - antenna_gain; + } + + /* Parse modulation (mandatory) */ + str = json_object_get_string(txpk_obj, "modu"); + if (str == NULL) { + MSG("WARNING: [down] no mandatory \"txpk.modu\" object in JSON, TX aborted\n"); + json_value_free(root_val); + continue; + } + if (strcmp(str, "LORA") == 0) { + /* Lora modulation */ + txpkt.modulation = MOD_LORA; + + /* Parse Lora spreading-factor and modulation bandwidth (mandatory) */ + str = json_object_get_string(txpk_obj, "datr"); + if (str == NULL) { + MSG("WARNING: [down] no mandatory \"txpk.datr\" object in JSON, TX aborted\n"); + json_value_free(root_val); + continue; + } + i = sscanf(str, "SF%2hdBW%3hd", &x0, &x1); + if (i != 2) { + MSG("WARNING: [down] format error in \"txpk.datr\", TX aborted\n"); + json_value_free(root_val); + continue; + } + switch (x0) { + case 7: txpkt.datarate = DR_LORA_SF7; break; + case 8: txpkt.datarate = DR_LORA_SF8; break; + case 9: txpkt.datarate = DR_LORA_SF9; break; + case 10: txpkt.datarate = DR_LORA_SF10; break; + case 11: txpkt.datarate = DR_LORA_SF11; break; + case 12: txpkt.datarate = DR_LORA_SF12; break; + default: + MSG("WARNING: [down] format error in \"txpk.datr\", invalid SF, TX aborted\n"); + json_value_free(root_val); + continue; + } + switch (x1) { + case 125: txpkt.bandwidth = BW_125KHZ; break; + case 250: txpkt.bandwidth = BW_250KHZ; break; + case 500: txpkt.bandwidth = BW_500KHZ; break; + default: + MSG("WARNING: [down] format error in \"txpk.datr\", invalid BW, TX aborted\n"); + json_value_free(root_val); + continue; + } + + /* Parse ECC coding rate (optional field) */ + str = json_object_get_string(txpk_obj, "codr"); + if (str == NULL) { + MSG("WARNING: [down] no mandatory \"txpk.codr\" object in json, TX aborted\n"); + json_value_free(root_val); + continue; + } + if (strcmp(str, "4/5") == 0) txpkt.coderate = CR_LORA_4_5; + else if (strcmp(str, "4/6") == 0) txpkt.coderate = CR_LORA_4_6; + else if (strcmp(str, "2/3") == 0) txpkt.coderate = CR_LORA_4_6; + else if (strcmp(str, "4/7") == 0) txpkt.coderate = CR_LORA_4_7; + else if (strcmp(str, "4/8") == 0) txpkt.coderate = CR_LORA_4_8; + else if (strcmp(str, "1/2") == 0) txpkt.coderate = CR_LORA_4_8; + else { + MSG("WARNING: [down] format error in \"txpk.codr\", TX aborted\n"); + json_value_free(root_val); + continue; + } + + /* Parse signal polarity switch (optional field) */ + val = json_object_get_value(txpk_obj,"ipol"); + if (val != NULL) { + txpkt.invert_pol = (bool)json_value_get_boolean(val); + } + + /* parse Lora preamble length (optional field, optimum min value enforced) */ + val = json_object_get_value(txpk_obj,"prea"); + if (val != NULL) { + i = (int)json_value_get_number(val); + if (i >= MIN_LORA_PREAMB) { + txpkt.preamble = (uint16_t)i; + } else { + txpkt.preamble = (uint16_t)MIN_LORA_PREAMB; + } + } else { + txpkt.preamble = (uint16_t)STD_LORA_PREAMB; + } + + } else if (strcmp(str, "FSK") == 0) { + /* FSK modulation */ + txpkt.modulation = MOD_FSK; + + /* parse FSK bitrate (mandatory) */ + val = json_object_get_value(txpk_obj,"datr"); + if (val == NULL) { + MSG("WARNING: [down] no mandatory \"txpk.datr\" object in JSON, TX aborted\n"); + json_value_free(root_val); + continue; + } + txpkt.datarate = (uint32_t)(json_value_get_number(val)); + + /* parse frequency deviation (mandatory) */ + val = json_object_get_value(txpk_obj,"fdev"); + if (val == NULL) { + MSG("WARNING: [down] no mandatory \"txpk.fdev\" object in JSON, TX aborted\n"); + json_value_free(root_val); + continue; + } + txpkt.f_dev = (uint8_t)(json_value_get_number(val) / 1000.0); /* JSON value in Hz, txpkt.f_dev in kHz */ + + /* parse FSK preamble length (optional field, optimum min value enforced) */ + val = json_object_get_value(txpk_obj,"prea"); + if (val != NULL) { + i = (int)json_value_get_number(val); + if (i >= MIN_FSK_PREAMB) { + txpkt.preamble = (uint16_t)i; + } else { + txpkt.preamble = (uint16_t)MIN_FSK_PREAMB; + } + } else { + txpkt.preamble = (uint16_t)STD_FSK_PREAMB; + } + + } else { + MSG("WARNING: [down] invalid modulation in \"txpk.modu\", TX aborted\n"); + json_value_free(root_val); + continue; + } + + /* Parse payload length (mandatory) */ + val = json_object_get_value(txpk_obj,"size"); + if (val == NULL) { + MSG("WARNING: [down] no mandatory \"txpk.size\" object in JSON, TX aborted\n"); + json_value_free(root_val); + continue; + } + txpkt.size = (uint16_t)json_value_get_number(val); + + /* Parse payload data (mandatory) */ + str = json_object_get_string(txpk_obj, "data"); + if (str == NULL) { + MSG("WARNING: [down] no mandatory \"txpk.data\" object in JSON, TX aborted\n"); + json_value_free(root_val); + continue; + } + i = b64_to_bin(str, strlen(str), txpkt.payload, sizeof txpkt.payload); + if (i != txpkt.size) { + MSG("WARNING: [down] mismatch between .size and .data size once converter to binary\n"); + } + + /* free the JSON parse tree from memory */ + json_value_free(root_val); + + /* select TX mode */ + if (sent_immediate) { + txpkt.tx_mode = IMMEDIATE; + } else { + txpkt.tx_mode = TIMESTAMPED; + } + + /* record measurement data */ + pthread_mutex_lock(&mx_meas_dw); + 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); + + /* check TX parameter before trying to queue packet */ + jit_result = JIT_ERROR_OK; + if ((txpkt.freq_hz < tx_freq_min[txpkt.rf_chain]) || (txpkt.freq_hz > tx_freq_max[txpkt.rf_chain])) { + jit_result = JIT_ERROR_TX_FREQ; + MSG("ERROR: Packet REJECTED, unsupported frequency - %u (min:%u,max:%u)\n", txpkt.freq_hz, tx_freq_min[txpkt.rf_chain], tx_freq_max[txpkt.rf_chain]); + } + if (jit_result == JIT_ERROR_OK) { + for (i=0; i -1) { + jit_result = jit_dequeue(&jit_queue, pkt_index, &pkt, &pkt_type); + if (jit_result == JIT_ERROR_OK) { + /* update beacon stats */ + if (pkt_type == JIT_PKT_TYPE_BEACON) { + /* Compensate breacon frequency with xtal error */ + pthread_mutex_lock(&mx_xcorr); + pkt.freq_hz = (uint32_t)(xtal_correct * (double)pkt.freq_hz); + MSG_DEBUG(DEBUG_BEACON, "beacon_pkt.freq_hz=%u (xtal_correct=%.15lf)\n", pkt.freq_hz, xtal_correct); + pthread_mutex_unlock(&mx_xcorr); + + /* Update statistics */ + pthread_mutex_lock(&mx_meas_dw); + meas_nb_beacon_sent += 1; + pthread_mutex_unlock(&mx_meas_dw); + MSG("INFO: Beacon dequeued (count_us=%u)\n", pkt.count_us); + } + + /* check if concentrator is free for sending new packet */ + pthread_mutex_lock(&mx_concent); /* may have to wait for a fetch to finish */ + result = lgw_status(TX_STATUS, &tx_status); + pthread_mutex_unlock(&mx_concent); /* free concentrator ASAP */ + if (result == LGW_HAL_ERROR) { + MSG("WARNING: [jit] lgw_status failed\n"); + } else { + if (tx_status == TX_EMITTING) { + MSG("ERROR: concentrator is currently emitting\n"); + print_tx_status(tx_status); + continue; + } else if (tx_status == TX_SCHEDULED) { + MSG("WARNING: a downlink was already scheduled, overwritting it...\n"); + print_tx_status(tx_status); + } else { + /* Nothing to do */ + } + } + + /* send packet to concentrator */ + pthread_mutex_lock(&mx_concent); /* may have to wait for a fetch to finish */ + result = lgw_send(pkt); + pthread_mutex_unlock(&mx_concent); /* free concentrator ASAP */ + if (result == LGW_HAL_ERROR) { + pthread_mutex_lock(&mx_meas_dw); + meas_nb_tx_fail += 1; + pthread_mutex_unlock(&mx_meas_dw); + MSG("WARNING: [jit] lgw_send failed\n"); + continue; + } else { + pthread_mutex_lock(&mx_meas_dw); + meas_nb_tx_ok += 1; + pthread_mutex_unlock(&mx_meas_dw); + MSG_DEBUG(DEBUG_PKT_FWD, "lgw_send done: count_us=%u\n", pkt.count_us); + } + } else { + MSG("ERROR: jit_dequeue failed with %d\n", jit_result); + } + } + } else if (jit_result == JIT_ERROR_EMPTY) { + /* Do nothing, it can happen */ + } else { + MSG("ERROR: jit_peek failed with %d\n", jit_result); + } + } +} + +/* -------------------------------------------------------------------------- */ +/* --- THREAD 4: PARSE GPS MESSAGE AND KEEP GATEWAY IN SYNC ----------------- */ + +static void gps_process_sync(void) { + struct timespec gps_time; + struct timespec utc; + uint32_t trig_tstamp; /* concentrator timestamp associated with PPM pulse */ + int i = lgw_gps_get(&utc, &gps_time, NULL, NULL); + + /* get GPS time for synchronization */ + if (i != LGW_GPS_SUCCESS) { + MSG("WARNING: [gps] could not get GPS time from GPS\n"); + return; + } + + /* get timestamp captured on PPM pulse */ + pthread_mutex_lock(&mx_concent); + i = lgw_get_trigcnt(&trig_tstamp); + pthread_mutex_unlock(&mx_concent); + if (i != LGW_HAL_SUCCESS) { + MSG("WARNING: [gps] failed to read concentrator timestamp\n"); + return; + } + + /* try to update time reference with the new GPS time & timestamp */ + pthread_mutex_lock(&mx_timeref); + i = lgw_gps_sync(&time_reference_gps, trig_tstamp, utc, gps_time); + pthread_mutex_unlock(&mx_timeref); + if (i != LGW_GPS_SUCCESS) { + MSG("WARNING: [gps] GPS out of sync, keeping previous time reference\n"); + } +} + +static void gps_process_coords(void) { + /* position variable */ + struct coord_s coord; + struct coord_s gpserr; + int i = lgw_gps_get(NULL, NULL, &coord, &gpserr); + + /* update gateway coordinates */ + pthread_mutex_lock(&mx_meas_gps); + if (i == LGW_GPS_SUCCESS) { + gps_coord_valid = true; + meas_gps_coord = coord; + meas_gps_err = gpserr; + // TODO: report other GPS statistics (typ. signal quality & integrity) + } else { + gps_coord_valid = false; + } + pthread_mutex_unlock(&mx_meas_gps); +} + +void thread_gps(void) { + /* serial variables */ + char serial_buff[128]; /* buffer to receive GPS data */ + size_t wr_idx = 0; /* pointer to end of chars in buffer */ + + /* variables for PPM pulse GPS synchronization */ + enum gps_msg latest_msg; /* keep track of latest NMEA message parsed */ + + /* initialize some variables before loop */ + memset(serial_buff, 0, sizeof serial_buff); + + int invalid_nb_char_count = 0; + while (!exit_sig && !quit_sig) { + size_t rd_idx = 0; + size_t frame_end_idx = 0; + + /* blocking non-canonical read on serial port */ + ssize_t nb_char = read(gps_tty_fd, serial_buff + wr_idx, LGW_GPS_MIN_MSG_SIZE); + if (nb_char <= 0) { + invalid_nb_char_count++; + if ((invalid_nb_char_count % 20000) == 0){ + MSG("WARNING: [gps] read() returned value %d\n", nb_char); + } + continue; + } + wr_idx += (size_t)nb_char; + + /******************************************* + * Scan buffer for UBX/NMEA sync chars and * + * attempt to decode frame if one is found * + *******************************************/ + while(rd_idx < wr_idx) { + size_t frame_size = 0; + + /* Scan buffer for UBX sync char */ + if(serial_buff[rd_idx] == (char)LGW_GPS_UBX_SYNC_CHAR) { + + /*********************** + * Found UBX sync char * + ***********************/ + latest_msg = lgw_parse_ubx(&serial_buff[rd_idx], (wr_idx - rd_idx), &frame_size); + + if (frame_size > 0) { + if (latest_msg == INCOMPLETE) { + /* UBX header found but frame appears to be missing bytes */ + frame_size = 0; + } else if (latest_msg == INVALID) { + /* message header received but message appears to be corrupted */ + MSG("WARNING: [gps] could not get a valid message from GPS (no time)\n"); + frame_size = 0; + } else if (latest_msg == UBX_NAV_TIMEGPS) { + gps_process_sync(); + } + } + } else if(serial_buff[rd_idx] == LGW_GPS_NMEA_SYNC_CHAR) { + /************************ + * Found NMEA sync char * + ************************/ + /* scan for NMEA end marker (LF = 0x0a) */ + char* nmea_end_ptr = memchr(&serial_buff[rd_idx],(int)0x0a, (wr_idx - rd_idx)); + + if(nmea_end_ptr) { + /* found end marker */ + frame_size = nmea_end_ptr - &serial_buff[rd_idx] + 1; + latest_msg = lgw_parse_nmea(&serial_buff[rd_idx], frame_size); + + if(latest_msg == INVALID || latest_msg == UNKNOWN) { + /* checksum failed */ + frame_size = 0; + } else if (latest_msg == NMEA_RMC) { /* Get location from RMC frames */ + gps_process_coords(); + } + } + } + + if(frame_size > 0) { + /* At this point message is a checksum verified frame + we're processed or ignored. Remove frame from buffer */ + rd_idx += frame_size; + frame_end_idx = rd_idx; + } else { + rd_idx++; + } + } /* ...for(rd_idx = 0... */ + + if(frame_end_idx) { + /* Frames have been processed. Remove bytes to end of last processed frame */ + memcpy(serial_buff, &serial_buff[frame_end_idx], wr_idx - frame_end_idx); + wr_idx -= frame_end_idx; + } /* ...for(rd_idx = 0... */ + + /* Prevent buffer overflow */ + if((sizeof(serial_buff) - wr_idx) < LGW_GPS_MIN_MSG_SIZE) { + memcpy(serial_buff, &serial_buff[LGW_GPS_MIN_MSG_SIZE], wr_idx - LGW_GPS_MIN_MSG_SIZE); + wr_idx -= LGW_GPS_MIN_MSG_SIZE; + } + } + MSG("\nINFO: End of GPS thread\n"); +} + +/* -------------------------------------------------------------------------- */ +/* --- THREAD 5: CHECK TIME REFERENCE AND CALCULATE XTAL CORRECTION --------- */ + +void thread_valid(void) { + + /* GPS reference validation variables */ + long gps_ref_age = 0; + bool ref_valid_local = false; + double xtal_err_cpy; + + /* variables for XTAL correction averaging */ + unsigned init_cpt = 0; + double init_acc = 0.0; + double x; + + /* correction debug */ + // FILE * log_file = NULL; + // time_t now_time; + // char log_name[64]; + + /* initialization */ + // time(&now_time); + // strftime(log_name,sizeof log_name,"xtal_err_%Y%m%dT%H%M%SZ.csv",localtime(&now_time)); + // log_file = fopen(log_name, "w"); + // setbuf(log_file, NULL); + // fprintf(log_file,"\"xtal_correct\",\"XERR_INIT_AVG %u XERR_FILT_COEF %u\"\n", XERR_INIT_AVG, XERR_FILT_COEF); // DEBUG + + /* main loop task */ + while (!exit_sig && !quit_sig) { + wait_ms(1000); + + /* calculate when the time reference was last updated */ + pthread_mutex_lock(&mx_timeref); + gps_ref_age = (long)difftime(time(NULL), time_reference_gps.systime); + if ((gps_ref_age >= 0) && (gps_ref_age <= GPS_REF_MAX_AGE)) { + /* time ref is ok, validate and */ + gps_ref_valid = true; + ref_valid_local = true; + xtal_err_cpy = time_reference_gps.xtal_err; + //printf("XTAL err: %.15lf (1/XTAL_err:%.15lf)\n", xtal_err_cpy, 1/xtal_err_cpy); // DEBUG + } else { + /* time ref is too old, invalidate */ + gps_ref_valid = false; + ref_valid_local = false; + } + pthread_mutex_unlock(&mx_timeref); + + /* manage XTAL correction */ + if (ref_valid_local == false) { + /* couldn't sync, or sync too old -> invalidate XTAL correction */ + pthread_mutex_lock(&mx_xcorr); + xtal_correct_ok = false; + xtal_correct = 1.0; + pthread_mutex_unlock(&mx_xcorr); + init_cpt = 0; + init_acc = 0.0; + } else { + if (init_cpt < XERR_INIT_AVG) { + /* initial accumulation */ + init_acc += xtal_err_cpy; + ++init_cpt; + } else if (init_cpt == XERR_INIT_AVG) { + /* initial average calculation */ + pthread_mutex_lock(&mx_xcorr); + xtal_correct = (double)(XERR_INIT_AVG) / init_acc; + //printf("XERR_INIT_AVG=%d, init_acc=%.15lf\n", XERR_INIT_AVG, init_acc); + xtal_correct_ok = true; + pthread_mutex_unlock(&mx_xcorr); + ++init_cpt; + // fprintf(log_file,"%.18lf,\"average\"\n", xtal_correct); // DEBUG + } else { + /* tracking with low-pass filter */ + x = 1 / xtal_err_cpy; + pthread_mutex_lock(&mx_xcorr); + xtal_correct = xtal_correct - xtal_correct/XERR_FILT_COEF + x/XERR_FILT_COEF; + pthread_mutex_unlock(&mx_xcorr); + // fprintf(log_file,"%.18lf,\"track\"\n", xtal_correct); // DEBUG + } + } + // printf("Time ref: %s, XTAL correct: %s (%.15lf)\n", ref_valid_local?"valid":"invalid", xtal_correct_ok?"valid":"invalid", xtal_correct); // DEBUG + } + MSG("\nINFO: End of validation thread\n"); +} + +/* --- EOF ------------------------------------------------------------------ */ diff --git a/lora/rak2245/loragw_spi.native.c b/lora/rak2245/loragw_spi.native.c new file mode 100644 index 0000000..a4f4b01 --- /dev/null +++ b/lora/rak2245/loragw_spi.native.c @@ -0,0 +1,385 @@ +/* + / _____) _ | | +( (____ _____ ____ _| |_ _____ ____| |__ + \____ \| ___ | (_ _) ___ |/ ___) _ \ + _____) ) ____| | | || |_| ____( (___| | | | +(______/|_____)_|_|_| \__)_____)\____)_| |_| + (C)2013 Semtech-Cycleo + +Description: + Host specific functions to address the LoRa concentrator registers through + a SPI interface. + Single-byte read/write and burst read/write. + Does not handle pagination. + Could be used with multiple SPI ports in parallel (explicit file descriptor) + +License: Revised BSD License, see LICENSE.TXT file include in the project +Maintainer: Sylvain Miermont +*/ + + +/* -------------------------------------------------------------------------- */ +/* --- DEPENDANCIES --------------------------------------------------------- */ + +#include /* C99 types */ +#include /* printf fprintf */ +#include /* malloc free */ +#include /* lseek, close */ +#include /* open */ +#include /* memset */ + +#include +#include + +#include "loragw_spi.h" +#include "loragw_hal.h" + +/* -------------------------------------------------------------------------- */ +/* --- PRIVATE MACROS ------------------------------------------------------- */ + +#define ARRAY_SIZE(a) (sizeof(a) / sizeof((a)[0])) +#if DEBUG_SPI == 1 + #define DEBUG_MSG(str) fprintf(stderr, str) + #define DEBUG_PRINTF(fmt, args...) fprintf(stderr,"%s:%d: "fmt, __FUNCTION__, __LINE__, args) + #define CHECK_NULL(a) if(a==NULL){fprintf(stderr,"%s:%d: ERROR: NULL POINTER AS ARGUMENT\n", __FUNCTION__, __LINE__);return LGW_SPI_ERROR;} +#else + #define DEBUG_MSG(str) + #define DEBUG_PRINTF(fmt, args...) + #define CHECK_NULL(a) if(a==NULL){return LGW_SPI_ERROR;} +#endif + +/* -------------------------------------------------------------------------- */ +/* --- PRIVATE CONSTANTS ---------------------------------------------------- */ + +#define READ_ACCESS 0x00 +#define WRITE_ACCESS 0x80 +#define SPI_SPEED 2000000 +#define SPI_DEV_PATH "/dev/spidev0.0" +//#define SPI_DEV_PATH "/dev/spidev32766.0" + +/* -------------------------------------------------------------------------- */ +/* --- PUBLIC FUNCTIONS DEFINITION ------------------------------------------ */ + +/* SPI initialization and configuration */ +int lgw_spi_open(void **spi_target_ptr) { + int *spi_device = NULL; + int dev; + int a=0, b=0; + int i; + + /* check input variables */ + CHECK_NULL(spi_target_ptr); /* cannot be null, must point on a void pointer (*spi_target_ptr can be null) */ + + /* allocate memory for the device descriptor */ + spi_device = malloc(sizeof(int)); + if (spi_device == NULL) { + DEBUG_MSG("ERROR: MALLOC FAIL\n"); + return LGW_SPI_ERROR; + } + + /* open SPI device */ + dev = open(SPI_DEV_PATH, O_RDWR); + if (dev < 0) { + DEBUG_PRINTF("ERROR: failed to open SPI device %s\n", SPI_DEV_PATH); + return LGW_SPI_ERROR; + } + + /* setting SPI mode to 'mode 0' */ + i = SPI_MODE_0; + a = ioctl(dev, SPI_IOC_WR_MODE, &i); + b = ioctl(dev, SPI_IOC_RD_MODE, &i); + if ((a < 0) || (b < 0)) { + DEBUG_MSG("ERROR: SPI PORT FAIL TO SET IN MODE 0\n"); + close(dev); + free(spi_device); + return LGW_SPI_ERROR; + } + + /* setting SPI max clk (in Hz) */ + i = SPI_SPEED; + a = ioctl(dev, SPI_IOC_WR_MAX_SPEED_HZ, &i); + b = ioctl(dev, SPI_IOC_RD_MAX_SPEED_HZ, &i); + if ((a < 0) || (b < 0)) { + DEBUG_MSG("ERROR: SPI PORT FAIL TO SET MAX SPEED\n"); + close(dev); + free(spi_device); + return LGW_SPI_ERROR; + } + + /* setting SPI to MSB first */ + i = 0; + a = ioctl(dev, SPI_IOC_WR_LSB_FIRST, &i); + b = ioctl(dev, SPI_IOC_RD_LSB_FIRST, &i); + if ((a < 0) || (b < 0)) { + DEBUG_MSG("ERROR: SPI PORT FAIL TO SET MSB FIRST\n"); + close(dev); + free(spi_device); + return LGW_SPI_ERROR; + } + + /* setting SPI to 8 bits per word */ + i = 0; + a = ioctl(dev, SPI_IOC_WR_BITS_PER_WORD, &i); + b = ioctl(dev, SPI_IOC_RD_BITS_PER_WORD, &i); + if ((a < 0) || (b < 0)) { + DEBUG_MSG("ERROR: SPI PORT FAIL TO SET 8 BITS-PER-WORD\n"); + close(dev); + return LGW_SPI_ERROR; + } + + *spi_device = dev; + *spi_target_ptr = (void *)spi_device; + DEBUG_MSG("Note: SPI port opened and configured ok\n"); + return LGW_SPI_SUCCESS; +} + +/* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ */ + +/* SPI release */ +int lgw_spi_close(void *spi_target) { + int spi_device; + int a; + + /* check input variables */ + CHECK_NULL(spi_target); + + /* close file & deallocate file descriptor */ + spi_device = *(int *)spi_target; /* must check that spi_target is not null beforehand */ + a = close(spi_device); + free(spi_target); + + /* determine return code */ + if (a < 0) { + DEBUG_MSG("ERROR: SPI PORT FAILED TO CLOSE\n"); + return LGW_SPI_ERROR; + } else { + DEBUG_MSG("Note: SPI port closed\n"); + return LGW_SPI_SUCCESS; + } +} + +/* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ */ + +/* Simple write */ +int lgw_spi_w(void *spi_target, uint8_t spi_mux_mode, uint8_t spi_mux_target, uint8_t address, uint8_t data) { + int spi_device; + uint8_t out_buf[3]; + uint8_t command_size; + struct spi_ioc_transfer k; + int a; + + /* check input variables */ + CHECK_NULL(spi_target); + if ((address & 0x80) != 0) { + DEBUG_MSG("WARNING: SPI address > 127\n"); + } + + spi_device = *(int *)spi_target; /* must check that spi_target is not null beforehand */ + + /* prepare frame to be sent */ + if (spi_mux_mode == LGW_SPI_MUX_MODE1) { + out_buf[0] = spi_mux_target; + out_buf[1] = WRITE_ACCESS | (address & 0x7F); + out_buf[2] = data; + command_size = 3; + } else { + out_buf[0] = WRITE_ACCESS | (address & 0x7F); + out_buf[1] = data; + command_size = 2; + } + + /* I/O transaction */ + memset(&k, 0, sizeof(k)); /* clear k */ + k.tx_buf = (unsigned long) out_buf; + k.len = command_size; + k.speed_hz = SPI_SPEED; + k.cs_change = 0; + k.bits_per_word = 8; + a = ioctl(spi_device, SPI_IOC_MESSAGE(1), &k); + + /* determine return code */ + if (a != (int)k.len) { + DEBUG_MSG("ERROR: SPI WRITE FAILURE\n"); + return LGW_SPI_ERROR; + } else { + DEBUG_MSG("Note: SPI write success\n"); + return LGW_SPI_SUCCESS; + } +} + +/* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ */ + +/* Simple read */ +int lgw_spi_r(void *spi_target, uint8_t spi_mux_mode, uint8_t spi_mux_target, uint8_t address, uint8_t *data) { + int spi_device; + uint8_t out_buf[3]; + uint8_t command_size; + uint8_t in_buf[ARRAY_SIZE(out_buf)]; + struct spi_ioc_transfer k; + int a; + + /* check input variables */ + CHECK_NULL(spi_target); + if ((address & 0x80) != 0) { + DEBUG_MSG("WARNING: SPI address > 127\n"); + } + CHECK_NULL(data); + + spi_device = *(int *)spi_target; /* must check that spi_target is not null beforehand */ + + /* prepare frame to be sent */ + if (spi_mux_mode == LGW_SPI_MUX_MODE1) { + out_buf[0] = spi_mux_target; + out_buf[1] = READ_ACCESS | (address & 0x7F); + out_buf[2] = 0x00; + command_size = 3; + } else { + out_buf[0] = READ_ACCESS | (address & 0x7F); + out_buf[1] = 0x00; + command_size = 2; + } + + /* I/O transaction */ + memset(&k, 0, sizeof(k)); /* clear k */ + k.tx_buf = (unsigned long) out_buf; + k.rx_buf = (unsigned long) in_buf; + k.len = command_size; + k.cs_change = 0; + a = ioctl(spi_device, SPI_IOC_MESSAGE(1), &k); + + /* determine return code */ + if (a != (int)k.len) { + DEBUG_MSG("ERROR: SPI READ FAILURE\n"); + return LGW_SPI_ERROR; + } else { + DEBUG_MSG("Note: SPI read success\n"); + *data = in_buf[command_size - 1]; + return LGW_SPI_SUCCESS; + } +} + +/* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ */ + +/* Burst (multiple-byte) write */ +int lgw_spi_wb(void *spi_target, uint8_t spi_mux_mode, uint8_t spi_mux_target, uint8_t address, uint8_t *data, uint16_t size) { + int spi_device; + uint8_t command[2]; + uint8_t command_size; + struct spi_ioc_transfer k[2]; + int size_to_do, chunk_size, offset; + int byte_transfered = 0; + int i; + + /* check input parameters */ + CHECK_NULL(spi_target); + if ((address & 0x80) != 0) { + DEBUG_MSG("WARNING: SPI address > 127\n"); + } + CHECK_NULL(data); + if (size == 0) { + DEBUG_MSG("ERROR: BURST OF NULL LENGTH\n"); + return LGW_SPI_ERROR; + } + + spi_device = *(int *)spi_target; /* must check that spi_target is not null beforehand */ + + /* prepare command byte */ + if (spi_mux_mode == LGW_SPI_MUX_MODE1) { + command[0] = spi_mux_target; + command[1] = WRITE_ACCESS | (address & 0x7F); + command_size = 2; + } else { + command[0] = WRITE_ACCESS | (address & 0x7F); + command_size = 1; + } + size_to_do = size; + + /* I/O transaction */ + memset(&k, 0, sizeof(k)); /* clear k */ + k[0].tx_buf = (unsigned long) &command[0]; + k[0].len = command_size; + k[0].cs_change = 0; + k[1].cs_change = 0; + for (i=0; size_to_do > 0; ++i) { + chunk_size = (size_to_do < LGW_BURST_CHUNK) ? size_to_do : LGW_BURST_CHUNK; + offset = i * LGW_BURST_CHUNK; + k[1].tx_buf = (unsigned long)(data + offset); + k[1].len = chunk_size; + byte_transfered += (ioctl(spi_device, SPI_IOC_MESSAGE(2), &k) - k[0].len ); + DEBUG_PRINTF("BURST WRITE: to trans %d # chunk %d # transferred %d \n", size_to_do, chunk_size, byte_transfered); + size_to_do -= chunk_size; /* subtract the quantity of data already transferred */ + } + + /* determine return code */ + if (byte_transfered != size) { + DEBUG_MSG("ERROR: SPI BURST WRITE FAILURE\n"); + return LGW_SPI_ERROR; + } else { + DEBUG_MSG("Note: SPI burst write success\n"); + return LGW_SPI_SUCCESS; + } +} + +/* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ */ + +/* Burst (multiple-byte) read */ +int lgw_spi_rb(void *spi_target, uint8_t spi_mux_mode, uint8_t spi_mux_target, uint8_t address, uint8_t *data, uint16_t size) { + int spi_device; + uint8_t command[2]; + uint8_t command_size; + struct spi_ioc_transfer k[2]; + int size_to_do, chunk_size, offset; + int byte_transfered = 0; + int i; + + /* check input parameters */ + CHECK_NULL(spi_target); + if ((address & 0x80) != 0) { + DEBUG_MSG("WARNING: SPI address > 127\n"); + } + CHECK_NULL(data); + if (size == 0) { + DEBUG_MSG("ERROR: BURST OF NULL LENGTH\n"); + return LGW_SPI_ERROR; + } + + spi_device = *(int *)spi_target; /* must check that spi_target is not null beforehand */ + + /* prepare command byte */ + if (spi_mux_mode == LGW_SPI_MUX_MODE1) { + command[0] = spi_mux_target; + command[1] = READ_ACCESS | (address & 0x7F); + command_size = 2; + } else { + command[0] = READ_ACCESS | (address & 0x7F); + command_size = 1; + } + size_to_do = size; + + /* I/O transaction */ + memset(&k, 0, sizeof(k)); /* clear k */ + k[0].tx_buf = (unsigned long) &command[0]; + k[0].len = command_size; + k[0].cs_change = 0; + k[1].cs_change = 0; + for (i=0; size_to_do > 0; ++i) { + chunk_size = (size_to_do < LGW_BURST_CHUNK) ? size_to_do : LGW_BURST_CHUNK; + offset = i * LGW_BURST_CHUNK; + k[1].rx_buf = (unsigned long)(data + offset); + k[1].len = chunk_size; + byte_transfered += (ioctl(spi_device, SPI_IOC_MESSAGE(2), &k) - k[0].len ); + DEBUG_PRINTF("BURST READ: to trans %d # chunk %d # transferred %d \n", size_to_do, chunk_size, byte_transfered); + size_to_do -= chunk_size; /* subtract the quantity of data already transferred */ + } + + /* determine return code */ + if (byte_transfered != size) { + DEBUG_MSG("ERROR: SPI BURST READ FAILURE\n"); + return LGW_SPI_ERROR; + } else { + DEBUG_MSG("Note: SPI burst read success\n"); + return LGW_SPI_SUCCESS; + } +} + +/* --- EOF ------------------------------------------------------------------ */ diff --git a/lora/rak2247/Makefile-gw b/lora/rak2247/Makefile-gw new file mode 100755 index 0000000..3a1c041 --- /dev/null +++ b/lora/rak2247/Makefile-gw @@ -0,0 +1,27 @@ +### Environment constants + +ARCH ?= +CROSS_COMPILE ?= +export + +### general build targets + +all: + $(MAKE) all -e -C libloragw + $(MAKE) all -e -C util_pkt_logger + $(MAKE) all -e -C util_spi_stress + $(MAKE) all -e -C util_tx_test + $(MAKE) all -e -C util_lbt_test + $(MAKE) all -e -C util_tx_continuous + $(MAKE) all -e -C util_spectral_scan + +clean: + $(MAKE) clean -e -C libloragw + $(MAKE) clean -e -C util_pkt_logger + $(MAKE) clean -e -C util_spi_stress + $(MAKE) clean -e -C util_tx_test + $(MAKE) clean -e -C util_lbt_test + $(MAKE) clean -e -C util_tx_continuous + $(MAKE) clean -e -C util_spectral_scan + +### EOF diff --git a/lora/rak2247/Makefile-gw-lib b/lora/rak2247/Makefile-gw-lib new file mode 100755 index 0000000..567a099 --- /dev/null +++ b/lora/rak2247/Makefile-gw-lib @@ -0,0 +1,113 @@ +### get external defined data + +LIBLORAGW_VERSION := `cat ../VERSION` +include library.cfg + +### constant symbols + +ARCH ?= +CROSS_COMPILE ?= +CC := $(CROSS_COMPILE)gcc +AR := $(CROSS_COMPILE)ar + +CFLAGS := -O2 -Wall -Wextra -std=c99 -Iinc -I. + +OBJDIR = obj +INCLUDES = $(wildcard inc/*.h) +### library.cfg configuration file processing + +ifeq ($(CFG_SPI),native) + CFG_SPI_MSG := Linux native SPI driver + CFG_SPI_OPT := CFG_SPI_NATIVE +else ifeq ($(CFG_SPI),ftdi) + CFG_SPI_MSG := FTDI SPI-over-USB bridge using libmpsse/libftdi/libusb + CFG_SPI_OPT := CFG_SPI_FTDI +else + $(error No SPI physical layer selected, check ../target.cfg file.) +endif + +### linking options + +ifeq ($(CFG_SPI),native) + LIBS := -lloragw -lrt -lm +else ifeq ($(CFG_SPI),ftdi) + LIBS := -lloragw -lrt -lmpsse -lm +endif + +### general build targets + +all: libloragw.a test_loragw_spi test_loragw_reg test_loragw_hal test_loragw_gps test_loragw_cal + +clean: + rm -f libloragw.a + rm -f test_loragw_* + rm -f $(OBJDIR)/*.o + rm -f inc/config.h + +### transpose library.cfg into a C header file : config.h + +inc/config.h: ../VERSION library.cfg + @echo "*** Checking libloragw library configuration ***" + @rm -f $@ + #File initialization + @echo "#ifndef _LORAGW_CONFIGURATION_H" >> $@ + @echo "#define _LORAGW_CONFIGURATION_H" >> $@ + # Release version + @echo "Release version : $(LIBLORAGW_VERSION)" + @echo " #define LIBLORAGW_VERSION "\"$(LIBLORAGW_VERSION)\""" >> $@ + # SPI interface + @echo "SPI interface : $(CFG_SPI_MSG)" + @echo " #define $(CFG_SPI_OPT) 1" >> $@ + # Debug options + @echo " #define DEBUG_AUX $(DEBUG_AUX)" >> $@ + @echo " #define DEBUG_SPI $(DEBUG_SPI)" >> $@ + @echo " #define DEBUG_REG $(DEBUG_REG)" >> $@ + @echo " #define DEBUG_HAL $(DEBUG_HAL)" >> $@ + @echo " #define DEBUG_GPS $(DEBUG_GPS)" >> $@ + @echo " #define DEBUG_GPIO $(DEBUG_GPIO)" >> $@ + @echo " #define DEBUG_LBT $(DEBUG_LBT)" >> $@ + # end of file + @echo "#endif" >> $@ + @echo "*** Configuration seems ok ***" + +### library module target + +$(OBJDIR): + mkdir -p $(OBJDIR) + +$(OBJDIR)/%.o: src/%.c $(INCLUDES) inc/config.h | $(OBJDIR) + $(CC) -c $(CFLAGS) $< -o $@ + +ifeq ($(CFG_SPI),native) +$(OBJDIR)/loragw_spi.o: src/loragw_spi.native.c $(INCLUDES) inc/config.h | $(OBJDIR) + $(CC) -c $(CFLAGS) $< -o $@ +else ifeq ($(CFG_SPI),ftdi) +$(OBJDIR)/loragw_spi.o: src/loragw_spi.ftdi.c $(INCLUDES) inc/config.h | $(OBJDIR) + $(CC) -c $(CFLAGS) $< -o $@ +endif +$(OBJDIR)/loragw_hal.o: src/loragw_hal.c $(INCLUDES) src/arb_fw.var src/agc_fw.var src/cal_fw.var inc/config.h | $(OBJDIR) + $(CC) -c $(CFLAGS) $< -o $@ + +### static library + +libloragw.a: $(OBJDIR)/loragw_hal.o $(OBJDIR)/loragw_gps.o $(OBJDIR)/loragw_reg.o $(OBJDIR)/loragw_spi.o $(OBJDIR)/loragw_aux.o $(OBJDIR)/loragw_radio.o $(OBJDIR)/loragw_fpga.o $(OBJDIR)/loragw_lbt.o + $(AR) rcs $@ $^ + +### test programs + +test_loragw_spi: tst/test_loragw_spi.c libloragw.a + $(CC) $(CFLAGS) -L. $< -o $@ $(LIBS) + +test_loragw_reg: tst/test_loragw_reg.c libloragw.a + $(CC) $(CFLAGS) -L. $< -o $@ $(LIBS) + +test_loragw_hal: tst/test_loragw_hal.c libloragw.a + $(CC) $(CFLAGS) -L. $< -o $@ $(LIBS) + +test_loragw_gps: tst/test_loragw_gps.c libloragw.a + $(CC) $(CFLAGS) -L. $< -o $@ $(LIBS) + +test_loragw_cal: tst/test_loragw_cal.c libloragw.a src/cal_fw.var + $(CC) $(CFLAGS) -L. $< -o $@ $(LIBS) + +### EOF diff --git a/lora/rak2247/Makefile-lbt-test b/lora/rak2247/Makefile-lbt-test new file mode 100644 index 0000000..715e616 --- /dev/null +++ b/lora/rak2247/Makefile-lbt-test @@ -0,0 +1,65 @@ +### Application-specific constants + +APP_NAME := util_lbt_test + +### Environment constants + +LGW_PATH ?= ../libloragw +ARCH ?= +CROSS_COMPILE ?= + +### External constant definitions + +include $(LGW_PATH)/library.cfg + +### Constant symbols + +CC := $(CROSS_COMPILE)gcc +AR := $(CROSS_COMPILE)ar + +CFLAGS=-O2 -Wall -Wextra -std=c99 -Iinc -I. + +OBJDIR = obj + +### Constants for LoRa concentrator HAL library +# List the library sub-modules that are used by the application + +LGW_INC = $(LGW_PATH)/inc/config.h +LGW_INC += $(LGW_PATH)/inc/loragw_reg.h +LGW_INC += $(LGW_PATH)/inc/loragw_fpga.h + +### Linking options + +LIBS := -lloragw -lrt -lm -lmpsse + +### General build targets + +all: $(APP_NAME) + +clean: + rm -f $(OBJDIR)/*.o + rm -f $(APP_NAME) + +### HAL library (do no force multiple library rebuild even with 'make -B') + +$(LGW_PATH)/inc/config.h: + @if test ! -f $@; then \ + $(MAKE) all -C $(LGW_PATH); \ + fi + +$(LGW_PATH)/libloragw.a: $(LGW_INC) + @if test ! -f $@; then \ + $(MAKE) all -C $(LGW_PATH); \ + fi + +### Main program compilation and assembly +$(OBJDIR): + mkdir -p $(OBJDIR) + +$(OBJDIR)/$(APP_NAME).o: src/$(APP_NAME).c $(LGW_INC) | $(OBJDIR) + $(CC) -c $(CFLAGS) -I$(LGW_PATH)/inc $< -o $@ + +$(APP_NAME): $(OBJDIR)/$(APP_NAME).o $(LGW_PATH)/libloragw.a + $(CC) -L$(LGW_PATH) $< -o $@ $(LIBS) + +### EOF diff --git a/lora/rak2247/Makefile-pk b/lora/rak2247/Makefile-pk new file mode 100644 index 0000000..e488a6c --- /dev/null +++ b/lora/rak2247/Makefile-pk @@ -0,0 +1,70 @@ +### Application-specific constants + +APP_NAME := lora_pkt_fwd + +### Environment constants + +LGW_PATH ?= ../../lora_gateway/libloragw +ARCH ?= +CROSS_COMPILE ?= + +OBJDIR = obj +INCLUDES = $(wildcard inc/*.h) + +### External constant definitions +# must get library build option to know if mpsse must be linked or not + +include $(LGW_PATH)/library.cfg +RELEASE_VERSION := `cat ../VERSION` + +### Constant symbols + +CC := $(CROSS_COMPILE)gcc +AR := $(CROSS_COMPILE)ar + +CFLAGS := -O2 -Wall -Wextra -std=c99 -Iinc -I. +VFLAG := -D VERSION_STRING="\"$(RELEASE_VERSION)\"" + +### Constants for Lora concentrator HAL library +# List the library sub-modules that are used by the application + +LGW_INC = +ifneq ($(wildcard $(LGW_PATH)/inc/config.h),) + # only for HAL version 1.3 and beyond + LGW_INC += $(LGW_PATH)/inc/config.h +endif +LGW_INC += $(LGW_PATH)/inc/loragw_hal.h +LGW_INC += $(LGW_PATH)/inc/loragw_gps.h + +### Linking options +ifeq ($(CFG_SPI),native) + LIBS := -lloragw -lrt -lpthread -lm +else ifeq ($(CFG_SPI),ftdi) + LIBS := -lloragw -lrt -lpthread -lmpsse -lm +endif + +### General build targets + +all: $(APP_NAME) + +clean: + rm -f $(OBJDIR)/*.o + rm -f $(APP_NAME) + +### Sub-modules compilation + +$(OBJDIR): + mkdir -p $(OBJDIR) + +$(OBJDIR)/%.o: src/%.c $(INCLUDES) | $(OBJDIR) + $(CC) -c $(CFLAGS) -I$(LGW_PATH)/inc $< -o $@ + +### Main program compilation and assembly + +$(OBJDIR)/$(APP_NAME).o: src/$(APP_NAME).c $(LGW_INC) $(INCLUDES) | $(OBJDIR) + $(CC) -c $(CFLAGS) $(VFLAG) -I$(LGW_PATH)/inc $< -o $@ + +$(APP_NAME): $(OBJDIR)/$(APP_NAME).o $(LGW_PATH)/libloragw.a $(OBJDIR)/parson.o $(OBJDIR)/base64.o $(OBJDIR)/jitqueue.o $(OBJDIR)/timersync.o + $(CC) -L$(LGW_PATH) $< $(OBJDIR)/parson.o $(OBJDIR)/base64.o $(OBJDIR)/jitqueue.o $(OBJDIR)/timersync.o -o $@ $(LIBS) + +### EOF diff --git a/lora/rak2247/Makefile-pkt-logger b/lora/rak2247/Makefile-pkt-logger new file mode 100644 index 0000000..b156000 --- /dev/null +++ b/lora/rak2247/Makefile-pkt-logger @@ -0,0 +1,70 @@ +### Application-specific constants + +APP_NAME := util_pkt_logger + +### Environment constants + +LGW_PATH ?= ../libloragw +ARCH ?= +CROSS_COMPILE ?= + +### External constant definitions + +include $(LGW_PATH)/library.cfg + +### Constant symbols + +CC := $(CROSS_COMPILE)gcc +AR := $(CROSS_COMPILE)ar + +CFLAGS=-O2 -Wall -Wextra -std=c99 -Iinc -I. + +OBJDIR = obj + +### Constants for LoRa concentrator HAL library +# List the library sub-modules that are used by the application + +LGW_INC = $(LGW_PATH)/inc/config.h +LGW_INC += $(LGW_PATH)/inc/loragw_hal.h + +### Linking options + +LIBS := -lloragw -lrt -lm -lmpsse + +### General build targets + +all: $(APP_NAME) + +clean: + rm -f $(OBJDIR)/*.o + rm -f $(APP_NAME) + +### HAL library (do no force multiple library rebuild even with 'make -B') + +$(LGW_PATH)/inc/config.h: + @if test ! -f $@; then \ + $(MAKE) all -C $(LGW_PATH); \ + fi + +$(LGW_PATH)/libloragw.a: $(LGW_INC) + @if test ! -f $@; then \ + $(MAKE) all -C $(LGW_PATH); \ + fi + +### Sub-modules compilation + +$(OBJDIR): + mkdir -p $(OBJDIR) + +$(OBJDIR)/parson.o: src/parson.c inc/parson.h | $(OBJDIR) + $(CC) -c $(CFLAGS) $< -o $@ + +### Main program compilation and assembly + +$(OBJDIR)/$(APP_NAME).o: src/$(APP_NAME).c $(LGW_INC) inc/parson.h | $(OBJDIR) + $(CC) -c $(CFLAGS) -I$(LGW_PATH)/inc $< -o $@ + +$(APP_NAME): $(OBJDIR)/$(APP_NAME).o $(LGW_PATH)/libloragw.a $(OBJDIR)/parson.o + $(CC) -L$(LGW_PATH) $< $(OBJDIR)/parson.o -o $@ $(LIBS) + +### EOF diff --git a/lora/rak2247/Makefile-spectral-scan b/lora/rak2247/Makefile-spectral-scan new file mode 100644 index 0000000..80264da --- /dev/null +++ b/lora/rak2247/Makefile-spectral-scan @@ -0,0 +1,63 @@ +### Environment constants + +LGW_PATH ?= ../libloragw +ARCH ?= +CROSS_COMPILE ?= + +### External constant definitions + +include $(LGW_PATH)/library.cfg + +### Constant symbols + +CC = $(CROSS_COMPILE)gcc +AR = $(CROSS_COMPILE)ar +CFLAGS = -O2 -Wall -Wextra -std=c99 -I inc + +OBJDIR = obj +INCLUDES = $(wildcard inc/*.h) + +### Constants for LoRa concentrator HAL library +# List the library sub-modules that are used by the application + +LGW_INC = $(LGW_PATH)/inc/config.h +LGW_INC += $(LGW_PATH)/inc/loragw_hal.h + +### Linking options + +LIBS := -lloragw -lrt -lmpsse + +### General build targets + +all: util_spectral_scan + +clean: + rm -f $(OBJDIR)/*.o + rm -f util_spectral_scan + +### HAL library (do no force multiple library rebuild even with 'make -B') + +$(LGW_PATH)/inc/config.h: + @if test ! -f $@; then \ + $(MAKE) all -C $(LGW_PATH); \ + fi + +$(LGW_PATH)/libloragw.a: $(LGW_INC) + @if test ! -f $@; then \ + $(MAKE) all -C $(LGW_PATH); \ + fi + +### Sub-modules compilation + +$(OBJDIR): + mkdir -p $(OBJDIR) + +$(OBJDIR)/%.o: src/%.c $(INCLUDES) | $(OBJDIR) + $(CC) -c $(CFLAGS) -I$(LGW_PATH)/inc $< -o $@ + +### Main program assembly + +util_spectral_scan: $(OBJDIR)/util_spectral_scan.o + $(CC) -L$(LGW_PATH) $^ $(LIBS) -o $@ + +### EOF diff --git a/lora/rak2247/Makefile-spi-stress b/lora/rak2247/Makefile-spi-stress new file mode 100644 index 0000000..2ced64a --- /dev/null +++ b/lora/rak2247/Makefile-spi-stress @@ -0,0 +1,66 @@ +### Application-specific constants + +APP_NAME := util_spi_stress + +### Environment constants + +LGW_PATH ?= ../libloragw +ARCH ?= +CROSS_COMPILE ?= + +### External constant definitions +# must get library build option to know if mpsse must be linked or not + +include $(LGW_PATH)/library.cfg + +### Constant symbols + +CC := $(CROSS_COMPILE)gcc +AR := $(CROSS_COMPILE)ar + +CFLAGS=-O2 -Wall -Wextra -std=c99 -Iinc -I. + +OBJDIR = obj + +### Constants for LoRa concentrator HAL library +# List the library sub-modules that are used by the application + +LGW_INC = $(LGW_PATH)/inc/config.h +LGW_INC += $(LGW_PATH)/inc/loragw_reg.h + +### Linking options + +LIBS := -lloragw -lrt -lm -lmpsse + +### General build targets + +all: $(APP_NAME) + +clean: + rm -f $(OBJDIR)/*.o + rm -f $(APP_NAME) + +### HAL library (do no force multiple library rebuild even with 'make -B') + +$(LGW_PATH)/inc/config.h: + @if test ! -f $@; then \ + $(MAKE) all -C $(LGW_PATH); \ + fi + +$(LGW_PATH)/libloragw.a: $(LGW_INC) + @if test ! -f $@; then \ + $(MAKE) all -C $(LGW_PATH); \ + fi + +### Main program compilation and assembly + +$(OBJDIR): + mkdir -p $(OBJDIR) + +$(OBJDIR)/$(APP_NAME).o: src/$(APP_NAME).c $(LGW_INC) | $(OBJDIR) + $(CC) -c $(CFLAGS) -I$(LGW_PATH)/inc $< -o $@ + +$(APP_NAME): $(OBJDIR)/$(APP_NAME).o $(LGW_PATH)/libloragw.a + $(CC) -L$(LGW_PATH) $< -o $@ $(LIBS) + +### EOF diff --git a/lora/rak2247/Makefile-tx-continuous b/lora/rak2247/Makefile-tx-continuous new file mode 100644 index 0000000..d5e0c5b --- /dev/null +++ b/lora/rak2247/Makefile-tx-continuous @@ -0,0 +1,68 @@ +### Application-specific constants + +APP_NAME := util_tx_continuous + +### Environment constants + +LGW_PATH ?= ../libloragw +ARCH ?= +CROSS_COMPILE ?= + +### External constant definitions +# must get library build option to know if mpsse must be linked or not + +include $(LGW_PATH)/library.cfg + +### Constant symbols + +CC := $(CROSS_COMPILE)gcc +AR := $(CROSS_COMPILE)ar + +CFLAGS=-O2 -Wall -Wextra -std=c99 -Iinc -I. + +OBJDIR = obj + +### Constants for LoRa concentrator HAL library +# List the library sub-modules that are used by the application + +LGW_INC = $(LGW_PATH)/inc/config.h +LGW_INC += $(LGW_PATH)/inc/loragw_hal.h +LGW_INC += $(LGW_PATH)/inc/loragw_reg.h +LGW_INC += $(LGW_PATH)/inc/loragw_aux.h + +### Linking options + +LIBS := -lloragw -lrt -lm -lmpsse + +### General build targets + +all: $(APP_NAME) + +clean: + rm -f $(OBJDIR)/*.o + rm -f $(APP_NAME) + +### HAL library (do no force multiple library rebuild even with 'make -B') + +$(LGW_PATH)/inc/config.h: + @if test ! -f $@; then \ + $(MAKE) all -C $(LGW_PATH); \ + fi + +$(LGW_PATH)/libloragw.a: $(LGW_INC) + @if test ! -f $@; then \ + $(MAKE) all -C $(LGW_PATH); \ + fi + +### Main program compilation and assembly + +$(OBJDIR): + mkdir -p $(OBJDIR) + +$(OBJDIR)/$(APP_NAME).o: src/$(APP_NAME).c $(LGW_INC) | $(OBJDIR) + $(CC) -c $(CFLAGS) -I$(LGW_PATH)/inc $< -o $@ + +$(APP_NAME): $(OBJDIR)/$(APP_NAME).o $(LGW_PATH)/libloragw.a + $(CC) -L$(LGW_PATH) $< -o $@ $(LIBS) + +### EOF diff --git a/lora/rak2247/Makefile-tx-test b/lora/rak2247/Makefile-tx-test new file mode 100644 index 0000000..ab30e7f --- /dev/null +++ b/lora/rak2247/Makefile-tx-test @@ -0,0 +1,67 @@ +### Application-specific constants + +APP_NAME := util_tx_test + +### Environment constants + +LGW_PATH ?= ../libloragw +ARCH ?= +CROSS_COMPILE ?= + +### External constant definitions +# must get library build option to know if mpsse must be linked or not + +include $(LGW_PATH)/library.cfg + +### Constant symbols + +CC := $(CROSS_COMPILE)gcc +AR := $(CROSS_COMPILE)ar + +CFLAGS=-O2 -Wall -Wextra -std=c99 -Iinc -I. + +OBJDIR = obj + +### Constants for LoRa concentrator HAL library +# List the library sub-modules that are used by the application + +LGW_INC = $(LGW_PATH)/inc/config.h +LGW_INC += $(LGW_PATH)/inc/loragw_hal.h +LGW_INC += $(LGW_PATH)/inc/loragw_aux.h + +### Linking options + +LIBS := -lloragw -lrt -lm -lmpsse + +### General build targets + +all: $(APP_NAME) + +clean: + rm -f $(OBJDIR)/*.o + rm -f $(APP_NAME) + +### HAL library (do no force multiple library rebuild even with 'make -B') + +$(LGW_PATH)/inc/config.h: + @if test ! -f $@; then \ + $(MAKE) all -C $(LGW_PATH); \ + fi + +$(LGW_PATH)/libloragw.a: $(LGW_INC) + @if test ! -f $@; then \ + $(MAKE) all -C $(LGW_PATH); \ + fi + +### Main program compilation and assembly + +$(OBJDIR): + mkdir -p $(OBJDIR) + +$(OBJDIR)/$(APP_NAME).o: src/$(APP_NAME).c $(LGW_INC) | $(OBJDIR) + $(CC) -c $(CFLAGS) -I$(LGW_PATH)/inc $< -o $@ + +$(APP_NAME): $(OBJDIR)/$(APP_NAME).o $(LGW_PATH)/libloragw.a + $(CC) -L$(LGW_PATH) $< -o $@ $(LIBS) + +### EOF diff --git a/lora/rak2247/global_conf/global_conf.as_923.json b/lora/rak2247/global_conf/global_conf.as_923.json new file mode 100644 index 0000000..5127049 --- /dev/null +++ b/lora/rak2247/global_conf/global_conf.as_923.json @@ -0,0 +1,218 @@ +{ + "SX1301_conf": { + "lorawan_public": true, + "clksrc": 1, + "clksrc_desc": "radio_1 provides clock to concentrator for most devices except MultiTech. For MultiTech set to 0.", + "antenna_gain": 0, + "antenna_gain_desc": "antenna gain, in dBi", + "radio_0": { + "enable": true, + "type": "SX1257", + "freq": 923600000, + "rssi_offset": -166.0, + "tx_enable": true, + "tx_freq_min": 923200000, + "tx_freq_max": 925000000 + }, + "radio_1": { + "enable": true, + "type": "SX1257", + "freq": 924600000, + "rssi_offset": -166.0, + "tx_enable": false + }, + "chan_multiSF_0": { + "desc": "Lora MAC, 125kHz, all SF, 923.2 MHz", + "enable": true, + "radio": 0, + "if": -400000 + }, + "chan_multiSF_1": { + "desc": "Lora MAC, 125kHz, all SF, 923.4 MHz", + "enable": true, + "radio": 0, + "if": -200000 + }, + "chan_multiSF_2": { + "desc": "Lora MAC, 125kHz, all SF, 923.6 MHz", + "enable": true, + "radio": 0, + "if": 0 + }, + "chan_multiSF_3": { + "desc": "Lora MAC, 125kHz, all SF, 923.8 MHz", + "enable": true, + "radio": 0, + "if": 200000 + }, + "chan_multiSF_4": { + "desc": "Lora MAC, 125kHz, all SF, 924.0 MHz", + "enable": true, + "radio": 0, + "if": 400000 + }, + "chan_multiSF_5": { + "desc": "Lora MAC, 125kHz, all SF, 924.2 MHz", + "enable": true, + "radio": 1, + "if": -400000 + }, + "chan_multiSF_6": { + "desc": "Lora MAC, 125kHz, all SF, 924.4 MHz", + "enable": true, + "radio": 1, + "if": -200000 + }, + "chan_multiSF_7": { + "desc": "Lora MAC, 125kHz, all SF, 924.6 MHz", + "enable": true, + "radio": 1, + "if": 0 + }, + "chan_Lora_std": { + "desc": "Lora MAC, 250kHz, SF7, 924.5 MHz", + "enable": true, + "radio": 1, + "if": -100000, + "bandwidth": 250000, + "spread_factor": 7 + }, + "chan_FSK": { + "desc": "FSK 50kbps, 924.8 MHz", + "enable": true, + "radio": 1, + "if": 200000, + "bandwidth": 125000, + "datarate": 50000 + }, + "tx_lut_0": { + "desc": "TX gain table, index 0", + "pa_gain": 0, + "mix_gain": 8, + "rf_power": -6, + "dig_gain": 0 + }, + "tx_lut_1": { + "desc": "TX gain table, index 1", + "pa_gain": 0, + "mix_gain": 10, + "rf_power": -3, + "dig_gain": 0 + }, + "tx_lut_2": { + "desc": "TX gain table, index 2", + "pa_gain": 0, + "mix_gain": 12, + "rf_power": 0, + "dig_gain": 0 + }, + "tx_lut_3": { + "desc": "TX gain table, index 3", + "pa_gain": 1, + "mix_gain": 8, + "rf_power": 3, + "dig_gain": 0 + }, + "tx_lut_4": { + "desc": "TX gain table, index 4", + "pa_gain": 1, + "mix_gain": 10, + "rf_power": 6, + "dig_gain": 0 + }, + "tx_lut_5": { + "desc": "TX gain table, index 5", + "pa_gain": 1, + "mix_gain": 12, + "rf_power": 10, + "dig_gain": 0 + }, + "tx_lut_6": { + "desc": "TX gain table, index 6", + "pa_gain": 1, + "mix_gain": 13, + "rf_power": 11, + "dig_gain": 0 + }, + "tx_lut_7": { + "desc": "TX gain table, index 7", + "pa_gain": 2, + "mix_gain": 9, + "rf_power": 12, + "dig_gain": 0 + }, + "tx_lut_8": { + "desc": "TX gain table, index 8", + "pa_gain": 1, + "mix_gain": 15, + "rf_power": 13, + "dig_gain": 0 + }, + "tx_lut_9": { + "desc": "TX gain table, index 9", + "pa_gain": 2, + "mix_gain": 10, + "rf_power": 14, + "dig_gain": 0 + }, + "tx_lut_10": { + "desc": "TX gain table, index 10", + "pa_gain": 2, + "mix_gain": 11, + "rf_power": 16, + "dig_gain": 0 + }, + "tx_lut_11": { + "desc": "TX gain table, index 11", + "pa_gain": 3, + "mix_gain": 9, + "rf_power": 20, + "dig_gain": 0 + }, + "tx_lut_12": { + "desc": "TX gain table, index 12", + "pa_gain": 3, + "mix_gain": 10, + "rf_power": 23, + "dig_gain": 0 + }, + "tx_lut_13": { + "desc": "TX gain table, index 13", + "pa_gain": 3, + "mix_gain": 11, + "rf_power": 25, + "dig_gain": 0 + }, + "tx_lut_14": { + "desc": "TX gain table, index 14", + "pa_gain": 3, + "mix_gain": 12, + "rf_power": 26, + "dig_gain": 0 + }, + "tx_lut_15": { + "desc": "TX gain table, index 15", + "pa_gain": 3, + "mix_gain": 14, + "rf_power": 27, + "dig_gain": 0 + } + }, + "gateway_conf": { + "gateway_ID": "0000000000000000", + /* change with default server address/ports, or overwrite in local_conf.json */ + "server_address": "router.as2.thethings.network", + "serv_port_up": 1700, + "serv_port_down": 1700, + /* adjust the following parameters for your network */ + "keepalive_interval": 10, + "stat_interval": 30, + "push_timeout_ms": 100, + /* forward only valid packets */ + "forward_crc_valid": true, + "forward_crc_error": false, + "forward_crc_disabled": false, + "autoquit_threshold": 6 + } + +} diff --git a/lora/rak2247/global_conf/global_conf.au_915_928.json b/lora/rak2247/global_conf/global_conf.au_915_928.json new file mode 100644 index 0000000..e3764fd --- /dev/null +++ b/lora/rak2247/global_conf/global_conf.au_915_928.json @@ -0,0 +1,215 @@ +{ + "SX1301_conf": { + "lorawan_public": true, + "clksrc": 1, + "clksrc_desc": "radio_1 provides clock to concentrator for most devices except MultiTech. For MultiTech set to 0.", + "antenna_gain": 0, + "antenna_gain_desc": "antenna gain, in dBi", + "radio_0": { + "enable": true, + "type": "SX1257", + "freq": 917200000, + "rssi_offset": -166.0, + "tx_enable": true, + "tx_freq_min": 915000000, + "tx_freq_max": 928000000 + }, + "radio_1": { + "enable": true, + "type": "SX1257", + "freq": 917900000, + "rssi_offset": -166.0, + "tx_enable": false + }, + "chan_multiSF_0": { + "desc": "Lora MAC, 125kHz, all SF, 916.8 MHz", + "enable": true, + "radio": 0, + "if": -400000 + }, + "chan_multiSF_1": { + "desc": "Lora MAC, 125kHz, all SF, 917.0 MHz", + "enable": true, + "radio": 0, + "if": -200000 + }, + "chan_multiSF_2": { + "desc": "Lora MAC, 125kHz, all SF, 917.2 MHz", + "enable": true, + "radio": 0, + "if": 0 + }, + "chan_multiSF_3": { + "desc": "Lora MAC, 125kHz, all SF, 917.4 MHz", + "enable": true, + "radio": 0, + "if": 200000 + }, + "chan_multiSF_4": { + "desc": "Lora MAC, 125kHz, all SF, 917.6 MHz", + "enable": true, + "radio": 1, + "if": -300000 + }, + "chan_multiSF_5": { + "desc": "Lora MAC, 125kHz, all SF, 917.8 MHz", + "enable": true, + "radio": 1, + "if": -100000 + }, + "chan_multiSF_6": { + "desc": "Lora MAC, 125kHz, all SF, 918.0 MHz", + "enable": true, + "radio": 1, + "if": 100000 + }, + "chan_multiSF_7": { + "desc": "Lora MAC, 125kHz, all SF, 918.2 MHz", + "enable": true, + "radio": 1, + "if": 300000 + }, + "chan_Lora_std": { + "desc": "Lora MAC, 500kHz, SF8, 917.5 MHz", + "enable": true, + "radio": 0, + "if": 300000, + "bandwidth": 500000, + "spread_factor": 8 + }, + "chan_FSK": { + "desc": "disabled", + "enable": false + }, + "tx_lut_0": { + "desc": "TX gain table, index 0", + "pa_gain": 0, + "mix_gain": 8, + "rf_power": -6, + "dig_gain": 0 + }, + "tx_lut_1": { + "desc": "TX gain table, index 1", + "pa_gain": 0, + "mix_gain": 10, + "rf_power": -3, + "dig_gain": 0 + }, + "tx_lut_2": { + "desc": "TX gain table, index 2", + "pa_gain": 0, + "mix_gain": 12, + "rf_power": 0, + "dig_gain": 0 + }, + "tx_lut_3": { + "desc": "TX gain table, index 3", + "pa_gain": 1, + "mix_gain": 8, + "rf_power": 3, + "dig_gain": 0 + }, + "tx_lut_4": { + "desc": "TX gain table, index 4", + "pa_gain": 1, + "mix_gain": 10, + "rf_power": 6, + "dig_gain": 0 + }, + "tx_lut_5": { + "desc": "TX gain table, index 5", + "pa_gain": 1, + "mix_gain": 12, + "rf_power": 10, + "dig_gain": 0 + }, + "tx_lut_6": { + "desc": "TX gain table, index 6", + "pa_gain": 1, + "mix_gain": 13, + "rf_power": 11, + "dig_gain": 0 + }, + "tx_lut_7": { + "desc": "TX gain table, index 7", + "pa_gain": 2, + "mix_gain": 9, + "rf_power": 12, + "dig_gain": 0 + }, + "tx_lut_8": { + "desc": "TX gain table, index 8", + "pa_gain": 1, + "mix_gain": 15, + "rf_power": 13, + "dig_gain": 0 + }, + "tx_lut_9": { + "desc": "TX gain table, index 9", + "pa_gain": 2, + "mix_gain": 10, + "rf_power": 14, + "dig_gain": 0 + }, + "tx_lut_10": { + "desc": "TX gain table, index 10", + "pa_gain": 2, + "mix_gain": 11, + "rf_power": 16, + "dig_gain": 0 + }, + "tx_lut_11": { + "desc": "TX gain table, index 11", + "pa_gain": 3, + "mix_gain": 9, + "rf_power": 20, + "dig_gain": 0 + }, + "tx_lut_12": { + "desc": "TX gain table, index 12", + "pa_gain": 3, + "mix_gain": 10, + "rf_power": 23, + "dig_gain": 0 + }, + "tx_lut_13": { + "desc": "TX gain table, index 13", + "pa_gain": 3, + "mix_gain": 11, + "rf_power": 25, + "dig_gain": 0 + }, + "tx_lut_14": { + "desc": "TX gain table, index 14", + "pa_gain": 3, + "mix_gain": 12, + "rf_power": 26, + "dig_gain": 0 + }, + "tx_lut_15": { + "desc": "TX gain table, index 15", + "pa_gain": 3, + "mix_gain": 14, + "rf_power": 27, + "dig_gain": 0 + } + }, + "gateway_conf": { + "gateway_ID": "0000000000000000", + /* change with default server address/ports, or overwrite in local_conf.json */ + "server_address": "router.au.thethings.network", + "serv_port_up": 1700, + "serv_port_down": 1700, + /* adjust the following parameters for your network */ + "keepalive_interval": 10, + "stat_interval": 30, + "push_timeout_ms": 100, + /* forward only valid packets */ + "forward_crc_valid": true, + "forward_crc_error": false, + "forward_crc_disabled": false, + "autoquit_threshold": 6 + } + +} + diff --git a/lora/rak2247/global_conf/global_conf.cn_470_510.json b/lora/rak2247/global_conf/global_conf.cn_470_510.json new file mode 100644 index 0000000..222e020 --- /dev/null +++ b/lora/rak2247/global_conf/global_conf.cn_470_510.json @@ -0,0 +1,210 @@ +{ + "SX1301_conf": { + "lorawan_public": true, + "clksrc": 1, + "clksrc_desc": "radio_1 provides clock to concentrator for most devices except MultiTech. For MultiTech set to 0.", + "antenna_gain": 0, + "antenna_gain_desc": "antenna gain, in dBi", + "radio_0": { + "enable": true, + "type": "SX1255", + "freq": 486600000, + "rssi_offset": -176.0, + "tx_enable": true, + "tx_freq_min": 470000000, + "tx_freq_max": 510000000 + }, + "radio_1": { + "enable": true, + "type": "SX1255", + "freq": 487400000, + "rssi_offset": -176.0, + "tx_enable": false + }, + "chan_multiSF_0": { + "desc": "Lora MAC, 125kHz, all SF, 487.1 MHz", + "enable": true, + "radio": 1, + "if": -300000 + }, + "chan_multiSF_1": { + "desc": "Lora MAC, 125kHz, all SF, 487.3 MHz", + "enable": true, + "radio": 1, + "if": -100000 + }, + "chan_multiSF_2": { + "desc": "Lora MAC, 125kHz, all SF, 487.5 MHz", + "enable": true, + "radio": 1, + "if": 100000 + }, + "chan_multiSF_3": { + "desc": "Lora MAC, 125kHz, all SF, 487.7 MHz", + "enable": true, + "radio": 1, + "if": 300000 + }, + "chan_multiSF_4": { + "desc": "Lora MAC, 125kHz, all SF, 486.3 MHz", + "enable": true, + "radio": 0, + "if": -300000 + }, + "chan_multiSF_5": { + "desc": "Lora MAC, 125kHz, all SF, 486.5 MHz", + "enable": true, + "radio": 0, + "if": -100000 + }, + "chan_multiSF_6": { + "desc": "Lora MAC, 125kHz, all SF, 486.7 MHz", + "enable": true, + "radio": 0, + "if": 100000 + }, + "chan_multiSF_7": { + "desc": "Lora MAC, 125kHz, all SF, 486.9 MHz", + "enable": true, + "radio": 0, + "if": 300000 + }, + "chan_Lora_std": { + "desc": "disabled", + "enable": false + }, + "chan_FSK": { + "desc": "disabled", + "enable": false + }, + "tx_lut_0": { + "desc": "TX gain table, index 0", + "pa_gain": 0, + "mix_gain": 8, + "rf_power": -6, + "dig_gain": 0 + }, + "tx_lut_1": { + "desc": "TX gain table, index 1", + "pa_gain": 0, + "mix_gain": 10, + "rf_power": -3, + "dig_gain": 0 + }, + "tx_lut_2": { + "desc": "TX gain table, index 2", + "pa_gain": 0, + "mix_gain": 12, + "rf_power": 0, + "dig_gain": 0 + }, + "tx_lut_3": { + "desc": "TX gain table, index 3", + "pa_gain": 1, + "mix_gain": 8, + "rf_power": 3, + "dig_gain": 0 + }, + "tx_lut_4": { + "desc": "TX gain table, index 4", + "pa_gain": 1, + "mix_gain": 10, + "rf_power": 6, + "dig_gain": 0 + }, + "tx_lut_5": { + "desc": "TX gain table, index 5", + "pa_gain": 1, + "mix_gain": 12, + "rf_power": 10, + "dig_gain": 0 + }, + "tx_lut_6": { + "desc": "TX gain table, index 6", + "pa_gain": 1, + "mix_gain": 13, + "rf_power": 11, + "dig_gain": 0 + }, + "tx_lut_7": { + "desc": "TX gain table, index 7", + "pa_gain": 2, + "mix_gain": 9, + "rf_power": 12, + "dig_gain": 0 + }, + "tx_lut_8": { + "desc": "TX gain table, index 8", + "pa_gain": 1, + "mix_gain": 15, + "rf_power": 13, + "dig_gain": 0 + }, + "tx_lut_9": { + "desc": "TX gain table, index 9", + "pa_gain": 2, + "mix_gain": 10, + "rf_power": 14, + "dig_gain": 0 + }, + "tx_lut_10": { + "desc": "TX gain table, index 10", + "pa_gain": 2, + "mix_gain": 11, + "rf_power": 16, + "dig_gain": 0 + }, + "tx_lut_11": { + "desc": "TX gain table, index 11", + "pa_gain": 3, + "mix_gain": 9, + "rf_power": 20, + "dig_gain": 0 + }, + "tx_lut_12": { + "desc": "TX gain table, index 12", + "pa_gain": 3, + "mix_gain": 10, + "rf_power": 23, + "dig_gain": 0 + }, + "tx_lut_13": { + "desc": "TX gain table, index 13", + "pa_gain": 3, + "mix_gain": 11, + "rf_power": 25, + "dig_gain": 0 + }, + "tx_lut_14": { + "desc": "TX gain table, index 14", + "pa_gain": 3, + "mix_gain": 12, + "rf_power": 26, + "dig_gain": 0 + }, + "tx_lut_15": { + "desc": "TX gain table, index 15", + "pa_gain": 3, + "mix_gain": 14, + "rf_power": 27, + "dig_gain": 0 + } + }, + "gateway_conf": { + "gateway_ID": "0000000000000000", + /* change with default server address/ports, or overwrite in local_conf.json */ + "server_address": "router.cn.thethings.network", + "serv_port_up": 1700, + "serv_port_down": 1700, + /* adjust the following parameters for your network */ + "keepalive_interval": 10, + "stat_interval": 30, + "push_timeout_ms": 100, + /* forward only valid packets */ + "forward_crc_valid": true, + "forward_crc_error": false, + "forward_crc_disabled": false, + "autoquit_threshold": 6 + } +} + diff --git a/lora/rak2247/global_conf/global_conf.eu_433.json b/lora/rak2247/global_conf/global_conf.eu_433.json new file mode 100644 index 0000000..a42f1b2 --- /dev/null +++ b/lora/rak2247/global_conf/global_conf.eu_433.json @@ -0,0 +1,217 @@ +{ + + "SX1301_conf": { + "lorawan_public": true, + "clksrc": 1, /* radio_1 provides clock to concentrator */ + "antenna_gain": 0, /* antenna gain, in dBi */ + "radio_0": { + "enable": true, + "type": "SX1255", + "freq": 434375000, + "rssi_offset": -166.0, + "tx_enable": true, + "tx_freq_min": 433050000, + "tx_freq_max": 434900000 + }, + "radio_1": { + "enable": true, + "type": "SX1255", + "freq": 433575000, + "rssi_offset": -166.0, + "tx_enable": false + }, + "chan_multiSF_0": { + /* Lora MAC channel, 125kHz, all SF, 433.175 MHz */ + "enable": true, + "radio": 1, + "if": -400000 + }, + "chan_multiSF_1": { + /* Lora MAC channel, 125kHz, all SF, 433.375 MHz */ + "enable": true, + "radio": 1, + "if": -200000 + }, + "chan_multiSF_2": { + /* Lora MAC channel, 125kHz, all SF, 433.575 MHz */ + "enable": true, + "radio": 1, + "if": 0 + }, + "chan_multiSF_3": { + /* Lora MAC channel, 125kHz, all SF, 433.975 MHz */ + "enable": true, + "radio": 0, + "if": -400000 + }, + "chan_multiSF_4": { + /* Lora MAC channel, 125kHz, all SF, 434.175 MHz */ + "enable": true, + "radio": 0, + "if": -200000 + }, + "chan_multiSF_5": { + /* Lora MAC channel, 125kHz, all SF, 434.375 MHz */ + "enable": true, + "radio": 0, + "if": 0 + }, + "chan_multiSF_6": { + /* Lora MAC channel, 125kHz, all SF, 434.575 MHz */ + "enable": true, + "radio": 0, + "if": 200000 + }, + "chan_multiSF_7": { + /* Lora MAC channel, 125kHz, all SF, 434.775 MHz */ + "enable": true, + "radio": 0, + "if": 400000 + }, + "chan_Lora_std": { + /* Lora MAC channel, 250kHz, SF7, 434.175 MHz */ + "enable": true, + "radio": 1, + "if": -200000, + "bandwidth": 250000, + "spread_factor": 7 + }, + "chan_FSK": { + /* FSK 50kbps channel, 434.675 MHz */ + "enable": true, + "radio": 1, + "if": 300000, + "bandwidth": 125000, + "datarate": 50000 + }, + "tx_lut_0": { + /* TX gain table, index 0 */ + "pa_gain": 0, + "mix_gain": 8, + "rf_power": -6, + "dig_gain": 0 + }, + "tx_lut_1": { + /* TX gain table, index 1 */ + "pa_gain": 0, + "mix_gain": 10, + "rf_power": -3, + "dig_gain": 0 + }, + "tx_lut_2": { + /* TX gain table, index 2 */ + "pa_gain": 0, + "mix_gain": 12, + "rf_power": 0, + "dig_gain": 0 + }, + "tx_lut_3": { + /* TX gain table, index 3 */ + "pa_gain": 1, + "mix_gain": 8, + "rf_power": 3, + "dig_gain": 0 + }, + "tx_lut_4": { + /* TX gain table, index 4 */ + "pa_gain": 1, + "mix_gain": 10, + "rf_power": 6, + "dig_gain": 0 + }, + "tx_lut_5": { + /* TX gain table, index 5 */ + "pa_gain": 1, + "mix_gain": 12, + "rf_power": 10, + "dig_gain": 0 + }, + "tx_lut_6": { + /* TX gain table, index 6 */ + "pa_gain": 1, + "mix_gain": 13, + "rf_power": 11, + "dig_gain": 0 + }, + "tx_lut_7": { + /* TX gain table, index 7 */ + "pa_gain": 2, + "mix_gain": 9, + "rf_power": 12, + "dig_gain": 0 + }, + "tx_lut_8": { + /* TX gain table, index 8 */ + "pa_gain": 1, + "mix_gain": 15, + "rf_power": 13, + "dig_gain": 0 + }, + "tx_lut_9": { + /* TX gain table, index 9 */ + "pa_gain": 2, + "mix_gain": 10, + "rf_power": 14, + "dig_gain": 0 + }, + "tx_lut_10": { + /* TX gain table, index 10 */ + "pa_gain": 2, + "mix_gain": 11, + "rf_power": 16, + "dig_gain": 0 + }, + "tx_lut_11": { + /* TX gain table, index 11 */ + "pa_gain": 3, + "mix_gain": 9, + "rf_power": 20, + "dig_gain": 0 + }, + "tx_lut_12": { + "desc": "TX gain table, index 12", + "pa_gain": 3, + "mix_gain": 10, + "rf_power": 23, + "dig_gain": 0 + }, + "tx_lut_13": { + "desc": "TX gain table, index 13", + "pa_gain": 3, + "mix_gain": 11, + "rf_power": 25, + "dig_gain": 0 + }, + "tx_lut_14": { + "desc": "TX gain table, index 14", + "pa_gain": 3, + "mix_gain": 12, + "rf_power": 26, + "dig_gain": 0 + }, + "tx_lut_15": { + "desc": "TX gain table, index 15", + "pa_gain": 3, + "mix_gain": 14, + "rf_power": 27, + "dig_gain": 0 + } + }, + "gateway_conf": { + "gateway_ID": "0000000000000000", + /* change with default server address/ports, or overwrite in local_conf.json */ + "server_address": "localhost", + "serv_port_up": 1700, + "serv_port_down": 1700, + /* adjust the following parameters for your network */ + "keepalive_interval": 10, + "stat_interval": 30, + "push_timeout_ms": 100, + /* forward only valid packets */ + "forward_crc_valid": true, + "forward_crc_error": false, + "forward_crc_disabled": false, + "autoquit_threshold": 6 + } +} + diff --git a/lora/rak2247/global_conf/global_conf.eu_863_870.json b/lora/rak2247/global_conf/global_conf.eu_863_870.json new file mode 100644 index 0000000..3cfd8a7 --- /dev/null +++ b/lora/rak2247/global_conf/global_conf.eu_863_870.json @@ -0,0 +1,193 @@ +{ + "SX1301_conf": { + "lorawan_public": true, + "clksrc": 1, + "antenna_gain": 0, + "radio_0": { + "enable": true, + "type": "SX1257", + "freq": 867500000, + "rssi_offset": -166.0, + "tx_enable": true, + "tx_freq_min": 863000000, + "tx_freq_max": 870000000 + }, + "radio_1": { + "enable": true, + "type": "SX1257", + "freq": 868500000, + "rssi_offset": -166.0, + "tx_enable": false + }, + "chan_multiSF_0": { + "enable": true, + "radio": 1, + "if": -400000 + }, + "chan_multiSF_1": { + "enable": true, + "radio": 1, + "if": -200000 + }, + "chan_multiSF_2": { + "enable": true, + "radio": 1, + "if": 0 + }, + "chan_multiSF_3": { + "enable": true, + "radio": 0, + "if": -400000 + }, + "chan_multiSF_4": { + "enable": true, + "radio": 0, + "if": -200000 + }, + "chan_multiSF_5": { + "enable": true, + "radio": 0, + "if": 0 + }, + "chan_multiSF_6": { + "enable": true, + "radio": 0, + "if": 200000 + }, + "chan_multiSF_7": { + "enable": true, + "radio": 0, + "if": 400000 + }, + "chan_Lora_std": { + "enable": true, + "radio": 1, + "if": -200000, + "bandwidth": 250000, + "spread_factor": 7 + }, + "chan_FSK": { + "enable": true, + "radio": 1, + "if": 300000, + "bandwidth": 125000, + "datarate": 50000 + }, + "tx_lut_0": { + "pa_gain": 0, + "mix_gain": 8, + "rf_power": -6, + "dig_gain": 0 + }, + "tx_lut_1": { + "pa_gain": 0, + "mix_gain": 10, + "rf_power": -3, + "dig_gain": 0 + }, + "tx_lut_2": { + "pa_gain": 0, + "mix_gain": 12, + "rf_power": 0, + "dig_gain": 0 + }, + "tx_lut_3": { + "pa_gain": 1, + "mix_gain": 8, + "rf_power": 3, + "dig_gain": 0 + }, + "tx_lut_4": { + "pa_gain": 1, + "mix_gain": 10, + "rf_power": 6, + "dig_gain": 0 + }, + "tx_lut_5": { + "pa_gain": 1, + "mix_gain": 12, + "rf_power": 10, + "dig_gain": 0 + }, + "tx_lut_6": { + "pa_gain": 1, + "mix_gain": 13, + "rf_power": 11, + "dig_gain": 0 + }, + "tx_lut_7": { + "pa_gain": 2, + "mix_gain": 9, + "rf_power": 12, + "dig_gain": 0 + }, + "tx_lut_8": { + "pa_gain": 1, + "mix_gain": 15, + "rf_power": 13, + "dig_gain": 0 + }, + "tx_lut_9": { + "pa_gain": 2, + "mix_gain": 10, + "rf_power": 14, + "dig_gain": 0 + }, + "tx_lut_10": { + "pa_gain": 2, + "mix_gain": 11, + "rf_power": 16, + "dig_gain": 0 + }, + "tx_lut_11": { + "pa_gain": 3, + "mix_gain": 9, + "rf_power": 20, + "dig_gain": 0 + }, + "tx_lut_12": { + "desc": "TX gain table, index 12", + "pa_gain": 3, + "mix_gain": 10, + "rf_power": 23, + "dig_gain": 0 + }, + "tx_lut_13": { + "desc": "TX gain table, index 13", + "pa_gain": 3, + "mix_gain": 11, + "rf_power": 25, + "dig_gain": 0 + }, + "tx_lut_14": { + "desc": "TX gain table, index 14", + "pa_gain": 3, + "mix_gain": 12, + "rf_power": 26, + "dig_gain": 0 + }, + "tx_lut_15": { + "desc": "TX gain table, index 15", + "pa_gain": 3, + "mix_gain": 14, + "rf_power": 27, + "dig_gain": 0 + } + }, + "gateway_conf": { + "gateway_ID": "0000000000000000", + /* change with default server address/ports, or overwrite in local_conf.json */ + "server_address": "router.eu.thethings.network", + "serv_port_up": 1700, + "serv_port_down": 1700, + /* adjust the following parameters for your network */ + "keepalive_interval": 10, + "stat_interval": 30, + "push_timeout_ms": 100, + /* forward only valid packets */ + "forward_crc_valid": true, + "forward_crc_error": false, + "forward_crc_disabled": false, + "autoquit_threshold": 6 + } +} diff --git a/lora/rak2247/global_conf/global_conf.in_865_867.json b/lora/rak2247/global_conf/global_conf.in_865_867.json new file mode 100644 index 0000000..f024127 --- /dev/null +++ b/lora/rak2247/global_conf/global_conf.in_865_867.json @@ -0,0 +1,202 @@ +{ + "SX1301_conf": { + "lorawan_public": true, + "clksrc": 1, + "clksrc_desc": "radio_1 provides clock to concentrator for most devices except MultiTech. For MultiTech set to 0.", + "antenna_gain": 0, + "antenna_gain_desc": "antenna gain, in dBi", + "radio_0": { + "enable": true, + "type": "SX1257", + "freq": 865200000, + "rssi_offset": -166.0, + "tx_enable": true, + "tx_freq_min": 865000000, + "tx_freq_max": 867000000, + "tx_notch_freq": 129000 + }, + "radio_1": { + "enable": true, + "type": "SX1257", + "freq": 866385000, + "rssi_offset": -166.0, + "tx_enable": false + }, + "chan_multiSF_0": { + "desc": "Lora MAC, 125kHz, all SF, 865.0625 MHz", + "enable": true, + "radio": 0, + "if": -137500 + }, + "chan_multiSF_1": { + "desc": "Lora MAC, 125kHz, all SF, 865.4025 MHz", + "enable": true, + "radio": 0, + "if": 202500 + }, + "chan_multiSF_2": { + "desc": "Lora MAC, 125kHz, all SF, 865.9850 MHz", + "enable": true, + "radio": 1, + "if": -400000 + }, + "chan_multiSF_3": { + "desc": "disabled", + "enable": false + }, + "chan_multiSF_4": { + "desc": "disabled", + "enable": false + }, + "chan_multiSF_5": { + "desc": "disabled", + "enable": false + }, + "chan_multiSF_6": { + "desc": "disabled", + "enable": false + }, + "chan_multiSF_7": { + "desc": "disabled", + "enable": false + }, + "chan_Lora_std": { + "desc": "disabled", + "enable": false + }, + "chan_FSK": { + "desc": "disabled", + "enable": false + }, + "tx_lut_0": { + "desc": "TX gain table, index 0", + "pa_gain": 0, + "mix_gain": 8, + "rf_power": -6, + "dig_gain": 0 + }, + "tx_lut_1": { + "desc": "TX gain table, index 1", + "pa_gain": 0, + "mix_gain": 10, + "rf_power": -3, + "dig_gain": 0 + }, + "tx_lut_2": { + "desc": "TX gain table, index 2", + "pa_gain": 0, + "mix_gain": 12, + "rf_power": 0, + "dig_gain": 0 + }, + "tx_lut_3": { + "desc": "TX gain table, index 3", + "pa_gain": 1, + "mix_gain": 8, + "rf_power": 3, + "dig_gain": 0 + }, + "tx_lut_4": { + "desc": "TX gain table, index 4", + "pa_gain": 1, + "mix_gain": 10, + "rf_power": 6, + "dig_gain": 0 + }, + "tx_lut_5": { + "desc": "TX gain table, index 5", + "pa_gain": 1, + "mix_gain": 12, + "rf_power": 10, + "dig_gain": 0 + }, + "tx_lut_6": { + "desc": "TX gain table, index 6", + "pa_gain": 1, + "mix_gain": 13, + "rf_power": 11, + "dig_gain": 0 + }, + "tx_lut_7": { + "desc": "TX gain table, index 7", + "pa_gain": 2, + "mix_gain": 9, + "rf_power": 12, + "dig_gain": 0 + }, + "tx_lut_8": { + "desc": "TX gain table, index 8", + "pa_gain": 1, + "mix_gain": 15, + "rf_power": 13, + "dig_gain": 0 + }, + "tx_lut_9": { + "desc": "TX gain table, index 9", + "pa_gain": 2, + "mix_gain": 10, + "rf_power": 14, + "dig_gain": 0 + }, + "tx_lut_10": { + "desc": "TX gain table, index 10", + "pa_gain": 2, + "mix_gain": 11, + "rf_power": 16, + "dig_gain": 0 + }, + "tx_lut_11": { + "desc": "TX gain table, index 11", + "pa_gain": 3, + "mix_gain": 9, + "rf_power": 20, + "dig_gain": 0 + }, + "tx_lut_12": { + "desc": "TX gain table, index 12", + "pa_gain": 3, + "mix_gain": 10, + "rf_power": 23, + "dig_gain": 0 + }, + "tx_lut_13": { + "desc": "TX gain table, index 13", + "pa_gain": 3, + "mix_gain": 11, + "rf_power": 25, + "dig_gain": 0 + }, + "tx_lut_14": { + "desc": "TX gain table, index 14", + "pa_gain": 3, + "mix_gain": 12, + "rf_power": 26, + "dig_gain": 0 + }, + "tx_lut_15": { + "desc": "TX gain table, index 15", + "pa_gain": 3, + "mix_gain": 14, + "rf_power": 27, + "dig_gain": 0 + } + }, + "gateway_conf": { + "gateway_ID": "0000000000000000", + /* change with default server address/ports, or overwrite in local_conf.json */ + "server_address": "router.as.thethings.network", + "serv_port_up": 1700, + "serv_port_down": 1700, + /* adjust the following parameters for your network */ + "keepalive_interval": 10, + "stat_interval": 30, + "push_timeout_ms": 100, + /* forward only valid packets */ + "forward_crc_valid": true, + "forward_crc_error": false, + "forward_crc_disabled": false, + "autoquit_threshold": 6 + } + +} + diff --git a/lora/rak2247/global_conf/global_conf.kr_920_923.json b/lora/rak2247/global_conf/global_conf.kr_920_923.json new file mode 100644 index 0000000..0fcb6e5 --- /dev/null +++ b/lora/rak2247/global_conf/global_conf.kr_920_923.json @@ -0,0 +1,210 @@ +{ + "SX1301_conf": { + "lorawan_public": true, + "clksrc": 1, + "clksrc_desc": "radio_1 provides clock to concentrator for most devices except MultiTech. For MultiTech set to 0.", + "antenna_gain": 0, + "antenna_gain_desc": "antenna gain, in dBi", + "radio_0": { + "enable": true, + "type": "SX1257", + "freq": 922400000, + "rssi_offset": -166.0, + "tx_enable": true, + "tx_freq_min": 920900000, + "tx_freq_max": 923300000 + }, + "radio_1": { + "enable": true, + "type": "SX1257", + "freq": 923000000, + "rssi_offset": -166.0, + "tx_enable": false + }, + "chan_multiSF_0": { + "desc": "Lora MAC, 125kHz, all SF, 922.1 MHz", + "enable": true, + "radio": 0, + "if": -300000 + }, + "chan_multiSF_1": { + "desc": "Lora MAC, 125kHz, all SF, 922.3 MHz", + "enable": true, + "radio": 0, + "if": -100000 + }, + "chan_multiSF_2": { + "desc": "Lora MAC, 125kHz, all SF, 922.5 MHz", + "enable": true, + "radio": 0, + "if": 100000 + }, + "chan_multiSF_3": { + "desc": "Lora MAC, 125kHz, all SF, 922.7 MHz", + "enable": true, + "radio": 0, + "if": 300000 + }, + "chan_multiSF_4": { + "desc": "Lora MAC, 125kHz, all SF, 922.9 MHz", + "enable": true, + "radio": 1, + "if": -100000 + }, + "chan_multiSF_5": { + "desc": "Lora MAC, 125kHz, all SF, 923.1 MHz", + "enable": true, + "radio": 1, + "if": 100000 + }, + "chan_multiSF_6": { + "desc": "Lora MAC, 125kHz, all SF, 923.3 MHz", + "enable": true, + "radio": 1, + "if": 300000 + }, + "chan_multiSF_7": { + "desc": "disabled", + "enable": false + }, + "chan_Lora_std": { + "desc": "disabled", + "enable": false + }, + "chan_FSK": { + "desc": "disabled", + "enable": false + }, + "tx_lut_0": { + "desc": "TX gain table, index 0", + "pa_gain": 0, + "mix_gain": 8, + "rf_power": -6, + "dig_gain": 0 + }, + "tx_lut_1": { + "desc": "TX gain table, index 1", + "pa_gain": 0, + "mix_gain": 10, + "rf_power": -3, + "dig_gain": 0 + }, + "tx_lut_2": { + "desc": "TX gain table, index 2", + "pa_gain": 0, + "mix_gain": 12, + "rf_power": 0, + "dig_gain": 0 + }, + "tx_lut_3": { + "desc": "TX gain table, index 3", + "pa_gain": 1, + "mix_gain": 8, + "rf_power": 3, + "dig_gain": 0 + }, + "tx_lut_4": { + "desc": "TX gain table, index 4", + "pa_gain": 1, + "mix_gain": 10, + "rf_power": 6, + "dig_gain": 0 + }, + "tx_lut_5": { + "desc": "TX gain table, index 5", + "pa_gain": 1, + "mix_gain": 12, + "rf_power": 10, + "dig_gain": 0 + }, + "tx_lut_6": { + "desc": "TX gain table, index 6", + "pa_gain": 1, + "mix_gain": 13, + "rf_power": 11, + "dig_gain": 0 + }, + "tx_lut_7": { + "desc": "TX gain table, index 7", + "pa_gain": 2, + "mix_gain": 9, + "rf_power": 12, + "dig_gain": 0 + }, + "tx_lut_8": { + "desc": "TX gain table, index 8", + "pa_gain": 1, + "mix_gain": 15, + "rf_power": 13, + "dig_gain": 0 + }, + "tx_lut_9": { + "desc": "TX gain table, index 9", + "pa_gain": 2, + "mix_gain": 10, + "rf_power": 14, + "dig_gain": 0 + }, + "tx_lut_10": { + "desc": "TX gain table, index 10", + "pa_gain": 2, + "mix_gain": 11, + "rf_power": 16, + "dig_gain": 0 + }, + "tx_lut_11": { + "desc": "TX gain table, index 11", + "pa_gain": 3, + "mix_gain": 9, + "rf_power": 20, + "dig_gain": 0 + }, + "tx_lut_12": { + "desc": "TX gain table, index 12", + "pa_gain": 3, + "mix_gain": 10, + "rf_power": 23, + "dig_gain": 0 + }, + "tx_lut_13": { + "desc": "TX gain table, index 13", + "pa_gain": 3, + "mix_gain": 11, + "rf_power": 25, + "dig_gain": 0 + }, + "tx_lut_14": { + "desc": "TX gain table, index 14", + "pa_gain": 3, + "mix_gain": 12, + "rf_power": 26, + "dig_gain": 0 + }, + "tx_lut_15": { + "desc": "TX gain table, index 15", + "pa_gain": 3, + "mix_gain": 14, + "rf_power": 27, + "dig_gain": 0 + } + }, + "gateway_conf": { + "gateway_ID": "0000000000000000", + /* change with default server address/ports, or overwrite in local_conf.json */ + "server_address": "router.kr.thethings.network", + "serv_port_up": 1700, + "serv_port_down": 1700, + /* adjust the following parameters for your network */ + "keepalive_interval": 10, + "stat_interval": 30, + "push_timeout_ms": 100, + /* forward only valid packets */ + "forward_crc_valid": true, + "forward_crc_error": false, + "forward_crc_disabled": false, + "autoquit_threshold": 6 + } + +} + + diff --git a/lora/rak2247/global_conf/global_conf.ru_864_870.json b/lora/rak2247/global_conf/global_conf.ru_864_870.json new file mode 100644 index 0000000..631afa5 --- /dev/null +++ b/lora/rak2247/global_conf/global_conf.ru_864_870.json @@ -0,0 +1,209 @@ +{ + "SX1301_conf": { + "lorawan_public": true, + "clksrc": 1, + "clksrc_desc": "radio_1 provides clock to concentrator for most devices except MultiTech. For MultiTech set to 0.", + "antenna_gain": 0, + "antenna_gain_desc": "antenna gain, in dBi", + "radio_0": { + "enable": true, + "type": "SX1257", + "freq": 864500000, + "rssi_offset": -166.0, + "tx_enable": true, + "tx_freq_min": 863000000, + "tx_freq_max": 870000000 + }, + "radio_1": { + "enable": true, + "type": "SX1257", + "freq": 869000000, + "rssi_offset": -166.0, + "tx_enable": false + }, + "chan_multiSF_0": { + "desc": "Lora MAC, 125kHz, all SF, 864.1 MHz", + "enable": true, + "radio": 0, + "if": -400000 + }, + "chan_multiSF_1": { + "desc": "Lora MAC, 125kHz, all SF, 864.3 MHz", + "enable": true, + "radio": 0, + "if": -200000 + }, + "chan_multiSF_2": { + "desc": "Lora MAC, 125kHz, all SF, 864.5 MHz", + "enable": true, + "radio": 0, + "if": 0 + }, + "chan_multiSF_3": { + "desc": "Lora MAC, 125kHz, all SF, 864.7 MHz", + "enable": true, + "radio": 0, + "if": 200000 + }, + "chan_multiSF_4": { + "desc": "Lora MAC, 125kHz, all SF, 864.9 MHz", + "enable": true, + "radio": 0, + "if": 400000 + }, + "chan_multiSF_5": { + "desc": "Lora MAC, 125kHz, all SF, 868.9 MHz", + "enable": true, + "radio": 1, + "if": -100000 + }, + "chan_multiSF_6": { + "desc": "Lora MAC, 125kHz, all SF, 869.1 MHz", + "enable": true, + "radio": 1, + "if": 100000 + }, + "chan_multiSF_7": { + "desc": "disabled", + "enable": false + }, + "chan_Lora_std": { + "desc": "disabled", + "enable": false + }, + "chan_FSK": { + "desc": "disabled", + "enable": false + }, + "tx_lut_0": { + "desc": "TX gain table, index 0", + "pa_gain": 0, + "mix_gain": 8, + "rf_power": -6, + "dig_gain": 0 + }, + "tx_lut_1": { + "desc": "TX gain table, index 1", + "pa_gain": 0, + "mix_gain": 10, + "rf_power": -3, + "dig_gain": 0 + }, + "tx_lut_2": { + "desc": "TX gain table, index 2", + "pa_gain": 0, + "mix_gain": 12, + "rf_power": 0, + "dig_gain": 0 + }, + "tx_lut_3": { + "desc": "TX gain table, index 3", + "pa_gain": 1, + "mix_gain": 8, + "rf_power": 3, + "dig_gain": 0 + }, + "tx_lut_4": { + "desc": "TX gain table, index 4", + "pa_gain": 1, + "mix_gain": 10, + "rf_power": 6, + "dig_gain": 0 + }, + "tx_lut_5": { + "desc": "TX gain table, index 5", + "pa_gain": 1, + "mix_gain": 12, + "rf_power": 10, + "dig_gain": 0 + }, + "tx_lut_6": { + "desc": "TX gain table, index 6", + "pa_gain": 1, + "mix_gain": 13, + "rf_power": 11, + "dig_gain": 0 + }, + "tx_lut_7": { + "desc": "TX gain table, index 7", + "pa_gain": 2, + "mix_gain": 9, + "rf_power": 12, + "dig_gain": 0 + }, + "tx_lut_8": { + "desc": "TX gain table, index 8", + "pa_gain": 1, + "mix_gain": 15, + "rf_power": 13, + "dig_gain": 0 + }, + "tx_lut_9": { + "desc": "TX gain table, index 9", + "pa_gain": 2, + "mix_gain": 10, + "rf_power": 14, + "dig_gain": 0 + }, + "tx_lut_10": { + "desc": "TX gain table, index 10", + "pa_gain": 2, + "mix_gain": 11, + "rf_power": 16, + "dig_gain": 0 + }, + "tx_lut_11": { + "desc": "TX gain table, index 11", + "pa_gain": 3, + "mix_gain": 9, + "rf_power": 20, + "dig_gain": 0 + }, + "tx_lut_12": { + "desc": "TX gain table, index 12", + "pa_gain": 3, + "mix_gain": 10, + "rf_power": 23, + "dig_gain": 0 + }, + "tx_lut_13": { + "desc": "TX gain table, index 13", + "pa_gain": 3, + "mix_gain": 11, + "rf_power": 25, + "dig_gain": 0 + }, + "tx_lut_14": { + "desc": "TX gain table, index 14", + "pa_gain": 3, + "mix_gain": 12, + "rf_power": 26, + "dig_gain": 0 + }, + "tx_lut_15": { + "desc": "TX gain table, index 15", + "pa_gain": 3, + "mix_gain": 14, + "rf_power": 27, + "dig_gain": 0 + } + }, + "gateway_conf": { + "gateway_ID": "0000000000000000", + /* change with default server address/ports, or overwrite in local_conf.json */ + "server_address": "router.ru.thethings.network", + "serv_port_up": 1700, + "serv_port_down": 1700, + /* adjust the following parameters for your network */ + "keepalive_interval": 10, + "stat_interval": 30, + "push_timeout_ms": 100, + /* forward only valid packets */ + "forward_crc_valid": true, + "forward_crc_error": false, + "forward_crc_disabled": false, + "autoquit_threshold": 6 + } + +} + diff --git a/lora/rak2247/global_conf/global_conf.us_902_928.json b/lora/rak2247/global_conf/global_conf.us_902_928.json new file mode 100644 index 0000000..6da7245 --- /dev/null +++ b/lora/rak2247/global_conf/global_conf.us_902_928.json @@ -0,0 +1,205 @@ +{ + "SX1301_conf": { + "lorawan_public": true, + "clksrc": 1, + "antenna_gain": 0, + "radio_0": { + "enable": true, + "type": "SX1257", + "freq": 904300000, + "rssi_offset": -166.0, + "tx_enable": true, + "tx_freq_min": 902000000, + "tx_freq_max": 928000000 + }, + "radio_1": { + "enable": true, + "type": "SX1257", + "freq": 905000000, + "rssi_offset": -166.0, + "tx_enable": false + }, + "chan_multiSF_0": { + "enable": true, + "radio": 0, + "if": -400000 + }, + "chan_multiSF_1": { + "enable": true, + "radio": 0, + "if": -200000 + }, + "chan_multiSF_2": { + "enable": true, + "radio": 0, + "if": 0 + }, + "chan_multiSF_3": { + "enable": true, + "radio": 0, + "if": 200000 + }, + "chan_multiSF_4": { + "enable": true, + "radio": 1, + "if": -300000 + }, + "chan_multiSF_5": { + "enable": true, + "radio": 1, + "if": -100000 + }, + "chan_multiSF_6": { + "enable": true, + "radio": 1, + "if": 100000 + }, + "chan_multiSF_7": { + "enable": true, + "radio": 1, + "if": 300000 + }, + "chan_Lora_std": { + "enable": true, + "radio": 0, + "if": 300000, + "bandwidth": 500000, + "spread_factor": 8 + }, + "chan_FSK": { + "enable": false, + "radio": 0, + "if": 300000, + "bandwidth": 250000, + "datarate": 100000 + }, + "tx_lut_0": { + "desc": "TX gain table, index 0", + "pa_gain": 0, + "mix_gain": 8, + "rf_power": -6, + "dig_gain": 0 + }, + "tx_lut_1": { + "desc": "TX gain table, index 1", + "pa_gain": 0, + "mix_gain": 10, + "rf_power": -3, + "dig_gain": 0 + }, + "tx_lut_2": { + "desc": "TX gain table, index 2", + "pa_gain": 0, + "mix_gain": 12, + "rf_power": 0, + "dig_gain": 0 + }, + "tx_lut_3": { + "desc": "TX gain table, index 3", + "pa_gain": 1, + "mix_gain": 8, + "rf_power": 3, + "dig_gain": 0 + }, + "tx_lut_4": { + "desc": "TX gain table, index 4", + "pa_gain": 1, + "mix_gain": 10, + "rf_power": 6, + "dig_gain": 0 + }, + "tx_lut_5": { + "desc": "TX gain table, index 5", + "pa_gain": 1, + "mix_gain": 12, + "rf_power": 10, + "dig_gain": 0 + }, + "tx_lut_6": { + "desc": "TX gain table, index 6", + "pa_gain": 1, + "mix_gain": 13, + "rf_power": 11, + "dig_gain": 0 + }, + "tx_lut_7": { + "desc": "TX gain table, index 7", + "pa_gain": 2, + "mix_gain": 9, + "rf_power": 12, + "dig_gain": 0 + }, + "tx_lut_8": { + "desc": "TX gain table, index 8", + "pa_gain": 1, + "mix_gain": 15, + "rf_power": 13, + "dig_gain": 0 + }, + "tx_lut_9": { + "desc": "TX gain table, index 9", + "pa_gain": 2, + "mix_gain": 10, + "rf_power": 14, + "dig_gain": 0 + }, + "tx_lut_10": { + "desc": "TX gain table, index 10", + "pa_gain": 2, + "mix_gain": 11, + "rf_power": 16, + "dig_gain": 0 + }, + "tx_lut_11": { + "desc": "TX gain table, index 11", + "pa_gain": 3, + "mix_gain": 9, + "rf_power": 20, + "dig_gain": 0 + }, + "tx_lut_12": { + "desc": "TX gain table, index 12", + "pa_gain": 3, + "mix_gain": 10, + "rf_power": 23, + "dig_gain": 0 + }, + "tx_lut_13": { + "desc": "TX gain table, index 13", + "pa_gain": 3, + "mix_gain": 11, + "rf_power": 25, + "dig_gain": 0 + }, + "tx_lut_14": { + "desc": "TX gain table, index 14", + "pa_gain": 3, + "mix_gain": 12, + "rf_power": 26, + "dig_gain": 0 + }, + "tx_lut_15": { + "desc": "TX gain table, index 15", + "pa_gain": 3, + "mix_gain": 14, + "rf_power": 27, + "dig_gain": 0 + } + }, + "gateway_conf": { + "gateway_ID": "0000000000000000", + /* change with default server address/ports, or overwrite in local_conf.json */ + "server_address": "router.us.thethings.network", + "serv_port_up": 1700, + "serv_port_down": 1700, + /* adjust the following parameters for your network */ + "keepalive_interval": 10, + "stat_interval": 30, + "push_timeout_ms": 100, + /* forward only valid packets */ + "forward_crc_valid": true, + "forward_crc_error": false, + "forward_crc_disabled": false, + "autoquit_threshold": 6 + } +} diff --git a/lora/rak2247/install.sh b/lora/rak2247/install.sh new file mode 100755 index 0000000..441a2e7 --- /dev/null +++ b/lora/rak2247/install.sh @@ -0,0 +1,98 @@ +#!/bin/bash + +# Stop on the first sign of trouble +set -e + +if [ $UID != 0 ]; then + echo "ERROR: Operation not permitted. Forgot sudo?" + exit 1 +fi + +SCRIPT_DIR=$(pwd) + +# Request gateway configuration data +# There are two ways to do it, manually specify everything +# or rely on the gateway EUI and retrieve settings files from remote (recommended) +echo "Gateway configuration:" + +if [ ! -d "/usr/local/rak/gateway-config-info" ]; then mkdir "/usr/local/rak/gateway-config-info" -p ; fi + +# Try to get gateway ID from MAC address +# First try eth0, if that does not exist, try wlan0 (for RPi Zero) +GATEWAY_EUI_NIC="eth0" +if [[ `grep "$GATEWAY_EUI_NIC" /proc/net/dev` == "" ]]; then + GATEWAY_EUI_NIC="wlan0" +fi + +if [[ `grep "$GATEWAY_EUI_NIC" /proc/net/dev` == "" ]]; then + echo "ERROR: No network interface found. Cannot set gateway ID." + exit 1 +fi + +if [ ! -d "/usr/local/rak/bin" ]; then mkdir "/usr/local/rak/bin" -p ; fi + +GATEWAY_EUI=$(ip link show $GATEWAY_EUI_NIC | awk '/ether/ {print $2}' | awk -F\: '{print $1$2$3"FFFE"$4$5$6}') +GATEWAY_EUI=${GATEWAY_EUI^^} # toupper + +echo "Detected EUI $GATEWAY_EUI from $GATEWAY_EUI_NIC" + +# Check dependencies +echo "Installing dependencies..." +apt-get -y install git libftdi-dev libusb-dev + +# Build libraries + +if [ ! -d libmpsse ]; then + git clone https://github.com/devttys0/libmpsse.git +fi +pushd libmpsse/src +./configure --disable-python +make +make install +ldconfig +popd + +# Install LoRaWAN packet forwarder repositories +INSTALL_DIR="./" +if [ ! -d "$INSTALL_DIR" ]; then mkdir $INSTALL_DIR; fi +pushd $INSTALL_DIR + +# Build LoRa gateway app + +if [ ! -d lora_gateway ]; then + git clone https://github.com/Lora-net/lora_gateway.git +fi +pushd lora_gateway + +cp ./libloragw/99-libftdi.rules /etc/udev/rules.d/99-libftdi.rules +cp $SCRIPT_DIR/loragw_spi.ftdi.c ./libloragw/src/ +cp $SCRIPT_DIR/Makefile-gw-lib ./libloragw/Makefile +cp $SCRIPT_DIR/Makefile-lbt-test ./util_lbt_test/Makefile +cp $SCRIPT_DIR/Makefile-pkt-logger ./util_pkt_logger/Makefile +cp $SCRIPT_DIR/Makefile-spectral-scan ./util_spectral_scan/Makefile +cp $SCRIPT_DIR/Makefile-spi-stress ./util_spi_stress/Makefile +cp $SCRIPT_DIR/Makefile-tx-continuous ./util_tx_continuous/Makefile +cp $SCRIPT_DIR/Makefile-tx-test ./util_tx_test/Makefile +cp $SCRIPT_DIR/library.cfg ./libloragw/ +cp $SCRIPT_DIR/Makefile-gw ./Makefile + +sed -i -e 's/CFG_SPI= native/CFG_SPI= ftdi/g' ./libloragw/library.cfg + +make +popd + +# Build packet forwarder +if [ ! -d packet_forwarder ]; then + git clone https://github.com/Lora-net/packet_forwarder.git +fi +pushd packet_forwarder + +cp $SCRIPT_DIR/Makefile-pk ./lora_pkt_fwd/Makefile + +make + +popd + +LOCAL_CONFIG_FILE=$INSTALL_DIR/packet_forwarder/lora_pkt_fwd/local_conf.json +echo -e "{\n\t\"gateway_conf\": {\n\t\t\"gateway_ID\": \"$GATEWAY_EUI\" \n\t}\n}" >$LOCAL_CONFIG_FILE +cp global_conf $INSTALL_DIR/packet_forwarder/lora_pkt_fwd/ -rf diff --git a/lora/rak2247/library.cfg b/lora/rak2247/library.cfg new file mode 100755 index 0000000..f627325 --- /dev/null +++ b/lora/rak2247/library.cfg @@ -0,0 +1,21 @@ +# 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 (RECOMMENDED). +# Note: check the value of /dev/spidevX.X defined in source code +# to ensure the right device will be opened on your platform. +# ftdi FTDI SPI-over-USB bridge using libmpsse/libftdi/libusb + +CFG_SPI= ftdi + +### 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 +DEBUG_HAL= 0 +DEBUG_LBT= 0 +DEBUG_GPS= 0 diff --git a/lora/rak2247/loragw_spi.ftdi.c b/lora/rak2247/loragw_spi.ftdi.c new file mode 100755 index 0000000..d441a40 --- /dev/null +++ b/lora/rak2247/loragw_spi.ftdi.c @@ -0,0 +1,298 @@ +/* + / _____) _ | | +( (____ _____ ____ _| |_ _____ ____| |__ + \____ \| ___ | (_ _) ___ |/ ___) _ \ + _____) ) ____| | | || |_| ____( (___| | | | +(______/|_____)_|_|_| \__)_____)\____)_| |_| + (C)2013 Semtech-Cycleo + +Description: + Host specific functions to address the LoRa concentrator registers through + a SPI interface. + Single-byte read/write and burst read/write. + Does not handle pagination. + Could be used with multiple SPI ports in parallel (explicit file descriptor) + +License: Revised BSD License, see LICENSE.TXT file include in the project +Maintainer: Sylvain Miermont +*/ + + +/* -------------------------------------------------------------------------- */ +/* --- DEPENDANCIES --------------------------------------------------------- */ + +#include /* C99 types */ +#include /* printf fprintf */ +#include /* malloc free */ +#include /* memcpy */ + +#include + +#include "loragw_spi.h" + +/* -------------------------------------------------------------------------- */ +/* --- PRIVATE MACROS ------------------------------------------------------- */ + +#define ARRAY_SIZE(a) (sizeof(a) / sizeof((a)[0])) +#if DEBUG_SPI == 1 + #define DEBUG_MSG(str) fprintf(stderr, str) + #define DEBUG_PRINTF(fmt, args...) fprintf(stderr,"%s:%d: "fmt, __FUNCTION__, __LINE__, args) + #define CHECK_NULL(a) if(a==NULL){fprintf(stderr,"%s:%d: ERROR: NULL POINTER AS ARGUMENT\n", __FUNCTION__, __LINE__);return LGW_SPI_ERROR;} +#else + #define DEBUG_MSG(str) + #define DEBUG_PRINTF(fmt, args...) + #define CHECK_NULL(a) if(a==NULL){return LGW_SPI_ERROR;} +#endif + +/* -------------------------------------------------------------------------- */ +/* --- PRIVATE CONSTANTS ---------------------------------------------------- */ + +#define READ_ACCESS 0x00 +#define WRITE_ACCESS 0x80 + +/* parameters for a FT2232H */ +#define VID 0x0403 +#define PID 0x6010 + +/* -------------------------------------------------------------------------- */ +/* --- PUBLIC FUNCTIONS DEFINITION ------------------------------------------ */ + +/* SPI initialization and configuration */ +int lgw_spi_open(void **spi_target_ptr) { + struct mpsse_context *mpsse = NULL; + int a, b; + + /* check input variables */ + CHECK_NULL(spi_target_ptr); /* cannot be null, must point on a void pointer (*spi_target_ptr can be null) */ + + /* try to open the first available FTDI device matching VID/PID parameters */ + mpsse = OpenIndex(VID,PID,SPI0, SIX_MHZ, MSB, IFACE_A, NULL, NULL, 0); + if (mpsse == NULL) { + DEBUG_MSG("ERROR: MPSSE OPEN FUNCTION RETURNED NULL\n"); + return LGW_SPI_ERROR; + } + if (mpsse->open != 1) { + DEBUG_MSG("ERROR: MPSSE OPEN FUNCTION FAILED\n"); + return LGW_SPI_ERROR; + } + + /* toggle pin ADBUS5 of the FT2232H */ + /* On the Semtech reference board, it resets the SX1301 */ + a = PinHigh(mpsse, GPIOL1); + b = PinLow(mpsse, GPIOL1); + if ((a != MPSSE_OK) || (b != MPSSE_OK)) { + DEBUG_MSG("ERROR: IMPOSSIBLE TO TOGGLE GPIOL1/ADBUS5\n"); + return LGW_SPI_ERROR; + } + + DEBUG_PRINTF("SPI port opened and configured ok\ndesc: %s\nPID: 0x%04X\nVID: 0x%04X\nclock: %d\nLibmpsse version: 0x%02X\n", GetDescription(mpsse), GetPid(mpsse), GetVid(mpsse), GetClock(mpsse), Version()); + *spi_target_ptr = (void *)mpsse; + return LGW_SPI_SUCCESS; +} + +/* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ */ + +/* SPI release */ +int lgw_spi_close(void *spi_target) { + struct mpsse_context *mpsse = spi_target; + + /* check input variables */ + CHECK_NULL(spi_target); + + Close(mpsse); + + /* close return no status, assume success (0_o) */ + return LGW_SPI_SUCCESS; +} + +/* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ */ + +/* Simple write */ +/* transaction time: .6 to 1 ms typically */ +int lgw_spi_w(void *spi_target,uint8_t spi_mux_mode, uint8_t spi_mux_target, uint8_t address, uint8_t data) { + struct mpsse_context *mpsse = spi_target; + uint8_t out_buf[2]; + int a, b, c; + + /* check input variables */ + CHECK_NULL(spi_target); + if ((address & 0x80) != 0) { + DEBUG_MSG("WARNING: SPI address > 127\n"); + } + + /* prepare frame to be sent */ + out_buf[0] = WRITE_ACCESS | (address & 0x7F); + out_buf[1] = data; + + /* MPSSE transaction */ + a = Start(mpsse); + b = FastWrite(mpsse, (char *)out_buf, 2); + c = Stop(mpsse); + + /* determine return code */ + if ((a != MPSSE_OK) || (b != MPSSE_OK) || (c != MPSSE_OK)) { + DEBUG_MSG("ERROR: SPI WRITE FAILURE\n"); + return LGW_SPI_ERROR; + } else { + DEBUG_MSG("Note: SPI write success\n"); + return LGW_SPI_SUCCESS; + } +} + +/* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ */ + +/* Simple read (using Transfer function) */ +/* transaction time: 1.1 to 2 ms typically */ +int lgw_spi_r(void *spi_target, uint8_t spi_mux_mode, uint8_t spi_mux_target,uint8_t address, uint8_t *data) { + struct mpsse_context *mpsse = spi_target; + uint8_t out_buf[2]; + uint8_t *in_buf = NULL; + int a, b; + + /* check input variables */ + CHECK_NULL(spi_target); + if ((address & 0x80) != 0) { + DEBUG_MSG("WARNING: SPI address > 127\n"); + } + CHECK_NULL(data); + + /* prepare frame to be sent */ + out_buf[0] = READ_ACCESS | (address & 0x7F); + out_buf[1] = 0x00; + + /* MPSSE transaction */ + a = Start(mpsse); + in_buf = (uint8_t *)Transfer(mpsse, (char *)out_buf, 2); + b = Stop(mpsse); + + /* determine return code */ + if ((in_buf == NULL) || (a != MPSSE_OK) || (b != MPSSE_OK)) { + DEBUG_MSG("ERROR: SPI READ FAILURE\n"); + if (in_buf != NULL) { + free(in_buf); + } + return LGW_SPI_ERROR; + } else { + DEBUG_MSG("Note: SPI read success\n"); + *data = in_buf[1]; + free(in_buf); + return LGW_SPI_SUCCESS; + } +} + +/* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ */ + +/* Burst (multiple-byte) write */ +/* transaction time: 3.7ms for 2500 data bytes @6MHz, 1kB chunks */ +/* transaction time: 0.5ms for 16 data bytes @6MHz, 1kB chunks */ +int lgw_spi_wb(void *spi_target, uint8_t spi_mux_mode, uint8_t spi_mux_target,uint8_t address, uint8_t *data, uint16_t size) { + struct mpsse_context *mpsse = spi_target; + uint8_t command; + uint8_t *out_buf = NULL; + int size_to_do, buf_size, chunk_size, offset; + int a=0, b=0, c=0; + int i; + + /* check input parameters */ + CHECK_NULL(spi_target); + if ((address & 0x80) != 0) { + DEBUG_MSG("WARNING: SPI address > 127\n"); + } + CHECK_NULL(data); + if (size == 0) { + DEBUG_MSG("ERROR: BURST OF NULL LENGTH\n"); + return LGW_SPI_ERROR; + } + + /* prepare command byte */ + command = WRITE_ACCESS | (address & 0x7F); + size_to_do = size + 1; /* add a byte for the address */ + + /* allocate data buffer */ + buf_size = (size_to_do < LGW_BURST_CHUNK) ? size_to_do : LGW_BURST_CHUNK; + out_buf = malloc(buf_size); + if (out_buf == NULL) { + DEBUG_MSG("ERROR: MALLOC FAIL\n"); + return LGW_SPI_ERROR; + } + + /* start MPSSE transaction */ + a = Start(mpsse); + for (i=0; size_to_do > 0; ++i) { + chunk_size = (size_to_do < LGW_BURST_CHUNK) ? size_to_do : LGW_BURST_CHUNK; + if (i == 0) { + /* first chunk, need to append the address */ + out_buf[0] = command; + memcpy(out_buf+1, data, chunk_size-1); + } else { + /* following chunks, just copy the data */ + offset = (i * LGW_BURST_CHUNK) - 1; + memcpy(out_buf, data + offset, chunk_size); + } + b = FastWrite(mpsse, (char *)out_buf, chunk_size); + size_to_do -= chunk_size; /* subtract the quantity of data already transferred */ + } + c = Stop(mpsse); + + /* deallocate data buffer */ + free(out_buf); + + /* determine return code (only the last FastWrite is checked) */ + if ((a != MPSSE_OK) || (b != MPSSE_OK) || (c != MPSSE_OK)) { + DEBUG_MSG("ERROR: SPI BURST WRITE FAILURE\n"); + return LGW_SPI_ERROR; + } else { + DEBUG_MSG("Note: SPI burst write success\n"); + return LGW_SPI_SUCCESS; + } +} + +/* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ */ + +/* Burst (multiple-byte) read (using FastWrite & FastRead functions) */ +/* transaction time: 7-12ms for 2500 data bytes @6MHz, 1kB chunks */ +/* transaction time: 2ms for 16 data bytes @6MHz, 1kB chunks */ +int lgw_spi_rb(void *spi_target, uint8_t spi_mux_mode, uint8_t spi_mux_target,uint8_t address, uint8_t *data, uint16_t size) { + struct mpsse_context *mpsse = spi_target; + uint8_t command; + int size_to_do, chunk_size, offset; + int a=0, b=0, c=0, d=0; + int i; + + /* check input parameters */ + CHECK_NULL(spi_target); + if ((address & 0x80) != 0) { + DEBUG_MSG("WARNING: SPI address > 127\n"); + } + CHECK_NULL(data); + if (size == 0) { + DEBUG_MSG("ERROR: BURST OF NULL LENGTH\n"); + return LGW_SPI_ERROR; + } + + /* prepare command byte */ + command = READ_ACCESS | (address & 0x7F); + size_to_do = size; + + /* start MPSSE transaction */ + a = Start(mpsse); + b = FastWrite(mpsse, (char *)&command, 1); + for (i=0; size_to_do > 0; ++i) { + chunk_size = (size_to_do < LGW_BURST_CHUNK) ? size_to_do : LGW_BURST_CHUNK; + offset = i * LGW_BURST_CHUNK; + c = FastRead(mpsse, (char *)(data + offset), chunk_size); + size_to_do -= chunk_size; /* subtract the quantity of data already transferred */ + } + d = Stop(mpsse); + + /* determine return code (only the last FastRead is checked) */ + if ((a != MPSSE_OK) || (b != MPSSE_OK) || (c != MPSSE_OK) || (d != MPSSE_OK)) { + DEBUG_MSG("ERROR: SPI BURST READ FAILURE\n"); + return LGW_SPI_ERROR; + } else { + DEBUG_MSG("Note: SPI burst read success\n"); + return LGW_SPI_SUCCESS; + } +} + +/* --- EOF ------------------------------------------------------------------ */ diff --git a/lora/rak7243/global_conf.json b/lora/rak7243/global_conf.json new file mode 100644 index 0000000..d4fc5b5 --- /dev/null +++ b/lora/rak7243/global_conf.json @@ -0,0 +1,199 @@ +{ + "SX1301_conf": { + "lorawan_public": true, + "clksrc": 1, + "antenna_gain": 0, + "radio_0": { + "enable": true, + "type": "SX1257", + "freq": 867500000, + "rssi_offset": -166.0, + "tx_enable": true, + "tx_freq_min": 863000000, + "tx_freq_max": 870000000 + }, + "radio_1": { + "enable": true, + "type": "SX1257", + "freq": 868500000, + "rssi_offset": -166.0, + "tx_enable": false + }, + "chan_multiSF_0": { + "enable": true, + "radio": 1, + "if": -400000 + }, + "chan_multiSF_1": { + "enable": true, + "radio": 1, + "if": -200000 + }, + "chan_multiSF_2": { + "enable": true, + "radio": 1, + "if": 0 + }, + "chan_multiSF_3": { + "enable": true, + "radio": 0, + "if": -400000 + }, + "chan_multiSF_4": { + "enable": true, + "radio": 0, + "if": -200000 + }, + "chan_multiSF_5": { + "enable": true, + "radio": 0, + "if": 0 + }, + "chan_multiSF_6": { + "enable": true, + "radio": 0, + "if": 200000 + }, + "chan_multiSF_7": { + "enable": true, + "radio": 0, + "if": 400000 + }, + "chan_Lora_std": { + "enable": true, + "radio": 1, + "if": -200000, + "bandwidth": 250000, + "spread_factor": 7 + }, + "chan_FSK": { + "enable": true, + "radio": 1, + "if": 300000, + "bandwidth": 125000, + "datarate": 50000 + }, + "tx_lut_0": { + "pa_gain": 0, + "mix_gain": 8, + "rf_power": -6, + "dig_gain": 0 + }, + "tx_lut_1": { + "pa_gain": 0, + "mix_gain": 10, + "rf_power": -3, + "dig_gain": 0 + }, + "tx_lut_2": { + "pa_gain": 0, + "mix_gain": 12, + "rf_power": 0, + "dig_gain": 0 + }, + "tx_lut_3": { + "pa_gain": 1, + "mix_gain": 8, + "rf_power": 3, + "dig_gain": 0 + }, + "tx_lut_4": { + "pa_gain": 1, + "mix_gain": 10, + "rf_power": 6, + "dig_gain": 0 + }, + "tx_lut_5": { + "pa_gain": 1, + "mix_gain": 12, + "rf_power": 10, + "dig_gain": 0 + }, + "tx_lut_6": { + "pa_gain": 1, + "mix_gain": 13, + "rf_power": 11, + "dig_gain": 0 + }, + "tx_lut_7": { + "pa_gain": 2, + "mix_gain": 9, + "rf_power": 12, + "dig_gain": 0 + }, + "tx_lut_8": { + "pa_gain": 1, + "mix_gain": 15, + "rf_power": 13, + "dig_gain": 0 + }, + "tx_lut_9": { + "pa_gain": 2, + "mix_gain": 10, + "rf_power": 14, + "dig_gain": 0 + }, + "tx_lut_10": { + "pa_gain": 2, + "mix_gain": 11, + "rf_power": 16, + "dig_gain": 0 + }, + "tx_lut_11": { + "pa_gain": 3, + "mix_gain": 9, + "rf_power": 20, + "dig_gain": 0 + }, + "tx_lut_12": { + "desc": "TX gain table, index 12", + "pa_gain": 3, + "mix_gain": 10, + "rf_power": 23, + "dig_gain": 0 + }, + "tx_lut_13": { + "desc": "TX gain table, index 13", + "pa_gain": 3, + "mix_gain": 11, + "rf_power": 25, + "dig_gain": 0 + }, + "tx_lut_14": { + "desc": "TX gain table, index 14", + "pa_gain": 3, + "mix_gain": 12, + "rf_power": 26, + "dig_gain": 0 + }, + "tx_lut_15": { + "desc": "TX gain table, index 15", + "pa_gain": 3, + "mix_gain": 14, + "rf_power": 27, + "dig_gain": 0 + } + }, + "gateway_conf": { + "gateway_ID": "0000000000000000", + /* change with default server address/ports, or overwrite in local_conf.json */ + "server_address": "127.0.0.1", + "serv_port_up": 1700, + "serv_port_down": 1700, + /* adjust the following parameters for your network */ + "keepalive_interval": 10, + "stat_interval": 30, + "push_timeout_ms": 100, + /* forward only valid packets */ + "forward_crc_valid": true, + "forward_crc_error": false, + "forward_crc_disabled": false, + /* gps enable */ + "gps": true, + "gps_tty_path": "/dev/i2c-1", + "fake_gps": false, + "ref_latitude": 10, + "ref_longitude": 20, + "ref_altitude": -1 + } +} diff --git a/lora/rak7243/global_conf/global_conf.as_923.json b/lora/rak7243/global_conf/global_conf.as_923.json new file mode 100644 index 0000000..afcae83 --- /dev/null +++ b/lora/rak7243/global_conf/global_conf.as_923.json @@ -0,0 +1,225 @@ +{ + "SX1301_conf": { + "lorawan_public": true, + "clksrc": 1, + "clksrc_desc": "radio_1 provides clock to concentrator for most devices except MultiTech. For MultiTech set to 0.", + "antenna_gain": 0, + "antenna_gain_desc": "antenna gain, in dBi", + "radio_0": { + "enable": true, + "type": "SX1257", + "freq": 923600000, + "rssi_offset": -166.0, + "tx_enable": true, + "tx_freq_min": 923200000, + "tx_freq_max": 925000000 + }, + "radio_1": { + "enable": true, + "type": "SX1257", + "freq": 924600000, + "rssi_offset": -166.0, + "tx_enable": false + }, + "chan_multiSF_0": { + "desc": "Lora MAC, 125kHz, all SF, 923.2 MHz", + "enable": true, + "radio": 0, + "if": -400000 + }, + "chan_multiSF_1": { + "desc": "Lora MAC, 125kHz, all SF, 923.4 MHz", + "enable": true, + "radio": 0, + "if": -200000 + }, + "chan_multiSF_2": { + "desc": "Lora MAC, 125kHz, all SF, 923.6 MHz", + "enable": true, + "radio": 0, + "if": 0 + }, + "chan_multiSF_3": { + "desc": "Lora MAC, 125kHz, all SF, 923.8 MHz", + "enable": true, + "radio": 0, + "if": 200000 + }, + "chan_multiSF_4": { + "desc": "Lora MAC, 125kHz, all SF, 924.0 MHz", + "enable": true, + "radio": 0, + "if": 400000 + }, + "chan_multiSF_5": { + "desc": "Lora MAC, 125kHz, all SF, 924.2 MHz", + "enable": true, + "radio": 1, + "if": -400000 + }, + "chan_multiSF_6": { + "desc": "Lora MAC, 125kHz, all SF, 924.4 MHz", + "enable": true, + "radio": 1, + "if": -200000 + }, + "chan_multiSF_7": { + "desc": "Lora MAC, 125kHz, all SF, 924.6 MHz", + "enable": true, + "radio": 1, + "if": 0 + }, + "chan_Lora_std": { + "desc": "Lora MAC, 250kHz, SF7, 924.5 MHz", + "enable": true, + "radio": 1, + "if": -100000, + "bandwidth": 250000, + "spread_factor": 7 + }, + "chan_FSK": { + "desc": "FSK 50kbps, 924.8 MHz", + "enable": true, + "radio": 1, + "if": 200000, + "bandwidth": 125000, + "datarate": 50000 + }, + "tx_lut_0": { + "desc": "TX gain table, index 0", + "pa_gain": 0, + "mix_gain": 8, + "rf_power": -6, + "dig_gain": 0 + }, + "tx_lut_1": { + "desc": "TX gain table, index 1", + "pa_gain": 0, + "mix_gain": 10, + "rf_power": -3, + "dig_gain": 0 + }, + "tx_lut_2": { + "desc": "TX gain table, index 2", + "pa_gain": 0, + "mix_gain": 12, + "rf_power": 0, + "dig_gain": 0 + }, + "tx_lut_3": { + "desc": "TX gain table, index 3", + "pa_gain": 1, + "mix_gain": 8, + "rf_power": 3, + "dig_gain": 0 + }, + "tx_lut_4": { + "desc": "TX gain table, index 4", + "pa_gain": 1, + "mix_gain": 10, + "rf_power": 6, + "dig_gain": 0 + }, + "tx_lut_5": { + "desc": "TX gain table, index 5", + "pa_gain": 1, + "mix_gain": 12, + "rf_power": 10, + "dig_gain": 0 + }, + "tx_lut_6": { + "desc": "TX gain table, index 6", + "pa_gain": 1, + "mix_gain": 13, + "rf_power": 11, + "dig_gain": 0 + }, + "tx_lut_7": { + "desc": "TX gain table, index 7", + "pa_gain": 2, + "mix_gain": 9, + "rf_power": 12, + "dig_gain": 0 + }, + "tx_lut_8": { + "desc": "TX gain table, index 8", + "pa_gain": 1, + "mix_gain": 15, + "rf_power": 13, + "dig_gain": 0 + }, + "tx_lut_9": { + "desc": "TX gain table, index 9", + "pa_gain": 2, + "mix_gain": 10, + "rf_power": 14, + "dig_gain": 0 + }, + "tx_lut_10": { + "desc": "TX gain table, index 10", + "pa_gain": 2, + "mix_gain": 11, + "rf_power": 16, + "dig_gain": 0 + }, + "tx_lut_11": { + "desc": "TX gain table, index 11", + "pa_gain": 3, + "mix_gain": 9, + "rf_power": 20, + "dig_gain": 0 + }, + "tx_lut_12": { + "desc": "TX gain table, index 12", + "pa_gain": 3, + "mix_gain": 10, + "rf_power": 23, + "dig_gain": 0 + }, + "tx_lut_13": { + "desc": "TX gain table, index 13", + "pa_gain": 3, + "mix_gain": 11, + "rf_power": 25, + "dig_gain": 0 + }, + "tx_lut_14": { + "desc": "TX gain table, index 14", + "pa_gain": 3, + "mix_gain": 12, + "rf_power": 26, + "dig_gain": 0 + }, + "tx_lut_15": { + "desc": "TX gain table, index 15", + "pa_gain": 3, + "mix_gain": 14, + "rf_power": 27, + "dig_gain": 0 + } + }, + "gateway_conf": { + "gateway_ID": "0000000000000000", + /* change with default server address/ports, or overwrite in local_conf.json */ + "server_address": "router.as2.thethings.network", + "serv_port_up": 1700, + "serv_port_down": 1700, + /* adjust the following parameters for your network */ + "keepalive_interval": 10, + "stat_interval": 30, + "push_timeout_ms": 100, + /* forward only valid packets */ + "forward_crc_valid": true, + "forward_crc_error": false, + "forward_crc_disabled": false, + /* gps enable */ + "gps": true, + "gps_tty_path": "/dev/i2c-1", + "fake_gps": false, + "ref_latitude": 10, + "ref_longitude": 20, + "ref_altitude": -1, + "autoquit_threshold": 6 + } + +} diff --git a/lora/rak7243/global_conf/global_conf.au_915_928.json b/lora/rak7243/global_conf/global_conf.au_915_928.json new file mode 100644 index 0000000..55d9c70 --- /dev/null +++ b/lora/rak7243/global_conf/global_conf.au_915_928.json @@ -0,0 +1,222 @@ +{ + "SX1301_conf": { + "lorawan_public": true, + "clksrc": 1, + "clksrc_desc": "radio_1 provides clock to concentrator for most devices except MultiTech. For MultiTech set to 0.", + "antenna_gain": 0, + "antenna_gain_desc": "antenna gain, in dBi", + "radio_0": { + "enable": true, + "type": "SX1257", + "freq": 917200000, + "rssi_offset": -166.0, + "tx_enable": true, + "tx_freq_min": 915000000, + "tx_freq_max": 928000000 + }, + "radio_1": { + "enable": true, + "type": "SX1257", + "freq": 917900000, + "rssi_offset": -166.0, + "tx_enable": false + }, + "chan_multiSF_0": { + "desc": "Lora MAC, 125kHz, all SF, 916.8 MHz", + "enable": true, + "radio": 0, + "if": -400000 + }, + "chan_multiSF_1": { + "desc": "Lora MAC, 125kHz, all SF, 917.0 MHz", + "enable": true, + "radio": 0, + "if": -200000 + }, + "chan_multiSF_2": { + "desc": "Lora MAC, 125kHz, all SF, 917.2 MHz", + "enable": true, + "radio": 0, + "if": 0 + }, + "chan_multiSF_3": { + "desc": "Lora MAC, 125kHz, all SF, 917.4 MHz", + "enable": true, + "radio": 0, + "if": 200000 + }, + "chan_multiSF_4": { + "desc": "Lora MAC, 125kHz, all SF, 917.6 MHz", + "enable": true, + "radio": 1, + "if": -300000 + }, + "chan_multiSF_5": { + "desc": "Lora MAC, 125kHz, all SF, 917.8 MHz", + "enable": true, + "radio": 1, + "if": -100000 + }, + "chan_multiSF_6": { + "desc": "Lora MAC, 125kHz, all SF, 918.0 MHz", + "enable": true, + "radio": 1, + "if": 100000 + }, + "chan_multiSF_7": { + "desc": "Lora MAC, 125kHz, all SF, 918.2 MHz", + "enable": true, + "radio": 1, + "if": 300000 + }, + "chan_Lora_std": { + "desc": "Lora MAC, 500kHz, SF8, 917.5 MHz", + "enable": true, + "radio": 0, + "if": 300000, + "bandwidth": 500000, + "spread_factor": 8 + }, + "chan_FSK": { + "desc": "disabled", + "enable": false + }, + "tx_lut_0": { + "desc": "TX gain table, index 0", + "pa_gain": 0, + "mix_gain": 8, + "rf_power": -6, + "dig_gain": 0 + }, + "tx_lut_1": { + "desc": "TX gain table, index 1", + "pa_gain": 0, + "mix_gain": 10, + "rf_power": -3, + "dig_gain": 0 + }, + "tx_lut_2": { + "desc": "TX gain table, index 2", + "pa_gain": 0, + "mix_gain": 12, + "rf_power": 0, + "dig_gain": 0 + }, + "tx_lut_3": { + "desc": "TX gain table, index 3", + "pa_gain": 1, + "mix_gain": 8, + "rf_power": 3, + "dig_gain": 0 + }, + "tx_lut_4": { + "desc": "TX gain table, index 4", + "pa_gain": 1, + "mix_gain": 10, + "rf_power": 6, + "dig_gain": 0 + }, + "tx_lut_5": { + "desc": "TX gain table, index 5", + "pa_gain": 1, + "mix_gain": 12, + "rf_power": 10, + "dig_gain": 0 + }, + "tx_lut_6": { + "desc": "TX gain table, index 6", + "pa_gain": 1, + "mix_gain": 13, + "rf_power": 11, + "dig_gain": 0 + }, + "tx_lut_7": { + "desc": "TX gain table, index 7", + "pa_gain": 2, + "mix_gain": 9, + "rf_power": 12, + "dig_gain": 0 + }, + "tx_lut_8": { + "desc": "TX gain table, index 8", + "pa_gain": 1, + "mix_gain": 15, + "rf_power": 13, + "dig_gain": 0 + }, + "tx_lut_9": { + "desc": "TX gain table, index 9", + "pa_gain": 2, + "mix_gain": 10, + "rf_power": 14, + "dig_gain": 0 + }, + "tx_lut_10": { + "desc": "TX gain table, index 10", + "pa_gain": 2, + "mix_gain": 11, + "rf_power": 16, + "dig_gain": 0 + }, + "tx_lut_11": { + "desc": "TX gain table, index 11", + "pa_gain": 3, + "mix_gain": 9, + "rf_power": 20, + "dig_gain": 0 + }, + "tx_lut_12": { + "desc": "TX gain table, index 12", + "pa_gain": 3, + "mix_gain": 10, + "rf_power": 23, + "dig_gain": 0 + }, + "tx_lut_13": { + "desc": "TX gain table, index 13", + "pa_gain": 3, + "mix_gain": 11, + "rf_power": 25, + "dig_gain": 0 + }, + "tx_lut_14": { + "desc": "TX gain table, index 14", + "pa_gain": 3, + "mix_gain": 12, + "rf_power": 26, + "dig_gain": 0 + }, + "tx_lut_15": { + "desc": "TX gain table, index 15", + "pa_gain": 3, + "mix_gain": 14, + "rf_power": 27, + "dig_gain": 0 + } + }, + "gateway_conf": { + "gateway_ID": "0000000000000000", + /* change with default server address/ports, or overwrite in local_conf.json */ + "server_address": "router.au.thethings.network", + "serv_port_up": 1700, + "serv_port_down": 1700, + /* adjust the following parameters for your network */ + "keepalive_interval": 10, + "stat_interval": 30, + "push_timeout_ms": 100, + /* forward only valid packets */ + "forward_crc_valid": true, + "forward_crc_error": false, + "forward_crc_disabled": false, + /* gps enable */ + "gps": true, + "gps_tty_path": "/dev/i2c-1", + "fake_gps": false, + "ref_latitude": 10, + "ref_longitude": 20, + "ref_altitude": -1, + "autoquit_threshold": 6 + } + +} + diff --git a/lora/rak7243/global_conf/global_conf.cn_470_510.json b/lora/rak7243/global_conf/global_conf.cn_470_510.json new file mode 100644 index 0000000..7dafb4a --- /dev/null +++ b/lora/rak7243/global_conf/global_conf.cn_470_510.json @@ -0,0 +1,217 @@ +{ + "SX1301_conf": { + "lorawan_public": true, + "clksrc": 1, + "clksrc_desc": "radio_1 provides clock to concentrator for most devices except MultiTech. For MultiTech set to 0.", + "antenna_gain": 0, + "antenna_gain_desc": "antenna gain, in dBi", + "radio_0": { + "enable": true, + "type": "SX1255", + "freq": 486600000, + "rssi_offset": -176.0, + "tx_enable": true, + "tx_freq_min": 470000000, + "tx_freq_max": 510000000 + }, + "radio_1": { + "enable": true, + "type": "SX1255", + "freq": 487400000, + "rssi_offset": -176.0, + "tx_enable": false + }, + "chan_multiSF_0": { + "desc": "Lora MAC, 125kHz, all SF, 487.1 MHz", + "enable": true, + "radio": 1, + "if": -300000 + }, + "chan_multiSF_1": { + "desc": "Lora MAC, 125kHz, all SF, 487.3 MHz", + "enable": true, + "radio": 1, + "if": -100000 + }, + "chan_multiSF_2": { + "desc": "Lora MAC, 125kHz, all SF, 487.5 MHz", + "enable": true, + "radio": 1, + "if": 100000 + }, + "chan_multiSF_3": { + "desc": "Lora MAC, 125kHz, all SF, 487.7 MHz", + "enable": true, + "radio": 1, + "if": 300000 + }, + "chan_multiSF_4": { + "desc": "Lora MAC, 125kHz, all SF, 486.3 MHz", + "enable": true, + "radio": 0, + "if": -300000 + }, + "chan_multiSF_5": { + "desc": "Lora MAC, 125kHz, all SF, 486.5 MHz", + "enable": true, + "radio": 0, + "if": -100000 + }, + "chan_multiSF_6": { + "desc": "Lora MAC, 125kHz, all SF, 486.7 MHz", + "enable": true, + "radio": 0, + "if": 100000 + }, + "chan_multiSF_7": { + "desc": "Lora MAC, 125kHz, all SF, 486.9 MHz", + "enable": true, + "radio": 0, + "if": 300000 + }, + "chan_Lora_std": { + "desc": "disabled", + "enable": false + }, + "chan_FSK": { + "desc": "disabled", + "enable": false + }, + "tx_lut_0": { + "desc": "TX gain table, index 0", + "pa_gain": 0, + "mix_gain": 8, + "rf_power": -6, + "dig_gain": 0 + }, + "tx_lut_1": { + "desc": "TX gain table, index 1", + "pa_gain": 0, + "mix_gain": 10, + "rf_power": -3, + "dig_gain": 0 + }, + "tx_lut_2": { + "desc": "TX gain table, index 2", + "pa_gain": 0, + "mix_gain": 12, + "rf_power": 0, + "dig_gain": 0 + }, + "tx_lut_3": { + "desc": "TX gain table, index 3", + "pa_gain": 1, + "mix_gain": 8, + "rf_power": 3, + "dig_gain": 0 + }, + "tx_lut_4": { + "desc": "TX gain table, index 4", + "pa_gain": 1, + "mix_gain": 10, + "rf_power": 6, + "dig_gain": 0 + }, + "tx_lut_5": { + "desc": "TX gain table, index 5", + "pa_gain": 1, + "mix_gain": 12, + "rf_power": 10, + "dig_gain": 0 + }, + "tx_lut_6": { + "desc": "TX gain table, index 6", + "pa_gain": 1, + "mix_gain": 13, + "rf_power": 11, + "dig_gain": 0 + }, + "tx_lut_7": { + "desc": "TX gain table, index 7", + "pa_gain": 2, + "mix_gain": 9, + "rf_power": 12, + "dig_gain": 0 + }, + "tx_lut_8": { + "desc": "TX gain table, index 8", + "pa_gain": 1, + "mix_gain": 15, + "rf_power": 13, + "dig_gain": 0 + }, + "tx_lut_9": { + "desc": "TX gain table, index 9", + "pa_gain": 2, + "mix_gain": 10, + "rf_power": 14, + "dig_gain": 0 + }, + "tx_lut_10": { + "desc": "TX gain table, index 10", + "pa_gain": 2, + "mix_gain": 11, + "rf_power": 16, + "dig_gain": 0 + }, + "tx_lut_11": { + "desc": "TX gain table, index 11", + "pa_gain": 3, + "mix_gain": 9, + "rf_power": 20, + "dig_gain": 0 + }, + "tx_lut_12": { + "desc": "TX gain table, index 12", + "pa_gain": 3, + "mix_gain": 10, + "rf_power": 23, + "dig_gain": 0 + }, + "tx_lut_13": { + "desc": "TX gain table, index 13", + "pa_gain": 3, + "mix_gain": 11, + "rf_power": 25, + "dig_gain": 0 + }, + "tx_lut_14": { + "desc": "TX gain table, index 14", + "pa_gain": 3, + "mix_gain": 12, + "rf_power": 26, + "dig_gain": 0 + }, + "tx_lut_15": { + "desc": "TX gain table, index 15", + "pa_gain": 3, + "mix_gain": 14, + "rf_power": 27, + "dig_gain": 0 + } + }, + "gateway_conf": { + "gateway_ID": "0000000000000000", + /* change with default server address/ports, or overwrite in local_conf.json */ + "server_address": "router.cn.thethings.network", + "serv_port_up": 1700, + "serv_port_down": 1700, + /* adjust the following parameters for your network */ + "keepalive_interval": 10, + "stat_interval": 30, + "push_timeout_ms": 100, + /* forward only valid packets */ + "forward_crc_valid": true, + "forward_crc_error": false, + "forward_crc_disabled": false, + /* gps enable */ + "gps": true, + "gps_tty_path": "/dev/i2c-1", + "fake_gps": false, + "ref_latitude": 10, + "ref_longitude": 20, + "ref_altitude": -1, + "autoquit_threshold": 6 + } +} + diff --git a/lora/rak7243/global_conf/global_conf.eu_433.json b/lora/rak7243/global_conf/global_conf.eu_433.json new file mode 100644 index 0000000..91238c6 --- /dev/null +++ b/lora/rak7243/global_conf/global_conf.eu_433.json @@ -0,0 +1,224 @@ +{ + + "SX1301_conf": { + "lorawan_public": true, + "clksrc": 1, /* radio_1 provides clock to concentrator */ + "antenna_gain": 0, /* antenna gain, in dBi */ + "radio_0": { + "enable": true, + "type": "SX1255", + "freq": 434375000, + "rssi_offset": -166.0, + "tx_enable": true, + "tx_freq_min": 433050000, + "tx_freq_max": 434900000 + }, + "radio_1": { + "enable": true, + "type": "SX1255", + "freq": 433575000, + "rssi_offset": -166.0, + "tx_enable": false + }, + "chan_multiSF_0": { + /* Lora MAC channel, 125kHz, all SF, 433.175 MHz */ + "enable": true, + "radio": 1, + "if": -400000 + }, + "chan_multiSF_1": { + /* Lora MAC channel, 125kHz, all SF, 433.375 MHz */ + "enable": true, + "radio": 1, + "if": -200000 + }, + "chan_multiSF_2": { + /* Lora MAC channel, 125kHz, all SF, 433.575 MHz */ + "enable": true, + "radio": 1, + "if": 0 + }, + "chan_multiSF_3": { + /* Lora MAC channel, 125kHz, all SF, 433.975 MHz */ + "enable": true, + "radio": 0, + "if": -400000 + }, + "chan_multiSF_4": { + /* Lora MAC channel, 125kHz, all SF, 434.175 MHz */ + "enable": true, + "radio": 0, + "if": -200000 + }, + "chan_multiSF_5": { + /* Lora MAC channel, 125kHz, all SF, 434.375 MHz */ + "enable": true, + "radio": 0, + "if": 0 + }, + "chan_multiSF_6": { + /* Lora MAC channel, 125kHz, all SF, 434.575 MHz */ + "enable": true, + "radio": 0, + "if": 200000 + }, + "chan_multiSF_7": { + /* Lora MAC channel, 125kHz, all SF, 434.775 MHz */ + "enable": true, + "radio": 0, + "if": 400000 + }, + "chan_Lora_std": { + /* Lora MAC channel, 250kHz, SF7, 434.175 MHz */ + "enable": true, + "radio": 1, + "if": -200000, + "bandwidth": 250000, + "spread_factor": 7 + }, + "chan_FSK": { + /* FSK 50kbps channel, 434.675 MHz */ + "enable": true, + "radio": 1, + "if": 300000, + "bandwidth": 125000, + "datarate": 50000 + }, + "tx_lut_0": { + /* TX gain table, index 0 */ + "pa_gain": 0, + "mix_gain": 8, + "rf_power": -6, + "dig_gain": 0 + }, + "tx_lut_1": { + /* TX gain table, index 1 */ + "pa_gain": 0, + "mix_gain": 10, + "rf_power": -3, + "dig_gain": 0 + }, + "tx_lut_2": { + /* TX gain table, index 2 */ + "pa_gain": 0, + "mix_gain": 12, + "rf_power": 0, + "dig_gain": 0 + }, + "tx_lut_3": { + /* TX gain table, index 3 */ + "pa_gain": 1, + "mix_gain": 8, + "rf_power": 3, + "dig_gain": 0 + }, + "tx_lut_4": { + /* TX gain table, index 4 */ + "pa_gain": 1, + "mix_gain": 10, + "rf_power": 6, + "dig_gain": 0 + }, + "tx_lut_5": { + /* TX gain table, index 5 */ + "pa_gain": 1, + "mix_gain": 12, + "rf_power": 10, + "dig_gain": 0 + }, + "tx_lut_6": { + /* TX gain table, index 6 */ + "pa_gain": 1, + "mix_gain": 13, + "rf_power": 11, + "dig_gain": 0 + }, + "tx_lut_7": { + /* TX gain table, index 7 */ + "pa_gain": 2, + "mix_gain": 9, + "rf_power": 12, + "dig_gain": 0 + }, + "tx_lut_8": { + /* TX gain table, index 8 */ + "pa_gain": 1, + "mix_gain": 15, + "rf_power": 13, + "dig_gain": 0 + }, + "tx_lut_9": { + /* TX gain table, index 9 */ + "pa_gain": 2, + "mix_gain": 10, + "rf_power": 14, + "dig_gain": 0 + }, + "tx_lut_10": { + /* TX gain table, index 10 */ + "pa_gain": 2, + "mix_gain": 11, + "rf_power": 16, + "dig_gain": 0 + }, + "tx_lut_11": { + /* TX gain table, index 11 */ + "pa_gain": 3, + "mix_gain": 9, + "rf_power": 20, + "dig_gain": 0 + }, + "tx_lut_12": { + "desc": "TX gain table, index 12", + "pa_gain": 3, + "mix_gain": 10, + "rf_power": 23, + "dig_gain": 0 + }, + "tx_lut_13": { + "desc": "TX gain table, index 13", + "pa_gain": 3, + "mix_gain": 11, + "rf_power": 25, + "dig_gain": 0 + }, + "tx_lut_14": { + "desc": "TX gain table, index 14", + "pa_gain": 3, + "mix_gain": 12, + "rf_power": 26, + "dig_gain": 0 + }, + "tx_lut_15": { + "desc": "TX gain table, index 15", + "pa_gain": 3, + "mix_gain": 14, + "rf_power": 27, + "dig_gain": 0 + } + }, + "gateway_conf": { + "gateway_ID": "0000000000000000", + /* change with default server address/ports, or overwrite in local_conf.json */ + "server_address": "router.eu.thethings.network", + "serv_port_up": 1700, + "serv_port_down": 1700, + /* adjust the following parameters for your network */ + "keepalive_interval": 10, + "stat_interval": 30, + "push_timeout_ms": 100, + /* forward only valid packets */ + "forward_crc_valid": true, + "forward_crc_error": false, + "forward_crc_disabled": false, + /* gps enable */ + "gps": true, + "gps_tty_path": "/dev/i2c-1", + "fake_gps": false, + "ref_latitude": 10, + "ref_longitude": 20, + "ref_altitude": -1, + "autoquit_threshold": 6 + } +} + diff --git a/lora/rak7243/global_conf/global_conf.eu_863_870.json b/lora/rak7243/global_conf/global_conf.eu_863_870.json new file mode 100644 index 0000000..1914d44 --- /dev/null +++ b/lora/rak7243/global_conf/global_conf.eu_863_870.json @@ -0,0 +1,200 @@ +{ + "SX1301_conf": { + "lorawan_public": true, + "clksrc": 1, + "antenna_gain": 0, + "radio_0": { + "enable": true, + "type": "SX1257", + "freq": 867500000, + "rssi_offset": -166.0, + "tx_enable": true, + "tx_freq_min": 863000000, + "tx_freq_max": 870000000 + }, + "radio_1": { + "enable": true, + "type": "SX1257", + "freq": 868500000, + "rssi_offset": -166.0, + "tx_enable": false + }, + "chan_multiSF_0": { + "enable": true, + "radio": 1, + "if": -400000 + }, + "chan_multiSF_1": { + "enable": true, + "radio": 1, + "if": -200000 + }, + "chan_multiSF_2": { + "enable": true, + "radio": 1, + "if": 0 + }, + "chan_multiSF_3": { + "enable": true, + "radio": 0, + "if": -400000 + }, + "chan_multiSF_4": { + "enable": true, + "radio": 0, + "if": -200000 + }, + "chan_multiSF_5": { + "enable": true, + "radio": 0, + "if": 0 + }, + "chan_multiSF_6": { + "enable": true, + "radio": 0, + "if": 200000 + }, + "chan_multiSF_7": { + "enable": true, + "radio": 0, + "if": 400000 + }, + "chan_Lora_std": { + "enable": true, + "radio": 1, + "if": -200000, + "bandwidth": 250000, + "spread_factor": 7 + }, + "chan_FSK": { + "enable": true, + "radio": 1, + "if": 300000, + "bandwidth": 125000, + "datarate": 50000 + }, + "tx_lut_0": { + "pa_gain": 0, + "mix_gain": 8, + "rf_power": -6, + "dig_gain": 0 + }, + "tx_lut_1": { + "pa_gain": 0, + "mix_gain": 10, + "rf_power": -3, + "dig_gain": 0 + }, + "tx_lut_2": { + "pa_gain": 0, + "mix_gain": 12, + "rf_power": 0, + "dig_gain": 0 + }, + "tx_lut_3": { + "pa_gain": 1, + "mix_gain": 8, + "rf_power": 3, + "dig_gain": 0 + }, + "tx_lut_4": { + "pa_gain": 1, + "mix_gain": 10, + "rf_power": 6, + "dig_gain": 0 + }, + "tx_lut_5": { + "pa_gain": 1, + "mix_gain": 12, + "rf_power": 10, + "dig_gain": 0 + }, + "tx_lut_6": { + "pa_gain": 1, + "mix_gain": 13, + "rf_power": 11, + "dig_gain": 0 + }, + "tx_lut_7": { + "pa_gain": 2, + "mix_gain": 9, + "rf_power": 12, + "dig_gain": 0 + }, + "tx_lut_8": { + "pa_gain": 1, + "mix_gain": 15, + "rf_power": 13, + "dig_gain": 0 + }, + "tx_lut_9": { + "pa_gain": 2, + "mix_gain": 10, + "rf_power": 14, + "dig_gain": 0 + }, + "tx_lut_10": { + "pa_gain": 2, + "mix_gain": 11, + "rf_power": 16, + "dig_gain": 0 + }, + "tx_lut_11": { + "pa_gain": 3, + "mix_gain": 9, + "rf_power": 20, + "dig_gain": 0 + }, + "tx_lut_12": { + "desc": "TX gain table, index 12", + "pa_gain": 3, + "mix_gain": 10, + "rf_power": 23, + "dig_gain": 0 + }, + "tx_lut_13": { + "desc": "TX gain table, index 13", + "pa_gain": 3, + "mix_gain": 11, + "rf_power": 25, + "dig_gain": 0 + }, + "tx_lut_14": { + "desc": "TX gain table, index 14", + "pa_gain": 3, + "mix_gain": 12, + "rf_power": 26, + "dig_gain": 0 + }, + "tx_lut_15": { + "desc": "TX gain table, index 15", + "pa_gain": 3, + "mix_gain": 14, + "rf_power": 27, + "dig_gain": 0 + } + }, + "gateway_conf": { + "gateway_ID": "0000000000000000", + /* change with default server address/ports, or overwrite in local_conf.json */ + "server_address": "router.eu.thethings.network", + "serv_port_up": 1700, + "serv_port_down": 1700, + /* adjust the following parameters for your network */ + "keepalive_interval": 10, + "stat_interval": 30, + "push_timeout_ms": 100, + /* forward only valid packets */ + "forward_crc_valid": true, + "forward_crc_error": false, + "forward_crc_disabled": false, + /* gps enable */ + "gps": true, + "gps_tty_path": "/dev/i2c-1", + "fake_gps": false, + "ref_latitude": 10, + "ref_longitude": 20, + "ref_altitude": -1, + "autoquit_threshold": 6 + } +} diff --git a/lora/rak7243/global_conf/global_conf.in_865_867.json b/lora/rak7243/global_conf/global_conf.in_865_867.json new file mode 100644 index 0000000..107afec --- /dev/null +++ b/lora/rak7243/global_conf/global_conf.in_865_867.json @@ -0,0 +1,209 @@ +{ + "SX1301_conf": { + "lorawan_public": true, + "clksrc": 1, + "clksrc_desc": "radio_1 provides clock to concentrator for most devices except MultiTech. For MultiTech set to 0.", + "antenna_gain": 0, + "antenna_gain_desc": "antenna gain, in dBi", + "radio_0": { + "enable": true, + "type": "SX1257", + "freq": 865200000, + "rssi_offset": -166.0, + "tx_enable": true, + "tx_freq_min": 865000000, + "tx_freq_max": 867000000, + "tx_notch_freq": 129000 + }, + "radio_1": { + "enable": true, + "type": "SX1257", + "freq": 866385000, + "rssi_offset": -166.0, + "tx_enable": false + }, + "chan_multiSF_0": { + "desc": "Lora MAC, 125kHz, all SF, 865.0625 MHz", + "enable": true, + "radio": 0, + "if": -137500 + }, + "chan_multiSF_1": { + "desc": "Lora MAC, 125kHz, all SF, 865.4025 MHz", + "enable": true, + "radio": 0, + "if": 202500 + }, + "chan_multiSF_2": { + "desc": "Lora MAC, 125kHz, all SF, 865.9850 MHz", + "enable": true, + "radio": 1, + "if": -400000 + }, + "chan_multiSF_3": { + "desc": "disabled", + "enable": false + }, + "chan_multiSF_4": { + "desc": "disabled", + "enable": false + }, + "chan_multiSF_5": { + "desc": "disabled", + "enable": false + }, + "chan_multiSF_6": { + "desc": "disabled", + "enable": false + }, + "chan_multiSF_7": { + "desc": "disabled", + "enable": false + }, + "chan_Lora_std": { + "desc": "disabled", + "enable": false + }, + "chan_FSK": { + "desc": "disabled", + "enable": false + }, + "tx_lut_0": { + "desc": "TX gain table, index 0", + "pa_gain": 0, + "mix_gain": 8, + "rf_power": -6, + "dig_gain": 0 + }, + "tx_lut_1": { + "desc": "TX gain table, index 1", + "pa_gain": 0, + "mix_gain": 10, + "rf_power": -3, + "dig_gain": 0 + }, + "tx_lut_2": { + "desc": "TX gain table, index 2", + "pa_gain": 0, + "mix_gain": 12, + "rf_power": 0, + "dig_gain": 0 + }, + "tx_lut_3": { + "desc": "TX gain table, index 3", + "pa_gain": 1, + "mix_gain": 8, + "rf_power": 3, + "dig_gain": 0 + }, + "tx_lut_4": { + "desc": "TX gain table, index 4", + "pa_gain": 1, + "mix_gain": 10, + "rf_power": 6, + "dig_gain": 0 + }, + "tx_lut_5": { + "desc": "TX gain table, index 5", + "pa_gain": 1, + "mix_gain": 12, + "rf_power": 10, + "dig_gain": 0 + }, + "tx_lut_6": { + "desc": "TX gain table, index 6", + "pa_gain": 1, + "mix_gain": 13, + "rf_power": 11, + "dig_gain": 0 + }, + "tx_lut_7": { + "desc": "TX gain table, index 7", + "pa_gain": 2, + "mix_gain": 9, + "rf_power": 12, + "dig_gain": 0 + }, + "tx_lut_8": { + "desc": "TX gain table, index 8", + "pa_gain": 1, + "mix_gain": 15, + "rf_power": 13, + "dig_gain": 0 + }, + "tx_lut_9": { + "desc": "TX gain table, index 9", + "pa_gain": 2, + "mix_gain": 10, + "rf_power": 14, + "dig_gain": 0 + }, + "tx_lut_10": { + "desc": "TX gain table, index 10", + "pa_gain": 2, + "mix_gain": 11, + "rf_power": 16, + "dig_gain": 0 + }, + "tx_lut_11": { + "desc": "TX gain table, index 11", + "pa_gain": 3, + "mix_gain": 9, + "rf_power": 20, + "dig_gain": 0 + }, + "tx_lut_12": { + "desc": "TX gain table, index 12", + "pa_gain": 3, + "mix_gain": 10, + "rf_power": 23, + "dig_gain": 0 + }, + "tx_lut_13": { + "desc": "TX gain table, index 13", + "pa_gain": 3, + "mix_gain": 11, + "rf_power": 25, + "dig_gain": 0 + }, + "tx_lut_14": { + "desc": "TX gain table, index 14", + "pa_gain": 3, + "mix_gain": 12, + "rf_power": 26, + "dig_gain": 0 + }, + "tx_lut_15": { + "desc": "TX gain table, index 15", + "pa_gain": 3, + "mix_gain": 14, + "rf_power": 27, + "dig_gain": 0 + } + }, + "gateway_conf": { + "gateway_ID": "0000000000000000", + /* change with default server address/ports, or overwrite in local_conf.json */ + "server_address": "router.as.thethings.network", + "serv_port_up": 1700, + "serv_port_down": 1700, + /* adjust the following parameters for your network */ + "keepalive_interval": 10, + "stat_interval": 30, + "push_timeout_ms": 100, + /* forward only valid packets */ + "forward_crc_valid": true, + "forward_crc_error": false, + "forward_crc_disabled": false, + /* gps enable */ + "gps": true, + "gps_tty_path": "/dev/i2c-1", + "fake_gps": false, + "ref_latitude": 10, + "ref_longitude": 20, + "ref_altitude": -1, + "autoquit_threshold": 6 + } + +} + diff --git a/lora/rak7243/global_conf/global_conf.kr_920_923.json b/lora/rak7243/global_conf/global_conf.kr_920_923.json new file mode 100644 index 0000000..0beae57 --- /dev/null +++ b/lora/rak7243/global_conf/global_conf.kr_920_923.json @@ -0,0 +1,217 @@ +{ + "SX1301_conf": { + "lorawan_public": true, + "clksrc": 1, + "clksrc_desc": "radio_1 provides clock to concentrator for most devices except MultiTech. For MultiTech set to 0.", + "antenna_gain": 0, + "antenna_gain_desc": "antenna gain, in dBi", + "radio_0": { + "enable": true, + "type": "SX1257", + "freq": 922400000, + "rssi_offset": -166.0, + "tx_enable": true, + "tx_freq_min": 920900000, + "tx_freq_max": 923300000 + }, + "radio_1": { + "enable": true, + "type": "SX1257", + "freq": 923000000, + "rssi_offset": -166.0, + "tx_enable": false + }, + "chan_multiSF_0": { + "desc": "Lora MAC, 125kHz, all SF, 922.1 MHz", + "enable": true, + "radio": 0, + "if": -300000 + }, + "chan_multiSF_1": { + "desc": "Lora MAC, 125kHz, all SF, 922.3 MHz", + "enable": true, + "radio": 0, + "if": -100000 + }, + "chan_multiSF_2": { + "desc": "Lora MAC, 125kHz, all SF, 922.5 MHz", + "enable": true, + "radio": 0, + "if": 100000 + }, + "chan_multiSF_3": { + "desc": "Lora MAC, 125kHz, all SF, 922.7 MHz", + "enable": true, + "radio": 0, + "if": 300000 + }, + "chan_multiSF_4": { + "desc": "Lora MAC, 125kHz, all SF, 922.9 MHz", + "enable": true, + "radio": 1, + "if": -100000 + }, + "chan_multiSF_5": { + "desc": "Lora MAC, 125kHz, all SF, 923.1 MHz", + "enable": true, + "radio": 1, + "if": 100000 + }, + "chan_multiSF_6": { + "desc": "Lora MAC, 125kHz, all SF, 923.3 MHz", + "enable": true, + "radio": 1, + "if": 300000 + }, + "chan_multiSF_7": { + "desc": "disabled", + "enable": false + }, + "chan_Lora_std": { + "desc": "disabled", + "enable": false + }, + "chan_FSK": { + "desc": "disabled", + "enable": false + }, + "tx_lut_0": { + "desc": "TX gain table, index 0", + "pa_gain": 0, + "mix_gain": 8, + "rf_power": -6, + "dig_gain": 0 + }, + "tx_lut_1": { + "desc": "TX gain table, index 1", + "pa_gain": 0, + "mix_gain": 10, + "rf_power": -3, + "dig_gain": 0 + }, + "tx_lut_2": { + "desc": "TX gain table, index 2", + "pa_gain": 0, + "mix_gain": 12, + "rf_power": 0, + "dig_gain": 0 + }, + "tx_lut_3": { + "desc": "TX gain table, index 3", + "pa_gain": 1, + "mix_gain": 8, + "rf_power": 3, + "dig_gain": 0 + }, + "tx_lut_4": { + "desc": "TX gain table, index 4", + "pa_gain": 1, + "mix_gain": 10, + "rf_power": 6, + "dig_gain": 0 + }, + "tx_lut_5": { + "desc": "TX gain table, index 5", + "pa_gain": 1, + "mix_gain": 12, + "rf_power": 10, + "dig_gain": 0 + }, + "tx_lut_6": { + "desc": "TX gain table, index 6", + "pa_gain": 1, + "mix_gain": 13, + "rf_power": 11, + "dig_gain": 0 + }, + "tx_lut_7": { + "desc": "TX gain table, index 7", + "pa_gain": 2, + "mix_gain": 9, + "rf_power": 12, + "dig_gain": 0 + }, + "tx_lut_8": { + "desc": "TX gain table, index 8", + "pa_gain": 1, + "mix_gain": 15, + "rf_power": 13, + "dig_gain": 0 + }, + "tx_lut_9": { + "desc": "TX gain table, index 9", + "pa_gain": 2, + "mix_gain": 10, + "rf_power": 14, + "dig_gain": 0 + }, + "tx_lut_10": { + "desc": "TX gain table, index 10", + "pa_gain": 2, + "mix_gain": 11, + "rf_power": 16, + "dig_gain": 0 + }, + "tx_lut_11": { + "desc": "TX gain table, index 11", + "pa_gain": 3, + "mix_gain": 9, + "rf_power": 20, + "dig_gain": 0 + }, + "tx_lut_12": { + "desc": "TX gain table, index 12", + "pa_gain": 3, + "mix_gain": 10, + "rf_power": 23, + "dig_gain": 0 + }, + "tx_lut_13": { + "desc": "TX gain table, index 13", + "pa_gain": 3, + "mix_gain": 11, + "rf_power": 25, + "dig_gain": 0 + }, + "tx_lut_14": { + "desc": "TX gain table, index 14", + "pa_gain": 3, + "mix_gain": 12, + "rf_power": 26, + "dig_gain": 0 + }, + "tx_lut_15": { + "desc": "TX gain table, index 15", + "pa_gain": 3, + "mix_gain": 14, + "rf_power": 27, + "dig_gain": 0 + } + }, + "gateway_conf": { + "gateway_ID": "0000000000000000", + /* change with default server address/ports, or overwrite in local_conf.json */ + "server_address": "router.kr.thethings.network", + "serv_port_up": 1700, + "serv_port_down": 1700, + /* adjust the following parameters for your network */ + "keepalive_interval": 10, + "stat_interval": 30, + "push_timeout_ms": 100, + /* forward only valid packets */ + "forward_crc_valid": true, + "forward_crc_error": false, + "forward_crc_disabled": false, + /* gps enable */ + "gps": true, + "gps_tty_path": "/dev/i2c-1", + "fake_gps": false, + "ref_latitude": 10, + "ref_longitude": 20, + "ref_altitude": -1, + "autoquit_threshold": 6 + } + +} + + diff --git a/lora/rak7243/global_conf/global_conf.ru_864_870.json b/lora/rak7243/global_conf/global_conf.ru_864_870.json new file mode 100644 index 0000000..7f5a957 --- /dev/null +++ b/lora/rak7243/global_conf/global_conf.ru_864_870.json @@ -0,0 +1,216 @@ +{ + "SX1301_conf": { + "lorawan_public": true, + "clksrc": 1, + "clksrc_desc": "radio_1 provides clock to concentrator for most devices except MultiTech. For MultiTech set to 0.", + "antenna_gain": 0, + "antenna_gain_desc": "antenna gain, in dBi", + "radio_0": { + "enable": true, + "type": "SX1257", + "freq": 864500000, + "rssi_offset": -166.0, + "tx_enable": true, + "tx_freq_min": 863000000, + "tx_freq_max": 870000000 + }, + "radio_1": { + "enable": true, + "type": "SX1257", + "freq": 869000000, + "rssi_offset": -166.0, + "tx_enable": false + }, + "chan_multiSF_0": { + "desc": "Lora MAC, 125kHz, all SF, 864.1 MHz", + "enable": true, + "radio": 0, + "if": -400000 + }, + "chan_multiSF_1": { + "desc": "Lora MAC, 125kHz, all SF, 864.3 MHz", + "enable": true, + "radio": 0, + "if": -200000 + }, + "chan_multiSF_2": { + "desc": "Lora MAC, 125kHz, all SF, 864.5 MHz", + "enable": true, + "radio": 0, + "if": 0 + }, + "chan_multiSF_3": { + "desc": "Lora MAC, 125kHz, all SF, 864.7 MHz", + "enable": true, + "radio": 0, + "if": 200000 + }, + "chan_multiSF_4": { + "desc": "Lora MAC, 125kHz, all SF, 864.9 MHz", + "enable": true, + "radio": 0, + "if": 400000 + }, + "chan_multiSF_5": { + "desc": "Lora MAC, 125kHz, all SF, 868.9 MHz", + "enable": true, + "radio": 1, + "if": -100000 + }, + "chan_multiSF_6": { + "desc": "Lora MAC, 125kHz, all SF, 869.1 MHz", + "enable": true, + "radio": 1, + "if": 100000 + }, + "chan_multiSF_7": { + "desc": "disabled", + "enable": false + }, + "chan_Lora_std": { + "desc": "disabled", + "enable": false + }, + "chan_FSK": { + "desc": "disabled", + "enable": false + }, + "tx_lut_0": { + "desc": "TX gain table, index 0", + "pa_gain": 0, + "mix_gain": 8, + "rf_power": -6, + "dig_gain": 0 + }, + "tx_lut_1": { + "desc": "TX gain table, index 1", + "pa_gain": 0, + "mix_gain": 10, + "rf_power": -3, + "dig_gain": 0 + }, + "tx_lut_2": { + "desc": "TX gain table, index 2", + "pa_gain": 0, + "mix_gain": 12, + "rf_power": 0, + "dig_gain": 0 + }, + "tx_lut_3": { + "desc": "TX gain table, index 3", + "pa_gain": 1, + "mix_gain": 8, + "rf_power": 3, + "dig_gain": 0 + }, + "tx_lut_4": { + "desc": "TX gain table, index 4", + "pa_gain": 1, + "mix_gain": 10, + "rf_power": 6, + "dig_gain": 0 + }, + "tx_lut_5": { + "desc": "TX gain table, index 5", + "pa_gain": 1, + "mix_gain": 12, + "rf_power": 10, + "dig_gain": 0 + }, + "tx_lut_6": { + "desc": "TX gain table, index 6", + "pa_gain": 1, + "mix_gain": 13, + "rf_power": 11, + "dig_gain": 0 + }, + "tx_lut_7": { + "desc": "TX gain table, index 7", + "pa_gain": 2, + "mix_gain": 9, + "rf_power": 12, + "dig_gain": 0 + }, + "tx_lut_8": { + "desc": "TX gain table, index 8", + "pa_gain": 1, + "mix_gain": 15, + "rf_power": 13, + "dig_gain": 0 + }, + "tx_lut_9": { + "desc": "TX gain table, index 9", + "pa_gain": 2, + "mix_gain": 10, + "rf_power": 14, + "dig_gain": 0 + }, + "tx_lut_10": { + "desc": "TX gain table, index 10", + "pa_gain": 2, + "mix_gain": 11, + "rf_power": 16, + "dig_gain": 0 + }, + "tx_lut_11": { + "desc": "TX gain table, index 11", + "pa_gain": 3, + "mix_gain": 9, + "rf_power": 20, + "dig_gain": 0 + }, + "tx_lut_12": { + "desc": "TX gain table, index 12", + "pa_gain": 3, + "mix_gain": 10, + "rf_power": 23, + "dig_gain": 0 + }, + "tx_lut_13": { + "desc": "TX gain table, index 13", + "pa_gain": 3, + "mix_gain": 11, + "rf_power": 25, + "dig_gain": 0 + }, + "tx_lut_14": { + "desc": "TX gain table, index 14", + "pa_gain": 3, + "mix_gain": 12, + "rf_power": 26, + "dig_gain": 0 + }, + "tx_lut_15": { + "desc": "TX gain table, index 15", + "pa_gain": 3, + "mix_gain": 14, + "rf_power": 27, + "dig_gain": 0 + } + }, + "gateway_conf": { + "gateway_ID": "0000000000000000", + /* change with default server address/ports, or overwrite in local_conf.json */ + "server_address": "router.ru.thethings.network", + "serv_port_up": 1700, + "serv_port_down": 1700, + /* adjust the following parameters for your network */ + "keepalive_interval": 10, + "stat_interval": 30, + "push_timeout_ms": 100, + /* forward only valid packets */ + "forward_crc_valid": true, + "forward_crc_error": false, + "forward_crc_disabled": false, + /* gps enable */ + "gps": true, + "gps_tty_path": "/dev/i2c-1", + "fake_gps": false, + "ref_latitude": 10, + "ref_longitude": 20, + "ref_altitude": -1, + "autoquit_threshold": 6 + } + +} + diff --git a/lora/rak7243/global_conf/global_conf.us_902_928.json b/lora/rak7243/global_conf/global_conf.us_902_928.json new file mode 100644 index 0000000..9e85858 --- /dev/null +++ b/lora/rak7243/global_conf/global_conf.us_902_928.json @@ -0,0 +1,212 @@ +{ + "SX1301_conf": { + "lorawan_public": true, + "clksrc": 1, + "antenna_gain": 0, + "radio_0": { + "enable": true, + "type": "SX1257", + "freq": 904300000, + "rssi_offset": -166.0, + "tx_enable": true, + "tx_freq_min": 902000000, + "tx_freq_max": 928000000 + }, + "radio_1": { + "enable": true, + "type": "SX1257", + "freq": 905000000, + "rssi_offset": -166.0, + "tx_enable": false + }, + "chan_multiSF_0": { + "enable": true, + "radio": 0, + "if": -400000 + }, + "chan_multiSF_1": { + "enable": true, + "radio": 0, + "if": -200000 + }, + "chan_multiSF_2": { + "enable": true, + "radio": 0, + "if": 0 + }, + "chan_multiSF_3": { + "enable": true, + "radio": 0, + "if": 200000 + }, + "chan_multiSF_4": { + "enable": true, + "radio": 1, + "if": -300000 + }, + "chan_multiSF_5": { + "enable": true, + "radio": 1, + "if": -100000 + }, + "chan_multiSF_6": { + "enable": true, + "radio": 1, + "if": 100000 + }, + "chan_multiSF_7": { + "enable": true, + "radio": 1, + "if": 300000 + }, + "chan_Lora_std": { + "enable": true, + "radio": 0, + "if": 300000, + "bandwidth": 500000, + "spread_factor": 8 + }, + "chan_FSK": { + "enable": false, + "radio": 0, + "if": 300000, + "bandwidth": 250000, + "datarate": 100000 + }, + "tx_lut_0": { + "desc": "TX gain table, index 0", + "pa_gain": 0, + "mix_gain": 8, + "rf_power": -6, + "dig_gain": 0 + }, + "tx_lut_1": { + "desc": "TX gain table, index 1", + "pa_gain": 0, + "mix_gain": 10, + "rf_power": -3, + "dig_gain": 0 + }, + "tx_lut_2": { + "desc": "TX gain table, index 2", + "pa_gain": 0, + "mix_gain": 12, + "rf_power": 0, + "dig_gain": 0 + }, + "tx_lut_3": { + "desc": "TX gain table, index 3", + "pa_gain": 1, + "mix_gain": 8, + "rf_power": 3, + "dig_gain": 0 + }, + "tx_lut_4": { + "desc": "TX gain table, index 4", + "pa_gain": 1, + "mix_gain": 10, + "rf_power": 6, + "dig_gain": 0 + }, + "tx_lut_5": { + "desc": "TX gain table, index 5", + "pa_gain": 1, + "mix_gain": 12, + "rf_power": 10, + "dig_gain": 0 + }, + "tx_lut_6": { + "desc": "TX gain table, index 6", + "pa_gain": 1, + "mix_gain": 13, + "rf_power": 11, + "dig_gain": 0 + }, + "tx_lut_7": { + "desc": "TX gain table, index 7", + "pa_gain": 2, + "mix_gain": 9, + "rf_power": 12, + "dig_gain": 0 + }, + "tx_lut_8": { + "desc": "TX gain table, index 8", + "pa_gain": 1, + "mix_gain": 15, + "rf_power": 13, + "dig_gain": 0 + }, + "tx_lut_9": { + "desc": "TX gain table, index 9", + "pa_gain": 2, + "mix_gain": 10, + "rf_power": 14, + "dig_gain": 0 + }, + "tx_lut_10": { + "desc": "TX gain table, index 10", + "pa_gain": 2, + "mix_gain": 11, + "rf_power": 16, + "dig_gain": 0 + }, + "tx_lut_11": { + "desc": "TX gain table, index 11", + "pa_gain": 3, + "mix_gain": 9, + "rf_power": 20, + "dig_gain": 0 + }, + "tx_lut_12": { + "desc": "TX gain table, index 12", + "pa_gain": 3, + "mix_gain": 10, + "rf_power": 23, + "dig_gain": 0 + }, + "tx_lut_13": { + "desc": "TX gain table, index 13", + "pa_gain": 3, + "mix_gain": 11, + "rf_power": 25, + "dig_gain": 0 + }, + "tx_lut_14": { + "desc": "TX gain table, index 14", + "pa_gain": 3, + "mix_gain": 12, + "rf_power": 26, + "dig_gain": 0 + }, + "tx_lut_15": { + "desc": "TX gain table, index 15", + "pa_gain": 3, + "mix_gain": 14, + "rf_power": 27, + "dig_gain": 0 + } + }, + "gateway_conf": { + "gateway_ID": "0000000000000000", + /* change with default server address/ports, or overwrite in local_conf.json */ + "server_address": "router.us.thethings.network", + "serv_port_up": 1700, + "serv_port_down": 1700, + /* adjust the following parameters for your network */ + "keepalive_interval": 10, + "stat_interval": 30, + "push_timeout_ms": 100, + /* forward only valid packets */ + "forward_crc_valid": true, + "forward_crc_error": false, + "forward_crc_disabled": false, + /* gps enable */ + "gps": true, + "gps_tty_path": "/dev/i2c-1", + "fake_gps": false, + "ref_latitude": 10, + "ref_longitude": 20, + "ref_altitude": -1, + "autoquit_threshold": 6 + } +} diff --git a/lora/rak7243/install.sh b/lora/rak7243/install.sh new file mode 100755 index 0000000..b1f9e8a --- /dev/null +++ b/lora/rak7243/install.sh @@ -0,0 +1,98 @@ +#!/bin/bash + +# Stop on the first sign of trouble +set -e + +if [ $UID != 0 ]; then + echo "ERROR: Operation not permitted. Forgot sudo?" + exit 1 +fi + +SCRIPT_DIR=$(pwd) + +# Request gateway configuration data +# There are two ways to do it, manually specify everything +# or rely on the gateway EUI and retrieve settings files from remote (recommended) +echo "Gateway configuration:" + +# Try to get gateway ID from MAC address +# First try eth0, if that does not exist, try wlan0 (for RPi Zero) +GATEWAY_EUI_NIC="eth0" +if [[ `grep "$GATEWAY_EUI_NIC" /proc/net/dev` == "" ]]; then + GATEWAY_EUI_NIC="wlan0" +fi + +if [[ `grep "$GATEWAY_EUI_NIC" /proc/net/dev` == "" ]]; then + echo "ERROR: No network interface found. Cannot set gateway ID." + exit 1 +fi + +if [ ! -d "/usr/local/rak/bin" ]; then mkdir "/usr/local/rak/bin" -p ; fi + +GATEWAY_EUI=$(ip link show $GATEWAY_EUI_NIC | awk '/ether/ {print $2}' | awk -F\: '{print $1$2$3"FFFE"$4$5$6}') +GATEWAY_EUI=${GATEWAY_EUI^^} # toupper + +echo "Detected EUI $GATEWAY_EUI from $GATEWAY_EUI_NIC" + +if [[ $NEW_HOSTNAME == "" ]]; then NEW_HOSTNAME="rak-gateway"; fi + +if [[ $GATEWAY_LAT == "" ]]; then GATEWAY_LAT=0; fi + +if [[ $GATEWAY_LON == "" ]]; then GATEWAY_LON=0; fi + +if [[ $GATEWAY_ALT == "" ]]; then GATEWAY_ALT=0; fi + + +# Change hostname if needed +CURRENT_HOSTNAME=$(hostname) + +if [[ $NEW_HOSTNAME != $CURRENT_HOSTNAME ]]; then + echo "Updating hostname to '$NEW_HOSTNAME'..." + hostname $NEW_HOSTNAME + echo $NEW_HOSTNAME > /etc/hostname + sed -i "s/$CURRENT_HOSTNAME/$NEW_HOSTNAME/" /etc/hosts +fi + +# Install LoRaWAN packet forwarder repositories +INSTALL_DIR="./" +if [ ! -d "$INSTALL_DIR" ]; then mkdir $INSTALL_DIR; fi +pushd $INSTALL_DIR + +# Build LoRa gateway app + +if [ ! -d lora_gateway ]; then + git clone https://github.com/Lora-net/lora_gateway.git +fi + +pushd lora_gateway + +cp $SCRIPT_DIR/library.cfg ./libloragw/library.cfg +cp $SCRIPT_DIR/loragw_gps.c ./libloragw/src/loragw_gps.c +cp $SCRIPT_DIR/loragw_spi.native.c ./libloragw/src/loragw_spi.native.c +cp $SCRIPT_DIR/test_loragw_gps.c ./libloragw/tst/test_loragw_gps.c +make + +popd + +# Build packet forwarder + +if [ ! -d packet_forwarder ]; then + git clone https://github.com/Lora-net/packet_forwarder.git +fi +pushd packet_forwarder + +cp $SCRIPT_DIR/lora_pkt_fwd.c ./lora_pkt_fwd/src/lora_pkt_fwd.c + +make + +popd + +LOCAL_CONFIG_FILE=$INSTALL_DIR/packet_forwarder/lora_pkt_fwd/local_conf.json +echo -e "{\n\t\"gateway_conf\": {\n\t\t\"gateway_ID\": \"$GATEWAY_EUI\"\n\t}\n}" >$LOCAL_CONFIG_FILE + +echo "Gateway EUI is: $GATEWAY_EUI" +echo "The hostname is: $NEW_HOSTNAME" + +cp global_conf $INSTALL_DIR/packet_forwarder/lora_pkt_fwd/ -rf +cp ppp.sh /usr/local/rak/bin/ + diff --git a/lora/rak7243/library.cfg b/lora/rak7243/library.cfg new file mode 100644 index 0000000..9455ee6 --- /dev/null +++ b/lora/rak7243/library.cfg @@ -0,0 +1,18 @@ +# That file will be included in the Makefile files that have hardware dependencies + +### 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 + +CFG_SPI= native + +PLATFORM= imst_rpi + +#CFG_BAND= au915 + +DEBUG_AUX= 0 +DEBUG_SPI= 0 +DEBUG_REG= 0 +DEBUG_HAL= 0 +DEBUG_LBT= 0 +DEBUG_GPS= 0 diff --git a/lora/rak7243/lora_pkt_fwd.c b/lora/rak7243/lora_pkt_fwd.c new file mode 100644 index 0000000..2671b02 --- /dev/null +++ b/lora/rak7243/lora_pkt_fwd.c @@ -0,0 +1,2893 @@ +/* + / _____) _ | | +( (____ _____ ____ _| |_ _____ ____| |__ + \____ \| ___ | (_ _) ___ |/ ___) _ \ + _____) ) ____| | | || |_| ____( (___| | | | +(______/|_____)_|_|_| \__)_____)\____)_| |_| + (C)2013 Semtech-Cycleo + +Description: + Configure Lora concentrator and forward packets to a server + Use GPS for packet timestamping. + Send a becon at a regular interval without server intervention + +License: Revised BSD License, see LICENSE.TXT file include in the project +Maintainer: Michael Coracin +*/ + + +/* -------------------------------------------------------------------------- */ +/* --- DEPENDANCIES --------------------------------------------------------- */ + +/* fix an issue between POSIX and C99 */ +#if __STDC_VERSION__ >= 199901L + #define _XOPEN_SOURCE 600 +#else + #define _XOPEN_SOURCE 500 +#endif + +#include /* C99 types */ +#include /* bool type */ +#include /* printf, fprintf, snprintf, fopen, fputs */ + +#include /* memset */ +#include /* sigaction */ +#include /* time, clock_gettime, strftime, gmtime */ +#include /* timeval */ +#include /* getopt, access */ +#include /* atoi, exit */ +#include /* error messages */ +#include /* modf */ +#include + +#include /* socket specific definitions */ +#include /* INET constants and stuff */ +#include /* IP address conversion stuff */ +#include /* gai_strerror */ + +#include + +#include "trace.h" +#include "jitqueue.h" +#include "timersync.h" +#include "parson.h" +#include "base64.h" +#include "loragw_hal.h" +#include "loragw_gps.h" +#include "loragw_aux.h" +#include "loragw_reg.h" + +/* -------------------------------------------------------------------------- */ +/* --- PRIVATE MACROS ------------------------------------------------------- */ + +#define ARRAY_SIZE(a) (sizeof(a) / sizeof((a)[0])) +#define STRINGIFY(x) #x +#define STR(x) STRINGIFY(x) + +/* -------------------------------------------------------------------------- */ +/* --- PRIVATE CONSTANTS ---------------------------------------------------- */ + +#ifndef VERSION_STRING + #define VERSION_STRING "undefined" +#endif + +#define DEFAULT_SERVER 127.0.0.1 /* hostname also supported */ +#define DEFAULT_PORT_UP 1780 +#define DEFAULT_PORT_DW 1782 +#define DEFAULT_KEEPALIVE 5 /* default time interval for downstream keep-alive packet */ +#define DEFAULT_STAT 30 /* default time interval for statistics */ +#define PUSH_TIMEOUT_MS 100 +#define PULL_TIMEOUT_MS 200 +#define GPS_REF_MAX_AGE 30 /* maximum admitted delay in seconds of GPS loss before considering latest GPS sync unusable */ +#define FETCH_SLEEP_MS 10 /* nb of ms waited when a fetch return no packets */ +#define BEACON_POLL_MS 50 /* time in ms between polling of beacon TX status */ + +#define PROTOCOL_VERSION 2 /* v1.3 */ + +#define XERR_INIT_AVG 128 /* nb of measurements the XTAL correction is averaged on as initial value */ +#define XERR_FILT_COEF 256 /* coefficient for low-pass XTAL error tracking */ + +#define PKT_PUSH_DATA 0 +#define PKT_PUSH_ACK 1 +#define PKT_PULL_DATA 2 +#define PKT_PULL_RESP 3 +#define PKT_PULL_ACK 4 +#define PKT_TX_ACK 5 + +#define NB_PKT_MAX 8 /* max number of packets per fetch/send cycle */ + +#define MIN_LORA_PREAMB 6 /* minimum Lora preamble length for this application */ +#define STD_LORA_PREAMB 8 +#define MIN_FSK_PREAMB 3 /* minimum FSK preamble length for this application */ +#define STD_FSK_PREAMB 5 + +#define STATUS_SIZE 200 +#define TX_BUFF_SIZE ((540 * NB_PKT_MAX) + 30 + STATUS_SIZE) + +#define UNIX_GPS_EPOCH_OFFSET 315964800 /* Number of seconds ellapsed between 01.Jan.1970 00:00:00 + and 06.Jan.1980 00:00:00 */ + +#define DEFAULT_BEACON_FREQ_HZ 869525000 +#define DEFAULT_BEACON_FREQ_NB 1 +#define DEFAULT_BEACON_FREQ_STEP 0 +#define DEFAULT_BEACON_DATARATE 9 +#define DEFAULT_BEACON_BW_HZ 125000 +#define DEFAULT_BEACON_POWER 14 +#define DEFAULT_BEACON_INFODESC 0 + +/* -------------------------------------------------------------------------- */ +/* --- PRIVATE VARIABLES (GLOBAL) ------------------------------------------- */ + +/* signal handling variables */ +volatile bool exit_sig = false; /* 1 -> application terminates cleanly (shut down hardware, close open files, etc) */ +volatile bool quit_sig = false; /* 1 -> application terminates without shutting down the hardware */ + +/* packets filtering configuration variables */ +static bool fwd_valid_pkt = true; /* packets with PAYLOAD CRC OK are forwarded */ +static bool fwd_error_pkt = false; /* packets with PAYLOAD CRC ERROR are NOT forwarded */ +static bool fwd_nocrc_pkt = false; /* packets with NO PAYLOAD CRC are NOT forwarded */ + +/* 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 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 */ + +/* statistics collection configuration variables */ +static unsigned stat_interval = DEFAULT_STAT; /* time interval (in sec) at which statistics are collected and displayed */ + +/* gateway <-> MAC protocol variables */ +static uint32_t net_mac_h; /* Most Significant Nibble, network order */ +static uint32_t net_mac_l; /* Least Significant Nibble, network order */ + +/* network sockets */ +static int sock_up; /* socket for upstream traffic */ +static int sock_down; /* socket for downstream traffic */ + +/* network protocol variables */ +static struct timeval push_timeout_half = {0, (PUSH_TIMEOUT_MS * 500)}; /* cut in half, critical for throughput */ +static struct timeval pull_timeout = {0, (PULL_TIMEOUT_MS * 1000)}; /* non critical for throughput */ + +/* hardware access control and correction */ +pthread_mutex_t mx_concent = PTHREAD_MUTEX_INITIALIZER; /* control access to the concentrator */ +static pthread_mutex_t mx_xcorr = PTHREAD_MUTEX_INITIALIZER; /* control access to the XTAL correction */ +static bool xtal_correct_ok = false; /* set true when XTAL correction is stable enough */ +static double xtal_correct = 1.0; + +/* GPS configuration and synchronization */ +static char gps_tty_path[64] = "\0"; /* path of the TTY port GPS is connected on */ +static int gps_tty_fd = -1; /* file descriptor of the GPS TTY port */ +static bool gps_enabled = false; /* is GPS enabled on that gateway ? */ + +/* GPS time reference */ +static pthread_mutex_t mx_timeref = PTHREAD_MUTEX_INITIALIZER; /* control access to GPS time reference */ +static bool gps_ref_valid; /* is GPS reference acceptable (ie. not too old) */ +static struct tref time_reference_gps; /* time reference used for GPS <-> timestamp conversion */ + +/* Reference coordinates, for broadcasting (beacon) */ +static struct coord_s reference_coord; + +/* Enable faking the GPS coordinates of the gateway */ +static bool gps_fake_enable; /* enable the feature */ + +/* measurements to establish statistics */ +static pthread_mutex_t mx_meas_up = PTHREAD_MUTEX_INITIALIZER; /* control access to the upstream measurements */ +static uint32_t meas_nb_rx_rcv = 0; /* count packets received */ +static uint32_t meas_nb_rx_ok = 0; /* count packets received with PAYLOAD CRC OK */ +static uint32_t meas_nb_rx_bad = 0; /* count packets received with PAYLOAD CRC ERROR */ +static uint32_t meas_nb_rx_nocrc = 0; /* count packets received with NO PAYLOAD CRC */ +static uint32_t meas_up_pkt_fwd = 0; /* number of radio packet forwarded to the server */ +static uint32_t meas_up_network_byte = 0; /* sum of UDP bytes sent for upstream traffic */ +static uint32_t meas_up_payload_byte = 0; /* sum of radio payload bytes sent for upstream traffic */ +static uint32_t meas_up_dgram_sent = 0; /* number of datagrams sent for upstream traffic */ +static uint32_t meas_up_ack_rcv = 0; /* number of datagrams acknowledged for upstream traffic */ + +static pthread_mutex_t mx_meas_dw = PTHREAD_MUTEX_INITIALIZER; /* control access to the downstream measurements */ +static uint32_t meas_dw_pull_sent = 0; /* number of PULL requests sent for downstream traffic */ +static uint32_t meas_dw_ack_rcv = 0; /* number of PULL requests acknowledged for downstream traffic */ +static uint32_t meas_dw_dgram_rcv = 0; /* count PULL response packets received for downstream traffic */ +static uint32_t meas_dw_network_byte = 0; /* sum of UDP bytes sent for upstream traffic */ +static uint32_t meas_dw_payload_byte = 0; /* sum of radio payload bytes sent for upstream traffic */ +static uint32_t meas_nb_tx_ok = 0; /* count packets emitted successfully */ +static uint32_t meas_nb_tx_fail = 0; /* count packets were TX failed for other reasons */ +static uint32_t meas_nb_tx_requested = 0; /* count TX request from server (downlinks) */ +static uint32_t meas_nb_tx_rejected_collision_packet = 0; /* count packets were TX request were rejected due to collision with another packet already programmed */ +static uint32_t meas_nb_tx_rejected_collision_beacon = 0; /* count packets were TX request were rejected due to collision with a beacon already programmed */ +static uint32_t meas_nb_tx_rejected_too_late = 0; /* count packets were TX request were rejected because it is too late to program it */ +static uint32_t meas_nb_tx_rejected_too_early = 0; /* count packets were TX request were rejected because timestamp is too much in advance */ +static uint32_t meas_nb_beacon_queued = 0; /* count beacon inserted in jit queue */ +static uint32_t meas_nb_beacon_sent = 0; /* count beacon actually sent to concentrator */ +static uint32_t meas_nb_beacon_rejected = 0; /* count beacon rejected for queuing */ + +static pthread_mutex_t mx_meas_gps = PTHREAD_MUTEX_INITIALIZER; /* control access to the GPS statistics */ +static bool gps_coord_valid; /* could we get valid GPS coordinates ? */ +static struct coord_s meas_gps_coord; /* GPS position of the gateway */ +static struct coord_s meas_gps_err; /* GPS position of the gateway */ + +static pthread_mutex_t mx_stat_rep = PTHREAD_MUTEX_INITIALIZER; /* control access to the status report */ +static bool report_ready = false; /* true when there is a new report to send to the server */ +static char status_report[STATUS_SIZE]; /* status report as a JSON object */ + +/* beacon parameters */ +static uint32_t beacon_period = 0; /* set beaconing period, must be a sub-multiple of 86400, the nb of sec in a day */ +static uint32_t beacon_freq_hz = DEFAULT_BEACON_FREQ_HZ; /* set beacon TX frequency, in Hz */ +static uint8_t beacon_freq_nb = DEFAULT_BEACON_FREQ_NB; /* set number of beaconing channels beacon */ +static uint32_t beacon_freq_step = DEFAULT_BEACON_FREQ_STEP; /* set frequency step between beacon channels, in Hz */ +static uint8_t beacon_datarate = DEFAULT_BEACON_DATARATE; /* set beacon datarate (SF) */ +static uint32_t beacon_bw_hz = DEFAULT_BEACON_BW_HZ; /* set beacon bandwidth, in Hz */ +static int8_t beacon_power = DEFAULT_BEACON_POWER; /* set beacon TX power, in dBm */ +static uint8_t beacon_infodesc = DEFAULT_BEACON_INFODESC; /* set beacon information descriptor */ + +/* auto-quit function */ +static uint32_t autoquit_threshold = 0; /* enable auto-quit after a number of non-acknowledged PULL_DATA (0 = disabled)*/ + +/* Just In Time TX scheduling */ +static struct jit_queue_s jit_queue; + +/* Gateway specificities */ +static int8_t antenna_gain = 0; + +/* TX capabilities */ +static struct lgw_tx_gain_lut_s txlut; /* TX gain table */ +static uint32_t tx_freq_min[LGW_RF_CHAIN_NB]; /* lowest frequency supported by TX chain */ +static uint32_t tx_freq_max[LGW_RF_CHAIN_NB]; /* highest frequency supported by TX chain */ + +/* -------------------------------------------------------------------------- */ +/* --- PRIVATE FUNCTIONS DECLARATION ---------------------------------------- */ + +static void sig_handler(int sigio); + +static int parse_SX1301_configuration(const char * conf_file); + +static int parse_gateway_configuration(const char * conf_file); + +static uint16_t crc16(const uint8_t * data, unsigned size); + +static double difftimespec(struct timespec end, struct timespec beginning); + +static void gps_process_sync(void); + +static void gps_process_coords(void); + +/* threads */ +void thread_up(void); +void thread_down(void); +void thread_gps(void); +void thread_valid(void); +void thread_jit(void); +void thread_timersync(void); + +/* -------------------------------------------------------------------------- */ +/* --- PRIVATE FUNCTIONS DEFINITION ----------------------------------------- */ + +static void sig_handler(int sigio) { + if (sigio == SIGQUIT) { + quit_sig = true; + } else if ((sigio == SIGINT) || (sigio == SIGTERM)) { + exit_sig = true; + } + return; +} + +static int parse_SX1301_configuration(const char * conf_file) { + int i; + char param_name[32]; /* used to generate variable parameter names */ + const char *str; /* used to store string value from JSON object */ + const char conf_obj_name[] = "SX1301_conf"; + JSON_Value *root_val = NULL; + JSON_Object *conf_obj = NULL; + JSON_Object *conf_lbt_obj = NULL; + JSON_Object *conf_lbtchan_obj = NULL; + JSON_Value *val = NULL; + JSON_Array *conf_array = NULL; + struct lgw_conf_board_s boardconf; + struct lgw_conf_lbt_s lbtconf; + struct lgw_conf_rxrf_s rfconf; + struct lgw_conf_rxif_s ifconf; + uint32_t sf, bw, fdev; + + /* try to parse JSON */ + root_val = json_parse_file_with_comments(conf_file); + if (root_val == NULL) { + MSG("ERROR: %s is not a valid JSON file\n", conf_file); + exit(EXIT_FAILURE); + } + + /* point to the gateway configuration object */ + conf_obj = json_object_get_object(json_value_get_object(root_val), conf_obj_name); + if (conf_obj == NULL) { + MSG("INFO: %s does not contain a JSON object named %s\n", conf_file, conf_obj_name); + return -1; + } else { + MSG("INFO: %s does contain a JSON object named %s, parsing SX1301 parameters\n", conf_file, conf_obj_name); + } + + /* set board configuration */ + memset(&boardconf, 0, sizeof boardconf); /* initialize configuration structure */ + val = json_object_get_value(conf_obj, "lorawan_public"); /* fetch value (if possible) */ + if (json_value_get_type(val) == JSONBoolean) { + boardconf.lorawan_public = (bool)json_value_get_boolean(val); + } else { + MSG("WARNING: Data type for lorawan_public seems wrong, please check\n"); + boardconf.lorawan_public = false; + } + val = json_object_get_value(conf_obj, "clksrc"); /* fetch value (if possible) */ + if (json_value_get_type(val) == JSONNumber) { + boardconf.clksrc = (uint8_t)json_value_get_number(val); + } else { + MSG("WARNING: Data type for clksrc seems wrong, please check\n"); + boardconf.clksrc = 0; + } + MSG("INFO: lorawan_public %d, clksrc %d\n", boardconf.lorawan_public, boardconf.clksrc); + /* all parameters parsed, submitting configuration to the HAL */ + if (lgw_board_setconf(boardconf) != LGW_HAL_SUCCESS) { + MSG("ERROR: Failed to configure board\n"); + return -1; + } + + /* set LBT configuration */ + memset(&lbtconf, 0, sizeof lbtconf); /* initialize configuration structure */ + conf_lbt_obj = json_object_get_object(conf_obj, "lbt_cfg"); /* fetch value (if possible) */ + if (conf_lbt_obj == NULL) { + MSG("INFO: no configuration for LBT\n"); + } else { + val = json_object_get_value(conf_lbt_obj, "enable"); /* fetch value (if possible) */ + if (json_value_get_type(val) == JSONBoolean) { + lbtconf.enable = (bool)json_value_get_boolean(val); + } else { + MSG("WARNING: Data type for lbt_cfg.enable seems wrong, please check\n"); + lbtconf.enable = false; + } + if (lbtconf.enable == true) { + val = json_object_get_value(conf_lbt_obj, "rssi_target"); /* fetch value (if possible) */ + if (json_value_get_type(val) == JSONNumber) { + lbtconf.rssi_target = (int8_t)json_value_get_number(val); + } else { + MSG("WARNING: Data type for lbt_cfg.rssi_target seems wrong, please check\n"); + lbtconf.rssi_target = 0; + } + val = json_object_get_value(conf_lbt_obj, "sx127x_rssi_offset"); /* fetch value (if possible) */ + if (json_value_get_type(val) == JSONNumber) { + lbtconf.rssi_offset = (int8_t)json_value_get_number(val); + } else { + MSG("WARNING: Data type for lbt_cfg.sx127x_rssi_offset seems wrong, please check\n"); + lbtconf.rssi_offset = 0; + } + /* set LBT channels configuration */ + conf_array = json_object_get_array(conf_lbt_obj, "chan_cfg"); + if (conf_array != NULL) { + lbtconf.nb_channel = json_array_get_count( conf_array ); + MSG("INFO: %u LBT channels configured\n", lbtconf.nb_channel); + } + for (i = 0; i < (int)lbtconf.nb_channel; i++) { + /* Sanity check */ + if (i >= LBT_CHANNEL_FREQ_NB) + { + MSG("ERROR: LBT channel %d not supported, skip it\n", i ); + break; + } + /* Get LBT channel configuration object from array */ + conf_lbtchan_obj = json_array_get_object(conf_array, i); + + /* Channel frequency */ + val = json_object_dotget_value(conf_lbtchan_obj, "freq_hz"); /* fetch value (if possible) */ + if (json_value_get_type(val) == JSONNumber) { + lbtconf.channels[i].freq_hz = (uint32_t)json_value_get_number(val); + } else { + MSG("WARNING: Data type for lbt_cfg.channels[%d].freq_hz seems wrong, please check\n", i); + lbtconf.channels[i].freq_hz = 0; + } + + /* Channel scan time */ + val = json_object_dotget_value(conf_lbtchan_obj, "scan_time_us"); /* fetch value (if possible) */ + if (json_value_get_type(val) == JSONNumber) { + lbtconf.channels[i].scan_time_us = (uint16_t)json_value_get_number(val); + } else { + MSG("WARNING: Data type for lbt_cfg.channels[%d].scan_time_us seems wrong, please check\n", i); + lbtconf.channels[i].scan_time_us = 0; + } + } + + /* all parameters parsed, submitting configuration to the HAL */ + if (lgw_lbt_setconf(lbtconf) != LGW_HAL_SUCCESS) { + MSG("ERROR: Failed to configure LBT\n"); + return -1; + } + } else { + MSG("INFO: LBT is disabled\n"); + } + } + + /* set antenna gain configuration */ + val = json_object_get_value(conf_obj, "antenna_gain"); /* fetch value (if possible) */ + if (val != NULL) { + if (json_value_get_type(val) == JSONNumber) { + antenna_gain = (int8_t)json_value_get_number(val); + } else { + MSG("WARNING: Data type for antenna_gain seems wrong, please check\n"); + antenna_gain = 0; + } + } + MSG("INFO: antenna_gain %d dBi\n", antenna_gain); + + /* set configuration for tx gains */ + memset(&txlut, 0, sizeof txlut); /* initialize configuration structure */ + for (i = 0; i < TX_GAIN_LUT_SIZE_MAX; i++) { + snprintf(param_name, sizeof param_name, "tx_lut_%i", i); /* compose parameter path inside JSON structure */ + val = json_object_get_value(conf_obj, param_name); /* fetch value (if possible) */ + if (json_value_get_type(val) != JSONObject) { + MSG("INFO: no configuration for tx gain lut %i\n", i); + continue; + } + txlut.size++; /* update TX LUT size based on JSON object found in configuration file */ + /* there is an object to configure that TX gain index, let's parse it */ + snprintf(param_name, sizeof param_name, "tx_lut_%i.pa_gain", i); + val = json_object_dotget_value(conf_obj, param_name); + if (json_value_get_type(val) == JSONNumber) { + txlut.lut[i].pa_gain = (uint8_t)json_value_get_number(val); + } else { + MSG("WARNING: Data type for %s[%d] seems wrong, please check\n", param_name, i); + txlut.lut[i].pa_gain = 0; + } + snprintf(param_name, sizeof param_name, "tx_lut_%i.dac_gain", i); + val = json_object_dotget_value(conf_obj, param_name); + if (json_value_get_type(val) == JSONNumber) { + txlut.lut[i].dac_gain = (uint8_t)json_value_get_number(val); + } else { + txlut.lut[i].dac_gain = 3; /* This is the only dac_gain supported for now */ + } + snprintf(param_name, sizeof param_name, "tx_lut_%i.dig_gain", i); + val = json_object_dotget_value(conf_obj, param_name); + if (json_value_get_type(val) == JSONNumber) { + txlut.lut[i].dig_gain = (uint8_t)json_value_get_number(val); + } else { + MSG("WARNING: Data type for %s[%d] seems wrong, please check\n", param_name, i); + txlut.lut[i].dig_gain = 0; + } + snprintf(param_name, sizeof param_name, "tx_lut_%i.mix_gain", i); + val = json_object_dotget_value(conf_obj, param_name); + if (json_value_get_type(val) == JSONNumber) { + txlut.lut[i].mix_gain = (uint8_t)json_value_get_number(val); + } else { + MSG("WARNING: Data type for %s[%d] seems wrong, please check\n", param_name, i); + txlut.lut[i].mix_gain = 0; + } + snprintf(param_name, sizeof param_name, "tx_lut_%i.rf_power", i); + val = json_object_dotget_value(conf_obj, param_name); + if (json_value_get_type(val) == JSONNumber) { + txlut.lut[i].rf_power = (int8_t)json_value_get_number(val); + } else { + MSG("WARNING: Data type for %s[%d] seems wrong, please check\n", param_name, i); + txlut.lut[i].rf_power = 0; + } + } + /* all parameters parsed, submitting configuration to the HAL */ + if (txlut.size > 0) { + MSG("INFO: Configuring TX LUT with %u indexes\n", txlut.size); + if (lgw_txgain_setconf(&txlut) != LGW_HAL_SUCCESS) { + MSG("ERROR: Failed to configure concentrator TX Gain LUT\n"); + return -1; + } + } else { + MSG("WARNING: No TX gain LUT defined\n"); + } + + /* set configuration for RF chains */ + for (i = 0; i < LGW_RF_CHAIN_NB; ++i) { + memset(&rfconf, 0, sizeof rfconf); /* initialize configuration structure */ + snprintf(param_name, sizeof param_name, "radio_%i", i); /* compose parameter path inside JSON structure */ + val = json_object_get_value(conf_obj, param_name); /* fetch value (if possible) */ + if (json_value_get_type(val) != JSONObject) { + MSG("INFO: no configuration for radio %i\n", i); + continue; + } + /* there is an object to configure that radio, let's parse it */ + snprintf(param_name, sizeof param_name, "radio_%i.enable", i); + val = json_object_dotget_value(conf_obj, param_name); + if (json_value_get_type(val) == JSONBoolean) { + rfconf.enable = (bool)json_value_get_boolean(val); + } else { + rfconf.enable = false; + } + if (rfconf.enable == false) { /* radio disabled, nothing else to parse */ + MSG("INFO: radio %i disabled\n", i); + } else { /* radio enabled, will parse the other parameters */ + snprintf(param_name, sizeof param_name, "radio_%i.freq", i); + rfconf.freq_hz = (uint32_t)json_object_dotget_number(conf_obj, param_name); + snprintf(param_name, sizeof param_name, "radio_%i.rssi_offset", i); + rfconf.rssi_offset = (float)json_object_dotget_number(conf_obj, param_name); + snprintf(param_name, sizeof param_name, "radio_%i.type", i); + str = json_object_dotget_string(conf_obj, param_name); + if (!strncmp(str, "SX1255", 6)) { + rfconf.type = LGW_RADIO_TYPE_SX1255; + } else if (!strncmp(str, "SX1257", 6)) { + rfconf.type = LGW_RADIO_TYPE_SX1257; + } else { + MSG("WARNING: invalid radio type: %s (should be SX1255 or SX1257)\n", str); + } + snprintf(param_name, sizeof param_name, "radio_%i.tx_enable", i); + val = json_object_dotget_value(conf_obj, param_name); + if (json_value_get_type(val) == JSONBoolean) { + rfconf.tx_enable = (bool)json_value_get_boolean(val); + if (rfconf.tx_enable == true) { + /* tx is enabled on this rf chain, we need its frequency range */ + snprintf(param_name, sizeof param_name, "radio_%i.tx_freq_min", i); + tx_freq_min[i] = (uint32_t)json_object_dotget_number(conf_obj, param_name); + snprintf(param_name, sizeof param_name, "radio_%i.tx_freq_max", i); + tx_freq_max[i] = (uint32_t)json_object_dotget_number(conf_obj, param_name); + if ((tx_freq_min[i] == 0) || (tx_freq_max[i] == 0)) { + MSG("WARNING: no frequency range specified for TX rf chain %d\n", i); + } + /* ... and the notch filter frequency to be set */ + snprintf(param_name, sizeof param_name, "radio_%i.tx_notch_freq", i); + rfconf.tx_notch_freq = (uint32_t)json_object_dotget_number(conf_obj, param_name); + } + } else { + rfconf.tx_enable = false; + } + MSG("INFO: radio %i enabled (type %s), center frequency %u, RSSI offset %f, tx enabled %d, tx_notch_freq %u\n", i, str, rfconf.freq_hz, rfconf.rssi_offset, rfconf.tx_enable, rfconf.tx_notch_freq); + } + /* all parameters parsed, submitting configuration to the HAL */ + if (lgw_rxrf_setconf(i, rfconf) != LGW_HAL_SUCCESS) { + MSG("ERROR: invalid configuration for radio %i\n", i); + return -1; + } + } + + /* set configuration for Lora multi-SF channels (bandwidth cannot be set) */ + for (i = 0; i < LGW_MULTI_NB; ++i) { + memset(&ifconf, 0, sizeof ifconf); /* initialize configuration structure */ + snprintf(param_name, sizeof param_name, "chan_multiSF_%i", i); /* compose parameter path inside JSON structure */ + val = json_object_get_value(conf_obj, param_name); /* fetch value (if possible) */ + if (json_value_get_type(val) != JSONObject) { + MSG("INFO: no configuration for Lora multi-SF channel %i\n", i); + continue; + } + /* there is an object to configure that Lora multi-SF channel, let's parse it */ + snprintf(param_name, sizeof param_name, "chan_multiSF_%i.enable", i); + val = json_object_dotget_value(conf_obj, param_name); + if (json_value_get_type(val) == JSONBoolean) { + ifconf.enable = (bool)json_value_get_boolean(val); + } else { + ifconf.enable = false; + } + if (ifconf.enable == false) { /* Lora multi-SF channel disabled, nothing else to parse */ + MSG("INFO: Lora multi-SF channel %i disabled\n", i); + } else { /* Lora multi-SF channel enabled, will parse the other parameters */ + snprintf(param_name, sizeof param_name, "chan_multiSF_%i.radio", i); + ifconf.rf_chain = (uint32_t)json_object_dotget_number(conf_obj, param_name); + snprintf(param_name, sizeof param_name, "chan_multiSF_%i.if", i); + ifconf.freq_hz = (int32_t)json_object_dotget_number(conf_obj, param_name); + // TODO: handle individual SF enabling and disabling (spread_factor) + MSG("INFO: Lora multi-SF channel %i> radio %i, IF %i Hz, 125 kHz bw, SF 7 to 12\n", i, ifconf.rf_chain, ifconf.freq_hz); + } + /* all parameters parsed, submitting configuration to the HAL */ + if (lgw_rxif_setconf(i, ifconf) != LGW_HAL_SUCCESS) { + MSG("ERROR: invalid configuration for Lora multi-SF channel %i\n", i); + return -1; + } + } + + /* set configuration for Lora standard channel */ + memset(&ifconf, 0, sizeof ifconf); /* initialize configuration structure */ + val = json_object_get_value(conf_obj, "chan_Lora_std"); /* fetch value (if possible) */ + if (json_value_get_type(val) != JSONObject) { + MSG("INFO: no configuration for Lora standard channel\n"); + } else { + val = json_object_dotget_value(conf_obj, "chan_Lora_std.enable"); + if (json_value_get_type(val) == JSONBoolean) { + ifconf.enable = (bool)json_value_get_boolean(val); + } else { + ifconf.enable = false; + } + if (ifconf.enable == false) { + MSG("INFO: Lora standard channel %i disabled\n", i); + } else { + ifconf.rf_chain = (uint32_t)json_object_dotget_number(conf_obj, "chan_Lora_std.radio"); + ifconf.freq_hz = (int32_t)json_object_dotget_number(conf_obj, "chan_Lora_std.if"); + bw = (uint32_t)json_object_dotget_number(conf_obj, "chan_Lora_std.bandwidth"); + switch(bw) { + case 500000: ifconf.bandwidth = BW_500KHZ; break; + case 250000: ifconf.bandwidth = BW_250KHZ; break; + case 125000: ifconf.bandwidth = BW_125KHZ; break; + default: ifconf.bandwidth = BW_UNDEFINED; + } + sf = (uint32_t)json_object_dotget_number(conf_obj, "chan_Lora_std.spread_factor"); + switch(sf) { + case 7: ifconf.datarate = DR_LORA_SF7; break; + case 8: ifconf.datarate = DR_LORA_SF8; break; + case 9: ifconf.datarate = DR_LORA_SF9; break; + case 10: ifconf.datarate = DR_LORA_SF10; break; + case 11: ifconf.datarate = DR_LORA_SF11; break; + case 12: ifconf.datarate = DR_LORA_SF12; break; + default: ifconf.datarate = DR_UNDEFINED; + } + MSG("INFO: Lora std channel> radio %i, IF %i Hz, %u Hz bw, SF %u\n", ifconf.rf_chain, ifconf.freq_hz, bw, sf); + } + if (lgw_rxif_setconf(8, ifconf) != LGW_HAL_SUCCESS) { + MSG("ERROR: invalid configuration for Lora standard channel\n"); + return -1; + } + } + + /* set configuration for FSK channel */ + memset(&ifconf, 0, sizeof ifconf); /* initialize configuration structure */ + val = json_object_get_value(conf_obj, "chan_FSK"); /* fetch value (if possible) */ + if (json_value_get_type(val) != JSONObject) { + MSG("INFO: no configuration for FSK channel\n"); + } else { + val = json_object_dotget_value(conf_obj, "chan_FSK.enable"); + if (json_value_get_type(val) == JSONBoolean) { + ifconf.enable = (bool)json_value_get_boolean(val); + } else { + ifconf.enable = false; + } + if (ifconf.enable == false) { + MSG("INFO: FSK channel %i disabled\n", i); + } else { + ifconf.rf_chain = (uint32_t)json_object_dotget_number(conf_obj, "chan_FSK.radio"); + ifconf.freq_hz = (int32_t)json_object_dotget_number(conf_obj, "chan_FSK.if"); + bw = (uint32_t)json_object_dotget_number(conf_obj, "chan_FSK.bandwidth"); + fdev = (uint32_t)json_object_dotget_number(conf_obj, "chan_FSK.freq_deviation"); + ifconf.datarate = (uint32_t)json_object_dotget_number(conf_obj, "chan_FSK.datarate"); + + /* if chan_FSK.bandwidth is set, it has priority over chan_FSK.freq_deviation */ + if ((bw == 0) && (fdev != 0)) { + bw = 2 * fdev + ifconf.datarate; + } + if (bw == 0) ifconf.bandwidth = BW_UNDEFINED; + else if (bw <= 7800) ifconf.bandwidth = BW_7K8HZ; + else if (bw <= 15600) ifconf.bandwidth = BW_15K6HZ; + else if (bw <= 31200) ifconf.bandwidth = BW_31K2HZ; + else if (bw <= 62500) ifconf.bandwidth = BW_62K5HZ; + else if (bw <= 125000) ifconf.bandwidth = BW_125KHZ; + else if (bw <= 250000) ifconf.bandwidth = BW_250KHZ; + else if (bw <= 500000) ifconf.bandwidth = BW_500KHZ; + else ifconf.bandwidth = BW_UNDEFINED; + + MSG("INFO: FSK channel> radio %i, IF %i Hz, %u Hz bw, %u bps datarate\n", ifconf.rf_chain, ifconf.freq_hz, bw, ifconf.datarate); + } + if (lgw_rxif_setconf(9, ifconf) != LGW_HAL_SUCCESS) { + MSG("ERROR: invalid configuration for FSK channel\n"); + return -1; + } + } + json_value_free(root_val); + + return 0; +} + +static int parse_gateway_configuration(const char * conf_file) { + const char conf_obj_name[] = "gateway_conf"; + JSON_Value *root_val; + JSON_Object *conf_obj = NULL; + JSON_Value *val = NULL; /* needed to detect the absence of some fields */ + const char *str; /* pointer to sub-strings in the JSON data */ + unsigned long long ull = 0; + + /* try to parse JSON */ + root_val = json_parse_file_with_comments(conf_file); + if (root_val == NULL) { + MSG("ERROR: %s is not a valid JSON file\n", conf_file); + exit(EXIT_FAILURE); + } + + /* point to the gateway configuration object */ + conf_obj = json_object_get_object(json_value_get_object(root_val), conf_obj_name); + if (conf_obj == NULL) { + MSG("INFO: %s does not contain a JSON object named %s\n", conf_file, conf_obj_name); + return -1; + } else { + MSG("INFO: %s does contain a JSON object named %s, parsing gateway parameters\n", conf_file, conf_obj_name); + } + + /* gateway unique identifier (aka MAC address) (optional) */ + str = json_object_get_string(conf_obj, "gateway_ID"); + if (str != NULL) { + sscanf(str, "%llx", &ull); + lgwm = ull; + MSG("INFO: gateway MAC address is configured to %016llX\n", ull); + } + + /* server hostname or IP address (optional) */ + str = json_object_get_string(conf_obj, "server_address"); + if (str != NULL) { + strncpy(serv_addr, str, sizeof serv_addr); + MSG("INFO: server hostname or IP address is configured to \"%s\"\n", serv_addr); + } + + /* get up and down ports (optional) */ + val = json_object_get_value(conf_obj, "serv_port_up"); + if (val != NULL) { + snprintf(serv_port_up, sizeof serv_port_up, "%u", (uint16_t)json_value_get_number(val)); + MSG("INFO: upstream port is configured to \"%s\"\n", serv_port_up); + } + val = json_object_get_value(conf_obj, "serv_port_down"); + if (val != NULL) { + 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); + } + + /* get keep-alive interval (in seconds) for downstream (optional) */ + val = json_object_get_value(conf_obj, "keepalive_interval"); + if (val != NULL) { + keepalive_time = (int)json_value_get_number(val); + MSG("INFO: downstream keep-alive interval is configured to %u seconds\n", keepalive_time); + } + + /* get interval (in seconds) for statistics display (optional) */ + val = json_object_get_value(conf_obj, "stat_interval"); + if (val != NULL) { + stat_interval = (unsigned)json_value_get_number(val); + MSG("INFO: statistics display interval is configured to %u seconds\n", stat_interval); + } + + /* get time-out value (in ms) for upstream datagrams (optional) */ + val = json_object_get_value(conf_obj, "push_timeout_ms"); + if (val != NULL) { + push_timeout_half.tv_usec = 500 * (long int)json_value_get_number(val); + MSG("INFO: upstream PUSH_DATA time-out is configured to %u ms\n", (unsigned)(push_timeout_half.tv_usec / 500)); + } + + /* packet filtering parameters */ + val = json_object_get_value(conf_obj, "forward_crc_valid"); + if (json_value_get_type(val) == JSONBoolean) { + fwd_valid_pkt = (bool)json_value_get_boolean(val); + } + MSG("INFO: packets received with a valid CRC will%s be forwarded\n", (fwd_valid_pkt ? "" : " NOT")); + val = json_object_get_value(conf_obj, "forward_crc_error"); + if (json_value_get_type(val) == JSONBoolean) { + fwd_error_pkt = (bool)json_value_get_boolean(val); + } + MSG("INFO: packets received with a CRC error will%s be forwarded\n", (fwd_error_pkt ? "" : " NOT")); + val = json_object_get_value(conf_obj, "forward_crc_disabled"); + if (json_value_get_type(val) == JSONBoolean) { + fwd_nocrc_pkt = (bool)json_value_get_boolean(val); + } + MSG("INFO: packets received with no CRC will%s be forwarded\n", (fwd_nocrc_pkt ? "" : " NOT")); + + /* GPS module TTY path (optional) */ + str = json_object_get_string(conf_obj, "gps_tty_path"); + if (str != NULL) { + strncpy(gps_tty_path, str, sizeof gps_tty_path); + MSG("INFO: GPS serial port path is configured to \"%s\"\n", gps_tty_path); + } + + /* get reference coordinates */ + val = json_object_get_value(conf_obj, "ref_latitude"); + if (val != NULL) { + reference_coord.lat = (double)json_value_get_number(val); + MSG("INFO: Reference latitude is configured to %f deg\n", reference_coord.lat); + } + val = json_object_get_value(conf_obj, "ref_longitude"); + if (val != NULL) { + reference_coord.lon = (double)json_value_get_number(val); + MSG("INFO: Reference longitude is configured to %f deg\n", reference_coord.lon); + } + val = json_object_get_value(conf_obj, "ref_altitude"); + if (val != NULL) { + reference_coord.alt = (short)json_value_get_number(val); + MSG("INFO: Reference altitude is configured to %i meters\n", reference_coord.alt); + } + + /* Gateway GPS coordinates hardcoding (aka. faking) option */ + val = json_object_get_value(conf_obj, "fake_gps"); + if (json_value_get_type(val) == JSONBoolean) { + gps_fake_enable = (bool)json_value_get_boolean(val); + if (gps_fake_enable == true) { + MSG("INFO: fake GPS is enabled\n"); + } else { + MSG("INFO: fake GPS is disabled\n"); + } + } + + /* Beacon signal period (optional) */ + val = json_object_get_value(conf_obj, "beacon_period"); + if (val != NULL) { + beacon_period = (uint32_t)json_value_get_number(val); + if ((beacon_period > 0) && (beacon_period < 6)) { + MSG("ERROR: invalid configuration for Beacon period, must be >= 6s\n"); + return -1; + } else { + MSG("INFO: Beaconing period is configured to %u seconds\n", beacon_period); + } + } + + /* Beacon TX frequency (optional) */ + val = json_object_get_value(conf_obj, "beacon_freq_hz"); + if (val != NULL) { + beacon_freq_hz = (uint32_t)json_value_get_number(val); + MSG("INFO: Beaconing signal will be emitted at %u Hz\n", beacon_freq_hz); + } + + /* Number of beacon channels (optional) */ + val = json_object_get_value(conf_obj, "beacon_freq_nb"); + if (val != NULL) { + beacon_freq_nb = (uint8_t)json_value_get_number(val); + MSG("INFO: Beaconing channel number is set to %u\n", beacon_freq_nb); + } + + /* Frequency step between beacon channels (optional) */ + val = json_object_get_value(conf_obj, "beacon_freq_step"); + if (val != NULL) { + beacon_freq_step = (uint32_t)json_value_get_number(val); + MSG("INFO: Beaconing channel frequency step is set to %uHz\n", beacon_freq_step); + } + + /* Beacon datarate (optional) */ + val = json_object_get_value(conf_obj, "beacon_datarate"); + if (val != NULL) { + beacon_datarate = (uint8_t)json_value_get_number(val); + MSG("INFO: Beaconing datarate is set to SF%d\n", beacon_datarate); + } + + /* Beacon modulation bandwidth (optional) */ + val = json_object_get_value(conf_obj, "beacon_bw_hz"); + if (val != NULL) { + beacon_bw_hz = (uint32_t)json_value_get_number(val); + MSG("INFO: Beaconing modulation bandwidth is set to %dHz\n", beacon_bw_hz); + } + + /* Beacon TX power (optional) */ + val = json_object_get_value(conf_obj, "beacon_power"); + if (val != NULL) { + beacon_power = (int8_t)json_value_get_number(val); + MSG("INFO: Beaconing TX power is set to %ddBm\n", beacon_power); + } + + /* Beacon information descriptor (optional) */ + val = json_object_get_value(conf_obj, "beacon_infodesc"); + if (val != NULL) { + beacon_infodesc = (uint8_t)json_value_get_number(val); + MSG("INFO: Beaconing information descriptor is set to %u\n", beacon_infodesc); + } + + /* Auto-quit threshold (optional) */ + val = json_object_get_value(conf_obj, "autoquit_threshold"); + if (val != NULL) { + autoquit_threshold = (uint32_t)json_value_get_number(val); + MSG("INFO: Auto-quit after %u non-acknowledged PULL_DATA\n", autoquit_threshold); + } + + /* free JSON parsing data structure */ + json_value_free(root_val); + return 0; +} + +static uint16_t crc16(const uint8_t * data, unsigned size) { + const uint16_t crc_poly = 0x1021; + const uint16_t init_val = 0x0000; + uint16_t x = init_val; + unsigned i, j; + + if (data == NULL) { + return 0; + } + + for (i=0; i>32))); + net_mac_l = htonl((uint32_t)(0xFFFFFFFF & lgwm )); + + /* prepare hints to open network sockets */ + memset(&hints, 0, sizeof hints); + hints.ai_family = AF_INET; /* WA: Forcing IPv4 as AF_UNSPEC makes connection on localhost to fail */ + hints.ai_socktype = SOCK_DGRAM; + + /* look for server address w/ upstream port */ + i = getaddrinfo(serv_addr, serv_port_up, &hints, &result); + if (i != 0) { + MSG("ERROR: [up] getaddrinfo on address %s (PORT %s) returned %s\n", serv_addr, serv_port_up, gai_strerror(i)); + exit(EXIT_FAILURE); + } + + /* try to open socket for upstream traffic */ + for (q=result; q!=NULL; q=q->ai_next) { + sock_up = socket(q->ai_family, q->ai_socktype,q->ai_protocol); + if (sock_up == -1) continue; /* try next field */ + else break; /* success, get out of loop */ + } + if (q == NULL) { + MSG("ERROR: [up] failed to open socket to any of server %s addresses (port %s)\n", serv_addr, serv_port_up); + i = 1; + for (q=result; q!=NULL; q=q->ai_next) { + getnameinfo(q->ai_addr, q->ai_addrlen, host_name, sizeof host_name, port_name, sizeof port_name, NI_NUMERICHOST); + MSG("INFO: [up] result %i host:%s service:%s\n", i, host_name, port_name); + ++i; + } + exit(EXIT_FAILURE); + } + + /* connect so we can send/receive packet with the server only */ + i = connect(sock_up, q->ai_addr, q->ai_addrlen); + if (i != 0) { + MSG("ERROR: [up] connect returned %s\n", strerror(errno)); + exit(EXIT_FAILURE); + } + freeaddrinfo(result); + + /* look for server address w/ downstream port */ + i = getaddrinfo(serv_addr, serv_port_down, &hints, &result); + if (i != 0) { + MSG("ERROR: [down] getaddrinfo on address %s (port %s) returned %s\n", serv_addr, serv_port_up, gai_strerror(i)); + exit(EXIT_FAILURE); + } + + /* try to open socket for downstream traffic */ + for (q=result; q!=NULL; q=q->ai_next) { + sock_down = socket(q->ai_family, q->ai_socktype,q->ai_protocol); + if (sock_down == -1) continue; /* try next field */ + else break; /* success, get out of loop */ + } + if (q == NULL) { + MSG("ERROR: [down] failed to open socket to any of server %s addresses (port %s)\n", serv_addr, serv_port_up); + i = 1; + for (q=result; q!=NULL; q=q->ai_next) { + getnameinfo(q->ai_addr, q->ai_addrlen, host_name, sizeof host_name, port_name, sizeof port_name, NI_NUMERICHOST); + MSG("INFO: [down] result %i host:%s service:%s\n", i, host_name, port_name); + ++i; + } + exit(EXIT_FAILURE); + } + + /* connect so we can send/receive packet with the server only */ + i = connect(sock_down, q->ai_addr, q->ai_addrlen); + if (i != 0) { + MSG("ERROR: [down] connect returned %s\n", strerror(errno)); + exit(EXIT_FAILURE); + } + freeaddrinfo(result); + + /* starting the concentrator */ + i = lgw_start(); + if (i == LGW_HAL_SUCCESS) { + MSG("INFO: [main] concentrator started, packet can now be received\n"); + } else { + MSG("ERROR: [main] failed to start the concentrator\n"); + exit(EXIT_FAILURE); + } + + /* spawn threads to manage upstream and downstream */ + i = pthread_create( &thrid_up, NULL, (void * (*)(void *))thread_up, NULL); + if (i != 0) { + MSG("ERROR: [main] impossible to create upstream thread\n"); + exit(EXIT_FAILURE); + } + i = pthread_create( &thrid_down, NULL, (void * (*)(void *))thread_down, NULL); + if (i != 0) { + MSG("ERROR: [main] impossible to create downstream thread\n"); + exit(EXIT_FAILURE); + } + i = pthread_create( &thrid_jit, NULL, (void * (*)(void *))thread_jit, NULL); + if (i != 0) { + MSG("ERROR: [main] impossible to create JIT thread\n"); + exit(EXIT_FAILURE); + } + i = pthread_create( &thrid_timersync, NULL, (void * (*)(void *))thread_timersync, NULL); + if (i != 0) { + MSG("ERROR: [main] impossible to create Timer Sync 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); + if (i != 0) { + MSG("ERROR: [main] impossible to create GPS thread\n"); + exit(EXIT_FAILURE); + } + i = pthread_create( &thrid_valid, NULL, (void * (*)(void *))thread_valid, NULL); + if (i != 0) { + MSG("ERROR: [main] impossible to create validation thread\n"); + exit(EXIT_FAILURE); + } + } + + /* configure signal handling */ + sigemptyset(&sigact.sa_mask); + sigact.sa_flags = 0; + sigact.sa_handler = sig_handler; + sigaction(SIGQUIT, &sigact, NULL); /* Ctrl-\ */ + sigaction(SIGINT, &sigact, NULL); /* Ctrl-C */ + sigaction(SIGTERM, &sigact, NULL); /* default "kill" command */ + + /* main loop task : statistics collection */ + while (!exit_sig && !quit_sig) { + /* wait for next reporting interval */ + wait_ms(1000 * stat_interval); + + /* get timestamp for statistics */ + t = time(NULL); + strftime(stat_timestamp, sizeof stat_timestamp, "%F %T %Z", gmtime(&t)); + + /* access upstream statistics, copy and reset them */ + pthread_mutex_lock(&mx_meas_up); + cp_nb_rx_rcv = meas_nb_rx_rcv; + cp_nb_rx_ok = meas_nb_rx_ok; + cp_nb_rx_bad = meas_nb_rx_bad; + cp_nb_rx_nocrc = meas_nb_rx_nocrc; + cp_up_pkt_fwd = meas_up_pkt_fwd; + cp_up_network_byte = meas_up_network_byte; + cp_up_payload_byte = meas_up_payload_byte; + cp_up_dgram_sent = meas_up_dgram_sent; + cp_up_ack_rcv = meas_up_ack_rcv; + meas_nb_rx_rcv = 0; + meas_nb_rx_ok = 0; + meas_nb_rx_bad = 0; + meas_nb_rx_nocrc = 0; + meas_up_pkt_fwd = 0; + meas_up_network_byte = 0; + meas_up_payload_byte = 0; + meas_up_dgram_sent = 0; + meas_up_ack_rcv = 0; + pthread_mutex_unlock(&mx_meas_up); + if (cp_nb_rx_rcv > 0) { + rx_ok_ratio = (float)cp_nb_rx_ok / (float)cp_nb_rx_rcv; + rx_bad_ratio = (float)cp_nb_rx_bad / (float)cp_nb_rx_rcv; + rx_nocrc_ratio = (float)cp_nb_rx_nocrc / (float)cp_nb_rx_rcv; + } else { + rx_ok_ratio = 0.0; + rx_bad_ratio = 0.0; + rx_nocrc_ratio = 0.0; + } + if (cp_up_dgram_sent > 0) { + up_ack_ratio = (float)cp_up_ack_rcv / (float)cp_up_dgram_sent; + } else { + up_ack_ratio = 0.0; + } + + /* access downstream statistics, copy and reset them */ + pthread_mutex_lock(&mx_meas_dw); + cp_dw_pull_sent = meas_dw_pull_sent; + cp_dw_ack_rcv = meas_dw_ack_rcv; + cp_dw_dgram_rcv = meas_dw_dgram_rcv; + cp_dw_network_byte = meas_dw_network_byte; + cp_dw_payload_byte = meas_dw_payload_byte; + cp_nb_tx_ok = meas_nb_tx_ok; + cp_nb_tx_fail = meas_nb_tx_fail; + cp_nb_tx_requested += meas_nb_tx_requested; + cp_nb_tx_rejected_collision_packet += meas_nb_tx_rejected_collision_packet; + cp_nb_tx_rejected_collision_beacon += meas_nb_tx_rejected_collision_beacon; + cp_nb_tx_rejected_too_late += meas_nb_tx_rejected_too_late; + cp_nb_tx_rejected_too_early += meas_nb_tx_rejected_too_early; + cp_nb_beacon_queued += meas_nb_beacon_queued; + cp_nb_beacon_sent += meas_nb_beacon_sent; + cp_nb_beacon_rejected += meas_nb_beacon_rejected; + meas_dw_pull_sent = 0; + meas_dw_ack_rcv = 0; + meas_dw_dgram_rcv = 0; + meas_dw_network_byte = 0; + meas_dw_payload_byte = 0; + meas_nb_tx_ok = 0; + meas_nb_tx_fail = 0; + meas_nb_tx_requested = 0; + meas_nb_tx_rejected_collision_packet = 0; + meas_nb_tx_rejected_collision_beacon = 0; + meas_nb_tx_rejected_too_late = 0; + meas_nb_tx_rejected_too_early = 0; + meas_nb_beacon_queued = 0; + meas_nb_beacon_sent = 0; + meas_nb_beacon_rejected = 0; + pthread_mutex_unlock(&mx_meas_dw); + if (cp_dw_pull_sent > 0) { + dw_ack_ratio = (float)cp_dw_ack_rcv / (float)cp_dw_pull_sent; + } else { + dw_ack_ratio = 0.0; + } + + /* access GPS statistics, copy them */ + if (gps_enabled == true) { + pthread_mutex_lock(&mx_meas_gps); + coord_ok = gps_coord_valid; + cp_gps_coord = meas_gps_coord; + pthread_mutex_unlock(&mx_meas_gps); + } + + /* overwrite with reference coordinates if function is enabled */ + if (gps_fake_enable == true) { + cp_gps_coord = reference_coord; + } + + /* display a report */ + printf("\n##### %s #####\n", stat_timestamp); + printf("### [UPSTREAM] ###\n"); + printf("# RF packets received by concentrator: %u\n", cp_nb_rx_rcv); + printf("# CRC_OK: %.2f%%, CRC_FAIL: %.2f%%, NO_CRC: %.2f%%\n", 100.0 * rx_ok_ratio, 100.0 * rx_bad_ratio, 100.0 * rx_nocrc_ratio); + printf("# RF packets forwarded: %u (%u bytes)\n", cp_up_pkt_fwd, cp_up_payload_byte); + printf("# PUSH_DATA datagrams sent: %u (%u bytes)\n", cp_up_dgram_sent, cp_up_network_byte); + printf("# PUSH_DATA acknowledged: %.2f%%\n", 100.0 * up_ack_ratio); + printf("### [DOWNSTREAM] ###\n"); + printf("# PULL_DATA sent: %u (%.2f%% acknowledged)\n", cp_dw_pull_sent, 100.0 * dw_ack_ratio); + printf("# PULL_RESP(onse) datagrams received: %u (%u bytes)\n", cp_dw_dgram_rcv, cp_dw_network_byte); + printf("# RF packets sent to concentrator: %u (%u bytes)\n", (cp_nb_tx_ok+cp_nb_tx_fail), cp_dw_payload_byte); + printf("# TX errors: %u\n", cp_nb_tx_fail); + if (cp_nb_tx_requested != 0 ) { + printf("# TX rejected (collision packet): %.2f%% (req:%u, rej:%u)\n", 100.0 * cp_nb_tx_rejected_collision_packet / cp_nb_tx_requested, cp_nb_tx_requested, cp_nb_tx_rejected_collision_packet); + printf("# TX rejected (collision beacon): %.2f%% (req:%u, rej:%u)\n", 100.0 * cp_nb_tx_rejected_collision_beacon / cp_nb_tx_requested, cp_nb_tx_requested, cp_nb_tx_rejected_collision_beacon); + printf("# TX rejected (too late): %.2f%% (req:%u, rej:%u)\n", 100.0 * cp_nb_tx_rejected_too_late / cp_nb_tx_requested, cp_nb_tx_requested, cp_nb_tx_rejected_too_late); + printf("# TX rejected (too early): %.2f%% (req:%u, rej:%u)\n", 100.0 * cp_nb_tx_rejected_too_early / cp_nb_tx_requested, cp_nb_tx_requested, cp_nb_tx_rejected_too_early); + } + printf("# BEACON queued: %u\n", cp_nb_beacon_queued); + printf("# BEACON sent so far: %u\n", cp_nb_beacon_sent); + printf("# BEACON rejected: %u\n", cp_nb_beacon_rejected); + printf("### [JIT] ###\n"); + /* get timestamp captured on PPM pulse */ + pthread_mutex_lock(&mx_concent); + i = lgw_get_trigcnt(&trig_tstamp); + pthread_mutex_unlock(&mx_concent); + if (i != LGW_HAL_SUCCESS) { + printf("# SX1301 time (PPS): unknown\n"); + } else { + printf("# SX1301 time (PPS): %u\n", trig_tstamp); + } + jit_print_queue (&jit_queue, false, DEBUG_LOG); + printf("### [GPS] ###\n"); + if (gps_enabled == true) { + /* no need for mutex, display is not critical */ + if (gps_ref_valid == true) { + printf("# Valid time reference (age: %li sec)\n", (long)difftime(time(NULL), time_reference_gps.systime)); + } else { + printf("# Invalid time reference (age: %li sec)\n", (long)difftime(time(NULL), time_reference_gps.systime)); + } + if (coord_ok == true) { + printf("# GPS coordinates: latitude %.5f, longitude %.5f, altitude %i m\n", cp_gps_coord.lat, cp_gps_coord.lon, cp_gps_coord.alt); + } else { + printf("# no valid GPS coordinates available yet\n"); + } + } else if (gps_fake_enable == true) { + printf("# GPS *FAKE* coordinates: latitude %.5f, longitude %.5f, altitude %i m\n", cp_gps_coord.lat, cp_gps_coord.lon, cp_gps_coord.alt); + } else { + printf("# GPS sync is disabled\n"); + } + printf("##### END #####\n"); + + /* generate a JSON report (will be sent to server by upstream thread) */ + pthread_mutex_lock(&mx_stat_rep); + if (((gps_enabled == true) && (coord_ok == true)) || (gps_fake_enable == true)) { + snprintf(status_report, STATUS_SIZE, "\"stat\":{\"time\":\"%s\",\"lati\":%.5f,\"long\":%.5f,\"alti\":%i,\"rxnb\":%u,\"rxok\":%u,\"rxfw\":%u,\"ackr\":%.1f,\"dwnb\":%u,\"txnb\":%u}", stat_timestamp, cp_gps_coord.lat, cp_gps_coord.lon, cp_gps_coord.alt, cp_nb_rx_rcv, cp_nb_rx_ok, cp_up_pkt_fwd, 100.0 * up_ack_ratio, cp_dw_dgram_rcv, cp_nb_tx_ok); + } else { + snprintf(status_report, STATUS_SIZE, "\"stat\":{\"time\":\"%s\",\"rxnb\":%u,\"rxok\":%u,\"rxfw\":%u,\"ackr\":%.1f,\"dwnb\":%u,\"txnb\":%u}", stat_timestamp, cp_nb_rx_rcv, cp_nb_rx_ok, cp_up_pkt_fwd, 100.0 * up_ack_ratio, cp_dw_dgram_rcv, cp_nb_tx_ok); + } + report_ready = true; + pthread_mutex_unlock(&mx_stat_rep); + } + + /* wait for upstream thread to finish (1 fetch cycle max) */ + pthread_join(thrid_up, NULL); + pthread_cancel(thrid_down); /* don't wait for downstream thread */ + pthread_cancel(thrid_jit); /* don't wait for jit thread */ + pthread_cancel(thrid_timersync); /* don't wait for timer sync thread */ + if (gps_enabled == true) { + pthread_cancel(thrid_gps); /* don't wait for GPS thread */ + pthread_cancel(thrid_valid); /* don't wait for validation thread */ + + i = lgw_gps_disable(gps_tty_fd); + if (i == LGW_HAL_SUCCESS) { + MSG("INFO: GPS closed successfully\n"); + } else { + MSG("WARNING: failed to close GPS successfully\n"); + } + } + + /* if an exit signal was received, try to quit properly */ + if (exit_sig) { + /* shut down network sockets */ + shutdown(sock_up, SHUT_RDWR); + shutdown(sock_down, SHUT_RDWR); + /* stop the hardware */ + i = lgw_stop(); + if (i == LGW_HAL_SUCCESS) { + MSG("INFO: concentrator stopped successfully\n"); + } else { + MSG("WARNING: failed to stop concentrator successfully\n"); + } + } + + MSG("INFO: Exiting packet forwarder program\n"); + exit(EXIT_SUCCESS); +} + +/* -------------------------------------------------------------------------- */ +/* --- THREAD 1: RECEIVING PACKETS AND FORWARDING THEM ---------------------- */ + +void thread_up(void) { + int i, j; /* loop variables */ + unsigned pkt_in_dgram; /* nb on Lora packet in the current datagram */ + + /* allocate memory for packet fetching and processing */ + struct lgw_pkt_rx_s rxpkt[NB_PKT_MAX]; /* array containing inbound packets + metadata */ + struct lgw_pkt_rx_s *p; /* pointer on a RX packet */ + int nb_pkt; + + /* local copy of GPS time reference */ + bool ref_ok = false; /* determine if GPS time reference must be used or not */ + struct tref local_ref; /* time reference used for UTC <-> timestamp conversion */ + + /* data buffers */ + uint8_t buff_up[TX_BUFF_SIZE]; /* buffer to compose the upstream packet */ + int buff_index; + uint8_t buff_ack[32]; /* buffer to receive acknowledges */ + + /* protocol variables */ + uint8_t token_h; /* random token for acknowledgement matching */ + uint8_t token_l; /* random token for acknowledgement matching */ + + /* ping measurement variables */ + struct timespec send_time; + struct timespec recv_time; + + /* GPS synchronization variables */ + struct timespec pkt_utc_time; + struct tm * x; /* broken-up UTC time */ + struct timespec pkt_gps_time; + uint64_t pkt_gps_time_ms; + + /* report management variable */ + bool send_report = false; + + /* mote info variables */ + uint32_t mote_addr = 0; + uint16_t mote_fcnt = 0; + + /* set upstream socket RX timeout */ + i = setsockopt(sock_up, SOL_SOCKET, SO_RCVTIMEO, (void *)&push_timeout_half, sizeof push_timeout_half); + if (i != 0) { + MSG("ERROR: [up] setsockopt returned %s\n", strerror(errno)); + exit(EXIT_FAILURE); + } + + /* pre-fill the data buffer with fixed fields */ + buff_up[0] = PROTOCOL_VERSION; + buff_up[3] = PKT_PUSH_DATA; + *(uint32_t *)(buff_up + 4) = net_mac_h; + *(uint32_t *)(buff_up + 8) = net_mac_l; + + while (!exit_sig && !quit_sig) { + + /* fetch packets */ + pthread_mutex_lock(&mx_concent); + nb_pkt = lgw_receive(NB_PKT_MAX, rxpkt); + pthread_mutex_unlock(&mx_concent); + if (nb_pkt == LGW_HAL_ERROR) { + MSG("ERROR: [up] failed packet fetch, exiting\n"); + exit(EXIT_FAILURE); + } + + /* check if there are status report to send */ + send_report = report_ready; /* copy the variable so it doesn't change mid-function */ + /* no mutex, we're only reading */ + + /* wait a short time if no packets, nor status report */ + if ((nb_pkt == 0) && (send_report == false)) { + wait_ms(FETCH_SLEEP_MS); + continue; + } + + /* get a copy of GPS time reference (avoid 1 mutex per packet) */ + if ((nb_pkt > 0) && (gps_enabled == true)) { + pthread_mutex_lock(&mx_timeref); + ref_ok = gps_ref_valid; + local_ref = time_reference_gps; + pthread_mutex_unlock(&mx_timeref); + } else { + ref_ok = false; + } + + /* start composing datagram with the header */ + token_h = (uint8_t)rand(); /* random token */ + token_l = (uint8_t)rand(); /* random token */ + buff_up[1] = token_h; + buff_up[2] = token_l; + buff_index = 12; /* 12-byte header */ + + /* start of JSON structure */ + memcpy((void *)(buff_up + buff_index), (void *)"{\"rxpk\":[", 9); + buff_index += 9; + + /* serialize Lora packets metadata and payload */ + pkt_in_dgram = 0; + for (i=0; i < nb_pkt; ++i) { + p = &rxpkt[i]; + + /* Get mote information from current packet (addr, fcnt) */ + /* FHDR - DevAddr */ + mote_addr = p->payload[1]; + mote_addr |= p->payload[2] << 8; + mote_addr |= p->payload[3] << 16; + mote_addr |= p->payload[4] << 24; + /* FHDR - FCnt */ + mote_fcnt = p->payload[6]; + mote_fcnt |= p->payload[7] << 8; + + /* basic packet filtering */ + pthread_mutex_lock(&mx_meas_up); + meas_nb_rx_rcv += 1; + switch(p->status) { + case STAT_CRC_OK: + meas_nb_rx_ok += 1; + printf( "\nINFO: Received pkt from mote: %08X (fcnt=%u)\n", mote_addr, mote_fcnt ); + if (!fwd_valid_pkt) { + pthread_mutex_unlock(&mx_meas_up); + continue; /* skip that packet */ + } + break; + case STAT_CRC_BAD: + meas_nb_rx_bad += 1; + if (!fwd_error_pkt) { + pthread_mutex_unlock(&mx_meas_up); + continue; /* skip that packet */ + } + break; + case STAT_NO_CRC: + meas_nb_rx_nocrc += 1; + if (!fwd_nocrc_pkt) { + pthread_mutex_unlock(&mx_meas_up); + continue; /* skip that packet */ + } + break; + default: + MSG("WARNING: [up] received packet with unknown status %u (size %u, modulation %u, BW %u, DR %u, RSSI %.1f)\n", p->status, p->size, p->modulation, p->bandwidth, p->datarate, p->rssi); + pthread_mutex_unlock(&mx_meas_up); + continue; /* skip that packet */ + // exit(EXIT_FAILURE); + } + meas_up_pkt_fwd += 1; + meas_up_payload_byte += p->size; + pthread_mutex_unlock(&mx_meas_up); + + /* Start of packet, add inter-packet separator if necessary */ + if (pkt_in_dgram == 0) { + buff_up[buff_index] = '{'; + ++buff_index; + } else { + buff_up[buff_index] = ','; + buff_up[buff_index+1] = '{'; + buff_index += 2; + } + + /* RAW timestamp, 8-17 useful chars */ + j = snprintf((char *)(buff_up + buff_index), TX_BUFF_SIZE-buff_index, "\"tmst\":%u", p->count_us); + if (j > 0) { + buff_index += j; + } else { + MSG("ERROR: [up] snprintf failed line %u\n", (__LINE__ - 4)); + exit(EXIT_FAILURE); + } + + /* Packet RX time (GPS based), 37 useful chars */ + if (ref_ok == true) { + /* convert packet timestamp to UTC absolute time */ + j = lgw_cnt2utc(local_ref, p->count_us, &pkt_utc_time); + if (j == LGW_GPS_SUCCESS) { + /* split the UNIX timestamp to its calendar components */ + x = gmtime(&(pkt_utc_time.tv_sec)); + j = snprintf((char *)(buff_up + buff_index), TX_BUFF_SIZE-buff_index, ",\"time\":\"%04i-%02i-%02iT%02i:%02i:%02i.%06liZ\"", (x->tm_year)+1900, (x->tm_mon)+1, x->tm_mday, x->tm_hour, x->tm_min, x->tm_sec, (pkt_utc_time.tv_nsec)/1000); /* ISO 8601 format */ + if (j > 0) { + buff_index += j; + } else { + MSG("ERROR: [up] snprintf failed line %u\n", (__LINE__ - 4)); + exit(EXIT_FAILURE); + } + } + /* convert packet timestamp to GPS absolute time */ + j = lgw_cnt2gps(local_ref, p->count_us, &pkt_gps_time); + if (j == LGW_GPS_SUCCESS) { + pkt_gps_time_ms = pkt_gps_time.tv_sec * 1E3 + pkt_gps_time.tv_nsec / 1E6; + j = snprintf((char *)(buff_up + buff_index), TX_BUFF_SIZE-buff_index, ",\"tmms\":%llu", + pkt_gps_time_ms); /* GPS time in milliseconds since 06.Jan.1980 */ + if (j > 0) { + buff_index += j; + } else { + MSG("ERROR: [up] snprintf failed line %u\n", (__LINE__ - 4)); + exit(EXIT_FAILURE); + } + } + } + + /* Packet concentrator channel, RF chain & RX frequency, 34-36 useful chars */ + j = snprintf((char *)(buff_up + buff_index), TX_BUFF_SIZE-buff_index, ",\"chan\":%1u,\"rfch\":%1u,\"freq\":%.6lf", p->if_chain, p->rf_chain, ((double)p->freq_hz / 1e6)); + if (j > 0) { + buff_index += j; + } else { + MSG("ERROR: [up] snprintf failed line %u\n", (__LINE__ - 4)); + exit(EXIT_FAILURE); + } + + /* Packet status, 9-10 useful chars */ + switch (p->status) { + case STAT_CRC_OK: + memcpy((void *)(buff_up + buff_index), (void *)",\"stat\":1", 9); + buff_index += 9; + break; + case STAT_CRC_BAD: + memcpy((void *)(buff_up + buff_index), (void *)",\"stat\":-1", 10); + buff_index += 10; + break; + case STAT_NO_CRC: + memcpy((void *)(buff_up + buff_index), (void *)",\"stat\":0", 9); + buff_index += 9; + break; + default: + MSG("ERROR: [up] received packet with unknown status\n"); + memcpy((void *)(buff_up + buff_index), (void *)",\"stat\":?", 9); + buff_index += 9; + exit(EXIT_FAILURE); + } + + /* Packet modulation, 13-14 useful chars */ + if (p->modulation == MOD_LORA) { + memcpy((void *)(buff_up + buff_index), (void *)",\"modu\":\"LORA\"", 14); + buff_index += 14; + + /* Lora datarate & bandwidth, 16-19 useful chars */ + switch (p->datarate) { + case DR_LORA_SF7: + memcpy((void *)(buff_up + buff_index), (void *)",\"datr\":\"SF7", 12); + buff_index += 12; + break; + case DR_LORA_SF8: + memcpy((void *)(buff_up + buff_index), (void *)",\"datr\":\"SF8", 12); + buff_index += 12; + break; + case DR_LORA_SF9: + memcpy((void *)(buff_up + buff_index), (void *)",\"datr\":\"SF9", 12); + buff_index += 12; + break; + case DR_LORA_SF10: + memcpy((void *)(buff_up + buff_index), (void *)",\"datr\":\"SF10", 13); + buff_index += 13; + break; + case DR_LORA_SF11: + memcpy((void *)(buff_up + buff_index), (void *)",\"datr\":\"SF11", 13); + buff_index += 13; + break; + case DR_LORA_SF12: + memcpy((void *)(buff_up + buff_index), (void *)",\"datr\":\"SF12", 13); + buff_index += 13; + break; + default: + 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); + } + switch (p->bandwidth) { + case BW_125KHZ: + memcpy((void *)(buff_up + buff_index), (void *)"BW125\"", 6); + buff_index += 6; + break; + case BW_250KHZ: + memcpy((void *)(buff_up + buff_index), (void *)"BW250\"", 6); + buff_index += 6; + break; + case BW_500KHZ: + memcpy((void *)(buff_up + buff_index), (void *)"BW500\"", 6); + buff_index += 6; + break; + default: + MSG("ERROR: [up] lora packet with unknown bandwidth\n"); + memcpy((void *)(buff_up + buff_index), (void *)"BW?\"", 4); + buff_index += 4; + exit(EXIT_FAILURE); + } + + /* Packet ECC coding rate, 11-13 useful chars */ + switch (p->coderate) { + case CR_LORA_4_5: + memcpy((void *)(buff_up + buff_index), (void *)",\"codr\":\"4/5\"", 13); + buff_index += 13; + break; + case CR_LORA_4_6: + memcpy((void *)(buff_up + buff_index), (void *)",\"codr\":\"4/6\"", 13); + buff_index += 13; + break; + case CR_LORA_4_7: + memcpy((void *)(buff_up + buff_index), (void *)",\"codr\":\"4/7\"", 13); + buff_index += 13; + break; + case CR_LORA_4_8: + memcpy((void *)(buff_up + buff_index), (void *)",\"codr\":\"4/8\"", 13); + buff_index += 13; + break; + case 0: /* treat the CR0 case (mostly false sync) */ + memcpy((void *)(buff_up + buff_index), (void *)",\"codr\":\"OFF\"", 13); + buff_index += 13; + break; + default: + MSG("ERROR: [up] lora packet with unknown coderate\n"); + memcpy((void *)(buff_up + buff_index), (void *)",\"codr\":\"?\"", 11); + buff_index += 11; + exit(EXIT_FAILURE); + } + + /* Lora SNR, 11-13 useful chars */ + j = snprintf((char *)(buff_up + buff_index), TX_BUFF_SIZE-buff_index, ",\"lsnr\":%.1f", p->snr); + if (j > 0) { + buff_index += j; + } else { + MSG("ERROR: [up] snprintf failed line %u\n", (__LINE__ - 4)); + exit(EXIT_FAILURE); + } + } else if (p->modulation == MOD_FSK) { + memcpy((void *)(buff_up + buff_index), (void *)",\"modu\":\"FSK\"", 13); + buff_index += 13; + + /* FSK datarate, 11-14 useful chars */ + j = snprintf((char *)(buff_up + buff_index), TX_BUFF_SIZE-buff_index, ",\"datr\":%u", p->datarate); + if (j > 0) { + buff_index += j; + } else { + MSG("ERROR: [up] snprintf failed line %u\n", (__LINE__ - 4)); + exit(EXIT_FAILURE); + } + } else { + MSG("ERROR: [up] received packet with unknown modulation\n"); + exit(EXIT_FAILURE); + } + + /* Packet RSSI, payload size, 18-23 useful chars */ + j = snprintf((char *)(buff_up + buff_index), TX_BUFF_SIZE-buff_index, ",\"rssi\":%.0f,\"size\":%u", p->rssi, p->size); + if (j > 0) { + buff_index += j; + } else { + MSG("ERROR: [up] snprintf failed line %u\n", (__LINE__ - 4)); + exit(EXIT_FAILURE); + } + + /* Packet base64-encoded payload, 14-350 useful chars */ + memcpy((void *)(buff_up + buff_index), (void *)",\"data\":\"", 9); + buff_index += 9; + j = bin_to_b64(p->payload, p->size, (char *)(buff_up + buff_index), 341); /* 255 bytes = 340 chars in b64 + null char */ + if (j>=0) { + buff_index += j; + } else { + MSG("ERROR: [up] bin_to_b64 failed line %u\n", (__LINE__ - 5)); + exit(EXIT_FAILURE); + } + buff_up[buff_index] = '"'; + ++buff_index; + + /* End of packet serialization */ + buff_up[buff_index] = '}'; + ++buff_index; + ++pkt_in_dgram; + } + + /* restart fetch sequence without sending empty JSON if all packets have been filtered out */ + if (pkt_in_dgram == 0) { + if (send_report == true) { + /* need to clean up the beginning of the payload */ + buff_index -= 8; /* removes "rxpk":[ */ + } else { + /* all packet have been filtered out and no report, restart loop */ + continue; + } + } else { + /* end of packet array */ + buff_up[buff_index] = ']'; + ++buff_index; + /* add separator if needed */ + if (send_report == true) { + buff_up[buff_index] = ','; + ++buff_index; + } + } + + /* add status report if a new one is available */ + if (send_report == true) { + pthread_mutex_lock(&mx_stat_rep); + report_ready = false; + j = snprintf((char *)(buff_up + buff_index), TX_BUFF_SIZE-buff_index, "%s", status_report); + pthread_mutex_unlock(&mx_stat_rep); + if (j > 0) { + buff_index += j; + } else { + MSG("ERROR: [up] snprintf failed line %u\n", (__LINE__ - 5)); + exit(EXIT_FAILURE); + } + } + + /* end of JSON datagram payload */ + buff_up[buff_index] = '}'; + ++buff_index; + buff_up[buff_index] = 0; /* add string terminator, for safety */ + + printf("\nJSON up: %s\n", (char *)(buff_up + 12)); /* DEBUG: display JSON payload */ + + /* send datagram to server */ + send(sock_up, (void *)buff_up, buff_index, 0); + clock_gettime(CLOCK_MONOTONIC, &send_time); + pthread_mutex_lock(&mx_meas_up); + meas_up_dgram_sent += 1; + meas_up_network_byte += buff_index; + + /* wait for acknowledge (in 2 times, to catch extra packets) */ + for (i=0; i<2; ++i) { + j = recv(sock_up, (void *)buff_ack, sizeof buff_ack, 0); + clock_gettime(CLOCK_MONOTONIC, &recv_time); + if (j == -1) { + if (errno == EAGAIN) { /* timeout */ + continue; + } else { /* server connection error */ + break; + } + } else if ((j < 4) || (buff_ack[0] != PROTOCOL_VERSION) || (buff_ack[3] != PKT_PUSH_ACK)) { + //MSG("WARNING: [up] ignored invalid non-ACL packet\n"); + continue; + } else if ((buff_ack[1] != token_h) || (buff_ack[2] != token_l)) { + //MSG("WARNING: [up] ignored out-of sync ACK packet\n"); + continue; + } else { + MSG("INFO: [up] PUSH_ACK received in %i ms\n", (int)(1000 * difftimespec(recv_time, send_time))); + meas_up_ack_rcv += 1; + break; + } + } + pthread_mutex_unlock(&mx_meas_up); + } + MSG("\nINFO: End of upstream thread\n"); +} + +/* -------------------------------------------------------------------------- */ +/* --- THREAD 2: POLLING SERVER AND ENQUEUING PACKETS IN JIT QUEUE ---------- */ + +void thread_down(void) { + int i; /* loop variables */ + + /* configuration and metadata for an outbound packet */ + struct lgw_pkt_tx_s txpkt; + bool sent_immediate = false; /* option to sent the packet immediately */ + + /* local timekeeping variables */ + struct timespec send_time; /* time of the pull request */ + struct timespec recv_time; /* time of return from recv socket call */ + + /* data buffers */ + uint8_t buff_down[1000]; /* buffer to receive downstream packets */ + uint8_t buff_req[12]; /* buffer to compose pull requests */ + int msg_len; + + /* protocol variables */ + uint8_t token_h; /* random token for acknowledgement matching */ + uint8_t token_l; /* random token for acknowledgement matching */ + bool req_ack = false; /* keep track of whether PULL_DATA was acknowledged or not */ + + /* JSON parsing variables */ + JSON_Value *root_val = NULL; + JSON_Object *txpk_obj = NULL; + JSON_Value *val = NULL; /* needed to detect the absence of some fields */ + const char *str; /* pointer to sub-strings in the JSON data */ + short x0, x1; + uint64_t x2; + double x3, x4; + + /* variables to send on GPS timestamp */ + struct tref local_ref; /* time reference used for GPS <-> timestamp conversion */ + struct timespec gps_tx; /* GPS time that needs to be converted to timestamp */ + + /* beacon variables */ + struct lgw_pkt_tx_s beacon_pkt; + uint8_t beacon_chan; + uint8_t beacon_loop; + size_t beacon_RFU1_size = 0; + size_t beacon_RFU2_size = 0; + uint8_t beacon_pyld_idx = 0; + time_t diff_beacon_time; + struct timespec next_beacon_gps_time; /* gps time of next beacon packet */ + struct timespec last_beacon_gps_time; /* gps time of last enqueued beacon packet */ + int retry; + + /* beacon data fields, byte 0 is Least Significant Byte */ + int32_t field_latitude; /* 3 bytes, derived from reference latitude */ + int32_t field_longitude; /* 3 bytes, derived from reference longitude */ + uint16_t field_crc1, field_crc2; + + /* auto-quit variable */ + uint32_t autoquit_cnt = 0; /* count the number of PULL_DATA sent since the latest PULL_ACK */ + + /* Just In Time downlink */ + struct timeval current_unix_time; + struct timeval current_concentrator_time; + enum jit_error_e jit_result = JIT_ERROR_OK; + enum jit_pkt_type_e downlink_type; + + /* set downstream socket RX timeout */ + i = setsockopt(sock_down, SOL_SOCKET, SO_RCVTIMEO, (void *)&pull_timeout, sizeof pull_timeout); + if (i != 0) { + MSG("ERROR: [down] setsockopt returned %s\n", strerror(errno)); + exit(EXIT_FAILURE); + } + + /* pre-fill the pull request buffer with fixed fields */ + buff_req[0] = PROTOCOL_VERSION; + buff_req[3] = PKT_PULL_DATA; + *(uint32_t *)(buff_req + 4) = net_mac_h; + *(uint32_t *)(buff_req + 8) = net_mac_l; + + /* beacon variables initialization */ + last_beacon_gps_time.tv_sec = 0; + last_beacon_gps_time.tv_nsec = 0; + + /* beacon packet parameters */ + beacon_pkt.tx_mode = ON_GPS; /* send on PPS pulse */ + beacon_pkt.rf_chain = 0; /* antenna A */ + beacon_pkt.rf_power = beacon_power; + beacon_pkt.modulation = MOD_LORA; + switch (beacon_bw_hz) { + case 125000: + beacon_pkt.bandwidth = BW_125KHZ; + break; + case 500000: + beacon_pkt.bandwidth = BW_500KHZ; + break; + default: + /* should not happen */ + MSG("ERROR: unsupported bandwidth for beacon\n"); + exit(EXIT_FAILURE); + } + switch (beacon_datarate) { + case 8: + beacon_pkt.datarate = DR_LORA_SF8; + beacon_RFU1_size = 1; + beacon_RFU2_size = 3; + break; + case 9: + beacon_pkt.datarate = DR_LORA_SF9; + beacon_RFU1_size = 2; + beacon_RFU2_size = 0; + break; + case 10: + beacon_pkt.datarate = DR_LORA_SF10; + beacon_RFU1_size = 3; + beacon_RFU2_size = 1; + break; + case 12: + beacon_pkt.datarate = DR_LORA_SF12; + beacon_RFU1_size = 5; + beacon_RFU2_size = 3; + break; + default: + /* should not happen */ + MSG("ERROR: unsupported datarate for beacon\n"); + exit(EXIT_FAILURE); + } + beacon_pkt.size = beacon_RFU1_size + 4 + 2 + 7 + beacon_RFU2_size + 2; + beacon_pkt.coderate = CR_LORA_4_5; + beacon_pkt.invert_pol = false; + beacon_pkt.preamble = 10; + beacon_pkt.no_crc = true; + beacon_pkt.no_header = true; + + /* network common part beacon fields (little endian) */ + for (i = 0; i < (int)beacon_RFU1_size; i++) { + beacon_pkt.payload[beacon_pyld_idx++] = 0x0; + } + + /* network common part beacon fields (little endian) */ + beacon_pyld_idx += 4; /* time (variable), filled later */ + beacon_pyld_idx += 2; /* crc1 (variable), filled later */ + + /* calculate the latitude and longitude that must be publicly reported */ + field_latitude = (int32_t)((reference_coord.lat / 90.0) * (double)(1<<23)); + if (field_latitude > (int32_t)0x007FFFFF) { + field_latitude = (int32_t)0x007FFFFF; /* +90 N is represented as 89.99999 N */ + } else if (field_latitude < (int32_t)0xFF800000) { + field_latitude = (int32_t)0xFF800000; + } + field_longitude = (int32_t)((reference_coord.lon / 180.0) * (double)(1<<23)); + if (field_longitude > (int32_t)0x007FFFFF) { + field_longitude = (int32_t)0x007FFFFF; /* +180 E is represented as 179.99999 E */ + } else if (field_longitude < (int32_t)0xFF800000) { + field_longitude = (int32_t)0xFF800000; + } + + /* gateway specific beacon fields */ + beacon_pkt.payload[beacon_pyld_idx++] = beacon_infodesc; + beacon_pkt.payload[beacon_pyld_idx++] = 0xFF & field_latitude; + beacon_pkt.payload[beacon_pyld_idx++] = 0xFF & (field_latitude >> 8); + beacon_pkt.payload[beacon_pyld_idx++] = 0xFF & (field_latitude >> 16); + beacon_pkt.payload[beacon_pyld_idx++] = 0xFF & field_longitude; + beacon_pkt.payload[beacon_pyld_idx++] = 0xFF & (field_longitude >> 8); + beacon_pkt.payload[beacon_pyld_idx++] = 0xFF & (field_longitude >> 16); + + /* RFU */ + for (i = 0; i < (int)beacon_RFU2_size; i++) { + beacon_pkt.payload[beacon_pyld_idx++] = 0x0; + } + + /* CRC of the beacon gateway specific part fields */ + field_crc2 = crc16((beacon_pkt.payload + 6 + beacon_RFU1_size), 7 + beacon_RFU2_size); + beacon_pkt.payload[beacon_pyld_idx++] = 0xFF & field_crc2; + beacon_pkt.payload[beacon_pyld_idx++] = 0xFF & (field_crc2 >> 8); + + /* JIT queue initialization */ + jit_queue_init(&jit_queue); + + while (!exit_sig && !quit_sig) { + + /* auto-quit if the threshold is crossed */ + if ((autoquit_threshold > 0) && (autoquit_cnt >= autoquit_threshold)) { + exit_sig = true; + MSG("INFO: [down] the last %u PULL_DATA were not ACKed, exiting application\n", autoquit_threshold); + break; + } + + /* generate random token for request */ + token_h = (uint8_t)rand(); /* random token */ + token_l = (uint8_t)rand(); /* random token */ + buff_req[1] = token_h; + buff_req[2] = token_l; + + /* send PULL request and record time */ + send(sock_down, (void *)buff_req, sizeof buff_req, 0); + clock_gettime(CLOCK_MONOTONIC, &send_time); + pthread_mutex_lock(&mx_meas_dw); + meas_dw_pull_sent += 1; + pthread_mutex_unlock(&mx_meas_dw); + req_ack = false; + autoquit_cnt++; + + /* listen to packets and process them until a new PULL request must be sent */ + recv_time = send_time; + while ((int)difftimespec(recv_time, send_time) < keepalive_time) { + + /* try to receive a datagram */ + msg_len = recv(sock_down, (void *)buff_down, (sizeof buff_down)-1, 0); + clock_gettime(CLOCK_MONOTONIC, &recv_time); + + /* Pre-allocate beacon slots in JiT queue, to check downlink collisions */ + beacon_loop = JIT_NUM_BEACON_IN_QUEUE - jit_queue.num_beacon; + retry = 0; + while (beacon_loop && (beacon_period != 0)) { + pthread_mutex_lock(&mx_timeref); + /* Wait for GPS to be ready before inserting beacons in JiT queue */ + if ((gps_ref_valid == true) && (xtal_correct_ok == true)) { + + /* compute GPS time for next beacon to come */ + /* LoRaWAN: T = k*beacon_period + TBeaconDelay */ + /* with TBeaconDelay = [1.5ms +/- 1µs]*/ + if (last_beacon_gps_time.tv_sec == 0) { + /* if no beacon has been queued, get next slot from current GPS time */ + diff_beacon_time = time_reference_gps.gps.tv_sec % ((time_t)beacon_period); + next_beacon_gps_time.tv_sec = time_reference_gps.gps.tv_sec + + ((time_t)beacon_period - diff_beacon_time); + } else { + /* if there is already a beacon, take it as reference */ + next_beacon_gps_time.tv_sec = last_beacon_gps_time.tv_sec + beacon_period; + } + /* now we can add a beacon_period to the reference to get next beacon GPS time */ + next_beacon_gps_time.tv_sec += (retry * beacon_period); + next_beacon_gps_time.tv_nsec = 0; + +#if DEBUG_BEACON + { + time_t time_unix; + + time_unix = time_reference_gps.gps.tv_sec + UNIX_GPS_EPOCH_OFFSET; + MSG_DEBUG(DEBUG_BEACON, "GPS-now : %s", ctime(&time_unix)); + time_unix = last_beacon_gps_time.tv_sec + UNIX_GPS_EPOCH_OFFSET; + MSG_DEBUG(DEBUG_BEACON, "GPS-last: %s", ctime(&time_unix)); + time_unix = next_beacon_gps_time.tv_sec + UNIX_GPS_EPOCH_OFFSET; + MSG_DEBUG(DEBUG_BEACON, "GPS-next: %s", ctime(&time_unix)); + } +#endif + + /* convert GPS time to concentrator time, and set packet counter for JiT trigger */ + lgw_gps2cnt(time_reference_gps, next_beacon_gps_time, &(beacon_pkt.count_us)); + pthread_mutex_unlock(&mx_timeref); + + /* apply frequency correction to beacon TX frequency */ + if (beacon_freq_nb > 1) { + beacon_chan = (next_beacon_gps_time.tv_sec / beacon_period) % beacon_freq_nb; /* floor rounding */ + } else { + beacon_chan = 0; + } + /* Compute beacon frequency */ + beacon_pkt.freq_hz = beacon_freq_hz + (beacon_chan * beacon_freq_step); + + /* load time in beacon payload */ + beacon_pyld_idx = beacon_RFU1_size; + beacon_pkt.payload[beacon_pyld_idx++] = 0xFF & next_beacon_gps_time.tv_sec; + beacon_pkt.payload[beacon_pyld_idx++] = 0xFF & (next_beacon_gps_time.tv_sec >> 8); + beacon_pkt.payload[beacon_pyld_idx++] = 0xFF & (next_beacon_gps_time.tv_sec >> 16); + beacon_pkt.payload[beacon_pyld_idx++] = 0xFF & (next_beacon_gps_time.tv_sec >> 24); + + /* calculate CRC */ + field_crc1 = crc16(beacon_pkt.payload, 4 + beacon_RFU1_size); /* CRC for the network common part */ + beacon_pkt.payload[beacon_pyld_idx++] = 0xFF & field_crc1; + beacon_pkt.payload[beacon_pyld_idx++] = 0xFF & (field_crc1 >> 8); + + /* Insert beacon packet in JiT queue */ + gettimeofday(¤t_unix_time, NULL); + get_concentrator_time(¤t_concentrator_time, current_unix_time); + jit_result = jit_enqueue(&jit_queue, ¤t_concentrator_time, &beacon_pkt, JIT_PKT_TYPE_BEACON); + if (jit_result == JIT_ERROR_OK) { + /* update stats */ + pthread_mutex_lock(&mx_meas_dw); + meas_nb_beacon_queued += 1; + pthread_mutex_unlock(&mx_meas_dw); + + /* One more beacon in the queue */ + beacon_loop--; + retry = 0; + last_beacon_gps_time.tv_sec = next_beacon_gps_time.tv_sec; /* keep this beacon time as reference for next one to be programmed */ + + /* display beacon payload */ + MSG("INFO: Beacon queued (count_us=%u, freq_hz=%u, size=%u):\n", beacon_pkt.count_us, beacon_pkt.freq_hz, beacon_pkt.size); + printf( " => " ); + for (i = 0; i < beacon_pkt.size; ++i) { + MSG("%02X ", beacon_pkt.payload[i]); + } + MSG("\n"); + } else { + MSG_DEBUG(DEBUG_BEACON, "--> beacon queuing failed with %d\n", jit_result); + /* update stats */ + pthread_mutex_lock(&mx_meas_dw); + if (jit_result != JIT_ERROR_COLLISION_BEACON) { + meas_nb_beacon_rejected += 1; + } + pthread_mutex_unlock(&mx_meas_dw); + /* In case previous enqueue failed, we retry one period later until it succeeds */ + /* Note: In case the GPS has been unlocked for a while, there can be lots of retries */ + /* to be done from last beacon time to a new valid one */ + retry++; + MSG_DEBUG(DEBUG_BEACON, "--> beacon queuing retry=%d\n", retry); + } + } else { + pthread_mutex_unlock(&mx_timeref); + break; + } + } + + /* if no network message was received, got back to listening sock_down socket */ + if (msg_len == -1) { + //MSG("WARNING: [down] recv returned %s\n", strerror(errno)); /* too verbose */ + continue; + } + + /* if the datagram does not respect protocol, just ignore it */ + if ((msg_len < 4) || (buff_down[0] != PROTOCOL_VERSION) || ((buff_down[3] != PKT_PULL_RESP) && (buff_down[3] != PKT_PULL_ACK))) { + MSG("WARNING: [down] ignoring invalid packet len=%d, protocol_version=%d, id=%d\n", + msg_len, buff_down[0], buff_down[3]); + continue; + } + + /* if the datagram is an ACK, check token */ + if (buff_down[3] == PKT_PULL_ACK) { + if ((buff_down[1] == token_h) && (buff_down[2] == token_l)) { + if (req_ack) { + MSG("INFO: [down] duplicate ACK received :)\n"); + } else { /* if that packet was not already acknowledged */ + req_ack = true; + autoquit_cnt = 0; + pthread_mutex_lock(&mx_meas_dw); + meas_dw_ack_rcv += 1; + pthread_mutex_unlock(&mx_meas_dw); + MSG("INFO: [down] PULL_ACK received in %i ms\n", (int)(1000 * difftimespec(recv_time, send_time))); + } + } else { /* out-of-sync token */ + MSG("INFO: [down] received out-of-sync ACK\n"); + } + continue; + } + + /* the datagram is a PULL_RESP */ + buff_down[msg_len] = 0; /* add string terminator, just to be safe */ + MSG("INFO: [down] PULL_RESP received - token[%d:%d] :)\n", buff_down[1], buff_down[2]); /* very verbose */ + printf("\nJSON down: %s\n", (char *)(buff_down + 4)); /* DEBUG: display JSON payload */ + + /* initialize TX struct and try to parse JSON */ + memset(&txpkt, 0, sizeof txpkt); + root_val = json_parse_string_with_comments((const char *)(buff_down + 4)); /* JSON offset */ + if (root_val == NULL) { + MSG("WARNING: [down] invalid JSON, TX aborted\n"); + continue; + } + + /* look for JSON sub-object 'txpk' */ + txpk_obj = json_object_get_object(json_value_get_object(root_val), "txpk"); + if (txpk_obj == NULL) { + MSG("WARNING: [down] no \"txpk\" object in JSON, TX aborted\n"); + json_value_free(root_val); + continue; + } + + /* Parse "immediate" tag, or target timestamp, or UTC time to be converted by GPS (mandatory) */ + i = json_object_get_boolean(txpk_obj,"imme"); /* can be 1 if true, 0 if false, or -1 if not a JSON boolean */ + if (i == 1) { + /* TX procedure: send immediately */ + sent_immediate = true; + downlink_type = JIT_PKT_TYPE_DOWNLINK_CLASS_C; + MSG("INFO: [down] a packet will be sent in \"immediate\" mode\n"); + } else { + sent_immediate = false; + val = json_object_get_value(txpk_obj,"tmst"); + if (val != NULL) { + /* TX procedure: send on timestamp value */ + txpkt.count_us = (uint32_t)json_value_get_number(val); + + /* Concentrator timestamp is given, we consider it is a Class A downlink */ + downlink_type = JIT_PKT_TYPE_DOWNLINK_CLASS_A; + } else { + /* TX procedure: send on GPS time (converted to timestamp value) */ + val = json_object_get_value(txpk_obj, "tmms"); + if (val == NULL) { + MSG("WARNING: [down] no mandatory \"txpk.tmst\" or \"txpk.tmms\" objects in JSON, TX aborted\n"); + json_value_free(root_val); + continue; + } + if (gps_enabled == true) { + pthread_mutex_lock(&mx_timeref); + if (gps_ref_valid == true) { + local_ref = time_reference_gps; + pthread_mutex_unlock(&mx_timeref); + } else { + pthread_mutex_unlock(&mx_timeref); + MSG("WARNING: [down] no valid GPS time reference yet, impossible to send packet on specific GPS time, TX aborted\n"); + json_value_free(root_val); + + /* send acknoledge datagram to server */ + send_tx_ack(buff_down[1], buff_down[2], JIT_ERROR_GPS_UNLOCKED); + continue; + } + } else { + MSG("WARNING: [down] GPS disabled, impossible to send packet on specific GPS time, TX aborted\n"); + json_value_free(root_val); + + /* send acknoledge datagram to server */ + send_tx_ack(buff_down[1], buff_down[2], JIT_ERROR_GPS_UNLOCKED); + continue; + } + + /* Get GPS time from JSON */ + x2 = (uint64_t)json_value_get_number(val); + + /* Convert GPS time from milliseconds to timespec */ + x3 = modf((double)x2/1E3, &x4); + gps_tx.tv_sec = (time_t)x4; /* get seconds from integer part */ + gps_tx.tv_nsec = (long)(x3 * 1E9); /* get nanoseconds from fractional part */ + + /* transform GPS time to timestamp */ + i = lgw_gps2cnt(local_ref, gps_tx, &(txpkt.count_us)); + if (i != LGW_GPS_SUCCESS) { + MSG("WARNING: [down] could not convert GPS time to timestamp, TX aborted\n"); + json_value_free(root_val); + continue; + } else { + MSG("INFO: [down] a packet will be sent on timestamp value %u (calculated from GPS time)\n", txpkt.count_us); + } + + /* GPS timestamp is given, we consider it is a Class B downlink */ + downlink_type = JIT_PKT_TYPE_DOWNLINK_CLASS_B; + } + } + + /* Parse "No CRC" flag (optional field) */ + val = json_object_get_value(txpk_obj,"ncrc"); + if (val != NULL) { + txpkt.no_crc = (bool)json_value_get_boolean(val); + } + + /* parse target frequency (mandatory) */ + val = json_object_get_value(txpk_obj,"freq"); + if (val == NULL) { + MSG("WARNING: [down] no mandatory \"txpk.freq\" object in JSON, TX aborted\n"); + json_value_free(root_val); + continue; + } + txpkt.freq_hz = (uint32_t)((double)(1.0e6) * json_value_get_number(val)); + + /* parse RF chain used for TX (mandatory) */ + val = json_object_get_value(txpk_obj,"rfch"); + if (val == NULL) { + MSG("WARNING: [down] no mandatory \"txpk.rfch\" object in JSON, TX aborted\n"); + json_value_free(root_val); + continue; + } + txpkt.rf_chain = (uint8_t)json_value_get_number(val); + + /* parse TX power (optional field) */ + val = json_object_get_value(txpk_obj,"powe"); + if (val != NULL) { + txpkt.rf_power = (int8_t)json_value_get_number(val) - antenna_gain; + } + + /* Parse modulation (mandatory) */ + str = json_object_get_string(txpk_obj, "modu"); + if (str == NULL) { + MSG("WARNING: [down] no mandatory \"txpk.modu\" object in JSON, TX aborted\n"); + json_value_free(root_val); + continue; + } + if (strcmp(str, "LORA") == 0) { + /* Lora modulation */ + txpkt.modulation = MOD_LORA; + + /* Parse Lora spreading-factor and modulation bandwidth (mandatory) */ + str = json_object_get_string(txpk_obj, "datr"); + if (str == NULL) { + MSG("WARNING: [down] no mandatory \"txpk.datr\" object in JSON, TX aborted\n"); + json_value_free(root_val); + continue; + } + i = sscanf(str, "SF%2hdBW%3hd", &x0, &x1); + if (i != 2) { + MSG("WARNING: [down] format error in \"txpk.datr\", TX aborted\n"); + json_value_free(root_val); + continue; + } + switch (x0) { + case 7: txpkt.datarate = DR_LORA_SF7; break; + case 8: txpkt.datarate = DR_LORA_SF8; break; + case 9: txpkt.datarate = DR_LORA_SF9; break; + case 10: txpkt.datarate = DR_LORA_SF10; break; + case 11: txpkt.datarate = DR_LORA_SF11; break; + case 12: txpkt.datarate = DR_LORA_SF12; break; + default: + MSG("WARNING: [down] format error in \"txpk.datr\", invalid SF, TX aborted\n"); + json_value_free(root_val); + continue; + } + switch (x1) { + case 125: txpkt.bandwidth = BW_125KHZ; break; + case 250: txpkt.bandwidth = BW_250KHZ; break; + case 500: txpkt.bandwidth = BW_500KHZ; break; + default: + MSG("WARNING: [down] format error in \"txpk.datr\", invalid BW, TX aborted\n"); + json_value_free(root_val); + continue; + } + + /* Parse ECC coding rate (optional field) */ + str = json_object_get_string(txpk_obj, "codr"); + if (str == NULL) { + MSG("WARNING: [down] no mandatory \"txpk.codr\" object in json, TX aborted\n"); + json_value_free(root_val); + continue; + } + if (strcmp(str, "4/5") == 0) txpkt.coderate = CR_LORA_4_5; + else if (strcmp(str, "4/6") == 0) txpkt.coderate = CR_LORA_4_6; + else if (strcmp(str, "2/3") == 0) txpkt.coderate = CR_LORA_4_6; + else if (strcmp(str, "4/7") == 0) txpkt.coderate = CR_LORA_4_7; + else if (strcmp(str, "4/8") == 0) txpkt.coderate = CR_LORA_4_8; + else if (strcmp(str, "1/2") == 0) txpkt.coderate = CR_LORA_4_8; + else { + MSG("WARNING: [down] format error in \"txpk.codr\", TX aborted\n"); + json_value_free(root_val); + continue; + } + + /* Parse signal polarity switch (optional field) */ + val = json_object_get_value(txpk_obj,"ipol"); + if (val != NULL) { + txpkt.invert_pol = (bool)json_value_get_boolean(val); + } + + /* parse Lora preamble length (optional field, optimum min value enforced) */ + val = json_object_get_value(txpk_obj,"prea"); + if (val != NULL) { + i = (int)json_value_get_number(val); + if (i >= MIN_LORA_PREAMB) { + txpkt.preamble = (uint16_t)i; + } else { + txpkt.preamble = (uint16_t)MIN_LORA_PREAMB; + } + } else { + txpkt.preamble = (uint16_t)STD_LORA_PREAMB; + } + + } else if (strcmp(str, "FSK") == 0) { + /* FSK modulation */ + txpkt.modulation = MOD_FSK; + + /* parse FSK bitrate (mandatory) */ + val = json_object_get_value(txpk_obj,"datr"); + if (val == NULL) { + MSG("WARNING: [down] no mandatory \"txpk.datr\" object in JSON, TX aborted\n"); + json_value_free(root_val); + continue; + } + txpkt.datarate = (uint32_t)(json_value_get_number(val)); + + /* parse frequency deviation (mandatory) */ + val = json_object_get_value(txpk_obj,"fdev"); + if (val == NULL) { + MSG("WARNING: [down] no mandatory \"txpk.fdev\" object in JSON, TX aborted\n"); + json_value_free(root_val); + continue; + } + txpkt.f_dev = (uint8_t)(json_value_get_number(val) / 1000.0); /* JSON value in Hz, txpkt.f_dev in kHz */ + + /* parse FSK preamble length (optional field, optimum min value enforced) */ + val = json_object_get_value(txpk_obj,"prea"); + if (val != NULL) { + i = (int)json_value_get_number(val); + if (i >= MIN_FSK_PREAMB) { + txpkt.preamble = (uint16_t)i; + } else { + txpkt.preamble = (uint16_t)MIN_FSK_PREAMB; + } + } else { + txpkt.preamble = (uint16_t)STD_FSK_PREAMB; + } + + } else { + MSG("WARNING: [down] invalid modulation in \"txpk.modu\", TX aborted\n"); + json_value_free(root_val); + continue; + } + + /* Parse payload length (mandatory) */ + val = json_object_get_value(txpk_obj,"size"); + if (val == NULL) { + MSG("WARNING: [down] no mandatory \"txpk.size\" object in JSON, TX aborted\n"); + json_value_free(root_val); + continue; + } + txpkt.size = (uint16_t)json_value_get_number(val); + + /* Parse payload data (mandatory) */ + str = json_object_get_string(txpk_obj, "data"); + if (str == NULL) { + MSG("WARNING: [down] no mandatory \"txpk.data\" object in JSON, TX aborted\n"); + json_value_free(root_val); + continue; + } + i = b64_to_bin(str, strlen(str), txpkt.payload, sizeof txpkt.payload); + if (i != txpkt.size) { + MSG("WARNING: [down] mismatch between .size and .data size once converter to binary\n"); + } + + /* free the JSON parse tree from memory */ + json_value_free(root_val); + + /* select TX mode */ + if (sent_immediate) { + txpkt.tx_mode = IMMEDIATE; + } else { + txpkt.tx_mode = TIMESTAMPED; + } + + /* record measurement data */ + pthread_mutex_lock(&mx_meas_dw); + 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); + + /* check TX parameter before trying to queue packet */ + jit_result = JIT_ERROR_OK; + if ((txpkt.freq_hz < tx_freq_min[txpkt.rf_chain]) || (txpkt.freq_hz > tx_freq_max[txpkt.rf_chain])) { + jit_result = JIT_ERROR_TX_FREQ; + MSG("ERROR: Packet REJECTED, unsupported frequency - %u (min:%u,max:%u)\n", txpkt.freq_hz, tx_freq_min[txpkt.rf_chain], tx_freq_max[txpkt.rf_chain]); + } + if (jit_result == JIT_ERROR_OK) { + for (i=0; i -1) { + jit_result = jit_dequeue(&jit_queue, pkt_index, &pkt, &pkt_type); + if (jit_result == JIT_ERROR_OK) { + /* update beacon stats */ + if (pkt_type == JIT_PKT_TYPE_BEACON) { + /* Compensate breacon frequency with xtal error */ + pthread_mutex_lock(&mx_xcorr); + pkt.freq_hz = (uint32_t)(xtal_correct * (double)pkt.freq_hz); + MSG_DEBUG(DEBUG_BEACON, "beacon_pkt.freq_hz=%u (xtal_correct=%.15lf)\n", pkt.freq_hz, xtal_correct); + pthread_mutex_unlock(&mx_xcorr); + + /* Update statistics */ + pthread_mutex_lock(&mx_meas_dw); + meas_nb_beacon_sent += 1; + pthread_mutex_unlock(&mx_meas_dw); + MSG("INFO: Beacon dequeued (count_us=%u)\n", pkt.count_us); + } + + /* check if concentrator is free for sending new packet */ + pthread_mutex_lock(&mx_concent); /* may have to wait for a fetch to finish */ + result = lgw_status(TX_STATUS, &tx_status); + pthread_mutex_unlock(&mx_concent); /* free concentrator ASAP */ + if (result == LGW_HAL_ERROR) { + MSG("WARNING: [jit] lgw_status failed\n"); + } else { + if (tx_status == TX_EMITTING) { + MSG("ERROR: concentrator is currently emitting\n"); + print_tx_status(tx_status); + continue; + } else if (tx_status == TX_SCHEDULED) { + MSG("WARNING: a downlink was already scheduled, overwritting it...\n"); + print_tx_status(tx_status); + } else { + /* Nothing to do */ + } + } + + /* send packet to concentrator */ + pthread_mutex_lock(&mx_concent); /* may have to wait for a fetch to finish */ + result = lgw_send(pkt); + pthread_mutex_unlock(&mx_concent); /* free concentrator ASAP */ + if (result == LGW_HAL_ERROR) { + pthread_mutex_lock(&mx_meas_dw); + meas_nb_tx_fail += 1; + pthread_mutex_unlock(&mx_meas_dw); + MSG("WARNING: [jit] lgw_send failed\n"); + continue; + } else { + pthread_mutex_lock(&mx_meas_dw); + meas_nb_tx_ok += 1; + pthread_mutex_unlock(&mx_meas_dw); + MSG_DEBUG(DEBUG_PKT_FWD, "lgw_send done: count_us=%u\n", pkt.count_us); + } + } else { + MSG("ERROR: jit_dequeue failed with %d\n", jit_result); + } + } + } else if (jit_result == JIT_ERROR_EMPTY) { + /* Do nothing, it can happen */ + } else { + MSG("ERROR: jit_peek failed with %d\n", jit_result); + } + } +} + +/* -------------------------------------------------------------------------- */ +/* --- THREAD 4: PARSE GPS MESSAGE AND KEEP GATEWAY IN SYNC ----------------- */ + +static void gps_process_sync(void) { + struct timespec gps_time; + struct timespec utc; + uint32_t trig_tstamp; /* concentrator timestamp associated with PPM pulse */ + int i = lgw_gps_get(&utc, &gps_time, NULL, NULL); + + /* get GPS time for synchronization */ + if (i != LGW_GPS_SUCCESS) { + MSG("WARNING: [gps] could not get GPS time from GPS\n"); + return; + } + + /* get timestamp captured on PPM pulse */ + pthread_mutex_lock(&mx_concent); + i = lgw_get_trigcnt(&trig_tstamp); + pthread_mutex_unlock(&mx_concent); + if (i != LGW_HAL_SUCCESS) { + MSG("WARNING: [gps] failed to read concentrator timestamp\n"); + return; + } + + /* try to update time reference with the new GPS time & timestamp */ + pthread_mutex_lock(&mx_timeref); + i = lgw_gps_sync(&time_reference_gps, trig_tstamp, utc, gps_time); + pthread_mutex_unlock(&mx_timeref); + if (i != LGW_GPS_SUCCESS) { + MSG("WARNING: [gps] GPS out of sync, keeping previous time reference\n"); + } +} + +static void gps_process_coords(void) { + /* position variable */ + struct coord_s coord; + struct coord_s gpserr; + int i = lgw_gps_get(NULL, NULL, &coord, &gpserr); + + /* update gateway coordinates */ + pthread_mutex_lock(&mx_meas_gps); + if (i == LGW_GPS_SUCCESS) { + gps_coord_valid = true; + meas_gps_coord = coord; + meas_gps_err = gpserr; + // TODO: report other GPS statistics (typ. signal quality & integrity) + } else { + gps_coord_valid = false; + } + pthread_mutex_unlock(&mx_meas_gps); +} + +void thread_gps(void) { + /* serial variables */ + char serial_buff[128]; /* buffer to receive GPS data */ + size_t wr_idx = 0; /* pointer to end of chars in buffer */ + + /* variables for PPM pulse GPS synchronization */ + enum gps_msg latest_msg; /* keep track of latest NMEA message parsed */ + + /* initialize some variables before loop */ + memset(serial_buff, 0, sizeof serial_buff); + + int invalid_nb_char_count = 0; + while (!exit_sig && !quit_sig) { + size_t rd_idx = 0; + size_t frame_end_idx = 0; + + /* blocking non-canonical read on serial port */ + ssize_t nb_char = read(gps_tty_fd, serial_buff + wr_idx, LGW_GPS_MIN_MSG_SIZE); + if (nb_char <= 0) { + invalid_nb_char_count++; + if ((invalid_nb_char_count % 20000) == 0){ + MSG("WARNING: [gps] read() returned value %d\n", nb_char); + } + continue; + } + wr_idx += (size_t)nb_char; + + /******************************************* + * Scan buffer for UBX/NMEA sync chars and * + * attempt to decode frame if one is found * + *******************************************/ + while(rd_idx < wr_idx) { + size_t frame_size = 0; + + /* Scan buffer for UBX sync char */ + if(serial_buff[rd_idx] == (char)LGW_GPS_UBX_SYNC_CHAR) { + + /*********************** + * Found UBX sync char * + ***********************/ + latest_msg = lgw_parse_ubx(&serial_buff[rd_idx], (wr_idx - rd_idx), &frame_size); + + if (frame_size > 0) { + if (latest_msg == INCOMPLETE) { + /* UBX header found but frame appears to be missing bytes */ + frame_size = 0; + } else if (latest_msg == INVALID) { + /* message header received but message appears to be corrupted */ + MSG("WARNING: [gps] could not get a valid message from GPS (no time)\n"); + frame_size = 0; + } else if (latest_msg == UBX_NAV_TIMEGPS) { + gps_process_sync(); + } + } + } else if(serial_buff[rd_idx] == LGW_GPS_NMEA_SYNC_CHAR) { + /************************ + * Found NMEA sync char * + ************************/ + /* scan for NMEA end marker (LF = 0x0a) */ + char* nmea_end_ptr = memchr(&serial_buff[rd_idx],(int)0x0a, (wr_idx - rd_idx)); + + if(nmea_end_ptr) { + /* found end marker */ + frame_size = nmea_end_ptr - &serial_buff[rd_idx] + 1; + latest_msg = lgw_parse_nmea(&serial_buff[rd_idx], frame_size); + + if(latest_msg == INVALID || latest_msg == UNKNOWN) { + /* checksum failed */ + frame_size = 0; + } else if (latest_msg == NMEA_RMC) { /* Get location from RMC frames */ + gps_process_coords(); + } + } + } + + if(frame_size > 0) { + /* At this point message is a checksum verified frame + we're processed or ignored. Remove frame from buffer */ + rd_idx += frame_size; + frame_end_idx = rd_idx; + } else { + rd_idx++; + } + } /* ...for(rd_idx = 0... */ + + if(frame_end_idx) { + /* Frames have been processed. Remove bytes to end of last processed frame */ + memcpy(serial_buff, &serial_buff[frame_end_idx], wr_idx - frame_end_idx); + wr_idx -= frame_end_idx; + } /* ...for(rd_idx = 0... */ + + /* Prevent buffer overflow */ + if((sizeof(serial_buff) - wr_idx) < LGW_GPS_MIN_MSG_SIZE) { + memcpy(serial_buff, &serial_buff[LGW_GPS_MIN_MSG_SIZE], wr_idx - LGW_GPS_MIN_MSG_SIZE); + wr_idx -= LGW_GPS_MIN_MSG_SIZE; + } + } + MSG("\nINFO: End of GPS thread\n"); +} + +/* -------------------------------------------------------------------------- */ +/* --- THREAD 5: CHECK TIME REFERENCE AND CALCULATE XTAL CORRECTION --------- */ + +void thread_valid(void) { + + /* GPS reference validation variables */ + long gps_ref_age = 0; + bool ref_valid_local = false; + double xtal_err_cpy; + + /* variables for XTAL correction averaging */ + unsigned init_cpt = 0; + double init_acc = 0.0; + double x; + + /* correction debug */ + // FILE * log_file = NULL; + // time_t now_time; + // char log_name[64]; + + /* initialization */ + // time(&now_time); + // strftime(log_name,sizeof log_name,"xtal_err_%Y%m%dT%H%M%SZ.csv",localtime(&now_time)); + // log_file = fopen(log_name, "w"); + // setbuf(log_file, NULL); + // fprintf(log_file,"\"xtal_correct\",\"XERR_INIT_AVG %u XERR_FILT_COEF %u\"\n", XERR_INIT_AVG, XERR_FILT_COEF); // DEBUG + + /* main loop task */ + while (!exit_sig && !quit_sig) { + wait_ms(1000); + + /* calculate when the time reference was last updated */ + pthread_mutex_lock(&mx_timeref); + gps_ref_age = (long)difftime(time(NULL), time_reference_gps.systime); + if ((gps_ref_age >= 0) && (gps_ref_age <= GPS_REF_MAX_AGE)) { + /* time ref is ok, validate and */ + gps_ref_valid = true; + ref_valid_local = true; + xtal_err_cpy = time_reference_gps.xtal_err; + //printf("XTAL err: %.15lf (1/XTAL_err:%.15lf)\n", xtal_err_cpy, 1/xtal_err_cpy); // DEBUG + } else { + /* time ref is too old, invalidate */ + gps_ref_valid = false; + ref_valid_local = false; + } + pthread_mutex_unlock(&mx_timeref); + + /* manage XTAL correction */ + if (ref_valid_local == false) { + /* couldn't sync, or sync too old -> invalidate XTAL correction */ + pthread_mutex_lock(&mx_xcorr); + xtal_correct_ok = false; + xtal_correct = 1.0; + pthread_mutex_unlock(&mx_xcorr); + init_cpt = 0; + init_acc = 0.0; + } else { + if (init_cpt < XERR_INIT_AVG) { + /* initial accumulation */ + init_acc += xtal_err_cpy; + ++init_cpt; + } else if (init_cpt == XERR_INIT_AVG) { + /* initial average calculation */ + pthread_mutex_lock(&mx_xcorr); + xtal_correct = (double)(XERR_INIT_AVG) / init_acc; + //printf("XERR_INIT_AVG=%d, init_acc=%.15lf\n", XERR_INIT_AVG, init_acc); + xtal_correct_ok = true; + pthread_mutex_unlock(&mx_xcorr); + ++init_cpt; + // fprintf(log_file,"%.18lf,\"average\"\n", xtal_correct); // DEBUG + } else { + /* tracking with low-pass filter */ + x = 1 / xtal_err_cpy; + pthread_mutex_lock(&mx_xcorr); + xtal_correct = xtal_correct - xtal_correct/XERR_FILT_COEF + x/XERR_FILT_COEF; + pthread_mutex_unlock(&mx_xcorr); + // fprintf(log_file,"%.18lf,\"track\"\n", xtal_correct); // DEBUG + } + } + // printf("Time ref: %s, XTAL correct: %s (%.15lf)\n", ref_valid_local?"valid":"invalid", xtal_correct_ok?"valid":"invalid", xtal_correct); // DEBUG + } + MSG("\nINFO: End of validation thread\n"); +} + +/* --- EOF ------------------------------------------------------------------ */ diff --git a/lora/rak7243/loragw_gps.c b/lora/rak7243/loragw_gps.c new file mode 100644 index 0000000..b6f2bb1 --- /dev/null +++ b/lora/rak7243/loragw_gps.c @@ -0,0 +1,842 @@ +/* + / _____) _ | | +( (____ _____ ____ _| |_ _____ ____| |__ + \____ \| ___ | (_ _) ___ |/ ___) _ \ + _____) ) ____| | | || |_| ____( (___| | | | +(______/|_____)_|_|_| \__)_____)\____)_| |_| + (C)2013 Semtech-Cycleo + +Description: + Library of functions to manage a GNSS module (typically GPS) for accurate + timestamping of packets and synchronisation of gateways. + A limited set of module brands/models are supported. + +License: Revised BSD License, see LICENSE.TXT file include in the project +Maintainer: Michael Coracin +*/ + + +/* -------------------------------------------------------------------------- */ +/* --- DEPENDANCIES --------------------------------------------------------- */ + +#define _GNU_SOURCE /* needed for qsort_r to be defined */ +#include /* C99 types */ +#include /* bool type */ +#include /* printf fprintf */ +#include /* memcpy */ + +#include /* struct timespec */ +#include /* open */ +#include /* tcflush */ +#include /* modf */ +#include + +#include + +#include "loragw_gps.h" + +/* -------------------------------------------------------------------------- */ +/* --- PRIVATE MACROS ------------------------------------------------------- */ + +#define ARRAY_SIZE(a) (sizeof(a) / sizeof((a)[0])) +#if DEBUG_GPS == 1 + #define DEBUG_MSG(args...) fprintf(stderr, args) + #define DEBUG_ARRAY(a,b,c) for(a=0;a= buff_size) { + DEBUG_MSG("Maximum length reached for nmea_checksum\n"); + return -1; + } + } + + /* Convert checksum value to 2 hexadecimal characters */ + checksum[0] = nibble_to_hexchar(check_num / 16); /* upper nibble */ + checksum[1] = nibble_to_hexchar(check_num % 16); /* lower nibble */ + + return i + 1; +} + +/* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ */ + +static char nibble_to_hexchar(uint8_t a) { + if (a < 10) { + return '0' + a; + } else if (a < 16) { + return 'A' + (a-10); + } else { + return '?'; + } +} + +/* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ */ + +/* +Calculate the checksum of a NMEA frame and compare it to the checksum that is +present at the end of it. +Return true if it matches +*/ +static bool validate_nmea_checksum(const char *serial_buff, int buff_size) { + int checksum_index; + char checksum[2]; /* 2 characters to calculate NMEA checksum */ + + checksum_index = nmea_checksum(serial_buff, buff_size, checksum); + + /* could we calculate a verification checksum ? */ + if (checksum_index < 0) { + DEBUG_MSG("ERROR: IMPOSSIBLE TO PARSE NMEA SENTENCE\n"); + return false; + } + + /* check if there are enough char in the serial buffer to read checksum */ + if (checksum_index >= (buff_size - 2)) { + DEBUG_MSG("ERROR: IMPOSSIBLE TO READ NMEA SENTENCE CHECKSUM\n"); + return false; + } + + /* check the checksum per se */ + if ((serial_buff[checksum_index] == checksum[0]) && (serial_buff[checksum_index+1] == checksum[1])) { + return true; + } else { + DEBUG_MSG("ERROR: NMEA CHECKSUM %c%c DOESN'T MATCH VERIFICATION CHECKSUM %c%c\n", serial_buff[checksum_index], serial_buff[checksum_index+1], checksum[0], checksum[1]); + return false; + } +} + +/* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ */ + +/* +Return true if the "label" string (can contain wildcard characters) matches +the begining of the "s" string +*/ +static bool match_label(const char *s, char *label, int size, char wildcard) { + int i; + + for (i=0; i < size; i++) { + if (label[i] == wildcard) continue; + if (label[i] != s[i]) return false; + } + return true; +} + +/* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ */ + +/* +Chop a string into smaller strings +Replace every separator in the input character buffer by a null character so +that all s[index] are valid strings. +Populate an array of integer 'idx_ary' representing indexes of token in the +string. +buff_size and max_idx are there to prevent segfaults. +Return the number of token found (number of idx_ary filled). +*/ +int str_chop(char *s, int buff_size, char separator, int *idx_ary, int max_idx) { + int i = 0; /* index in the string */ + int j = 0; /* index in the result array */ + + if ((s == NULL) || (buff_size < 0) || (separator == 0) || (idx_ary == NULL) || (max_idx < 0)) { + /* unsafe to do anything */ + return -1; + } + if ((buff_size == 0) || (max_idx == 0)) { + /* nothing to do */ + return 0; + } + s[buff_size - 1] = 0; /* add string terminator at the end of the buffer, just to be sure */ + idx_ary[j] = 0; + j += 1; + /* loop until string terminator is reached */ + while (s[i] != 0) { + if (s[i] == separator) { + s[i] = 0; /* replace separator by string terminator */ + if (j >= max_idx) { /* no more room in the index array */ + return j; + } + idx_ary[j] = i+1; /* next token start after replaced separator */ + ++j; + } + ++i; + } + return j; +} + +/* -------------------------------------------------------------------------- */ +/* --- PUBLIC FUNCTIONS DEFINITION ------------------------------------------ */ + +int lgw_gps_enable(char *tty_path, char *gps_family, speed_t target_brate, int *fd_ptr) { + int i; + struct termios ttyopt; /* serial port options */ + int gps_tty_dev; /* file descriptor to the serial port of the GNSS module */ + uint8_t ubx_cmd_timegps[UBX_MSG_NAVTIMEGPS_LEN] = { + 0xB5, 0x62, /* UBX Sync Chars */ + 0x06, 0x01, /* CFG-MSG Class/ID */ + 0x08, 0x00, /* Payload length */ + 0x01, 0x20, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, /* Enable NAV-TIMEGPS output on serial */ + 0x31, 0x91 }; /* Checksum */ + ssize_t num_written; + + /* check input parameters */ + CHECK_NULL(tty_path); + CHECK_NULL(fd_ptr); + + /* open TTY device */ + gps_tty_dev = open(tty_path, O_RDWR | O_NOCTTY); + if (gps_tty_dev <= 0) { + DEBUG_MSG("ERROR: TTY PORT FAIL TO OPEN, CHECK PATH AND ACCESS RIGHTS\n"); + return LGW_GPS_ERROR; + } + *fd_ptr = gps_tty_dev; + if(ioctl(gps_tty_dev, I2C_SLAVE, 0x42) < 0) + { + DEBUG_MSG("ERROR: I2C FAIL TO SET ADDR\n"); + return LGW_GPS_ERROR; + } + + /* manage the different GPS modules families */ +#if 0 + if (gps_family == NULL) { + DEBUG_MSG("WARNING: this version of GPS module may not be supported\n"); + } else if (strncmp(gps_family, "ubx7", 4) != 0) { + /* The current implementation relies on proprietary messages from U-Blox */ + /* GPS modules (UBX, NAV-TIMEGPS...) and has only be tested with a u-blox 7. */ + /* Those messages allow to get NATIVE GPS time (no leap seconds) required */ + /* for class-B handling and GPS synchronization */ + /* see lgw_parse_ubx() function for details */ + DEBUG_MSG("WARNING: this version of GPS module may not be supported\n"); + } + + /* manage the target bitrate */ + if (target_brate != 0) { + DEBUG_MSG("WARNING: target_brate parameter ignored for now\n"); // TODO + } + + /* get actual serial port configuration */ + i = tcgetattr(gps_tty_dev, &ttyopt); + if (i != 0) { + DEBUG_MSG("ERROR: IMPOSSIBLE TO GET TTY PORT CONFIGURATION\n"); + return LGW_GPS_ERROR; + } + + /* Save current serial port configuration for restoring later */ + memcpy(&ttyopt_restore, &ttyopt, sizeof ttyopt); + + /* update baudrates */ + cfsetispeed(&ttyopt, DEFAULT_BAUDRATE); + cfsetospeed(&ttyopt, DEFAULT_BAUDRATE); + + /* update terminal parameters */ + /* The following configuration should allow to: + - Get ASCII NMEA messages + - Get UBX binary messages + - Send UBX binary commands + Note: as binary data have to be read/written, we need to disable + various character processing to avoid loosing data */ + /* Control Modes */ + ttyopt.c_cflag |= CLOCAL; /* local connection, no modem control */ + ttyopt.c_cflag |= CREAD; /* enable receiving characters */ + ttyopt.c_cflag |= CS8; /* 8 bit frames */ + ttyopt.c_cflag &= ~PARENB; /* no parity */ + ttyopt.c_cflag &= ~CSTOPB; /* one stop bit */ + /* Input Modes */ + ttyopt.c_iflag |= IGNPAR; /* ignore bytes with parity errors */ + ttyopt.c_iflag &= ~ICRNL; /* do not map CR to NL on input*/ + ttyopt.c_iflag &= ~IGNCR; /* do not ignore carriage return on input */ + ttyopt.c_iflag &= ~IXON; /* disable Start/Stop output control */ + ttyopt.c_iflag &= ~IXOFF; /* do not send Start/Stop characters */ + /* Output Modes */ + ttyopt.c_oflag = 0; /* disable everything on output as we only write binary */ + /* Local Modes */ + ttyopt.c_lflag &= ~ICANON; /* disable canonical input - cannot use with binary input */ + ttyopt.c_lflag &= ~ISIG; /* disable check for INTR, QUIT, SUSP special characters */ + ttyopt.c_lflag &= ~IEXTEN; /* disable any special control character */ + ttyopt.c_lflag &= ~ECHO; /* do not echo back every character typed */ + ttyopt.c_lflag &= ~ECHOE; /* does not erase the last character in current line */ + ttyopt.c_lflag &= ~ECHOK; /* do not echo NL after KILL character */ + + /* settings for non-canonical mode + read will block for until the lesser of VMIN or requested chars have been received */ + ttyopt.c_cc[VMIN] = LGW_GPS_MIN_MSG_SIZE; + ttyopt.c_cc[VTIME] = 0; + + /* set new serial ports parameters */ + i = tcsetattr(gps_tty_dev, TCSANOW, &ttyopt); + if (i != 0){ + DEBUG_MSG("ERROR: IMPOSSIBLE TO UPDATE TTY PORT CONFIGURATION\n"); + return LGW_GPS_ERROR; + } + tcflush(gps_tty_dev, TCIOFLUSH); + + /* Send UBX CFG NAV-TIMEGPS message to tell GPS module to output native GPS time */ + /* This is a binary message, serial port has to be properly configured to handle this */ +#endif + num_written = write (gps_tty_dev, ubx_cmd_timegps, UBX_MSG_NAVTIMEGPS_LEN); + if (num_written != UBX_MSG_NAVTIMEGPS_LEN) { + DEBUG_MSG("ERROR: Failed to write on serial port (written=%d)\n", (int) num_written); + } + /* get timezone info */ + tzset(); + + /* initialize global variables */ + gps_time_ok = false; + gps_pos_ok = false; + gps_mod = 'N'; + + return LGW_GPS_SUCCESS; +} + +/* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ */ + +int lgw_gps_disable(int fd) { + int i; + + /* restore serial ports parameters */ + i = tcsetattr(fd, TCSANOW, &ttyopt_restore); + if (i != 0){ + DEBUG_MSG("ERROR: IMPOSSIBLE TO RESTORE TTY PORT CONFIGURATION\n"); + return LGW_GPS_ERROR; + } + tcflush(fd, TCIOFLUSH); + + i = close(fd); + if (i <= 0) { + DEBUG_MSG("ERROR: TTY PORT FAIL TO CLOSE\n"); + return LGW_GPS_ERROR; + } + + return LGW_GPS_SUCCESS; +} + +/* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ */ + +enum gps_msg lgw_parse_ubx(const char *serial_buff, size_t buff_size, size_t *msg_size) { + bool valid = 0; /* iTOW, fTOW and week validity */ + unsigned int payload_length; + uint8_t ck_a, ck_b; + uint8_t ck_a_rcv, ck_b_rcv; + unsigned int i; + + *msg_size = 0; /* ensure msg_size alway receives a value */ + + /* check input parameters */ + if (serial_buff == NULL) { + return IGNORED; + } + if (buff_size < 8) { + DEBUG_MSG("ERROR: TOO SHORT TO BE A VALID UBX MESSAGE\n"); + return IGNORED; + } + + /* display received serial data and checksum */ + DEBUG_MSG("Note: parsing UBX frame> "); + for (i=0; i (int)(sizeof(parser_buf) - 1)) { + DEBUG_MSG("Note: input string to big for parsing\n"); + return INVALID; + } + + /* look for some NMEA sentences in particular */ + if (buff_size < 8) { + DEBUG_MSG("ERROR: TOO SHORT TO BE A VALID NMEA SENTENCE\n"); + return UNKNOWN; + } else if (!validate_nmea_checksum(serial_buff, buff_size)) { + DEBUG_MSG("Warning: invalid NMEA sentence (bad checksum)\n"); + return INVALID; + } else if (match_label(serial_buff, "$G?RMC", 6, '?')) { + /* + NMEA sentence format: $xxRMC,time,status,lat,NS,long,EW,spd,cog,date,mv,mvEW,posMode*cs + Valid fix: $GPRMC,083559.34,A,4717.11437,N,00833.91522,E,0.004,77.52,091202,,,A*00 + No fix: $GPRMC,,V,,,,,,,,,,N*00 + */ + memcpy(parser_buf, serial_buff, buff_size); + parser_buf[buff_size] = '\0'; + nb_fields = str_chop(parser_buf, buff_size, ',', str_index, ARRAY_SIZE(str_index)); + if (nb_fields != 13) { + DEBUG_MSG("Warning: invalid RMC sentence (number of fields)\n"); + return IGNORED; + } + /* parse GPS status */ + gps_mod = *(parser_buf + str_index[12]); /* get first character, no need to bother with sscanf */ + if ((gps_mod != 'N') && (gps_mod != 'A') && (gps_mod != 'D')) { + gps_mod = 'N'; + } + /* parse complete time */ + i = sscanf(parser_buf + str_index[1], "%2hd%2hd%2hd%4f", &gps_hou, &gps_min, &gps_sec, &gps_fra); + j = sscanf(parser_buf + str_index[9], "%2hd%2hd%2hd", &gps_day, &gps_mon, &gps_yea); + if ((i == 4) && (j == 3)) { + if ((gps_mod == 'A') || (gps_mod == 'D')) { + gps_time_ok = true; + DEBUG_MSG("Note: Valid RMC sentence, GPS locked, date: 20%02d-%02d-%02dT%02d:%02d:%06.3fZ\n", gps_yea, gps_mon, gps_day, gps_hou, gps_min, gps_fra + (float)gps_sec); + } else { + gps_time_ok = false; + DEBUG_MSG("Note: Valid RMC sentence, no satellite fix, estimated date: 20%02d-%02d-%02dT%02d:%02d:%06.3fZ\n", gps_yea, gps_mon, gps_day, gps_hou, gps_min, gps_fra + (float)gps_sec); + } + } else { + /* could not get a valid hour AND date */ + gps_time_ok = false; + DEBUG_MSG("Note: Valid RMC sentence, mode %c, no date\n", gps_mod); + } + return NMEA_RMC; + } else if (match_label(serial_buff, "$G?GGA", 6, '?')) { + /* + NMEA sentence format: $xxGGA,time,lat,NS,long,EW,quality,numSV,HDOP,alt,M,sep,M,diffAge,diffStation*cs + Valid fix: $GPGGA,092725.00,4717.11399,N,00833.91590,E,1,08,1.01,499.6,M,48.0,M,,*5B + */ + memcpy(parser_buf, serial_buff, buff_size); + parser_buf[buff_size] = '\0'; + nb_fields = str_chop(parser_buf, buff_size, ',', str_index, ARRAY_SIZE(str_index)); + if (nb_fields != 15) { + DEBUG_MSG("Warning: invalid GGA sentence (number of fields)\n"); + return IGNORED; + } + /* parse number of satellites used for fix */ + sscanf(parser_buf + str_index[7], "%hd", &gps_sat); + /* parse 3D coordinates */ + i = sscanf(parser_buf + str_index[2], "%2hd%10lf", &gps_dla, &gps_mla); + gps_ola = *(parser_buf + str_index[3]); + j = sscanf(parser_buf + str_index[4], "%3hd%10lf", &gps_dlo, &gps_mlo); + gps_olo = *(parser_buf + str_index[5]); + k = sscanf(parser_buf + str_index[9], "%hd", &gps_alt); + if ((i == 2) && (j == 2) && (k == 1) && ((gps_ola=='N')||(gps_ola=='S')) && ((gps_olo=='E')||(gps_olo=='W'))) { + gps_pos_ok = true; + DEBUG_MSG("Note: Valid GGA sentence, %d sat, lat %02ddeg %06.3fmin %c, lon %03ddeg%06.3fmin %c, alt %d\n", gps_sat, gps_dla, gps_mla, gps_ola, gps_dlo, gps_mlo, gps_olo, gps_alt); + } else { + /* could not get a valid latitude, longitude AND altitude */ + gps_pos_ok = false; + DEBUG_MSG("Note: Valid GGA sentence, %d sat, no coordinates\n", gps_sat); + } + return NMEA_GGA; + } else { + DEBUG_MSG("Note: ignored NMEA sentence\n"); /* quite verbose */ + return IGNORED; + } +} + +/* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ */ + +int lgw_gps_get(struct timespec *utc, struct timespec *gps_time, struct coord_s *loc, struct coord_s *err) { + struct tm x; + time_t y; + double intpart, fractpart; + + if (utc != NULL) { + if (!gps_time_ok) { + DEBUG_MSG("ERROR: NO VALID TIME TO RETURN\n"); + return LGW_GPS_ERROR; + } + memset(&x, 0, sizeof(x)); + if (gps_yea < 100) { /* 2-digits year, 20xx */ + x.tm_year = gps_yea + 100; /* 100 years offset to 1900 */ + } else { /* 4-digits year, Gregorian calendar */ + x.tm_year = gps_yea - 1900; + } + x.tm_mon = gps_mon - 1; /* tm_mon is [0,11], gps_mon is [1,12] */ + x.tm_mday = gps_day; + x.tm_hour = gps_hou; + x.tm_min = gps_min; + x.tm_sec = gps_sec; + y = mktime(&x) - timezone; /* need to substract timezone bc mktime assumes time vector is local time */ + if (y == (time_t)(-1)) { + DEBUG_MSG("ERROR: FAILED TO CONVERT BROKEN-DOWN TIME\n"); + return LGW_GPS_ERROR; + } + utc->tv_sec = y; + utc->tv_nsec = (int32_t)(gps_fra * 1e9); + } + if (gps_time != NULL) { + if (!gps_time_ok) { + DEBUG_MSG("ERROR: NO VALID TIME TO RETURN\n"); + return LGW_GPS_ERROR; + } + fractpart = modf(((double)gps_iTOW / 1E3) + ((double)gps_fTOW / 1E9), &intpart); + /* Number of seconds since beginning on current GPS week */ + gps_time->tv_sec = (time_t)intpart; + /* Number of seconds since GPS epoch 06.Jan.1980 */ + gps_time->tv_sec += (time_t)gps_week * 604800; /* day*hours*minutes*secondes: 7*24*60*60; */ + /* Fractional part in nanoseconds */ + gps_time->tv_nsec = (long)(fractpart * 1E9); + } + if (loc != NULL) { + if (!gps_pos_ok) { + DEBUG_MSG("ERROR: NO VALID POSITION TO RETURN\n"); + return LGW_GPS_ERROR; + } + loc->lat = ((double)gps_dla + (gps_mla/60.0)) * ((gps_ola == 'N')?1.0:-1.0); + loc->lon = ((double)gps_dlo + (gps_mlo/60.0)) * ((gps_olo == 'E')?1.0:-1.0); + loc->alt = gps_alt; + } + if (err != NULL) { + DEBUG_MSG("Warning: localization error processing not implemented yet\n"); + err->lat = 0.0; + err->lon = 0.0; + err->alt = 0; + } + + return LGW_GPS_SUCCESS; +} + +/* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ */ + +int lgw_gps_sync(struct tref *ref, uint32_t count_us, struct timespec utc, struct timespec gps_time) { + double cnt_diff; /* internal concentrator time difference (in seconds) */ + double utc_diff; /* UTC time difference (in seconds) */ + double slope; /* time slope between new reference and old reference (for sanity check) */ + + bool aber_n0; /* is the update value for synchronization aberrant or not ? */ + static bool aber_min1 = false; /* keep track of whether value at sync N-1 was aberrant or not */ + static bool aber_min2 = false; /* keep track of whether value at sync N-2 was aberrant or not */ + + CHECK_NULL(ref); + + /* calculate the slope */ + + cnt_diff = (double)(count_us - ref->count_us) / (double)(TS_CPS); /* uncorrected by xtal_err */ + utc_diff = (double)(utc.tv_sec - (ref->utc).tv_sec) + (1E-9 * (double)(utc.tv_nsec - (ref->utc).tv_nsec)); + + /* detect aberrant points by measuring if slope limits are exceeded */ + if (utc_diff != 0) { // prevent divide by zero + slope = cnt_diff/utc_diff; + if ((slope > PLUS_10PPM) || (slope < MINUS_10PPM)) { + DEBUG_MSG("Warning: correction range exceeded\n"); + aber_n0 = true; + } else { + aber_n0 = false; + } + } else { + DEBUG_MSG("Warning: aberrant UTC value for synchronization\n"); + aber_n0 = true; + } + + /* watch if the 3 latest sync point were aberrant or not */ + if (aber_n0 == false) { + /* value no aberrant -> sync with smoothed slope */ + ref->systime = time(NULL); + ref->count_us = count_us; + ref->utc.tv_sec = utc.tv_sec; + ref->utc.tv_nsec = utc.tv_nsec; + ref->gps.tv_sec = gps_time.tv_sec; + ref->gps.tv_nsec = gps_time.tv_nsec; + ref->xtal_err = slope; + aber_min2 = aber_min1; + aber_min1 = aber_n0; + return LGW_GPS_SUCCESS; + } else if (aber_n0 && aber_min1 && aber_min2) { + /* 3 successive aberrant values -> sync reset (keep xtal_err) */ + ref->systime = time(NULL); + ref->count_us = count_us; + ref->utc.tv_sec = utc.tv_sec; + ref->utc.tv_nsec = utc.tv_nsec; + ref->gps.tv_sec = gps_time.tv_sec; + ref->gps.tv_nsec = gps_time.tv_nsec; + /* reset xtal_err only if the present value is out of range */ + if ((ref->xtal_err > PLUS_10PPM) || (ref->xtal_err < MINUS_10PPM)) { + ref->xtal_err = 1.0; + } + DEBUG_MSG("Warning: 3 successive aberrant sync attempts, sync reset\n"); + aber_min2 = aber_min1; + aber_min1 = aber_n0; + return LGW_GPS_SUCCESS; + } else { + /* only 1 or 2 successive aberrant values -> ignore and return an error */ + aber_min2 = aber_min1; + aber_min1 = aber_n0; + return LGW_GPS_ERROR; + } + + return LGW_GPS_SUCCESS; +} + +/* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ */ + +int lgw_cnt2utc(struct tref ref, uint32_t count_us, struct timespec *utc) { + double delta_sec; + double intpart, fractpart; + long tmp; + + CHECK_NULL(utc); + if ((ref.systime == 0) || (ref.xtal_err > PLUS_10PPM) || (ref.xtal_err < MINUS_10PPM)) { + DEBUG_MSG("ERROR: INVALID REFERENCE FOR CNT -> UTC CONVERSION\n"); + return LGW_GPS_ERROR; + } + + /* calculate delta in seconds between reference count_us and target count_us */ + delta_sec = (double)(count_us - ref.count_us) / (TS_CPS * ref.xtal_err); + + /* now add that delta to reference UTC time */ + fractpart = modf (delta_sec , &intpart); + tmp = ref.utc.tv_nsec + (long)(fractpart * 1E9); + if (tmp < (long)1E9) { /* the nanosecond part doesn't overflow */ + utc->tv_sec = ref.utc.tv_sec + (time_t)intpart; + utc->tv_nsec = tmp; + } else { /* must carry one second */ + utc->tv_sec = ref.utc.tv_sec + (time_t)intpart + 1; + utc->tv_nsec = tmp - (long)1E9; + } + + return LGW_GPS_SUCCESS; +} + +/* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ */ + +int lgw_utc2cnt(struct tref ref, struct timespec utc, uint32_t *count_us) { + double delta_sec; + + CHECK_NULL(count_us); + if ((ref.systime == 0) || (ref.xtal_err > PLUS_10PPM) || (ref.xtal_err < MINUS_10PPM)) { + DEBUG_MSG("ERROR: INVALID REFERENCE FOR UTC -> CNT CONVERSION\n"); + return LGW_GPS_ERROR; + } + + /* calculate delta in seconds between reference utc and target utc */ + delta_sec = (double)(utc.tv_sec - ref.utc.tv_sec); + delta_sec += 1E-9 * (double)(utc.tv_nsec - ref.utc.tv_nsec); + + /* now convert that to internal counter tics and add that to reference counter value */ + *count_us = ref.count_us + (uint32_t)(delta_sec * TS_CPS * ref.xtal_err); + + return LGW_GPS_SUCCESS; +} + +/* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ */ + +int lgw_cnt2gps(struct tref ref, uint32_t count_us, struct timespec *gps_time) { + double delta_sec; + double intpart, fractpart; + long tmp; + + CHECK_NULL(gps_time); + if ((ref.systime == 0) || (ref.xtal_err > PLUS_10PPM) || (ref.xtal_err < MINUS_10PPM)) { + DEBUG_MSG("ERROR: INVALID REFERENCE FOR CNT -> GPS CONVERSION\n"); + return LGW_GPS_ERROR; + } + + /* calculate delta in milliseconds between reference count_us and target count_us */ + delta_sec = (double)(count_us - ref.count_us) / (TS_CPS * ref.xtal_err); + + /* now add that delta to reference GPS time */ + fractpart = modf (delta_sec , &intpart); + tmp = ref.gps.tv_nsec + (long)(fractpart * 1E9); + if (tmp < (long)1E9) { /* the nanosecond part doesn't overflow */ + gps_time->tv_sec = ref.gps.tv_sec + (time_t)intpart; + gps_time->tv_nsec = tmp; + } else { /* must carry one second */ + gps_time->tv_sec = ref.gps.tv_sec + (time_t)intpart + 1; + gps_time->tv_nsec = tmp - (long)1E9; + } + + return LGW_GPS_SUCCESS; +} + +/* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ */ + +int lgw_gps2cnt(struct tref ref, struct timespec gps_time, uint32_t *count_us) { + double delta_sec; + + CHECK_NULL(count_us); + if ((ref.systime == 0) || (ref.xtal_err > PLUS_10PPM) || (ref.xtal_err < MINUS_10PPM)) { + DEBUG_MSG("ERROR: INVALID REFERENCE FOR GPS -> CNT CONVERSION\n"); + return LGW_GPS_ERROR; + } + + /* calculate delta in seconds between reference gps time and target gps time */ + delta_sec = (double)(gps_time.tv_sec - ref.gps.tv_sec); + delta_sec += 1E-9 * (double)(gps_time.tv_nsec - ref.gps.tv_nsec); + + /* now convert that to internal counter tics and add that to reference counter value */ + *count_us = ref.count_us + (uint32_t)(delta_sec * TS_CPS * ref.xtal_err); + + return LGW_GPS_SUCCESS; +} + +/* --- EOF ------------------------------------------------------------------ */ diff --git a/lora/rak7243/loragw_spi.native.c b/lora/rak7243/loragw_spi.native.c new file mode 100644 index 0000000..a4f4b01 --- /dev/null +++ b/lora/rak7243/loragw_spi.native.c @@ -0,0 +1,385 @@ +/* + / _____) _ | | +( (____ _____ ____ _| |_ _____ ____| |__ + \____ \| ___ | (_ _) ___ |/ ___) _ \ + _____) ) ____| | | || |_| ____( (___| | | | +(______/|_____)_|_|_| \__)_____)\____)_| |_| + (C)2013 Semtech-Cycleo + +Description: + Host specific functions to address the LoRa concentrator registers through + a SPI interface. + Single-byte read/write and burst read/write. + Does not handle pagination. + Could be used with multiple SPI ports in parallel (explicit file descriptor) + +License: Revised BSD License, see LICENSE.TXT file include in the project +Maintainer: Sylvain Miermont +*/ + + +/* -------------------------------------------------------------------------- */ +/* --- DEPENDANCIES --------------------------------------------------------- */ + +#include /* C99 types */ +#include /* printf fprintf */ +#include /* malloc free */ +#include /* lseek, close */ +#include /* open */ +#include /* memset */ + +#include +#include + +#include "loragw_spi.h" +#include "loragw_hal.h" + +/* -------------------------------------------------------------------------- */ +/* --- PRIVATE MACROS ------------------------------------------------------- */ + +#define ARRAY_SIZE(a) (sizeof(a) / sizeof((a)[0])) +#if DEBUG_SPI == 1 + #define DEBUG_MSG(str) fprintf(stderr, str) + #define DEBUG_PRINTF(fmt, args...) fprintf(stderr,"%s:%d: "fmt, __FUNCTION__, __LINE__, args) + #define CHECK_NULL(a) if(a==NULL){fprintf(stderr,"%s:%d: ERROR: NULL POINTER AS ARGUMENT\n", __FUNCTION__, __LINE__);return LGW_SPI_ERROR;} +#else + #define DEBUG_MSG(str) + #define DEBUG_PRINTF(fmt, args...) + #define CHECK_NULL(a) if(a==NULL){return LGW_SPI_ERROR;} +#endif + +/* -------------------------------------------------------------------------- */ +/* --- PRIVATE CONSTANTS ---------------------------------------------------- */ + +#define READ_ACCESS 0x00 +#define WRITE_ACCESS 0x80 +#define SPI_SPEED 2000000 +#define SPI_DEV_PATH "/dev/spidev0.0" +//#define SPI_DEV_PATH "/dev/spidev32766.0" + +/* -------------------------------------------------------------------------- */ +/* --- PUBLIC FUNCTIONS DEFINITION ------------------------------------------ */ + +/* SPI initialization and configuration */ +int lgw_spi_open(void **spi_target_ptr) { + int *spi_device = NULL; + int dev; + int a=0, b=0; + int i; + + /* check input variables */ + CHECK_NULL(spi_target_ptr); /* cannot be null, must point on a void pointer (*spi_target_ptr can be null) */ + + /* allocate memory for the device descriptor */ + spi_device = malloc(sizeof(int)); + if (spi_device == NULL) { + DEBUG_MSG("ERROR: MALLOC FAIL\n"); + return LGW_SPI_ERROR; + } + + /* open SPI device */ + dev = open(SPI_DEV_PATH, O_RDWR); + if (dev < 0) { + DEBUG_PRINTF("ERROR: failed to open SPI device %s\n", SPI_DEV_PATH); + return LGW_SPI_ERROR; + } + + /* setting SPI mode to 'mode 0' */ + i = SPI_MODE_0; + a = ioctl(dev, SPI_IOC_WR_MODE, &i); + b = ioctl(dev, SPI_IOC_RD_MODE, &i); + if ((a < 0) || (b < 0)) { + DEBUG_MSG("ERROR: SPI PORT FAIL TO SET IN MODE 0\n"); + close(dev); + free(spi_device); + return LGW_SPI_ERROR; + } + + /* setting SPI max clk (in Hz) */ + i = SPI_SPEED; + a = ioctl(dev, SPI_IOC_WR_MAX_SPEED_HZ, &i); + b = ioctl(dev, SPI_IOC_RD_MAX_SPEED_HZ, &i); + if ((a < 0) || (b < 0)) { + DEBUG_MSG("ERROR: SPI PORT FAIL TO SET MAX SPEED\n"); + close(dev); + free(spi_device); + return LGW_SPI_ERROR; + } + + /* setting SPI to MSB first */ + i = 0; + a = ioctl(dev, SPI_IOC_WR_LSB_FIRST, &i); + b = ioctl(dev, SPI_IOC_RD_LSB_FIRST, &i); + if ((a < 0) || (b < 0)) { + DEBUG_MSG("ERROR: SPI PORT FAIL TO SET MSB FIRST\n"); + close(dev); + free(spi_device); + return LGW_SPI_ERROR; + } + + /* setting SPI to 8 bits per word */ + i = 0; + a = ioctl(dev, SPI_IOC_WR_BITS_PER_WORD, &i); + b = ioctl(dev, SPI_IOC_RD_BITS_PER_WORD, &i); + if ((a < 0) || (b < 0)) { + DEBUG_MSG("ERROR: SPI PORT FAIL TO SET 8 BITS-PER-WORD\n"); + close(dev); + return LGW_SPI_ERROR; + } + + *spi_device = dev; + *spi_target_ptr = (void *)spi_device; + DEBUG_MSG("Note: SPI port opened and configured ok\n"); + return LGW_SPI_SUCCESS; +} + +/* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ */ + +/* SPI release */ +int lgw_spi_close(void *spi_target) { + int spi_device; + int a; + + /* check input variables */ + CHECK_NULL(spi_target); + + /* close file & deallocate file descriptor */ + spi_device = *(int *)spi_target; /* must check that spi_target is not null beforehand */ + a = close(spi_device); + free(spi_target); + + /* determine return code */ + if (a < 0) { + DEBUG_MSG("ERROR: SPI PORT FAILED TO CLOSE\n"); + return LGW_SPI_ERROR; + } else { + DEBUG_MSG("Note: SPI port closed\n"); + return LGW_SPI_SUCCESS; + } +} + +/* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ */ + +/* Simple write */ +int lgw_spi_w(void *spi_target, uint8_t spi_mux_mode, uint8_t spi_mux_target, uint8_t address, uint8_t data) { + int spi_device; + uint8_t out_buf[3]; + uint8_t command_size; + struct spi_ioc_transfer k; + int a; + + /* check input variables */ + CHECK_NULL(spi_target); + if ((address & 0x80) != 0) { + DEBUG_MSG("WARNING: SPI address > 127\n"); + } + + spi_device = *(int *)spi_target; /* must check that spi_target is not null beforehand */ + + /* prepare frame to be sent */ + if (spi_mux_mode == LGW_SPI_MUX_MODE1) { + out_buf[0] = spi_mux_target; + out_buf[1] = WRITE_ACCESS | (address & 0x7F); + out_buf[2] = data; + command_size = 3; + } else { + out_buf[0] = WRITE_ACCESS | (address & 0x7F); + out_buf[1] = data; + command_size = 2; + } + + /* I/O transaction */ + memset(&k, 0, sizeof(k)); /* clear k */ + k.tx_buf = (unsigned long) out_buf; + k.len = command_size; + k.speed_hz = SPI_SPEED; + k.cs_change = 0; + k.bits_per_word = 8; + a = ioctl(spi_device, SPI_IOC_MESSAGE(1), &k); + + /* determine return code */ + if (a != (int)k.len) { + DEBUG_MSG("ERROR: SPI WRITE FAILURE\n"); + return LGW_SPI_ERROR; + } else { + DEBUG_MSG("Note: SPI write success\n"); + return LGW_SPI_SUCCESS; + } +} + +/* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ */ + +/* Simple read */ +int lgw_spi_r(void *spi_target, uint8_t spi_mux_mode, uint8_t spi_mux_target, uint8_t address, uint8_t *data) { + int spi_device; + uint8_t out_buf[3]; + uint8_t command_size; + uint8_t in_buf[ARRAY_SIZE(out_buf)]; + struct spi_ioc_transfer k; + int a; + + /* check input variables */ + CHECK_NULL(spi_target); + if ((address & 0x80) != 0) { + DEBUG_MSG("WARNING: SPI address > 127\n"); + } + CHECK_NULL(data); + + spi_device = *(int *)spi_target; /* must check that spi_target is not null beforehand */ + + /* prepare frame to be sent */ + if (spi_mux_mode == LGW_SPI_MUX_MODE1) { + out_buf[0] = spi_mux_target; + out_buf[1] = READ_ACCESS | (address & 0x7F); + out_buf[2] = 0x00; + command_size = 3; + } else { + out_buf[0] = READ_ACCESS | (address & 0x7F); + out_buf[1] = 0x00; + command_size = 2; + } + + /* I/O transaction */ + memset(&k, 0, sizeof(k)); /* clear k */ + k.tx_buf = (unsigned long) out_buf; + k.rx_buf = (unsigned long) in_buf; + k.len = command_size; + k.cs_change = 0; + a = ioctl(spi_device, SPI_IOC_MESSAGE(1), &k); + + /* determine return code */ + if (a != (int)k.len) { + DEBUG_MSG("ERROR: SPI READ FAILURE\n"); + return LGW_SPI_ERROR; + } else { + DEBUG_MSG("Note: SPI read success\n"); + *data = in_buf[command_size - 1]; + return LGW_SPI_SUCCESS; + } +} + +/* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ */ + +/* Burst (multiple-byte) write */ +int lgw_spi_wb(void *spi_target, uint8_t spi_mux_mode, uint8_t spi_mux_target, uint8_t address, uint8_t *data, uint16_t size) { + int spi_device; + uint8_t command[2]; + uint8_t command_size; + struct spi_ioc_transfer k[2]; + int size_to_do, chunk_size, offset; + int byte_transfered = 0; + int i; + + /* check input parameters */ + CHECK_NULL(spi_target); + if ((address & 0x80) != 0) { + DEBUG_MSG("WARNING: SPI address > 127\n"); + } + CHECK_NULL(data); + if (size == 0) { + DEBUG_MSG("ERROR: BURST OF NULL LENGTH\n"); + return LGW_SPI_ERROR; + } + + spi_device = *(int *)spi_target; /* must check that spi_target is not null beforehand */ + + /* prepare command byte */ + if (spi_mux_mode == LGW_SPI_MUX_MODE1) { + command[0] = spi_mux_target; + command[1] = WRITE_ACCESS | (address & 0x7F); + command_size = 2; + } else { + command[0] = WRITE_ACCESS | (address & 0x7F); + command_size = 1; + } + size_to_do = size; + + /* I/O transaction */ + memset(&k, 0, sizeof(k)); /* clear k */ + k[0].tx_buf = (unsigned long) &command[0]; + k[0].len = command_size; + k[0].cs_change = 0; + k[1].cs_change = 0; + for (i=0; size_to_do > 0; ++i) { + chunk_size = (size_to_do < LGW_BURST_CHUNK) ? size_to_do : LGW_BURST_CHUNK; + offset = i * LGW_BURST_CHUNK; + k[1].tx_buf = (unsigned long)(data + offset); + k[1].len = chunk_size; + byte_transfered += (ioctl(spi_device, SPI_IOC_MESSAGE(2), &k) - k[0].len ); + DEBUG_PRINTF("BURST WRITE: to trans %d # chunk %d # transferred %d \n", size_to_do, chunk_size, byte_transfered); + size_to_do -= chunk_size; /* subtract the quantity of data already transferred */ + } + + /* determine return code */ + if (byte_transfered != size) { + DEBUG_MSG("ERROR: SPI BURST WRITE FAILURE\n"); + return LGW_SPI_ERROR; + } else { + DEBUG_MSG("Note: SPI burst write success\n"); + return LGW_SPI_SUCCESS; + } +} + +/* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ */ + +/* Burst (multiple-byte) read */ +int lgw_spi_rb(void *spi_target, uint8_t spi_mux_mode, uint8_t spi_mux_target, uint8_t address, uint8_t *data, uint16_t size) { + int spi_device; + uint8_t command[2]; + uint8_t command_size; + struct spi_ioc_transfer k[2]; + int size_to_do, chunk_size, offset; + int byte_transfered = 0; + int i; + + /* check input parameters */ + CHECK_NULL(spi_target); + if ((address & 0x80) != 0) { + DEBUG_MSG("WARNING: SPI address > 127\n"); + } + CHECK_NULL(data); + if (size == 0) { + DEBUG_MSG("ERROR: BURST OF NULL LENGTH\n"); + return LGW_SPI_ERROR; + } + + spi_device = *(int *)spi_target; /* must check that spi_target is not null beforehand */ + + /* prepare command byte */ + if (spi_mux_mode == LGW_SPI_MUX_MODE1) { + command[0] = spi_mux_target; + command[1] = READ_ACCESS | (address & 0x7F); + command_size = 2; + } else { + command[0] = READ_ACCESS | (address & 0x7F); + command_size = 1; + } + size_to_do = size; + + /* I/O transaction */ + memset(&k, 0, sizeof(k)); /* clear k */ + k[0].tx_buf = (unsigned long) &command[0]; + k[0].len = command_size; + k[0].cs_change = 0; + k[1].cs_change = 0; + for (i=0; size_to_do > 0; ++i) { + chunk_size = (size_to_do < LGW_BURST_CHUNK) ? size_to_do : LGW_BURST_CHUNK; + offset = i * LGW_BURST_CHUNK; + k[1].rx_buf = (unsigned long)(data + offset); + k[1].len = chunk_size; + byte_transfered += (ioctl(spi_device, SPI_IOC_MESSAGE(2), &k) - k[0].len ); + DEBUG_PRINTF("BURST READ: to trans %d # chunk %d # transferred %d \n", size_to_do, chunk_size, byte_transfered); + size_to_do -= chunk_size; /* subtract the quantity of data already transferred */ + } + + /* determine return code */ + if (byte_transfered != size) { + DEBUG_MSG("ERROR: SPI BURST READ FAILURE\n"); + return LGW_SPI_ERROR; + } else { + DEBUG_MSG("Note: SPI burst read success\n"); + return LGW_SPI_SUCCESS; + } +} + +/* --- EOF ------------------------------------------------------------------ */ diff --git a/lora/rak7243/ppp.sh b/lora/rak7243/ppp.sh new file mode 100755 index 0000000..e200683 --- /dev/null +++ b/lora/rak7243/ppp.sh @@ -0,0 +1,16 @@ +#!/bin/bash + +while [ true=true ] +do +# echo aaa + line=`ifconfig | grep ppp0 -c` +# echo $line + + if [ $line -ne 0 ]; then +# echo "111" + route del default + route add default dev ppp0 + exit + fi + sleep 30 +done diff --git a/lora/rak7243/test_loragw_gps.c b/lora/rak7243/test_loragw_gps.c new file mode 100644 index 0000000..d652343 --- /dev/null +++ b/lora/rak7243/test_loragw_gps.c @@ -0,0 +1,288 @@ +/* + / _____) _ | | +( (____ _____ ____ _| |_ _____ ____| |__ + \____ \| ___ | (_ _) ___ |/ ___) _ \ + _____) ) ____| | | || |_| ____( (___| | | | +(______/|_____)_|_|_| \__)_____)\____)_| |_| + (C)2013 Semtech-Cycleo + +Description: + Minimum test program for the loragw_gps 'library' + +License: Revised BSD License, see LICENSE.TXT file include in the project +Maintainer: Michael Coracin +*/ + + +/* -------------------------------------------------------------------------- */ +/* --- DEPENDANCIES --------------------------------------------------------- */ + +/* fix an issue between POSIX and C99 */ +#if __STDC_VERSION__ >= 199901L + #define _XOPEN_SOURCE 600 +#else + #define _XOPEN_SOURCE 500 +#endif + +#include /* C99 types */ +#include /* bool type */ +#include /* printf */ +#include /* memset */ +#include /* sigaction */ +#include /* exit */ +#include /* read */ + +#include "loragw_hal.h" +#include "loragw_gps.h" +#include "loragw_aux.h" + +/* -------------------------------------------------------------------------- */ +/* --- PRIVATE VARIABLES ---------------------------------------------------- */ + +static int exit_sig = 0; /* 1 -> application terminates cleanly (shut down hardware, close open files, etc) */ +static int quit_sig = 0; /* 1 -> application terminates without shutting down the hardware */ + +struct tref ppm_ref; + +/* -------------------------------------------------------------------------- */ +/* --- PRIVATE FUNCTIONS DECLARATION ---------------------------------------- */ + +static void sig_handler(int sigio); +static void gps_process_sync(void); +static void gps_process_coords(void); + +/* -------------------------------------------------------------------------- */ +/* --- PRIVATE FUNCTIONS DEFINITION ----------------------------------------- */ + +static void sig_handler(int sigio) { + if (sigio == SIGQUIT) { + quit_sig = 1;; + } else if ((sigio == SIGINT) || (sigio == SIGTERM)) { + exit_sig = 1; + } +} + +static void gps_process_sync(void) { + /* variables for PPM pulse GPS synchronization */ + uint32_t ppm_tstamp; + struct timespec ppm_gps; + struct timespec ppm_utc; + + /* variables for timestamp <-> GPS time conversions */ + uint32_t x, z; + struct timespec y; + + /* get GPS time for synchronization */ + int i = lgw_gps_get(&ppm_utc, &ppm_gps, NULL, NULL); + if (i != LGW_GPS_SUCCESS) { + printf(" No valid reference GPS time available, synchronization impossible.\n"); + return; + } + + /* get timestamp for synchronization */ + i = lgw_get_trigcnt(&ppm_tstamp); + if (i != LGW_HAL_SUCCESS) { + printf(" Failed to read timestamp, synchronization impossible.\n"); + return; + } + + /* try to update synchronize time reference with the new GPS & timestamp */ + i = lgw_gps_sync(&ppm_ref, ppm_tstamp, ppm_utc, ppm_gps); + if (i != LGW_GPS_SUCCESS) { + printf(" Synchronization error.\n"); + return; + } + + /* display result */ + printf(" * Synchronization successful *\n"); + printf(" UTC reference time: %lld.%09ld\n", (long long)ppm_ref.utc.tv_sec, ppm_ref.utc.tv_nsec); + printf(" GPS reference time: %lld.%09ld\n", (long long)ppm_ref.gps.tv_sec, ppm_ref.gps.tv_nsec); + printf(" Internal counter reference value: %u\n", ppm_ref.count_us); + printf(" Clock error: %.9f\n", ppm_ref.xtal_err); + + x = ppm_tstamp + 500000; + printf(" * Test of timestamp counter <-> GPS value conversion *\n"); + printf(" Test value: %u\n", x); + lgw_cnt2gps(ppm_ref, x, &y); + printf(" Conversion to GPS: %lld.%09ld\n", (long long)y.tv_sec, y.tv_nsec); + lgw_gps2cnt(ppm_ref, y, &z); + printf(" Converted back: %u ==> %dµs\n", z, (int32_t)(z-x)); + printf(" * Test of timestamp counter <-> UTC value conversion *\n"); + printf(" Test value: %u\n", x); + lgw_cnt2utc(ppm_ref, x, &y); + printf(" Conversion to UTC: %lld.%09ld\n", (long long)y.tv_sec, y.tv_nsec); + lgw_utc2cnt(ppm_ref, y, &z); + printf(" Converted back: %u ==> %dµs\n", z, (int32_t)(z-x)); +} + +static void gps_process_coords(void) { + /* position variable */ + struct coord_s coord; + struct coord_s gpserr; + int i = lgw_gps_get(NULL, NULL, &coord, &gpserr); + + /* update gateway coordinates */ + if (i == LGW_GPS_SUCCESS) { + printf("# GPS coordinates: latitude %.5f, longitude %.5f, altitude %i m\n", coord.lat, coord.lon, coord.alt); + printf("# GPS err: latitude %.5f, longitude %.5f, altitude %i m\n", gpserr.lat, gpserr.lon, gpserr.alt); + } +} + +/* -------------------------------------------------------------------------- */ +/* --- MAIN FUNCTION -------------------------------------------------------- */ + +int main() +{ + struct sigaction sigact; /* SIGQUIT&SIGINT&SIGTERM signal handling */ + + int i; + + /* concentrator variables */ + struct lgw_conf_board_s boardconf; + struct lgw_conf_rxrf_s rfconf; + + /* serial variables */ + char serial_buff[128]; /* buffer to receive GPS data */ + size_t wr_idx = 0; /* pointer to end of chars in buffer */ + int gps_tty_dev; /* file descriptor to the serial port of the GNSS module */ + + /* NMEA/UBX variables */ + enum gps_msg latest_msg; /* keep track of latest NMEA/UBX message parsed */ + + /* configure signal handling */ + sigemptyset(&sigact.sa_mask); + sigact.sa_flags = 0; + sigact.sa_handler = sig_handler; + sigaction(SIGQUIT, &sigact, NULL); + sigaction(SIGINT, &sigact, NULL); + sigaction(SIGTERM, &sigact, NULL); + + /* Intro message and library information */ + printf("Beginning of test for loragw_gps.c\n"); + printf("*** Library version information ***\n%s\n***\n", lgw_version_info()); + + /* Open and configure GPS */ + i = lgw_gps_enable("/dev/i2c-1", "ubx7", 0, &gps_tty_dev); + if (i != LGW_GPS_SUCCESS) { + printf("ERROR: IMPOSSIBLE TO ENABLE GPS\n"); + exit(EXIT_FAILURE); + } + + /* start concentrator (default conf for IoT SK) */ + /* board config */ + memset(&boardconf, 0, sizeof(boardconf)); + boardconf.lorawan_public = true; + boardconf.clksrc = 1; + lgw_board_setconf(boardconf); + + /* RF config */ + memset(&rfconf, 0, sizeof(rfconf)); + rfconf.enable = true; + rfconf.freq_hz = 868000000; + rfconf.rssi_offset = 0.0; + rfconf.type = LGW_RADIO_TYPE_SX1257; + rfconf.tx_enable = true; + lgw_rxrf_setconf(0, rfconf); + + lgw_start(); + + /* initialize some variables before loop */ + memset(serial_buff, 0, sizeof serial_buff); + memset(&ppm_ref, 0, sizeof ppm_ref); + + /* loop until user action */ + while ((quit_sig != 1) && (exit_sig != 1)) { + size_t rd_idx = 0; + size_t frame_end_idx = 0; + + /* blocking non-canonical read on serial port */ + ssize_t nb_char = read(gps_tty_dev, serial_buff + wr_idx, LGW_GPS_MIN_MSG_SIZE); + if (nb_char <= 0) { + printf("WARNING: [gps] read() returned value %d\n", nb_char); + continue; + } + wr_idx += (size_t)nb_char; + + /******************************************* + * Scan buffer for UBX/NMEA sync chars and * + * attempt to decode frame if one is found * + *******************************************/ + while (rd_idx < wr_idx) { + size_t frame_size = 0; + + /* Scan buffer for UBX sync char */ + if (serial_buff[rd_idx] == LGW_GPS_UBX_SYNC_CHAR) { + + /*********************** + * Found UBX sync char * + ***********************/ + latest_msg = lgw_parse_ubx(&serial_buff[rd_idx], (wr_idx - rd_idx), &frame_size); + + if (frame_size > 0) { + if (latest_msg == INCOMPLETE) { + /* UBX header found but frame appears to be missing bytes */ + frame_size = 0; + } else if (latest_msg == INVALID) { + /* message header received but message appears to be corrupted */ + printf("WARNING: [gps] could not get a valid message from GPS (no time)\n"); + frame_size = 0; + } else if (latest_msg == UBX_NAV_TIMEGPS) { + printf("\n~~ UBX NAV-TIMEGPS sentence, triggering synchronization attempt ~~\n"); + gps_process_sync(); + } + } + } else if(serial_buff[rd_idx] == LGW_GPS_NMEA_SYNC_CHAR) { + /************************ + * Found NMEA sync char * + ************************/ + /* scan for NMEA end marker (LF = 0x0a) */ + char* nmea_end_ptr = memchr(&serial_buff[rd_idx],(int)0x0a, (wr_idx - rd_idx)); + + if (nmea_end_ptr) { + /* found end marker */ + frame_size = nmea_end_ptr - &serial_buff[rd_idx] + 1; + latest_msg = lgw_parse_nmea(&serial_buff[rd_idx], frame_size); + + if(latest_msg == INVALID || latest_msg == UNKNOWN) { + /* checksum failed */ + frame_size = 0; + } else if (latest_msg == NMEA_RMC) { /* Get location from RMC frames */ + gps_process_coords(); + } + } + } + + if (frame_size > 0) { + /* At this point message is a checksum verified frame + we're processed or ignored. Remove frame from buffer */ + rd_idx += frame_size; + frame_end_idx = rd_idx; + } else { + rd_idx++; + } + } /* ...for(rd_idx = 0... */ + + if (frame_end_idx) { + /* Frames have been processed. Remove bytes to end of last processed frame */ + memcpy(serial_buff,&serial_buff[frame_end_idx],wr_idx - frame_end_idx); + wr_idx -= frame_end_idx; + } /* ...for(rd_idx = 0... */ + + /* Prevent buffer overflow */ + if ((sizeof(serial_buff) - wr_idx) < LGW_GPS_MIN_MSG_SIZE) { + memcpy(serial_buff,&serial_buff[LGW_GPS_MIN_MSG_SIZE],wr_idx - LGW_GPS_MIN_MSG_SIZE); + wr_idx -= LGW_GPS_MIN_MSG_SIZE; + } + } + + /* clean up before leaving */ + if (exit_sig == 1) { + lgw_gps_disable(gps_tty_dev); + lgw_stop(); + } + + printf("\nEnd of test for loragw_gps.c\n"); + exit(EXIT_SUCCESS); +} + +/* --- EOF ------------------------------------------------------------------ */ diff --git a/lora/set_eui.sh b/lora/set_eui.sh new file mode 100755 index 0000000..1c7c115 --- /dev/null +++ b/lora/set_eui.sh @@ -0,0 +1,18 @@ +#! /bin/bash +GATEWAY_EUI="" +if [ ! -e "/opt/ttn-gateway/packet_forwarder/lora_pkt_fwd/local_conf.json" ]; then + GATEWAY_EUI_NIC="eth0" + if [[ `grep "$GATEWAY_EUI_NIC" /proc/net/dev` == "" ]]; then + GATEWAY_EUI_NIC="wlan0" + fi + + if [[ `grep "$GATEWAY_EUI_NIC" /proc/net/dev` == "" ]]; then + echo "ERROR: No network interface found. Cannot set gateway ID." +# exit 1 + fi + GATEWAY_EUI=$(ip link show $GATEWAY_EUI_NIC | awk '/ether/ {print $2}' | awk -F\: '{print $1$2$3"FFFE"$4$5$6}') + GATEWAY_EUI=${GATEWAY_EUI^^} + LOCAL_CONFIG_FILE=/opt/ttn-gateway/packet_forwarder/lora_pkt_fwd/local_conf.json + echo -e "{\n\t\"gateway_conf\": {\n\t\t\"gateway_ID\": \"$GATEWAY_EUI\" \n\t}\n}" >$LOCAL_CONFIG_FILE + echo "$GATEWAY_EUI" +fi diff --git a/lora/start.sh b/lora/start.sh new file mode 100755 index 0000000..75c8ab3 --- /dev/null +++ b/lora/start.sh @@ -0,0 +1,19 @@ +#! /bin/bash + + +# Reset iC880a PIN +SX1301_RESET_BCM_PIN=17 +echo "$SX1301_RESET_BCM_PIN" > /sys/class/gpio/export +echo "out" > /sys/class/gpio/gpio$SX1301_RESET_BCM_PIN/direction +echo "0" > /sys/class/gpio/gpio$SX1301_RESET_BCM_PIN/value +sleep 0.1 +echo "1" > /sys/class/gpio/gpio$SX1301_RESET_BCM_PIN/value +sleep 0.1 +echo "0" > /sys/class/gpio/gpio$SX1301_RESET_BCM_PIN/value +sleep 0.1 +echo "$SX1301_RESET_BCM_PIN" > /sys/class/gpio/unexport +./set_eui.sh +sleep 0.2 +./update_gwid.sh ./local_conf.json +sleep 0.5 +./lora_pkt_fwd diff --git a/lora/ttn-gateway.service b/lora/ttn-gateway.service new file mode 100644 index 0000000..6eec245 --- /dev/null +++ b/lora/ttn-gateway.service @@ -0,0 +1,12 @@ +[Unit] +Description=The Things Network Gateway + +[Service] +WorkingDirectory=/opt/ttn-gateway/packet_forwarder/lora_pkt_fwd/ +ExecStart=/opt/ttn-gateway/packet_forwarder/lora_pkt_fwd/start.sh +SyslogIdentifier=ttn-gateway +Restart=always +RestartSec=5 + +[Install] +WantedBy=multi-user.target diff --git a/lora/update_gwid.sh b/lora/update_gwid.sh new file mode 100755 index 0000000..5b0bed6 --- /dev/null +++ b/lora/update_gwid.sh @@ -0,0 +1,31 @@ +#!/bin/sh + +# This script is a helper to update the Gateway_ID field of given +# JSON configuration file, as a EUI-64 address generated from the 48-bits MAC +# address of the device it is run from. +# +# Usage examples: +# ./update_gwid.sh ./local_conf.json + +iot_sk_update_gwid() { + # get gateway ID from its MAC address to generate an EUI-64 address + GWID_MIDFIX="fffe" + GWID_BEGIN=$(ip link show eth0 | awk '/ether/ {print $2}' | awk -F\: '{print $1$2$3}') + GWID_END=$(ip link show eth0 | awk '/ether/ {print $2}' | awk -F\: '{print $4$5$6}') + + # replace last 8 digits of default gateway ID by actual GWID, in given JSON configuration file + sed -i 's/\(^\s*"gateway_ID":\s*"\).\{16\}"\s*\(,\?\).*$/\1'${GWID_BEGIN}${GWID_MIDFIX}${GWID_END}'"\2/' $1 + + echo "Gateway_ID set to "$GWID_BEGIN$GWID_MIDFIX$GWID_END" in file "$1 +} + +if [ $# -ne 1 ] +then + echo "Usage: $0 [filename]" + echo " filename: Path to JSON file containing Gateway_ID for packet forwarder" + exit 1 +fi + +iot_sk_update_gwid $1 + +exit 0 diff --git a/loraserver/init_sql.sql b/loraserver/init_sql.sql new file mode 100644 index 0000000..d8fe3c7 --- /dev/null +++ b/loraserver/init_sql.sql @@ -0,0 +1,3044 @@ +-- +-- PostgreSQL database cluster dump +-- + +SET default_transaction_read_only = off; + +SET client_encoding = 'UTF8'; +SET standard_conforming_strings = on; + +-- +-- Roles +-- + +CREATE ROLE loraserver_as; +ALTER ROLE loraserver_as WITH NOSUPERUSER INHERIT NOCREATEROLE NOCREATEDB LOGIN NOREPLICATION NOBYPASSRLS PASSWORD 'md5efa6acb899280a4cfb24ee8fa630b55c'; +CREATE ROLE loraserver_ns; +ALTER ROLE loraserver_ns WITH NOSUPERUSER INHERIT NOCREATEROLE NOCREATEDB LOGIN NOREPLICATION NOBYPASSRLS PASSWORD 'md52a083cb233ff34a5b79014712fef7ad0'; +CREATE ROLE postgres; +ALTER ROLE postgres WITH SUPERUSER INHERIT CREATEROLE CREATEDB LOGIN REPLICATION BYPASSRLS; + + + + + + +-- +-- Database creation +-- + +CREATE DATABASE loraserver_as WITH TEMPLATE = template0 OWNER = loraserver_as; +CREATE DATABASE loraserver_ns WITH TEMPLATE = template0 OWNER = loraserver_ns; +REVOKE CONNECT,TEMPORARY ON DATABASE template1 FROM PUBLIC; +GRANT CONNECT ON DATABASE template1 TO PUBLIC; + + +\connect loraserver_as + +SET default_transaction_read_only = off; + +-- +-- PostgreSQL database dump +-- + +-- Dumped from database version 9.6.13 +-- Dumped by pg_dump version 9.6.13 + +SET statement_timeout = 0; +SET lock_timeout = 0; +SET idle_in_transaction_session_timeout = 0; +SET client_encoding = 'UTF8'; +SET standard_conforming_strings = on; +SELECT pg_catalog.set_config('search_path', '', false); +SET check_function_bodies = false; +SET xmloption = content; +SET client_min_messages = warning; +SET row_security = off; + +-- +-- Name: plpgsql; Type: EXTENSION; Schema: -; Owner: +-- + +CREATE EXTENSION IF NOT EXISTS plpgsql WITH SCHEMA pg_catalog; + + +-- +-- Name: EXTENSION plpgsql; Type: COMMENT; Schema: -; Owner: +-- + +COMMENT ON EXTENSION plpgsql IS 'PL/pgSQL procedural language'; + + +-- +-- Name: hstore; Type: EXTENSION; Schema: -; Owner: +-- + +CREATE EXTENSION IF NOT EXISTS hstore WITH SCHEMA public; + + +-- +-- Name: EXTENSION hstore; Type: COMMENT; Schema: -; Owner: +-- + +COMMENT ON EXTENSION hstore IS 'data type for storing sets of (key, value) pairs'; + + +-- +-- Name: pg_trgm; Type: EXTENSION; Schema: -; Owner: +-- + +CREATE EXTENSION IF NOT EXISTS pg_trgm WITH SCHEMA public; + + +-- +-- Name: EXTENSION pg_trgm; Type: COMMENT; Schema: -; Owner: +-- + +COMMENT ON EXTENSION pg_trgm IS 'text similarity measurement and index searching based on trigrams'; + + +SET default_tablespace = ''; + +SET default_with_oids = false; + +-- +-- Name: application; Type: TABLE; Schema: public; Owner: loraserver_as +-- + +CREATE TABLE public.application ( + id bigint NOT NULL, + name character varying(100) NOT NULL, + description text NOT NULL, + organization_id bigint NOT NULL, + service_profile_id uuid NOT NULL, + payload_codec text DEFAULT ''::text NOT NULL, + payload_encoder_script text DEFAULT ''::text NOT NULL, + payload_decoder_script text DEFAULT ''::text NOT NULL +); + + +ALTER TABLE public.application OWNER TO loraserver_as; + +-- +-- Name: application_id_seq; Type: SEQUENCE; Schema: public; Owner: loraserver_as +-- + +CREATE SEQUENCE public.application_id_seq + START WITH 1 + INCREMENT BY 1 + NO MINVALUE + NO MAXVALUE + CACHE 1; + + +ALTER TABLE public.application_id_seq OWNER TO loraserver_as; + +-- +-- Name: application_id_seq; Type: SEQUENCE OWNED BY; Schema: public; Owner: loraserver_as +-- + +ALTER SEQUENCE public.application_id_seq OWNED BY public.application.id; + + +-- +-- Name: device; Type: TABLE; Schema: public; Owner: loraserver_as +-- + +CREATE TABLE public.device ( + dev_eui bytea NOT NULL, + created_at timestamp with time zone NOT NULL, + updated_at timestamp with time zone NOT NULL, + application_id bigint NOT NULL, + device_profile_id uuid NOT NULL, + name character varying(100) NOT NULL, + description text NOT NULL, + last_seen_at timestamp with time zone, + device_status_battery numeric(5,2), + device_status_margin integer, + latitude double precision, + longitude double precision, + altitude double precision, + device_status_external_power_source boolean NOT NULL, + dr smallint +); + + +ALTER TABLE public.device OWNER TO loraserver_as; + +-- +-- Name: device_activation; Type: TABLE; Schema: public; Owner: loraserver_as +-- + +CREATE TABLE public.device_activation ( + id bigint NOT NULL, + created_at timestamp with time zone NOT NULL, + dev_eui bytea NOT NULL, + dev_addr bytea NOT NULL, + app_s_key bytea NOT NULL +); + + +ALTER TABLE public.device_activation OWNER TO loraserver_as; + +-- +-- Name: device_activation_id_seq; Type: SEQUENCE; Schema: public; Owner: loraserver_as +-- + +CREATE SEQUENCE public.device_activation_id_seq + START WITH 1 + INCREMENT BY 1 + NO MINVALUE + NO MAXVALUE + CACHE 1; + + +ALTER TABLE public.device_activation_id_seq OWNER TO loraserver_as; + +-- +-- Name: device_activation_id_seq; Type: SEQUENCE OWNED BY; Schema: public; Owner: loraserver_as +-- + +ALTER SEQUENCE public.device_activation_id_seq OWNED BY public.device_activation.id; + + +-- +-- Name: device_keys; Type: TABLE; Schema: public; Owner: loraserver_as +-- + +CREATE TABLE public.device_keys ( + dev_eui bytea NOT NULL, + created_at timestamp with time zone NOT NULL, + updated_at timestamp with time zone NOT NULL, + nwk_key bytea NOT NULL, + join_nonce integer NOT NULL, + app_key bytea NOT NULL, + gen_app_key bytea NOT NULL +); + + +ALTER TABLE public.device_keys OWNER TO loraserver_as; + +-- +-- Name: device_multicast_group; Type: TABLE; Schema: public; Owner: loraserver_as +-- + +CREATE TABLE public.device_multicast_group ( + dev_eui bytea NOT NULL, + multicast_group_id uuid NOT NULL, + created_at timestamp with time zone NOT NULL +); + + +ALTER TABLE public.device_multicast_group OWNER TO loraserver_as; + +-- +-- Name: device_profile; Type: TABLE; Schema: public; Owner: loraserver_as +-- + +CREATE TABLE public.device_profile ( + device_profile_id uuid NOT NULL, + network_server_id bigint NOT NULL, + organization_id bigint NOT NULL, + created_at timestamp with time zone NOT NULL, + updated_at timestamp with time zone NOT NULL, + name character varying(100) NOT NULL, + payload_codec text NOT NULL, + payload_encoder_script text NOT NULL, + payload_decoder_script text NOT NULL +); + + +ALTER TABLE public.device_profile OWNER TO loraserver_as; + +-- +-- Name: fuota_deployment; Type: TABLE; Schema: public; Owner: loraserver_as +-- + +CREATE TABLE public.fuota_deployment ( + id uuid NOT NULL, + created_at timestamp with time zone NOT NULL, + updated_at timestamp with time zone NOT NULL, + name character varying(100) NOT NULL, + multicast_group_id uuid, + group_type character(1) NOT NULL, + dr smallint NOT NULL, + frequency integer NOT NULL, + ping_slot_period smallint NOT NULL, + fragmentation_matrix bytea NOT NULL, + descriptor bytea NOT NULL, + payload bytea NOT NULL, + frag_size smallint NOT NULL, + redundancy smallint NOT NULL, + multicast_timeout smallint NOT NULL, + block_ack_delay smallint NOT NULL, + state character varying(20) NOT NULL, + unicast_timeout bigint NOT NULL, + next_step_after timestamp with time zone NOT NULL +); + + +ALTER TABLE public.fuota_deployment OWNER TO loraserver_as; + +-- +-- Name: fuota_deployment_device; Type: TABLE; Schema: public; Owner: loraserver_as +-- + +CREATE TABLE public.fuota_deployment_device ( + fuota_deployment_id uuid NOT NULL, + dev_eui bytea NOT NULL, + created_at timestamp with time zone NOT NULL, + updated_at timestamp with time zone NOT NULL, + state character varying(20) NOT NULL, + error_message text NOT NULL +); + + +ALTER TABLE public.fuota_deployment_device OWNER TO loraserver_as; + +-- +-- Name: gateway; Type: TABLE; Schema: public; Owner: loraserver_as +-- + +CREATE TABLE public.gateway ( + mac bytea NOT NULL, + created_at timestamp with time zone NOT NULL, + updated_at timestamp with time zone NOT NULL, + name character varying(100) NOT NULL, + description text NOT NULL, + organization_id bigint NOT NULL, + ping boolean DEFAULT false NOT NULL, + last_ping_id bigint, + last_ping_sent_at timestamp with time zone, + network_server_id bigint NOT NULL, + gateway_profile_id uuid +); + + +ALTER TABLE public.gateway OWNER TO loraserver_as; + +-- +-- Name: gateway_ping; Type: TABLE; Schema: public; Owner: loraserver_as +-- + +CREATE TABLE public.gateway_ping ( + id bigint NOT NULL, + created_at timestamp with time zone NOT NULL, + gateway_mac bytea NOT NULL, + frequency integer NOT NULL, + dr integer NOT NULL +); + + +ALTER TABLE public.gateway_ping OWNER TO loraserver_as; + +-- +-- Name: gateway_ping_id_seq; Type: SEQUENCE; Schema: public; Owner: loraserver_as +-- + +CREATE SEQUENCE public.gateway_ping_id_seq + START WITH 1 + INCREMENT BY 1 + NO MINVALUE + NO MAXVALUE + CACHE 1; + + +ALTER TABLE public.gateway_ping_id_seq OWNER TO loraserver_as; + +-- +-- Name: gateway_ping_id_seq; Type: SEQUENCE OWNED BY; Schema: public; Owner: loraserver_as +-- + +ALTER SEQUENCE public.gateway_ping_id_seq OWNED BY public.gateway_ping.id; + + +-- +-- Name: gateway_ping_rx; Type: TABLE; Schema: public; Owner: loraserver_as +-- + +CREATE TABLE public.gateway_ping_rx ( + id bigint NOT NULL, + created_at timestamp with time zone NOT NULL, + ping_id bigint NOT NULL, + gateway_mac bytea NOT NULL, + received_at timestamp with time zone, + rssi integer NOT NULL, + lora_snr numeric(3,1) NOT NULL, + location point, + altitude double precision +); + + +ALTER TABLE public.gateway_ping_rx OWNER TO loraserver_as; + +-- +-- Name: gateway_ping_rx_id_seq; Type: SEQUENCE; Schema: public; Owner: loraserver_as +-- + +CREATE SEQUENCE public.gateway_ping_rx_id_seq + START WITH 1 + INCREMENT BY 1 + NO MINVALUE + NO MAXVALUE + CACHE 1; + + +ALTER TABLE public.gateway_ping_rx_id_seq OWNER TO loraserver_as; + +-- +-- Name: gateway_ping_rx_id_seq; Type: SEQUENCE OWNED BY; Schema: public; Owner: loraserver_as +-- + +ALTER SEQUENCE public.gateway_ping_rx_id_seq OWNED BY public.gateway_ping_rx.id; + + +-- +-- Name: gateway_profile; Type: TABLE; Schema: public; Owner: loraserver_as +-- + +CREATE TABLE public.gateway_profile ( + gateway_profile_id uuid NOT NULL, + network_server_id bigint NOT NULL, + created_at timestamp with time zone NOT NULL, + updated_at timestamp with time zone NOT NULL, + name character varying(100) NOT NULL +); + + +ALTER TABLE public.gateway_profile OWNER TO loraserver_as; + +-- +-- Name: gorp_migrations; Type: TABLE; Schema: public; Owner: loraserver_as +-- + +CREATE TABLE public.gorp_migrations ( + id text NOT NULL, + applied_at timestamp with time zone +); + + +ALTER TABLE public.gorp_migrations OWNER TO loraserver_as; + +-- +-- Name: integration; Type: TABLE; Schema: public; Owner: loraserver_as +-- + +CREATE TABLE public.integration ( + id bigint NOT NULL, + created_at timestamp with time zone NOT NULL, + updated_at timestamp with time zone NOT NULL, + application_id bigint NOT NULL, + kind character varying(20) NOT NULL, + settings jsonb +); + + +ALTER TABLE public.integration OWNER TO loraserver_as; + +-- +-- Name: integration_id_seq; Type: SEQUENCE; Schema: public; Owner: loraserver_as +-- + +CREATE SEQUENCE public.integration_id_seq + START WITH 1 + INCREMENT BY 1 + NO MINVALUE + NO MAXVALUE + CACHE 1; + + +ALTER TABLE public.integration_id_seq OWNER TO loraserver_as; + +-- +-- Name: integration_id_seq; Type: SEQUENCE OWNED BY; Schema: public; Owner: loraserver_as +-- + +ALTER SEQUENCE public.integration_id_seq OWNED BY public.integration.id; + + +-- +-- Name: multicast_group; Type: TABLE; Schema: public; Owner: loraserver_as +-- + +CREATE TABLE public.multicast_group ( + id uuid NOT NULL, + created_at timestamp with time zone NOT NULL, + updated_at timestamp with time zone NOT NULL, + name character varying(100) NOT NULL, + service_profile_id uuid NOT NULL, + mc_app_s_key bytea, + mc_key bytea NOT NULL, + f_cnt bigint NOT NULL +); + + +ALTER TABLE public.multicast_group OWNER TO loraserver_as; + +-- +-- Name: network_server; Type: TABLE; Schema: public; Owner: loraserver_as +-- + +CREATE TABLE public.network_server ( + id bigint NOT NULL, + created_at timestamp with time zone NOT NULL, + updated_at timestamp with time zone NOT NULL, + name character varying(100) NOT NULL, + server character varying(255) NOT NULL, + ca_cert text DEFAULT ''::text NOT NULL, + tls_cert text DEFAULT ''::text NOT NULL, + tls_key text DEFAULT ''::text NOT NULL, + routing_profile_ca_cert text DEFAULT ''::text NOT NULL, + routing_profile_tls_cert text DEFAULT ''::text NOT NULL, + routing_profile_tls_key text DEFAULT ''::text NOT NULL, + gateway_discovery_enabled boolean DEFAULT false NOT NULL, + gateway_discovery_interval integer DEFAULT 0 NOT NULL, + gateway_discovery_tx_frequency integer DEFAULT 0 NOT NULL, + gateway_discovery_dr smallint DEFAULT 0 NOT NULL +); + + +ALTER TABLE public.network_server OWNER TO loraserver_as; + +-- +-- Name: network_server_id_seq; Type: SEQUENCE; Schema: public; Owner: loraserver_as +-- + +CREATE SEQUENCE public.network_server_id_seq + START WITH 1 + INCREMENT BY 1 + NO MINVALUE + NO MAXVALUE + CACHE 1; + + +ALTER TABLE public.network_server_id_seq OWNER TO loraserver_as; + +-- +-- Name: network_server_id_seq; Type: SEQUENCE OWNED BY; Schema: public; Owner: loraserver_as +-- + +ALTER SEQUENCE public.network_server_id_seq OWNED BY public.network_server.id; + + +-- +-- Name: organization; Type: TABLE; Schema: public; Owner: loraserver_as +-- + +CREATE TABLE public.organization ( + id bigint NOT NULL, + created_at timestamp with time zone NOT NULL, + updated_at timestamp with time zone NOT NULL, + name character varying(100) NOT NULL, + display_name character varying(100) NOT NULL, + can_have_gateways boolean NOT NULL +); + + +ALTER TABLE public.organization OWNER TO loraserver_as; + +-- +-- Name: organization_id_seq; Type: SEQUENCE; Schema: public; Owner: loraserver_as +-- + +CREATE SEQUENCE public.organization_id_seq + START WITH 1 + INCREMENT BY 1 + NO MINVALUE + NO MAXVALUE + CACHE 1; + + +ALTER TABLE public.organization_id_seq OWNER TO loraserver_as; + +-- +-- Name: organization_id_seq; Type: SEQUENCE OWNED BY; Schema: public; Owner: loraserver_as +-- + +ALTER SEQUENCE public.organization_id_seq OWNED BY public.organization.id; + + +-- +-- Name: organization_user; Type: TABLE; Schema: public; Owner: loraserver_as +-- + +CREATE TABLE public.organization_user ( + id bigint NOT NULL, + created_at timestamp with time zone NOT NULL, + updated_at timestamp with time zone NOT NULL, + user_id bigint NOT NULL, + organization_id bigint NOT NULL, + is_admin boolean NOT NULL +); + + +ALTER TABLE public.organization_user OWNER TO loraserver_as; + +-- +-- Name: organization_user_id_seq; Type: SEQUENCE; Schema: public; Owner: loraserver_as +-- + +CREATE SEQUENCE public.organization_user_id_seq + START WITH 1 + INCREMENT BY 1 + NO MINVALUE + NO MAXVALUE + CACHE 1; + + +ALTER TABLE public.organization_user_id_seq OWNER TO loraserver_as; + +-- +-- Name: organization_user_id_seq; Type: SEQUENCE OWNED BY; Schema: public; Owner: loraserver_as +-- + +ALTER SEQUENCE public.organization_user_id_seq OWNED BY public.organization_user.id; + + +-- +-- Name: remote_fragmentation_session; Type: TABLE; Schema: public; Owner: loraserver_as +-- + +CREATE TABLE public.remote_fragmentation_session ( + dev_eui bytea NOT NULL, + frag_index smallint NOT NULL, + created_at timestamp with time zone NOT NULL, + updated_at timestamp with time zone NOT NULL, + mc_group_ids smallint[], + nb_frag integer NOT NULL, + frag_size smallint NOT NULL, + fragmentation_matrix bytea NOT NULL, + block_ack_delay smallint NOT NULL, + padding smallint NOT NULL, + descriptor bytea NOT NULL, + state character varying(20) NOT NULL, + state_provisioned boolean DEFAULT false NOT NULL, + retry_after timestamp with time zone NOT NULL, + retry_count smallint NOT NULL, + retry_interval bigint NOT NULL +); + + +ALTER TABLE public.remote_fragmentation_session OWNER TO loraserver_as; + +-- +-- Name: remote_multicast_class_c_session; Type: TABLE; Schema: public; Owner: loraserver_as +-- + +CREATE TABLE public.remote_multicast_class_c_session ( + dev_eui bytea NOT NULL, + multicast_group_id uuid NOT NULL, + created_at timestamp with time zone NOT NULL, + updated_at timestamp with time zone NOT NULL, + mc_group_id smallint NOT NULL, + session_time timestamp with time zone NOT NULL, + session_time_out smallint NOT NULL, + dl_frequency integer NOT NULL, + dr smallint NOT NULL, + state_provisioned boolean DEFAULT false NOT NULL, + retry_after timestamp with time zone NOT NULL, + retry_count smallint NOT NULL, + retry_interval bigint NOT NULL +); + + +ALTER TABLE public.remote_multicast_class_c_session OWNER TO loraserver_as; + +-- +-- Name: remote_multicast_setup; Type: TABLE; Schema: public; Owner: loraserver_as +-- + +CREATE TABLE public.remote_multicast_setup ( + dev_eui bytea NOT NULL, + multicast_group_id uuid NOT NULL, + created_at timestamp with time zone NOT NULL, + updated_at timestamp with time zone NOT NULL, + mc_group_id smallint NOT NULL, + mc_addr bytea NOT NULL, + mc_key_encrypted bytea NOT NULL, + min_mc_f_cnt bigint NOT NULL, + max_mc_f_cnt bigint NOT NULL, + state character varying(20) NOT NULL, + state_provisioned boolean DEFAULT false NOT NULL, + retry_after timestamp with time zone NOT NULL, + retry_count smallint NOT NULL, + retry_interval bigint NOT NULL +); + + +ALTER TABLE public.remote_multicast_setup OWNER TO loraserver_as; + +-- +-- Name: service_profile; Type: TABLE; Schema: public; Owner: loraserver_as +-- + +CREATE TABLE public.service_profile ( + service_profile_id uuid NOT NULL, + organization_id bigint NOT NULL, + network_server_id bigint NOT NULL, + created_at timestamp with time zone NOT NULL, + updated_at timestamp with time zone NOT NULL, + name character varying(100) NOT NULL +); + + +ALTER TABLE public.service_profile OWNER TO loraserver_as; + +-- +-- Name: user; Type: TABLE; Schema: public; Owner: loraserver_as +-- + +CREATE TABLE public."user" ( + id bigint NOT NULL, + created_at timestamp with time zone NOT NULL, + updated_at timestamp with time zone NOT NULL, + username character varying(100) NOT NULL, + password_hash character varying(200) NOT NULL, + session_ttl bigint NOT NULL, + is_active boolean NOT NULL, + is_admin boolean NOT NULL, + email text DEFAULT ''::text NOT NULL, + note text DEFAULT ''::text NOT NULL +); + + +ALTER TABLE public."user" OWNER TO loraserver_as; + +-- +-- Name: user_id_seq; Type: SEQUENCE; Schema: public; Owner: loraserver_as +-- + +CREATE SEQUENCE public.user_id_seq + START WITH 1 + INCREMENT BY 1 + NO MINVALUE + NO MAXVALUE + CACHE 1; + + +ALTER TABLE public.user_id_seq OWNER TO loraserver_as; + +-- +-- Name: user_id_seq; Type: SEQUENCE OWNED BY; Schema: public; Owner: loraserver_as +-- + +ALTER SEQUENCE public.user_id_seq OWNED BY public."user".id; + + +-- +-- Name: application id; Type: DEFAULT; Schema: public; Owner: loraserver_as +-- + +ALTER TABLE ONLY public.application ALTER COLUMN id SET DEFAULT nextval('public.application_id_seq'::regclass); + + +-- +-- Name: device_activation id; Type: DEFAULT; Schema: public; Owner: loraserver_as +-- + +ALTER TABLE ONLY public.device_activation ALTER COLUMN id SET DEFAULT nextval('public.device_activation_id_seq'::regclass); + + +-- +-- Name: gateway_ping id; Type: DEFAULT; Schema: public; Owner: loraserver_as +-- + +ALTER TABLE ONLY public.gateway_ping ALTER COLUMN id SET DEFAULT nextval('public.gateway_ping_id_seq'::regclass); + + +-- +-- Name: gateway_ping_rx id; Type: DEFAULT; Schema: public; Owner: loraserver_as +-- + +ALTER TABLE ONLY public.gateway_ping_rx ALTER COLUMN id SET DEFAULT nextval('public.gateway_ping_rx_id_seq'::regclass); + + +-- +-- Name: integration id; Type: DEFAULT; Schema: public; Owner: loraserver_as +-- + +ALTER TABLE ONLY public.integration ALTER COLUMN id SET DEFAULT nextval('public.integration_id_seq'::regclass); + + +-- +-- Name: network_server id; Type: DEFAULT; Schema: public; Owner: loraserver_as +-- + +ALTER TABLE ONLY public.network_server ALTER COLUMN id SET DEFAULT nextval('public.network_server_id_seq'::regclass); + + +-- +-- Name: organization id; Type: DEFAULT; Schema: public; Owner: loraserver_as +-- + +ALTER TABLE ONLY public.organization ALTER COLUMN id SET DEFAULT nextval('public.organization_id_seq'::regclass); + + +-- +-- Name: organization_user id; Type: DEFAULT; Schema: public; Owner: loraserver_as +-- + +ALTER TABLE ONLY public.organization_user ALTER COLUMN id SET DEFAULT nextval('public.organization_user_id_seq'::regclass); + + +-- +-- Name: user id; Type: DEFAULT; Schema: public; Owner: loraserver_as +-- + +ALTER TABLE ONLY public."user" ALTER COLUMN id SET DEFAULT nextval('public.user_id_seq'::regclass); + + +-- +-- Data for Name: application; Type: TABLE DATA; Schema: public; Owner: loraserver_as +-- + +COPY public.application (id, name, description, organization_id, service_profile_id, payload_codec, payload_encoder_script, payload_decoder_script) FROM stdin; +1 App App 1 539d73d0-e87b-42e6-a7c3-4df12aca3493 CUSTOM_JS // Decode decodes an array of bytes into an object.\n// - fPort contains the LoRaWAN fPort number\n// - bytes is an array of bytes, e.g. [225, 230, 255, 0]\n// The function must return an object, e.g. {"temperature": 22.5}\nfunction bin2String(array) {\n return String.fromCharCode.apply(String, array);\n}\n\nfunction bin2HexStr(arr)\n \n{\n var str = "";\n for(var i=0; i Shared access policies. The policy must contain Manage & Send. + connection_string="" + + # Publish mode. + # + # Select either "topic", or "queue". + publish_mode="" + + # Publish name. + # + # The name of the topic or queue. + publish_name="" + + + # Google Cloud Pub/Sub integration. + [application_server.integration.gcp_pub_sub] + # Path to the IAM service-account credentials file. + # + # Note: this service-account must have the following Pub/Sub roles: + # * Pub/Sub Editor + credentials_file="" + + # Google Cloud project id. + project_id="" + + # Pub/Sub topic name. + topic_name="" + + + # Settings for the "internal api" + # + # This is the API used by LoRa Server to communicate with LoRa App Server + # and should not be exposed to the end-user. + [application_server.api] + # ip:port to bind the api server + bind="0.0.0.0:8001" + + # ca certificate used by the api server (optional) + ca_cert="" + + # tls certificate used by the api server (optional) + tls_cert="" + + # tls key used by the api server (optional) + tls_key="" + + # Public ip:port of the application-server API. + # + # This is used by LoRa Server to connect to LoRa App Server. When running + # LoRa App Server on a different host than LoRa Server, make sure to set + # this to the host:ip on which LoRa Server can reach LoRa App Server. + # The port must be equal to the port configured by the 'bind' flag + # above. + public_host="localhost:8001" + + + # Settings for the "external api" + # + # This is the API and web-interface exposed to the end-user. + [application_server.external_api] + # ip:port to bind the (user facing) http server to (web-interface and REST / gRPC api) + bind="0.0.0.0:8080" + + # http server TLS certificate (optional) + tls_cert="" + + # http server TLS key (optional) + tls_key="" + + # JWT secret used for api authentication / authorization + # You could generate this by executing 'openssl rand -base64 32' for example + jwt_secret="verysecret" + + # Allow origin header (CORS). + # + # Set this to allows cross-domain communication from the browser (CORS). + # Example value: https://example.com. + # When left blank (default), CORS will not be used. + cors_allow_origin="" + + # when set, existing users can't be re-assigned (to avoid exposure of all users to an organization admin)" + disable_assign_existing_users=false + + + # Settings for the remote multicast setup. + [application_server.remote_multicast_setup] + # Synchronization interval. + sync_interval="1s" + + # Synchronization retries. + sync_retries=3 + + # Synchronization batch-size. + sync_batch_size=100 + + + # Settings for the fragmentation-session setup. + [application_server.fragmentation_session] + # Synchronization interval. + sync_interval="1s" + + # Synchronization retries. + sync_retries=3 + + # Synchronization batch-size. + sync_batch_size=100 + + + +# Join-server configuration. +# +# LoRa App Server implements a (subset) of the join-api specified by the +# LoRaWAN Backend Interfaces specification. This API is used by LoRa Server +# to handle join-requests. +[join_server] +# ip:port to bind the join-server api interface to +bind="0.0.0.0:8003" + +# CA certificate (optional). +# +# When set, the server requires a client-certificate and will validate this +# certificate on incoming requests. +ca_cert="" + +# TLS server-certificate (optional). +# +# Set this to enable TLS. +tls_cert="" + +# TLS server-certificate key (optional). +# +# Set this to enable TLS. +tls_key="" + + +# Key Encryption Key (KEK) configuration. +# +# The KEK meganism is used to encrypt the session-keys sent from the +# join-server to the network-server. +# +# The LoRa App Server join-server will use the NetID of the requesting +# network-server as the KEK label. When no such label exists in the set, +# the session-keys will be sent unencrypted (which can be fine for +# private networks). +# +# Please refer to the LoRaWAN Backend Interface specification +# 'Key Transport Security' section for more information. +[join_server.kek] + + # Application-server KEK label. + # + # This defines the KEK label used to encrypt the AppSKey (note that the + # AppSKey is signaled to the NS and on the first received uplink from the + # NS to the AS). + # + # When left blank, the AppSKey will be sent unencrypted (which can be fine + # for private networks). + as_kek_label="" + + # KEK set. + # + # Example (the [[join_server.kek.set]] can be repeated): + # [[join_server.kek.set]] + # # KEK label. + # label="000000" + + # # Key Encryption Key. + # kek="01020304050607080102030405060708" + diff --git a/loraserver/loraserver_conf/loraserver.as_923.toml b/loraserver/loraserver_conf/loraserver.as_923.toml new file mode 100644 index 0000000..ba06f15 --- /dev/null +++ b/loraserver/loraserver_conf/loraserver.as_923.toml @@ -0,0 +1,191 @@ +# This configuration configures LoRa Server for the EU868 band using a MQTT +# broker to communicate with the gateways. Many options and defaults have been +# omitted for simplicity. +# +# For other bands, see the ./examples/ sub-directory. + + +# PostgreSQL settings. +# +# Please note that PostgreSQL 9.5+ is required. +[postgresql] +# PostgreSQL dsn (e.g.: postgres://user:password@hostname/database?sslmode=disable). +# +# Besides using an URL (e.g. 'postgres://user:password@hostname/database?sslmode=disable') +# it is also possible to use the following format: +# 'user=loraserver dbname=loraserver sslmode=disable'. +# +# The following connection parameters are supported: +# +# * dbname - The name of the database to connect to +# * user - The user to sign in as +# * password - The user's password +# * host - The host to connect to. Values that start with / are for unix domain sockets. (default is localhost) +# * port - The port to bind to. (default is 5432) +# * sslmode - Whether or not to use SSL (default is require, this is not the default for libpq) +# * fallback_application_name - An application_name to fall back to if one isn't provided. +# * connect_timeout - Maximum wait for connection, in seconds. Zero or not specified means wait indefinitely. +# * sslcert - Cert file location. The file must contain PEM encoded data. +# * sslkey - Key file location. The file must contain PEM encoded data. +# * sslrootcert - The location of the root certificate file. The file must contain PEM encoded data. +# +# Valid values for sslmode are: +# +# * disable - No SSL +# * require - Always SSL (skip verification) +# * verify-ca - Always SSL (verify that the certificate presented by the server was signed by a trusted CA) +# * verify-full - Always SSL (verify that the certification presented by the server was signed by a trusted CA and the server host name matches the one in the certificate) +#dsn="postgres://localhost/loraserver_ns?sslmode=disable" +dsn="postgres://loraserver_ns:dbpassword@localhost/loraserver_ns?sslmode=disable" + + +# Redis settings +# +# Please note that Redis 2.6.0+ is required. +[redis] +# Redis url (e.g. redis://user:password@hostname/0) +# +# For more information about the Redis URL format, see: +# https://www.iana.org/assignments/uri-schemes/prov/redis +url="redis://localhost:6379" + + +# Network-server settings. +[network_server] +# Network identifier (NetID, 3 bytes) encoded as HEX (e.g. 010203) +net_id="000000" + + + # LoRaWAN regional band configuration. + # + # Note that you might want to consult the LoRaWAN Regional Parameters + # specification for valid values that apply to your region. + # See: https://www.lora-alliance.org/lorawan-for-developers + [network_server.band] + name="AS_923" + + + # LoRaWAN network related settings. + [network_server.network_settings] + + # Extra channel configuration. + # + # Use this for LoRaWAN regions where it is possible to extend the by default + # available channels with additional channels (e.g. the EU band). + # The first 5 channels will be configured as part of the OTAA join-response + # (using the CFList field). + # The other channels (or channel / data-rate changes) will be (re)configured + # using the NewChannelReq mac-command. + # +# [[network_server.network_settings.extra_channels]] +# frequency=867100000 +# min_dr=0 +# max_dr=5 + +# [[network_server.network_settings.extra_channels]] +# frequency=867300000 +# min_dr=0 +# max_dr=5 + +# [[network_server.network_settings.extra_channels]] +# frequency=867500000 +# min_dr=0 +# max_dr=5 + +# [[network_server.network_settings.extra_channels]] +# frequency=867700000 +# min_dr=0 +# max_dr=5 + +# [[network_server.network_settings.extra_channels]] +# frequency=867900000 +# min_dr=0 +# max_dr=5 + + + # Class B settings + [network_server.network_settings.class_b] + # Ping-slot data-rate. + ping_slot_dr=0 + + # Ping-slot frequency (Hz) + # + # Set this to 0 to use the default frequency plan for the configured region + # (which could be frequency hopping). + ping_slot_frequency=0 + + + # Network-server API + # + # This is the network-server API that is used by LoRa App Server or other + # custom components interacting with LoRa Server. + [network_server.api] + # ip:port to bind the api server + bind="0.0.0.0:8000" + + + # Backend defines the gateway backend settings. + # + # The gateway backend handles the communication with the gateway(s) part of + # the LoRaWAN network. + [network_server.gateway.backend] + # Backend + type="mqtt" + + + # MQTT gateway backend settings. + # + # This is the backend communicating with the LoRa gateways over a MQTT broker. + [network_server.gateway.backend.mqtt] + # MQTT topic templates for the different MQTT topics. + # + # The meaning of these topics are documented at: + # https://www.loraserver.io/lora-gateway-bridge/ + # + # The default values match the default expected configuration of the + # LoRa Gateway Bridge MQTT backend. Therefore only change these values when + # absolutely needed. + + # Event topic template. + event_topic="gateway/+/event/+" + + # Command topic template. + # + # Use: + # * "{{ .GatewayID }}" as an substitution for the LoRa gateway ID + # * "{{ .CommandType }}" as an substitution for the command type + command_topic_template="gateway/{{ .GatewayID }}/command/{{ .CommandType }}" + + # MQTT server (e.g. scheme://host:port where scheme is tcp, ssl or ws) + server="tcp://localhost:1883" + + # Connect with the given username (optional) + username="" + + # Connect with the given password (optional) + password="" + + +# Metrics collection settings. +[metrics] +# Timezone +# +# The timezone is used for correctly aggregating the metrics (e.g. per hour, +# day or month). +# Example: "Europe/Amsterdam" or "Local" for the the system's local time zone. +timezone="Local" + + +# Join-server settings. +[join_server] + + # Default join-server settings. + # + # This join-server will be used when resolving the JoinEUI is set to false + # or as a fallback when resolving the JoinEUI fails. + [join_server.default] + # hostname:port of the default join-server + # + # This API is provided by LoRa App Server. + server="http://localhost:8003" + diff --git a/loraserver/loraserver_conf/loraserver.au_915_928.toml b/loraserver/loraserver_conf/loraserver.au_915_928.toml new file mode 100644 index 0000000..9587716 --- /dev/null +++ b/loraserver/loraserver_conf/loraserver.au_915_928.toml @@ -0,0 +1,191 @@ +# This configuration configures LoRa Server for the EU868 band using a MQTT +# broker to communicate with the gateways. Many options and defaults have been +# omitted for simplicity. +# +# For other bands, see the ./examples/ sub-directory. + + +# PostgreSQL settings. +# +# Please note that PostgreSQL 9.5+ is required. +[postgresql] +# PostgreSQL dsn (e.g.: postgres://user:password@hostname/database?sslmode=disable). +# +# Besides using an URL (e.g. 'postgres://user:password@hostname/database?sslmode=disable') +# it is also possible to use the following format: +# 'user=loraserver dbname=loraserver sslmode=disable'. +# +# The following connection parameters are supported: +# +# * dbname - The name of the database to connect to +# * user - The user to sign in as +# * password - The user's password +# * host - The host to connect to. Values that start with / are for unix domain sockets. (default is localhost) +# * port - The port to bind to. (default is 5432) +# * sslmode - Whether or not to use SSL (default is require, this is not the default for libpq) +# * fallback_application_name - An application_name to fall back to if one isn't provided. +# * connect_timeout - Maximum wait for connection, in seconds. Zero or not specified means wait indefinitely. +# * sslcert - Cert file location. The file must contain PEM encoded data. +# * sslkey - Key file location. The file must contain PEM encoded data. +# * sslrootcert - The location of the root certificate file. The file must contain PEM encoded data. +# +# Valid values for sslmode are: +# +# * disable - No SSL +# * require - Always SSL (skip verification) +# * verify-ca - Always SSL (verify that the certificate presented by the server was signed by a trusted CA) +# * verify-full - Always SSL (verify that the certification presented by the server was signed by a trusted CA and the server host name matches the one in the certificate) +#dsn="postgres://localhost/loraserver_ns?sslmode=disable" +dsn="postgres://loraserver_ns:dbpassword@localhost/loraserver_ns?sslmode=disable" + + +# Redis settings +# +# Please note that Redis 2.6.0+ is required. +[redis] +# Redis url (e.g. redis://user:password@hostname/0) +# +# For more information about the Redis URL format, see: +# https://www.iana.org/assignments/uri-schemes/prov/redis +url="redis://localhost:6379" + + +# Network-server settings. +[network_server] +# Network identifier (NetID, 3 bytes) encoded as HEX (e.g. 010203) +net_id="000000" + + + # LoRaWAN regional band configuration. + # + # Note that you might want to consult the LoRaWAN Regional Parameters + # specification for valid values that apply to your region. + # See: https://www.lora-alliance.org/lorawan-for-developers + [network_server.band] + name="AU_915_928" + + + # LoRaWAN network related settings. + [network_server.network_settings] + + # Extra channel configuration. + # + # Use this for LoRaWAN regions where it is possible to extend the by default + # available channels with additional channels (e.g. the EU band). + # The first 5 channels will be configured as part of the OTAA join-response + # (using the CFList field). + # The other channels (or channel / data-rate changes) will be (re)configured + # using the NewChannelReq mac-command. + # +# [[network_server.network_settings.extra_channels]] +# frequency=867100000 +# min_dr=0 +# max_dr=5 + +# [[network_server.network_settings.extra_channels]] +# frequency=867300000 +# min_dr=0 +# max_dr=5 + +# [[network_server.network_settings.extra_channels]] +# frequency=867500000 +# min_dr=0 +# max_dr=5 + +# [[network_server.network_settings.extra_channels]] +# frequency=867700000 +# min_dr=0 +# max_dr=5 + +# [[network_server.network_settings.extra_channels]] +# frequency=867900000 +# min_dr=0 +# max_dr=5 + + + # Class B settings + [network_server.network_settings.class_b] + # Ping-slot data-rate. + ping_slot_dr=0 + + # Ping-slot frequency (Hz) + # + # Set this to 0 to use the default frequency plan for the configured region + # (which could be frequency hopping). + ping_slot_frequency=0 + + + # Network-server API + # + # This is the network-server API that is used by LoRa App Server or other + # custom components interacting with LoRa Server. + [network_server.api] + # ip:port to bind the api server + bind="0.0.0.0:8000" + + + # Backend defines the gateway backend settings. + # + # The gateway backend handles the communication with the gateway(s) part of + # the LoRaWAN network. + [network_server.gateway.backend] + # Backend + type="mqtt" + + + # MQTT gateway backend settings. + # + # This is the backend communicating with the LoRa gateways over a MQTT broker. + [network_server.gateway.backend.mqtt] + # MQTT topic templates for the different MQTT topics. + # + # The meaning of these topics are documented at: + # https://www.loraserver.io/lora-gateway-bridge/ + # + # The default values match the default expected configuration of the + # LoRa Gateway Bridge MQTT backend. Therefore only change these values when + # absolutely needed. + + # Event topic template. + event_topic="gateway/+/event/+" + + # Command topic template. + # + # Use: + # * "{{ .GatewayID }}" as an substitution for the LoRa gateway ID + # * "{{ .CommandType }}" as an substitution for the command type + command_topic_template="gateway/{{ .GatewayID }}/command/{{ .CommandType }}" + + # MQTT server (e.g. scheme://host:port where scheme is tcp, ssl or ws) + server="tcp://localhost:1883" + + # Connect with the given username (optional) + username="" + + # Connect with the given password (optional) + password="" + + +# Metrics collection settings. +[metrics] +# Timezone +# +# The timezone is used for correctly aggregating the metrics (e.g. per hour, +# day or month). +# Example: "Europe/Amsterdam" or "Local" for the the system's local time zone. +timezone="Local" + + +# Join-server settings. +[join_server] + + # Default join-server settings. + # + # This join-server will be used when resolving the JoinEUI is set to false + # or as a fallback when resolving the JoinEUI fails. + [join_server.default] + # hostname:port of the default join-server + # + # This API is provided by LoRa App Server. + server="http://localhost:8003" + diff --git a/loraserver/loraserver_conf/loraserver.cn_470_510.toml b/loraserver/loraserver_conf/loraserver.cn_470_510.toml new file mode 100644 index 0000000..9cb297d --- /dev/null +++ b/loraserver/loraserver_conf/loraserver.cn_470_510.toml @@ -0,0 +1,191 @@ +# This configuration configures LoRa Server for the EU868 band using a MQTT +# broker to communicate with the gateways. Many options and defaults have been +# omitted for simplicity. +# +# For other bands, see the ./examples/ sub-directory. + + +# PostgreSQL settings. +# +# Please note that PostgreSQL 9.5+ is required. +[postgresql] +# PostgreSQL dsn (e.g.: postgres://user:password@hostname/database?sslmode=disable). +# +# Besides using an URL (e.g. 'postgres://user:password@hostname/database?sslmode=disable') +# it is also possible to use the following format: +# 'user=loraserver dbname=loraserver sslmode=disable'. +# +# The following connection parameters are supported: +# +# * dbname - The name of the database to connect to +# * user - The user to sign in as +# * password - The user's password +# * host - The host to connect to. Values that start with / are for unix domain sockets. (default is localhost) +# * port - The port to bind to. (default is 5432) +# * sslmode - Whether or not to use SSL (default is require, this is not the default for libpq) +# * fallback_application_name - An application_name to fall back to if one isn't provided. +# * connect_timeout - Maximum wait for connection, in seconds. Zero or not specified means wait indefinitely. +# * sslcert - Cert file location. The file must contain PEM encoded data. +# * sslkey - Key file location. The file must contain PEM encoded data. +# * sslrootcert - The location of the root certificate file. The file must contain PEM encoded data. +# +# Valid values for sslmode are: +# +# * disable - No SSL +# * require - Always SSL (skip verification) +# * verify-ca - Always SSL (verify that the certificate presented by the server was signed by a trusted CA) +# * verify-full - Always SSL (verify that the certification presented by the server was signed by a trusted CA and the server host name matches the one in the certificate) +#dsn="postgres://localhost/loraserver_ns?sslmode=disable" +dsn="postgres://loraserver_ns:dbpassword@localhost/loraserver_ns?sslmode=disable" + + +# Redis settings +# +# Please note that Redis 2.6.0+ is required. +[redis] +# Redis url (e.g. redis://user:password@hostname/0) +# +# For more information about the Redis URL format, see: +# https://www.iana.org/assignments/uri-schemes/prov/redis +url="redis://localhost:6379" + + +# Network-server settings. +[network_server] +# Network identifier (NetID, 3 bytes) encoded as HEX (e.g. 010203) +net_id="000000" + + + # LoRaWAN regional band configuration. + # + # Note that you might want to consult the LoRaWAN Regional Parameters + # specification for valid values that apply to your region. + # See: https://www.lora-alliance.org/lorawan-for-developers + [network_server.band] + name="CN_470_510" + + + # LoRaWAN network related settings. + [network_server.network_settings] + + # Extra channel configuration. + # + # Use this for LoRaWAN regions where it is possible to extend the by default + # available channels with additional channels (e.g. the EU band). + # The first 5 channels will be configured as part of the OTAA join-response + # (using the CFList field). + # The other channels (or channel / data-rate changes) will be (re)configured + # using the NewChannelReq mac-command. + # +# [[network_server.network_settings.extra_channels]] +# frequency=867100000 +# min_dr=0 +# max_dr=5 + +# [[network_server.network_settings.extra_channels]] +# frequency=867300000 +# min_dr=0 +# max_dr=5 + +# [[network_server.network_settings.extra_channels]] +# frequency=867500000 +# min_dr=0 +# max_dr=5 + +# [[network_server.network_settings.extra_channels]] +# frequency=867700000 +# min_dr=0 +# max_dr=5 + +# [[network_server.network_settings.extra_channels]] +# frequency=867900000 +# min_dr=0 +# max_dr=5 + + + # Class B settings + [network_server.network_settings.class_b] + # Ping-slot data-rate. + ping_slot_dr=0 + + # Ping-slot frequency (Hz) + # + # Set this to 0 to use the default frequency plan for the configured region + # (which could be frequency hopping). + ping_slot_frequency=0 + + + # Network-server API + # + # This is the network-server API that is used by LoRa App Server or other + # custom components interacting with LoRa Server. + [network_server.api] + # ip:port to bind the api server + bind="0.0.0.0:8000" + + + # Backend defines the gateway backend settings. + # + # The gateway backend handles the communication with the gateway(s) part of + # the LoRaWAN network. + [network_server.gateway.backend] + # Backend + type="mqtt" + + + # MQTT gateway backend settings. + # + # This is the backend communicating with the LoRa gateways over a MQTT broker. + [network_server.gateway.backend.mqtt] + # MQTT topic templates for the different MQTT topics. + # + # The meaning of these topics are documented at: + # https://www.loraserver.io/lora-gateway-bridge/ + # + # The default values match the default expected configuration of the + # LoRa Gateway Bridge MQTT backend. Therefore only change these values when + # absolutely needed. + + # Event topic template. + event_topic="gateway/+/event/+" + + # Command topic template. + # + # Use: + # * "{{ .GatewayID }}" as an substitution for the LoRa gateway ID + # * "{{ .CommandType }}" as an substitution for the command type + command_topic_template="gateway/{{ .GatewayID }}/command/{{ .CommandType }}" + + # MQTT server (e.g. scheme://host:port where scheme is tcp, ssl or ws) + server="tcp://localhost:1883" + + # Connect with the given username (optional) + username="" + + # Connect with the given password (optional) + password="" + + +# Metrics collection settings. +[metrics] +# Timezone +# +# The timezone is used for correctly aggregating the metrics (e.g. per hour, +# day or month). +# Example: "Europe/Amsterdam" or "Local" for the the system's local time zone. +timezone="Local" + + +# Join-server settings. +[join_server] + + # Default join-server settings. + # + # This join-server will be used when resolving the JoinEUI is set to false + # or as a fallback when resolving the JoinEUI fails. + [join_server.default] + # hostname:port of the default join-server + # + # This API is provided by LoRa App Server. + server="http://localhost:8003" + diff --git a/loraserver/loraserver_conf/loraserver.cn_779_787.toml b/loraserver/loraserver_conf/loraserver.cn_779_787.toml new file mode 100644 index 0000000..53304f7 --- /dev/null +++ b/loraserver/loraserver_conf/loraserver.cn_779_787.toml @@ -0,0 +1,191 @@ +# This configuration configures LoRa Server for the EU868 band using a MQTT +# broker to communicate with the gateways. Many options and defaults have been +# omitted for simplicity. +# +# For other bands, see the ./examples/ sub-directory. + + +# PostgreSQL settings. +# +# Please note that PostgreSQL 9.5+ is required. +[postgresql] +# PostgreSQL dsn (e.g.: postgres://user:password@hostname/database?sslmode=disable). +# +# Besides using an URL (e.g. 'postgres://user:password@hostname/database?sslmode=disable') +# it is also possible to use the following format: +# 'user=loraserver dbname=loraserver sslmode=disable'. +# +# The following connection parameters are supported: +# +# * dbname - The name of the database to connect to +# * user - The user to sign in as +# * password - The user's password +# * host - The host to connect to. Values that start with / are for unix domain sockets. (default is localhost) +# * port - The port to bind to. (default is 5432) +# * sslmode - Whether or not to use SSL (default is require, this is not the default for libpq) +# * fallback_application_name - An application_name to fall back to if one isn't provided. +# * connect_timeout - Maximum wait for connection, in seconds. Zero or not specified means wait indefinitely. +# * sslcert - Cert file location. The file must contain PEM encoded data. +# * sslkey - Key file location. The file must contain PEM encoded data. +# * sslrootcert - The location of the root certificate file. The file must contain PEM encoded data. +# +# Valid values for sslmode are: +# +# * disable - No SSL +# * require - Always SSL (skip verification) +# * verify-ca - Always SSL (verify that the certificate presented by the server was signed by a trusted CA) +# * verify-full - Always SSL (verify that the certification presented by the server was signed by a trusted CA and the server host name matches the one in the certificate) +#dsn="postgres://localhost/loraserver_ns?sslmode=disable" +dsn="postgres://loraserver_ns:dbpassword@localhost/loraserver_ns?sslmode=disable" + + +# Redis settings +# +# Please note that Redis 2.6.0+ is required. +[redis] +# Redis url (e.g. redis://user:password@hostname/0) +# +# For more information about the Redis URL format, see: +# https://www.iana.org/assignments/uri-schemes/prov/redis +url="redis://localhost:6379" + + +# Network-server settings. +[network_server] +# Network identifier (NetID, 3 bytes) encoded as HEX (e.g. 010203) +net_id="000000" + + + # LoRaWAN regional band configuration. + # + # Note that you might want to consult the LoRaWAN Regional Parameters + # specification for valid values that apply to your region. + # See: https://www.lora-alliance.org/lorawan-for-developers + [network_server.band] + name="CN_779_787" + + + # LoRaWAN network related settings. + [network_server.network_settings] + + # Extra channel configuration. + # + # Use this for LoRaWAN regions where it is possible to extend the by default + # available channels with additional channels (e.g. the EU band). + # The first 5 channels will be configured as part of the OTAA join-response + # (using the CFList field). + # The other channels (or channel / data-rate changes) will be (re)configured + # using the NewChannelReq mac-command. + # +# [[network_server.network_settings.extra_channels]] +# frequency=867100000 +# min_dr=0 +# max_dr=5 + +# [[network_server.network_settings.extra_channels]] +# frequency=867300000 +# min_dr=0 +# max_dr=5 + +# [[network_server.network_settings.extra_channels]] +# frequency=867500000 +# min_dr=0 +# max_dr=5 + +# [[network_server.network_settings.extra_channels]] +# frequency=867700000 +# min_dr=0 +# max_dr=5 + +# [[network_server.network_settings.extra_channels]] +# frequency=867900000 +# min_dr=0 +# max_dr=5 + + + # Class B settings + [network_server.network_settings.class_b] + # Ping-slot data-rate. + ping_slot_dr=0 + + # Ping-slot frequency (Hz) + # + # Set this to 0 to use the default frequency plan for the configured region + # (which could be frequency hopping). + ping_slot_frequency=0 + + + # Network-server API + # + # This is the network-server API that is used by LoRa App Server or other + # custom components interacting with LoRa Server. + [network_server.api] + # ip:port to bind the api server + bind="0.0.0.0:8000" + + + # Backend defines the gateway backend settings. + # + # The gateway backend handles the communication with the gateway(s) part of + # the LoRaWAN network. + [network_server.gateway.backend] + # Backend + type="mqtt" + + + # MQTT gateway backend settings. + # + # This is the backend communicating with the LoRa gateways over a MQTT broker. + [network_server.gateway.backend.mqtt] + # MQTT topic templates for the different MQTT topics. + # + # The meaning of these topics are documented at: + # https://www.loraserver.io/lora-gateway-bridge/ + # + # The default values match the default expected configuration of the + # LoRa Gateway Bridge MQTT backend. Therefore only change these values when + # absolutely needed. + + # Event topic template. + event_topic="gateway/+/event/+" + + # Command topic template. + # + # Use: + # * "{{ .GatewayID }}" as an substitution for the LoRa gateway ID + # * "{{ .CommandType }}" as an substitution for the command type + command_topic_template="gateway/{{ .GatewayID }}/command/{{ .CommandType }}" + + # MQTT server (e.g. scheme://host:port where scheme is tcp, ssl or ws) + server="tcp://localhost:1883" + + # Connect with the given username (optional) + username="" + + # Connect with the given password (optional) + password="" + + +# Metrics collection settings. +[metrics] +# Timezone +# +# The timezone is used for correctly aggregating the metrics (e.g. per hour, +# day or month). +# Example: "Europe/Amsterdam" or "Local" for the the system's local time zone. +timezone="Local" + + +# Join-server settings. +[join_server] + + # Default join-server settings. + # + # This join-server will be used when resolving the JoinEUI is set to false + # or as a fallback when resolving the JoinEUI fails. + [join_server.default] + # hostname:port of the default join-server + # + # This API is provided by LoRa App Server. + server="http://localhost:8003" + diff --git a/loraserver/loraserver_conf/loraserver.eu_433.toml b/loraserver/loraserver_conf/loraserver.eu_433.toml new file mode 100644 index 0000000..d4b5801 --- /dev/null +++ b/loraserver/loraserver_conf/loraserver.eu_433.toml @@ -0,0 +1,191 @@ +# This configuration configures LoRa Server for the EU868 band using a MQTT +# broker to communicate with the gateways. Many options and defaults have been +# omitted for simplicity. +# +# For other bands, see the ./examples/ sub-directory. + + +# PostgreSQL settings. +# +# Please note that PostgreSQL 9.5+ is required. +[postgresql] +# PostgreSQL dsn (e.g.: postgres://user:password@hostname/database?sslmode=disable). +# +# Besides using an URL (e.g. 'postgres://user:password@hostname/database?sslmode=disable') +# it is also possible to use the following format: +# 'user=loraserver dbname=loraserver sslmode=disable'. +# +# The following connection parameters are supported: +# +# * dbname - The name of the database to connect to +# * user - The user to sign in as +# * password - The user's password +# * host - The host to connect to. Values that start with / are for unix domain sockets. (default is localhost) +# * port - The port to bind to. (default is 5432) +# * sslmode - Whether or not to use SSL (default is require, this is not the default for libpq) +# * fallback_application_name - An application_name to fall back to if one isn't provided. +# * connect_timeout - Maximum wait for connection, in seconds. Zero or not specified means wait indefinitely. +# * sslcert - Cert file location. The file must contain PEM encoded data. +# * sslkey - Key file location. The file must contain PEM encoded data. +# * sslrootcert - The location of the root certificate file. The file must contain PEM encoded data. +# +# Valid values for sslmode are: +# +# * disable - No SSL +# * require - Always SSL (skip verification) +# * verify-ca - Always SSL (verify that the certificate presented by the server was signed by a trusted CA) +# * verify-full - Always SSL (verify that the certification presented by the server was signed by a trusted CA and the server host name matches the one in the certificate) +#dsn="postgres://localhost/loraserver_ns?sslmode=disable" +dsn="postgres://loraserver_ns:dbpassword@localhost/loraserver_ns?sslmode=disable" + + +# Redis settings +# +# Please note that Redis 2.6.0+ is required. +[redis] +# Redis url (e.g. redis://user:password@hostname/0) +# +# For more information about the Redis URL format, see: +# https://www.iana.org/assignments/uri-schemes/prov/redis +url="redis://localhost:6379" + + +# Network-server settings. +[network_server] +# Network identifier (NetID, 3 bytes) encoded as HEX (e.g. 010203) +net_id="000000" + + + # LoRaWAN regional band configuration. + # + # Note that you might want to consult the LoRaWAN Regional Parameters + # specification for valid values that apply to your region. + # See: https://www.lora-alliance.org/lorawan-for-developers + [network_server.band] + name="EU_433" + + + # LoRaWAN network related settings. + [network_server.network_settings] + + # Extra channel configuration. + # + # Use this for LoRaWAN regions where it is possible to extend the by default + # available channels with additional channels (e.g. the EU band). + # The first 5 channels will be configured as part of the OTAA join-response + # (using the CFList field). + # The other channels (or channel / data-rate changes) will be (re)configured + # using the NewChannelReq mac-command. + # +# [[network_server.network_settings.extra_channels]] +# frequency=867100000 +# min_dr=0 +# max_dr=5 + +# [[network_server.network_settings.extra_channels]] +# frequency=867300000 +# min_dr=0 +# max_dr=5 + +# [[network_server.network_settings.extra_channels]] +# frequency=867500000 +# min_dr=0 +# max_dr=5 + +# [[network_server.network_settings.extra_channels]] +# frequency=867700000 +# min_dr=0 +# max_dr=5 + +# [[network_server.network_settings.extra_channels]] +# frequency=867900000 +# min_dr=0 +# max_dr=5 + + + # Class B settings + [network_server.network_settings.class_b] + # Ping-slot data-rate. + ping_slot_dr=0 + + # Ping-slot frequency (Hz) + # + # Set this to 0 to use the default frequency plan for the configured region + # (which could be frequency hopping). + ping_slot_frequency=0 + + + # Network-server API + # + # This is the network-server API that is used by LoRa App Server or other + # custom components interacting with LoRa Server. + [network_server.api] + # ip:port to bind the api server + bind="0.0.0.0:8000" + + + # Backend defines the gateway backend settings. + # + # The gateway backend handles the communication with the gateway(s) part of + # the LoRaWAN network. + [network_server.gateway.backend] + # Backend + type="mqtt" + + + # MQTT gateway backend settings. + # + # This is the backend communicating with the LoRa gateways over a MQTT broker. + [network_server.gateway.backend.mqtt] + # MQTT topic templates for the different MQTT topics. + # + # The meaning of these topics are documented at: + # https://www.loraserver.io/lora-gateway-bridge/ + # + # The default values match the default expected configuration of the + # LoRa Gateway Bridge MQTT backend. Therefore only change these values when + # absolutely needed. + + # Event topic template. + event_topic="gateway/+/event/+" + + # Command topic template. + # + # Use: + # * "{{ .GatewayID }}" as an substitution for the LoRa gateway ID + # * "{{ .CommandType }}" as an substitution for the command type + command_topic_template="gateway/{{ .GatewayID }}/command/{{ .CommandType }}" + + # MQTT server (e.g. scheme://host:port where scheme is tcp, ssl or ws) + server="tcp://localhost:1883" + + # Connect with the given username (optional) + username="" + + # Connect with the given password (optional) + password="" + + +# Metrics collection settings. +[metrics] +# Timezone +# +# The timezone is used for correctly aggregating the metrics (e.g. per hour, +# day or month). +# Example: "Europe/Amsterdam" or "Local" for the the system's local time zone. +timezone="Local" + + +# Join-server settings. +[join_server] + + # Default join-server settings. + # + # This join-server will be used when resolving the JoinEUI is set to false + # or as a fallback when resolving the JoinEUI fails. + [join_server.default] + # hostname:port of the default join-server + # + # This API is provided by LoRa App Server. + server="http://localhost:8003" + diff --git a/loraserver/loraserver_conf/loraserver.eu_863_870.toml b/loraserver/loraserver_conf/loraserver.eu_863_870.toml new file mode 100644 index 0000000..d968009 --- /dev/null +++ b/loraserver/loraserver_conf/loraserver.eu_863_870.toml @@ -0,0 +1,191 @@ +# This configuration configures LoRa Server for the EU868 band using a MQTT +# broker to communicate with the gateways. Many options and defaults have been +# omitted for simplicity. +# +# For other bands, see the ./examples/ sub-directory. + + +# PostgreSQL settings. +# +# Please note that PostgreSQL 9.5+ is required. +[postgresql] +# PostgreSQL dsn (e.g.: postgres://user:password@hostname/database?sslmode=disable). +# +# Besides using an URL (e.g. 'postgres://user:password@hostname/database?sslmode=disable') +# it is also possible to use the following format: +# 'user=loraserver dbname=loraserver sslmode=disable'. +# +# The following connection parameters are supported: +# +# * dbname - The name of the database to connect to +# * user - The user to sign in as +# * password - The user's password +# * host - The host to connect to. Values that start with / are for unix domain sockets. (default is localhost) +# * port - The port to bind to. (default is 5432) +# * sslmode - Whether or not to use SSL (default is require, this is not the default for libpq) +# * fallback_application_name - An application_name to fall back to if one isn't provided. +# * connect_timeout - Maximum wait for connection, in seconds. Zero or not specified means wait indefinitely. +# * sslcert - Cert file location. The file must contain PEM encoded data. +# * sslkey - Key file location. The file must contain PEM encoded data. +# * sslrootcert - The location of the root certificate file. The file must contain PEM encoded data. +# +# Valid values for sslmode are: +# +# * disable - No SSL +# * require - Always SSL (skip verification) +# * verify-ca - Always SSL (verify that the certificate presented by the server was signed by a trusted CA) +# * verify-full - Always SSL (verify that the certification presented by the server was signed by a trusted CA and the server host name matches the one in the certificate) +#dsn="postgres://localhost/loraserver_ns?sslmode=disable" +dsn="postgres://loraserver_ns:dbpassword@localhost/loraserver_ns?sslmode=disable" + + +# Redis settings +# +# Please note that Redis 2.6.0+ is required. +[redis] +# Redis url (e.g. redis://user:password@hostname/0) +# +# For more information about the Redis URL format, see: +# https://www.iana.org/assignments/uri-schemes/prov/redis +url="redis://localhost:6379" + + +# Network-server settings. +[network_server] +# Network identifier (NetID, 3 bytes) encoded as HEX (e.g. 010203) +net_id="000000" + + + # LoRaWAN regional band configuration. + # + # Note that you might want to consult the LoRaWAN Regional Parameters + # specification for valid values that apply to your region. + # See: https://www.lora-alliance.org/lorawan-for-developers + [network_server.band] + name="EU_863_870" + + + # LoRaWAN network related settings. + [network_server.network_settings] + + # Extra channel configuration. + # + # Use this for LoRaWAN regions where it is possible to extend the by default + # available channels with additional channels (e.g. the EU band). + # The first 5 channels will be configured as part of the OTAA join-response + # (using the CFList field). + # The other channels (or channel / data-rate changes) will be (re)configured + # using the NewChannelReq mac-command. + # +# [[network_server.network_settings.extra_channels]] +# frequency=867100000 +# min_dr=0 +# max_dr=5 + +# [[network_server.network_settings.extra_channels]] +# frequency=867300000 +# min_dr=0 +# max_dr=5 + +# [[network_server.network_settings.extra_channels]] +# frequency=867500000 +# min_dr=0 +# max_dr=5 + +# [[network_server.network_settings.extra_channels]] +# frequency=867700000 +# min_dr=0 +# max_dr=5 + +# [[network_server.network_settings.extra_channels]] +# frequency=867900000 +# min_dr=0 +# max_dr=5 + + + # Class B settings + [network_server.network_settings.class_b] + # Ping-slot data-rate. + ping_slot_dr=0 + + # Ping-slot frequency (Hz) + # + # Set this to 0 to use the default frequency plan for the configured region + # (which could be frequency hopping). + ping_slot_frequency=0 + + + # Network-server API + # + # This is the network-server API that is used by LoRa App Server or other + # custom components interacting with LoRa Server. + [network_server.api] + # ip:port to bind the api server + bind="0.0.0.0:8000" + + + # Backend defines the gateway backend settings. + # + # The gateway backend handles the communication with the gateway(s) part of + # the LoRaWAN network. + [network_server.gateway.backend] + # Backend + type="mqtt" + + + # MQTT gateway backend settings. + # + # This is the backend communicating with the LoRa gateways over a MQTT broker. + [network_server.gateway.backend.mqtt] + # MQTT topic templates for the different MQTT topics. + # + # The meaning of these topics are documented at: + # https://www.loraserver.io/lora-gateway-bridge/ + # + # The default values match the default expected configuration of the + # LoRa Gateway Bridge MQTT backend. Therefore only change these values when + # absolutely needed. + + # Event topic template. + event_topic="gateway/+/event/+" + + # Command topic template. + # + # Use: + # * "{{ .GatewayID }}" as an substitution for the LoRa gateway ID + # * "{{ .CommandType }}" as an substitution for the command type + command_topic_template="gateway/{{ .GatewayID }}/command/{{ .CommandType }}" + + # MQTT server (e.g. scheme://host:port where scheme is tcp, ssl or ws) + server="tcp://localhost:1883" + + # Connect with the given username (optional) + username="" + + # Connect with the given password (optional) + password="" + + +# Metrics collection settings. +[metrics] +# Timezone +# +# The timezone is used for correctly aggregating the metrics (e.g. per hour, +# day or month). +# Example: "Europe/Amsterdam" or "Local" for the the system's local time zone. +timezone="Local" + + +# Join-server settings. +[join_server] + + # Default join-server settings. + # + # This join-server will be used when resolving the JoinEUI is set to false + # or as a fallback when resolving the JoinEUI fails. + [join_server.default] + # hostname:port of the default join-server + # + # This API is provided by LoRa App Server. + server="http://localhost:8003" + diff --git a/loraserver/loraserver_conf/loraserver.in_865_867.toml b/loraserver/loraserver_conf/loraserver.in_865_867.toml new file mode 100644 index 0000000..af3567d --- /dev/null +++ b/loraserver/loraserver_conf/loraserver.in_865_867.toml @@ -0,0 +1,191 @@ +# This configuration configures LoRa Server for the EU868 band using a MQTT +# broker to communicate with the gateways. Many options and defaults have been +# omitted for simplicity. +# +# For other bands, see the ./examples/ sub-directory. + + +# PostgreSQL settings. +# +# Please note that PostgreSQL 9.5+ is required. +[postgresql] +# PostgreSQL dsn (e.g.: postgres://user:password@hostname/database?sslmode=disable). +# +# Besides using an URL (e.g. 'postgres://user:password@hostname/database?sslmode=disable') +# it is also possible to use the following format: +# 'user=loraserver dbname=loraserver sslmode=disable'. +# +# The following connection parameters are supported: +# +# * dbname - The name of the database to connect to +# * user - The user to sign in as +# * password - The user's password +# * host - The host to connect to. Values that start with / are for unix domain sockets. (default is localhost) +# * port - The port to bind to. (default is 5432) +# * sslmode - Whether or not to use SSL (default is require, this is not the default for libpq) +# * fallback_application_name - An application_name to fall back to if one isn't provided. +# * connect_timeout - Maximum wait for connection, in seconds. Zero or not specified means wait indefinitely. +# * sslcert - Cert file location. The file must contain PEM encoded data. +# * sslkey - Key file location. The file must contain PEM encoded data. +# * sslrootcert - The location of the root certificate file. The file must contain PEM encoded data. +# +# Valid values for sslmode are: +# +# * disable - No SSL +# * require - Always SSL (skip verification) +# * verify-ca - Always SSL (verify that the certificate presented by the server was signed by a trusted CA) +# * verify-full - Always SSL (verify that the certification presented by the server was signed by a trusted CA and the server host name matches the one in the certificate) +#dsn="postgres://localhost/loraserver_ns?sslmode=disable" +dsn="postgres://loraserver_ns:dbpassword@localhost/loraserver_ns?sslmode=disable" + + +# Redis settings +# +# Please note that Redis 2.6.0+ is required. +[redis] +# Redis url (e.g. redis://user:password@hostname/0) +# +# For more information about the Redis URL format, see: +# https://www.iana.org/assignments/uri-schemes/prov/redis +url="redis://localhost:6379" + + +# Network-server settings. +[network_server] +# Network identifier (NetID, 3 bytes) encoded as HEX (e.g. 010203) +net_id="000000" + + + # LoRaWAN regional band configuration. + # + # Note that you might want to consult the LoRaWAN Regional Parameters + # specification for valid values that apply to your region. + # See: https://www.lora-alliance.org/lorawan-for-developers + [network_server.band] + name="IN_865_867" + + + # LoRaWAN network related settings. + [network_server.network_settings] + + # Extra channel configuration. + # + # Use this for LoRaWAN regions where it is possible to extend the by default + # available channels with additional channels (e.g. the EU band). + # The first 5 channels will be configured as part of the OTAA join-response + # (using the CFList field). + # The other channels (or channel / data-rate changes) will be (re)configured + # using the NewChannelReq mac-command. + # +# [[network_server.network_settings.extra_channels]] +# frequency=867100000 +# min_dr=0 +# max_dr=5 + +# [[network_server.network_settings.extra_channels]] +# frequency=867300000 +# min_dr=0 +# max_dr=5 + +# [[network_server.network_settings.extra_channels]] +# frequency=867500000 +# min_dr=0 +# max_dr=5 + +# [[network_server.network_settings.extra_channels]] +# frequency=867700000 +# min_dr=0 +# max_dr=5 + +# [[network_server.network_settings.extra_channels]] +# frequency=867900000 +# min_dr=0 +# max_dr=5 + + + # Class B settings + [network_server.network_settings.class_b] + # Ping-slot data-rate. + ping_slot_dr=0 + + # Ping-slot frequency (Hz) + # + # Set this to 0 to use the default frequency plan for the configured region + # (which could be frequency hopping). + ping_slot_frequency=0 + + + # Network-server API + # + # This is the network-server API that is used by LoRa App Server or other + # custom components interacting with LoRa Server. + [network_server.api] + # ip:port to bind the api server + bind="0.0.0.0:8000" + + + # Backend defines the gateway backend settings. + # + # The gateway backend handles the communication with the gateway(s) part of + # the LoRaWAN network. + [network_server.gateway.backend] + # Backend + type="mqtt" + + + # MQTT gateway backend settings. + # + # This is the backend communicating with the LoRa gateways over a MQTT broker. + [network_server.gateway.backend.mqtt] + # MQTT topic templates for the different MQTT topics. + # + # The meaning of these topics are documented at: + # https://www.loraserver.io/lora-gateway-bridge/ + # + # The default values match the default expected configuration of the + # LoRa Gateway Bridge MQTT backend. Therefore only change these values when + # absolutely needed. + + # Event topic template. + event_topic="gateway/+/event/+" + + # Command topic template. + # + # Use: + # * "{{ .GatewayID }}" as an substitution for the LoRa gateway ID + # * "{{ .CommandType }}" as an substitution for the command type + command_topic_template="gateway/{{ .GatewayID }}/command/{{ .CommandType }}" + + # MQTT server (e.g. scheme://host:port where scheme is tcp, ssl or ws) + server="tcp://localhost:1883" + + # Connect with the given username (optional) + username="" + + # Connect with the given password (optional) + password="" + + +# Metrics collection settings. +[metrics] +# Timezone +# +# The timezone is used for correctly aggregating the metrics (e.g. per hour, +# day or month). +# Example: "Europe/Amsterdam" or "Local" for the the system's local time zone. +timezone="Local" + + +# Join-server settings. +[join_server] + + # Default join-server settings. + # + # This join-server will be used when resolving the JoinEUI is set to false + # or as a fallback when resolving the JoinEUI fails. + [join_server.default] + # hostname:port of the default join-server + # + # This API is provided by LoRa App Server. + server="http://localhost:8003" + diff --git a/loraserver/loraserver_conf/loraserver.kr_920_923.toml b/loraserver/loraserver_conf/loraserver.kr_920_923.toml new file mode 100644 index 0000000..3e3a704 --- /dev/null +++ b/loraserver/loraserver_conf/loraserver.kr_920_923.toml @@ -0,0 +1,191 @@ +# This configuration configures LoRa Server for the EU868 band using a MQTT +# broker to communicate with the gateways. Many options and defaults have been +# omitted for simplicity. +# +# For other bands, see the ./examples/ sub-directory. + + +# PostgreSQL settings. +# +# Please note that PostgreSQL 9.5+ is required. +[postgresql] +# PostgreSQL dsn (e.g.: postgres://user:password@hostname/database?sslmode=disable). +# +# Besides using an URL (e.g. 'postgres://user:password@hostname/database?sslmode=disable') +# it is also possible to use the following format: +# 'user=loraserver dbname=loraserver sslmode=disable'. +# +# The following connection parameters are supported: +# +# * dbname - The name of the database to connect to +# * user - The user to sign in as +# * password - The user's password +# * host - The host to connect to. Values that start with / are for unix domain sockets. (default is localhost) +# * port - The port to bind to. (default is 5432) +# * sslmode - Whether or not to use SSL (default is require, this is not the default for libpq) +# * fallback_application_name - An application_name to fall back to if one isn't provided. +# * connect_timeout - Maximum wait for connection, in seconds. Zero or not specified means wait indefinitely. +# * sslcert - Cert file location. The file must contain PEM encoded data. +# * sslkey - Key file location. The file must contain PEM encoded data. +# * sslrootcert - The location of the root certificate file. The file must contain PEM encoded data. +# +# Valid values for sslmode are: +# +# * disable - No SSL +# * require - Always SSL (skip verification) +# * verify-ca - Always SSL (verify that the certificate presented by the server was signed by a trusted CA) +# * verify-full - Always SSL (verify that the certification presented by the server was signed by a trusted CA and the server host name matches the one in the certificate) +#dsn="postgres://localhost/loraserver_ns?sslmode=disable" +dsn="postgres://loraserver_ns:dbpassword@localhost/loraserver_ns?sslmode=disable" + + +# Redis settings +# +# Please note that Redis 2.6.0+ is required. +[redis] +# Redis url (e.g. redis://user:password@hostname/0) +# +# For more information about the Redis URL format, see: +# https://www.iana.org/assignments/uri-schemes/prov/redis +url="redis://localhost:6379" + + +# Network-server settings. +[network_server] +# Network identifier (NetID, 3 bytes) encoded as HEX (e.g. 010203) +net_id="000000" + + + # LoRaWAN regional band configuration. + # + # Note that you might want to consult the LoRaWAN Regional Parameters + # specification for valid values that apply to your region. + # See: https://www.lora-alliance.org/lorawan-for-developers + [network_server.band] + name="KR_920_923" + + + # LoRaWAN network related settings. + [network_server.network_settings] + + # Extra channel configuration. + # + # Use this for LoRaWAN regions where it is possible to extend the by default + # available channels with additional channels (e.g. the EU band). + # The first 5 channels will be configured as part of the OTAA join-response + # (using the CFList field). + # The other channels (or channel / data-rate changes) will be (re)configured + # using the NewChannelReq mac-command. + # +# [[network_server.network_settings.extra_channels]] +# frequency=867100000 +# min_dr=0 +# max_dr=5 + +# [[network_server.network_settings.extra_channels]] +# frequency=867300000 +# min_dr=0 +# max_dr=5 + +# [[network_server.network_settings.extra_channels]] +# frequency=867500000 +# min_dr=0 +# max_dr=5 + +# [[network_server.network_settings.extra_channels]] +# frequency=867700000 +# min_dr=0 +# max_dr=5 + +# [[network_server.network_settings.extra_channels]] +# frequency=867900000 +# min_dr=0 +# max_dr=5 + + + # Class B settings + [network_server.network_settings.class_b] + # Ping-slot data-rate. + ping_slot_dr=0 + + # Ping-slot frequency (Hz) + # + # Set this to 0 to use the default frequency plan for the configured region + # (which could be frequency hopping). + ping_slot_frequency=0 + + + # Network-server API + # + # This is the network-server API that is used by LoRa App Server or other + # custom components interacting with LoRa Server. + [network_server.api] + # ip:port to bind the api server + bind="0.0.0.0:8000" + + + # Backend defines the gateway backend settings. + # + # The gateway backend handles the communication with the gateway(s) part of + # the LoRaWAN network. + [network_server.gateway.backend] + # Backend + type="mqtt" + + + # MQTT gateway backend settings. + # + # This is the backend communicating with the LoRa gateways over a MQTT broker. + [network_server.gateway.backend.mqtt] + # MQTT topic templates for the different MQTT topics. + # + # The meaning of these topics are documented at: + # https://www.loraserver.io/lora-gateway-bridge/ + # + # The default values match the default expected configuration of the + # LoRa Gateway Bridge MQTT backend. Therefore only change these values when + # absolutely needed. + + # Event topic template. + event_topic="gateway/+/event/+" + + # Command topic template. + # + # Use: + # * "{{ .GatewayID }}" as an substitution for the LoRa gateway ID + # * "{{ .CommandType }}" as an substitution for the command type + command_topic_template="gateway/{{ .GatewayID }}/command/{{ .CommandType }}" + + # MQTT server (e.g. scheme://host:port where scheme is tcp, ssl or ws) + server="tcp://localhost:1883" + + # Connect with the given username (optional) + username="" + + # Connect with the given password (optional) + password="" + + +# Metrics collection settings. +[metrics] +# Timezone +# +# The timezone is used for correctly aggregating the metrics (e.g. per hour, +# day or month). +# Example: "Europe/Amsterdam" or "Local" for the the system's local time zone. +timezone="Local" + + +# Join-server settings. +[join_server] + + # Default join-server settings. + # + # This join-server will be used when resolving the JoinEUI is set to false + # or as a fallback when resolving the JoinEUI fails. + [join_server.default] + # hostname:port of the default join-server + # + # This API is provided by LoRa App Server. + server="http://localhost:8003" + diff --git a/loraserver/loraserver_conf/loraserver.ru_864_870.toml b/loraserver/loraserver_conf/loraserver.ru_864_870.toml new file mode 100644 index 0000000..90d70e6 --- /dev/null +++ b/loraserver/loraserver_conf/loraserver.ru_864_870.toml @@ -0,0 +1,191 @@ +# This configuration configures LoRa Server for the EU868 band using a MQTT +# broker to communicate with the gateways. Many options and defaults have been +# omitted for simplicity. +# +# For other bands, see the ./examples/ sub-directory. + + +# PostgreSQL settings. +# +# Please note that PostgreSQL 9.5+ is required. +[postgresql] +# PostgreSQL dsn (e.g.: postgres://user:password@hostname/database?sslmode=disable). +# +# Besides using an URL (e.g. 'postgres://user:password@hostname/database?sslmode=disable') +# it is also possible to use the following format: +# 'user=loraserver dbname=loraserver sslmode=disable'. +# +# The following connection parameters are supported: +# +# * dbname - The name of the database to connect to +# * user - The user to sign in as +# * password - The user's password +# * host - The host to connect to. Values that start with / are for unix domain sockets. (default is localhost) +# * port - The port to bind to. (default is 5432) +# * sslmode - Whether or not to use SSL (default is require, this is not the default for libpq) +# * fallback_application_name - An application_name to fall back to if one isn't provided. +# * connect_timeout - Maximum wait for connection, in seconds. Zero or not specified means wait indefinitely. +# * sslcert - Cert file location. The file must contain PEM encoded data. +# * sslkey - Key file location. The file must contain PEM encoded data. +# * sslrootcert - The location of the root certificate file. The file must contain PEM encoded data. +# +# Valid values for sslmode are: +# +# * disable - No SSL +# * require - Always SSL (skip verification) +# * verify-ca - Always SSL (verify that the certificate presented by the server was signed by a trusted CA) +# * verify-full - Always SSL (verify that the certification presented by the server was signed by a trusted CA and the server host name matches the one in the certificate) +#dsn="postgres://localhost/loraserver_ns?sslmode=disable" +dsn="postgres://loraserver_ns:dbpassword@localhost/loraserver_ns?sslmode=disable" + + +# Redis settings +# +# Please note that Redis 2.6.0+ is required. +[redis] +# Redis url (e.g. redis://user:password@hostname/0) +# +# For more information about the Redis URL format, see: +# https://www.iana.org/assignments/uri-schemes/prov/redis +url="redis://localhost:6379" + + +# Network-server settings. +[network_server] +# Network identifier (NetID, 3 bytes) encoded as HEX (e.g. 010203) +net_id="000000" + + + # LoRaWAN regional band configuration. + # + # Note that you might want to consult the LoRaWAN Regional Parameters + # specification for valid values that apply to your region. + # See: https://www.lora-alliance.org/lorawan-for-developers + [network_server.band] + name="RU_864_870" + + + # LoRaWAN network related settings. + [network_server.network_settings] + + # Extra channel configuration. + # + # Use this for LoRaWAN regions where it is possible to extend the by default + # available channels with additional channels (e.g. the EU band). + # The first 5 channels will be configured as part of the OTAA join-response + # (using the CFList field). + # The other channels (or channel / data-rate changes) will be (re)configured + # using the NewChannelReq mac-command. + # +# [[network_server.network_settings.extra_channels]] +# frequency=867100000 +# min_dr=0 +# max_dr=5 + +# [[network_server.network_settings.extra_channels]] +# frequency=867300000 +# min_dr=0 +# max_dr=5 + +# [[network_server.network_settings.extra_channels]] +# frequency=867500000 +# min_dr=0 +# max_dr=5 + +# [[network_server.network_settings.extra_channels]] +# frequency=867700000 +# min_dr=0 +# max_dr=5 + +# [[network_server.network_settings.extra_channels]] +# frequency=867900000 +# min_dr=0 +# max_dr=5 + + + # Class B settings + [network_server.network_settings.class_b] + # Ping-slot data-rate. + ping_slot_dr=0 + + # Ping-slot frequency (Hz) + # + # Set this to 0 to use the default frequency plan for the configured region + # (which could be frequency hopping). + ping_slot_frequency=0 + + + # Network-server API + # + # This is the network-server API that is used by LoRa App Server or other + # custom components interacting with LoRa Server. + [network_server.api] + # ip:port to bind the api server + bind="0.0.0.0:8000" + + + # Backend defines the gateway backend settings. + # + # The gateway backend handles the communication with the gateway(s) part of + # the LoRaWAN network. + [network_server.gateway.backend] + # Backend + type="mqtt" + + + # MQTT gateway backend settings. + # + # This is the backend communicating with the LoRa gateways over a MQTT broker. + [network_server.gateway.backend.mqtt] + # MQTT topic templates for the different MQTT topics. + # + # The meaning of these topics are documented at: + # https://www.loraserver.io/lora-gateway-bridge/ + # + # The default values match the default expected configuration of the + # LoRa Gateway Bridge MQTT backend. Therefore only change these values when + # absolutely needed. + + # Event topic template. + event_topic="gateway/+/event/+" + + # Command topic template. + # + # Use: + # * "{{ .GatewayID }}" as an substitution for the LoRa gateway ID + # * "{{ .CommandType }}" as an substitution for the command type + command_topic_template="gateway/{{ .GatewayID }}/command/{{ .CommandType }}" + + # MQTT server (e.g. scheme://host:port where scheme is tcp, ssl or ws) + server="tcp://localhost:1883" + + # Connect with the given username (optional) + username="" + + # Connect with the given password (optional) + password="" + + +# Metrics collection settings. +[metrics] +# Timezone +# +# The timezone is used for correctly aggregating the metrics (e.g. per hour, +# day or month). +# Example: "Europe/Amsterdam" or "Local" for the the system's local time zone. +timezone="Local" + + +# Join-server settings. +[join_server] + + # Default join-server settings. + # + # This join-server will be used when resolving the JoinEUI is set to false + # or as a fallback when resolving the JoinEUI fails. + [join_server.default] + # hostname:port of the default join-server + # + # This API is provided by LoRa App Server. + server="http://localhost:8003" + diff --git a/loraserver/loraserver_conf/loraserver.toml b/loraserver/loraserver_conf/loraserver.toml new file mode 100644 index 0000000..d968009 --- /dev/null +++ b/loraserver/loraserver_conf/loraserver.toml @@ -0,0 +1,191 @@ +# This configuration configures LoRa Server for the EU868 band using a MQTT +# broker to communicate with the gateways. Many options and defaults have been +# omitted for simplicity. +# +# For other bands, see the ./examples/ sub-directory. + + +# PostgreSQL settings. +# +# Please note that PostgreSQL 9.5+ is required. +[postgresql] +# PostgreSQL dsn (e.g.: postgres://user:password@hostname/database?sslmode=disable). +# +# Besides using an URL (e.g. 'postgres://user:password@hostname/database?sslmode=disable') +# it is also possible to use the following format: +# 'user=loraserver dbname=loraserver sslmode=disable'. +# +# The following connection parameters are supported: +# +# * dbname - The name of the database to connect to +# * user - The user to sign in as +# * password - The user's password +# * host - The host to connect to. Values that start with / are for unix domain sockets. (default is localhost) +# * port - The port to bind to. (default is 5432) +# * sslmode - Whether or not to use SSL (default is require, this is not the default for libpq) +# * fallback_application_name - An application_name to fall back to if one isn't provided. +# * connect_timeout - Maximum wait for connection, in seconds. Zero or not specified means wait indefinitely. +# * sslcert - Cert file location. The file must contain PEM encoded data. +# * sslkey - Key file location. The file must contain PEM encoded data. +# * sslrootcert - The location of the root certificate file. The file must contain PEM encoded data. +# +# Valid values for sslmode are: +# +# * disable - No SSL +# * require - Always SSL (skip verification) +# * verify-ca - Always SSL (verify that the certificate presented by the server was signed by a trusted CA) +# * verify-full - Always SSL (verify that the certification presented by the server was signed by a trusted CA and the server host name matches the one in the certificate) +#dsn="postgres://localhost/loraserver_ns?sslmode=disable" +dsn="postgres://loraserver_ns:dbpassword@localhost/loraserver_ns?sslmode=disable" + + +# Redis settings +# +# Please note that Redis 2.6.0+ is required. +[redis] +# Redis url (e.g. redis://user:password@hostname/0) +# +# For more information about the Redis URL format, see: +# https://www.iana.org/assignments/uri-schemes/prov/redis +url="redis://localhost:6379" + + +# Network-server settings. +[network_server] +# Network identifier (NetID, 3 bytes) encoded as HEX (e.g. 010203) +net_id="000000" + + + # LoRaWAN regional band configuration. + # + # Note that you might want to consult the LoRaWAN Regional Parameters + # specification for valid values that apply to your region. + # See: https://www.lora-alliance.org/lorawan-for-developers + [network_server.band] + name="EU_863_870" + + + # LoRaWAN network related settings. + [network_server.network_settings] + + # Extra channel configuration. + # + # Use this for LoRaWAN regions where it is possible to extend the by default + # available channels with additional channels (e.g. the EU band). + # The first 5 channels will be configured as part of the OTAA join-response + # (using the CFList field). + # The other channels (or channel / data-rate changes) will be (re)configured + # using the NewChannelReq mac-command. + # +# [[network_server.network_settings.extra_channels]] +# frequency=867100000 +# min_dr=0 +# max_dr=5 + +# [[network_server.network_settings.extra_channels]] +# frequency=867300000 +# min_dr=0 +# max_dr=5 + +# [[network_server.network_settings.extra_channels]] +# frequency=867500000 +# min_dr=0 +# max_dr=5 + +# [[network_server.network_settings.extra_channels]] +# frequency=867700000 +# min_dr=0 +# max_dr=5 + +# [[network_server.network_settings.extra_channels]] +# frequency=867900000 +# min_dr=0 +# max_dr=5 + + + # Class B settings + [network_server.network_settings.class_b] + # Ping-slot data-rate. + ping_slot_dr=0 + + # Ping-slot frequency (Hz) + # + # Set this to 0 to use the default frequency plan for the configured region + # (which could be frequency hopping). + ping_slot_frequency=0 + + + # Network-server API + # + # This is the network-server API that is used by LoRa App Server or other + # custom components interacting with LoRa Server. + [network_server.api] + # ip:port to bind the api server + bind="0.0.0.0:8000" + + + # Backend defines the gateway backend settings. + # + # The gateway backend handles the communication with the gateway(s) part of + # the LoRaWAN network. + [network_server.gateway.backend] + # Backend + type="mqtt" + + + # MQTT gateway backend settings. + # + # This is the backend communicating with the LoRa gateways over a MQTT broker. + [network_server.gateway.backend.mqtt] + # MQTT topic templates for the different MQTT topics. + # + # The meaning of these topics are documented at: + # https://www.loraserver.io/lora-gateway-bridge/ + # + # The default values match the default expected configuration of the + # LoRa Gateway Bridge MQTT backend. Therefore only change these values when + # absolutely needed. + + # Event topic template. + event_topic="gateway/+/event/+" + + # Command topic template. + # + # Use: + # * "{{ .GatewayID }}" as an substitution for the LoRa gateway ID + # * "{{ .CommandType }}" as an substitution for the command type + command_topic_template="gateway/{{ .GatewayID }}/command/{{ .CommandType }}" + + # MQTT server (e.g. scheme://host:port where scheme is tcp, ssl or ws) + server="tcp://localhost:1883" + + # Connect with the given username (optional) + username="" + + # Connect with the given password (optional) + password="" + + +# Metrics collection settings. +[metrics] +# Timezone +# +# The timezone is used for correctly aggregating the metrics (e.g. per hour, +# day or month). +# Example: "Europe/Amsterdam" or "Local" for the the system's local time zone. +timezone="Local" + + +# Join-server settings. +[join_server] + + # Default join-server settings. + # + # This join-server will be used when resolving the JoinEUI is set to false + # or as a fallback when resolving the JoinEUI fails. + [join_server.default] + # hostname:port of the default join-server + # + # This API is provided by LoRa App Server. + server="http://localhost:8003" + diff --git a/loraserver/loraserver_conf/loraserver.us_902_928.toml b/loraserver/loraserver_conf/loraserver.us_902_928.toml new file mode 100644 index 0000000..4702477 --- /dev/null +++ b/loraserver/loraserver_conf/loraserver.us_902_928.toml @@ -0,0 +1,191 @@ +# This configuration configures LoRa Server for the EU868 band using a MQTT +# broker to communicate with the gateways. Many options and defaults have been +# omitted for simplicity. +# +# For other bands, see the ./examples/ sub-directory. + + +# PostgreSQL settings. +# +# Please note that PostgreSQL 9.5+ is required. +[postgresql] +# PostgreSQL dsn (e.g.: postgres://user:password@hostname/database?sslmode=disable). +# +# Besides using an URL (e.g. 'postgres://user:password@hostname/database?sslmode=disable') +# it is also possible to use the following format: +# 'user=loraserver dbname=loraserver sslmode=disable'. +# +# The following connection parameters are supported: +# +# * dbname - The name of the database to connect to +# * user - The user to sign in as +# * password - The user's password +# * host - The host to connect to. Values that start with / are for unix domain sockets. (default is localhost) +# * port - The port to bind to. (default is 5432) +# * sslmode - Whether or not to use SSL (default is require, this is not the default for libpq) +# * fallback_application_name - An application_name to fall back to if one isn't provided. +# * connect_timeout - Maximum wait for connection, in seconds. Zero or not specified means wait indefinitely. +# * sslcert - Cert file location. The file must contain PEM encoded data. +# * sslkey - Key file location. The file must contain PEM encoded data. +# * sslrootcert - The location of the root certificate file. The file must contain PEM encoded data. +# +# Valid values for sslmode are: +# +# * disable - No SSL +# * require - Always SSL (skip verification) +# * verify-ca - Always SSL (verify that the certificate presented by the server was signed by a trusted CA) +# * verify-full - Always SSL (verify that the certification presented by the server was signed by a trusted CA and the server host name matches the one in the certificate) +#dsn="postgres://localhost/loraserver_ns?sslmode=disable" +dsn="postgres://loraserver_ns:dbpassword@localhost/loraserver_ns?sslmode=disable" + + +# Redis settings +# +# Please note that Redis 2.6.0+ is required. +[redis] +# Redis url (e.g. redis://user:password@hostname/0) +# +# For more information about the Redis URL format, see: +# https://www.iana.org/assignments/uri-schemes/prov/redis +url="redis://localhost:6379" + + +# Network-server settings. +[network_server] +# Network identifier (NetID, 3 bytes) encoded as HEX (e.g. 010203) +net_id="000000" + + + # LoRaWAN regional band configuration. + # + # Note that you might want to consult the LoRaWAN Regional Parameters + # specification for valid values that apply to your region. + # See: https://www.lora-alliance.org/lorawan-for-developers + [network_server.band] + name="US_902_928" + + + # LoRaWAN network related settings. + [network_server.network_settings] + + # Extra channel configuration. + # + # Use this for LoRaWAN regions where it is possible to extend the by default + # available channels with additional channels (e.g. the EU band). + # The first 5 channels will be configured as part of the OTAA join-response + # (using the CFList field). + # The other channels (or channel / data-rate changes) will be (re)configured + # using the NewChannelReq mac-command. + # +# [[network_server.network_settings.extra_channels]] +# frequency=867100000 +# min_dr=0 +# max_dr=5 + +# [[network_server.network_settings.extra_channels]] +# frequency=867300000 +# min_dr=0 +# max_dr=5 + +# [[network_server.network_settings.extra_channels]] +# frequency=867500000 +# min_dr=0 +# max_dr=5 + +# [[network_server.network_settings.extra_channels]] +# frequency=867700000 +# min_dr=0 +# max_dr=5 + +# [[network_server.network_settings.extra_channels]] +# frequency=867900000 +# min_dr=0 +# max_dr=5 + + + # Class B settings + [network_server.network_settings.class_b] + # Ping-slot data-rate. + ping_slot_dr=0 + + # Ping-slot frequency (Hz) + # + # Set this to 0 to use the default frequency plan for the configured region + # (which could be frequency hopping). + ping_slot_frequency=0 + + + # Network-server API + # + # This is the network-server API that is used by LoRa App Server or other + # custom components interacting with LoRa Server. + [network_server.api] + # ip:port to bind the api server + bind="0.0.0.0:8000" + + + # Backend defines the gateway backend settings. + # + # The gateway backend handles the communication with the gateway(s) part of + # the LoRaWAN network. + [network_server.gateway.backend] + # Backend + type="mqtt" + + + # MQTT gateway backend settings. + # + # This is the backend communicating with the LoRa gateways over a MQTT broker. + [network_server.gateway.backend.mqtt] + # MQTT topic templates for the different MQTT topics. + # + # The meaning of these topics are documented at: + # https://www.loraserver.io/lora-gateway-bridge/ + # + # The default values match the default expected configuration of the + # LoRa Gateway Bridge MQTT backend. Therefore only change these values when + # absolutely needed. + + # Event topic template. + event_topic="gateway/+/event/+" + + # Command topic template. + # + # Use: + # * "{{ .GatewayID }}" as an substitution for the LoRa gateway ID + # * "{{ .CommandType }}" as an substitution for the command type + command_topic_template="gateway/{{ .GatewayID }}/command/{{ .CommandType }}" + + # MQTT server (e.g. scheme://host:port where scheme is tcp, ssl or ws) + server="tcp://localhost:1883" + + # Connect with the given username (optional) + username="" + + # Connect with the given password (optional) + password="" + + +# Metrics collection settings. +[metrics] +# Timezone +# +# The timezone is used for correctly aggregating the metrics (e.g. per hour, +# day or month). +# Example: "Europe/Amsterdam" or "Local" for the the system's local time zone. +timezone="Local" + + +# Join-server settings. +[join_server] + + # Default join-server settings. + # + # This join-server will be used when resolving the JoinEUI is set to false + # or as a fallback when resolving the JoinEUI fails. + [join_server.default] + # hostname:port of the default join-server + # + # This API is provided by LoRa App Server. + server="http://localhost:8003" + diff --git a/lorawan/install.sh b/lorawan/install.sh new file mode 100755 index 0000000..2590091 --- /dev/null +++ b/lorawan/install.sh @@ -0,0 +1,26 @@ +#!/bin/bash + +# Stop on the first sign of trouble +set -e + +SCRIPT_COMMON_FILE=$(pwd)/../rak/rak/shell_script/rak_common.sh +JSON_FILE=/usr/local/rak/rak_gw_model.json +GLOBAL_SUB_DIR=serial + +if [ $UID != 0 ]; then + echo_error "Operation not permitted. Forgot sudo?" + exit 1 +fi + +source $SCRIPT_COMMON_FILE + +apt-get install erlang-base erlang-crypto erlang-syntax-tools erlang-inets erlang-mnesia erlang-runtime-tools erlang-ssl erlang-public-key erlang-asn1 erlang-os-mon erlang-snmp erlang-xmerl -y +dpkg -i lorawan-server_0.6.7_all.deb + +sudo sed -i 's#1680#1700#g' /usr/lib/lorawan-server/releases/0.6.7/sys.config + +systemctl disable lorawan-server +systemctl stop lorawan-server + +echo_success "\nLoraWan installed successfully.\n" + diff --git a/lorawan/lorawan-server_0.6.7_all.deb b/lorawan/lorawan-server_0.6.7_all.deb new file mode 100644 index 0000000..8095c84 Binary files /dev/null and b/lorawan/lorawan-server_0.6.7_all.deb differ diff --git a/lte/install.sh b/lte/install.sh new file mode 100755 index 0000000..136835b --- /dev/null +++ b/lte/install.sh @@ -0,0 +1,23 @@ +#!/bin/bash + +SCRIPT_COMMON_FILE=$(pwd)/../rak/rak/shell_script/rak_common.sh +source $SCRIPT_COMMON_FILE + +# Stop on the first sign of trouble +set -e + +if [ $UID != 0 ]; then + echo "ERROR: Operation not permitted. Forgot sudo?" + exit 1 +fi + +RAK_GW_MODEL=`do_get_gw_model` +if [ "${RAK_GW_MODEL}" = "RAK7243" ]; then + if [ ! -d "/usr/local/rak/lte" ]; then mkdir "/usr/local/rak/lte" -p ; fi + + cp ppp-creator.sh /usr/local/rak/lte/ + cp rak-pppd.service /lib/systemd/system + + echo_success "Install LTE module success!\n" + sleep 2 +fi diff --git a/lte/ppp-creator.sh b/lte/ppp-creator.sh new file mode 100755 index 0000000..23db257 --- /dev/null +++ b/lte/ppp-creator.sh @@ -0,0 +1,75 @@ +#!/bin/sh + +#echo "install ppp" +#apt-get install ppp + +echo "creating directories" +mkdir -p /etc/chatscripts +mkdir -p /etc/ppp/peers + +echo "creating script file : /etc/chatscripts/quectel-chat-connect" +echo " +ABORT \"BUSY\" +ABORT \"NO CARRIER\" +ABORT \"NO DIALTONE\" +ABORT \"ERROR\" +ABORT \"NO ANSWER\" +TIMEOUT 30 +\"\" AT +OK ATE0 +OK ATI;+CSUB;+CSQ;+COPS?;+CGREG?;&D2 +# Insert the APN provided by your network operator, default apn is $1 +OK AT+CGDCONT=1,\"IP\",\"\\T\",,0,0 +OK ATD*99# +CONNECT" > /etc/chatscripts/quectel-chat-connect + + +echo "creating script file : /etc/chatscripts/quectel-chat-disconnect" +echo " +ABORT \"ERROR\" +ABORT \"NO DIALTONE\" +SAY \"\nSending break to the modem\n\" +"" +++ +"" +++ +"" +++ +SAY \"\nGoodbay\n\"" > /etc/chatscripts/quectel-chat-disconnect + + +echo "creating script file : /etc/ppp/peers/gprs" +echo " +/dev/$2 $3 +# The chat script, customize your APN in this file +connect 'chat -s -v -f /etc/chatscripts/quectel-chat-connect -T $1' +# The close script +disconnect 'chat -s -v -f /etc/chatscripts/quectel-chat-disconnect' +# Hide password in debug messages +hide-password +# The phone is not required to authenticate +noauth +# Debug info from pppd +debug +# If you want to use the HSDPA link as your gateway +defaultroute +# pppd must not propose any IP address to the peer +noipdefault +# No ppp compression +novj +novjccomp +noccp +ipcp-accept-local +ipcp-accept-remote +local +# For sanity, keep a lock on the serial line +lock +modem +dump +nodetach +# Hardware flow control +nocrtscts +remotename 3gppp +ipparam 3gppp +ipcp-max-failure 30 +# Ask the peer for up to 2 DNS server addresses +usepeerdns" > /etc/ppp/peers/gprs + +echo "\n\nUse \"sudo pppd call gprs\" command and Surf" diff --git a/lte/rak-pppd.service b/lte/rak-pppd.service new file mode 100644 index 0000000..f41d98e --- /dev/null +++ b/lte/rak-pppd.service @@ -0,0 +1,12 @@ +[Unit] +Description=Rak pppd for LTE Module + +[Service] +WorkingDirectory=/usr/sbin/ +ExecStart=/usr/sbin/pppd call gprs +SyslogIdentifier=rak-pppd +Restart=on-failure +RestartSec=5 + +[Install] +WantedBy=multi-user.target diff --git a/rak/gateway-config b/rak/gateway-config new file mode 100755 index 0000000..82fec7e --- /dev/null +++ b/rak/gateway-config @@ -0,0 +1,880 @@ +#!/bin/bash + +source /usr/local/rak/shell_script/rak_common.sh + +GATEWAY_CONFIG_INFO=/usr/local/rak/gateway-config-info.json +LORA_PKT_PATH=/opt/ttn-gateway/packet_forwarder/lora_pkt_fwd + +do_if_proc_is_run() +{ + if [ -n "`pgrep $1`" ]; then + return 0 + else + return 1 + fi +} + +do_check_ipaddr() +{ + echo $1|grep "^[0-9]\{1,3\}\.\([0-9]\{1,3\}\.\)\{2\}[0-9]\{1,3\}$" > /dev/null; + if [ $? -ne 0 ] + then + echo "Bad IP address" + return 1 + fi + ipaddr=$1 + a=`echo $ipaddr|awk -F . '{print $1}'` + b=`echo $ipaddr|awk -F . '{print $2}'` + c=`echo $ipaddr|awk -F . '{print $3}'` + d=`echo $ipaddr|awk -F . '{print $4}'` + for num in $a $b $c $d + do + if [ $num -gt 255 ] || [ $num -lt 0 ] + then + echo "Bad IP address" + return 1 + fi + done + + return 0 +} + +do_get_gateway_info() +{ + + do_get_json_value $1 $GATEWAY_CONFIG_INFO +} + +do_check_ip_is_localhost() +{ + if [ "$1" = "localhost" ] || [ "$1" = "127.0.0.1" ]; then + return 0 + else + return 1 + fi +} + +write_json_gateway_info() +{ + # $1 key; $2 value + do_check_variable_type $1 + RET=$? + if [ $RET -eq 3 ]; then + sed -i "s/^.*$1.*$/\"$1\":\"$2\",/" $GATEWAY_CONFIG_INFO + fi +} + +write_json_gateway_info_no_comma() +{ + # $1 key; $2 value + do_check_variable_type $1 + RET=$? + if [ $RET -eq 3 ]; then + sed -i "s/^.*$1.*$/\"$1\":\"$2\"/" $GATEWAY_CONFIG_INFO + fi +} + +write_json_server_plan() +{ + write_json_gateway_info "server_plan" $1 +} + +write_json_server_freq() +{ + write_json_gateway_info_no_comma "freq" $1 +} + +write_json_lora_server_ip() +{ + # . 字母 数字 + write_json_gateway_info "lora_server_ip" $1 +} + +write_json_wifi_mode() +{ + # 数字 1/2 + write_json_gateway_info "wifi_mode" $1 +} + +write_json_ap_ssid() +{ + # 数字 字母 - _ + write_json_gateway_info "ap_ssid" $1 +} + +write_json_ap_pwd() +{ + # 数字 字母 特殊字符 + write_json_gateway_info_no_comma "ap_pwd" $1 +} + +write_json_lan_ip() +{ + # 数字 . 校验下是否为有效IP + write_json_gateway_info "lan_ip" $1 +} + +write_json_lan_gw() +{ + # 数字 . 校验下是否为有效IP + write_json_gateway_info_no_comma "lan_gw" $1 +} + +write_json_wlan_ip() +{ + # 数字 . 校验下是否为有效IP + write_json_gateway_info "wifi_ip" $1 +} + +write_json_wlan_gw() +{ + # 数字 . 校验下是否为有效IP + write_json_gateway_info_no_comma "wifi_gw" $1 +} + +write_json_apn_name() +{ + # 任意 + write_json_gateway_info "apn_name" $1 +} + +write_json_apn_baud() +{ + # 数字 + write_json_gateway_info_no_comma "apn_baud" $1 +} + +write_json_lte_mode() +{ + # 数字 + write_json_gateway_info_no_comma "lte_mode" $1 +} + +write_json_active_lora_server() +{ + write_json_gateway_info "active_lora_server" $1 +} + +do_setup_admin_password() { + dialog --title "Setup pi password" --yesno "You will be asked to enter a new password." 5 60 + RET=$? + if [ $RET -eq 0 ]; then + passwd pi + RET=$? + if [ $RET -eq 0 ]; then + dialog --title "Setup pi password" --msgbox "Password has been changed succesfully." 5 60 + fi + fi + do_main_menu +} + +do_restart_packet_forwarder() { + systemctl stop ttn-gateway + systemctl start ttn-gateway + RET=$? + if [ $RET -eq 0 ]; then + dialog --title "Restart packet-forwarder" --msgbox "The packet-forwarder has been restarted." 5 60 + fi + if [ $# -eq 0 ]; then + do_main_menu + fi +} + +do_copy_global_conf() { + cp $LORA_PKT_PATH/global_conf/global_conf.$2.json $LORA_PKT_PATH/global_conf.json + + if [ "$1" = "ttn" ]; then + dialog --title "Server-plan configuration" --msgbox "Server-plan configuration has been copied." 5 60 + write_json_server_plan 1 + elif [ "$1" = "loraserver" ]; then + write_json_server_plan 2 + do_set_lora_server_ip + cp /etc/loraserver/loraserver.$2.toml /etc/loraserver/loraserver.toml + do_if_proc_is_run "loraserver" + RET=$? + if [ $RET -eq 0 ]; then + do_LoRa_Server restart + fi + elif [ "$1" = "lorawan" ]; then + write_json_server_plan 3 + do_set_lora_server_ip + fi + + do_restart_packet_forwarder 1 +} + + + +do_setup_ttn_channel_plan() { + default_item=1 + FUN=$(dialog --title "TTN Channel-plan configuration" --default-item $default_item --menu "Select the Channel-plan:" 18 60 12 \ + 1 "AS_923" \ + 2 "AU_915_928" \ + 3 "CN_470_510" \ + 4 "EU_863_870" \ + 5 "IN_865_867" \ + 6 "KR_920_923" \ + 7 "RU_864_870" \ + 8 "US_902_928" \ + 3>&1 1>&2 2>&3) + RET=$? + if [ $RET -eq 1 ]; then + : + elif [ $RET -eq 0 ]; then + case "$FUN" in + 1) do_copy_global_conf "ttn" "as_923" 1;; + 2) do_copy_global_conf "ttn" "au_915_928" 2;; + 3) do_copy_global_conf "ttn" "cn_470_510" 3;; + 4) do_copy_global_conf "ttn" "eu_863_870" 4;; + 5) do_copy_global_conf "ttn" "in_865_867" 5;; + 6) do_copy_global_conf "ttn" "kr_920_923" 6;; + 7) do_copy_global_conf "ttn" "ru_864_870" 7;; + 8) do_copy_global_conf "ttn" "us_902_928" 8;; + esac + fi +} + +do_enable_loraserver() +{ + systemctl enable loraserver + systemctl enable lora-app-server + systemctl enable lora-gateway-bridge + systemctl restart loraserver + systemctl restart lora-app-server + systemctl restart lora-gateway-bridge +} + +do_disable_loraserver() +{ + systemctl disable loraserver + systemctl disable lora-app-server + systemctl disable lora-gateway-bridge + systemctl stop loraserver + systemctl stop lora-app-server + systemctl stop lora-gateway-bridge +} + +do_set_lora_server_ip() +{ + rm /tmp/gate_server_ip -rf + mkfifo /tmp/gate_server_ip + default_item=`do_get_gateway_info lora_server.lora_server_ip` + dialog --title "lora server IP" --nocancel --inputbox "SERVER_IP:" 10 40 "$default_item" 2> /tmp/gate_server_ip & + RET=$? + if [ $RET -eq 1 ]; then + echo "error" + elif [ $RET -eq 0 ]; then + gate_server_ip="$( cat /tmp/gate_server_ip )" + rm /tmp/gate_server_ip + write_json_lora_server_ip "$gate_server_ip" + sed -i "s/^.*server_address.*$/\t\"server_address\": \"$gate_server_ip\",/" $LORA_PKT_PATH/global_conf.json + do_check_ip_is_localhost $gate_server_ip + RET=$? + if [ $RET -eq 0 ]; then + do_LoRa_Server enable + do_LoRa_Server restart + else + do_LoRa_Server diable + do_LoRa_Server stop + fi + fi +} + +do_setup_LoRaServer_channel_plan() { + default_item=1 + FUN=$(dialog --title "LoRaServer Channel-plan configuration" --default-item $default_item --menu "Server the Channel-plan:" 18 60 12 \ + 1 "AS_923" \ + 2 "AU_915_928" \ + 3 "CN_470_510" \ + 4 "EU_433" \ + 5 "EU_863_870" \ + 6 "IN_865_867" \ + 7 "KR_920_923" \ + 8 "RU_864_870" \ + 9 "US_902_928" \ + 3>&1 1>&2 2>&3) + RET=$? + if [ $RET -eq 0 ]; then + case "$FUN" in + 1) do_copy_global_conf "loraserver" "as_923" 1;; + 2) do_copy_global_conf "loraserver" "au_915_928" 2;; + 3) do_copy_global_conf "loraserver" "cn_470_510" 3;; + 4) do_copy_global_conf "loraserver" "eu_433" 4;; + 5) do_copy_global_conf "loraserver" "eu_863_870" 5;; + 6) do_copy_global_conf "loraserver" "in_865_867" 6;; + 7) do_copy_global_conf "loraserver" "kr_920_923" 7;; + 8) do_copy_global_conf "loraserver" "ru_864_870" 8;; + 9) do_copy_global_conf "loraserver" "us_902_928" 9;; + esac + fi +} + +do_setup_LoRaWan_channel_plan() { + default_item=1 + FUN=$(dialog --title "LoRaServer Channel-plan configuration" --default-item $default_item --menu "Server the Channel-plan:" 18 60 12 \ + 1 "AS_923" \ + 2 "AU_915_928" \ + 3 "CN_470_510" \ + 4 "EU_433" \ + 5 "EU_863_870" \ + 6 "IN_865_867" \ + 7 "KR_920_923" \ + 8 "RU_864_870" \ + 9 "US_902_928" \ + 3>&1 1>&2 2>&3) + RET=$? + if [ $RET -eq 1 ]; then + : + elif [ $RET -eq 0 ]; then + case "$FUN" in + 1) do_copy_global_conf "lorawan" "as_923" 1;; + 2) do_copy_global_conf "lorawan" "au_915_928" 2;; + 3) do_copy_global_conf "lorawan" "cn_470_510" 3;; + 4) do_copy_global_conf "lorawan" "eu_433" 4;; + 5) do_copy_global_conf "lorawan" "eu_863_870" 5;; + 6) do_copy_global_conf "lorawan" "in_865_867" 6;; + 7) do_copy_global_conf "lorawan" "kr_920_923" 7;; + 8) do_copy_global_conf "lorawan" "ru_864_870" 8;; + 9) do_copy_global_conf "lorawan" "us_902_928" 9;; + esac + fi +} + +do_setup_channel_plan() { + # $1: concentrator type + # $2: config suffix, eg ".gps" + default_item=`do_get_gateway_info lora_server.server_plan` + + FUN=$(dialog --title "Server-plan configuration" --default-item $default_item --menu "Select the Server-plan:" 15 60 3 \ + 1 "Server is TTN" \ + 2 "Server is LoRaServer" \ + 3>&1 1>&2 2>&3) + RET=$? + + if [ $RET -eq 1 ]; then + : + elif [ $RET -eq 0 ]; then + case "$FUN" in + 1) do_setup_ttn_channel_plan;; + 2) do_setup_LoRaServer_channel_plan ;; + esac + fi + do_main_menu +} + +do_LoRa_Server() +{ + systemctl $1 loraserver + systemctl $1 lora-app-server + systemctl $1 lora-gateway-bridge +} + +do_lorawan_server() +{ + systemctl $1 lorawan-server +} + +do_disable_all_lora_server() +{ + do_LoRa_Server stop + do_lorawan_server stop + + do_LoRa_Server disable + do_lorawan_server disable + + write_json_active_lora_server 1 +} + +do_select_LoRaServer() +{ + do_lorawan_server disable + do_lorawan_server stop + + do_LoRa_Server enable + do_LoRa_Server start + + write_json_active_lora_server 2 +} + +do_select_LoRaWan() +{ + do_LoRa_Server disable + do_LoRa_Server stop + + do_lorawan_server enable + do_lorawan_server start + + write_json_active_lora_server 3 +} + +do_select_lora_server() +{ + default_item=`do_get_gateway_info active_lora_server` + FUN=$(dialog --title "Select lora server" --cancel-label "Quit" --default-item $default_item --menu "Configuration options:" 13 80 20 \ + 1 "Disable all lora server" \ + 2 "Select LoRaServer" \ + 3 "Select LoRaWan" \ + 3>&1 1>&2 2>&3) + RET=$? + if [ $RET -eq 1 ]; then + clear + return 0 + elif [ $RET -eq 0 ]; then + case "$FUN" in + 1) do_disable_all_lora_server;; + 2) do_select_LoRaServer;; + 3) do_select_LoRaWan;; + esac + fi + do_main_menu +} + +do_enable_ap_mode() +{ + write_json_wifi_mode 1 + systemctl enable create_ap + + if [ -f "/sbin/wpa_supplicant" ]; then + mv /sbin/wpa_supplicant /sbin/wpa_supplicant_bak + fi + dialog --title "Enable AP Mode" --msgbox "The AP mode will active after the operating system reboot." 5 70 +} + +do_enable_wifi_mode() +{ + write_json_wifi_mode 2 + systemctl disable create_ap + + if [ -f "/sbin/wpa_supplicant_bak" ]; then + mv /sbin/wpa_supplicant_bak /sbin/wpa_supplicant + fi + + dialog --title "Enable Wifi Mode" --msgbox "The Client mode will active after the operating system reboot." 5 70 +} + +do_modify_ssid_for_ap() +{ + echo "aaa" + rm /tmp/rak_ssid -rf + mkfifo /tmp/rak_ssid + rm /tmp/rak_ap_pwd -rf + mkfifo /tmp/rak_ap_pwd + + # get old ssid + old_ap_ssid=`do_get_gateway_info wifi.ap_ssid` + + # get old pwd + old_ap_pwd=`do_get_gateway_info wifi.ap_pwd` + + # dialog ip + dialog --title "AP SSID" --nocancel --inputbox "SSID:" 10 40 "$old_ap_ssid" 2> /tmp/rak_ssid & + RET=$? + + if [ $RET -eq 1 ]; then + clear + elif [ $RET -eq 0 ]; then + new_ap_ssid="$( cat /tmp/rak_ssid )" + rm /tmp/rak_ssid + ssid_len=${#new_ap_ssid} + fi + + #dialog pwd + dialog --title "AP Password" --nocancel --inputbox "Password:" 10 40 "$old_ap_pwd" 2> /tmp/rak_ap_pwd & + if [ $RET -ne 0 ]; then + clear + else + new_ap_pwd="$( cat /tmp/rak_ap_pwd )" + pwd_len=${#new_ap_pwd} + rm /tmp/rak_ap_pwd + + fi + + if [ $ssid_len -eq 0 ] || [ $pwd_len -eq 0 ] || [ $pwd_len -lt 8 ] ||[ $pwd_len -gt 63 ]; then + if [ $ssid_len -eq 0 ]; then + dialog --title "Configure AP SSID" --msgbox "SSID cannot be empty." 5 28 + elif [ $pwd_len -eq 0 ] || [ $pwd_len -lt 8 ] ||[ $pwd_len -gt 63 ]; then + dialog --title "Configure AP Password" --msgbox "Invalid passphrase length ${pwd_len} (expected: 8..63)." 5 52 + else + clear + fi + else + sed -i "26c SSID=$new_ap_ssid" /usr/local/rak/ap/create_ap.conf + sed -i "27c PASSPHRASE=$new_ap_pwd" /usr/local/rak/ap/create_ap.conf + + write_json_ap_ssid $new_ap_ssid + write_json_ap_pwd $new_ap_pwd + dialog --title "Configute AP info" --msgbox "Modify AP info success.Changes will take effect after OS restart." 5 72 + fi + +} + +do_add_new_ssid() +{ + rm /tmp/wifi_ssid -rf + mkfifo /tmp/wifi_ssid + rm /tmp/wifi_pwd -rf + mkfifo /tmp/wifi_pwd + dialog --title "Configure WIFI" --nocancel --inputbox "SSID:" 10 40 2> /tmp/wifi_ssid & + if [ $RET -ne 0 ]; then + echo "test" + return 1 + fi + dialog --title "Configure WIFI" --nocancel --inputbox "Password:" 10 40 2> /tmp/wifi_pwd & + if [ $RET -ne 0 ]; then + return 1 + fi + + linenum=`sed -n '/update_config/=' /etc/wpa_supplicant/wpa_supplicant.conf` + let linenum=linenum+1 + + wifi_ssid="$( cat /tmp/wifi_ssid )" + wifi_pwd="$( cat /tmp/wifi_pwd )" + ssid_len=${#wifi_ssid} + pwd_len=${#wifi_pwd} + + if [ $ssid_len -eq 0 ]; then + dialog --title "Configure WIFI" --msgbox "SSID cannot be empty." 5 28 + return 1 + fi + + if [ $pwd_len -eq 0 ] || [ $pwd_len -lt 8 ] ||[ $pwd_len -gt 63 ]; then + dialog --title "Configure WIFI" --msgbox "Invalid passphrase length ${pwd_len} (expected: 8..63)." 5 52 + return 1 + else +# sed -i "${linenum}inetwork={\nssid=\"${wifi_ssid}\"\nkey_mgmt=WPA-PSK\npsk=\"${wifi_pwd}\"\n}" /etc/wpa_supplicant/wpa_supplicant.conf + echo " +ctrl_interface=DIR=/var/run/wpa_supplicant GROUP=netdev +update_config=1 +network={ +ssid=\"${wifi_ssid}\" +key_mgmt=WPA-PSK +psk=\"${wifi_pwd}\" +} +" > /etc/wpa_supplicant/wpa_supplicant.conf + wpa_cli -i wlan0 reconfigure + dialog --title "Configure WIFI" --msgbox "Add new SSID success. Configuration will take effect after OS reboot." 5 78 + fi +} + +do_configure_wlan_ip() { + rm /tmp/wlan0_ip -rf + mkfifo /tmp/wlan0_ip + + rm /tmp/wlan0_gw -rf + mkfifo /tmp/wlan0_gw + + # get old ip + old_wlan0_ip=`do_get_gateway_info wifi.wifi_ip` + + # dialog ip + dialog --title "Set wlan0 IP" --nocancel --inputbox "IP:" 10 40 "$old_wlan0_ip" 2> /tmp/wlan0_ip & + RET=$? + + if [ $RET -eq 1 ]; then + echo "error" + elif [ $RET -eq 0 ]; then + new_wlan0_ip="$( cat /tmp/wlan0_ip )" + do_check_ipaddr $new_wlan0_ip + RET_IP=$? + rm /tmp/wlan0_ip + fi + + # get old gw + old_wlan0_gw=`do_get_gateway_info wifi.wifi_gw` + + # dialog wlan0 gw + dialog --title "Set wlan0 gateway IP" --nocancel --inputbox "Gateway IP:" 10 40 "$old_wlan0_gw" 2> /tmp/wlan0_gw & + RET=$? + + if [ $RET -eq 1 ]; then + echo "error" + elif [ $RET -eq 0 ]; then + new_wlan0_gw="$( cat /tmp/wlan0_gw )" + do_check_ipaddr $new_wlan0_gw + RET_GW=$? + rm /tmp/wlan0_gw + fi + + if [ $RET_IP -eq 1 ]; then + dialog --title "Configure wlan0" --msgbox "Invalid IP address." 5 50 + elif [ $RET_GW -eq 1 ]; then + dialog --title "Configure wlan0" --msgbox "Invalid Gateway IP address." 5 50 + else + + linenum=`sed -n '/RAK_wlan0_IP/=' /etc/dhcpcd.conf` + let line_ip=linenum+2 + let line_gw=linenum+3 + + sed -i "${line_ip}cstatic ip_address=${new_wlan0_ip}" /etc/dhcpcd.conf + sed -i "${line_gw}cstatic routers=${new_wlan0_gw}" /etc/dhcpcd.conf + write_json_wlan_ip ${new_wlan0_ip} + write_json_wlan_gw ${new_wlan0_gw} + dialog --title "Configure wlan0" --msgbox "Configure wlan0 success.Changes will take effect after OS restart." 5 70 + fi +} + +do_configure_wifi() { + default_item=`do_get_gateway_info wifi.wifi_mode` + + FUN=$(dialog --title "Configure wifi" --cancel-label "Cancel" --default-item $default_item --menu "Configuration options:" 12 60 20 \ + 1 "Enable AP Mode/Disable Client Mode" \ + 2 "Enable Client Mode/Disable AP Mode" \ + 3 "Modify SSID and pwd for AP Mode" \ + 4 "Add New SSID for Client" \ + 3>&1 1>&2 2>&3) + RET=$? + if [ $RET -eq 0 ]; then + case "$FUN" in + 1) do_enable_ap_mode;; + 2) do_enable_wifi_mode;; + 3) do_modify_ssid_for_ap;; + 4) do_add_new_ssid;; + esac + fi + + do_main_menu +} + +do_configure_lan() { + rm /tmp/eth0_ip -rf + mkfifo /tmp/eth0_ip + + rm /tmp/eth0_gw -rf + mkfifo /tmp/eth0_gw + + # get old ip + old_eth0_ip=`do_get_gateway_info lan.lan_ip` + + # dialog ip + dialog --title "Set eth0 IP" --nocancel --inputbox "IP:" 10 40 "$old_eth0_ip" 2> /tmp/eth0_ip & + RET=$? + + if [ $RET -eq 1 ]; then + echo "error" + elif [ $RET -eq 0 ]; then + new_eth0_ip="$( cat /tmp/eth0_ip )" + do_check_ipaddr $new_eth0_ip + RET_IP=$? + rm /tmp/eth0_ip + fi + + # get old gw + old_eth0_gw=`do_get_gateway_info lan.lan_gw` + + # dialog eth0 gw + dialog --title "Set eth0 gateway IP" --nocancel --inputbox "Gateway IP:" 10 40 "$old_eth0_gw" 2> /tmp/eth0_gw & + RET=$? + + if [ $RET -eq 1 ]; then + echo "error" + elif [ $RET -eq 0 ]; then + new_eth0_gw="$( cat /tmp/eth0_gw )" + do_check_ipaddr $new_eth0_gw + RET_GW=$? + rm /tmp/eth0_gw + fi + + if [ $RET_IP -eq 1 ]; then + dialog --title "Configure LAN" --msgbox "Invalid IP address." 5 50 + elif [ $RET_GW -eq 1 ]; then + dialog --title "Configure LAN" --msgbox "Invalid Gateway IP address." 5 50 + else + + linenum=`sed -n '/RAK_eth0_IP/=' /etc/dhcpcd.conf` + let line_ip=linenum+2 + let line_gw=linenum+3 + + sed -i "${line_ip}cstatic ip_address=${new_eth0_ip}" /etc/dhcpcd.conf + sed -i "${line_gw}cstatic routers=${new_eth0_gw}" /etc/dhcpcd.conf + write_json_lan_ip ${new_eth0_ip} + write_json_lan_gw ${new_eth0_gw} + dialog --title "Configure LAN" --msgbox "Configure LAN success.Changes will take effect after OS restart." 5 70 + fi + + do_main_menu +} + +do_enable_2013() +{ + write_json_lte_mode 1 + systemctl enable rak-pppd + dialog --title "Enable LTE Module" --msgbox "The LTE module will power on after the operating system starts." 5 70 +# do_main_menu +} + +do_disable_2013() +{ + write_json_lte_mode 2 + systemctl disable rak-pppd + dialog --title "Disable LTE Module" --msgbox "The LTE module will not power on after the operating system starts." 5 71 +# do_main_menu +} + +do_rak2013() +{ + # get lte module status + default_item=`do_get_gateway_info lte_mode` + + FUN=$(dialog --title "LTE Module" --cancel-label "Cancel" --default-item $default_item --menu "Configuration options:" 10 60 20 \ + 1 "Enable LTE Automatic Dial-up" \ + 2 "Disable LTE Automatic Dial-up" \ + 3>&1 1>&2 2>&3) + RET=$? + if [ $RET -eq 1 ]; then + clear + elif [ $RET -eq 0 ]; then + case "$FUN" in + 1) do_enable_2013;; + 2) do_disable_2013;; + esac + fi + do_main_menu +} + +do_set_apn_name() +{ + # get old apn + old_apn=`do_get_gateway_info apn.apn_name` + + # get old baud speed + old_baud=`do_get_gateway_info apn.apn_baud` + + rm /tmp/apn_name -rf + mkfifo /tmp/apn_name + rm /tmp/band_speed -rf + mkfifo /tmp/band_speed + dialog --title "APN Name" --nocancel --inputbox "APN Name:" 10 40 "$old_apn" 2> /tmp/apn_name & + dialog --title "Baud Speed" --nocancel --inputbox "Baud Speed:" 10 40 "$old_baud" 2> /tmp/band_speed & + RET=$? + + if [ $RET -eq 1 ]; then + echo "error" + elif [ $RET -eq 0 ]; then + new_apn_name="$( cat /tmp/apn_name )" + new_baud_speed="$( cat /tmp/band_speed )" + + RET2=`do_check_variable_type $new_baud_speed` + if [ $RET2 -ne 0 ]; then + dialog --title "Baud Speed" --msgbox "Invalid baud speed." 5 40 + else + /usr/local/rak/lte/ppp-creator.sh "${new_apn_name}" ttyAMA0 ${new_baud_speed} >/dev/null + rm /tmp/apn_name -rf + rm /tmp/band_speed -rf + + write_json_apn_name $new_apn_name + write_json_apn_baud $new_baud_speed + fi + fi + do_main_menu +} + +do_get_gw_id() +{ + GATEWAY_EUI_NIC="eth0" + if [[ `grep "$GATEWAY_EUI_NIC" /proc/net/dev` == "" ]]; then + GATEWAY_EUI_NIC="wlan0" + fi + + if [[ `grep "$GATEWAY_EUI_NIC" /proc/net/dev` == "" ]]; then + echo "" + fi + GATEWAY_EUI=$(ip link show $GATEWAY_EUI_NIC | awk '/ether/ {print $2}' | awk -F\: '{print $1$2$3"FFFE"$4$5$6}') + GATEWAY_EUI=${GATEWAY_EUI^^} + echo $GATEWAY_EUI +} + +do_main_menu() { + GW_MODEL=`do_get_gw_model` + GW_VERSION=`do_get_gw_version` + GW_ID=`do_get_gw_id` + + if [ "$GW_MODEL" = "RAK2245" ] || [ "$GW_MODEL" = "RAK831" ]; then + + FUN=$(dialog --title "$GW_MODEL (Gateway ID:$GW_ID Version: $GW_VERSION)" --cancel-label "Quit" --menu "Configuration options:" 16 80 20 \ + 1 "Set pi password" \ + 2 "Setup RAK Gateway LoRa concentrator" \ + 3 "Restart packet-forwarder" \ + 4 "Edit packet-forwarder config" \ + 5 "Configure WIFI" \ + 6 "Configure LAN" \ + 3>&1 1>&2 2>&3) + RET=$? + if [ $RET -eq 1 ]; then + clear + return 0 + elif [ $RET -eq 0 ]; then + case "$FUN" in + 1) do_setup_admin_password;; + 2) do_setup_channel_plan;; + 3) do_restart_packet_forwarder;; + 4) nano $LORA_PKT_PATH/global_conf.json && do_main_menu;; + 5) do_configure_wifi;; + 6) do_configure_lan;; + esac + fi + + elif [ "$GW_MODEL" = "RAK7243" ]; then + + FUN=$(dialog --title "$GW_MODEL (Gateway ID:$GW_ID Version: $GW_VERSION)" --cancel-label "Quit" --menu "Configuration options:" 19 80 20 \ + 1 "Set pi password" \ + 2 "Setup RAK Gateway LoRa concentrator" \ + 3 "Restart packet-forwarder" \ + 4 "Edit packet-forwarder config" \ + 5 "Configure WIFI" \ + 6 "Configure LAN" \ + 7 "Configure APN name" \ + 8 "Configure LTE Module" \ + 3>&1 1>&2 2>&3) + RET=$? + if [ $RET -eq 1 ]; then + clear + return 0 + elif [ $RET -eq 0 ]; then + case "$FUN" in + 1) do_setup_admin_password;; + 2) do_setup_channel_plan;; + 3) do_restart_packet_forwarder;; + 4) nano $LORA_PKT_PATH/global_conf.json && do_main_menu;; + 5) do_configure_wifi;; + 6) do_configure_lan;; + 7) do_set_apn_name;; + 8) do_rak2013;; + esac + fi + + elif [ "$GW_MODEL" = "RAK2247" ] || [ "$GW_MODEL" = "RAK833" ]; then + FUN=$(dialog --title "$GW_MODEL (Gateway ID:$GW_ID Version: $GW_VERSION)" --cancel-label "Quit" --menu "Configuration options:" 16 80 20 \ + 1 "Set pi password" \ + 2 "Setup RAK Gateway LoRa concentrator" \ + 3 "Restart packet-forwarder" \ + 4 "Edit packet-forwarder config" \ + 5 "Configure WIFI" \ + 6 "Configure LAN" \ + 3>&1 1>&2 2>&3) + RET=$? + if [ $RET -eq 1 ]; then + clear + return 0 + elif [ $RET -eq 0 ]; then + case "$FUN" in + 1) do_setup_admin_password;; + 2) do_setup_channel_plan;; + 3) do_restart_packet_forwarder;; + 4) nano $LORA_PKT_PATH/global_conf.json && do_main_menu;; + 5) do_configure_wifi;; + 6) do_configure_lan;; + esac + fi + else + echo "invalid gateway model:$GW_MODEL" + + fi +} + +if [ $(id -u) -ne 0 ]; then + printf "Script must be run as root. Try 'sudo gateway-config'\n" + exit 1 +fi + +do_main_menu + diff --git a/rak/gateway-config_for_3.0 b/rak/gateway-config_for_3.0 new file mode 100755 index 0000000..ebf542f --- /dev/null +++ b/rak/gateway-config_for_3.0 @@ -0,0 +1,881 @@ +#!/bin/bash + +source /usr/local/rak/shell_script/rak_common.sh + +GATEWAY_CONFIG_INFO=/usr/local/rak/gateway-config-info.json +LORA_PKT_PATH=/opt/ttn-gateway/packet_forwarder/lora_pkt_fwd + +do_if_proc_is_run() +{ + if [ -n "`pgrep $1`" ]; then + return 0 + else + return 1 + fi +} + +do_check_ipaddr() +{ + echo $1|grep "^[0-9]\{1,3\}\.\([0-9]\{1,3\}\.\)\{2\}[0-9]\{1,3\}$" > /dev/null; + if [ $? -ne 0 ] + then + echo "Bad IP address" + return 1 + fi + ipaddr=$1 + a=`echo $ipaddr|awk -F . '{print $1}'` + b=`echo $ipaddr|awk -F . '{print $2}'` + c=`echo $ipaddr|awk -F . '{print $3}'` + d=`echo $ipaddr|awk -F . '{print $4}'` + for num in $a $b $c $d + do + if [ $num -gt 255 ] || [ $num -lt 0 ] + then + echo "Bad IP address" + return 1 + fi + done + + return 0 +} + +do_get_gateway_info() +{ + + do_get_json_value $1 $GATEWAY_CONFIG_INFO +} + +do_check_ip_is_localhost() +{ + if [ "$1" = "localhost" ] || [ "$1" = "127.0.0.1" ]; then + return 0 + else + return 1 + fi +} + +write_json_gateway_info() +{ + # $1 key; $2 value + do_check_variable_type $1 + RET=$? + if [ $RET -eq 3 ]; then + sed -i "s/^.*$1.*$/\"$1\":\"$2\",/" $GATEWAY_CONFIG_INFO + fi +} + +write_json_gateway_info_no_comma() +{ + # $1 key; $2 value + do_check_variable_type $1 + RET=$? + if [ $RET -eq 3 ]; then + sed -i "s/^.*$1.*$/\"$1\":\"$2\"/" $GATEWAY_CONFIG_INFO + fi +} + +write_json_server_plan() +{ + write_json_gateway_info "server_plan" $1 +} + +write_json_server_freq() +{ + write_json_gateway_info_no_comma "freq" $1 +} + +write_json_lora_server_ip() +{ + # . 字母 数字 + write_json_gateway_info "lora_server_ip" $1 +} + +write_json_wifi_mode() +{ + # 数字 1/2 + write_json_gateway_info "wifi_mode" $1 +} + +write_json_ap_ssid() +{ + # 数字 字母 - _ + write_json_gateway_info "ap_ssid" $1 +} + +write_json_ap_pwd() +{ + # 数字 字母 特殊字符 + write_json_gateway_info_no_comma "ap_pwd" $1 +} + +write_json_lan_ip() +{ + # 数字 . 校验下是否为有效IP + write_json_gateway_info "lan_ip" $1 +} + +write_json_lan_gw() +{ + # 数字 . 校验下是否为有效IP + write_json_gateway_info_no_comma "lan_gw" $1 +} + +write_json_wlan_ip() +{ + # 数字 . 校验下是否为有效IP + write_json_gateway_info "wifi_ip" $1 +} + +write_json_wlan_gw() +{ + # 数字 . 校验下是否为有效IP + write_json_gateway_info_no_comma "wifi_gw" $1 +} + +write_json_apn_name() +{ + # 任意 + write_json_gateway_info "apn_name" $1 +} + +write_json_apn_baud() +{ + # 数字 + write_json_gateway_info_no_comma "apn_baud" $1 +} + +write_json_lte_mode() +{ + # 数字 + write_json_gateway_info_no_comma "lte_mode" $1 +} + +write_json_active_lora_server() +{ + write_json_gateway_info "active_lora_server" $1 +} + +do_setup_admin_password() { + dialog --title "Setup pi password" --yesno "You will be asked to enter a new password." 5 60 + RET=$? + if [ $RET -eq 0 ]; then + passwd pi + RET=$? + if [ $RET -eq 0 ]; then + dialog --title "Setup pi password" --msgbox "Password has been changed succesfully." 5 60 + fi + fi + do_main_menu +} + +do_restart_packet_forwarder() { + systemctl stop ttn-gateway + systemctl start ttn-gateway + RET=$? + if [ $RET -eq 0 ]; then + dialog --title "Restart packet-forwarder" --msgbox "The packet-forwarder has been restarted." 5 60 + fi + if [ $# -eq 0 ]; then + do_main_menu + fi +} + +do_copy_global_conf() { + cp $LORA_PKT_PATH/global_conf/global_conf.$2.json $LORA_PKT_PATH/global_conf.json + + sed -i "s/^.*RAK_GW_FREQ.*$/RAK_GW_FREQ=$2/" /usr/local/rak/lora/rak.env + + if [ "$1" = "ttn" ]; then + dialog --title "Server-plan configuration" --msgbox "Server-plan configuration has been copied." 5 60 + write_json_server_plan 1 + elif [ "$1" = "loraserver" ]; then + write_json_server_plan 2 + do_set_lora_server_ip + cp /etc/loraserver/loraserver.$2.toml /etc/loraserver/loraserver.toml + do_if_proc_is_run "loraserver" + RET=$? + if [ $RET -eq 0 ]; then + do_LoRa_Server restart + fi + elif [ "$1" = "lorawan" ]; then + write_json_server_plan 3 + do_set_lora_server_ip + fi + + sed -i "s/^.*RAK_GW_FREQ.*$/RAK_GW_FREQ=$2/" /usr/local/rak/lora/rak.env + do_restart_packet_forwarder 1 +} + + + +do_setup_ttn_channel_plan() { + default_item=1 + FUN=$(dialog --title "TTN Channel-plan configuration" --default-item $default_item --menu "Select the Channel-plan:" 18 60 12 \ + 1 "AS_923" \ + 2 "AU_915_928" \ + 3 "CN_470_510" \ + 4 "EU_863_870" \ + 5 "IN_865_867" \ + 6 "KR_920_923" \ + 7 "RU_864_870" \ + 8 "US_902_928" \ + 3>&1 1>&2 2>&3) + RET=$? + if [ $RET -eq 1 ]; then + : + elif [ $RET -eq 0 ]; then + case "$FUN" in + 1) do_copy_global_conf "ttn" "as_923" 1;; + 2) do_copy_global_conf "ttn" "au_915_928" 2;; + 3) do_copy_global_conf "ttn" "cn_470_510" 3;; + 4) do_copy_global_conf "ttn" "eu_863_870" 4;; + 5) do_copy_global_conf "ttn" "in_865_867" 5;; + 6) do_copy_global_conf "ttn" "kr_920_923" 6;; + 7) do_copy_global_conf "ttn" "ru_864_870" 7;; + 8) do_copy_global_conf "ttn" "us_902_928" 8;; + esac + fi +} + +do_enable_loraserver() +{ + systemctl enable loraserver + systemctl enable lora-app-server + systemctl enable lora-gateway-bridge + systemctl restart loraserver + systemctl restart lora-app-server + systemctl restart lora-gateway-bridge +} + +do_disable_loraserver() +{ + systemctl disable loraserver + systemctl disable lora-app-server + systemctl disable lora-gateway-bridge + systemctl stop loraserver + systemctl stop lora-app-server + systemctl stop lora-gateway-bridge +} + +do_set_lora_server_ip() +{ + rm /tmp/gate_server_ip -rf + mkfifo /tmp/gate_server_ip + default_item=`do_get_gateway_info lora_server.lora_server_ip` + dialog --title "lora server IP" --nocancel --inputbox "SERVER_IP:" 10 40 "$default_item" 2> /tmp/gate_server_ip & + RET=$? + if [ $RET -eq 1 ]; then + echo "error" + elif [ $RET -eq 0 ]; then + gate_server_ip="$( cat /tmp/gate_server_ip )" + rm /tmp/gate_server_ip + write_json_lora_server_ip "$gate_server_ip" + sed -i "s/^.*server_address.*$/\t\"server_address\": \"$gate_server_ip\",/" $LORA_PKT_PATH/global_conf.json + fi +} + +do_setup_LoRaServer_channel_plan() { + default_item=1 + FUN=$(dialog --title "LoRaServer Channel-plan configuration" --default-item $default_item --menu "Server the Channel-plan:" 18 60 12 \ + 1 "AS_923" \ + 2 "AU_915_928" \ + 3 "CN_470_510" \ + 4 "EU_433" \ + 5 "EU_863_870" \ + 6 "IN_865_867" \ + 7 "KR_920_923" \ + 8 "RU_864_870" \ + 9 "US_902_928" \ + 3>&1 1>&2 2>&3) + RET=$? + if [ $RET -eq 0 ]; then + case "$FUN" in + 1) do_copy_global_conf "loraserver" "as_923" 1;; + 2) do_copy_global_conf "loraserver" "au_915_928" 2;; + 3) do_copy_global_conf "loraserver" "cn_470_510" 3;; + 4) do_copy_global_conf "loraserver" "eu_433" 4;; + 5) do_copy_global_conf "loraserver" "eu_863_870" 5;; + 6) do_copy_global_conf "loraserver" "in_865_867" 6;; + 7) do_copy_global_conf "loraserver" "kr_920_923" 7;; + 8) do_copy_global_conf "loraserver" "ru_864_870" 8;; + 9) do_copy_global_conf "loraserver" "us_902_928" 9;; + esac + fi +} + +do_setup_LoRaWan_channel_plan() { + default_item=1 + FUN=$(dialog --title "LoRaServer Channel-plan configuration" --default-item $default_item --menu "Server the Channel-plan:" 18 60 12 \ + 1 "AS_923" \ + 2 "AU_915_928" \ + 3 "CN_470_510" \ + 4 "EU_433" \ + 5 "EU_863_870" \ + 6 "IN_865_867" \ + 7 "KR_920_923" \ + 8 "RU_864_870" \ + 9 "US_902_928" \ + 3>&1 1>&2 2>&3) + RET=$? + if [ $RET -eq 1 ]; then + : + elif [ $RET -eq 0 ]; then + case "$FUN" in + 1) do_copy_global_conf "lorawan" "as_923" 1;; + 2) do_copy_global_conf "lorawan" "au_915_928" 2;; + 3) do_copy_global_conf "lorawan" "cn_470_510" 3;; + 4) do_copy_global_conf "lorawan" "eu_433" 4;; + 5) do_copy_global_conf "lorawan" "eu_863_870" 5;; + 6) do_copy_global_conf "lorawan" "in_865_867" 6;; + 7) do_copy_global_conf "lorawan" "kr_920_923" 7;; + 8) do_copy_global_conf "lorawan" "ru_864_870" 8;; + 9) do_copy_global_conf "lorawan" "us_902_928" 9;; + esac + fi +} + +do_setup_channel_plan() { + # $1: concentrator type + # $2: config suffix, eg ".gps" + default_item=`do_get_gateway_info lora_server.server_plan` + + FUN=$(dialog --title "Server-plan configuration" --default-item $default_item --menu "Select the Server-plan:" 15 60 3 \ + 1 "Server is TTN" \ + 2 "Server is LoRaServer" \ + 3 "Server is LoRaWAN" \ + 3>&1 1>&2 2>&3) + RET=$? + + if [ $RET -eq 1 ]; then + : + elif [ $RET -eq 0 ]; then + case "$FUN" in + 1) do_setup_ttn_channel_plan;; + 2) do_setup_LoRaServer_channel_plan ;; + 3) do_setup_LoRaWan_channel_plan ;; + esac + fi + do_main_menu +} + +do_LoRa_Server() +{ + systemctl $1 loraserver + systemctl $1 lora-app-server + systemctl $1 lora-gateway-bridge +} + +do_lorawan_server() +{ + systemctl $1 lorawan-server +} + +do_disable_all_lora_server() +{ + do_LoRa_Server stop + do_lorawan_server stop + + do_LoRa_Server disable + do_lorawan_server disable + + write_json_active_lora_server 1 +} + +do_select_LoRaServer() +{ + do_lorawan_server disable + do_lorawan_server stop + + do_LoRa_Server enable + do_LoRa_Server start + + write_json_active_lora_server 2 +} + +do_select_LoRaWan() +{ + do_LoRa_Server disable + do_LoRa_Server stop + + do_lorawan_server enable + do_lorawan_server start + + write_json_active_lora_server 3 +} + +do_select_lora_server() +{ + default_item=`do_get_gateway_info active_lora_server` + FUN=$(dialog --title "Select lora server" --cancel-label "Quit" --default-item $default_item --menu "Configuration options:" 13 80 20 \ + 1 "Disable all lora server" \ + 2 "Select LoRaServer" \ + 3 "Select LoRaWan" \ + 3>&1 1>&2 2>&3) + RET=$? + if [ $RET -eq 1 ]; then + clear + return 0 + elif [ $RET -eq 0 ]; then + case "$FUN" in + 1) do_disable_all_lora_server;; + 2) do_select_LoRaServer;; + 3) do_select_LoRaWan;; + esac + fi + do_main_menu +} + +do_enable_ap_mode() +{ + write_json_wifi_mode 1 + systemctl enable create_ap + + if [ -f "/sbin/wpa_supplicant" ]; then + mv /sbin/wpa_supplicant /sbin/wpa_supplicant_bak + fi + dialog --title "Enable AP Mode" --msgbox "The AP mode will active after the operating system reboot." 5 70 +} + +do_enable_wifi_mode() +{ + write_json_wifi_mode 2 + systemctl disable create_ap + + if [ -f "/sbin/wpa_supplicant_bak" ]; then + mv /sbin/wpa_supplicant_bak /sbin/wpa_supplicant + fi + + dialog --title "Enable Wifi Mode" --msgbox "The Client mode will active after the operating system reboot." 5 70 +} + +do_modify_ssid_for_ap() +{ + echo "aaa" + rm /tmp/rak_ssid -rf + mkfifo /tmp/rak_ssid + rm /tmp/rak_ap_pwd -rf + mkfifo /tmp/rak_ap_pwd + + # get old ssid + old_ap_ssid=`do_get_gateway_info wifi.ap_ssid` + + # get old pwd + old_ap_pwd=`do_get_gateway_info wifi.ap_pwd` + + # dialog ip + dialog --title "AP SSID" --nocancel --inputbox "SSID:" 10 40 "$old_ap_ssid" 2> /tmp/rak_ssid & + RET=$? + + if [ $RET -eq 1 ]; then + clear + elif [ $RET -eq 0 ]; then + new_ap_ssid="$( cat /tmp/rak_ssid )" + rm /tmp/rak_ssid + ssid_len=${#new_ap_ssid} + fi + + #dialog pwd + dialog --title "AP Password" --nocancel --inputbox "Password:" 10 40 "$old_ap_pwd" 2> /tmp/rak_ap_pwd & + if [ $RET -ne 0 ]; then + clear + else + new_ap_pwd="$( cat /tmp/rak_ap_pwd )" + pwd_len=${#new_ap_pwd} + rm /tmp/rak_ap_pwd + + fi + + if [ $ssid_len -eq 0 ] || [ $pwd_len -eq 0 ] || [ $pwd_len -lt 8 ] ||[ $pwd_len -gt 63 ]; then + if [ $ssid_len -eq 0 ]; then + dialog --title "Configure AP SSID" --msgbox "SSID cannot be empty." 5 28 + elif [ $pwd_len -eq 0 ] || [ $pwd_len -lt 8 ] ||[ $pwd_len -gt 63 ]; then + dialog --title "Configure AP Password" --msgbox "Invalid passphrase length ${pwd_len} (expected: 8..63)." 5 52 + else + clear + fi + else + sed -i "26c SSID=$new_ap_ssid" /usr/local/rak/ap/create_ap.conf + sed -i "27c PASSPHRASE=$new_ap_pwd" /usr/local/rak/ap/create_ap.conf + + write_json_ap_ssid $new_ap_ssid + write_json_ap_pwd $new_ap_pwd + dialog --title "Configute AP info" --msgbox "Modify AP info success.Changes will take effect after OS restart." 5 72 + fi + +} + +do_add_new_ssid() +{ + rm /tmp/wifi_ssid -rf + mkfifo /tmp/wifi_ssid + rm /tmp/wifi_pwd -rf + mkfifo /tmp/wifi_pwd + dialog --title "Configure WIFI" --nocancel --inputbox "SSID:" 10 40 2> /tmp/wifi_ssid & + if [ $RET -ne 0 ]; then + echo "test" + return 1 + fi + dialog --title "Configure WIFI" --nocancel --inputbox "Password:" 10 40 2> /tmp/wifi_pwd & + if [ $RET -ne 0 ]; then + return 1 + fi + + linenum=`sed -n '/update_config/=' /etc/wpa_supplicant/wpa_supplicant.conf` + let linenum=linenum+1 + + wifi_ssid="$( cat /tmp/wifi_ssid )" + wifi_pwd="$( cat /tmp/wifi_pwd )" + ssid_len=${#wifi_ssid} + pwd_len=${#wifi_pwd} + + if [ $ssid_len -eq 0 ]; then + dialog --title "Configure WIFI" --msgbox "SSID cannot be empty." 5 28 + return 1 + fi + + if [ $pwd_len -eq 0 ] || [ $pwd_len -lt 8 ] ||[ $pwd_len -gt 63 ]; then + dialog --title "Configure WIFI" --msgbox "Invalid passphrase length ${pwd_len} (expected: 8..63)." 5 52 + return 1 + else +# sed -i "${linenum}inetwork={\nssid=\"${wifi_ssid}\"\nkey_mgmt=WPA-PSK\npsk=\"${wifi_pwd}\"\n}" /etc/wpa_supplicant/wpa_supplicant.conf + echo " +ctrl_interface=DIR=/var/run/wpa_supplicant GROUP=netdev +update_config=1 +network={ +ssid=\"${wifi_ssid}\" +key_mgmt=WPA-PSK +psk=\"${wifi_pwd}\" +} +" > /etc/wpa_supplicant/wpa_supplicant.conf + dialog --title "Configure WIFI" --msgbox "Add new SSID success.Configuration will take effect after OS restart" 5 72 + fi +} + +do_configure_wlan_ip() { + rm /tmp/wlan0_ip -rf + mkfifo /tmp/wlan0_ip + + rm /tmp/wlan0_gw -rf + mkfifo /tmp/wlan0_gw + + # get old ip + old_wlan0_ip=`do_get_gateway_info wifi.wifi_ip` + + # dialog ip + dialog --title "Set wlan0 IP" --nocancel --inputbox "IP:" 10 40 "$old_wlan0_ip" 2> /tmp/wlan0_ip & + RET=$? + + if [ $RET -eq 1 ]; then + echo "error" + elif [ $RET -eq 0 ]; then + new_wlan0_ip="$( cat /tmp/wlan0_ip )" + do_check_ipaddr $new_wlan0_ip + RET_IP=$? + rm /tmp/wlan0_ip + fi + + # get old gw + old_wlan0_gw=`do_get_gateway_info wifi.wifi_gw` + + # dialog wlan0 gw + dialog --title "Set wlan0 gateway IP" --nocancel --inputbox "Gateway IP:" 10 40 "$old_wlan0_gw" 2> /tmp/wlan0_gw & + RET=$? + + if [ $RET -eq 1 ]; then + echo "error" + elif [ $RET -eq 0 ]; then + new_wlan0_gw="$( cat /tmp/wlan0_gw )" + do_check_ipaddr $new_wlan0_gw + RET_GW=$? + rm /tmp/wlan0_gw + fi + + if [ $RET_IP -eq 1 ]; then + dialog --title "Configure wlan0" --msgbox "Invalid IP address." 5 50 + elif [ $RET_GW -eq 1 ]; then + dialog --title "Configure wlan0" --msgbox "Invalid Gateway IP address." 5 50 + else + + linenum=`sed -n '/RAK_wlan0_IP/=' /etc/dhcpcd.conf` + let line_ip=linenum+2 + let line_gw=linenum+3 + + sed -i "${line_ip}cstatic ip_address=${new_wlan0_ip}" /etc/dhcpcd.conf + sed -i "${line_gw}cstatic routers=${new_wlan0_gw}" /etc/dhcpcd.conf + write_json_wlan_ip ${new_wlan0_ip} + write_json_wlan_gw ${new_wlan0_gw} + dialog --title "Configure wlan0" --msgbox "Configure wlan0 success.Changes will take effect after OS restart." 5 70 + fi +} + +do_configure_wifi() { + default_item=`do_get_gateway_info wifi.wifi_mode` + + FUN=$(dialog --title "Configure wifi" --cancel-label "Cancel" --default-item $default_item --menu "Configuration options:" 12 60 20 \ + 1 "Enable AP Mode/Disable Client Mode" \ + 2 "Enable Client Mode/Disable AP Mode" \ + 3 "Modify SSID and pwd for AP Mode" \ + 4 "Add New SSID for Client" \ + 3>&1 1>&2 2>&3) + RET=$? + if [ $RET -eq 0 ]; then + case "$FUN" in + 1) do_enable_ap_mode;; + 2) do_enable_wifi_mode;; + 3) do_modify_ssid_for_ap;; + 4) do_add_new_ssid;; + esac + fi + + do_main_menu +} + +do_configure_lan() { + rm /tmp/eth0_ip -rf + mkfifo /tmp/eth0_ip + + rm /tmp/eth0_gw -rf + mkfifo /tmp/eth0_gw + + # get old ip + old_eth0_ip=`do_get_gateway_info lan.lan_ip` + + # dialog ip + dialog --title "Set eth0 IP" --nocancel --inputbox "IP:" 10 40 "$old_eth0_ip" 2> /tmp/eth0_ip & + RET=$? + + if [ $RET -eq 1 ]; then + echo "error" + elif [ $RET -eq 0 ]; then + new_eth0_ip="$( cat /tmp/eth0_ip )" + do_check_ipaddr $new_eth0_ip + RET_IP=$? + rm /tmp/eth0_ip + fi + + # get old gw + old_eth0_gw=`do_get_gateway_info lan.lan_gw` + + # dialog eth0 gw + dialog --title "Set eth0 gateway IP" --nocancel --inputbox "Gateway IP:" 10 40 "$old_eth0_gw" 2> /tmp/eth0_gw & + RET=$? + + if [ $RET -eq 1 ]; then + echo "error" + elif [ $RET -eq 0 ]; then + new_eth0_gw="$( cat /tmp/eth0_gw )" + do_check_ipaddr $new_eth0_gw + RET_GW=$? + rm /tmp/eth0_gw + fi + + if [ $RET_IP -eq 1 ]; then + dialog --title "Configure LAN" --msgbox "Invalid IP address." 5 50 + elif [ $RET_GW -eq 1 ]; then + dialog --title "Configure LAN" --msgbox "Invalid Gateway IP address." 5 50 + else + + linenum=`sed -n '/RAK_eth0_IP/=' /etc/dhcpcd.conf` + let line_ip=linenum+2 + let line_gw=linenum+3 + + sed -i "${line_ip}cstatic ip_address=${new_eth0_ip}" /etc/dhcpcd.conf + sed -i "${line_gw}cstatic routers=${new_eth0_gw}" /etc/dhcpcd.conf + write_json_lan_ip ${new_eth0_ip} + write_json_lan_gw ${new_eth0_gw} + dialog --title "Configure LAN" --msgbox "Configure LAN success.Changes will take effect after OS restart." 5 70 + fi + + do_main_menu +} + +do_enable_2013() +{ + write_json_lte_mode 1 + systemctl enable rak-pppd + dialog --title "Enable LTE Module" --msgbox "The LTE module will power on after the operating system starts." 5 70 +# do_main_menu +} + +do_disable_2013() +{ + write_json_lte_mode 2 + systemctl disable rak-pppd + dialog --title "Disable LTE Module" --msgbox "The LTE module will not power on after the operating system starts." 5 71 +# do_main_menu +} + +do_rak2013() +{ + # get lte module status + default_item=`do_get_gateway_info lte_mode` + + FUN=$(dialog --title "LTE Module" --cancel-label "Cancel" --default-item $default_item --menu "Configuration options:" 10 60 20 \ + 1 "Enable LTE Automatic Dial-up" \ + 2 "Disable LTE Automatic Dial-up" \ + 3>&1 1>&2 2>&3) + RET=$? + if [ $RET -eq 1 ]; then + clear + elif [ $RET -eq 0 ]; then + case "$FUN" in + 1) do_enable_2013;; + 2) do_disable_2013;; + esac + fi + do_main_menu +} + +do_set_apn_name() +{ + # get old apn + old_apn=`do_get_gateway_info apn.apn_name` + + # get old baud speed + old_baud=`do_get_gateway_info apn.apn_baud` + + rm /tmp/apn_name -rf + mkfifo /tmp/apn_name + rm /tmp/band_speed -rf + mkfifo /tmp/band_speed + dialog --title "APN Name" --nocancel --inputbox "APN Name:" 10 40 "$old_apn" 2> /tmp/apn_name & + dialog --title "Baud Speed" --nocancel --inputbox "Baud Speed:" 10 40 "$old_baud" 2> /tmp/band_speed & + RET=$? + + if [ $RET -eq 1 ]; then + echo "error" + elif [ $RET -eq 0 ]; then + new_apn_name="$( cat /tmp/apn_name )" + new_baud_speed="$( cat /tmp/band_speed )" + + RET2=`do_check_variable_type $new_baud_speed` + if [ $RET2 -ne 0 ]; then + dialog --title "Baud Speed" --msgbox "Invalid baud speed." 5 40 + else + /usr/local/rak/lte/ppp-creator.sh "${new_apn_name}" ttyAMA0 ${new_baud_speed} >/dev/null + rm /tmp/apn_name -rf + rm /tmp/band_speed -rf + + write_json_apn_name $new_apn_name + write_json_apn_baud $new_baud_speed + fi + fi + do_main_menu +} + +do_get_gw_id() +{ + GATEWAY_EUI_NIC="eth0" + if [[ `grep "$GATEWAY_EUI_NIC" /proc/net/dev` == "" ]]; then + GATEWAY_EUI_NIC="wlan0" + fi + + if [[ `grep "$GATEWAY_EUI_NIC" /proc/net/dev` == "" ]]; then + echo "" + fi + GATEWAY_EUI=$(ip link show $GATEWAY_EUI_NIC | awk '/ether/ {print $2}' | awk -F\: '{print $1$2$3"FFFE"$4$5$6}') + GATEWAY_EUI=${GATEWAY_EUI^^} + echo $GATEWAY_EUI +} + +do_main_menu() { + GW_MODEL=`do_get_gw_model` + GW_VERSION=`do_get_gw_version` + GW_ID=`do_get_gw_id` + + if [ "$GW_MODEL" = "RAK2245" ] || [ "$GW_MODEL" = "RAK831" ]; then + + FUN=$(dialog --title "$GW_MODEL (Gateway ID:$GW_ID Version: $GW_VERSION)" --cancel-label "Quit" --menu "Configuration options:" 16 80 20 \ + 1 "Set pi password" \ + 2 "Setup RAK Gateway LoRa concentrator" \ + 3 "Restart packet-forwarder" \ + 4 "Edit packet-forwarder config" \ + 5 "Select lora server" \ + 6 "Configure WIFI" \ + 7 "Configure LAN" \ + 3>&1 1>&2 2>&3) + RET=$? + if [ $RET -eq 1 ]; then + clear + return 0 + elif [ $RET -eq 0 ]; then + case "$FUN" in + 1) do_setup_admin_password;; + 2) do_setup_channel_plan;; + 3) do_restart_packet_forwarder;; + 4) nano $LORA_PKT_PATH/global_conf.json && do_main_menu;; + 5) do_select_lora_server;; + 6) do_configure_wifi;; + 7) do_configure_lan;; + esac + fi + + elif [ "$GW_MODEL" = "RAK7243" ]; then + + FUN=$(dialog --title "$GW_MODEL (Gateway ID:$GW_ID Version: $GW_VERSION)" --cancel-label "Quit" --menu "Configuration options:" 19 80 20 \ + 1 "Set pi password" \ + 2 "Setup RAK Gateway LoRa concentrator" \ + 3 "Restart packet-forwarder" \ + 4 "Edit packet-forwarder config" \ + 5 "Select lora server" \ + 6 "Configure WIFI" \ + 7 "Configure LAN" \ + 8 "Configure APN name" \ + 9 "Configure LTE Module" \ + 3>&1 1>&2 2>&3) + RET=$? + if [ $RET -eq 1 ]; then + clear + return 0 + elif [ $RET -eq 0 ]; then + case "$FUN" in + 1) do_setup_admin_password;; + 2) do_setup_channel_plan;; + 3) do_restart_packet_forwarder;; + 4) nano $LORA_PKT_PATH/global_conf.json && do_main_menu;; + 5) do_select_lora_server;; + 6) do_configure_wifi;; + 7) do_configure_lan;; + 8) do_set_apn_name;; + 9) do_rak2013;; + esac + fi + + elif [ "$GW_MODEL" = "RAK2247" ] || [ "$GW_MODEL" = "RAK833" ]; then + FUN=$(dialog --title "$GW_MODEL (Gateway ID:$GW_ID Version: $GW_VERSION)" --cancel-label "Quit" --menu "Configuration options:" 16 80 20 \ + 1 "Set pi password" \ + 2 "Setup RAK Gateway LoRa concentrator" \ + 3 "Restart packet-forwarder" \ + 4 "Edit packet-forwarder config" \ + 5 "Select lora server" \ + 6 "Configure WIFI" \ + 7 "Configure LAN" \ + 3>&1 1>&2 2>&3) + RET=$? + if [ $RET -eq 1 ]; then + clear + return 0 + elif [ $RET -eq 0 ]; then + case "$FUN" in + 1) do_setup_admin_password;; + 2) do_setup_channel_plan;; + 3) do_restart_packet_forwarder;; + 4) nano $LORA_PKT_PATH/global_conf.json && do_main_menu;; + 5) do_select_lora_server;; + 6) do_configure_wifi;; + 7) do_configure_lan;; + esac + fi + else + echo "invalid gateway model:$GW_MODEL" + + fi +} + +if [ $(id -u) -ne 0 ]; then + printf "Script must be run as root. Try 'sudo gateway-config'\n" + exit 1 +fi + +do_main_menu + diff --git a/rak/gateway-version b/rak/gateway-version new file mode 100755 index 0000000..bcb90c8 --- /dev/null +++ b/rak/gateway-version @@ -0,0 +1,12 @@ +#!/bin/bash + +SCRIPT_COMMON_FILE=/usr/local/rak/shell_script/rak_common.sh + +source $SCRIPT_COMMON_FILE + +GW_MODEL=`do_get_gw_model` +GW_VERSION=`do_get_gw_version` +GW_ID=`do_get_gw_id` + +echo "Gateway ID:$GW_ID" +echo "RAKWireless gateway $GW_MODEL version $GW_VERSION" diff --git a/rak/install.sh b/rak/install.sh new file mode 100755 index 0000000..31ee6df --- /dev/null +++ b/rak/install.sh @@ -0,0 +1,43 @@ +#!/bin/bash + +# Stop on the first sign of trouble +set -e + +SCRIPT_COMMON_FILE=$(pwd)/../rak/rak/shell_script/rak_common.sh + +do_get_gw_id() +{ + GATEWAY_EUI_NIC="eth0" + if [[ `grep "$GATEWAY_EUI_NIC" /proc/net/dev` == "" ]]; then + GATEWAY_EUI_NIC="wlan0" + fi + + if [[ `grep "$GATEWAY_EUI_NIC" /proc/net/dev` == "" ]]; then + echo "" + fi + GATEWAY_EUI=$(ip link show $GATEWAY_EUI_NIC | awk '/ether/ {print $2}' | awk -F\: '{print $1$2$3"FFFE"$4$5$6}') + GATEWAY_EUI=${GATEWAY_EUI^^} + echo $GATEWAY_EUI +} + +source $SCRIPT_COMMON_FILE + +if [ $UID != 0 ]; then + echo "Operation not permitted. Forgot sudo?" + exit 1 +fi + +systemctl disable hciuart + +apt install git ppp dialog jq minicom monit -y + +cp gateway-config /usr/bin/ +cp gateway-version /usr/bin/ +cp rak /usr/local/ -rf + +#JSON_FILE=/usr/local/rak/rak_gw_model.json +#GW_ID=`do_get_gw_id` +#linenum=`sed -n "/gw_id/=" $JSON_FILE` +#sed -i "${linenum}c\\\\t\"gw_id\": \"$GW_ID\"," $JSON_FILE + +echo_success "Copy Rak file success!" diff --git a/rak/rak/bin/active_lte_module.sh b/rak/rak/bin/active_lte_module.sh new file mode 100755 index 0000000..9df169e --- /dev/null +++ b/rak/rak/bin/active_lte_module.sh @@ -0,0 +1,34 @@ +#!/bin/sh + +cd /sys/class/gpio/ +echo 5 > export +echo 6 > export +echo 13 > export +echo 19 > export +echo 21 > export +echo 26 > export +echo out > gpio5/direction +echo out > gpio6/direction +echo out > gpio13/direction +echo out > gpio19/direction +echo in > gpio21/direction +echo out > gpio26/direction + +echo 0 > gpio5/value +echo 0 > gpio6/value +echo 0 > gpio13/value +echo 0 > gpio19/value +echo 0 > gpio26/value + + +# +cd /sys/class/gpio/ + +echo "18" > /sys/class/gpio/export +echo "out" > /sys/class/gpio/gpio18/direction +echo 0 > /sys/class/gpio/gpio18/value +sleep 0.2 +echo 1 > /sys/class/gpio/gpio18/value +sleep 0.2 +echo 0 > /sys/class/gpio/gpio18/value + diff --git a/rak/rak/bin/ppp.sh b/rak/rak/bin/ppp.sh new file mode 100755 index 0000000..e200683 --- /dev/null +++ b/rak/rak/bin/ppp.sh @@ -0,0 +1,16 @@ +#!/bin/bash + +while [ true=true ] +do +# echo aaa + line=`ifconfig | grep ppp0 -c` +# echo $line + + if [ $line -ne 0 ]; then +# echo "111" + route del default + route add default dev ppp0 + exit + fi + sleep 30 +done diff --git a/rak/rak/bin/rak_script b/rak/rak/bin/rak_script new file mode 100755 index 0000000..bcbd9cf --- /dev/null +++ b/rak/rak/bin/rak_script @@ -0,0 +1,38 @@ +#!/bin/bash + +SCRIPT_COMMON_FILE=/usr/local/rak/shell_script/rak_common.sh +source $SCRIPT_COMMON_FILE + +systemctl stop serial-getty@ttyAMA0.service + +# first boot, add gateway_id to loraserver +if [ -f "/usr/local/rak/first_boot/init_loraserver_db" ]; then + cd /usr/local/rak/first_boot + sudo ./init_loraserver_db + mv /usr/local/rak/first_boot/init_loraserver_db /usr/local/rak/first_boot/init_loraserver_db_bak +fi + +# first boot, set ssid +if [ -f "/usr/local/rak/first_boot/set_ssid" ]; then + cd /usr/local/rak/first_boot + sudo ./set_ssid + mv /usr/local/rak/first_boot/set_ssid /usr/local/rak/first_boot/set_ssid_bak +fi + +# first boot, expand sd card +if [ -f "/usr/local/rak/first_boot/expand_rootfs.sh" ]; then + /usr/local/rak/first_boot/expand_rootfs.sh + mv /usr/local/rak/first_boot/expand_rootfs.sh /usr/local/rak/first_boot/expand_rootfs_bak.sh + reboot +fi + +GW_MODEL=`do_get_gw_model` +# active lte +if [ "$GW_MODEL" = "RAK7243" ]; then + pushd /usr/local/rak/bin + ./active_lte_module.sh + ./ppp.sh & + popd +fi + + diff --git a/rak/rak/gateway-config-info.json b/rak/rak/gateway-config-info.json new file mode 100644 index 0000000..158d7ca --- /dev/null +++ b/rak/rak/gateway-config-info.json @@ -0,0 +1,30 @@ +{ + "lora_server": + { + "server_plan":"2", + "lora_server_ip":"127.0.0.1", + "up_port":"1700", + "down_port":"1700", + "freq":"5" + }, + "wifi": + { + "wifi_mode":"1", + "wifi_ip":"", + "wifi_gw":"", + "ap_ssid":"rakwireless_xxxx", + "ap_pwd":"rakwireless" + }, + "lan": + { + "lan_ip":"192.168.10.10", + "lan_gw":"192.168.10.1" + }, + "apn": + { + "apn_name":"HOLOGRAM", + "apn_baud":"115200" + }, + "active_lora_server":"2", + "lte_mode":"2" +} diff --git a/rak/rak/lte/ppp-creator.sh b/rak/rak/lte/ppp-creator.sh new file mode 100755 index 0000000..23db257 --- /dev/null +++ b/rak/rak/lte/ppp-creator.sh @@ -0,0 +1,75 @@ +#!/bin/sh + +#echo "install ppp" +#apt-get install ppp + +echo "creating directories" +mkdir -p /etc/chatscripts +mkdir -p /etc/ppp/peers + +echo "creating script file : /etc/chatscripts/quectel-chat-connect" +echo " +ABORT \"BUSY\" +ABORT \"NO CARRIER\" +ABORT \"NO DIALTONE\" +ABORT \"ERROR\" +ABORT \"NO ANSWER\" +TIMEOUT 30 +\"\" AT +OK ATE0 +OK ATI;+CSUB;+CSQ;+COPS?;+CGREG?;&D2 +# Insert the APN provided by your network operator, default apn is $1 +OK AT+CGDCONT=1,\"IP\",\"\\T\",,0,0 +OK ATD*99# +CONNECT" > /etc/chatscripts/quectel-chat-connect + + +echo "creating script file : /etc/chatscripts/quectel-chat-disconnect" +echo " +ABORT \"ERROR\" +ABORT \"NO DIALTONE\" +SAY \"\nSending break to the modem\n\" +"" +++ +"" +++ +"" +++ +SAY \"\nGoodbay\n\"" > /etc/chatscripts/quectel-chat-disconnect + + +echo "creating script file : /etc/ppp/peers/gprs" +echo " +/dev/$2 $3 +# The chat script, customize your APN in this file +connect 'chat -s -v -f /etc/chatscripts/quectel-chat-connect -T $1' +# The close script +disconnect 'chat -s -v -f /etc/chatscripts/quectel-chat-disconnect' +# Hide password in debug messages +hide-password +# The phone is not required to authenticate +noauth +# Debug info from pppd +debug +# If you want to use the HSDPA link as your gateway +defaultroute +# pppd must not propose any IP address to the peer +noipdefault +# No ppp compression +novj +novjccomp +noccp +ipcp-accept-local +ipcp-accept-remote +local +# For sanity, keep a lock on the serial line +lock +modem +dump +nodetach +# Hardware flow control +nocrtscts +remotename 3gppp +ipparam 3gppp +ipcp-max-failure 30 +# Ask the peer for up to 2 DNS server addresses +usepeerdns" > /etc/ppp/peers/gprs + +echo "\n\nUse \"sudo pppd call gprs\" command and Surf" diff --git a/rak/rak/rak_gw_model.json b/rak/rak/rak_gw_model.json new file mode 100644 index 0000000..70e8b47 --- /dev/null +++ b/rak/rak/rak_gw_model.json @@ -0,0 +1,4 @@ +{ + "gw_model": "RAK7243", + "gw_version": "2.9R" +} diff --git a/rak/rak/shell_script/gateway-config/configure_eth.sh b/rak/rak/shell_script/gateway-config/configure_eth.sh new file mode 100644 index 0000000..b3a24ab --- /dev/null +++ b/rak/rak/shell_script/gateway-config/configure_eth.sh @@ -0,0 +1,60 @@ +#!/bin/bash + +do_configure_lan() { + rm /tmp/eth0_ip -rf + mkfifo /tmp/eth0_ip + + rm /tmp/eth0_gw -rf + mkfifo /tmp/eth0_gw + + # get old ip + old_eth0_ip=`do_get_gateway_info lan.lan_ip` + + # dialog ip + dialog --title "Set eth0 IP" --nocancel --inputbox "IP:" 10 40 "$old_eth0_ip" 2> /tmp/eth0_ip & + RET=$? + + if [ $RET -eq 1 ]; then + echo "error" + elif [ $RET -eq 0 ]; then + new_eth0_ip="$( cat /tmp/eth0_ip )" + do_check_ipaddr $new_eth0_ip + RET_IP=$? + rm /tmp/eth0_ip + fi + + # get old gw + old_eth0_gw=`do_get_gateway_info lan.lan_gw` + + # dialog eth0 gw + dialog --title "Set eth0 gateway IP" --nocancel --inputbox "Gateway IP:" 10 40 "$old_eth0_gw" 2> /tmp/eth0_gw & + RET=$? + + if [ $RET -eq 1 ]; then + echo "error" + elif [ $RET -eq 0 ]; then + new_eth0_gw="$( cat /tmp/eth0_gw )" + do_check_ipaddr $new_eth0_gw + RET_GW=$? + rm /tmp/eth0_gw + fi + + if [ $RET_IP -eq 1 ]; then + dialog --title "Configure LAN" --msgbox "Invalid IP address." 5 50 + elif [ $RET_GW -eq 1 ]; then + dialog --title "Configure LAN" --msgbox "Invalid Gateway IP address." 5 50 + else + + linenum=`sed -n '/RAK_eth0_IP/=' /etc/dhcpcd.conf` + let line_ip=linenum+2 + let line_gw=linenum+3 + + sed -i "${line_ip}cstatic ip_address=${new_eth0_ip}" /etc/dhcpcd.conf + sed -i "${line_gw}cstatic routers=${new_eth0_gw}" /etc/dhcpcd.conf + write_json_lan_ip ${new_eth0_ip} + write_json_lan_gw ${new_eth0_gw} + dialog --title "Configure LAN" --msgbox "Configure LAN success.Changes will take effect after OS restart." 5 70 + fi + + do_main_menu +} diff --git a/rak/rak/shell_script/gateway-config/configure_gw_channel.sh b/rak/rak/shell_script/gateway-config/configure_gw_channel.sh new file mode 100644 index 0000000..f826a48 --- /dev/null +++ b/rak/rak/shell_script/gateway-config/configure_gw_channel.sh @@ -0,0 +1,191 @@ +#!/bin/bash + +LORA_PKT_PATH=/opt/ttn-gateway/packet_forwarder/lora_pkt_fwd + +do_restart_packet_forwarder() { + docker stop rak_lora + systemctl stop ttn-gateway + systemctl start ttn-gateway + RET=$? + if [ $RET -eq 0 ]; then + dialog --title "Restart packet-forwarder" --msgbox "The packet-forwarder has been restarted." 5 60 +# else +# dialog --title "Restart packet-forwarder" --msgbox "Restart LoRa program failed, please try again to restart the program." 5 73 + fi + if [ $# -eq 0 ]; then + do_main_menu + fi +} + +do_copy_global_conf() { + cp $LORA_PKT_PATH/global_conf/global_conf.$2.json $LORA_PKT_PATH/global_conf.json +# write_json_server_freq $3 + if [ "$1" = "ttn" ]; then + dialog --title "Server-plan configuration" --msgbox "Server-plan configuration has been copied." 5 60 + write_json_server_plan 1 + elif [ "$1" = "lora_server" ]; then + write_json_server_plan 2 + do_set_lora_server_ip + cp /etc/loraserver/loraserver.$2.toml /etc/loraserver/loraserver.toml + do_if_proc_is_run "loraserver" + RET=$? + if [ $RET -eq 0 ]; then + do_LoRa_Server restart + fi + elif [ "$1" = "lorawan" ]; then + write_json_server_plan 3 + do_set_lora_server_ip + fi + + do_restart_packet_forwarder 1 +} + +do_setup_ttn_channel_plan() { +# default_item=`do_get_gateway_info lora_server.freq` + default_item=1 + FUN=$(dialog --title "TTN Channel-plan configuration" --default-item $default_item --menu "Select the Channel-plan:" 18 60 12 \ + 1 "AS_923" \ + 2 "AU_915_928" \ + 3 "CN_470_510" \ + 4 "EU_863_870" \ + 5 "IN_865_867" \ + 6 "KR_920_923" \ + 7 "RU_864_870" \ + 8 "US_902_928" \ + 3>&1 1>&2 2>&3) + RET=$? + if [ $RET -eq 1 ]; then + echo "test" + elif [ $RET -eq 0 ]; then + case "$FUN" in + 1) do_copy_global_conf "ttn" "as_923" 1;; + 2) do_copy_global_conf "ttn" "au_915_928" 2;; + 3) do_copy_global_conf "ttn" "cn_470_510" 3;; + 4) do_copy_global_conf "ttn" "eu_863_870" 4;; + 5) do_copy_global_conf "ttn" "in_865_867" 5;; + 6) do_copy_global_conf "ttn" "kr_920_923" 6;; + 7) do_copy_global_conf "ttn" "ru_864_870" 7;; + 8) do_copy_global_conf "ttn" "us_902_928" 8;; + esac + fi +} + +do_set_lora_server_ip() +{ + rm /tmp/gate_server_ip -rf + mkfifo /tmp/gate_server_ip + default_item=`do_get_gateway_info lora_server.lora_server_ip` + dialog --title "lora server IP" --nocancel --inputbox "SERVER_IP:" 10 40 "$default_item" 2> /tmp/gate_server_ip & + RET=$? + if [ $RET -eq 1 ]; then + echo "error" + elif [ $RET -eq 0 ]; then + gate_server_ip="$( cat /tmp/gate_server_ip )" + rm /tmp/gate_server_ip + + write_json_lora_server_ip "$gate_server_ip" + do_check_ip_is_localhost "$gate_server_ip" + RET=$? + if [ $RET -eq 0 ]; then +# sed -i "s/^.*RAK_LORA_SERVER_IP.*$/RAK_LORA_SERVER_IP=172.17.0.1/" /usr/local/rak/lora/rak.env + gate_server_ip="172.17.0.1" +# else +# sed -i "s/^.*RAK_LORA_SERVER_IP.*$/RAK_LORA_SERVER_IP=$gate_server_ip/" /usr/local/rak/lora/rak.env + fi + + sed -i "s/^.*server_address.*$/\t\"server_address\": \"$gate_server_ip\",/" /usr/local/rak/lora/global_conf.json + sed -i "s/^.*RAK_LORA_SERVER_IP.*$/RAK_LORA_SERVER_IP=$gate_server_ip/" /usr/local/rak/lora/rak.env + fi +} + +do_setup_lora_server_channel_plan() { +# default_item=`do_get_gateway_info lora_server.freq` + default_item=1 + FUN=$(dialog --title "LoRaServer Channel-plan configuration" --default-item $default_item --menu "Server the Channel-plan:" 18 60 12 \ + 1 "AS_923" \ + 2 "AU_915_928" \ + 3 "CN_470_510" \ + 4 "EU_433" \ + 5 "EU_863_870" \ + 6 "IN_865_867" \ + 7 "KR_920_923" \ + 8 "RU_864_870" \ + 9 "US_902_928" \ + 3>&1 1>&2 2>&3) + RET=$? + if [ $RET -eq 1 ]; then + echo "error" + + elif [ $RET -eq 0 ]; then + case "$FUN" in + 1) do_copy_global_conf "lora_server" "as_923" 1;; + 2) do_copy_global_conf "lora_server" "au_915_928" 2;; + 3) do_copy_global_conf "lora_server" "cn_470_510" 3;; + 4) do_copy_global_conf "lora_server" "eu_433" 4;; + 5) do_copy_global_conf "lora_server" "eu_863_870" 5;; + 6) do_copy_global_conf "lora_server" "in_865_867" 6;; + 7) do_copy_global_conf "lora_server" "kr_920_923" 7;; + 8) do_copy_global_conf "lora_server" "ru_864_870" 8;; + 9) do_copy_global_conf "lora_server" "us_902_928" 9;; + esac + fi +} + +do_setup_lorawan_server_channel_plan() { +# default_item=`do_get_gateway_info lora_server.freq` + default_item=1 + FUN=$(dialog --title "LoRaServer Channel-plan configuration" --default-item $default_item --menu "Server the Channel-plan:" 18 60 12 \ + 1 "AS_923" \ + 2 "AU_915_928" \ + 3 "CN_470_510" \ + 4 "EU_433" \ + 5 "EU_863_870" \ + 6 "IN_865_867" \ + 7 "KR_920_923" \ + 8 "RU_864_870" \ + 9 "US_902_928" \ + 3>&1 1>&2 2>&3) + RET=$? + if [ $RET -eq 1 ]; then + echo "error" + + elif [ $RET -eq 0 ]; then + case "$FUN" in + 1) do_copy_global_conf "lorawan" "as_923" 1;; + 2) do_copy_global_conf "lorawan" "au_915_928" 2;; + 3) do_copy_global_conf "lorawan" "cn_470_510" 3;; + 4) do_copy_global_conf "lorawan" "eu_433" 4;; + 5) do_copy_global_conf "lorawan" "eu_863_870" 5;; + 6) do_copy_global_conf "lorawan" "in_865_867" 6;; + 7) do_copy_global_conf "lorawan" "kr_920_923" 7;; + 8) do_copy_global_conf "lorawan" "ru_864_870" 8;; + 9) do_copy_global_conf "lorawan" "us_902_928" 9;; + esac + fi +} + +do_setup_channel_plan() { + # $1: concentrator type + # $2: config suffix, eg ".gps" + default_item=`do_get_gateway_info lora_server.server_plan` + + FUN=$(dialog --title "Server-plan configuration" --default-item $default_item --menu "Select the Server-plan:" 15 60 3 \ + 1 "Server is TTN" \ + 2 "Server is LoRaServer" \ + 3>&1 1>&2 2>&3) + RET=$? + + if [ $RET -eq 1 ]; then + echo "test" + elif [ $RET -eq 0 ]; then + case "$FUN" in + 1) do_setup_ttn_channel_plan;; + 2) do_setup_lora_server_channel_plan ;; + esac + fi + do_main_menu +} + + + + diff --git a/rak/rak/shell_script/gateway-config/configure_lora_server.sh b/rak/rak/shell_script/gateway-config/configure_lora_server.sh new file mode 100644 index 0000000..e69de29 diff --git a/rak/rak/shell_script/gateway-config/configure_lte_module.sh b/rak/rak/shell_script/gateway-config/configure_lte_module.sh new file mode 100644 index 0000000..2e7c6fa --- /dev/null +++ b/rak/rak/shell_script/gateway-config/configure_lte_module.sh @@ -0,0 +1,75 @@ +#!/bin/bash + +do_enable_2013() +{ + write_json_lte_mode 1 + systemctl enable rak-pppd + dialog --title "Enable LTE Module" --msgbox "The LTE module will power on after the operating system starts." 5 70 +# do_main_menu +} + +do_disable_2013() +{ + write_json_lte_mode 2 + systemctl disable rak-pppd + dialog --title "Disable LTE Module" --msgbox "The LTE module will not power on after the operating system starts." 5 71 +# do_main_menu +} + +do_rak2013() +{ + # get lte module status + default_item=`do_get_gateway_info lte_mode` + + FUN=$(dialog --title "LTE Module" --cancel-label "Cancel" --default-item $default_item --menu "Configuration options:" 10 60 20 \ + 1 "Enable LTE Automatic Dial-up" \ + 2 "Disable LTE Automatic Dial-up" \ + 3>&1 1>&2 2>&3) + RET=$? + if [ $RET -eq 1 ]; then + clear + elif [ $RET -eq 0 ]; then + case "$FUN" in + 1) do_enable_2013;; + 2) do_disable_2013;; + esac + fi + do_main_menu +} + +do_set_apn_name() +{ + # get old apn + old_apn=`do_get_gateway_info apn.apn_name` + + # get old baud speed + old_baud=`do_get_gateway_info apn.apn_baud` + + rm /tmp/apn_name -rf + mkfifo /tmp/apn_name + rm /tmp/band_speed -rf + mkfifo /tmp/band_speed + dialog --title "APN Name" --nocancel --inputbox "APN Name:" 10 40 "$old_apn" 2> /tmp/apn_name & + dialog --title "Baud Speed" --nocancel --inputbox "Baud Speed:" 10 40 "$old_baud" 2> /tmp/band_speed & + RET=$? + + if [ $RET -eq 1 ]; then + echo "error" + elif [ $RET -eq 0 ]; then + new_apn_name="$( cat /tmp/apn_name )" + new_baud_speed="$( cat /tmp/band_speed )" + + RET2=`do_check_variable_type $new_baud_speed` + if [ $RET2 -ne 0 ]; then + dialog --title "Baud Speed" --msgbox "Invalid baud speed." 5 40 + else + /usr/local/rak/lte/ppp-creator.sh "${new_apn_name}" ttyAMA0 ${new_baud_speed} >/dev/null + rm /tmp/apn_name -rf + rm /tmp/band_speed -rf + + write_json_apn_name $new_apn_name + write_json_apn_baud $new_baud_speed + fi + fi + do_main_menu +} diff --git a/rak/rak/shell_script/gateway-config/configure_wlan.sh b/rak/rak/shell_script/gateway-config/configure_wlan.sh new file mode 100644 index 0000000..409525e --- /dev/null +++ b/rak/rak/shell_script/gateway-config/configure_wlan.sh @@ -0,0 +1,205 @@ +#!/bin/bash + +do_enable_ap_mode() +{ + write_json_wifi_mode 1 + systemctl enable create_ap + + if [ -f "/sbin/wpa_supplicant" ]; then + mv /sbin/wpa_supplicant /sbin/wpa_supplicant_bak + fi + dialog --title "Enable AP Mode" --msgbox "The AP mode will active after the operating system reboot." 5 70 +} + +do_enable_wifi_mode() +{ + write_json_wifi_mode 2 + systemctl disable create_ap + + if [ -f "/sbin/wpa_supplicant_bak" ]; then + mv /sbin/wpa_supplicant_bak /sbin/wpa_supplicant + fi + + dialog --title "Enable Wifi Mode" --msgbox "The Client mode will active after the operating system reboot." 5 70 +} + +do_modify_ssid_for_ap() +{ + echo "aaa" + rm /tmp/rak_ssid -rf + mkfifo /tmp/rak_ssid + rm /tmp/rak_ap_pwd -rf + mkfifo /tmp/rak_ap_pwd + + # get old ssid + old_ap_ssid=`do_get_gateway_info wifi.ap_ssid` + + # get old pwd + old_ap_pwd=`do_get_gateway_info wifi.ap_pwd` + + # dialog ip + dialog --title "AP SSID" --nocancel --inputbox "SSID:" 10 40 "$old_ap_ssid" 2> /tmp/rak_ssid & + RET=$? + + if [ $RET -eq 1 ]; then + clear + elif [ $RET -eq 0 ]; then + new_ap_ssid="$( cat /tmp/rak_ssid )" + rm /tmp/rak_ssid + ssid_len=${#new_ap_ssid} + fi + + #dialog pwd + dialog --title "AP Password" --nocancel --inputbox "Password:" 10 40 "$old_ap_pwd" 2> /tmp/rak_ap_pwd & + if [ $RET -ne 0 ]; then + clear + else + new_ap_pwd="$( cat /tmp/rak_ap_pwd )" + pwd_len=${#new_ap_pwd} + rm /tmp/rak_ap_pwd + + fi + + if [ $ssid_len -eq 0 ] || [ $pwd_len -eq 0 ] || [ $pwd_len -lt 8 ] ||[ $pwd_len -gt 63 ]; then + if [ $ssid_len -eq 0 ]; then + dialog --title "Configure AP SSID" --msgbox "SSID cannot be empty." 5 28 + elif [ $pwd_len -eq 0 ] || [ $pwd_len -lt 8 ] ||[ $pwd_len -gt 63 ]; then + dialog --title "Configure AP Password" --msgbox "Invalid passphrase length ${pwd_len} (expected: 8..63)." 5 52 + else + clear + fi + else + sed -i "26c SSID=$new_ap_ssid" /usr/local/rak/ap/create_ap.conf + sed -i "27c PASSPHRASE=$new_ap_pwd" /usr/local/rak/ap/create_ap.conf + + write_json_ap_ssid $new_ap_ssid + write_json_ap_pwd $new_ap_pwd + dialog --title "Configute AP info" --msgbox "Modify AP info success.Changes will take effect after OS restart." 5 72 + fi + +# do_main_menu +} + +do_add_new_ssid() +{ + rm /tmp/wifi_ssid -rf + mkfifo /tmp/wifi_ssid + rm /tmp/wifi_pwd -rf + mkfifo /tmp/wifi_pwd + dialog --title "Configure WIFI" --nocancel --inputbox "SSID:" 10 40 2> /tmp/wifi_ssid & + if [ $RET -ne 0 ]; then +# do_main_menu + echo "test" + return 1 + fi + dialog --title "Configure WIFI" --nocancel --inputbox "Password:" 10 40 2> /tmp/wifi_pwd & + if [ $RET -ne 0 ]; then +# do_main_menu + return 1 + fi + + linenum=`sed -n '/update_config/=' /etc/wpa_supplicant/wpa_supplicant.conf` + let linenum=linenum+1 + + wifi_ssid="$( cat /tmp/wifi_ssid )" + wifi_pwd="$( cat /tmp/wifi_pwd )" + ssid_len=${#wifi_ssid} + pwd_len=${#wifi_pwd} + + if [ $ssid_len -eq 0 ]; then + dialog --title "Configure WIFI" --msgbox "SSID cannot be empty." 5 28 +# do_main_menu + return 1 + fi + + if [ $pwd_len -eq 0 ] || [ $pwd_len -lt 8 ] ||[ $pwd_len -gt 63 ]; then + dialog --title "Configure WIFI" --msgbox "Invalid passphrase length ${pwd_len} (expected: 8..63)." 5 52 + # do_main_menu + return 1 + else + sed -i "${linenum}inetwork={\nssid=\"${wifi_ssid}\"\nkey_mgmt=WPA-PSK\npsk=\"${wifi_pwd}\"\n}" /etc/wpa_supplicant/wpa_supplicant.conf + dialog --title "Configure WIFI" --msgbox "Add new SSID success.Configuration will take effect after OS restart" 5 72 + fi +} + +do_configure_wlan_ip() { + rm /tmp/wlan0_ip -rf + mkfifo /tmp/wlan0_ip + + rm /tmp/wlan0_gw -rf + mkfifo /tmp/wlan0_gw + + # get old ip + old_wlan0_ip=`do_get_gateway_info wifi.wifi_ip` + + # dialog ip + dialog --title "Set wlan0 IP" --nocancel --inputbox "IP:" 10 40 "$old_wlan0_ip" 2> /tmp/wlan0_ip & + RET=$? + + if [ $RET -eq 1 ]; then + echo "error" + elif [ $RET -eq 0 ]; then + new_wlan0_ip="$( cat /tmp/wlan0_ip )" + do_check_ipaddr $new_wlan0_ip + RET_IP=$? + rm /tmp/wlan0_ip + fi + + # get old gw + old_wlan0_gw=`do_get_gateway_info wifi.wifi_gw` + + # dialog wlan0 gw + dialog --title "Set wlan0 gateway IP" --nocancel --inputbox "Gateway IP:" 10 40 "$old_wlan0_gw" 2> /tmp/wlan0_gw & + RET=$? + + if [ $RET -eq 1 ]; then + echo "error" + elif [ $RET -eq 0 ]; then + new_wlan0_gw="$( cat /tmp/wlan0_gw )" + do_check_ipaddr $new_wlan0_gw + RET_GW=$? + rm /tmp/wlan0_gw + fi + + if [ $RET_IP -eq 1 ]; then + dialog --title "Configure wlan0" --msgbox "Invalid IP address." 5 50 + elif [ $RET_GW -eq 1 ]; then + dialog --title "Configure wlan0" --msgbox "Invalid Gateway IP address." 5 50 + else + + linenum=`sed -n '/RAK_wlan0_IP/=' /etc/dhcpcd.conf` + let line_ip=linenum+2 + let line_gw=linenum+3 + + sed -i "${line_ip}cstatic ip_address=${new_wlan0_ip}" /etc/dhcpcd.conf + sed -i "${line_gw}cstatic routers=${new_wlan0_gw}" /etc/dhcpcd.conf + write_json_wlan_ip ${new_wlan0_ip} + write_json_wlan_gw ${new_wlan0_gw} + dialog --title "Configure wlan0" --msgbox "Configure wlan0 success.Changes will take effect after OS restart." 5 70 + fi +} + +do_configure_wifi() { + default_item=`do_get_gateway_info wifi.wifi_mode` + + FUN=$(dialog --title "Configure wifi" --cancel-label "Cancel" --default-item $default_item --menu "Configuration options:" 12 60 20 \ + 1 "Enable AP Mode/Disable Client Mode" \ + 2 "Enable Client Mode/Disable AP Mode" \ + 3 "Modify SSID and pwd for AP Mode" \ + 4 "Add New SSID for Client" \ + 5 "Configure WLAN ip(When Client Mode)" \ + 3>&1 1>&2 2>&3) + RET=$? + if [ $RET -eq 0 ]; then + case "$FUN" in + 1) do_enable_ap_mode;; + 2) do_enable_wifi_mode;; + 3) do_modify_ssid_for_ap;; + 4) do_add_new_ssid;; + 5) do_configure_wlan_ip;; + esac + fi + + do_main_menu +} + diff --git a/rak/rak/shell_script/gateway-config/do_json.sh b/rak/rak/shell_script/gateway-config/do_json.sh new file mode 100644 index 0000000..ce2e430 --- /dev/null +++ b/rak/rak/shell_script/gateway-config/do_json.sh @@ -0,0 +1,36 @@ +#!/bin/bash + +do_get_json_value() +{ + # $1 key; $2 file + Var1=$(jq .$1 $2) + Var2=${Var1//\"/} + echo $Var2 +} + +do_get_gateway_info() +{ + GATEWAY_CONFIG_INFO=/usr/local/rak/gateway-config-info.json + do_get_json_value $1 $GATEWAY_CONFIG_INFO +} + +write_json_gateway_info() +{ + # $1 key; $2 value + do_check_variable_type $1 + RET=$? + if [ $RET -eq 3 ]; then + sed -i "s/^.*$1.*$/\"$1\":\"$2\",/" /usr/local/rak/gateway-config-info.json + fi +} + +write_json_gateway_info_no_comma() +{ + # $1 key; $2 value + do_check_variable_type $1 + RET=$? + if [ $RET -eq 3 ]; then + sed -i "s/^.*$1.*$/\"$1\":\"$2\"/" /usr/local/rak/gateway-config-info.json + fi +} + diff --git a/rak/rak/shell_script/rak_common.sh b/rak/rak/shell_script/rak_common.sh new file mode 100755 index 0000000..b304f00 --- /dev/null +++ b/rak/rak/shell_script/rak_common.sh @@ -0,0 +1,73 @@ +#!/bin/bash + +RAK_GW_INFO_JSON_FILE=/usr/local/rak/rak_gw_model.json +GATEWAY_CONFIG_INFO=/usr/local/rak/gateway-config-info.json + +function echo_normal() +{ + echo -e $1 +} + +function echo_success() +{ + echo -e "\033[1;32m$1\033[0m" +} + +function echo_error() +{ + echo -e "\033[1;31mERROR: $1\033[0m" +} + +function echo_warn() +{ + echo -e "\033[1;33mWARNING: $1\033[0m" +} + +do_get_json_value() +{ + # $1 key; $2 file + Var1=$(jq .$1 $2) + Var2=${Var1//\"/} + echo $Var2 +} + +do_get_gateway_info() +{ + do_get_json_value gw_model $GATEWAY_CONFIG_INFO +} + +do_get_gw_model() +{ + do_get_json_value gw_model $RAK_GW_INFO_JSON_FILE +} + +do_get_gw_version() +{ + do_get_json_value gw_version $RAK_GW_INFO_JSON_FILE +} + +do_get_gw_id() +{ + GATEWAY_EUI_NIC="eth0" + if [[ `grep "$GATEWAY_EUI_NIC" /proc/net/dev` == "" ]]; then + GATEWAY_EUI_NIC="wlan0" + fi + + if [[ `grep "$GATEWAY_EUI_NIC" /proc/net/dev` == "" ]]; then + echo "" + fi + GATEWAY_EUI=$(ip link show $GATEWAY_EUI_NIC | awk '/ether/ {print $2}' | awk -F\: '{print $1$2$3"FFFE"$4$5$6}') + GATEWAY_EUI=${GATEWAY_EUI^^} + echo $GATEWAY_EUI +} + +do_check_variable_type(){ + local a="$1" + printf "%d" "$a" &>/dev/null && return 0 + printf "%d" "$(echo $a|sed 's/^[+-]\?0\+//')" &>/dev/null && return 0 + printf "%f" "$a" &>/dev/null && return 1 + [ ${#a} -eq 1 ] && return 2 + return 3 +} + + diff --git a/sysconf/config.txt b/sysconf/config.txt new file mode 100644 index 0000000..46864bc --- /dev/null +++ b/sysconf/config.txt @@ -0,0 +1,60 @@ +# For more options and information see +# http://rpf.io/configtxt +# Some settings may impact device functionality. See link above for details + +# uncomment if you get no picture on HDMI for a default "safe" mode +#hdmi_safe=1 + +# uncomment this if your display has a black border of unused pixels visible +# and your display can output without overscan +#disable_overscan=1 + +# uncomment the following to adjust overscan. Use positive numbers if console +# goes off screen, and negative if there is too much border +#overscan_left=16 +#overscan_right=16 +#overscan_top=16 +#overscan_bottom=16 + +# uncomment to force a console size. By default it will be display's size minus +# overscan. +#framebuffer_width=1280 +#framebuffer_height=720 + +# uncomment if hdmi display is not detected and composite is being output +#hdmi_force_hotplug=1 + +# uncomment to force a specific HDMI mode (this will force VGA) +#hdmi_group=1 +#hdmi_mode=1 + +# uncomment to force a HDMI mode rather than DVI. This can make audio work in +# DMT (computer monitor) modes +#hdmi_drive=2 + +# uncomment to increase signal to HDMI, if you have interference, blanking, or +# no display +#config_hdmi_boost=4 + +# uncomment for composite PAL +#sdtv_mode=2 + +#uncomment to overclock the arm. 700 MHz is the default. +#arm_freq=800 + +# Uncomment some or all of these to enable the optional hardware interfaces +dtparam=i2c_arm=on +#dtparam=i2s=on +dtparam=spi=on +dtparam=i2c1=on +dtparam=i2c_arm_baudrate=10000 + +# Uncomment this to enable the lirc-rpi module +#dtoverlay=lirc-rpi + +# Additional overlays and parameters are documented /boot/overlays/README + +# Enable audio (loads snd_bcm2835) +dtparam=audio=on +dtoverlay=pi3-disable-bt +dtoverlay=dwc2 diff --git a/sysconf/install.sh b/sysconf/install.sh new file mode 100755 index 0000000..a5947ab --- /dev/null +++ b/sysconf/install.sh @@ -0,0 +1,30 @@ +#!/bin/bash + +# Stop on the first sign of trouble +set -e + +SCRIPT_COMMON_FILE=$(pwd)/../rak/rak/shell_script/rak_common.sh +source $SCRIPT_COMMON_FILE + +if [ $UID != 0 ]; then + echo_error "Operation not permitted. Forgot sudo?" + exit 1 +fi + +# add rak_script to rc.local +linenum=`sed -n '/rak_script/=' /etc/rc.local` +if [ ! -n "$linenum" ]; then + set -a line_array + line_index=0 + for linenum in `sed -n '/exit 0/=' /etc/rc.local`; do line_array[line_index]=$linenum; let line_index=line_index+1; done + sed -i "${line_array[${#line_array[*]} - 1]}i/usr/local/rak/bin/rak_script" /etc/rc.local +fi + +cp config.txt /boot/config.txt + +CMD_STR=`cat /boot/cmdline.txt` +echo "$CMD_STR modules-load=dwc2,g_ether" > /boot/cmdline.txt + +./set_ip.sh + +echo_success "Copy sys_config file success!" diff --git a/sysconf/set_ip.sh b/sysconf/set_ip.sh new file mode 100755 index 0000000..f32a19e --- /dev/null +++ b/sysconf/set_ip.sh @@ -0,0 +1,92 @@ +#!/bin/bash + +# Stop on the first sign of trouble +#set -e + +SCRIPT_COMMON_FILE=$(pwd)/../rak/rak/shell_script/rak_common.sh +source $SCRIPT_COMMON_FILE + +if [ $UID != 0 ]; then + echo_error "Operation not permitted. Forgot sudo?" + exit 1 +fi + +write_json_gateway_info_no_comma() +{ + # $1 key; $2 value + do_check_variable_type $1 + RET=$? + if [ $RET -eq 3 ]; then + sed -i "s/^.*$1.*$/\"$1\":\"$2\"/" /usr/local/rak/gateway-config-info.json + fi +} + +write_json_gateway_info() +{ + # $1 key; $2 value + do_check_variable_type $1 + RET=$? + if [ $RET -eq 3 ]; then + sed -i "s/^.*$1.*$/\"$1\":\"$2\",/" /usr/local/rak/gateway-config-info.json + fi +} + +write_json_lan_ip() +{ + # 数字 . 校验下是否为有效IP + write_json_gateway_info "lan_ip" $1 +} + +write_json_lan_gw() +{ + # 数字 . 校验下是否为有效IP + write_json_gateway_info_no_comma "lan_gw" $1 +} + +write_json_wlan_ip() +{ + # 数字 . 校验下是否为有效IP + write_json_gateway_info "wifi_ip" $1 +} + +write_json_wlan_gw() +{ + # 数字 . 校验下是否为有效IP + write_json_gateway_info "wifi_gw" $1 +} + +get_inte_ip() +{ + IP_ADDR=`ifconfig $1|grep inet|grep -v 127.0.0.1|grep -v inet6|awk '{print $2}'|tr -d "addr:"` + echo $IP_ADDR +} + +get_gw_by_ip() +{ + newip=$(echo $1 |cut -f 1-3 -d .) + echo $newip +} + +get_inte_ip wlan0 + +eth0_ip=`get_inte_ip eth0` + +if [ -z "$eth0_ip" ]; then + echo "eth0 ip null" + eth0_ip="192.168.10.10" + eth0_gw="192.168.10.1" +else + echo "eth0_ip:$eth0_ip" + eth0_gw=`get_gw_by_ip $eth0_ip`".1" +fi + +echo " +# WARNING:Do not delete or modify the following 5 lines!!! +# RAK_eth0_IP +interface eth0 +static ip_address=${eth0_ip} +static routers=${eth0_gw} +static domain_name_servers=8.8.8.8 223.5.5.5" >> /etc/dhcpcd.conf + +echo_success "Set eth0 IP address:$eth0_ip" +sleep 5