--- /dev/null
+#
+# Copyright (C) 2022 TDT AG <development@tdt.de>
+#
+# This is free software, licensed under the GNU General Public License v2.
+# See /LICENSE for more information.
+#
+#
+include $(TOPDIR)/rules.mk
+
+PKG_NAME:=basicstation
+PKG_VERSION:=2.0.6
+PKG_RELEASE:=$(AUTORELEASE)
+
+PKG_SOURCE:=$(PKG_NAME)-$(PKG_VERSION).tar.gz
+PKG_SOURCE_URL:=https://codeload.github.com/lorabasics/basicstation/tar.gz/v$(PKG_VERSION)?
+PKG_HASH:=7e285de94bae1174b4c3496fc3ab15fe67c72f92c0693d2320bafc654a9dfb43
+
+PKG_MAINTAINER:=Marcus Schref <mschref@tdt.de>
+PKG_LICENSE:=BSD-3-Clause
+PKG_LICENSE_FILES:=LICENSE
+
+PKG_BUILD_DEPENDS:=sx1302_hal mbedtls
+
+include $(INCLUDE_DIR)/package.mk
+include $(INCLUDE_DIR)/cmake.mk
+
+define Package/basicstation
+ SECTION:=net
+ CATEGORY:=Network
+ SUBMENU:=LoRaWAN
+ TITLE:=LoRa Basic Station
+ DEPENDS:=+kmod-usb-acm
+endef
+
+define Package/basicstation/description
+ LoRa Basic Station. The LoRaWAN Gateway Software.
+endef
+
+define Package/basicstation/conffiles
+/etc/config/basicstation
+endef
+
+define Build/Prepare
+ $(call Build/Prepare/Default)
+ rm -rf $(PKG_BUILD_DIR)/deps/
+ rm -f $(PKG_BUILD_DIR)/makefile
+ rm -f $(PKG_BUILD_DIR)/makefile.s2core
+ rm -f $(PKG_BUILD_DIR)/setup.gmk
+endef
+
+define Package/basicstation/install
+ $(INSTALL_DIR) $(1)/usr/bin
+ $(INSTALL_BIN) $(PKG_BUILD_DIR)/station $(1)/usr/bin
+ $(INSTALL_DIR) $(1)/etc/config
+ $(INSTALL_CONF) ./files/etc/config/basicstation $(1)/etc/config/basicstation
+ $(INSTALL_DIR) $(1)/etc/init.d
+ $(INSTALL_BIN) ./files/etc/init.d/basicstation $(1)/etc/init.d/basicstation
+endef
+
+$(eval $(call BuildPackage,basicstation))
--- /dev/null
+#!/bin/sh /etc/rc.common
+#
+# Copyright (C) 2022 TDT AG <development@tdt.de>
+#
+# This is free software, licensed under the GNU General Public License v2.
+# See https://www.gnu.org/licenses/gpl-2.0.txt for more information.
+
+START=85
+STOP=25
+
+USE_PROCD=1
+
+#radioconf
+DEFAULT_COMIF='usb'
+DEFAULT_DEVPATH='/dev/ttyACM0'
+DEFAULT_PPS=0
+DEFAULT_PUBLIC=1
+DEFAULT_CLKSRC=0
+DEFAULT_RADIO_0='rfconf0'
+DEFAULT_RADIO_1='rfconf1'
+
+#rfconf
+DEFAULT_TYPE='SX1250'
+DEFAULT_TX_ENABLE=0
+DEFAULT_FREQ=0
+DEFAULT_RSSI_OFFSET=0
+DEFAULT_ANTENNA_GAIN=0
+DEFAULT_RSSI_TCOMP='std'
+
+#rssi tcomp
+DEFAULT_RSSI_TCOMP_A=0
+DEFAULT_RSSI_TCOMP_B=0
+DEFAULT_RSSI_TCOMP_C=20.41
+DEFAULT_RSSI_TCOMP_D=2162.56
+DEFAULT_RSSI_TCOMP_E=0
+
+#tx gain lut
+DEFAULT_RF_POWER=0
+DEFAULT_PA_GAIN=0
+DEFAULT_PWR_IDX=0
+
+#station
+DEFAULT_RADIO_INIT=''
+DEFAULT_ID_GEN_IF='eth0'
+DEFAULT_ROUTER_ID='/sys/class/net/eth0/address'
+DEFAULT_LOG_FILE='/tmp/basicstation/log'
+DEFAULT_LOG_LEVEL='DEBUG'
+DEFAULT_LOG_SIZE=1
+DEFAULT_LOG_ROTATE=1
+
+#auth
+DEFAULT_CREDENTIALS='tc'
+DEFAULT_MODE='no'
+
+parse_txlut() {
+ local section="$1"
+ local buffer
+
+ config_get buffer "$section" usedBy
+
+ if [[ "$buffer" == *"$2"* ]]; then
+ json_add_object
+
+ config_get buffer "$section" rfPower "$DEFAULT_RF_POWER"
+ json_add_int 'rf_power' "$buffer"
+ config_get_bool buffer "$section" paGain "$DEFAULT_PA_GAIN"
+ json_add_int 'pa_gain' "$buffer"
+ config_get buffer "$section" pwrIdx "$DEFAULT_PWR_IDX"
+ json_add_int 'pwr_idx' "$buffer"
+
+ json_close_object
+ fi
+}
+
+parse_rssitcomp() {
+ local section="$1"
+ local buffer
+
+ if [ "$section" = "$2" ]; then
+ json_add_object 'rssi_tcomp'
+
+ config_get buffer "$section" coeff_a "$DEFAULT_RSSI_TCOMP_A"
+ json_add_double 'coeff_a' "$buffer"
+ config_get buffer "$section" coeff_b "$DEFAULT_RSSI_TCOMP_B"
+ json_add_double 'coeff_b' "$buffer"
+ config_get buffer "$section" coeff_c "$DEFAULT_RSSI_TCOMP_C"
+ json_add_double 'coeff_c' "$buffer"
+ config_get buffer "$section" coeff_d "$DEFAULT_RSSI_TCOMP_D"
+ json_add_double 'coeff_d' "$buffer"
+ config_get buffer "$section" coeff_e "$DEFAULT_RSSI_TCOMP_E"
+ json_add_double 'coeff_e' "$buffer"
+
+ json_close_object
+ fi
+}
+
+parse_rfconf() {
+ local section="$1"
+ local buffer
+
+ if [ "$section" = "$2" ]; then
+ json_add_object "radio_"$3""
+
+ config_get buffer "$section" type "$DEFAULT_TYPE"
+ json_add_string 'type' "$buffer"
+ config_get buffer "$section" freq "$DEFAULT_FREQ"
+ json_add_int 'freq' "$buffer"
+ config_get buffer "$section" antennaGain "$DEFAULT_ANTENNA_GAIN"
+ json_add_int 'antenna_gain' "$buffer"
+ config_get buffer "$section" rssiOffset "$DEFAULT_RSSI_OFFSET"
+ json_add_double 'rssi_offset' "$buffer"
+ config_get buffer "$section" useRssiTcomp "$DEFAULT_RSSI_TCOMP"
+ config_foreach parse_rssitcomp rssitcomp "$buffer"
+ config_get_bool buffer "$section" txEnable "$DEFAULT_TX_ENABLE"
+ json_add_boolean 'tx_enable' "$buffer"
+
+ if [ "$buffer" -eq 1 ]; then
+ json_add_array 'tx_gain_lut'
+ config_foreach parse_txlut txlut "$section"
+ json_close_array
+ fi
+
+ json_close_object
+ fi
+}
+
+parse_sx130x() {
+ local section="$1"
+ local comif
+ local devpath
+ local buffer
+
+ json_add_object 'radio_conf'
+
+ config_get comif "$section" comif "$DEFAULT_COMIF"
+ config_get devpath "$section" devpath "$DEFAULT_DEVPATH"
+ json_add_string 'device' ""$comif":"$devpath""
+ config_get_bool buffer "$section" pps "$DEFAULT_PPS"
+ json_add_boolean 'pps' "$buffer"
+ config_get_bool buffer "$section" public "$DEFAULT_PUBLIC"
+ json_add_boolean 'lorawan_public' "$buffer"
+ config_get buffer "$section" clksrc "$DEFAULT_CLKSRC"
+ json_add_int 'clksrc' "$buffer"
+ json_add_boolean 'full_duplex' 0
+ config_get buffer "$section" radio0 "$DEFAULT_RADIO_0"
+ config_foreach parse_rfconf rfconf "$buffer" 0
+ config_get buffer "$section" radio1 "$DEFAULT_RADIO_1"
+ config_foreach parse_rfconf rfconf "$buffer" 1
+
+ json_close_object
+}
+
+parse_station() {
+ local section="$1"
+ local buffer
+ local mac
+
+ config_get buffer "$section" idGenIf "$DEFAULT_ID_GEN_IF"
+ mac=$(head -n 1 /sys/class/net/"$buffer"/address)
+ uci_set basicstation "$section" stationid "${mac::8}:ff:fe:${mac:9:8}"
+ uci_commit basicstation
+
+ json_add_object 'station_conf'
+
+ config_get buffer "$section" routerid "$DEFAULT_ROUTER_ID"
+ json_add_string 'routerid' "$buffer"
+ config_get buffer "$section" radioInit "$DEFAULT_RADIO_INIT"
+ json_add_string 'radio_init' "$buffer"
+ config_get buffer "$section" logFile "$DEFAULT_LOG_FILE"
+ json_add_string 'log_file' "$buffer"
+ config_get buffer "$section" logLevel "$DEFAULT_LOG_LEVEL"
+ json_add_string 'log_level' "$buffer"
+ config_get buffer "$section" logSize "$DEFAULT_LOG_SIZE"
+ json_add_int 'log_size' $(( 1000000*buffer ))
+ config_get buffer "$section" logRotate "$DEFAULT_LOG_ROTATE"
+ json_add_int 'log_rotate' "$buffer"
+
+ json_close_object
+}
+
+parse_auth() {
+ local section="$1"
+ local cred
+ local mode
+ local addr
+ local port
+ local uri
+ local buffer
+
+ config_get cred "$section" cred "$DEFAULT_CREDENTIALS"
+ config_get mode "$section" mode "$DEFAULT_MODE"
+ config_get addr "$section" addr
+ config_get port "$section" port
+
+ if [ "$mode" != 'no' ]; then
+ config_get buffer "$section" trust
+ [ -f "$buffer" ] && cp "$buffer" /tmp/basicstation/"$cred".trust
+ if [ "$mode" = 'serverAndClient' ]; then
+ config_get buffer "$section" key
+ echo "$buffer" > /tmp/basicstation/"$cred".key
+ config_get buffer "$section" crt
+ [ -f "$buffer" ] && cp "$buffer" /tmp/basicstation/"$cred".crt
+ elif [ "$mode" = 'serverAndClientToken' ]; then
+ config_get buffer "$section" token
+ echo "$buffer" > /tmp/basicstation/"$cred".key
+ fi
+ if [ "$cred" = "tc" ]; then
+ uri="wss://${addr}:${port}"
+ else
+ uri="https://${addr}:${port}"
+ fi
+ else
+ if [ "$cred" = "tc" ]; then
+ uri="ws://${addr}:${port}"
+ else
+ uri="http://${addr}:${port}"
+ fi
+ fi
+
+ echo "$uri" > /tmp/basicstation/"$cred".uri
+}
+
+process_config() {
+ . /usr/share/libubox/jshn.sh
+ json_init
+
+ config_load basicstation
+ config_foreach parse_sx130x sx130x
+ config_foreach parse_station station
+ json_dump -i > /tmp/basicstation/station.conf
+ config_foreach parse_auth auth
+}
+
+service_triggers() {
+ procd_add_reload_trigger "basicstation"
+}
+
+start_service() {
+ rm -rf /tmp/basicstation/
+ mkdir -p /tmp/basicstation/
+
+ process_config
+
+ procd_open_instance
+ procd_set_param command /usr/bin/station
+ procd_append_param command --home /tmp/basicstation/
+ procd_append_param command --force
+ procd_set_param respawn
+ procd_close_instance
+}
+
+reload_service() {
+ restart "$@"
+}
--- /dev/null
+cmake_minimum_required(VERSION 3.18.4)
+project(basicstation)
+
+add_compile_definitions(CFG_linux)
+add_compile_definitions(CFG_lgw1)
+add_compile_definitions(CFG_sx1302)
+add_compile_definitions(CFG_ral_lgw)
+add_compile_definitions(CFG_no_leds)
+add_compile_definitions(CFG_argp)
+add_compile_definitions(CFG_platform="linux")
+add_compile_definitions(CFG_bdate=${PKG_SOURCE_DATE})
+file(STRINGS "VERSION.txt" VERSION_NUMBER)
+add_compile_definitions(CFG_version="${VERSION_NUMBER}")
+
+
+include_directories(src)
+include_directories(src-linux)
+
+find_path(SX1302_HAL_INCLUDE_DIR NAMES lgw/loragw_hal.h)
+find_path(MBEDTLS_INCLUDE_DIR NAMES mbedtls/x509.h)
+find_library(SX1302_HAL_LIBRARY NAMES libloragw.a PATH /usr/lib/)
+find_library(TINYMT32_LIBRARY NAMES libtinymt32.a PATH /usr/lib/)
+find_library(MBEDTLS_LIBRARY NAMES libmbedtls.a PATH /usr/lib/)
+find_library(MBEDCRYPTO_LIBRARY NAMES libmbedcrypto.a PATH /usr/lib/)
+find_library(MBEDX509_LIBRARY NAMES libmbedx509.a PATH /usr/lib/)
+
+set(basicstation_SOURCE_FILES
+ src/aio.c
+ src/argp.c
+ src/crc32.c
+ src/cups.c
+ src/flashsim.c
+ src/fs.c
+ src/genkwcrcs.c
+ src/lgwsim.c
+ src/log.c
+ src/lora.c
+ src/net.c
+ src/ral.c
+ src/ral_lgw.c
+ src/ral_lgw2.c
+ src/rt.c
+ src/s2conf.c
+ src/s2e.c
+ src/selftest_fs.c
+ src/selftest_lora.c
+ src/selftest_rt.c
+ src/selftest_ujdec.c
+ src/selftest_ujenc.c
+ src/selftest_xprintf.c
+ src/selftest_xq.c
+ src/selftests.c
+ src/sx1301v2conf.c
+ src/sx130xconf.c
+ src/sys.c
+ src/sys.h
+ src/tc.c
+ src/timesync.c
+ src/tls.c
+ src/uj.c
+ src/web.c
+ src/xq.c
+ src-linux/cmdfifo.c
+ src-linux/commands.c
+ src-linux/gps.c
+ src-linux/leds.c
+ src-linux/ral_master.c
+ src-linux/ral_slave.c
+ src-linux/rmtsh.c
+ src-linux/sys_linux.c
+ src-linux/sys_log.c
+ src-linux/web_linux.c)
+
+add_library(s2core ${basicstation_SOURCE_FILES})
+target_include_directories(s2core PRIVATE ${SX1302_HAL_INCLUDE_DIR})
+target_include_directories(s2core PRIVATE ${MBEDTLS_INCLUDE_DIR})
+target_link_libraries(s2core ${SX1302_HAL_LIBRARY} ${TINYMT32_LIBRARY} m)
+target_link_libraries(s2core ${MBEDTLS_LIBRARY})
+target_link_libraries(s2core ${MBEDCRYPTO_LIBRARY})
+target_link_libraries(s2core ${MBEDX509_LIBRARY})
+
+add_executable(station src-linux/station_main.c)
+
+target_link_libraries(station s2core)
+
+install(TARGETS station RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR})