├── VERSION ├── util_ack ├── obj │ └── .gitkeep ├── Makefile ├── readme.md └── src │ └── util_ack.c ├── util_sink ├── obj │ └── .gitkeep ├── Makefile ├── readme.md └── src │ └── util_sink.c ├── basic_pkt_fwd ├── obj │ └── .gitkeep ├── local_conf.json ├── Makefile ├── inc │ ├── base64.h │ └── parson.h ├── global_conf.json ├── readme.md └── src │ └── base64.c ├── beacon_pkt_fwd ├── obj │ └── .gitkeep ├── local_conf.json ├── Makefile ├── inc │ ├── base64.h │ └── parson.h ├── global_conf.json ├── readme.md └── src │ └── base64.c ├── gps_pkt_fwd ├── obj │ └── .gitkeep ├── local_conf.json ├── Makefile ├── inc │ ├── base64.h │ └── parson.h ├── global_conf.json ├── readme.md └── src │ └── base64.c ├── poly_pkt_fwd ├── obj │ └── .gitkeep ├── local_conf.json ├── inc │ ├── poly_pkt_fwd.h │ ├── base64.h │ ├── ghost.h │ ├── monitor.h │ └── parson.h ├── Makefile ├── global_conf_multitech-us915.json ├── global_conf.json ├── global_conf_multitech-eu868.json ├── global_conf_multitech-eu868-ttn.json ├── readme.md └── src │ └── base64.c ├── util_tx_test ├── obj │ └── .gitkeep ├── Makefile ├── inc │ └── base64.h ├── readme.md └── src │ └── base64.c ├── readme.md ├── multitech-bin ├── poly-packet-forwarder_2.1-r1_arm926ejste.ipk ├── poly-packet-forwarder_2.1-r2_arm926ejste.ipk └── poly-packet-forwarder_2.1-r3_arm926ejste.ipk ├── .gitignore ├── Makefile ├── reset_pkt_fwd.sh └── LICENSE /VERSION: -------------------------------------------------------------------------------- 1 | 2.1.0 2 | -------------------------------------------------------------------------------- /util_ack/obj/.gitkeep: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /util_sink/obj/.gitkeep: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /basic_pkt_fwd/obj/.gitkeep: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /beacon_pkt_fwd/obj/.gitkeep: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /gps_pkt_fwd/obj/.gitkeep: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /poly_pkt_fwd/obj/.gitkeep: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /util_tx_test/obj/.gitkeep: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /readme.md: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kersing/packet_forwarder-OLD/HEAD/readme.md -------------------------------------------------------------------------------- /multitech-bin/poly-packet-forwarder_2.1-r1_arm926ejste.ipk: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kersing/packet_forwarder-OLD/HEAD/multitech-bin/poly-packet-forwarder_2.1-r1_arm926ejste.ipk -------------------------------------------------------------------------------- /multitech-bin/poly-packet-forwarder_2.1-r2_arm926ejste.ipk: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kersing/packet_forwarder-OLD/HEAD/multitech-bin/poly-packet-forwarder_2.1-r2_arm926ejste.ipk -------------------------------------------------------------------------------- /multitech-bin/poly-packet-forwarder_2.1-r3_arm926ejste.ipk: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kersing/packet_forwarder-OLD/HEAD/multitech-bin/poly-packet-forwarder_2.1-r3_arm926ejste.ipk -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | *.a 2 | *.o 3 | *.swp 4 | *.bak 5 | 6 | .cproject 7 | .project 8 | .settings/ 9 | 10 | basic_pkt_fwd/basic_pkt_fwd 11 | gps_pkt_fwd/gps_pkt_fwd 12 | beacon_pkt_fwd/beacon_pkt_fwd 13 | poly_pkt_fwd/poly_pkt_fwd -------------------------------------------------------------------------------- /basic_pkt_fwd/local_conf.json: -------------------------------------------------------------------------------- 1 | { 2 | /* Put there parameters that are different for each gateway (eg. pointing one gateway to a test server while the others stay in production) */ 3 | /* Settings defined in global_conf will be overwritten by those in local_conf */ 4 | "gateway_conf": { 5 | "gateway_ID": "AA555A0000000101" /* you must pick a unique 64b number for each gateway (represented by an hex string) */ 6 | } 7 | } 8 | -------------------------------------------------------------------------------- /beacon_pkt_fwd/local_conf.json: -------------------------------------------------------------------------------- 1 | { 2 | /* Put there parameters that are different for each gateway (eg. pointing one gateway to a test server while the others stay in production) */ 3 | /* Settings defined in global_conf will be overwritten by those in local_conf */ 4 | "gateway_conf": { 5 | "gateway_ID": "AA555A0000000101" /* you must pick a unique 64b number for each gateway (represented by an hex string) */ 6 | } 7 | } 8 | -------------------------------------------------------------------------------- /gps_pkt_fwd/local_conf.json: -------------------------------------------------------------------------------- 1 | { 2 | /* Put there parameters that are different for each gateway (eg. pointing one gateway to a test server while the others stay in production) */ 3 | /* Settings defined in global_conf will be overwritten by those in local_conf */ 4 | "gateway_conf": { 5 | "gateway_ID": "AA555A0000000101" /* you must pick a unique 64b number for each gateway (represented by an hex string) */ 6 | } 7 | } 8 | -------------------------------------------------------------------------------- /util_ack/Makefile: -------------------------------------------------------------------------------- 1 | ### Application-specific constants 2 | 3 | APP_NAME := util_ack 4 | 5 | ### Constant symbols 6 | 7 | CC := $(CROSS_COMPILE)gcc 8 | AR := $(CROSS_COMPILE)ar 9 | 10 | CFLAGS := -O2 -Wall -Wextra -std=c99 -Iinc -I. 11 | 12 | ### General build targets 13 | 14 | all: $(APP_NAME) 15 | 16 | clean: 17 | rm -f obj/*.o 18 | rm -f $(APP_NAME) 19 | 20 | ### Main program compilation and assembly 21 | 22 | obj/$(APP_NAME).o: src/$(APP_NAME).c 23 | $(CC) -c $(CFLAGS) $< -o $@ 24 | 25 | $(APP_NAME): obj/$(APP_NAME).o 26 | $(CC) $< -o $@ 27 | 28 | ### EOF -------------------------------------------------------------------------------- /util_sink/Makefile: -------------------------------------------------------------------------------- 1 | ### Application-specific constants 2 | 3 | APP_NAME := util_sink 4 | 5 | ### Constant symbols 6 | 7 | CC := $(CROSS_COMPILE)gcc 8 | AR := $(CROSS_COMPILE)ar 9 | 10 | CFLAGS := -O2 -Wall -Wextra -std=c99 -Iinc -I. 11 | 12 | ### General build targets 13 | 14 | all: $(APP_NAME) 15 | 16 | clean: 17 | rm -f obj/*.o 18 | rm -f $(APP_NAME) 19 | 20 | ### Main program compilation and assembly 21 | 22 | obj/$(APP_NAME).o: src/$(APP_NAME).c 23 | $(CC) -c $(CFLAGS) $< -o $@ 24 | 25 | $(APP_NAME): obj/$(APP_NAME).o 26 | $(CC) $< -o $@ 27 | 28 | ### EOF -------------------------------------------------------------------------------- /Makefile: -------------------------------------------------------------------------------- 1 | ### Environment constants 2 | 3 | LGW_PATH ?= ../../lora_gateway/libloragw 4 | ARCH ?= 5 | CROSS_COMPILE ?= 6 | export 7 | 8 | ### general build targets 9 | 10 | all: 11 | $(MAKE) all -e -C basic_pkt_fwd 12 | $(MAKE) all -e -C gps_pkt_fwd 13 | $(MAKE) all -e -C beacon_pkt_fwd 14 | $(MAKE) all -e -C poly_pkt_fwd 15 | $(MAKE) all -e -C util_ack 16 | $(MAKE) all -e -C util_sink 17 | $(MAKE) all -e -C util_tx_test 18 | 19 | clean: 20 | $(MAKE) clean -e -C basic_pkt_fwd 21 | $(MAKE) clean -e -C gps_pkt_fwd 22 | $(MAKE) clean -e -C beacon_pkt_fwd 23 | $(MAKE) clean -e -C poly_pkt_fwd 24 | $(MAKE) clean -e -C util_ack 25 | $(MAKE) clean -e -C util_sink 26 | $(MAKE) clean -e -C util_tx_test 27 | 28 | ### EOF 29 | -------------------------------------------------------------------------------- /util_tx_test/Makefile: -------------------------------------------------------------------------------- 1 | ### Application-specific constants 2 | 3 | APP_NAME := util_tx_test 4 | 5 | ### Constant symbols 6 | 7 | CC := $(CROSS_COMPILE)gcc 8 | AR := $(CROSS_COMPILE)ar 9 | 10 | CFLAGS := -O2 -Wall -Wextra -std=c99 -Iinc -I. 11 | 12 | ### General build targets 13 | 14 | all: $(APP_NAME) 15 | 16 | clean: 17 | rm -f obj/*.o 18 | rm -f $(APP_NAME) 19 | 20 | ### Sub-modules compilation 21 | 22 | obj/base64.o: src/base64.c inc/base64.h 23 | $(CC) -c $(CFLAGS) $< -o $@ 24 | 25 | ### Main program compilation and assembly 26 | 27 | obj/$(APP_NAME).o: src/$(APP_NAME).c inc/base64.h 28 | $(CC) -c $(CFLAGS) $< -o $@ 29 | 30 | $(APP_NAME): obj/$(APP_NAME).o obj/base64.o 31 | $(CC) $< obj/base64.o -o $@ 32 | 33 | ### EOF -------------------------------------------------------------------------------- /poly_pkt_fwd/local_conf.json: -------------------------------------------------------------------------------- 1 | { 2 | /* Put there parameters that are different for each gateway (eg. pointing one gateway to a test server while the others stay in production) */ 3 | /* Settings defined in global_conf will be overwritten by those in local_conf */ 4 | "gateway_conf": { 5 | /* you must pick a unique 64b number for each gateway (represented by an hex string) */ 6 | "gateway_ID": "AA555A000004BABA", 7 | /* Email of gateway operator, max 40 chars*/ 8 | "contact_email": "operator@gateway.tst", 9 | /* Public description of this device, max 64 chars */ 10 | "description": "Update me", 11 | /* Enter VALID GPS coordinates below before enabling fake GPS */ 12 | "fake_gps": false, 13 | "ref_latitude": 10, 14 | "ref_longitude": 20, 15 | "ref_altitude": -1 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /poly_pkt_fwd/inc/poly_pkt_fwd.h: -------------------------------------------------------------------------------- 1 | /* 2 | * poly_pkt_fwd.h 3 | * 4 | * Created on: Aug 28, 2015 5 | * Author: ruud 6 | */ 7 | 8 | #ifndef _POLY_PKT_FWD_H_ 9 | #define _POLY_PKT_FWD_H_ 10 | 11 | #ifndef MSG 12 | //#define MSG(args...) printf(args) /* message that is destined to the user */ 13 | #define MSG(args...) { printf(args); fflush(stdout); } /* message that is destined to the user */ 14 | #endif 15 | 16 | 17 | /* -------------------------------------------------------------------------- */ 18 | /* --- MAC OSX Extensions -------------------------------------------------- */ 19 | 20 | struct timespec; 21 | 22 | #ifdef __MACH__ 23 | #define CLOCK_REALTIME 0 24 | #define CLOCK_MONOTONIC 0 25 | int clock_gettime(int clk_id, struct timespec* t); 26 | #endif 27 | 28 | double difftimespec(struct timespec end, struct timespec beginning); 29 | 30 | #endif /* _POLY_PKT_FWD_H_ */ 31 | -------------------------------------------------------------------------------- /basic_pkt_fwd/Makefile: -------------------------------------------------------------------------------- 1 | ### Application-specific constants 2 | 3 | APP_NAME := basic_pkt_fwd 4 | 5 | ### Environment constants 6 | 7 | LGW_PATH ?= ../../lora_gateway/libloragw 8 | ARCH ?= 9 | CROSS_COMPILE ?= 10 | 11 | ### External constant definitions 12 | # must get library build option to know if mpsse must be linked or not 13 | 14 | include $(LGW_PATH)/library.cfg 15 | RELEASE_VERSION := `cat ../VERSION` 16 | 17 | ### Constant symbols 18 | 19 | CC := $(CROSS_COMPILE)gcc 20 | AR := $(CROSS_COMPILE)ar 21 | 22 | CFLAGS := -O2 -Wall -Wextra -std=c99 -Iinc -I. 23 | VFLAG := -D VERSION_STRING="\"$(RELEASE_VERSION)\"" 24 | 25 | ### Constants for Lora concentrator HAL library 26 | # List the library sub-modules that are used by the application 27 | 28 | LGW_INC = 29 | ifneq ($(wildcard $(LGW_PATH)/inc/config.h),) 30 | # only for HAL version 1.3 and beyond 31 | LGW_INC += $(LGW_PATH)/inc/config.h 32 | endif 33 | LGW_INC += $(LGW_PATH)/inc/loragw_hal.h 34 | 35 | ### Linking options 36 | 37 | ifeq ($(CFG_SPI),native) 38 | LIBS := -lloragw -lrt -lpthread 39 | else ifeq ($(CFG_SPI),ftdi) 40 | LIBS := -lloragw -lrt -lpthread -lmpsse 41 | else ifeq ($(CFG_SPI),mac) 42 | $(error [error] Option mac not supported for SPI here) 43 | else 44 | # keep compatibility with SX1301 HAL version 1.2.x and bellow 45 | ifeq ($(LGW_PHY),native) 46 | LIBS := -lloragw -lrt -lpthread 47 | else ifeq ($(LGW_PHY),ftdi) 48 | LIBS := -lloragw -lrt -lpthread -lmpsse 49 | else ifeq ($(LGW_PHY),mac) 50 | $(error [error] Option mac not supported for SPI here) 51 | else 52 | $(error [error] Can't find configuration for SPI phy) 53 | endif 54 | endif 55 | 56 | ### General build targets 57 | 58 | all: $(APP_NAME) 59 | 60 | clean: 61 | rm -f obj/*.o 62 | rm -f $(APP_NAME) 63 | 64 | ### Sub-modules compilation 65 | 66 | obj/base64.o: src/base64.c inc/base64.h 67 | $(CC) -c $(CFLAGS) $< -o $@ 68 | 69 | obj/parson.o: src/parson.c inc/parson.h 70 | $(CC) -c $(CFLAGS) $< -o $@ 71 | 72 | ### Main program compilation and assembly 73 | 74 | obj/$(APP_NAME).o: src/$(APP_NAME).c $(LGW_INC) inc/parson.h inc/base64.h 75 | $(CC) -c $(CFLAGS) $(VFLAG) -I$(LGW_PATH)/inc $< -o $@ 76 | 77 | $(APP_NAME): obj/$(APP_NAME).o $(LGW_PATH)/libloragw.a obj/parson.o obj/base64.o 78 | $(CC) -L$(LGW_PATH) $< obj/parson.o obj/base64.o -o $@ $(LIBS) 79 | 80 | ### EOF 81 | -------------------------------------------------------------------------------- /gps_pkt_fwd/Makefile: -------------------------------------------------------------------------------- 1 | ### Application-specific constants 2 | 3 | APP_NAME := gps_pkt_fwd 4 | 5 | ### Environment constants 6 | 7 | LGW_PATH ?= ../../lora_gateway/libloragw 8 | ARCH ?= 9 | CROSS_COMPILE ?= 10 | 11 | ### External constant definitions 12 | # must get library build option to know if mpsse must be linked or not 13 | 14 | include $(LGW_PATH)/library.cfg 15 | RELEASE_VERSION := `cat ../VERSION` 16 | 17 | ### Constant symbols 18 | 19 | CC := $(CROSS_COMPILE)gcc 20 | AR := $(CROSS_COMPILE)ar 21 | 22 | CFLAGS := -O2 -Wall -Wextra -std=c99 -Iinc -I. 23 | VFLAG := -D VERSION_STRING="\"$(RELEASE_VERSION)\"" 24 | 25 | ### Constants for Lora concentrator HAL library 26 | # List the library sub-modules that are used by the application 27 | 28 | LGW_INC = 29 | ifneq ($(wildcard $(LGW_PATH)/inc/config.h),) 30 | # only for HAL version 1.3 and beyond 31 | LGW_INC += $(LGW_PATH)/inc/config.h 32 | endif 33 | LGW_INC += $(LGW_PATH)/inc/loragw_hal.h 34 | LGW_INC += $(LGW_PATH)/inc/loragw_gps.h 35 | 36 | ### Linking options 37 | 38 | ifeq ($(CFG_SPI),native) 39 | LIBS := -lloragw -lrt -lpthread 40 | else ifeq ($(CFG_SPI),ftdi) 41 | LIBS := -lloragw -lrt -lpthread -lmpsse 42 | else ifeq ($(CFG_SPI),mac) 43 | $(error [error] Option mac not supported for SPI here) 44 | else 45 | # keep compatibility with SX1301 HAL version 1.2.x and bellow 46 | ifeq ($(LGW_PHY),native) 47 | LIBS := -lloragw -lrt -lpthread 48 | else ifeq ($(LGW_PHY),ftdi) 49 | LIBS := -lloragw -lrt -lpthread -lmpsse 50 | else ifeq ($(LGW_PHY),mac) 51 | $(error [error] Option mac not supported for SPI here) 52 | else 53 | $(error [error] Can't find configuration for SPI phy) 54 | endif 55 | endif 56 | 57 | ### General build targets 58 | 59 | all: $(APP_NAME) 60 | 61 | clean: 62 | rm -f obj/*.o 63 | rm -f $(APP_NAME) 64 | 65 | ### Sub-modules compilation 66 | 67 | obj/base64.o: src/base64.c inc/base64.h 68 | $(CC) -c $(CFLAGS) $< -o $@ 69 | 70 | obj/parson.o: src/parson.c inc/parson.h 71 | $(CC) -c $(CFLAGS) $< -o $@ 72 | 73 | ### Main program compilation and assembly 74 | 75 | obj/$(APP_NAME).o: src/$(APP_NAME).c $(LGW_INC) inc/parson.h inc/base64.h 76 | $(CC) -c $(CFLAGS) $(VFLAG) -I$(LGW_PATH)/inc $< -o $@ 77 | 78 | $(APP_NAME): obj/$(APP_NAME).o $(LGW_PATH)/libloragw.a obj/parson.o obj/base64.o 79 | $(CC) -L$(LGW_PATH) $< obj/parson.o obj/base64.o -o $@ $(LIBS) 80 | 81 | ### EOF 82 | -------------------------------------------------------------------------------- /beacon_pkt_fwd/Makefile: -------------------------------------------------------------------------------- 1 | ### Application-specific constants 2 | 3 | APP_NAME := beacon_pkt_fwd 4 | 5 | ### Environment constants 6 | 7 | LGW_PATH ?= ../../lora_gateway/libloragw 8 | ARCH ?= 9 | CROSS_COMPILE ?= 10 | 11 | ### External constant definitions 12 | # must get library build option to know if mpsse must be linked or not 13 | 14 | include $(LGW_PATH)/library.cfg 15 | RELEASE_VERSION := `cat ../VERSION` 16 | 17 | ### Constant symbols 18 | 19 | CC := $(CROSS_COMPILE)gcc 20 | AR := $(CROSS_COMPILE)ar 21 | 22 | CFLAGS := -O2 -Wall -Wextra -std=c99 -Iinc -I. 23 | VFLAG := -D VERSION_STRING="\"$(RELEASE_VERSION)\"" 24 | 25 | ### Constants for Lora concentrator HAL library 26 | # List the library sub-modules that are used by the application 27 | 28 | LGW_INC = 29 | ifneq ($(wildcard $(LGW_PATH)/inc/config.h),) 30 | # only for HAL version 1.3 and beyond 31 | LGW_INC += $(LGW_PATH)/inc/config.h 32 | endif 33 | LGW_INC += $(LGW_PATH)/inc/loragw_hal.h 34 | LGW_INC += $(LGW_PATH)/inc/loragw_gps.h 35 | 36 | ### Linking options 37 | 38 | ifeq ($(CFG_SPI),native) 39 | LIBS := -lloragw -lrt -lpthread 40 | else ifeq ($(CFG_SPI),ftdi) 41 | LIBS := -lloragw -lrt -lpthread -lmpsse 42 | else ifeq ($(CFG_SPI),mac) 43 | $(error [error] Option mac not supported for SPI here) 44 | else 45 | # keep compatibility with SX1301 HAL version 1.2.x and bellow 46 | ifeq ($(LGW_PHY),native) 47 | LIBS := -lloragw -lrt -lpthread 48 | else ifeq ($(LGW_PHY),ftdi) 49 | LIBS := -lloragw -lrt -lpthread -lmpsse 50 | else ifeq ($(LGW_PHY),mac) 51 | $(error [error] Option mac not supported for SPI here) 52 | else 53 | $(error [error] Can't find configuration for SPI phy) 54 | endif 55 | endif 56 | 57 | ### General build targets 58 | 59 | all: $(APP_NAME) 60 | 61 | clean: 62 | rm -f obj/*.o 63 | rm -f $(APP_NAME) 64 | 65 | ### Sub-modules compilation 66 | 67 | obj/base64.o: src/base64.c inc/base64.h 68 | $(CC) -c $(CFLAGS) $< -o $@ 69 | 70 | obj/parson.o: src/parson.c inc/parson.h 71 | $(CC) -c $(CFLAGS) $< -o $@ 72 | 73 | ### Main program compilation and assembly 74 | 75 | obj/$(APP_NAME).o: src/$(APP_NAME).c $(LGW_INC) inc/parson.h inc/base64.h 76 | $(CC) -c $(CFLAGS) $(VFLAG) -I$(LGW_PATH)/inc $< -o $@ 77 | 78 | $(APP_NAME): obj/$(APP_NAME).o $(LGW_PATH)/libloragw.a obj/parson.o obj/base64.o 79 | $(CC) -L$(LGW_PATH) $< obj/parson.o obj/base64.o -o $@ $(LIBS) 80 | 81 | ### EOF 82 | -------------------------------------------------------------------------------- /basic_pkt_fwd/inc/base64.h: -------------------------------------------------------------------------------- 1 | /* 2 | / _____) _ | | 3 | ( (____ _____ ____ _| |_ _____ ____| |__ 4 | \____ \| ___ | (_ _) ___ |/ ___) _ \ 5 | _____) ) ____| | | || |_| ____( (___| | | | 6 | (______/|_____)_|_|_| \__)_____)\____)_| |_| 7 | (C)2013 Semtech-Cycleo 8 | 9 | Description: 10 | Base64 encoding & decoding library 11 | 12 | License: Revised BSD License, see LICENSE.TXT file include in the project 13 | Maintainer: Sylvain Miermont 14 | */ 15 | 16 | 17 | #ifndef _BASE64_H 18 | #define _BASE64_H 19 | 20 | /* -------------------------------------------------------------------------- */ 21 | /* --- DEPENDANCIES --------------------------------------------------------- */ 22 | 23 | #include /* C99 types */ 24 | 25 | /* -------------------------------------------------------------------------- */ 26 | /* --- PUBLIC FUNCTIONS PROTOTYPES ------------------------------------------ */ 27 | 28 | /** 29 | @brief Encode binary data in Base64 string (no padding) 30 | @param in pointer to a table of binary data 31 | @param size number of bytes to be encoded to base64 32 | @param out pointer to a string where the function will output encoded data 33 | @param max_len max length of the out string (including null char) 34 | @return >=0 length of the resulting string (w/o null char), -1 for error 35 | */ 36 | int bin_to_b64_nopad(const uint8_t * in, int size, char * out, int max_len); 37 | 38 | /** 39 | @brief Decode Base64 string to binary data (no padding) 40 | @param in string containing only base64 valid characters 41 | @param size number of characters to be decoded from base64 (w/o null char) 42 | @param out pointer to a data buffer where the function will output decoded data 43 | @param out_max_len usable size of the output data buffer 44 | @return >=0 number of bytes written to the data buffer, -1 for error 45 | */ 46 | int b64_to_bin_nopad(const char * in, int size, uint8_t * out, int max_len); 47 | 48 | /* === derivative functions === */ 49 | 50 | /** 51 | @brief Encode binary data in Base64 string (with added padding) 52 | */ 53 | int bin_to_b64(const uint8_t * in, int size, char * out, int max_len); 54 | 55 | /** 56 | @brief Decode Base64 string to binary data (remove padding if necessary) 57 | */ 58 | int b64_to_bin(const char * in, int size, uint8_t * out, int max_len); 59 | 60 | #endif 61 | 62 | /* --- EOF ------------------------------------------------------------------ */ 63 | -------------------------------------------------------------------------------- /gps_pkt_fwd/inc/base64.h: -------------------------------------------------------------------------------- 1 | /* 2 | / _____) _ | | 3 | ( (____ _____ ____ _| |_ _____ ____| |__ 4 | \____ \| ___ | (_ _) ___ |/ ___) _ \ 5 | _____) ) ____| | | || |_| ____( (___| | | | 6 | (______/|_____)_|_|_| \__)_____)\____)_| |_| 7 | (C)2013 Semtech-Cycleo 8 | 9 | Description: 10 | Base64 encoding & decoding library 11 | 12 | License: Revised BSD License, see LICENSE.TXT file include in the project 13 | Maintainer: Sylvain Miermont 14 | */ 15 | 16 | 17 | #ifndef _BASE64_H 18 | #define _BASE64_H 19 | 20 | /* -------------------------------------------------------------------------- */ 21 | /* --- DEPENDANCIES --------------------------------------------------------- */ 22 | 23 | #include /* C99 types */ 24 | 25 | /* -------------------------------------------------------------------------- */ 26 | /* --- PUBLIC FUNCTIONS PROTOTYPES ------------------------------------------ */ 27 | 28 | /** 29 | @brief Encode binary data in Base64 string (no padding) 30 | @param in pointer to a table of binary data 31 | @param size number of bytes to be encoded to base64 32 | @param out pointer to a string where the function will output encoded data 33 | @param max_len max length of the out string (including null char) 34 | @return >=0 length of the resulting string (w/o null char), -1 for error 35 | */ 36 | int bin_to_b64_nopad(const uint8_t * in, int size, char * out, int max_len); 37 | 38 | /** 39 | @brief Decode Base64 string to binary data (no padding) 40 | @param in string containing only base64 valid characters 41 | @param size number of characters to be decoded from base64 (w/o null char) 42 | @param out pointer to a data buffer where the function will output decoded data 43 | @param out_max_len usable size of the output data buffer 44 | @return >=0 number of bytes written to the data buffer, -1 for error 45 | */ 46 | int b64_to_bin_nopad(const char * in, int size, uint8_t * out, int max_len); 47 | 48 | /* === derivative functions === */ 49 | 50 | /** 51 | @brief Encode binary data in Base64 string (with added padding) 52 | */ 53 | int bin_to_b64(const uint8_t * in, int size, char * out, int max_len); 54 | 55 | /** 56 | @brief Decode Base64 string to binary data (remove padding if necessary) 57 | */ 58 | int b64_to_bin(const char * in, int size, uint8_t * out, int max_len); 59 | 60 | #endif 61 | 62 | /* --- EOF ------------------------------------------------------------------ */ 63 | -------------------------------------------------------------------------------- /poly_pkt_fwd/inc/base64.h: -------------------------------------------------------------------------------- 1 | /* 2 | / _____) _ | | 3 | ( (____ _____ ____ _| |_ _____ ____| |__ 4 | \____ \| ___ | (_ _) ___ |/ ___) _ \ 5 | _____) ) ____| | | || |_| ____( (___| | | | 6 | (______/|_____)_|_|_| \__)_____)\____)_| |_| 7 | (C)2013 Semtech-Cycleo 8 | 9 | Description: 10 | Base64 encoding & decoding library 11 | 12 | License: Revised BSD License, see LICENSE.TXT file include in the project 13 | Maintainer: Sylvain Miermont 14 | */ 15 | 16 | 17 | #ifndef _BASE64_H 18 | #define _BASE64_H 19 | 20 | /* -------------------------------------------------------------------------- */ 21 | /* --- DEPENDANCIES --------------------------------------------------------- */ 22 | 23 | #include /* C99 types */ 24 | 25 | /* -------------------------------------------------------------------------- */ 26 | /* --- PUBLIC FUNCTIONS PROTOTYPES ------------------------------------------ */ 27 | 28 | /** 29 | @brief Encode binary data in Base64 string (no padding) 30 | @param in pointer to a table of binary data 31 | @param size number of bytes to be encoded to base64 32 | @param out pointer to a string where the function will output encoded data 33 | @param max_len max length of the out string (including null char) 34 | @return >=0 length of the resulting string (w/o null char), -1 for error 35 | */ 36 | int bin_to_b64_nopad(const uint8_t * in, int size, char * out, int max_len); 37 | 38 | /** 39 | @brief Decode Base64 string to binary data (no padding) 40 | @param in string containing only base64 valid characters 41 | @param size number of characters to be decoded from base64 (w/o null char) 42 | @param out pointer to a data buffer where the function will output decoded data 43 | @param out_max_len usable size of the output data buffer 44 | @return >=0 number of bytes written to the data buffer, -1 for error 45 | */ 46 | int b64_to_bin_nopad(const char * in, int size, uint8_t * out, int max_len); 47 | 48 | /* === derivative functions === */ 49 | 50 | /** 51 | @brief Encode binary data in Base64 string (with added padding) 52 | */ 53 | int bin_to_b64(const uint8_t * in, int size, char * out, int max_len); 54 | 55 | /** 56 | @brief Decode Base64 string to binary data (remove padding if necessary) 57 | */ 58 | int b64_to_bin(const char * in, int size, uint8_t * out, int max_len); 59 | 60 | #endif 61 | 62 | /* --- EOF ------------------------------------------------------------------ */ 63 | -------------------------------------------------------------------------------- /util_tx_test/inc/base64.h: -------------------------------------------------------------------------------- 1 | /* 2 | / _____) _ | | 3 | ( (____ _____ ____ _| |_ _____ ____| |__ 4 | \____ \| ___ | (_ _) ___ |/ ___) _ \ 5 | _____) ) ____| | | || |_| ____( (___| | | | 6 | (______/|_____)_|_|_| \__)_____)\____)_| |_| 7 | (C)2013 Semtech-Cycleo 8 | 9 | Description: 10 | Base64 encoding & decoding library 11 | 12 | License: Revised BSD License, see LICENSE.TXT file include in the project 13 | Maintainer: Sylvain Miermont 14 | */ 15 | 16 | 17 | #ifndef _BASE64_H 18 | #define _BASE64_H 19 | 20 | /* -------------------------------------------------------------------------- */ 21 | /* --- DEPENDANCIES --------------------------------------------------------- */ 22 | 23 | #include /* C99 types */ 24 | 25 | /* -------------------------------------------------------------------------- */ 26 | /* --- PUBLIC FUNCTIONS PROTOTYPES ------------------------------------------ */ 27 | 28 | /** 29 | @brief Encode binary data in Base64 string (no padding) 30 | @param in pointer to a table of binary data 31 | @param size number of bytes to be encoded to base64 32 | @param out pointer to a string where the function will output encoded data 33 | @param max_len max length of the out string (including null char) 34 | @return >=0 length of the resulting string (w/o null char), -1 for error 35 | */ 36 | int bin_to_b64_nopad(const uint8_t * in, int size, char * out, int max_len); 37 | 38 | /** 39 | @brief Decode Base64 string to binary data (no padding) 40 | @param in string containing only base64 valid characters 41 | @param size number of characters to be decoded from base64 (w/o null char) 42 | @param out pointer to a data buffer where the function will output decoded data 43 | @param out_max_len usable size of the output data buffer 44 | @return >=0 number of bytes written to the data buffer, -1 for error 45 | */ 46 | int b64_to_bin_nopad(const char * in, int size, uint8_t * out, int max_len); 47 | 48 | /* === derivative functions === */ 49 | 50 | /** 51 | @brief Encode binary data in Base64 string (with added padding) 52 | */ 53 | int bin_to_b64(const uint8_t * in, int size, char * out, int max_len); 54 | 55 | /** 56 | @brief Decode Base64 string to binary data (remove padding if necessary) 57 | */ 58 | int b64_to_bin(const char * in, int size, uint8_t * out, int max_len); 59 | 60 | #endif 61 | 62 | /* --- EOF ------------------------------------------------------------------ */ 63 | -------------------------------------------------------------------------------- /beacon_pkt_fwd/inc/base64.h: -------------------------------------------------------------------------------- 1 | /* 2 | / _____) _ | | 3 | ( (____ _____ ____ _| |_ _____ ____| |__ 4 | \____ \| ___ | (_ _) ___ |/ ___) _ \ 5 | _____) ) ____| | | || |_| ____( (___| | | | 6 | (______/|_____)_|_|_| \__)_____)\____)_| |_| 7 | (C)2013 Semtech-Cycleo 8 | 9 | Description: 10 | Base64 encoding & decoding library 11 | 12 | License: Revised BSD License, see LICENSE.TXT file include in the project 13 | Maintainer: Sylvain Miermont 14 | */ 15 | 16 | 17 | #ifndef _BASE64_H 18 | #define _BASE64_H 19 | 20 | /* -------------------------------------------------------------------------- */ 21 | /* --- DEPENDANCIES --------------------------------------------------------- */ 22 | 23 | #include /* C99 types */ 24 | 25 | /* -------------------------------------------------------------------------- */ 26 | /* --- PUBLIC FUNCTIONS PROTOTYPES ------------------------------------------ */ 27 | 28 | /** 29 | @brief Encode binary data in Base64 string (no padding) 30 | @param in pointer to a table of binary data 31 | @param size number of bytes to be encoded to base64 32 | @param out pointer to a string where the function will output encoded data 33 | @param max_len max length of the out string (including null char) 34 | @return >=0 length of the resulting string (w/o null char), -1 for error 35 | */ 36 | int bin_to_b64_nopad(const uint8_t * in, int size, char * out, int max_len); 37 | 38 | /** 39 | @brief Decode Base64 string to binary data (no padding) 40 | @param in string containing only base64 valid characters 41 | @param size number of characters to be decoded from base64 (w/o null char) 42 | @param out pointer to a data buffer where the function will output decoded data 43 | @param out_max_len usable size of the output data buffer 44 | @return >=0 number of bytes written to the data buffer, -1 for error 45 | */ 46 | int b64_to_bin_nopad(const char * in, int size, uint8_t * out, int max_len); 47 | 48 | /* === derivative functions === */ 49 | 50 | /** 51 | @brief Encode binary data in Base64 string (with added padding) 52 | */ 53 | int bin_to_b64(const uint8_t * in, int size, char * out, int max_len); 54 | 55 | /** 56 | @brief Decode Base64 string to binary data (remove padding if necessary) 57 | */ 58 | int b64_to_bin(const char * in, int size, uint8_t * out, int max_len); 59 | 60 | #endif 61 | 62 | /* --- EOF ------------------------------------------------------------------ */ 63 | -------------------------------------------------------------------------------- /poly_pkt_fwd/inc/ghost.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Extension of Semtech Semtech-Cycleo Packet Forwarder. 3 | * (C) 2015 Beta Research BV 4 | * 5 | * Description: Virtualization of nodes. 6 | * 7 | * License: Revised BSD License, see LICENSE.TXT file include in the project 8 | * Maintainer: Ruud Vlaming 9 | */ 10 | 11 | #ifndef _GHOST_H_ 12 | #define _GHOST_H_ 13 | 14 | #include "loragw_hal.h" 15 | #include "poly_pkt_fwd.h" 16 | 17 | /* -------------------------------------------------------------------------- */ 18 | /* --- PRIVATE CONSTANTS AND FIELDS ------------------------------------------ */ 19 | 20 | 21 | /* Note that the ghost receive buffer must be large enough to store the 22 | * burst of data coming in just after the wait period in the main cycle 23 | * has commenced. In reality this wait state is one of the limiting factors 24 | * of the capacity. I am unaware of the number of packates the concentrator 25 | * can store, but my suspicion is 8. In this code the wait state is 10ms, 26 | * so this limits the maximum throughput in reality on: 8/0.01 = 800 packets/sec. 27 | * Although in burst mode it may be higher, since the wait time is not the 28 | * limiting factor at that moment. 29 | */ 30 | 31 | /* The total number of buffer bytes equals: (GHST_RX_BUFFSIZE + GHST_TX_BUFFSIZE) * GHST_NM_RCV */ 32 | #define GHST_MIN_PACKETSIZE 38 /* Minimal viable packet size. */ 33 | #define GHST_RX_BUFFSIZE 320 /* Size of buffer held for receiving packets */ 34 | #define GHST_TX_BUFFSIZE 320 /* Size of buffer held for receiving packets */ 35 | #define GHST_NM_RCV 12 /* max number of packets to be stored in receive mode, do not exceed 255 */ 36 | #define NODE_CALL_SECS 60 /* Minimum time between calls for ghost nodes, don't hammer de node server. */ 37 | 38 | /* -------------------------------------------------------------------------- */ 39 | /* --- PUBLIC FUNCTIONS PROTOTYPES ------------------------------------------ */ 40 | 41 | 42 | 43 | /* Call this to start/stop the server that communicates with the ghost node server. */ 44 | void ghost_start(const char * ghost_addr, const char * ghost_port); 45 | void ghost_stop(void); 46 | 47 | 48 | /* Call this to pull data from the receive buffer for ghost nodes.. */ 49 | int ghost_get(int max_pkt, struct lgw_pkt_rx_s *pkt_data); 50 | 51 | /* Call this to push data from the server to the receiving ghost node. 52 | * Data is send immediately. */ 53 | int ghost_put(); 54 | 55 | #endif 56 | 57 | /* --- EOF ------------------------------------------------------------------ */ 58 | -------------------------------------------------------------------------------- /util_sink/readme.md: -------------------------------------------------------------------------------- 1 | / _____) _ | | 2 | ( (____ _____ ____ _| |_ _____ ____| |__ 3 | \____ \| ___ | (_ _) ___ |/ ___) _ \ 4 | _____) ) ____| | | || |_| ____( (___| | | | 5 | (______/|_____)_|_|_| \__)_____)\____)_| |_| 6 | (C)2013 Semtech-Cycleo 7 | 8 | Utility: packet sink 9 | ===================== 10 | 11 | 1. Introduction 12 | ---------------- 13 | 14 | The packet sink is a simple helper program listening on a single port for UDP 15 | datagrams, and displaying a message each time one is received. The content of 16 | the datagram itself is ignored. 17 | 18 | This allow to test another software (locally or on another computer) that 19 | sends UDP datagrams without having ICMP 'port closed' errors each time. 20 | 21 | 2. Dependencies 22 | ---------------- 23 | 24 | None. 25 | 26 | 3. Usage 27 | --------- 28 | 29 | Start the program with the port number as first and only argument. 30 | 31 | To stop the application, press Ctrl+C. 32 | 33 | 4. License 34 | ----------- 35 | 36 | Copyright (C) 2013, SEMTECH S.A. 37 | All rights reserved. 38 | 39 | Redistribution and use in source and binary forms, with or without 40 | modification, are permitted provided that the following conditions are met: 41 | 42 | * Redistributions of source code must retain the above copyright 43 | notice, this list of conditions and the following disclaimer. 44 | * Redistributions in binary form must reproduce the above copyright 45 | notice, this list of conditions and the following disclaimer in the 46 | documentation and/or other materials provided with the distribution. 47 | * Neither the name of the Semtech corporation nor the 48 | names of its contributors may be used to endorse or promote products 49 | derived from this software without specific prior written permission. 50 | 51 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND 52 | ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 53 | WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 54 | DISCLAIMED. IN NO EVENT SHALL SEMTECH S.A. BE LIABLE FOR ANY 55 | DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 56 | (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 57 | LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND 58 | ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 59 | (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 60 | SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 61 | 62 | *EOF* -------------------------------------------------------------------------------- /poly_pkt_fwd/Makefile: -------------------------------------------------------------------------------- 1 | ### Application-specific constants 2 | 3 | APP_NAME := poly_pkt_fwd 4 | 5 | ### Environment constants 6 | 7 | LGW_PATH ?= ../../lora_gateway/libloragw 8 | ARCH ?= 9 | CROSS_COMPILE ?= 10 | 11 | ### External constant definitions 12 | # must get library build option to know if mpsse must be linked or not 13 | 14 | include $(LGW_PATH)/library.cfg 15 | RELEASE_VERSION := $(shell cat ../VERSION) 16 | 17 | ### Constant symbols 18 | 19 | CC := $(CROSS_COMPILE)gcc 20 | AR := $(CROSS_COMPILE)ar 21 | 22 | CFLAGS := -O2 -Wall -Wextra -std=c99 -Iinc -I. 23 | VFLAG := -D VERSION_STRING="\"$(RELEASE_VERSION)\"" 24 | 25 | ### Constants for Lora concentrator HAL library 26 | # List the library sub-modules that are used by the application 27 | 28 | LGW_INC = 29 | ifneq ($(wildcard $(LGW_PATH)/inc/config.h),) 30 | # only for HAL version 1.3 and beyond 31 | LGW_INC += $(LGW_PATH)/inc/config.h 32 | endif 33 | LGW_INC += $(LGW_PATH)/inc/loragw_hal.h 34 | LGW_INC += $(LGW_PATH)/inc/loragw_gps.h 35 | 36 | ### Linking options 37 | 38 | ifeq ($(CFG_SPI),native) 39 | LIBS := -lloragw -lrt -lpthread 40 | else ifeq ($(CFG_SPI),ftdi) 41 | LIBS := -lloragw -lrt -lpthread -lmpsse 42 | else ifeq ($(CFG_SPI),mac) 43 | LIBS := -lloragw -lpthread -lmpsse 44 | else 45 | # keep compatibility with SX1301 HAL version 1.2.x and bellow 46 | ifeq ($(LGW_PHY),native) 47 | LIBS := -lloragw -lrt -lpthread 48 | else ifeq ($(LGW_PHY),ftdi) 49 | LIBS := -lloragw -lrt -lpthread -lmpsse 50 | else ifeq ($(LGW_PHY),mac) 51 | LIBS := -lloragw -lpthread -lmpsse 52 | else 53 | $(error [error] Can't find configuration for SPI phy) 54 | endif 55 | endif 56 | 57 | ### General build targets 58 | 59 | all: $(APP_NAME) 60 | 61 | clean: 62 | rm -f obj/*.o 63 | rm -f $(APP_NAME) 64 | 65 | ### Sub-modules compilation 66 | 67 | obj/base64.o: src/base64.c inc/base64.h 68 | $(CC) -c $(CFLAGS) $< -o $@ 69 | 70 | obj/parson.o: src/parson.c inc/parson.h 71 | $(CC) -c $(CFLAGS) $< -o $@ 72 | 73 | obj/monitor.o: src/monitor.c inc/monitor.h 74 | $(CC) -c $(CFLAGS) $< -o $@ 75 | 76 | obj/ghost.o: src/ghost.c inc/ghost.h $(LGW_INC) 77 | $(CC) -I$(LGW_PATH)/inc -c $(CFLAGS) $< -o $@ 78 | 79 | ### Main program compilation and assembly 80 | 81 | obj/$(APP_NAME).o: src/$(APP_NAME).c $(LGW_INC) inc/parson.h inc/base64.h inc/ghost.h inc/monitor.h 82 | $(CC) -c $(CFLAGS) $(VFLAG) -I$(LGW_PATH)/inc $< -o $@ 83 | 84 | $(APP_NAME): obj/$(APP_NAME).o $(LGW_PATH)/libloragw.a obj/parson.o obj/base64.o obj/ghost.o obj/monitor.o 85 | $(CC) -L$(LGW_PATH) $< obj/parson.o obj/base64.o obj/ghost.o obj/monitor.o -o $@ $(LIBS) 86 | 87 | ### EOF 88 | -------------------------------------------------------------------------------- /reset_pkt_fwd.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | 3 | # This script is intended to be used on IoT Starter Kit platform only, it performs the 4 | # following actions: 5 | # - export/unpexort GPIO7 used to reset the SX1301 chip 6 | # - optionaly update the Gateway_ID field of given JSON configuration file, with MAC address 7 | # 8 | # Usage examples: 9 | # ./reset_pkt_fwd.sh start ./local_conf.json 10 | # ./gps_pkt_fwd 11 | # (stop with Ctrl-C) 12 | # ./reset_pkt_fwd.sh stop 13 | # ./reset_pkt_fwd.sh start 14 | # ./gps_pkt_fwd 15 | 16 | # Force bypassing auto update of Gateway_ID in JSON conf file 17 | IOT_SK_GWID_UPDATE=true 18 | 19 | # The reset pin of SX1301 is wired with RPi GPIO7 20 | IOT_SK_SX1301_RESET_PIN=7 21 | 22 | WAIT_GPIO() { 23 | sleep 0.1 24 | } 25 | 26 | iot_sk_init() { 27 | # setup GPIO 7 28 | echo "$IOT_SK_SX1301_RESET_PIN" > /sys/class/gpio/export; WAIT_GPIO 29 | 30 | # set GPIO 7 as output 31 | echo "out" > /sys/class/gpio/gpio$IOT_SK_SX1301_RESET_PIN/direction; WAIT_GPIO 32 | 33 | # write output for SX1301 reset 34 | echo "1" > /sys/class/gpio/gpio$IOT_SK_SX1301_RESET_PIN/value; WAIT_GPIO 35 | echo "0" > /sys/class/gpio/gpio$IOT_SK_SX1301_RESET_PIN/value; WAIT_GPIO 36 | 37 | # set GPIO 7 as input 38 | echo "in" > /sys/class/gpio/gpio$IOT_SK_SX1301_RESET_PIN/direction; WAIT_GPIO 39 | } 40 | 41 | iot_sk_term() { 42 | # cleanup GPIO 7 43 | if [ -d /sys/class/gpio/gpio$IOT_SK_SX1301_RESET_PIN ] 44 | then 45 | echo "$IOT_SK_SX1301_RESET_PIN" > /sys/class/gpio/unexport; WAIT_GPIO 46 | fi 47 | } 48 | 49 | iot_sk_update_gwid() { 50 | if [ -z "$1" ] 51 | then 52 | echo "Gateway_ID not set, using default" 53 | else 54 | # get gateway ID from its MAC address 55 | GWID_PREFIX="FFFE" 56 | GWID=$(ip link show eth0 | awk '/ether/ {print $2}' | awk -F\: '{print $1$2$3$4$5$6}') 57 | 58 | # replace last 8 digits of default gateway ID by actual GWID, in given JSON configuration file 59 | sed -i 's/\(^\s*"gateway_ID":\s*"\).\{16\}"\s*\(,\?\).*$/\1'${GWID_PREFIX}${GWID}'"\2/' $1 60 | 61 | echo "Gateway_ID set to "$GWID_PREFIX$GWID" in file "$1 62 | fi 63 | } 64 | 65 | case "$1" in 66 | start) 67 | iot_sk_term 68 | iot_sk_init 69 | if $IOT_SK_GWID_UPDATE; then 70 | iot_sk_update_gwid $2 71 | fi 72 | ;; 73 | stop) 74 | iot_sk_term 75 | ;; 76 | *) 77 | echo "Usage: $0 {start|stop} [filename]" 78 | echo " filename: Path to JSON file containing Gateway_ID for packet forwarder" 79 | exit 1 80 | ;; 81 | esac 82 | 83 | exit 0 84 | -------------------------------------------------------------------------------- /poly_pkt_fwd/inc/monitor.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Extension of Semtech Semtech-Cycleo Packet Forwarder. 3 | * (C) 2015 Beta Research BV 4 | * 5 | * Description: Monitor of the gateway. 6 | * 7 | * License: Revised BSD License, see LICENSE.TXT file include in the project 8 | * Maintainer: Ruud Vlaming 9 | */ 10 | 11 | #ifndef _ACCESS_H_ 12 | #define _ACCESS_H_ 13 | 14 | 15 | /* 16 | * At the moment the only requests that can come from the maintenance server are 17 | * - send monitor info. (on byte 5; 0: do not send, 1: send, others: ignore) 18 | * - open ssh tunnel (on byte 6; 0: do nothing, 1: open, 2: close, others: ignore) 19 | * The message should exactly be 6 bytes long. 20 | * This will be json encoded in the future. 21 | * */ 22 | 23 | //TODO: As we are not really sending any gateway specific information up to know, 24 | // We must ask ourselves the question is the monitor function really belongs in 25 | // in the poly_forwarder. It can also lead to instabilities. 26 | 27 | #include "poly_pkt_fwd.h" 28 | 29 | /* -------------------------------------------------------------------------- */ 30 | /* --- PRIVATE CONSTANTS AND FIELDS ----------------------------------------- */ 31 | 32 | #define MNTR_RQST_MSGSIZE 128 /* Monitor request max size. */ 33 | #define MNTR_CALL_SECS 60 /* Minimum time between calls for monitor nodes, don't hammer de node server. */ 34 | #define MONITOR_SIZE 256 /* Maximal size of the monitor JSON information packet. */ 35 | #define MNTR_SYS_MAX 16 /* Maixmal number of systemcalls that may be defined in array */ 36 | 37 | 38 | /* -------------------------------------------------------------------------- */ 39 | /* --- SHARED FIELDS -------------------------------------------------------- */ 40 | 41 | /* Monitor parameters */ 42 | //TODO: Although these defaults seem sensible it still is a code smell, remove 43 | //TODO: shared variables are an even worse code smell, solve this! 44 | extern uint16_t ssh_port; 45 | extern uint16_t http_port; 46 | extern char ssh_path[64]; 47 | extern char ngrok_path[64]; 48 | extern int mntr_sys_count; 49 | extern char mntr_sys_list[MNTR_SYS_MAX][64]; 50 | 51 | 52 | /* -------------------------------------------------------------------------- */ 53 | /* --- PUBLIC FUNCTIONS PROTOTYPES ------------------------------------------ */ 54 | 55 | /* Call this to start/stop the server that communicates with the monitor node server. */ 56 | void monitor_start(const char * monitor_addr, const char * monitor_port); 57 | void monitor_stop(void); 58 | 59 | #endif 60 | 61 | 62 | /* --- EOF ------------------------------------------------------------------ */ 63 | -------------------------------------------------------------------------------- /util_ack/readme.md: -------------------------------------------------------------------------------- 1 | / _____) _ | | 2 | ( (____ _____ ____ _| |_ _____ ____| |__ 3 | \____ \| ___ | (_ _) ___ |/ ___) _ \ 4 | _____) ) ____| | | || |_| ____( (___| | | | 5 | (______/|_____)_|_|_| \__)_____)\____)_| |_| 6 | (C)2013 Semtech-Cycleo 7 | 8 | Utility: packet acknowledger 9 | ============================= 10 | 11 | 1. Introduction 12 | ---------------- 13 | 14 | The packet acknowledger is a simple helper program listening on a single UDP 15 | port and responding to PUSH_DATA datagrams with PUSH_ACK, and to PULL_DATA 16 | datagrams with PULL_ACK. 17 | 18 | Informations about the datagrams received and the answers send are display on 19 | screen to help communication debugging. 20 | 21 | Packets not following the protocol detailed in the PROTOCOL.TXT document in the 22 | basic_pkt_fwt directory are ignored. 23 | 24 | 2. Dependencies 25 | ---------------- 26 | 27 | This program follows the v1.1 version of the gateway-to-server protocol. 28 | 29 | 3. Usage 30 | --------- 31 | 32 | Start the program with the port number as first and only argument. 33 | 34 | To stop the application, press Ctrl+C. 35 | 36 | 4. License 37 | ----------- 38 | 39 | Copyright (C) 2013, SEMTECH S.A. 40 | All rights reserved. 41 | 42 | Redistribution and use in source and binary forms, with or without 43 | modification, are permitted provided that the following conditions are met: 44 | 45 | * Redistributions of source code must retain the above copyright 46 | notice, this list of conditions and the following disclaimer. 47 | * Redistributions in binary form must reproduce the above copyright 48 | notice, this list of conditions and the following disclaimer in the 49 | documentation and/or other materials provided with the distribution. 50 | * Neither the name of the Semtech corporation nor the 51 | names of its contributors may be used to endorse or promote products 52 | derived from this software without specific prior written permission. 53 | 54 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND 55 | ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 56 | WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 57 | DISCLAIMED. IN NO EVENT SHALL SEMTECH S.A. BE LIABLE FOR ANY 58 | DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 59 | (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 60 | LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND 61 | ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 62 | (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 63 | SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 64 | 65 | *EOF* -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | Copyright (C) 2013, SEMTECH S.A. 2 | All rights reserved. 3 | 4 | Redistribution and use in source and binary forms, with or without 5 | modification, are permitted provided that the following conditions are met: 6 | * Redistributions of source code must retain the above copyright 7 | notice, this list of conditions and the following disclaimer. 8 | * Redistributions in binary form must reproduce the above copyright 9 | notice, this list of conditions and the following disclaimer in the 10 | documentation and/or other materials provided with the distribution. 11 | * Neither the name of the Semtech corporation nor the 12 | names of its contributors may be used to endorse or promote products 13 | derived from this software without specific prior written permission. 14 | 15 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND 16 | ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 17 | WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 18 | DISCLAIMED. IN NO EVENT SHALL SEMTECH S.A. BE LIABLE FOR ANY 19 | DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 20 | (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 21 | LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND 22 | ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 23 | (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 24 | SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 25 | 26 | 27 | --- For the parson library --- 28 | 29 | Parson ( http://kgabis.github.com/parson/ ) 30 | Copyright (C) 2012 Krzysztof Gabis 31 | 32 | Permission is hereby granted, free of charge, to any person obtaining a copy 33 | of this software and associated documentation files (the "Software"), to deal 34 | in the Software without restriction, including without limitation the rights 35 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 36 | copies of the Software, and to permit persons to whom the Software is 37 | furnished to do so, subject to the following conditions: 38 | 39 | The above copyright notice and this permission notice shall be included in 40 | all copies or substantial portions of the Software. 41 | 42 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 43 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 44 | ITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 45 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 46 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 47 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 48 | THE SOFTWARE. 49 | 50 | -------------------------------------------------------------------------------- /util_tx_test/readme.md: -------------------------------------------------------------------------------- 1 | / _____) _ | | 2 | ( (____ _____ ____ _| |_ _____ ____| |__ 3 | \____ \| ___ | (_ _) ___ |/ ___) _ \ 4 | _____) ) ____| | | || |_| ____( (___| | | | 5 | (______/|_____)_|_|_| \__)_____)\____)_| |_| 6 | (C)2013 Semtech-Cycleo 7 | 8 | Utility: network packet sender 9 | =============================== 10 | 11 | 1. Introduction 12 | ---------------- 13 | 14 | The network packet sender is a simple helper program used to send packets 15 | through the gateway-to-server downlink route. 16 | 17 | The program start by waiting for a gateway to send it a PULL_DATA datagram. 18 | After that, it will send back to the gateway a specified amount of PULL_RESP 19 | datagrams, each containing a packet to be sent immediately and a variable 20 | payload. 21 | 22 | 2. Dependencies 23 | ---------------- 24 | 25 | This program follows the v1.1 version of the gateway-to-server protocol. 26 | 27 | 3. Usage 28 | --------- 29 | 30 | The application runs until the specified number of packets have been sent. 31 | Press Ctrl+C to stop the application before that. 32 | 33 | Use the -n option to specify on which UDP port the program must wait for a 34 | gateway to contact it. 35 | 36 | Use the -f option followed by a real number (decimal point and scientific 37 | 'E notation' are OK) to specify the modulation central frequency. 38 | 39 | Use the -s option to specify the Spreading Factor of Lora modulation (values 7 40 | to 12 are valid). 41 | 42 | Use the -b option to set Lora modulation bandwidth in kHz (accepted values: 125, 43 | 250 or 500). 44 | 45 | Use the -p option to set the concentrator TX power in dBm. Not all values are 46 | supported by hardware (typically 14 et 20 dBm are supported, other values might 47 | not give expected power). Check with a RF power meter before connecting any 48 | sensitive equipment. 49 | 50 | Use the -t option to specify the number of milliseconds of pause between 51 | packets. Using zero will result in a quasi-continuous emission. 52 | 53 | Use the -x to specify how many packets should be sent. 54 | 55 | Use the -i option to invert the Lora modulation polarity. 56 | 57 | The packets are 20 bytes long, and protected by the smallest supported ECC. 58 | 59 | The payload content is: 60 | [T][E][S][T][10's decimal digit of the packet counter in ASCII][unit decimal 61 | digit of the packet counter in ASCII] followed by ASCII padding. 62 | 63 | 4. License 64 | ----------- 65 | 66 | Copyright (C) 2013, SEMTECH S.A. 67 | All rights reserved. 68 | 69 | Redistribution and use in source and binary forms, with or without 70 | modification, are permitted provided that the following conditions are met: 71 | 72 | * Redistributions of source code must retain the above copyright 73 | notice, this list of conditions and the following disclaimer. 74 | * Redistributions in binary form must reproduce the above copyright 75 | notice, this list of conditions and the following disclaimer in the 76 | documentation and/or other materials provided with the distribution. 77 | * Neither the name of the Semtech corporation nor the 78 | names of its contributors may be used to endorse or promote products 79 | derived from this software without specific prior written permission. 80 | 81 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND 82 | ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 83 | WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 84 | DISCLAIMED. IN NO EVENT SHALL SEMTECH S.A. BE LIABLE FOR ANY 85 | DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 86 | (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 87 | LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND 88 | ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 89 | (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 90 | SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 91 | 92 | *EOF* -------------------------------------------------------------------------------- /util_sink/src/util_sink.c: -------------------------------------------------------------------------------- 1 | /* 2 | / _____) _ | | 3 | ( (____ _____ ____ _| |_ _____ ____| |__ 4 | \____ \| ___ | (_ _) ___ |/ ___) _ \ 5 | _____) ) ____| | | || |_| ____( (___| | | | 6 | (______/|_____)_|_|_| \__)_____)\____)_| |_| 7 | (C)2013 Semtech-Cycleo 8 | 9 | Description: 10 | Network sink, receives UDP packets on certain ports and discards them 11 | 12 | License: Revised BSD License, see LICENSE.TXT file include in the project 13 | Maintainer: Sylvain Miermont 14 | */ 15 | 16 | 17 | /* -------------------------------------------------------------------------- */ 18 | /* --- DEPENDANCIES --------------------------------------------------------- */ 19 | 20 | /* fix an issue between POSIX and C99 */ 21 | #if __STDC_VERSION__ >= 199901L 22 | #define _XOPEN_SOURCE 600 23 | #else 24 | #define _XOPEN_SOURCE 500 25 | #endif 26 | 27 | #include /* C99 types */ 28 | #include /* printf, fprintf, sprintf, fopen, fputs */ 29 | 30 | #include /* memset */ 31 | #include /* time, clock_gettime, strftime, gmtime, clock_nanosleep*/ 32 | #include /* atoi, exit */ 33 | #include /* error messages */ 34 | 35 | #include /* socket specific definitions */ 36 | #include /* INET constants and stuff */ 37 | #include /* IP address conversion stuff */ 38 | #include /* gai_strerror */ 39 | 40 | /* -------------------------------------------------------------------------- */ 41 | /* --- PRIVATE MACROS ------------------------------------------------------- */ 42 | 43 | #define ARRAY_SIZE(a) (sizeof(a) / sizeof((a)[0])) 44 | #define STRINGIFY(x) #x 45 | #define STR(x) STRINGIFY(x) 46 | #define MSG(args...) fprintf(stderr, args) /* message that is destined to the user */ 47 | 48 | /* -------------------------------------------------------------------------- */ 49 | /* --- MAIN FUNCTION -------------------------------------------------------- */ 50 | 51 | int main(int argc, char **argv) 52 | { 53 | int i; /* loop variable and temporary variable for return value */ 54 | 55 | /* server socket creation */ 56 | int sock; /* socket file descriptor */ 57 | struct addrinfo hints; 58 | struct addrinfo *result; /* store result of getaddrinfo */ 59 | struct addrinfo *q; /* pointer to move into *result data */ 60 | char host_name[64]; 61 | char port_name[64]; 62 | 63 | /* variables for receiving packets */ 64 | struct sockaddr_storage dist_addr; 65 | socklen_t addr_len = sizeof dist_addr; 66 | uint8_t databuf[4096]; 67 | int byte_nb; 68 | 69 | /* check if port number was passed as parameter */ 70 | if (argc != 2) { 71 | MSG("Usage: util_sink \n"); 72 | exit(EXIT_FAILURE); 73 | } 74 | 75 | /* prepare hints to open network sockets */ 76 | memset(&hints, 0, sizeof hints); 77 | hints.ai_family = AF_UNSPEC; /* should handle IP v4 or v6 automatically */ 78 | hints.ai_socktype = SOCK_DGRAM; 79 | hints.ai_flags = AI_PASSIVE; /* will assign local IP automatically */ 80 | 81 | /* look for address */ 82 | i = getaddrinfo(NULL, argv[1], &hints, &result); 83 | if (i != 0) { 84 | MSG("ERROR: getaddrinfo returned %s\n", gai_strerror(i)); 85 | exit(EXIT_FAILURE); 86 | } 87 | 88 | /* try to open socket and bind it */ 89 | for (q=result; q!=NULL; q=q->ai_next) { 90 | sock = socket(q->ai_family, q->ai_socktype,q->ai_protocol); 91 | if (sock == -1) { 92 | continue; /* socket failed, try next field */ 93 | } else { 94 | i = bind(sock, q->ai_addr, q->ai_addrlen); 95 | if (i == -1) { 96 | shutdown(sock, SHUT_RDWR); 97 | continue; /* bind failed, try next field */ 98 | } else { 99 | break; /* success, get out of loop */ 100 | } 101 | } 102 | } 103 | if (q == NULL) { 104 | MSG("ERROR: failed to open socket or to bind to it\n"); 105 | i = 1; 106 | for (q=result; q!=NULL; q=q->ai_next) { 107 | getnameinfo(q->ai_addr, q->ai_addrlen, host_name, sizeof host_name, port_name, sizeof port_name, NI_NUMERICHOST); 108 | MSG("result %i host:%s service:%s\n", i, host_name, port_name); 109 | ++i; 110 | } 111 | exit(EXIT_FAILURE); 112 | } 113 | MSG("INFO: util_sink listening on port %s\n", argv[1]); 114 | freeaddrinfo(result); 115 | 116 | while (1) { 117 | byte_nb = recvfrom(sock, databuf, sizeof databuf, 0, (struct sockaddr *)&dist_addr, &addr_len); 118 | if (byte_nb == -1) { 119 | MSG("ERROR: recvfrom returned %s \n", strerror(errno)); 120 | exit(EXIT_FAILURE); 121 | } 122 | getnameinfo((struct sockaddr *)&dist_addr, addr_len, host_name, sizeof host_name, port_name, sizeof port_name, NI_NUMERICHOST); 123 | printf("Got packet from host %s port %s, %i bytes long\n", host_name, port_name, byte_nb); 124 | } 125 | } 126 | -------------------------------------------------------------------------------- /gps_pkt_fwd/inc/parson.h: -------------------------------------------------------------------------------- 1 | /* 2 | Parson ( http://kgabis.github.com/parson/ ) 3 | Copyright (C) 2013 Krzysztof Gabis 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in 13 | all copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 21 | THE SOFTWARE. 22 | */ 23 | 24 | #ifndef parson_parson_h 25 | #define parson_parson_h 26 | 27 | #ifdef __cplusplus 28 | extern "C" 29 | { 30 | #endif 31 | 32 | #include /* size_t */ 33 | 34 | #define PARSON_VERSION 20131130 35 | 36 | /* Types and enums */ 37 | typedef struct json_object_t JSON_Object; 38 | typedef struct json_array_t JSON_Array; 39 | typedef struct json_value_t JSON_Value; 40 | 41 | typedef enum json_value_type { 42 | JSONError = 0, 43 | JSONNull = 1, 44 | JSONString = 2, 45 | JSONNumber = 3, 46 | JSONObject = 4, 47 | JSONArray = 5, 48 | JSONBoolean = 6 49 | } JSON_Value_Type; 50 | 51 | 52 | /* Parses first JSON value in a file, returns NULL in case of error */ 53 | JSON_Value * json_parse_file(const char *filename); 54 | 55 | /* Parses first JSON value in a file and ignores comments (/ * * / and //), 56 | returns NULL in case of error */ 57 | JSON_Value * json_parse_file_with_comments(const char *filename); 58 | 59 | /* Parses first JSON value in a string, returns NULL in case of error */ 60 | JSON_Value * json_parse_string(const char *string); 61 | 62 | /* Parses first JSON value in a string and ignores comments (/ * * / and //), 63 | returns NULL in case of error */ 64 | JSON_Value * json_parse_string_with_comments(const char *string); 65 | 66 | /* JSON Object */ 67 | JSON_Value * json_object_get_value (const JSON_Object *object, const char *name); 68 | const char * json_object_get_string (const JSON_Object *object, const char *name); 69 | JSON_Object * json_object_get_object (const JSON_Object *object, const char *name); 70 | JSON_Array * json_object_get_array (const JSON_Object *object, const char *name); 71 | double json_object_get_number (const JSON_Object *object, const char *name); 72 | int json_object_get_boolean(const JSON_Object *object, const char *name); 73 | 74 | /* dotget functions enable addressing values with dot notation in nested objects, 75 | just like in structs or c++/java/c# objects (e.g. objectA.objectB.value). 76 | Because valid names in JSON can contain dots, some values may be inaccessible 77 | this way. */ 78 | JSON_Value * json_object_dotget_value (const JSON_Object *object, const char *name); 79 | const char * json_object_dotget_string (const JSON_Object *object, const char *name); 80 | JSON_Object * json_object_dotget_object (const JSON_Object *object, const char *name); 81 | JSON_Array * json_object_dotget_array (const JSON_Object *object, const char *name); 82 | double json_object_dotget_number (const JSON_Object *object, const char *name); 83 | int json_object_dotget_boolean(const JSON_Object *object, const char *name); 84 | 85 | /* Functions to get available names */ 86 | size_t json_object_get_count(const JSON_Object *object); 87 | const char * json_object_get_name (const JSON_Object *object, size_t index); 88 | 89 | /* JSON Array */ 90 | JSON_Value * json_array_get_value (const JSON_Array *array, size_t index); 91 | const char * json_array_get_string (const JSON_Array *array, size_t index); 92 | JSON_Object * json_array_get_object (const JSON_Array *array, size_t index); 93 | JSON_Array * json_array_get_array (const JSON_Array *array, size_t index); 94 | double json_array_get_number (const JSON_Array *array, size_t index); 95 | int json_array_get_boolean(const JSON_Array *array, size_t index); 96 | size_t json_array_get_count (const JSON_Array *array); 97 | 98 | /* JSON Value */ 99 | JSON_Value_Type json_value_get_type (const JSON_Value *value); 100 | JSON_Object * json_value_get_object (const JSON_Value *value); 101 | JSON_Array * json_value_get_array (const JSON_Value *value); 102 | const char * json_value_get_string (const JSON_Value *value); 103 | double json_value_get_number (const JSON_Value *value); 104 | int json_value_get_boolean(const JSON_Value *value); 105 | void json_value_free (JSON_Value *value); 106 | 107 | #ifdef __cplusplus 108 | } 109 | #endif 110 | 111 | #endif 112 | -------------------------------------------------------------------------------- /poly_pkt_fwd/inc/parson.h: -------------------------------------------------------------------------------- 1 | /* 2 | Parson ( http://kgabis.github.com/parson/ ) 3 | Copyright (C) 2013 Krzysztof Gabis 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in 13 | all copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 21 | THE SOFTWARE. 22 | */ 23 | 24 | #ifndef parson_parson_h 25 | #define parson_parson_h 26 | 27 | #ifdef __cplusplus 28 | extern "C" 29 | { 30 | #endif 31 | 32 | #include /* size_t */ 33 | 34 | #define PARSON_VERSION 20131130 35 | 36 | /* Types and enums */ 37 | typedef struct json_object_t JSON_Object; 38 | typedef struct json_array_t JSON_Array; 39 | typedef struct json_value_t JSON_Value; 40 | 41 | typedef enum json_value_type { 42 | JSONError = 0, 43 | JSONNull = 1, 44 | JSONString = 2, 45 | JSONNumber = 3, 46 | JSONObject = 4, 47 | JSONArray = 5, 48 | JSONBoolean = 6 49 | } JSON_Value_Type; 50 | 51 | 52 | /* Parses first JSON value in a file, returns NULL in case of error */ 53 | JSON_Value * json_parse_file(const char *filename); 54 | 55 | /* Parses first JSON value in a file and ignores comments (/ * * / and //), 56 | returns NULL in case of error */ 57 | JSON_Value * json_parse_file_with_comments(const char *filename); 58 | 59 | /* Parses first JSON value in a string, returns NULL in case of error */ 60 | JSON_Value * json_parse_string(const char *string); 61 | 62 | /* Parses first JSON value in a string and ignores comments (/ * * / and //), 63 | returns NULL in case of error */ 64 | JSON_Value * json_parse_string_with_comments(const char *string); 65 | 66 | /* JSON Object */ 67 | JSON_Value * json_object_get_value (const JSON_Object *object, const char *name); 68 | const char * json_object_get_string (const JSON_Object *object, const char *name); 69 | JSON_Object * json_object_get_object (const JSON_Object *object, const char *name); 70 | JSON_Array * json_object_get_array (const JSON_Object *object, const char *name); 71 | double json_object_get_number (const JSON_Object *object, const char *name); 72 | int json_object_get_boolean(const JSON_Object *object, const char *name); 73 | 74 | /* dotget functions enable addressing values with dot notation in nested objects, 75 | just like in structs or c++/java/c# objects (e.g. objectA.objectB.value). 76 | Because valid names in JSON can contain dots, some values may be inaccessible 77 | this way. */ 78 | JSON_Value * json_object_dotget_value (const JSON_Object *object, const char *name); 79 | const char * json_object_dotget_string (const JSON_Object *object, const char *name); 80 | JSON_Object * json_object_dotget_object (const JSON_Object *object, const char *name); 81 | JSON_Array * json_object_dotget_array (const JSON_Object *object, const char *name); 82 | double json_object_dotget_number (const JSON_Object *object, const char *name); 83 | int json_object_dotget_boolean(const JSON_Object *object, const char *name); 84 | 85 | /* Functions to get available names */ 86 | size_t json_object_get_count(const JSON_Object *object); 87 | const char * json_object_get_name (const JSON_Object *object, size_t index); 88 | 89 | /* JSON Array */ 90 | JSON_Value * json_array_get_value (const JSON_Array *array, size_t index); 91 | const char * json_array_get_string (const JSON_Array *array, size_t index); 92 | JSON_Object * json_array_get_object (const JSON_Array *array, size_t index); 93 | JSON_Array * json_array_get_array (const JSON_Array *array, size_t index); 94 | double json_array_get_number (const JSON_Array *array, size_t index); 95 | int json_array_get_boolean(const JSON_Array *array, size_t index); 96 | size_t json_array_get_count (const JSON_Array *array); 97 | 98 | /* JSON Value */ 99 | JSON_Value_Type json_value_get_type (const JSON_Value *value); 100 | JSON_Object * json_value_get_object (const JSON_Value *value); 101 | JSON_Array * json_value_get_array (const JSON_Value *value); 102 | const char * json_value_get_string (const JSON_Value *value); 103 | double json_value_get_number (const JSON_Value *value); 104 | int json_value_get_boolean(const JSON_Value *value); 105 | void json_value_free (JSON_Value *value); 106 | 107 | #ifdef __cplusplus 108 | } 109 | #endif 110 | 111 | #endif 112 | -------------------------------------------------------------------------------- /basic_pkt_fwd/inc/parson.h: -------------------------------------------------------------------------------- 1 | /* 2 | Parson ( http://kgabis.github.com/parson/ ) 3 | Copyright (C) 2013 Krzysztof Gabis 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in 13 | all copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 21 | THE SOFTWARE. 22 | */ 23 | 24 | #ifndef parson_parson_h 25 | #define parson_parson_h 26 | 27 | #ifdef __cplusplus 28 | extern "C" 29 | { 30 | #endif 31 | 32 | #include /* size_t */ 33 | 34 | #define PARSON_VERSION 20131130 35 | 36 | /* Types and enums */ 37 | typedef struct json_object_t JSON_Object; 38 | typedef struct json_array_t JSON_Array; 39 | typedef struct json_value_t JSON_Value; 40 | 41 | typedef enum json_value_type { 42 | JSONError = 0, 43 | JSONNull = 1, 44 | JSONString = 2, 45 | JSONNumber = 3, 46 | JSONObject = 4, 47 | JSONArray = 5, 48 | JSONBoolean = 6 49 | } JSON_Value_Type; 50 | 51 | 52 | /* Parses first JSON value in a file, returns NULL in case of error */ 53 | JSON_Value * json_parse_file(const char *filename); 54 | 55 | /* Parses first JSON value in a file and ignores comments (/ * * / and //), 56 | returns NULL in case of error */ 57 | JSON_Value * json_parse_file_with_comments(const char *filename); 58 | 59 | /* Parses first JSON value in a string, returns NULL in case of error */ 60 | JSON_Value * json_parse_string(const char *string); 61 | 62 | /* Parses first JSON value in a string and ignores comments (/ * * / and //), 63 | returns NULL in case of error */ 64 | JSON_Value * json_parse_string_with_comments(const char *string); 65 | 66 | /* JSON Object */ 67 | JSON_Value * json_object_get_value (const JSON_Object *object, const char *name); 68 | const char * json_object_get_string (const JSON_Object *object, const char *name); 69 | JSON_Object * json_object_get_object (const JSON_Object *object, const char *name); 70 | JSON_Array * json_object_get_array (const JSON_Object *object, const char *name); 71 | double json_object_get_number (const JSON_Object *object, const char *name); 72 | int json_object_get_boolean(const JSON_Object *object, const char *name); 73 | 74 | /* dotget functions enable addressing values with dot notation in nested objects, 75 | just like in structs or c++/java/c# objects (e.g. objectA.objectB.value). 76 | Because valid names in JSON can contain dots, some values may be inaccessible 77 | this way. */ 78 | JSON_Value * json_object_dotget_value (const JSON_Object *object, const char *name); 79 | const char * json_object_dotget_string (const JSON_Object *object, const char *name); 80 | JSON_Object * json_object_dotget_object (const JSON_Object *object, const char *name); 81 | JSON_Array * json_object_dotget_array (const JSON_Object *object, const char *name); 82 | double json_object_dotget_number (const JSON_Object *object, const char *name); 83 | int json_object_dotget_boolean(const JSON_Object *object, const char *name); 84 | 85 | /* Functions to get available names */ 86 | size_t json_object_get_count(const JSON_Object *object); 87 | const char * json_object_get_name (const JSON_Object *object, size_t index); 88 | 89 | /* JSON Array */ 90 | JSON_Value * json_array_get_value (const JSON_Array *array, size_t index); 91 | const char * json_array_get_string (const JSON_Array *array, size_t index); 92 | JSON_Object * json_array_get_object (const JSON_Array *array, size_t index); 93 | JSON_Array * json_array_get_array (const JSON_Array *array, size_t index); 94 | double json_array_get_number (const JSON_Array *array, size_t index); 95 | int json_array_get_boolean(const JSON_Array *array, size_t index); 96 | size_t json_array_get_count (const JSON_Array *array); 97 | 98 | /* JSON Value */ 99 | JSON_Value_Type json_value_get_type (const JSON_Value *value); 100 | JSON_Object * json_value_get_object (const JSON_Value *value); 101 | JSON_Array * json_value_get_array (const JSON_Value *value); 102 | const char * json_value_get_string (const JSON_Value *value); 103 | double json_value_get_number (const JSON_Value *value); 104 | int json_value_get_boolean(const JSON_Value *value); 105 | void json_value_free (JSON_Value *value); 106 | 107 | #ifdef __cplusplus 108 | } 109 | #endif 110 | 111 | #endif 112 | -------------------------------------------------------------------------------- /beacon_pkt_fwd/inc/parson.h: -------------------------------------------------------------------------------- 1 | /* 2 | Parson ( http://kgabis.github.com/parson/ ) 3 | Copyright (C) 2013 Krzysztof Gabis 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in 13 | all copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 21 | THE SOFTWARE. 22 | */ 23 | 24 | #ifndef parson_parson_h 25 | #define parson_parson_h 26 | 27 | #ifdef __cplusplus 28 | extern "C" 29 | { 30 | #endif 31 | 32 | #include /* size_t */ 33 | 34 | #define PARSON_VERSION 20131130 35 | 36 | /* Types and enums */ 37 | typedef struct json_object_t JSON_Object; 38 | typedef struct json_array_t JSON_Array; 39 | typedef struct json_value_t JSON_Value; 40 | 41 | typedef enum json_value_type { 42 | JSONError = 0, 43 | JSONNull = 1, 44 | JSONString = 2, 45 | JSONNumber = 3, 46 | JSONObject = 4, 47 | JSONArray = 5, 48 | JSONBoolean = 6 49 | } JSON_Value_Type; 50 | 51 | 52 | /* Parses first JSON value in a file, returns NULL in case of error */ 53 | JSON_Value * json_parse_file(const char *filename); 54 | 55 | /* Parses first JSON value in a file and ignores comments (/ * * / and //), 56 | returns NULL in case of error */ 57 | JSON_Value * json_parse_file_with_comments(const char *filename); 58 | 59 | /* Parses first JSON value in a string, returns NULL in case of error */ 60 | JSON_Value * json_parse_string(const char *string); 61 | 62 | /* Parses first JSON value in a string and ignores comments (/ * * / and //), 63 | returns NULL in case of error */ 64 | JSON_Value * json_parse_string_with_comments(const char *string); 65 | 66 | /* JSON Object */ 67 | JSON_Value * json_object_get_value (const JSON_Object *object, const char *name); 68 | const char * json_object_get_string (const JSON_Object *object, const char *name); 69 | JSON_Object * json_object_get_object (const JSON_Object *object, const char *name); 70 | JSON_Array * json_object_get_array (const JSON_Object *object, const char *name); 71 | double json_object_get_number (const JSON_Object *object, const char *name); 72 | int json_object_get_boolean(const JSON_Object *object, const char *name); 73 | 74 | /* dotget functions enable addressing values with dot notation in nested objects, 75 | just like in structs or c++/java/c# objects (e.g. objectA.objectB.value). 76 | Because valid names in JSON can contain dots, some values may be inaccessible 77 | this way. */ 78 | JSON_Value * json_object_dotget_value (const JSON_Object *object, const char *name); 79 | const char * json_object_dotget_string (const JSON_Object *object, const char *name); 80 | JSON_Object * json_object_dotget_object (const JSON_Object *object, const char *name); 81 | JSON_Array * json_object_dotget_array (const JSON_Object *object, const char *name); 82 | double json_object_dotget_number (const JSON_Object *object, const char *name); 83 | int json_object_dotget_boolean(const JSON_Object *object, const char *name); 84 | 85 | /* Functions to get available names */ 86 | size_t json_object_get_count(const JSON_Object *object); 87 | const char * json_object_get_name (const JSON_Object *object, size_t index); 88 | 89 | /* JSON Array */ 90 | JSON_Value * json_array_get_value (const JSON_Array *array, size_t index); 91 | const char * json_array_get_string (const JSON_Array *array, size_t index); 92 | JSON_Object * json_array_get_object (const JSON_Array *array, size_t index); 93 | JSON_Array * json_array_get_array (const JSON_Array *array, size_t index); 94 | double json_array_get_number (const JSON_Array *array, size_t index); 95 | int json_array_get_boolean(const JSON_Array *array, size_t index); 96 | size_t json_array_get_count (const JSON_Array *array); 97 | 98 | /* JSON Value */ 99 | JSON_Value_Type json_value_get_type (const JSON_Value *value); 100 | JSON_Object * json_value_get_object (const JSON_Value *value); 101 | JSON_Array * json_value_get_array (const JSON_Value *value); 102 | const char * json_value_get_string (const JSON_Value *value); 103 | double json_value_get_number (const JSON_Value *value); 104 | int json_value_get_boolean(const JSON_Value *value); 105 | void json_value_free (JSON_Value *value); 106 | 107 | #ifdef __cplusplus 108 | } 109 | #endif 110 | 111 | #endif 112 | -------------------------------------------------------------------------------- /basic_pkt_fwd/global_conf.json: -------------------------------------------------------------------------------- 1 | { 2 | "SX1301_conf": { 3 | "lorawan_public": true, 4 | "clksrc": 1, /* radio_1 provides clock to concentrator */ 5 | "radio_0": { 6 | "enable": true, 7 | "type": "SX1257", 8 | "freq": 867500000, 9 | "rssi_offset": -166.0, 10 | "tx_enable": true 11 | }, 12 | "radio_1": { 13 | "enable": true, 14 | "type": "SX1257", 15 | "freq": 868500000, 16 | "rssi_offset": -166.0, 17 | "tx_enable": false 18 | }, 19 | "chan_multiSF_0": { 20 | /* Lora MAC channel, 125kHz, all SF, 868.1 MHz */ 21 | "enable": true, 22 | "radio": 1, 23 | "if": -400000 24 | }, 25 | "chan_multiSF_1": { 26 | /* Lora MAC channel, 125kHz, all SF, 868.3 MHz */ 27 | "enable": true, 28 | "radio": 1, 29 | "if": -200000 30 | }, 31 | "chan_multiSF_2": { 32 | /* Lora MAC channel, 125kHz, all SF, 868.5 MHz */ 33 | "enable": true, 34 | "radio": 1, 35 | "if": 0 36 | }, 37 | "chan_multiSF_3": { 38 | /* Lora MAC channel, 125kHz, all SF, 867.1 MHz */ 39 | "enable": true, 40 | "radio": 0, 41 | "if": -400000 42 | }, 43 | "chan_multiSF_4": { 44 | /* Lora MAC channel, 125kHz, all SF, 867.3 MHz */ 45 | "enable": true, 46 | "radio": 0, 47 | "if": -200000 48 | }, 49 | "chan_multiSF_5": { 50 | /* Lora MAC channel, 125kHz, all SF, 867.5 MHz */ 51 | "enable": true, 52 | "radio": 0, 53 | "if": 0 54 | }, 55 | "chan_multiSF_6": { 56 | /* Lora MAC channel, 125kHz, all SF, 867.7 MHz */ 57 | "enable": true, 58 | "radio": 0, 59 | "if": 200000 60 | }, 61 | "chan_multiSF_7": { 62 | /* Lora MAC channel, 125kHz, all SF, 867.9 MHz */ 63 | "enable": true, 64 | "radio": 0, 65 | "if": 400000 66 | }, 67 | "chan_Lora_std": { 68 | /* Lora MAC channel, 250kHz, SF7, 868.3 MHz */ 69 | "enable": true, 70 | "radio": 1, 71 | "if": -200000, 72 | "bandwidth": 250000, 73 | "spread_factor": 7 74 | }, 75 | "chan_FSK": { 76 | /* FSK 50kbps channel, 868.8 MHz */ 77 | "enable": true, 78 | "radio": 1, 79 | "if": 300000, 80 | "bandwidth": 125000, 81 | "datarate": 50000 82 | }, 83 | "tx_lut_0": { 84 | /* TX gain table, index 0 */ 85 | "pa_gain": 0, 86 | "mix_gain": 8, 87 | "rf_power": -6, 88 | "dig_gain": 0 89 | }, 90 | "tx_lut_1": { 91 | /* TX gain table, index 1 */ 92 | "pa_gain": 0, 93 | "mix_gain": 10, 94 | "rf_power": -3, 95 | "dig_gain": 0 96 | }, 97 | "tx_lut_2": { 98 | /* TX gain table, index 2 */ 99 | "pa_gain": 0, 100 | "mix_gain": 12, 101 | "rf_power": 0, 102 | "dig_gain": 0 103 | }, 104 | "tx_lut_3": { 105 | /* TX gain table, index 3 */ 106 | "pa_gain": 1, 107 | "mix_gain": 8, 108 | "rf_power": 3, 109 | "dig_gain": 0 110 | }, 111 | "tx_lut_4": { 112 | /* TX gain table, index 4 */ 113 | "pa_gain": 1, 114 | "mix_gain": 10, 115 | "rf_power": 6, 116 | "dig_gain": 0 117 | }, 118 | "tx_lut_5": { 119 | /* TX gain table, index 5 */ 120 | "pa_gain": 1, 121 | "mix_gain": 12, 122 | "rf_power": 10, 123 | "dig_gain": 0 124 | }, 125 | "tx_lut_6": { 126 | /* TX gain table, index 6 */ 127 | "pa_gain": 1, 128 | "mix_gain": 13, 129 | "rf_power": 11, 130 | "dig_gain": 0 131 | }, 132 | "tx_lut_7": { 133 | /* TX gain table, index 7 */ 134 | "pa_gain": 2, 135 | "mix_gain": 9, 136 | "rf_power": 12, 137 | "dig_gain": 0 138 | }, 139 | "tx_lut_8": { 140 | /* TX gain table, index 8 */ 141 | "pa_gain": 1, 142 | "mix_gain": 15, 143 | "rf_power": 13, 144 | "dig_gain": 0 145 | }, 146 | "tx_lut_9": { 147 | /* TX gain table, index 9 */ 148 | "pa_gain": 2, 149 | "mix_gain": 10, 150 | "rf_power": 14, 151 | "dig_gain": 0 152 | }, 153 | "tx_lut_10": { 154 | /* TX gain table, index 10 */ 155 | "pa_gain": 2, 156 | "mix_gain": 11, 157 | "rf_power": 16, 158 | "dig_gain": 0 159 | }, 160 | "tx_lut_11": { 161 | /* TX gain table, index 11 */ 162 | "pa_gain": 3, 163 | "mix_gain": 9, 164 | "rf_power": 20, 165 | "dig_gain": 0 166 | }, 167 | "tx_lut_12": { 168 | /* TX gain table, index 12 */ 169 | "pa_gain": 3, 170 | "mix_gain": 10, 171 | "rf_power": 23, 172 | "dig_gain": 0 173 | }, 174 | "tx_lut_13": { 175 | /* TX gain table, index 13 */ 176 | "pa_gain": 3, 177 | "mix_gain": 11, 178 | "rf_power": 25, 179 | "dig_gain": 0 180 | }, 181 | "tx_lut_14": { 182 | /* TX gain table, index 14 */ 183 | "pa_gain": 3, 184 | "mix_gain": 12, 185 | "rf_power": 26, 186 | "dig_gain": 0 187 | }, 188 | "tx_lut_15": { 189 | /* TX gain table, index 15 */ 190 | "pa_gain": 3, 191 | "mix_gain": 14, 192 | "rf_power": 27, 193 | "dig_gain": 0 194 | } 195 | }, 196 | 197 | "gateway_conf": { 198 | "gateway_ID": "AA555A0000000000", 199 | /* change with default server address/ports, or overwrite in local_conf.json */ 200 | "server_address": "127.0.0.1", 201 | "serv_port_up": 1680, 202 | "serv_port_down": 1680, 203 | /* adjust the following parameters for your network */ 204 | "keepalive_interval": 10, 205 | "stat_interval": 30, 206 | "push_timeout_ms": 100, 207 | /* forward only valid packets */ 208 | "forward_crc_valid": true, 209 | "forward_crc_error": false, 210 | "forward_crc_disabled": false 211 | } 212 | } 213 | -------------------------------------------------------------------------------- /beacon_pkt_fwd/global_conf.json: -------------------------------------------------------------------------------- 1 | { 2 | "SX1301_conf": { 3 | "lorawan_public": true, 4 | "clksrc": 1, /* radio_1 provides clock to concentrator */ 5 | "radio_0": { 6 | "enable": true, 7 | "type": "SX1257", 8 | "freq": 867500000, 9 | "rssi_offset": -166.0, 10 | "tx_enable": true 11 | }, 12 | "radio_1": { 13 | "enable": true, 14 | "type": "SX1257", 15 | "freq": 868500000, 16 | "rssi_offset": -166.0, 17 | "tx_enable": false 18 | }, 19 | "chan_multiSF_0": { 20 | /* Lora MAC channel, 125kHz, all SF, 868.1 MHz */ 21 | "enable": true, 22 | "radio": 1, 23 | "if": -400000 24 | }, 25 | "chan_multiSF_1": { 26 | /* Lora MAC channel, 125kHz, all SF, 868.3 MHz */ 27 | "enable": true, 28 | "radio": 1, 29 | "if": -200000 30 | }, 31 | "chan_multiSF_2": { 32 | /* Lora MAC channel, 125kHz, all SF, 868.5 MHz */ 33 | "enable": true, 34 | "radio": 1, 35 | "if": 0 36 | }, 37 | "chan_multiSF_3": { 38 | /* Lora MAC channel, 125kHz, all SF, 867.1 MHz */ 39 | "enable": true, 40 | "radio": 0, 41 | "if": -400000 42 | }, 43 | "chan_multiSF_4": { 44 | /* Lora MAC channel, 125kHz, all SF, 867.3 MHz */ 45 | "enable": true, 46 | "radio": 0, 47 | "if": -200000 48 | }, 49 | "chan_multiSF_5": { 50 | /* Lora MAC channel, 125kHz, all SF, 867.5 MHz */ 51 | "enable": true, 52 | "radio": 0, 53 | "if": 0 54 | }, 55 | "chan_multiSF_6": { 56 | /* Lora MAC channel, 125kHz, all SF, 867.7 MHz */ 57 | "enable": true, 58 | "radio": 0, 59 | "if": 200000 60 | }, 61 | "chan_multiSF_7": { 62 | /* Lora MAC channel, 125kHz, all SF, 867.9 MHz */ 63 | "enable": true, 64 | "radio": 0, 65 | "if": 400000 66 | }, 67 | "chan_Lora_std": { 68 | /* Lora MAC channel, 250kHz, SF7, 868.3 MHz */ 69 | "enable": true, 70 | "radio": 1, 71 | "if": -200000, 72 | "bandwidth": 250000, 73 | "spread_factor": 7 74 | }, 75 | "chan_FSK": { 76 | /* FSK 50kbps channel, 868.8 MHz */ 77 | "enable": true, 78 | "radio": 1, 79 | "if": 300000, 80 | "bandwidth": 125000, 81 | "datarate": 50000 82 | }, 83 | "tx_lut_0": { 84 | /* TX gain table, index 0 */ 85 | "pa_gain": 0, 86 | "mix_gain": 8, 87 | "rf_power": -6, 88 | "dig_gain": 0 89 | }, 90 | "tx_lut_1": { 91 | /* TX gain table, index 1 */ 92 | "pa_gain": 0, 93 | "mix_gain": 10, 94 | "rf_power": -3, 95 | "dig_gain": 0 96 | }, 97 | "tx_lut_2": { 98 | /* TX gain table, index 2 */ 99 | "pa_gain": 0, 100 | "mix_gain": 12, 101 | "rf_power": 0, 102 | "dig_gain": 0 103 | }, 104 | "tx_lut_3": { 105 | /* TX gain table, index 3 */ 106 | "pa_gain": 1, 107 | "mix_gain": 8, 108 | "rf_power": 3, 109 | "dig_gain": 0 110 | }, 111 | "tx_lut_4": { 112 | /* TX gain table, index 4 */ 113 | "pa_gain": 1, 114 | "mix_gain": 10, 115 | "rf_power": 6, 116 | "dig_gain": 0 117 | }, 118 | "tx_lut_5": { 119 | /* TX gain table, index 5 */ 120 | "pa_gain": 1, 121 | "mix_gain": 12, 122 | "rf_power": 10, 123 | "dig_gain": 0 124 | }, 125 | "tx_lut_6": { 126 | /* TX gain table, index 6 */ 127 | "pa_gain": 1, 128 | "mix_gain": 13, 129 | "rf_power": 11, 130 | "dig_gain": 0 131 | }, 132 | "tx_lut_7": { 133 | /* TX gain table, index 7 */ 134 | "pa_gain": 2, 135 | "mix_gain": 9, 136 | "rf_power": 12, 137 | "dig_gain": 0 138 | }, 139 | "tx_lut_8": { 140 | /* TX gain table, index 8 */ 141 | "pa_gain": 1, 142 | "mix_gain": 15, 143 | "rf_power": 13, 144 | "dig_gain": 0 145 | }, 146 | "tx_lut_9": { 147 | /* TX gain table, index 9 */ 148 | "pa_gain": 2, 149 | "mix_gain": 10, 150 | "rf_power": 14, 151 | "dig_gain": 0 152 | }, 153 | "tx_lut_10": { 154 | /* TX gain table, index 10 */ 155 | "pa_gain": 2, 156 | "mix_gain": 11, 157 | "rf_power": 16, 158 | "dig_gain": 0 159 | }, 160 | "tx_lut_11": { 161 | /* TX gain table, index 11 */ 162 | "pa_gain": 3, 163 | "mix_gain": 9, 164 | "rf_power": 20, 165 | "dig_gain": 0 166 | }, 167 | "tx_lut_12": { 168 | /* TX gain table, index 12 */ 169 | "pa_gain": 3, 170 | "mix_gain": 10, 171 | "rf_power": 23, 172 | "dig_gain": 0 173 | }, 174 | "tx_lut_13": { 175 | /* TX gain table, index 13 */ 176 | "pa_gain": 3, 177 | "mix_gain": 11, 178 | "rf_power": 25, 179 | "dig_gain": 0 180 | }, 181 | "tx_lut_14": { 182 | /* TX gain table, index 14 */ 183 | "pa_gain": 3, 184 | "mix_gain": 12, 185 | "rf_power": 26, 186 | "dig_gain": 0 187 | }, 188 | "tx_lut_15": { 189 | /* TX gain table, index 15 */ 190 | "pa_gain": 3, 191 | "mix_gain": 14, 192 | "rf_power": 27, 193 | "dig_gain": 0 194 | } 195 | }, 196 | 197 | "gateway_conf": { 198 | "gateway_ID": "AA555A0000000000", 199 | /* change with default server address/ports, or overwrite in local_conf.json */ 200 | "server_address": "127.0.0.1", 201 | "serv_port_up": 1680, 202 | "serv_port_down": 1680, 203 | /* adjust the following parameters for your network */ 204 | "keepalive_interval": 10, 205 | "stat_interval": 30, 206 | "push_timeout_ms": 100, 207 | /* forward only valid packets */ 208 | "forward_crc_valid": true, 209 | "forward_crc_error": false, 210 | "forward_crc_disabled": false, 211 | /* GPS configuration */ 212 | "gps_tty_path": "/dev/ttyAMA0" 213 | } 214 | } 215 | -------------------------------------------------------------------------------- /gps_pkt_fwd/global_conf.json: -------------------------------------------------------------------------------- 1 | { 2 | "SX1301_conf": { 3 | "lorawan_public": true, 4 | "clksrc": 1, /* radio_1 provides clock to concentrator */ 5 | "radio_0": { 6 | "enable": true, 7 | "type": "SX1257", 8 | "freq": 867500000, 9 | "rssi_offset": -166.0, 10 | "tx_enable": true 11 | }, 12 | "radio_1": { 13 | "enable": true, 14 | "type": "SX1257", 15 | "freq": 868500000, 16 | "rssi_offset": -166.0, 17 | "tx_enable": false 18 | }, 19 | "chan_multiSF_0": { 20 | /* Lora MAC channel, 125kHz, all SF, 868.1 MHz */ 21 | "enable": true, 22 | "radio": 1, 23 | "if": -400000 24 | }, 25 | "chan_multiSF_1": { 26 | /* Lora MAC channel, 125kHz, all SF, 868.3 MHz */ 27 | "enable": true, 28 | "radio": 1, 29 | "if": -200000 30 | }, 31 | "chan_multiSF_2": { 32 | /* Lora MAC channel, 125kHz, all SF, 868.5 MHz */ 33 | "enable": true, 34 | "radio": 1, 35 | "if": 0 36 | }, 37 | "chan_multiSF_3": { 38 | /* Lora MAC channel, 125kHz, all SF, 867.1 MHz */ 39 | "enable": true, 40 | "radio": 0, 41 | "if": -400000 42 | }, 43 | "chan_multiSF_4": { 44 | /* Lora MAC channel, 125kHz, all SF, 867.3 MHz */ 45 | "enable": true, 46 | "radio": 0, 47 | "if": -200000 48 | }, 49 | "chan_multiSF_5": { 50 | /* Lora MAC channel, 125kHz, all SF, 867.5 MHz */ 51 | "enable": true, 52 | "radio": 0, 53 | "if": 0 54 | }, 55 | "chan_multiSF_6": { 56 | /* Lora MAC channel, 125kHz, all SF, 867.7 MHz */ 57 | "enable": true, 58 | "radio": 0, 59 | "if": 200000 60 | }, 61 | "chan_multiSF_7": { 62 | /* Lora MAC channel, 125kHz, all SF, 867.9 MHz */ 63 | "enable": true, 64 | "radio": 0, 65 | "if": 400000 66 | }, 67 | "chan_Lora_std": { 68 | /* Lora MAC channel, 250kHz, SF7, 868.3 MHz */ 69 | "enable": true, 70 | "radio": 1, 71 | "if": -200000, 72 | "bandwidth": 250000, 73 | "spread_factor": 7 74 | }, 75 | "chan_FSK": { 76 | /* FSK 50kbps channel, 868.8 MHz */ 77 | "enable": true, 78 | "radio": 1, 79 | "if": 300000, 80 | "bandwidth": 125000, 81 | "datarate": 50000 82 | }, 83 | "tx_lut_0": { 84 | /* TX gain table, index 0 */ 85 | "pa_gain": 0, 86 | "mix_gain": 8, 87 | "rf_power": -6, 88 | "dig_gain": 0 89 | }, 90 | "tx_lut_1": { 91 | /* TX gain table, index 1 */ 92 | "pa_gain": 0, 93 | "mix_gain": 10, 94 | "rf_power": -3, 95 | "dig_gain": 0 96 | }, 97 | "tx_lut_2": { 98 | /* TX gain table, index 2 */ 99 | "pa_gain": 0, 100 | "mix_gain": 12, 101 | "rf_power": 0, 102 | "dig_gain": 0 103 | }, 104 | "tx_lut_3": { 105 | /* TX gain table, index 3 */ 106 | "pa_gain": 1, 107 | "mix_gain": 8, 108 | "rf_power": 3, 109 | "dig_gain": 0 110 | }, 111 | "tx_lut_4": { 112 | /* TX gain table, index 4 */ 113 | "pa_gain": 1, 114 | "mix_gain": 10, 115 | "rf_power": 6, 116 | "dig_gain": 0 117 | }, 118 | "tx_lut_5": { 119 | /* TX gain table, index 5 */ 120 | "pa_gain": 1, 121 | "mix_gain": 12, 122 | "rf_power": 10, 123 | "dig_gain": 0 124 | }, 125 | "tx_lut_6": { 126 | /* TX gain table, index 6 */ 127 | "pa_gain": 1, 128 | "mix_gain": 13, 129 | "rf_power": 11, 130 | "dig_gain": 0 131 | }, 132 | "tx_lut_7": { 133 | /* TX gain table, index 7 */ 134 | "pa_gain": 2, 135 | "mix_gain": 9, 136 | "rf_power": 12, 137 | "dig_gain": 0 138 | }, 139 | "tx_lut_8": { 140 | /* TX gain table, index 8 */ 141 | "pa_gain": 1, 142 | "mix_gain": 15, 143 | "rf_power": 13, 144 | "dig_gain": 0 145 | }, 146 | "tx_lut_9": { 147 | /* TX gain table, index 9 */ 148 | "pa_gain": 2, 149 | "mix_gain": 10, 150 | "rf_power": 14, 151 | "dig_gain": 0 152 | }, 153 | "tx_lut_10": { 154 | /* TX gain table, index 10 */ 155 | "pa_gain": 2, 156 | "mix_gain": 11, 157 | "rf_power": 16, 158 | "dig_gain": 0 159 | }, 160 | "tx_lut_11": { 161 | /* TX gain table, index 11 */ 162 | "pa_gain": 3, 163 | "mix_gain": 9, 164 | "rf_power": 20, 165 | "dig_gain": 0 166 | }, 167 | "tx_lut_12": { 168 | /* TX gain table, index 12 */ 169 | "pa_gain": 3, 170 | "mix_gain": 10, 171 | "rf_power": 23, 172 | "dig_gain": 0 173 | }, 174 | "tx_lut_13": { 175 | /* TX gain table, index 13 */ 176 | "pa_gain": 3, 177 | "mix_gain": 11, 178 | "rf_power": 25, 179 | "dig_gain": 0 180 | }, 181 | "tx_lut_14": { 182 | /* TX gain table, index 14 */ 183 | "pa_gain": 3, 184 | "mix_gain": 12, 185 | "rf_power": 26, 186 | "dig_gain": 0 187 | }, 188 | "tx_lut_15": { 189 | /* TX gain table, index 15 */ 190 | "pa_gain": 3, 191 | "mix_gain": 14, 192 | "rf_power": 27, 193 | "dig_gain": 0 194 | } 195 | }, 196 | 197 | "gateway_conf": { 198 | "gateway_ID": "AA555A0000000000", 199 | /* change with default server address/ports, or overwrite in local_conf.json */ 200 | "server_address": "127.0.0.1", 201 | "serv_port_up": 1680, 202 | "serv_port_down": 1680, 203 | /* adjust the following parameters for your network */ 204 | "keepalive_interval": 10, 205 | "stat_interval": 30, 206 | "push_timeout_ms": 100, 207 | /* forward only valid packets */ 208 | "forward_crc_valid": true, 209 | "forward_crc_error": false, 210 | "forward_crc_disabled": false, 211 | /* GPS configuration */ 212 | "gps_tty_path": "/dev/ttyAMA0" 213 | } 214 | } 215 | 216 | -------------------------------------------------------------------------------- /util_ack/src/util_ack.c: -------------------------------------------------------------------------------- 1 | /* 2 | / _____) _ | | 3 | ( (____ _____ ____ _| |_ _____ ____| |__ 4 | \____ \| ___ | (_ _) ___ |/ ___) _ \ 5 | _____) ) ____| | | || |_| ____( (___| | | | 6 | (______/|_____)_|_|_| \__)_____)\____)_| |_| 7 | (C)2013 Semtech-Cycleo 8 | 9 | Description: 10 | Network sink, receives UDP packets and sends an acknowledge 11 | 12 | License: Revised BSD License, see LICENSE.TXT file include in the project 13 | Maintainer: Sylvain Miermont 14 | */ 15 | 16 | 17 | /* -------------------------------------------------------------------------- */ 18 | /* --- DEPENDANCIES --------------------------------------------------------- */ 19 | 20 | /* fix an issue between POSIX and C99 */ 21 | #if __STDC_VERSION__ >= 199901L 22 | #define _XOPEN_SOURCE 600 23 | #else 24 | #define _XOPEN_SOURCE 500 25 | #endif 26 | 27 | #include /* C99 types */ 28 | #include /* printf, fprintf, sprintf, fopen, fputs */ 29 | #include /* usleep */ 30 | 31 | #include /* memset */ 32 | #include /* time, clock_gettime, strftime, gmtime, clock_nanosleep*/ 33 | #include /* atoi, exit */ 34 | #include /* error messages */ 35 | 36 | #include /* socket specific definitions */ 37 | #include /* INET constants and stuff */ 38 | #include /* IP address conversion stuff */ 39 | #include /* gai_strerror */ 40 | 41 | /* -------------------------------------------------------------------------- */ 42 | /* --- PRIVATE MACROS ------------------------------------------------------- */ 43 | 44 | #define ARRAY_SIZE(a) (sizeof(a) / sizeof((a)[0])) 45 | #define STRINGIFY(x) #x 46 | #define STR(x) STRINGIFY(x) 47 | #define MSG(args...) fprintf(stderr, args) /* message that is destined to the user */ 48 | 49 | /* -------------------------------------------------------------------------- */ 50 | /* --- PRIVATE CONSTANTS ---------------------------------------------------- */ 51 | 52 | #define PROTOCOL_VERSION 1 53 | 54 | #define PKT_PUSH_DATA 0 55 | #define PKT_PUSH_ACK 1 56 | #define PKT_PULL_DATA 2 57 | #define PKT_PULL_RESP 3 58 | #define PKT_PULL_ACK 4 59 | 60 | /* -------------------------------------------------------------------------- */ 61 | /* --- MAIN FUNCTION -------------------------------------------------------- */ 62 | 63 | int main(int argc, char **argv) 64 | { 65 | int i; /* loop variable and temporary variable for return value */ 66 | 67 | /* server socket creation */ 68 | int sock; /* socket file descriptor */ 69 | struct addrinfo hints; 70 | struct addrinfo *result; /* store result of getaddrinfo */ 71 | struct addrinfo *q; /* pointer to move into *result data */ 72 | char host_name[64]; 73 | char port_name[64]; 74 | 75 | /* variables for receiving and sending packets */ 76 | struct sockaddr_storage dist_addr; 77 | socklen_t addr_len = sizeof dist_addr; 78 | uint8_t databuf[4096]; 79 | int byte_nb; 80 | 81 | /* variables for protocol management */ 82 | uint32_t raw_mac_h; /* Most Significant Nibble, network order */ 83 | uint32_t raw_mac_l; /* Least Significant Nibble, network order */ 84 | uint64_t gw_mac; /* MAC address of the client (gateway) */ 85 | uint8_t ack_command; 86 | 87 | /* check if port number was passed as parameter */ 88 | if (argc != 2) { 89 | MSG("Usage: util_ack \n"); 90 | exit(EXIT_FAILURE); 91 | } 92 | 93 | /* prepare hints to open network sockets */ 94 | memset(&hints, 0, sizeof hints); 95 | hints.ai_family = AF_UNSPEC; /* should handle IP v4 or v6 automatically */ 96 | hints.ai_socktype = SOCK_DGRAM; 97 | hints.ai_flags = AI_PASSIVE; /* will assign local IP automatically */ 98 | 99 | /* look for address */ 100 | i = getaddrinfo(NULL, argv[1], &hints, &result); 101 | if (i != 0) { 102 | MSG("ERROR: getaddrinfo returned %s\n", gai_strerror(i)); 103 | exit(EXIT_FAILURE); 104 | } 105 | 106 | /* try to open socket and bind it */ 107 | for (q=result; q!=NULL; q=q->ai_next) { 108 | sock = socket(q->ai_family, q->ai_socktype,q->ai_protocol); 109 | if (sock == -1) { 110 | continue; /* socket failed, try next field */ 111 | } else { 112 | i = bind(sock, q->ai_addr, q->ai_addrlen); 113 | if (i == -1) { 114 | shutdown(sock, SHUT_RDWR); 115 | continue; /* bind failed, try next field */ 116 | } else { 117 | break; /* success, get out of loop */ 118 | } 119 | } 120 | } 121 | if (q == NULL) { 122 | MSG("ERROR: failed to open socket or to bind to it\n"); 123 | i = 1; 124 | for (q=result; q!=NULL; q=q->ai_next) { 125 | getnameinfo(q->ai_addr, q->ai_addrlen, host_name, sizeof host_name, port_name, sizeof port_name, NI_NUMERICHOST); 126 | MSG("INFO: result %i host:%s service:%s\n", i, host_name, port_name); 127 | ++i; 128 | } 129 | exit(EXIT_FAILURE); 130 | } 131 | MSG("INFO: util_ack listening on port %s\n", argv[1]); 132 | freeaddrinfo(result); 133 | 134 | while (1) { 135 | /* wait to receive a packet */ 136 | byte_nb = recvfrom(sock, databuf, sizeof databuf, 0, (struct sockaddr *)&dist_addr, &addr_len); 137 | if (byte_nb == -1) { 138 | MSG("ERROR: recvfrom returned %s \n", strerror(errno)); 139 | exit(EXIT_FAILURE); 140 | } 141 | 142 | /* display info about the sender */ 143 | i = getnameinfo((struct sockaddr *)&dist_addr, addr_len, host_name, sizeof host_name, port_name, sizeof port_name, NI_NUMERICHOST); 144 | if (i == -1) { 145 | MSG("ERROR: getnameinfo returned %s \n", gai_strerror(i)); 146 | exit(EXIT_FAILURE); 147 | } 148 | printf(" -> pkt in , host %s (port %s), %i bytes", host_name, port_name, byte_nb); 149 | 150 | /* check and parse the payload */ 151 | if (byte_nb < 12) { /* not enough bytes for packet from gateway */ 152 | printf(" (too short for GW <-> MAC protocol)\n"); 153 | continue; 154 | } 155 | /* don't touch the token in position 1-2, it will be sent back "as is" for acknowledgement */ 156 | if (databuf[0] != PROTOCOL_VERSION) { /* check protocol version number */ 157 | printf(", invalid version %u\n", databuf[0]); 158 | continue; 159 | } 160 | raw_mac_h = *((uint32_t *)(databuf+4)); 161 | raw_mac_l = *((uint32_t *)(databuf+8)); 162 | gw_mac = ((uint64_t)ntohl(raw_mac_h) << 32) + (uint64_t)ntohl(raw_mac_l); 163 | 164 | /* interpret gateway command */ 165 | switch (databuf[3]) { 166 | case PKT_PUSH_DATA: 167 | printf(", PUSH_DATA from gateway 0x%08X%08X\n", (uint32_t)(gw_mac >> 32), (uint32_t)(gw_mac & 0xFFFFFFFF)); 168 | ack_command = PKT_PUSH_ACK; 169 | printf("<- pkt out, PUSH_ACK for host %s (port %s)", host_name, port_name); 170 | break; 171 | case PKT_PULL_DATA: 172 | printf(", PULL_DATA from gateway 0x%08X%08X\n", (uint32_t)(gw_mac >> 32), (uint32_t)(gw_mac & 0xFFFFFFFF)); 173 | ack_command = PKT_PULL_ACK; 174 | printf("<- pkt out, PULL_ACK for host %s (port %s)", host_name, port_name); 175 | break; 176 | default: 177 | printf(", unexpected command %u\n", databuf[3]); 178 | continue; 179 | } 180 | 181 | /* add some artificial latency */ 182 | usleep(30000); /* 30 ms */ 183 | 184 | /* send acknowledge and check return value */ 185 | databuf[3] = ack_command; 186 | byte_nb = sendto(sock, (void *)databuf, 4, 0, (struct sockaddr *)&dist_addr, addr_len); 187 | if (byte_nb == -1) { 188 | printf(", send error:%s\n", strerror(errno)); 189 | } else { 190 | printf(", %i bytes sent\n", byte_nb); 191 | } 192 | } 193 | } 194 | -------------------------------------------------------------------------------- /basic_pkt_fwd/readme.md: -------------------------------------------------------------------------------- 1 | / _____) _ | | 2 | ( (____ _____ ____ _| |_ _____ ____| |__ 3 | \____ \| ___ | (_ _) ___ |/ ___) _ \ 4 | _____) ) ____| | | || |_| ____( (___| | | | 5 | (______/|_____)_|_|_| \__)_____)\____)_| |_| 6 | (C)2013 Semtech-Cycleo 7 | 8 | Lora Gateway basic packet forwarder 9 | ==================================== 10 | 11 | 1. Introduction 12 | ---------------- 13 | 14 | The basic packet forwarder is a program running on the host of a Lora Gateway 15 | that forward RF packets receive by the concentrator to a server through a 16 | IP/UDP link, and emits RF packets that are sent by the server. 17 | 18 | To learn more about the network protocol between the gateway and the server, 19 | please read the PROTOCOL.TXT document. 20 | 21 | 2. System schematic and definitions 22 | ------------------------------------ 23 | 24 | ((( Y ))) 25 | | 26 | | 27 | +- -|- - - - - - - - - - - - -+ xxxxxxxxxxxx +--------+ 28 | |+--+-----------+ +------+| xx x x xxx | | 29 | || | | || xx Internet xx | | 30 | || Concentrator |<----+ Host |<------xx or xx-------->| | 31 | || | SPI | || xx Intranet xx | Server | 32 | |+--------------+ +------+| xxxx x xxxx | | 33 | | | xxxxxxxx | | 34 | | Gateway | | | 35 | +- - - - - - - - - - - - - - -+ +--------+ 36 | 37 | Concentrator: radio RX/TX board, based on Semtech multichannel modems (SX130x), 38 | transceivers (SX135x) and/or low-power stand-alone modems (SX127x). 39 | 40 | Host: embedded computer on which the packet forwarder is run. Drives the 41 | concentrator through a SPI link. 42 | 43 | Gateway: a device composed of at least one radio concentrator, a host, some 44 | network connection to the internet or a private network (Ethernet, 3G, Wifi, 45 | microwave link), and optionally a GPS receiver for synchronization. 46 | 47 | Server: an abstract computer that will process the RF packets received and 48 | forwarded by the gateway, and issue RF packets in response that the gateway 49 | will have to emit. 50 | 51 | 52 | 3. Dependencies 53 | ---------------- 54 | 55 | This program uses the Parson library (http://kgabis.github.com/parson/) by 56 | Krzysztof Gabis for JSON parsing. 57 | Many thanks to him for that very practical and well written library. 58 | 59 | This program is statically linked with the libloragw Lora concentrator library. 60 | It was tested with v1.3.0 of the library but should work with any later 61 | version provided the API is v1 or a later backward-compatible API. 62 | Data structures of the received packets are accessed by name (ie. not at a 63 | binary level) so new functionalities can be added to the API without affecting 64 | that program at all. 65 | 66 | This program follows the v1.0 version of the gateway-to-server protocol. 67 | 68 | The last dependency is the hardware concentrator (based on FPGA or SX130x 69 | chips) that must be matched with the proper version of the HAL. 70 | 71 | 4. Usage 72 | --------- 73 | 74 | To stop the application, press Ctrl+C. 75 | Unless it is manually stopped or encounter a critical error, the program will 76 | run forever. 77 | 78 | There are no command line launch options. 79 | 80 | The way the program takes configuration files into account is the following: 81 | * if there is a debug_conf.json parse it, others are ignored 82 | * if there is a global_conf.json parse it, look for the next file 83 | * if there is a local_conf.json parse it 84 | If some parameters are defined in both global and local configuration files, 85 | the local definition overwrites the global definition. 86 | 87 | The global configuration file should be exactly the same throughout your 88 | network, contain all global parameters (parameters for "sensor" radio 89 | channels) and preferably default "safe" values for parameters that are 90 | specific for each gateway (eg. specify a default MAC address). 91 | 92 | The local configuration file should contain parameters that are specific to 93 | each gateway (eg. MAC address, frequency for backhaul radio channels). 94 | 95 | In each configuration file, the program looks for a JSON object named 96 | "SX1301_conf" that should contain the parameters for the Lora concentrator 97 | board (RF channels definition, modem parameters, etc) and another JSON object 98 | called "gateway_conf" that should contain the gateway parameters (gateway MAC 99 | address, IP address of the server, keep-alive time, etc). 100 | 101 | To learn more about the JSON configuration format, read the provided JSON 102 | files and the libloragw API documentation. 103 | 104 | Every X seconds (parameter settable in the configuration files) the program 105 | display statistics on the RF packets received and sent, and the network 106 | datagrams received and sent. 107 | 108 | This basic variant of the packet forwarder does not send status report to the 109 | server. 110 | 111 | 5. License 112 | ----------- 113 | 114 | Copyright (C) 2013, SEMTECH S.A. 115 | All rights reserved. 116 | 117 | Redistribution and use in source and binary forms, with or without 118 | modification, are permitted provided that the following conditions are met: 119 | 120 | * Redistributions of source code must retain the above copyright 121 | notice, this list of conditions and the following disclaimer. 122 | * Redistributions in binary form must reproduce the above copyright 123 | notice, this list of conditions and the following disclaimer in the 124 | documentation and/or other materials provided with the distribution. 125 | * Neither the name of the Semtech corporation nor the 126 | names of its contributors may be used to endorse or promote products 127 | derived from this software without specific prior written permission. 128 | 129 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND 130 | ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 131 | WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 132 | DISCLAIMED. IN NO EVENT SHALL SEMTECH S.A. BE LIABLE FOR ANY 133 | DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 134 | (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 135 | LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND 136 | ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 137 | (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 138 | SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 139 | 140 | 6. License for Parson library 141 | ------------------------------ 142 | 143 | Parson ( http://kgabis.github.com/parson/ ) 144 | Copyright (C) 2012 Krzysztof Gabis 145 | 146 | Permission is hereby granted, free of charge, to any person obtaining a copy 147 | of this software and associated documentation files (the "Software"), to deal 148 | in the Software without restriction, including without limitation the rights 149 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 150 | copies of the Software, and to permit persons to whom the Software is 151 | furnished to do so, subject to the following conditions: 152 | 153 | The above copyright notice and this permission notice shall be included in 154 | all copies or substantial portions of the Software. 155 | 156 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 157 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 158 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 159 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 160 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 161 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 162 | THE SOFTWARE. 163 | 164 | *EOF* 165 | -------------------------------------------------------------------------------- /gps_pkt_fwd/readme.md: -------------------------------------------------------------------------------- 1 | / _____) _ | | 2 | ( (____ _____ ____ _| |_ _____ ____| |__ 3 | \____ \| ___ | (_ _) ___ |/ ___) _ \ 4 | _____) ) ____| | | || |_| ____( (___| | | | 5 | (______/|_____)_|_|_| \__)_____)\____)_| |_| 6 | (C)2013 Semtech-Cycleo 7 | 8 | Lora Gateway packet forwarder with GPS extensions 9 | ================================================== 10 | 11 | 1. Introduction 12 | ---------------- 13 | 14 | The GPS packet forwarder is a program running on the host of a Lora Gateway 15 | that forward RF packets receive by the concentrator to a server through a 16 | IP/UDP link, and emits RF packets that are sent by the server. 17 | 18 | To learn more about the network protocol between the gateway and the server, 19 | please read the PROTOCOL.TXT document. 20 | 21 | 2. System schematic and definitions 22 | ------------------------------------ 23 | 24 | ((( Y ))) 25 | | 26 | | 27 | +- -|- - - - - - - - - - - - -+ xxxxxxxxxxxx +--------+ 28 | |+--+-----------+ +------+| xx x x xxx | | 29 | || | | || xx Internet xx | | 30 | || Concentrator |<----+ Host |<------xx or xx-------->| | 31 | || | SPI | || xx Intranet xx | Server | 32 | |+--------------+ +------+| xxxx x xxxx | | 33 | | ^ ^ | xxxxxxxx | | 34 | | | PPS +-----+ NMEA | | | | 35 | | +------| GPS |-------+ | +--------+ 36 | | +-----+ | 37 | | | 38 | | Gateway | 39 | +- - - - - - - - - - - - - - -+ 40 | 41 | Concentrator: radio RX/TX board, based on Semtech multichannel modems (SX130x), 42 | transceivers (SX135x) and/or low-power stand-alone modems (SX127x). 43 | 44 | Host: embedded computer on which the packet forwarder is run. Drives the 45 | concentrator through a SPI link. 46 | 47 | Gateway: a device composed of at least one radio concentrator, a host, some 48 | network connection to the internet or a private network (Ethernet, 3G, Wifi, 49 | microwave link), and optionally a GPS receiver for synchronization. 50 | 51 | Server: an abstract computer that will process the RF packets received and 52 | forwarded by the gateway, and issue RF packets in response that the gateway 53 | will have to emit. 54 | 55 | 56 | 3. Dependencies 57 | ---------------- 58 | 59 | This program uses the Parson library (http://kgabis.github.com/parson/) by 60 | Krzysztof Gabis for JSON parsing. 61 | Many thanks to him for that very practical and well written library. 62 | 63 | This program is statically linked with the libloragw Lora concentrator library. 64 | It was tested with v1.3.0 of the library but should work with any later 65 | version provided the API is v1 or a later backward-compatible API. 66 | Data structures of the received packets are accessed by name (ie. not at a 67 | binary level) so new functionalities can be added to the API without affecting 68 | that program at all. 69 | 70 | This program follows the v1.1 version of the gateway-to-server protocol. 71 | 72 | The last dependency is the hardware concentrator (based on FPGA or SX130x 73 | chips) that must be matched with the proper version of the HAL. 74 | 75 | 4. Usage 76 | --------- 77 | 78 | To stop the application, press Ctrl+C. 79 | Unless it is manually stopped or encounter a critical error, the program will 80 | run forever. 81 | 82 | There are no command line launch options. 83 | 84 | The way the program takes configuration files into account is the following: 85 | * if there is a debug_conf.json parse it, others are ignored 86 | * if there is a global_conf.json parse it, look for the next file 87 | * if there is a local_conf.json parse it 88 | If some parameters are defined in both global and local configuration files, 89 | the local definition overwrites the global definition. 90 | 91 | The global configuration file should be exactly the same throughout your 92 | network, contain all global parameters (parameters for "sensor" radio 93 | channels) and preferably default "safe" values for parameters that are 94 | specific for each gateway (eg. specify a default MAC address). 95 | 96 | The local configuration file should contain parameters that are specific to 97 | each gateway (eg. MAC address, frequency for backhaul radio channels). 98 | 99 | In each configuration file, the program looks for a JSON object named 100 | "SX1301_conf" that should contain the parameters for the Lora concentrator 101 | board (RF channels definition, modem parameters, etc) and another JSON object 102 | called "gateway_conf" that should contain the gateway parameters (gateway MAC 103 | address, IP address of the server, keep-alive time, etc). 104 | 105 | To learn more about the JSON configuration format, read the provided JSON 106 | files and the libloragw API documentation. 107 | 108 | Every X seconds (parameter settable in the configuration files) the program 109 | display statistics on the RF packets received and sent, and the network 110 | datagrams received and sent. 111 | The program also send some statistics to the server in JSON format. 112 | 113 | 5. License 114 | ----------- 115 | 116 | Copyright (C) 2013, SEMTECH S.A. 117 | All rights reserved. 118 | 119 | Redistribution and use in source and binary forms, with or without 120 | modification, are permitted provided that the following conditions are met: 121 | 122 | * Redistributions of source code must retain the above copyright 123 | notice, this list of conditions and the following disclaimer. 124 | * Redistributions in binary form must reproduce the above copyright 125 | notice, this list of conditions and the following disclaimer in the 126 | documentation and/or other materials provided with the distribution. 127 | * Neither the name of the Semtech corporation nor the 128 | names of its contributors may be used to endorse or promote products 129 | derived from this software without specific prior written permission. 130 | 131 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND 132 | ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 133 | WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 134 | DISCLAIMED. IN NO EVENT SHALL SEMTECH S.A. BE LIABLE FOR ANY 135 | DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 136 | (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 137 | LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND 138 | ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 139 | (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 140 | SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 141 | 142 | 6. License for Parson library 143 | ------------------------------ 144 | 145 | Parson ( http://kgabis.github.com/parson/ ) 146 | Copyright (C) 2012 Krzysztof Gabis 147 | 148 | Permission is hereby granted, free of charge, to any person obtaining a copy 149 | of this software and associated documentation files (the "Software"), to deal 150 | in the Software without restriction, including without limitation the rights 151 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 152 | copies of the Software, and to permit persons to whom the Software is 153 | furnished to do so, subject to the following conditions: 154 | 155 | The above copyright notice and this permission notice shall be included in 156 | all copies or substantial portions of the Software. 157 | 158 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 159 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 160 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 161 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 162 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 163 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 164 | THE SOFTWARE. 165 | 166 | *EOF* 167 | -------------------------------------------------------------------------------- /beacon_pkt_fwd/readme.md: -------------------------------------------------------------------------------- 1 | / _____) _ | | 2 | ( (____ _____ ____ _| |_ _____ ____| |__ 3 | \____ \| ___ | (_ _) ___ |/ ___) _ \ 4 | _____) ) ____| | | || |_| ____( (___| | | | 5 | (______/|_____)_|_|_| \__)_____)\____)_| |_| 6 | (C)2013 Semtech-Cycleo 7 | 8 | Lora Gateway packet forwarder with beacon extension 9 | ===================================================== 10 | 11 | 1. Introduction 12 | ---------------- 13 | 14 | The beaconing packet forwarder is a program running on the host of a Lora 15 | Gateway that forward RF packets receive by the concentrator to a server 16 | through a IP/UDP link, and emits RF packets that are sent by the server. It 17 | also emits a network-wide GPS-synchronous beacon signal used for coordinating 18 | all the nodes of the network. 19 | 20 | To learn more about the network protocol between the gateway and the server, 21 | please read the PROTOCOL.TXT document. 22 | 23 | 2. System schematic and definitions 24 | ------------------------------------ 25 | 26 | ((( Y ))) 27 | | 28 | | 29 | +- -|- - - - - - - - - - - - -+ xxxxxxxxxxxx +--------+ 30 | |+--+-----------+ +------+| xx x x xxx | | 31 | || | | || xx Internet xx | | 32 | || Concentrator |<----+ Host |<------xx or xx-------->| | 33 | || | SPI | || xx Intranet xx | Server | 34 | |+--------------+ +------+| xxxx x xxxx | | 35 | | ^ ^ | xxxxxxxx | | 36 | | | PPS +-----+ NMEA | | | | 37 | | +------| GPS |-------+ | +--------+ 38 | | +-----+ | 39 | | | 40 | | Gateway | 41 | +- - - - - - - - - - - - - - -+ 42 | 43 | Concentrator: radio RX/TX board, based on Semtech multichannel modems (SX130x), 44 | transceivers (SX135x) and/or low-power stand-alone modems (SX127x). 45 | 46 | Host: embedded computer on which the packet forwarder is run. Drives the 47 | concentrator through a SPI link. 48 | 49 | Gateway: a device composed of at least one radio concentrator, a host, some 50 | network connection to the internet or a private network (Ethernet, 3G, Wifi, 51 | microwave link), and optionally a GPS receiver for synchronization. 52 | 53 | Server: an abstract computer that will process the RF packets received and 54 | forwarded by the gateway, and issue RF packets in response that the gateway 55 | will have to emit. 56 | 57 | 58 | 3. Dependencies 59 | ---------------- 60 | 61 | This program uses the Parson library (http://kgabis.github.com/parson/) by 62 | Krzysztof Gabis for JSON parsing. 63 | Many thanks to him for that very practical and well written library. 64 | 65 | This program is statically linked with the libloragw Lora concentrator library. 66 | It was tested with v1.3.0 of the library but should work with any later 67 | version provided the API is v1 or a later backward-compatible API. 68 | Data structures of the received packets are accessed by name (ie. not at a 69 | binary level) so new functionalities can be added to the API without affecting 70 | that program at all. 71 | 72 | This program follows the v1.1 version of the gateway-to-server protocol. 73 | 74 | The last dependency is the hardware concentrator (based on FPGA or SX130x 75 | chips) that must be matched with the proper version of the HAL. 76 | 77 | 4. Usage 78 | --------- 79 | 80 | To stop the application, press Ctrl+C. 81 | Unless it is manually stopped or encounter a critical error, the program will 82 | run forever. 83 | 84 | There are no command line launch options. 85 | 86 | The way the program takes configuration files into account is the following: 87 | * if there is a debug_conf.json parse it, others are ignored 88 | * if there is a global_conf.json parse it, look for the next file 89 | * if there is a local_conf.json parse it 90 | If some parameters are defined in both global and local configuration files, 91 | the local definition overwrites the global definition. 92 | 93 | The global configuration file should be exactly the same throughout your 94 | network, contain all global parameters (parameters for "sensor" radio 95 | channels) and preferably default "safe" values for parameters that are 96 | specific for each gateway (eg. specify a default MAC address). 97 | 98 | The local configuration file should contain parameters that are specific to 99 | each gateway (eg. MAC address, frequency for backhaul radio channels). 100 | 101 | In each configuration file, the program looks for a JSON object named 102 | "SX1301_conf" that should contain the parameters for the Lora concentrator 103 | board (RF channels definition, modem parameters, etc) and another JSON object 104 | called "gateway_conf" that should contain the gateway parameters (gateway MAC 105 | address, IP address of the server, keep-alive time, etc). 106 | 107 | To learn more about the JSON configuration format, read the provided JSON 108 | files and the libloragw API documentation. 109 | 110 | Every X seconds (parameter settable in the configuration files) the program 111 | display statistics on the RF packets received and sent, and the network 112 | datagrams received and sent. 113 | The program also send some statistics to the server in JSON format. 114 | 115 | 5. License 116 | ----------- 117 | 118 | Copyright (C) 2013, SEMTECH S.A. 119 | All rights reserved. 120 | 121 | Redistribution and use in source and binary forms, with or without 122 | modification, are permitted provided that the following conditions are met: 123 | 124 | * Redistributions of source code must retain the above copyright 125 | notice, this list of conditions and the following disclaimer. 126 | * Redistributions in binary form must reproduce the above copyright 127 | notice, this list of conditions and the following disclaimer in the 128 | documentation and/or other materials provided with the distribution. 129 | * Neither the name of the Semtech corporation nor the 130 | names of its contributors may be used to endorse or promote products 131 | derived from this software without specific prior written permission. 132 | 133 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND 134 | ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 135 | WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 136 | DISCLAIMED. IN NO EVENT SHALL SEMTECH S.A. BE LIABLE FOR ANY 137 | DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 138 | (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 139 | LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND 140 | ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 141 | (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 142 | SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 143 | 144 | 6. License for Parson library 145 | ------------------------------ 146 | 147 | Parson ( http://kgabis.github.com/parson/ ) 148 | Copyright (C) 2012 Krzysztof Gabis 149 | 150 | Permission is hereby granted, free of charge, to any person obtaining a copy 151 | of this software and associated documentation files (the "Software"), to deal 152 | in the Software without restriction, including without limitation the rights 153 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 154 | copies of the Software, and to permit persons to whom the Software is 155 | furnished to do so, subject to the following conditions: 156 | 157 | The above copyright notice and this permission notice shall be included in 158 | all copies or substantial portions of the Software. 159 | 160 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 161 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 162 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 163 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 164 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 165 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 166 | THE SOFTWARE. 167 | 168 | *EOF* 169 | -------------------------------------------------------------------------------- /poly_pkt_fwd/global_conf_multitech-us915.json: -------------------------------------------------------------------------------- 1 | { 2 | "SX1301_conf": { 3 | "lorawan_public": true, 4 | "clksrc": 0, /* radio_1 provides clock to concentrator */ 5 | "radio_0": { 6 | "enable": true, 7 | "type": "SX1257", 8 | "freq": 912200000, 9 | "rssi_offset": -166.0, 10 | "tx_enable": true 11 | }, 12 | "radio_1": { 13 | "enable": false, 14 | "type": "SX1257", 15 | "freq": 913000000, 16 | "rssi_offset": -166.0, 17 | "tx_enable": false 18 | }, 19 | "chan_multiSF_0": { 20 | "enable": true, 21 | "radio": 0, 22 | "if": -300000 23 | }, 24 | "chan_multiSF_1": { 25 | "enable": true, 26 | "radio": 0, 27 | "if": -100000 28 | }, 29 | "chan_multiSF_2": { 30 | "enable": true, 31 | "radio": 0, 32 | "if": 100000 33 | }, 34 | "chan_multiSF_3": { 35 | "enable": true, 36 | "radio": 0, 37 | "if": 300000 38 | }, 39 | "chan_multiSF_4": { 40 | "enable": true, 41 | "radio": 1, 42 | "if": -300000 43 | }, 44 | "chan_multiSF_5": { 45 | "enable": true, 46 | "radio": 1, 47 | "if": -100000 48 | }, 49 | "chan_multiSF_6": { 50 | "enable": true, 51 | "radio": 1, 52 | "if": 100000 53 | }, 54 | "chan_multiSF_7": { 55 | "enable": true, 56 | "radio": 1, 57 | "if": 300000 58 | }, 59 | "chan_Lora_std": { 60 | "enable": true, 61 | "radio": 0, 62 | "if": 400000, 63 | "bandwidth": 500000, 64 | "spread_factor": 8 65 | }, 66 | "chan_FSK": { 67 | "enable": true, 68 | "radio": 0, 69 | "if": 100000, 70 | "bandwidth": 250000, 71 | "datarate": 100000, 72 | "freq_deviation" : 25000 73 | }, 74 | "tx_lut_0": { 75 | /* TX gain table, index 0 */ 76 | "pa_gain": 0, 77 | "mix_gain": 8, 78 | "rf_power": -6, 79 | "dig_gain": 0 80 | }, 81 | "tx_lut_1": { 82 | /* TX gain table, index 1 */ 83 | "pa_gain": 0, 84 | "mix_gain": 10, 85 | "rf_power": -3, 86 | "dig_gain": 0 87 | }, 88 | "tx_lut_2": { 89 | /* TX gain table, index 2 */ 90 | "pa_gain": 0, 91 | "mix_gain": 12, 92 | "rf_power": 0, 93 | "dig_gain": 0 94 | }, 95 | "tx_lut_3": { 96 | /* TX gain table, index 3 */ 97 | "pa_gain": 1, 98 | "mix_gain": 8, 99 | "rf_power": 3, 100 | "dig_gain": 0 101 | }, 102 | "tx_lut_4": { 103 | /* TX gain table, index 4 */ 104 | "pa_gain": 1, 105 | "mix_gain": 10, 106 | "rf_power": 6, 107 | "dig_gain": 0 108 | }, 109 | "tx_lut_5": { 110 | /* TX gain table, index 5 */ 111 | "pa_gain": 1, 112 | "mix_gain": 12, 113 | "rf_power": 10, 114 | "dig_gain": 0 115 | }, 116 | "tx_lut_6": { 117 | /* TX gain table, index 6 */ 118 | "pa_gain": 1, 119 | "mix_gain": 13, 120 | "rf_power": 11, 121 | "dig_gain": 0 122 | }, 123 | "tx_lut_7": { 124 | /* TX gain table, index 7 */ 125 | "pa_gain": 2, 126 | "mix_gain": 9, 127 | "rf_power": 12, 128 | "dig_gain": 0 129 | }, 130 | "tx_lut_8": { 131 | /* TX gain table, index 8 */ 132 | "pa_gain": 1, 133 | "mix_gain": 15, 134 | "rf_power": 13, 135 | "dig_gain": 0 136 | }, 137 | "tx_lut_9": { 138 | /* TX gain table, index 9 */ 139 | "pa_gain": 2, 140 | "mix_gain": 10, 141 | "rf_power": 14, 142 | "dig_gain": 0 143 | }, 144 | "tx_lut_10": { 145 | /* TX gain table, index 10 */ 146 | "pa_gain": 2, 147 | "mix_gain": 11, 148 | "rf_power": 16, 149 | "dig_gain": 0 150 | }, 151 | "tx_lut_11": { 152 | /* TX gain table, index 11 */ 153 | "pa_gain": 3, 154 | "mix_gain": 10, 155 | "rf_power": 20, 156 | "dig_gain": 0 157 | }, 158 | "tx_lut_12": { 159 | /* TX gain table, index 12 */ 160 | "pa_gain": 3, 161 | "mix_gain": 11, 162 | "rf_power": 23, 163 | "dig_gain": 0 164 | }, 165 | "tx_lut_13": { 166 | /* TX gain table, index 13 */ 167 | "pa_gain": 3, 168 | "mix_gain": 12, 169 | "rf_power": 24, 170 | "dig_gain": 0 171 | }, 172 | "tx_lut_14": { 173 | /* TX gain table, index 14 */ 174 | "pa_gain": 3, 175 | "mix_gain": 13, 176 | "rf_power": 25, 177 | "dig_gain": 0 178 | }, 179 | "tx_lut_15": { 180 | /* TX gain table, index 15 */ 181 | "pa_gain": 3, 182 | "mix_gain": 15, 183 | "rf_power": 26, 184 | "dig_gain": 0 185 | } 186 | }, 187 | 188 | "gateway_conf": { 189 | /* change with default server address/ports, or overwrite in local_conf.json */ 190 | "gateway_ID": "AA555A0000000000", 191 | /* Devices */ 192 | "gps": true, 193 | "beacon": false, 194 | "monitor": false, 195 | "upstream": true, 196 | "downstream": true, 197 | "ghoststream": false, 198 | "radiostream": true, 199 | "statusstream": true, 200 | /* node server */ 201 | "server_address": "127.0.0.1", 202 | "serv_port_up": 1680, 203 | "serv_port_down": 1681, 204 | /* node servers for poly packet server (max 4) */ 205 | "servers": 206 | [ { "server_address": "127.0.0.1", 207 | "serv_port_up": 1680, 208 | "serv_port_down": 1681, 209 | "serv_enabled": false }, 210 | { /* "server_address": "us01-iot.semtech.com", */ 211 | "server_address": "12.13.93.141", 212 | "serv_port_up": 1780, 213 | "serv_port_down": 1780, 214 | "serv_enabled": true }, 215 | { /* "server_address": "croft.thethings.girovito.nl", */ 216 | "server_address": "54.72.145.119", 217 | "serv_port_up" : 1700, 218 | "serv_port_down" : 1700, 219 | "serv_enabled": true } ], 220 | /* adjust the following parameters for your network */ 221 | "keepalive_interval": 10, 222 | "stat_interval": 30, 223 | "push_timeout_ms": 100, 224 | /* forward only valid packets */ 225 | "forward_crc_valid": true, 226 | "forward_crc_error": false, 227 | "forward_crc_disabled": true, 228 | /* GPS configuration */ 229 | "gps_tty_path": "/dev/ttyAMA0", 230 | "fake_gps": false, 231 | "ref_latitude": 10, 232 | "ref_longitude": 20, 233 | "ref_altitude": -1, 234 | /* Ghost configuration */ 235 | "ghost_address": "127.0.0.1", 236 | "ghost_port": 1918, 237 | /* Monitor configuration */ 238 | "monitor_address": "127.0.0.1", 239 | "monitor_port": 2008, 240 | "ssh_path": "/usr/bin/ssh", 241 | "ssh_port": 22, 242 | "http_port": 80, 243 | "ngrok_path": "/usr/bin/ngrok", 244 | "system_calls": ["df -m","free -h","uptime","who -a","uname -a"], 245 | /* Platform definition, put a asterix here for the system value, max 24 chars. */ 246 | "platform": "*", 247 | /* Email of gateway operator, max 40 chars*/ 248 | "contact_email": "operator@gateway.tst", 249 | /* Public description of this device, max 64 chars */ 250 | "description": "Update me" 251 | } 252 | } 253 | -------------------------------------------------------------------------------- /poly_pkt_fwd/global_conf.json: -------------------------------------------------------------------------------- 1 | { 2 | "SX1301_conf": { 3 | "lorawan_public": true, 4 | "clksrc": 1, /* radio_1 provides clock to concentrator */ 5 | "radio_0": { 6 | "enable": true, 7 | "type": "SX1257", 8 | "freq": 867500000, 9 | "rssi_offset": -166.0, 10 | "tx_enable": true 11 | }, 12 | "radio_1": { 13 | "enable": true, 14 | "type": "SX1257", 15 | "freq": 868500000, 16 | "rssi_offset": -166.0, 17 | "tx_enable": false 18 | }, 19 | "chan_multiSF_0": { 20 | /* Lora MAC channel, 125kHz, all SF, 868.1 MHz */ 21 | "enable": true, 22 | "radio": 1, 23 | "if": -400000 24 | }, 25 | "chan_multiSF_1": { 26 | /* Lora MAC channel, 125kHz, all SF, 868.3 MHz */ 27 | "enable": true, 28 | "radio": 1, 29 | "if": -200000 30 | }, 31 | "chan_multiSF_2": { 32 | /* Lora MAC channel, 125kHz, all SF, 868.5 MHz */ 33 | "enable": true, 34 | "radio": 1, 35 | "if": 0 36 | }, 37 | "chan_multiSF_3": { 38 | /* Lora MAC channel, 125kHz, all SF, 867.1 MHz */ 39 | "enable": true, 40 | "radio": 0, 41 | "if": -400000 42 | }, 43 | "chan_multiSF_4": { 44 | /* Lora MAC channel, 125kHz, all SF, 867.3 MHz */ 45 | "enable": true, 46 | "radio": 0, 47 | "if": -200000 48 | }, 49 | "chan_multiSF_5": { 50 | /* Lora MAC channel, 125kHz, all SF, 867.5 MHz */ 51 | "enable": true, 52 | "radio": 0, 53 | "if": 0 54 | }, 55 | "chan_multiSF_6": { 56 | /* Lora MAC channel, 125kHz, all SF, 867.7 MHz */ 57 | "enable": true, 58 | "radio": 0, 59 | "if": 200000 60 | }, 61 | "chan_multiSF_7": { 62 | /* Lora MAC channel, 125kHz, all SF, 867.9 MHz */ 63 | "enable": true, 64 | "radio": 0, 65 | "if": 400000 66 | }, 67 | "chan_Lora_std": { 68 | /* Lora MAC channel, 250kHz, SF7, 868.3 MHz */ 69 | "enable": true, 70 | "radio": 1, 71 | "if": -200000, 72 | "bandwidth": 250000, 73 | "spread_factor": 7 74 | }, 75 | "chan_FSK": { 76 | /* FSK 50kbps channel, 868.8 MHz */ 77 | "enable": true, 78 | "radio": 1, 79 | "if": 300000, 80 | "bandwidth": 125000, 81 | "datarate": 50000 82 | }, 83 | "tx_lut_0": { 84 | /* TX gain table, index 0 */ 85 | "pa_gain": 0, 86 | "mix_gain": 8, 87 | "rf_power": -6, 88 | "dig_gain": 0 89 | }, 90 | "tx_lut_1": { 91 | /* TX gain table, index 1 */ 92 | "pa_gain": 0, 93 | "mix_gain": 10, 94 | "rf_power": -3, 95 | "dig_gain": 0 96 | }, 97 | "tx_lut_2": { 98 | /* TX gain table, index 2 */ 99 | "pa_gain": 0, 100 | "mix_gain": 12, 101 | "rf_power": 0, 102 | "dig_gain": 0 103 | }, 104 | "tx_lut_3": { 105 | /* TX gain table, index 3 */ 106 | "pa_gain": 1, 107 | "mix_gain": 8, 108 | "rf_power": 3, 109 | "dig_gain": 0 110 | }, 111 | "tx_lut_4": { 112 | /* TX gain table, index 4 */ 113 | "pa_gain": 1, 114 | "mix_gain": 10, 115 | "rf_power": 6, 116 | "dig_gain": 0 117 | }, 118 | "tx_lut_5": { 119 | /* TX gain table, index 5 */ 120 | "pa_gain": 1, 121 | "mix_gain": 12, 122 | "rf_power": 10, 123 | "dig_gain": 0 124 | }, 125 | "tx_lut_6": { 126 | /* TX gain table, index 6 */ 127 | "pa_gain": 1, 128 | "mix_gain": 13, 129 | "rf_power": 11, 130 | "dig_gain": 0 131 | }, 132 | "tx_lut_7": { 133 | /* TX gain table, index 7 */ 134 | "pa_gain": 2, 135 | "mix_gain": 9, 136 | "rf_power": 12, 137 | "dig_gain": 0 138 | }, 139 | "tx_lut_8": { 140 | /* TX gain table, index 8 */ 141 | "pa_gain": 1, 142 | "mix_gain": 15, 143 | "rf_power": 13, 144 | "dig_gain": 0 145 | }, 146 | "tx_lut_9": { 147 | /* TX gain table, index 9 */ 148 | "pa_gain": 2, 149 | "mix_gain": 10, 150 | "rf_power": 14, 151 | "dig_gain": 0 152 | }, 153 | "tx_lut_10": { 154 | /* TX gain table, index 10 */ 155 | "pa_gain": 2, 156 | "mix_gain": 11, 157 | "rf_power": 16, 158 | "dig_gain": 0 159 | }, 160 | "tx_lut_11": { 161 | /* TX gain table, index 11 */ 162 | "pa_gain": 3, 163 | "mix_gain": 9, 164 | "rf_power": 20, 165 | "dig_gain": 0 166 | }, 167 | "tx_lut_12": { 168 | /* TX gain table, index 12 */ 169 | "pa_gain": 3, 170 | "mix_gain": 10, 171 | "rf_power": 23, 172 | "dig_gain": 0 173 | }, 174 | "tx_lut_13": { 175 | /* TX gain table, index 13 */ 176 | "pa_gain": 3, 177 | "mix_gain": 11, 178 | "rf_power": 25, 179 | "dig_gain": 0 180 | }, 181 | "tx_lut_14": { 182 | /* TX gain table, index 14 */ 183 | "pa_gain": 3, 184 | "mix_gain": 12, 185 | "rf_power": 26, 186 | "dig_gain": 0 187 | }, 188 | "tx_lut_15": { 189 | /* TX gain table, index 15 */ 190 | "pa_gain": 3, 191 | "mix_gain": 14, 192 | "rf_power": 27, 193 | "dig_gain": 0 194 | } 195 | }, 196 | 197 | "gateway_conf": { 198 | /* change with default server address/ports, or overwrite in local_conf.json */ 199 | "gateway_ID": "AA555A0000000000", 200 | /* Devices */ 201 | "gps": true, 202 | "beacon": false, 203 | "monitor": false, 204 | "upstream": true, 205 | "downstream": true, 206 | "ghoststream": false, 207 | "radiostream": true, 208 | "statusstream": true, 209 | /* node server */ 210 | "server_address": "127.0.0.1", 211 | "serv_port_up": 1680, 212 | "serv_port_down": 1681, 213 | /* node servers for poly packet server (max 4) */ 214 | "servers": 215 | [ { "server_address": "127.0.0.1", 216 | "serv_port_up": 1680, 217 | "serv_port_down": 1681, 218 | "serv_enabled": true }, 219 | { "server_address": "iot.semtech.com", 220 | "serv_port_up": 1680, 221 | "serv_port_down": 1680, 222 | "serv_enabled": true } ], 223 | /* adjust the following parameters for your network */ 224 | "keepalive_interval": 10, 225 | "stat_interval": 30, 226 | "push_timeout_ms": 100, 227 | /* forward only valid packets */ 228 | "forward_crc_valid": true, 229 | "forward_crc_error": false, 230 | "forward_crc_disabled": false, 231 | /* GPS configuration */ 232 | "gps_tty_path": "/dev/ttyAMA0", 233 | "fake_gps": true, 234 | "ref_latitude": 10, 235 | "ref_longitude": 20, 236 | "ref_altitude": -1, 237 | /* Ghost configuration */ 238 | "ghost_address": "127.0.0.1", 239 | "ghost_port": 1918, 240 | /* Monitor configuration */ 241 | "monitor_address": "127.0.0.1", 242 | "monitor_port": 2008, 243 | "ssh_path": "/usr/bin/ssh", 244 | "ssh_port": 22, 245 | "http_port": 80, 246 | "ngrok_path": "/usr/bin/ngrok", 247 | "system_calls": ["df -m","free -h","uptime","who -a","uname -a"], 248 | /* Platform definition, put a asterix here for the system value, max 24 chars. */ 249 | "platform": "*", 250 | /* Email of gateway operator, max 40 chars*/ 251 | "contact_email": "operator@gateway.tst", 252 | /* Public description of this device, max 64 chars */ 253 | "description": "Update me" 254 | 255 | 256 | } 257 | } 258 | -------------------------------------------------------------------------------- /poly_pkt_fwd/global_conf_multitech-eu868.json: -------------------------------------------------------------------------------- 1 | { 2 | "SX1301_conf": { 3 | "lorawan_public": true, 4 | "clksrc": 0, /* radio_1 provides clock to concentrator */ 5 | "radio_0": { 6 | "enable": true, 7 | "type": "SX1257", 8 | "freq": 868500000, 9 | "rssi_offset": -166.0, 10 | "tx_enable": true 11 | }, 12 | "radio_1": { 13 | "enable": true, 14 | "type": "SX1257", 15 | "freq": 869500000, 16 | "rssi_offset": -166.0, 17 | "tx_enable": false 18 | }, 19 | "chan_multiSF_0": { 20 | /* Lora MAC channel, 125kHz, all SF, 868.1 MHz */ 21 | "enable": true, 22 | "radio": 0, 23 | "if": -400000 24 | }, 25 | "chan_multiSF_1": { 26 | /* Lora MAC channel, 125kHz, all SF, 868.3 MHz */ 27 | "enable": true, 28 | "radio": 0, 29 | "if": -200000 30 | }, 31 | "chan_multiSF_2": { 32 | /* Lora MAC channel, 125kHz, all SF, 868.5 MHz */ 33 | "enable": true, 34 | "radio": 0, 35 | "if": 0 36 | }, 37 | "chan_multiSF_3": { 38 | /* Lora MAC channel, 125kHz, all SF, 867.1 MHz */ 39 | "enable": true, 40 | "radio": 1, 41 | "if": -400000 42 | }, 43 | "chan_multiSF_4": { 44 | /* Lora MAC channel, 125kHz, all SF, 867.3 MHz */ 45 | "enable": true, 46 | "radio": 1, 47 | "if": -200000 48 | }, 49 | "chan_multiSF_5": { 50 | /* Lora MAC channel, 125kHz, all SF, 867.5 MHz */ 51 | "enable": true, 52 | "radio": 1, 53 | "if": 0 54 | }, 55 | "chan_multiSF_6": { 56 | /* Lora MAC channel, 125kHz, all SF, 867.7 MHz */ 57 | "enable": true, 58 | "radio": 1, 59 | "if": 200000 60 | }, 61 | "chan_multiSF_7": { 62 | /* Lora MAC channel, 125kHz, all SF, 867.9 MHz */ 63 | "enable": true, 64 | "radio": 1, 65 | "if": 400000 66 | }, 67 | "chan_Lora_std": { 68 | /* Lora MAC channel, 250kHz, SF7, 868.3 MHz */ 69 | "enable": true, 70 | "radio": 0, 71 | "if": -200000, 72 | "bandwidth": 250000, 73 | "spread_factor": 7 74 | }, 75 | "chan_FSK": { 76 | "enable": true, 77 | "radio": 0, 78 | "if": 100000, 79 | "bandwidth": 250000, 80 | "datarate": 50000, 81 | "freq_deviation" : 25000 82 | }, 83 | "tx_lut_0": { 84 | /* TX gain table, index 0 */ 85 | "pa_gain": 0, 86 | "mix_gain": 8, 87 | "rf_power": -6, 88 | "dig_gain": 0 89 | }, 90 | "tx_lut_1": { 91 | /* TX gain table, index 1 */ 92 | "pa_gain": 0, 93 | "mix_gain": 10, 94 | "rf_power": -3, 95 | "dig_gain": 0 96 | }, 97 | "tx_lut_2": { 98 | /* TX gain table, index 2 */ 99 | "pa_gain": 0, 100 | "mix_gain": 12, 101 | "rf_power": 0, 102 | "dig_gain": 0 103 | }, 104 | "tx_lut_3": { 105 | /* TX gain table, index 3 */ 106 | "pa_gain": 1, 107 | "mix_gain": 8, 108 | "rf_power": 3, 109 | "dig_gain": 0 110 | }, 111 | "tx_lut_4": { 112 | /* TX gain table, index 4 */ 113 | "pa_gain": 1, 114 | "mix_gain": 10, 115 | "rf_power": 6, 116 | "dig_gain": 0 117 | }, 118 | "tx_lut_5": { 119 | /* TX gain table, index 5 */ 120 | "pa_gain": 1, 121 | "mix_gain": 12, 122 | "rf_power": 10, 123 | "dig_gain": 0 124 | }, 125 | "tx_lut_6": { 126 | /* TX gain table, index 6 */ 127 | "pa_gain": 1, 128 | "mix_gain": 13, 129 | "rf_power": 11, 130 | "dig_gain": 0 131 | }, 132 | "tx_lut_7": { 133 | /* TX gain table, index 7 */ 134 | "pa_gain": 2, 135 | "mix_gain": 9, 136 | "rf_power": 12, 137 | "dig_gain": 0 138 | }, 139 | "tx_lut_8": { 140 | /* TX gain table, index 8 */ 141 | "pa_gain": 1, 142 | "mix_gain": 15, 143 | "rf_power": 13, 144 | "dig_gain": 0 145 | }, 146 | "tx_lut_9": { 147 | /* TX gain table, index 9 */ 148 | "pa_gain": 2, 149 | "mix_gain": 10, 150 | "rf_power": 14, 151 | "dig_gain": 0 152 | }, 153 | "tx_lut_10": { 154 | /* TX gain table, index 10 */ 155 | "pa_gain": 2, 156 | "mix_gain": 11, 157 | "rf_power": 16, 158 | "dig_gain": 0 159 | }, 160 | "tx_lut_11": { 161 | /* TX gain table, index 11 */ 162 | "pa_gain": 3, 163 | "mix_gain": 10, 164 | "rf_power": 20, 165 | "dig_gain": 0 166 | }, 167 | "tx_lut_12": { 168 | /* TX gain table, index 12 */ 169 | "pa_gain": 3, 170 | "mix_gain": 11, 171 | "rf_power": 23, 172 | "dig_gain": 0 173 | }, 174 | "tx_lut_13": { 175 | /* TX gain table, index 13 */ 176 | "pa_gain": 3, 177 | "mix_gain": 12, 178 | "rf_power": 24, 179 | "dig_gain": 0 180 | }, 181 | "tx_lut_14": { 182 | /* TX gain table, index 14 */ 183 | "pa_gain": 3, 184 | "mix_gain": 13, 185 | "rf_power": 25, 186 | "dig_gain": 0 187 | }, 188 | "tx_lut_15": { 189 | /* TX gain table, index 15 */ 190 | "pa_gain": 3, 191 | "mix_gain": 15, 192 | "rf_power": 26, 193 | "dig_gain": 0 194 | } 195 | }, 196 | 197 | "gateway_conf": { 198 | /* change with default server address/ports, or overwrite in local_conf.json */ 199 | "gateway_ID": "AA555A0000000000", 200 | /* Devices */ 201 | "gps": true, 202 | "beacon": false, 203 | "monitor": false, 204 | "upstream": true, 205 | "downstream": true, 206 | "ghoststream": false, 207 | "radiostream": true, 208 | "statusstream": true, 209 | /* node server */ 210 | "server_address": "127.0.0.1", 211 | "serv_port_up": 1680, 212 | "serv_port_down": 1681, 213 | /* node servers for poly packet server (max 4) */ 214 | "servers": 215 | [ { "server_address": "127.0.0.1", 216 | "serv_port_up": 1680, 217 | "serv_port_down": 1681, 218 | "serv_enabled": false }, 219 | { /* "server_address": "iot.semtech.com", */ 220 | "server_address": "80.83.53.26", 221 | "serv_port_up": 1680, 222 | "serv_port_down": 1680, 223 | "serv_enabled": true }, 224 | { /* "server_address": "croft.thethings.girovito.nl", */ 225 | "server_address": "54.72.145.119", 226 | "serv_port_up" : 1700, 227 | "serv_port_down" : 1700, 228 | "serv_enabled": true } ], 229 | /* adjust the following parameters for your network */ 230 | "keepalive_interval": 10, 231 | "stat_interval": 30, 232 | "push_timeout_ms": 100, 233 | /* forward only valid packets */ 234 | "forward_crc_valid": true, 235 | "forward_crc_error": false, 236 | "forward_crc_disabled": true, 237 | /* GPS configuration */ 238 | "gps_tty_path": "/dev/ttyAMA0", 239 | "fake_gps": false, 240 | "ref_latitude": 10, 241 | "ref_longitude": 20, 242 | "ref_altitude": -1, 243 | /* Ghost configuration */ 244 | "ghost_address": "127.0.0.1", 245 | "ghost_port": 1918, 246 | /* Monitor configuration */ 247 | "monitor_address": "127.0.0.1", 248 | "monitor_port": 2008, 249 | "ssh_path": "/usr/bin/ssh", 250 | "ssh_port": 22, 251 | "http_port": 80, 252 | "ngrok_path": "/usr/bin/ngrok", 253 | "system_calls": ["df -m","free -h","uptime","who -a","uname -a"], 254 | /* Platform definition, put a asterix here for the system value, max 24 chars. */ 255 | "platform": "*", 256 | /* Email of gateway operator, max 40 chars*/ 257 | "contact_email": "operator@gateway.tst", 258 | /* Public description of this device, max 64 chars */ 259 | "description": "Update me" 260 | } 261 | } 262 | -------------------------------------------------------------------------------- /poly_pkt_fwd/global_conf_multitech-eu868-ttn.json: -------------------------------------------------------------------------------- 1 | { 2 | "SX1301_conf": { 3 | "lorawan_public": true, 4 | "clksrc": 0, /* radio_0 provides clock to concentrator */ 5 | /* TTN EU channel plan */ 6 | "radio_0": { 7 | "enable": true, 8 | "type": "SX1257", 9 | "freq": 867500000, 10 | "rssi_offset": -166.0, 11 | "tx_enable": true 12 | }, 13 | "radio_1": { 14 | "enable": true, 15 | "type": "SX1257", 16 | "freq": 868500000, 17 | "rssi_offset": -166.0, 18 | "tx_enable": false 19 | }, 20 | "chan_multiSF_0": { 21 | /* Lora MAC channel, 125kHz, all SF, 868.1 MHz */ 22 | "enable": true, 23 | "radio": 1, 24 | "if": -400000 25 | }, 26 | "chan_multiSF_1": { 27 | /* Lora MAC channel, 125kHz, all SF, 868.3 MHz */ 28 | "enable": true, 29 | "radio": 1, 30 | "if": -200000 31 | }, 32 | "chan_multiSF_2": { 33 | /* Lora MAC channel, 125kHz, all SF, 868.5 MHz */ 34 | "enable": true, 35 | "radio": 1, 36 | "if": 0 37 | }, 38 | "chan_multiSF_3": { 39 | /* Lora MAC channel, 125kHz, all SF, 867.1 MHz */ 40 | "enable": true, 41 | "radio": 0, 42 | "if": -400000 43 | }, 44 | "chan_multiSF_4": { 45 | /* Lora MAC channel, 125kHz, all SF, 867.3 MHz */ 46 | "enable": true, 47 | "radio": 0, 48 | "if": -200000 49 | }, 50 | "chan_multiSF_5": { 51 | /* Lora MAC channel, 125kHz, all SF, 867.5 MHz */ 52 | "enable": true, 53 | "radio": 0, 54 | "if": 0 55 | }, 56 | "chan_multiSF_6": { 57 | /* Lora MAC channel, 125kHz, all SF, 867.7 MHz */ 58 | "enable": true, 59 | "radio": 0, 60 | "if": 200000 61 | }, 62 | "chan_multiSF_7": { 63 | /* Lora MAC channel, 125kHz, all SF, 867.9 MHz */ 64 | "enable": true, 65 | "radio": 0, 66 | "if": 400000 67 | }, 68 | "chan_Lora_std": { 69 | /* Lora MAC channel, 250kHz, SF7, 868.3 MHz */ 70 | "enable": true, 71 | "radio": 1, 72 | "if": -200000, 73 | "bandwidth": 250000, 74 | "spread_factor": 7 75 | }, 76 | "chan_FSK": { 77 | /* FSK 50kbps channel, 868.8 MHz */ 78 | "enable": true, 79 | "radio": 1, 80 | "if": 300000, 81 | "bandwidth": 150000, 82 | "datarate": 50000 83 | }, 84 | "tx_lut_0": { 85 | /* TX gain table, index 0 */ 86 | "pa_gain": 0, 87 | "mix_gain": 8, 88 | "rf_power": -6, 89 | "dig_gain": 0 90 | }, 91 | "tx_lut_1": { 92 | /* TX gain table, index 1 */ 93 | "pa_gain": 0, 94 | "mix_gain": 10, 95 | "rf_power": -3, 96 | "dig_gain": 0 97 | }, 98 | "tx_lut_2": { 99 | /* TX gain table, index 2 */ 100 | "pa_gain": 0, 101 | "mix_gain": 12, 102 | "rf_power": 0, 103 | "dig_gain": 0 104 | }, 105 | "tx_lut_3": { 106 | /* TX gain table, index 3 */ 107 | "pa_gain": 1, 108 | "mix_gain": 8, 109 | "rf_power": 3, 110 | "dig_gain": 0 111 | }, 112 | "tx_lut_4": { 113 | /* TX gain table, index 4 */ 114 | "pa_gain": 1, 115 | "mix_gain": 10, 116 | "rf_power": 6, 117 | "dig_gain": 0 118 | }, 119 | "tx_lut_5": { 120 | /* TX gain table, index 5 */ 121 | "pa_gain": 1, 122 | "mix_gain": 12, 123 | "rf_power": 10, 124 | "dig_gain": 0 125 | }, 126 | "tx_lut_6": { 127 | /* TX gain table, index 6 */ 128 | "pa_gain": 1, 129 | "mix_gain": 13, 130 | "rf_power": 11, 131 | "dig_gain": 0 132 | }, 133 | "tx_lut_7": { 134 | /* TX gain table, index 7 */ 135 | "pa_gain": 2, 136 | "mix_gain": 9, 137 | "rf_power": 12, 138 | "dig_gain": 0 139 | }, 140 | "tx_lut_8": { 141 | /* TX gain table, index 8 */ 142 | "pa_gain": 1, 143 | "mix_gain": 15, 144 | "rf_power": 13, 145 | "dig_gain": 0 146 | }, 147 | "tx_lut_9": { 148 | /* TX gain table, index 9 */ 149 | "pa_gain": 2, 150 | "mix_gain": 10, 151 | "rf_power": 14, 152 | "dig_gain": 0 153 | }, 154 | "tx_lut_10": { 155 | /* TX gain table, index 10 */ 156 | "pa_gain": 2, 157 | "mix_gain": 11, 158 | "rf_power": 16, 159 | "dig_gain": 0 160 | }, 161 | "tx_lut_11": { 162 | /* TX gain table, index 11 */ 163 | "pa_gain": 3, 164 | "mix_gain": 10, 165 | "rf_power": 20, 166 | "dig_gain": 0 167 | }, 168 | "tx_lut_12": { 169 | /* TX gain table, index 12 */ 170 | "pa_gain": 3, 171 | "mix_gain": 11, 172 | "rf_power": 23, 173 | "dig_gain": 0 174 | }, 175 | "tx_lut_13": { 176 | /* TX gain table, index 13 */ 177 | "pa_gain": 3, 178 | "mix_gain": 12, 179 | "rf_power": 24, 180 | "dig_gain": 0 181 | }, 182 | "tx_lut_14": { 183 | /* TX gain table, index 14 */ 184 | "pa_gain": 3, 185 | "mix_gain": 13, 186 | "rf_power": 25, 187 | "dig_gain": 0 188 | }, 189 | "tx_lut_15": { 190 | /* TX gain table, index 15 */ 191 | "pa_gain": 3, 192 | "mix_gain": 15, 193 | "rf_power": 26, 194 | "dig_gain": 0 195 | } 196 | }, 197 | 198 | "gateway_conf": { 199 | /* change with default server address/ports, or overwrite in local_conf.json */ 200 | "gateway_ID": "AA555A0000000000", 201 | /* Devices */ 202 | "gps": true, 203 | "beacon": false, 204 | "monitor": false, 205 | "upstream": true, 206 | "downstream": true, 207 | "ghoststream": false, 208 | "radiostream": true, 209 | "statusstream": true, 210 | /* node server */ 211 | "server_address": "127.0.0.1", 212 | "serv_port_up": 1680, 213 | "serv_port_down": 1681, 214 | /* node servers for poly packet server (max 4) */ 215 | "servers": 216 | [ { "server_address": "127.0.0.1", 217 | "serv_port_up": 1680, 218 | "serv_port_down": 1681, 219 | "serv_enabled": false }, 220 | { /* "server_address": "iot.semtech.com", */ 221 | "server_address": "80.83.53.26", 222 | "serv_port_up": 1680, 223 | "serv_port_down": 1680, 224 | "serv_enabled": true }, 225 | { /* "server_address": "croft.thethings.girovito.nl", */ 226 | "server_address": "54.72.145.119", 227 | "serv_port_up" : 1700, 228 | "serv_port_down" : 1700, 229 | "serv_enabled": true } ], 230 | /* adjust the following parameters for your network */ 231 | "keepalive_interval": 10, 232 | "stat_interval": 30, 233 | "push_timeout_ms": 100, 234 | /* forward only valid packets */ 235 | "forward_crc_valid": true, 236 | "forward_crc_error": false, 237 | "forward_crc_disabled": true, 238 | /* GPS configuration */ 239 | "gps_tty_path": "/dev/ttyAMA0", 240 | "fake_gps": false, 241 | "ref_latitude": 10, 242 | "ref_longitude": 20, 243 | "ref_altitude": -1, 244 | /* Ghost configuration */ 245 | "ghost_address": "127.0.0.1", 246 | "ghost_port": 1918, 247 | /* Monitor configuration */ 248 | "monitor_address": "127.0.0.1", 249 | "monitor_port": 2008, 250 | "ssh_path": "/usr/bin/ssh", 251 | "ssh_port": 22, 252 | "http_port": 80, 253 | "ngrok_path": "/usr/bin/ngrok", 254 | "system_calls": ["df -m","free -h","uptime","who -a","uname -a"], 255 | /* Platform definition, put a asterix here for the system value, max 24 chars. */ 256 | "platform": "*", 257 | /* Email of gateway operator, max 40 chars*/ 258 | "contact_email": "operator@gateway.tst", 259 | /* Public description of this device, max 64 chars */ 260 | "description": "Update me" 261 | } 262 | } 263 | -------------------------------------------------------------------------------- /poly_pkt_fwd/readme.md: -------------------------------------------------------------------------------- 1 | / _____) _ | | 2 | ( (____ _____ ____ _| |_ _____ ____| |__ 3 | \____ \| ___ | (_ _) ___ |/ ___) _ \ 4 | _____) ) ____| | | || |_| ____( (___| | | | 5 | (______/|_____)_|_|_| \__)_____)\____)_| |_| 6 | (C)2013 Semtech-Cycleo 7 | (C)2015 Modfications by Ruud Vlaming (The Things Network) 8 | 9 | Lora Gateway packet forwarder with multiple extensions 10 | ====================================================== 11 | 12 | WARNING: 13 | Bleeding edge work. Code not yet properly tested, will most likely 14 | fail directly afer startup. 15 | 16 | 1. Introduction 17 | ---------------- 18 | 19 | The poly packet forwarder is a program running on the host of a Lora 20 | Gateway that forward RF packets receive by the concentrator to a server 21 | through a IP/UDP link, and emits RF packets that are sent by the server. 22 | It is an 23 | 24 | It allows for the injection of virtual radio packets for testing and 25 | is capable of communication with multiple servers. It is based on the 26 | beacon_packet_forwarder with that distinction the operator has 27 | detailed control over all capabilities. So beacon, gps, injection, 28 | up/down stream, all can be (de)activated by modifying the json. 29 | 30 | To learn more about the network protocol between the gateway and the server, 31 | please read the PROTOCOL.TXT document. 32 | 33 | 2. System schematic and definitions 34 | ------------------------------------ 35 | 36 | ((( Y ))) 37 | | 38 | | 39 | +- -|- - - - - - - - - - - - -+ xxxxxxxx +---------+ 40 | |+--+-----------+ +------+| xxx xxx | |-+ 41 | || | | || xx Internet xx | | |-+ 42 | || Concentrator |<----+ Host |<---- xx or xx ======>| Network | | |-+ 43 | || | SPI | || xx Intranet xx | Servers | | | | 44 | |+--------------+ +------+| xxx xxx | | | | | 45 | | ^ ^ | | xxxxxxxx | | | | | | 46 | | | PPS +-----+ NMEA | | | | | | | | | 47 | | +------| GPS |-------+ | +--------+ +---------+ +---------+ | | | 48 | | +-----+ | | ghost | | monitor | +---------+ | | 49 | | | | server | | server | +---------+ | 50 | | Gateway | +--------+ +---------+ +---------+ 51 | +- - - - - - - - - - - - - - -+ 52 | 53 | Concentrator: radio RX/TX board, based on Semtech multichannel modems (SX130x), 54 | transceivers (SX135x) and/or low-power stand-alone modems (SX127x). 55 | 56 | Host: embedded computer on which the packet forwarder is run. Drives the 57 | concentrator through a SPI link. 58 | 59 | Gateway: a device composed of at least one radio concentrator, a host, some 60 | network connection to the internet or a private network (Ethernet, 3G, Wifi, 61 | microwave link), and optionally a GPS receiver for synchronization. 62 | 63 | Network Servers: abstract computers that will process the RF packets received and 64 | forwarded by the gateway, and issue RF packets in response that the gateway 65 | will have to emit. 66 | 67 | Ghost Server: Program on in/external computer the serves simulated radio 68 | packets for testing purposes. Packets are send/received via UDP protocol. 69 | 70 | Monitor Server: Program on in/external computer from which it is possible 71 | to maintain the gateway by requesting system status updates or logging in 72 | by an ssh tunnel through a firewall (on the gateways side) 73 | 74 | 75 | 3. Dependencies 76 | ---------------- 77 | 78 | This program uses the Parson library (http://kgabis.github.com/parson/) by 79 | Krzysztof Gabis for JSON parsing. 80 | Many thanks to him for that very practical and well written library. 81 | 82 | This program is statically linked with the libloragw Lora concentrator library. 83 | It was tested with v1.3.0 of the library but should work with any later 84 | version provided the API is v1 or a later backward-compatible API. 85 | Data structures of the received packets are accessed by name (ie. not at a 86 | binary level) so new functionalities can be added to the API without affecting 87 | that program at all. 88 | 89 | This program follows the v1.1 version of the gateway-to-server protocol. 90 | 91 | The last dependency is the hardware concentrator (based on FPGA or SX130x 92 | chips) that must be matched with the proper version of the HAL. 93 | 94 | 4. Usage 95 | --------- 96 | 97 | To stop the application, press Ctrl+C. 98 | Unless it is manually stopped or encounter a critical error, the program will 99 | run forever. 100 | 101 | There are no command line launch options. 102 | 103 | The way the program takes configuration files into account is the following: 104 | * if there is a debug_conf.json parse it, others are ignored 105 | * if there is a global_conf.json parse it, look for the next file 106 | * if there is a local_conf.json parse it 107 | If some parameters are defined in both global and local configuration files, 108 | the local definition overwrites the global definition. 109 | 110 | The global configuration file should be exactly the same throughout your 111 | network, contain all global parameters (parameters for "sensor" radio 112 | channels) and preferably default "safe" values for parameters that are 113 | specific for each gateway (eg. specify a default MAC address). 114 | 115 | The local configuration file should contain parameters that are specific to 116 | each gateway (eg. MAC address, frequency for backhaul radio channels). 117 | 118 | In each configuration file, the program looks for a JSON object named 119 | "SX1301_conf" that should contain the parameters for the Lora concentrator 120 | board (RF channels definition, modem parameters, etc) and another JSON object 121 | called "gateway_conf" that should contain the gateway parameters (gateway MAC 122 | address, IP address of the server, keep-alive time, etc). 123 | 124 | To learn more about the JSON configuration format, read the provided JSON 125 | files and the libloragw API documentation. 126 | 127 | Every X seconds (parameter settable in the configuration files) the program 128 | display statistics on the RF packets received and sent, and the network 129 | datagrams received and sent. 130 | The program also send some statistics to the server in JSON format. 131 | 132 | 5. License 133 | ----------- 134 | 135 | Copyright (C) 2013, SEMTECH S.A. 136 | All rights reserved. 137 | 138 | Redistribution and use in source and binary forms, with or without 139 | modification, are permitted provided that the following conditions are met: 140 | 141 | * Redistributions of source code must retain the above copyright 142 | notice, this list of conditions and the following disclaimer. 143 | * Redistributions in binary form must reproduce the above copyright 144 | notice, this list of conditions and the following disclaimer in the 145 | documentation and/or other materials provided with the distribution. 146 | * Neither the name of the Semtech corporation nor the 147 | names of its contributors may be used to endorse or promote products 148 | derived from this software without specific prior written permission. 149 | 150 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND 151 | ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 152 | WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 153 | DISCLAIMED. IN NO EVENT SHALL SEMTECH S.A. BE LIABLE FOR ANY 154 | DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 155 | (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 156 | LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND 157 | ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 158 | (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 159 | SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 160 | 161 | 6. License for Parson library 162 | ------------------------------ 163 | 164 | Parson ( http://kgabis.github.com/parson/ ) 165 | Copyright (C) 2012 Krzysztof Gabis 166 | 167 | Permission is hereby granted, free of charge, to any person obtaining a copy 168 | of this software and associated documentation files (the "Software"), to deal 169 | in the Software without restriction, including without limitation the rights 170 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 171 | copies of the Software, and to permit persons to whom the Software is 172 | furnished to do so, subject to the following conditions: 173 | 174 | The above copyright notice and this permission notice shall be included in 175 | all copies or substantial portions of the Software. 176 | 177 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 178 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 179 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 180 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 181 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 182 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 183 | THE SOFTWARE. 184 | 185 | *EOF* 186 | -------------------------------------------------------------------------------- /beacon_pkt_fwd/src/base64.c: -------------------------------------------------------------------------------- 1 | /* 2 | / _____) _ | | 3 | ( (____ _____ ____ _| |_ _____ ____| |__ 4 | \____ \| ___ | (_ _) ___ |/ ___) _ \ 5 | _____) ) ____| | | || |_| ____( (___| | | | 6 | (______/|_____)_|_|_| \__)_____)\____)_| |_| 7 | (C)2013 Semtech-Cycleo 8 | 9 | Description: 10 | Base64 encoding & decoding library 11 | 12 | License: Revised BSD License, see LICENSE.TXT file include in the project 13 | Maintainer: Sylvain Miermont 14 | */ 15 | 16 | 17 | /* -------------------------------------------------------------------------- */ 18 | /* --- DEPENDANCIES --------------------------------------------------------- */ 19 | 20 | #include 21 | #include 22 | #include 23 | 24 | #include "base64.h" 25 | 26 | /* -------------------------------------------------------------------------- */ 27 | /* --- PRIVATE MACROS ------------------------------------------------------- */ 28 | 29 | #define ARRAY_SIZE(a) (sizeof(a) / sizeof((a)[0])) 30 | #define CRIT(a) fprintf(stderr, "\nCRITICAL file:%s line:%u msg:%s\n", __FILE__, __LINE__,a);exit(EXIT_FAILURE) 31 | 32 | //#define DEBUG(args...) fprintf(stderr,"debug: " args) /* diagnostic message that is destined to the user */ 33 | #define DEBUG(args...) 34 | 35 | /* -------------------------------------------------------------------------- */ 36 | /* --- PRIVATE CONSTANTS ---------------------------------------------------- */ 37 | 38 | /* -------------------------------------------------------------------------- */ 39 | /* --- PRIVATE MODULE-WIDE VARIABLES ---------------------------------------- */ 40 | 41 | static char code_62 = '+'; /* RFC 1421 standard character for code 62 */ 42 | static char code_63 = '/'; /* RFC 1421 standard character for code 63 */ 43 | static char code_pad = '='; /* RFC 1421 padding character if padding */ 44 | 45 | /* -------------------------------------------------------------------------- */ 46 | /* --- PRIVATE FUNCTIONS DECLARATION ---------------------------------------- */ 47 | 48 | /** 49 | @brief Convert a code in the range 0-63 to an ASCII character 50 | */ 51 | char code_to_char(uint8_t x); 52 | 53 | /** 54 | @brief Convert an ASCII character to a code in the range 0-63 55 | */ 56 | uint8_t char_to_code(char x); 57 | 58 | /* -------------------------------------------------------------------------- */ 59 | /* --- PRIVATE FUNCTIONS DEFINITION ----------------------------------------- */ 60 | 61 | char code_to_char(uint8_t x) { 62 | if (x <= 25) { 63 | return 'A' + x; 64 | } else if ((x >= 26) && (x <= 51)) { 65 | return 'a' + (x-26); 66 | } else if ((x >= 52) && (x <= 61)) { 67 | return '0' + (x-52); 68 | } else if (x == 62) { 69 | return code_62; 70 | } else if (x == 63) { 71 | return code_63; 72 | } else { 73 | DEBUG("ERROR: %i IS OUT OF RANGE 0-63 FOR BASE64 ENCODING\n", x); 74 | exit(EXIT_FAILURE); 75 | } //TODO: improve error management 76 | } 77 | 78 | uint8_t char_to_code(char x) { 79 | if ((x >= 'A') && (x <= 'Z')) { 80 | return (uint8_t)x - (uint8_t)'A'; 81 | } else if ((x >= 'a') && (x <= 'z')) { 82 | return (uint8_t)x - (uint8_t)'a' + 26; 83 | } else if ((x >= '0') && (x <= '9')) { 84 | return (uint8_t)x - (uint8_t)'0' + 52; 85 | } else if (x == code_62) { 86 | return 62; 87 | } else if (x == code_63) { 88 | return 63; 89 | } else { 90 | DEBUG("ERROR: %c (0x%x) IS INVALID CHARACTER FOR BASE64 DECODING\n", x, x); 91 | exit(EXIT_FAILURE); 92 | } //TODO: improve error management 93 | } 94 | 95 | /* -------------------------------------------------------------------------- */ 96 | /* --- PUBLIC FUNCTIONS DEFINITION ------------------------------------------ */ 97 | 98 | int bin_to_b64_nopad(const uint8_t * in, int size, char * out, int max_len) { 99 | int i; 100 | int result_len; /* size of the result */ 101 | int full_blocks; /* number of 3 unsigned chars / 4 characters blocks */ 102 | int last_bytes; /* number of unsigned chars <3 in the last block */ 103 | int last_chars; /* number of characters <4 in the last block */ 104 | uint32_t b; 105 | 106 | /* check input values */ 107 | if ((out == NULL) || (in == NULL)) { 108 | DEBUG("ERROR: NULL POINTER AS OUTPUT IN BIN_TO_B64\n"); 109 | return -1; 110 | } 111 | if (size == 0) { 112 | *out = 0; /* null string */ 113 | return 0; 114 | } 115 | 116 | /* calculate the number of base64 'blocks' */ 117 | full_blocks = size / 3; 118 | last_bytes = size % 3; 119 | switch (last_bytes) { 120 | case 0: /* no byte left to encode */ 121 | last_chars = 0; 122 | break; 123 | case 1: /* 1 byte left to encode -> +2 chars */ 124 | last_chars = 2; 125 | break; 126 | case 2: /* 2 bytes left to encode -> +3 chars */ 127 | last_chars = 3; 128 | break; 129 | default: 130 | CRIT("switch default that should not be possible"); 131 | } 132 | 133 | /* check if output buffer is big enough */ 134 | result_len = (4*full_blocks) + last_chars; 135 | if (max_len < (result_len + 1)) { /* 1 char added for string terminator */ 136 | DEBUG("ERROR: OUTPUT BUFFER TOO SMALL IN BIN_TO_B64\n"); 137 | return -1; 138 | } 139 | 140 | /* process all the full blocks */ 141 | for (i=0; i < full_blocks; ++i) { 142 | b = (0xFF & in[3*i] ) << 16; 143 | b |= (0xFF & in[3*i + 1]) << 8; 144 | b |= 0xFF & in[3*i + 2]; 145 | out[4*i + 0] = code_to_char((b >> 18) & 0x3F); 146 | out[4*i + 1] = code_to_char((b >> 12) & 0x3F); 147 | out[4*i + 2] = code_to_char((b >> 6 ) & 0x3F); 148 | out[4*i + 3] = code_to_char( b & 0x3F); 149 | } 150 | 151 | /* process the last 'partial' block and terminate string */ 152 | i = full_blocks; 153 | if (last_chars == 0) { 154 | out[4*i] = 0; /* null character to terminate string */ 155 | } else if (last_chars == 2) { 156 | b = (0xFF & in[3*i] ) << 16; 157 | out[4*i + 0] = code_to_char((b >> 18) & 0x3F); 158 | out[4*i + 1] = code_to_char((b >> 12) & 0x3F); 159 | out[4*i + 2] = 0; /* null character to terminate string */ 160 | } else if (last_chars == 3) { 161 | b = (0xFF & in[3*i] ) << 16; 162 | b |= (0xFF & in[3*i + 1]) << 8; 163 | out[4*i + 0] = code_to_char((b >> 18) & 0x3F); 164 | out[4*i + 1] = code_to_char((b >> 12) & 0x3F); 165 | out[4*i + 2] = code_to_char((b >> 6 ) & 0x3F); 166 | out[4*i + 3] = 0; /* null character to terminate string */ 167 | } 168 | 169 | return result_len; 170 | } 171 | 172 | int b64_to_bin_nopad(const char * in, int size, uint8_t * out, int max_len) { 173 | int i; 174 | int result_len; /* size of the result */ 175 | int full_blocks; /* number of 3 unsigned chars / 4 characters blocks */ 176 | int last_chars; /* number of characters <4 in the last block */ 177 | int last_bytes; /* number of unsigned chars <3 in the last block */ 178 | uint32_t b; 179 | ; 180 | 181 | /* check input values */ 182 | if ((out == NULL) || (in == NULL)) { 183 | DEBUG("ERROR: NULL POINTER AS OUTPUT OR INPUT IN B64_TO_BIN\n"); 184 | return -1; 185 | } 186 | if (size == 0) { 187 | return 0; 188 | } 189 | 190 | /* calculate the number of base64 'blocks' */ 191 | full_blocks = size / 4; 192 | last_chars = size % 4; 193 | switch (last_chars) { 194 | case 0: /* no char left to decode */ 195 | last_bytes = 0; 196 | break; 197 | case 1: /* only 1 char left is an error */ 198 | DEBUG("ERROR: ONLY ONE CHAR LEFT IN B64_TO_BIN\n"); 199 | return -1; 200 | case 2: /* 2 chars left to decode -> +1 byte */ 201 | last_bytes = 1; 202 | break; 203 | case 3: /* 3 chars left to decode -> +2 bytes */ 204 | last_bytes = 2; 205 | break; 206 | default: 207 | CRIT("switch default that should not be possible"); 208 | } 209 | 210 | /* check if output buffer is big enough */ 211 | result_len = (3*full_blocks) + last_bytes; 212 | if (max_len < result_len) { 213 | DEBUG("ERROR: OUTPUT BUFFER TOO SMALL IN B64_TO_BIN\n"); 214 | return -1; 215 | } 216 | 217 | /* process all the full blocks */ 218 | for (i=0; i < full_blocks; ++i) { 219 | b = (0x3F & char_to_code(in[4*i] )) << 18; 220 | b |= (0x3F & char_to_code(in[4*i + 1])) << 12; 221 | b |= (0x3F & char_to_code(in[4*i + 2])) << 6; 222 | b |= 0x3F & char_to_code(in[4*i + 3]); 223 | out[3*i + 0] = (b >> 16) & 0xFF; 224 | out[3*i + 1] = (b >> 8 ) & 0xFF; 225 | out[3*i + 2] = b & 0xFF; 226 | } 227 | 228 | /* process the last 'partial' block */ 229 | i = full_blocks; 230 | if (last_bytes == 1) { 231 | b = (0x3F & char_to_code(in[4*i] )) << 18; 232 | b |= (0x3F & char_to_code(in[4*i + 1])) << 12; 233 | out[3*i + 0] = (b >> 16) & 0xFF; 234 | if (((b >> 12) & 0x0F) != 0) { 235 | DEBUG("WARNING: last character contains unusable bits\n"); 236 | } 237 | } else if (last_bytes == 2) { 238 | b = (0x3F & char_to_code(in[4*i] )) << 18; 239 | b |= (0x3F & char_to_code(in[4*i + 1])) << 12; 240 | b |= (0x3F & char_to_code(in[4*i + 2])) << 6; 241 | out[3*i + 0] = (b >> 16) & 0xFF; 242 | out[3*i + 1] = (b >> 8 ) & 0xFF; 243 | if (((b >> 6) & 0x03) != 0) { 244 | DEBUG("WARNING: last character contains unusable bits\n"); 245 | } 246 | } 247 | 248 | return result_len; 249 | } 250 | 251 | int bin_to_b64(const uint8_t * in, int size, char * out, int max_len) { 252 | int ret; 253 | 254 | ret = bin_to_b64_nopad(in, size, out, max_len); 255 | 256 | if (ret == -1) { 257 | return -1; 258 | } 259 | switch (ret%4) { 260 | case 0: /* nothing to do */ 261 | return ret; 262 | case 1: 263 | DEBUG("ERROR: INVALID UNPADDED BASE64 STRING\n"); 264 | return -1; 265 | case 2: /* 2 chars in last block, must add 2 padding char */ 266 | if (max_len > (ret + 2 + 1)) { 267 | out[ret] = code_pad; 268 | out[ret+1] = code_pad; 269 | out[ret+2] = 0; 270 | return ret+2; 271 | } else { 272 | DEBUG("ERROR: not enough room to add padding in bin_to_b64\n"); 273 | return -1; 274 | } 275 | case 3: /* 3 chars in last block, must add 1 padding char */ 276 | if (max_len > (ret + 1 + 1)) { 277 | out[ret] = code_pad; 278 | out[ret+1] = 0; 279 | return ret+1; 280 | } else { 281 | DEBUG("ERROR: not enough room to add padding in bin_to_b64\n"); 282 | return -1; 283 | } 284 | default: 285 | CRIT("switch default that should not be possible"); 286 | } 287 | } 288 | 289 | int b64_to_bin(const char * in, int size, uint8_t * out, int max_len) { 290 | if (in == NULL) { 291 | DEBUG("ERROR: NULL POINTER AS OUTPUT OR INPUT IN B64_TO_BIN\n"); 292 | return -1; 293 | } 294 | if ((size%4 == 0) && (size >= 4)) { /* potentially padded Base64 */ 295 | if (in[size-2] == code_pad) { /* 2 padding char to ignore */ 296 | return b64_to_bin_nopad(in, size-2, out, max_len); 297 | } else if (in[size-1] == code_pad) { /* 1 padding char to ignore */ 298 | return b64_to_bin_nopad(in, size-1, out, max_len); 299 | } else { /* no padding to ignore */ 300 | return b64_to_bin_nopad(in, size, out, max_len); 301 | } 302 | } else { /* treat as unpadded Base64 */ 303 | return b64_to_bin_nopad(in, size, out, max_len); 304 | } 305 | } 306 | 307 | 308 | /* --- EOF ------------------------------------------------------------------ */ 309 | -------------------------------------------------------------------------------- /gps_pkt_fwd/src/base64.c: -------------------------------------------------------------------------------- 1 | /* 2 | / _____) _ | | 3 | ( (____ _____ ____ _| |_ _____ ____| |__ 4 | \____ \| ___ | (_ _) ___ |/ ___) _ \ 5 | _____) ) ____| | | || |_| ____( (___| | | | 6 | (______/|_____)_|_|_| \__)_____)\____)_| |_| 7 | (C)2013 Semtech-Cycleo 8 | 9 | Description: 10 | Base64 encoding & decoding library 11 | 12 | License: Revised BSD License, see LICENSE.TXT file include in the project 13 | Maintainer: Sylvain Miermont 14 | */ 15 | 16 | 17 | /* -------------------------------------------------------------------------- */ 18 | /* --- DEPENDANCIES --------------------------------------------------------- */ 19 | 20 | #include 21 | #include 22 | #include 23 | 24 | #include "base64.h" 25 | 26 | /* -------------------------------------------------------------------------- */ 27 | /* --- PRIVATE MACROS ------------------------------------------------------- */ 28 | 29 | #define ARRAY_SIZE(a) (sizeof(a) / sizeof((a)[0])) 30 | #define CRIT(a) fprintf(stderr, "\nCRITICAL file:%s line:%u msg:%s\n", __FILE__, __LINE__,a);exit(EXIT_FAILURE) 31 | 32 | //#define DEBUG(args...) fprintf(stderr,"debug: " args) /* diagnostic message that is destined to the user */ 33 | #define DEBUG(args...) 34 | 35 | /* -------------------------------------------------------------------------- */ 36 | /* --- PRIVATE CONSTANTS ---------------------------------------------------- */ 37 | 38 | /* -------------------------------------------------------------------------- */ 39 | /* --- PRIVATE MODULE-WIDE VARIABLES ---------------------------------------- */ 40 | 41 | static char code_62 = '+'; /* RFC 1421 standard character for code 62 */ 42 | static char code_63 = '/'; /* RFC 1421 standard character for code 63 */ 43 | static char code_pad = '='; /* RFC 1421 padding character if padding */ 44 | 45 | /* -------------------------------------------------------------------------- */ 46 | /* --- PRIVATE FUNCTIONS DECLARATION ---------------------------------------- */ 47 | 48 | /** 49 | @brief Convert a code in the range 0-63 to an ASCII character 50 | */ 51 | char code_to_char(uint8_t x); 52 | 53 | /** 54 | @brief Convert an ASCII character to a code in the range 0-63 55 | */ 56 | uint8_t char_to_code(char x); 57 | 58 | /* -------------------------------------------------------------------------- */ 59 | /* --- PRIVATE FUNCTIONS DEFINITION ----------------------------------------- */ 60 | 61 | char code_to_char(uint8_t x) { 62 | if (x <= 25) { 63 | return 'A' + x; 64 | } else if ((x >= 26) && (x <= 51)) { 65 | return 'a' + (x-26); 66 | } else if ((x >= 52) && (x <= 61)) { 67 | return '0' + (x-52); 68 | } else if (x == 62) { 69 | return code_62; 70 | } else if (x == 63) { 71 | return code_63; 72 | } else { 73 | DEBUG("ERROR: %i IS OUT OF RANGE 0-63 FOR BASE64 ENCODING\n", x); 74 | exit(EXIT_FAILURE); 75 | } //TODO: improve error management 76 | } 77 | 78 | uint8_t char_to_code(char x) { 79 | if ((x >= 'A') && (x <= 'Z')) { 80 | return (uint8_t)x - (uint8_t)'A'; 81 | } else if ((x >= 'a') && (x <= 'z')) { 82 | return (uint8_t)x - (uint8_t)'a' + 26; 83 | } else if ((x >= '0') && (x <= '9')) { 84 | return (uint8_t)x - (uint8_t)'0' + 52; 85 | } else if (x == code_62) { 86 | return 62; 87 | } else if (x == code_63) { 88 | return 63; 89 | } else { 90 | DEBUG("ERROR: %c (0x%x) IS INVALID CHARACTER FOR BASE64 DECODING\n", x, x); 91 | exit(EXIT_FAILURE); 92 | } //TODO: improve error management 93 | } 94 | 95 | /* -------------------------------------------------------------------------- */ 96 | /* --- PUBLIC FUNCTIONS DEFINITION ------------------------------------------ */ 97 | 98 | int bin_to_b64_nopad(const uint8_t * in, int size, char * out, int max_len) { 99 | int i; 100 | int result_len; /* size of the result */ 101 | int full_blocks; /* number of 3 unsigned chars / 4 characters blocks */ 102 | int last_bytes; /* number of unsigned chars <3 in the last block */ 103 | int last_chars; /* number of characters <4 in the last block */ 104 | uint32_t b; 105 | 106 | /* check input values */ 107 | if ((out == NULL) || (in == NULL)) { 108 | DEBUG("ERROR: NULL POINTER AS OUTPUT IN BIN_TO_B64\n"); 109 | return -1; 110 | } 111 | if (size == 0) { 112 | *out = 0; /* null string */ 113 | return 0; 114 | } 115 | 116 | /* calculate the number of base64 'blocks' */ 117 | full_blocks = size / 3; 118 | last_bytes = size % 3; 119 | switch (last_bytes) { 120 | case 0: /* no byte left to encode */ 121 | last_chars = 0; 122 | break; 123 | case 1: /* 1 byte left to encode -> +2 chars */ 124 | last_chars = 2; 125 | break; 126 | case 2: /* 2 bytes left to encode -> +3 chars */ 127 | last_chars = 3; 128 | break; 129 | default: 130 | CRIT("switch default that should not be possible"); 131 | } 132 | 133 | /* check if output buffer is big enough */ 134 | result_len = (4*full_blocks) + last_chars; 135 | if (max_len < (result_len + 1)) { /* 1 char added for string terminator */ 136 | DEBUG("ERROR: OUTPUT BUFFER TOO SMALL IN BIN_TO_B64\n"); 137 | return -1; 138 | } 139 | 140 | /* process all the full blocks */ 141 | for (i=0; i < full_blocks; ++i) { 142 | b = (0xFF & in[3*i] ) << 16; 143 | b |= (0xFF & in[3*i + 1]) << 8; 144 | b |= 0xFF & in[3*i + 2]; 145 | out[4*i + 0] = code_to_char((b >> 18) & 0x3F); 146 | out[4*i + 1] = code_to_char((b >> 12) & 0x3F); 147 | out[4*i + 2] = code_to_char((b >> 6 ) & 0x3F); 148 | out[4*i + 3] = code_to_char( b & 0x3F); 149 | } 150 | 151 | /* process the last 'partial' block and terminate string */ 152 | i = full_blocks; 153 | if (last_chars == 0) { 154 | out[4*i] = 0; /* null character to terminate string */ 155 | } else if (last_chars == 2) { 156 | b = (0xFF & in[3*i] ) << 16; 157 | out[4*i + 0] = code_to_char((b >> 18) & 0x3F); 158 | out[4*i + 1] = code_to_char((b >> 12) & 0x3F); 159 | out[4*i + 2] = 0; /* null character to terminate string */ 160 | } else if (last_chars == 3) { 161 | b = (0xFF & in[3*i] ) << 16; 162 | b |= (0xFF & in[3*i + 1]) << 8; 163 | out[4*i + 0] = code_to_char((b >> 18) & 0x3F); 164 | out[4*i + 1] = code_to_char((b >> 12) & 0x3F); 165 | out[4*i + 2] = code_to_char((b >> 6 ) & 0x3F); 166 | out[4*i + 3] = 0; /* null character to terminate string */ 167 | } 168 | 169 | return result_len; 170 | } 171 | 172 | int b64_to_bin_nopad(const char * in, int size, uint8_t * out, int max_len) { 173 | int i; 174 | int result_len; /* size of the result */ 175 | int full_blocks; /* number of 3 unsigned chars / 4 characters blocks */ 176 | int last_chars; /* number of characters <4 in the last block */ 177 | int last_bytes; /* number of unsigned chars <3 in the last block */ 178 | uint32_t b; 179 | ; 180 | 181 | /* check input values */ 182 | if ((out == NULL) || (in == NULL)) { 183 | DEBUG("ERROR: NULL POINTER AS OUTPUT OR INPUT IN B64_TO_BIN\n"); 184 | return -1; 185 | } 186 | if (size == 0) { 187 | return 0; 188 | } 189 | 190 | /* calculate the number of base64 'blocks' */ 191 | full_blocks = size / 4; 192 | last_chars = size % 4; 193 | switch (last_chars) { 194 | case 0: /* no char left to decode */ 195 | last_bytes = 0; 196 | break; 197 | case 1: /* only 1 char left is an error */ 198 | DEBUG("ERROR: ONLY ONE CHAR LEFT IN B64_TO_BIN\n"); 199 | return -1; 200 | case 2: /* 2 chars left to decode -> +1 byte */ 201 | last_bytes = 1; 202 | break; 203 | case 3: /* 3 chars left to decode -> +2 bytes */ 204 | last_bytes = 2; 205 | break; 206 | default: 207 | CRIT("switch default that should not be possible"); 208 | } 209 | 210 | /* check if output buffer is big enough */ 211 | result_len = (3*full_blocks) + last_bytes; 212 | if (max_len < result_len) { 213 | DEBUG("ERROR: OUTPUT BUFFER TOO SMALL IN B64_TO_BIN\n"); 214 | return -1; 215 | } 216 | 217 | /* process all the full blocks */ 218 | for (i=0; i < full_blocks; ++i) { 219 | b = (0x3F & char_to_code(in[4*i] )) << 18; 220 | b |= (0x3F & char_to_code(in[4*i + 1])) << 12; 221 | b |= (0x3F & char_to_code(in[4*i + 2])) << 6; 222 | b |= 0x3F & char_to_code(in[4*i + 3]); 223 | out[3*i + 0] = (b >> 16) & 0xFF; 224 | out[3*i + 1] = (b >> 8 ) & 0xFF; 225 | out[3*i + 2] = b & 0xFF; 226 | } 227 | 228 | /* process the last 'partial' block */ 229 | i = full_blocks; 230 | if (last_bytes == 1) { 231 | b = (0x3F & char_to_code(in[4*i] )) << 18; 232 | b |= (0x3F & char_to_code(in[4*i + 1])) << 12; 233 | out[3*i + 0] = (b >> 16) & 0xFF; 234 | if (((b >> 12) & 0x0F) != 0) { 235 | DEBUG("WARNING: last character contains unusable bits\n"); 236 | } 237 | } else if (last_bytes == 2) { 238 | b = (0x3F & char_to_code(in[4*i] )) << 18; 239 | b |= (0x3F & char_to_code(in[4*i + 1])) << 12; 240 | b |= (0x3F & char_to_code(in[4*i + 2])) << 6; 241 | out[3*i + 0] = (b >> 16) & 0xFF; 242 | out[3*i + 1] = (b >> 8 ) & 0xFF; 243 | if (((b >> 6) & 0x03) != 0) { 244 | DEBUG("WARNING: last character contains unusable bits\n"); 245 | } 246 | } 247 | 248 | return result_len; 249 | } 250 | 251 | int bin_to_b64(const uint8_t * in, int size, char * out, int max_len) { 252 | int ret; 253 | 254 | ret = bin_to_b64_nopad(in, size, out, max_len); 255 | 256 | if (ret == -1) { 257 | return -1; 258 | } 259 | switch (ret%4) { 260 | case 0: /* nothing to do */ 261 | return ret; 262 | case 1: 263 | DEBUG("ERROR: INVALID UNPADDED BASE64 STRING\n"); 264 | return -1; 265 | case 2: /* 2 chars in last block, must add 2 padding char */ 266 | if (max_len >= (ret + 2 + 1)) { 267 | out[ret] = code_pad; 268 | out[ret+1] = code_pad; 269 | out[ret+2] = 0; 270 | return ret+2; 271 | } else { 272 | DEBUG("ERROR: not enough room to add padding in bin_to_b64\n"); 273 | return -1; 274 | } 275 | case 3: /* 3 chars in last block, must add 1 padding char */ 276 | if (max_len >= (ret + 1 + 1)) { 277 | out[ret] = code_pad; 278 | out[ret+1] = 0; 279 | return ret+1; 280 | } else { 281 | DEBUG("ERROR: not enough room to add padding in bin_to_b64\n"); 282 | return -1; 283 | } 284 | default: 285 | CRIT("switch default that should not be possible"); 286 | } 287 | } 288 | 289 | int b64_to_bin(const char * in, int size, uint8_t * out, int max_len) { 290 | if (in == NULL) { 291 | DEBUG("ERROR: NULL POINTER AS OUTPUT OR INPUT IN B64_TO_BIN\n"); 292 | return -1; 293 | } 294 | if ((size%4 == 0) && (size >= 4)) { /* potentially padded Base64 */ 295 | if (in[size-2] == code_pad) { /* 2 padding char to ignore */ 296 | return b64_to_bin_nopad(in, size-2, out, max_len); 297 | } else if (in[size-1] == code_pad) { /* 1 padding char to ignore */ 298 | return b64_to_bin_nopad(in, size-1, out, max_len); 299 | } else { /* no padding to ignore */ 300 | return b64_to_bin_nopad(in, size, out, max_len); 301 | } 302 | } else { /* treat as unpadded Base64 */ 303 | return b64_to_bin_nopad(in, size, out, max_len); 304 | } 305 | } 306 | 307 | 308 | /* --- EOF ------------------------------------------------------------------ */ 309 | -------------------------------------------------------------------------------- /poly_pkt_fwd/src/base64.c: -------------------------------------------------------------------------------- 1 | /* 2 | / _____) _ | | 3 | ( (____ _____ ____ _| |_ _____ ____| |__ 4 | \____ \| ___ | (_ _) ___ |/ ___) _ \ 5 | _____) ) ____| | | || |_| ____( (___| | | | 6 | (______/|_____)_|_|_| \__)_____)\____)_| |_| 7 | (C)2013 Semtech-Cycleo 8 | 9 | Description: 10 | Base64 encoding & decoding library 11 | 12 | License: Revised BSD License, see LICENSE.TXT file include in the project 13 | Maintainer: Sylvain Miermont 14 | */ 15 | 16 | 17 | /* -------------------------------------------------------------------------- */ 18 | /* --- DEPENDANCIES --------------------------------------------------------- */ 19 | 20 | #include 21 | #include 22 | #include 23 | 24 | #include "base64.h" 25 | 26 | /* -------------------------------------------------------------------------- */ 27 | /* --- PRIVATE MACROS ------------------------------------------------------- */ 28 | 29 | #define ARRAY_SIZE(a) (sizeof(a) / sizeof((a)[0])) 30 | #define CRIT(a) fprintf(stderr, "\nCRITICAL file:%s line:%u msg:%s\n", __FILE__, __LINE__,a);exit(EXIT_FAILURE) 31 | 32 | //#define DEBUG(args...) fprintf(stderr,"debug: " args) /* diagnostic message that is destined to the user */ 33 | #define DEBUG(args...) 34 | 35 | /* -------------------------------------------------------------------------- */ 36 | /* --- PRIVATE CONSTANTS ---------------------------------------------------- */ 37 | 38 | /* -------------------------------------------------------------------------- */ 39 | /* --- PRIVATE MODULE-WIDE VARIABLES ---------------------------------------- */ 40 | 41 | static char code_62 = '+'; /* RFC 1421 standard character for code 62 */ 42 | static char code_63 = '/'; /* RFC 1421 standard character for code 63 */ 43 | static char code_pad = '='; /* RFC 1421 padding character if padding */ 44 | 45 | /* -------------------------------------------------------------------------- */ 46 | /* --- PRIVATE FUNCTIONS DECLARATION ---------------------------------------- */ 47 | 48 | /** 49 | @brief Convert a code in the range 0-63 to an ASCII character 50 | */ 51 | char code_to_char(uint8_t x); 52 | 53 | /** 54 | @brief Convert an ASCII character to a code in the range 0-63 55 | */ 56 | uint8_t char_to_code(char x); 57 | 58 | /* -------------------------------------------------------------------------- */ 59 | /* --- PRIVATE FUNCTIONS DEFINITION ----------------------------------------- */ 60 | 61 | char code_to_char(uint8_t x) { 62 | if (x <= 25) { 63 | return 'A' + x; 64 | } else if ((x >= 26) && (x <= 51)) { 65 | return 'a' + (x-26); 66 | } else if ((x >= 52) && (x <= 61)) { 67 | return '0' + (x-52); 68 | } else if (x == 62) { 69 | return code_62; 70 | } else if (x == 63) { 71 | return code_63; 72 | } else { 73 | DEBUG("ERROR: %i IS OUT OF RANGE 0-63 FOR BASE64 ENCODING\n", x); 74 | exit(EXIT_FAILURE); 75 | } //TODO: improve error management 76 | } 77 | 78 | uint8_t char_to_code(char x) { 79 | if ((x >= 'A') && (x <= 'Z')) { 80 | return (uint8_t)x - (uint8_t)'A'; 81 | } else if ((x >= 'a') && (x <= 'z')) { 82 | return (uint8_t)x - (uint8_t)'a' + 26; 83 | } else if ((x >= '0') && (x <= '9')) { 84 | return (uint8_t)x - (uint8_t)'0' + 52; 85 | } else if (x == code_62) { 86 | return 62; 87 | } else if (x == code_63) { 88 | return 63; 89 | } else { 90 | DEBUG("ERROR: %c (0x%x) IS INVALID CHARACTER FOR BASE64 DECODING\n", x, x); 91 | exit(EXIT_FAILURE); 92 | } //TODO: improve error management 93 | } 94 | 95 | /* -------------------------------------------------------------------------- */ 96 | /* --- PUBLIC FUNCTIONS DEFINITION ------------------------------------------ */ 97 | 98 | int bin_to_b64_nopad(const uint8_t * in, int size, char * out, int max_len) { 99 | int i; 100 | int result_len; /* size of the result */ 101 | int full_blocks; /* number of 3 unsigned chars / 4 characters blocks */ 102 | int last_bytes; /* number of unsigned chars <3 in the last block */ 103 | int last_chars; /* number of characters <4 in the last block */ 104 | uint32_t b; 105 | 106 | /* check input values */ 107 | if ((out == NULL) || (in == NULL)) { 108 | DEBUG("ERROR: NULL POINTER AS OUTPUT IN BIN_TO_B64\n"); 109 | return -1; 110 | } 111 | if (size == 0) { 112 | *out = 0; /* null string */ 113 | return 0; 114 | } 115 | 116 | /* calculate the number of base64 'blocks' */ 117 | full_blocks = size / 3; 118 | last_bytes = size % 3; 119 | switch (last_bytes) { 120 | case 0: /* no byte left to encode */ 121 | last_chars = 0; 122 | break; 123 | case 1: /* 1 byte left to encode -> +2 chars */ 124 | last_chars = 2; 125 | break; 126 | case 2: /* 2 bytes left to encode -> +3 chars */ 127 | last_chars = 3; 128 | break; 129 | default: 130 | CRIT("switch default that should not be possible"); 131 | } 132 | 133 | /* check if output buffer is big enough */ 134 | result_len = (4*full_blocks) + last_chars; 135 | if (max_len < (result_len + 1)) { /* 1 char added for string terminator */ 136 | DEBUG("ERROR: OUTPUT BUFFER TOO SMALL IN BIN_TO_B64\n"); 137 | return -1; 138 | } 139 | 140 | /* process all the full blocks */ 141 | for (i=0; i < full_blocks; ++i) { 142 | b = (0xFF & in[3*i] ) << 16; 143 | b |= (0xFF & in[3*i + 1]) << 8; 144 | b |= 0xFF & in[3*i + 2]; 145 | out[4*i + 0] = code_to_char((b >> 18) & 0x3F); 146 | out[4*i + 1] = code_to_char((b >> 12) & 0x3F); 147 | out[4*i + 2] = code_to_char((b >> 6 ) & 0x3F); 148 | out[4*i + 3] = code_to_char( b & 0x3F); 149 | } 150 | 151 | /* process the last 'partial' block and terminate string */ 152 | i = full_blocks; 153 | if (last_chars == 0) { 154 | out[4*i] = 0; /* null character to terminate string */ 155 | } else if (last_chars == 2) { 156 | b = (0xFF & in[3*i] ) << 16; 157 | out[4*i + 0] = code_to_char((b >> 18) & 0x3F); 158 | out[4*i + 1] = code_to_char((b >> 12) & 0x3F); 159 | out[4*i + 2] = 0; /* null character to terminate string */ 160 | } else if (last_chars == 3) { 161 | b = (0xFF & in[3*i] ) << 16; 162 | b |= (0xFF & in[3*i + 1]) << 8; 163 | out[4*i + 0] = code_to_char((b >> 18) & 0x3F); 164 | out[4*i + 1] = code_to_char((b >> 12) & 0x3F); 165 | out[4*i + 2] = code_to_char((b >> 6 ) & 0x3F); 166 | out[4*i + 3] = 0; /* null character to terminate string */ 167 | } 168 | 169 | return result_len; 170 | } 171 | 172 | int b64_to_bin_nopad(const char * in, int size, uint8_t * out, int max_len) { 173 | int i; 174 | int result_len; /* size of the result */ 175 | int full_blocks; /* number of 3 unsigned chars / 4 characters blocks */ 176 | int last_chars; /* number of characters <4 in the last block */ 177 | int last_bytes; /* number of unsigned chars <3 in the last block */ 178 | uint32_t b; 179 | ; 180 | 181 | /* check input values */ 182 | if ((out == NULL) || (in == NULL)) { 183 | DEBUG("ERROR: NULL POINTER AS OUTPUT OR INPUT IN B64_TO_BIN\n"); 184 | return -1; 185 | } 186 | if (size == 0) { 187 | return 0; 188 | } 189 | 190 | /* calculate the number of base64 'blocks' */ 191 | full_blocks = size / 4; 192 | last_chars = size % 4; 193 | switch (last_chars) { 194 | case 0: /* no char left to decode */ 195 | last_bytes = 0; 196 | break; 197 | case 1: /* only 1 char left is an error */ 198 | DEBUG("ERROR: ONLY ONE CHAR LEFT IN B64_TO_BIN\n"); 199 | return -1; 200 | case 2: /* 2 chars left to decode -> +1 byte */ 201 | last_bytes = 1; 202 | break; 203 | case 3: /* 3 chars left to decode -> +2 bytes */ 204 | last_bytes = 2; 205 | break; 206 | default: 207 | CRIT("switch default that should not be possible"); 208 | } 209 | 210 | /* check if output buffer is big enough */ 211 | result_len = (3*full_blocks) + last_bytes; 212 | if (max_len < result_len) { 213 | DEBUG("ERROR: OUTPUT BUFFER TOO SMALL IN B64_TO_BIN\n"); 214 | return -1; 215 | } 216 | 217 | /* process all the full blocks */ 218 | for (i=0; i < full_blocks; ++i) { 219 | b = (0x3F & char_to_code(in[4*i] )) << 18; 220 | b |= (0x3F & char_to_code(in[4*i + 1])) << 12; 221 | b |= (0x3F & char_to_code(in[4*i + 2])) << 6; 222 | b |= 0x3F & char_to_code(in[4*i + 3]); 223 | out[3*i + 0] = (b >> 16) & 0xFF; 224 | out[3*i + 1] = (b >> 8 ) & 0xFF; 225 | out[3*i + 2] = b & 0xFF; 226 | } 227 | 228 | /* process the last 'partial' block */ 229 | i = full_blocks; 230 | if (last_bytes == 1) { 231 | b = (0x3F & char_to_code(in[4*i] )) << 18; 232 | b |= (0x3F & char_to_code(in[4*i + 1])) << 12; 233 | out[3*i + 0] = (b >> 16) & 0xFF; 234 | if (((b >> 12) & 0x0F) != 0) { 235 | DEBUG("WARNING: last character contains unusable bits\n"); 236 | } 237 | } else if (last_bytes == 2) { 238 | b = (0x3F & char_to_code(in[4*i] )) << 18; 239 | b |= (0x3F & char_to_code(in[4*i + 1])) << 12; 240 | b |= (0x3F & char_to_code(in[4*i + 2])) << 6; 241 | out[3*i + 0] = (b >> 16) & 0xFF; 242 | out[3*i + 1] = (b >> 8 ) & 0xFF; 243 | if (((b >> 6) & 0x03) != 0) { 244 | DEBUG("WARNING: last character contains unusable bits\n"); 245 | } 246 | } 247 | 248 | return result_len; 249 | } 250 | 251 | int bin_to_b64(const uint8_t * in, int size, char * out, int max_len) { 252 | int ret; 253 | 254 | ret = bin_to_b64_nopad(in, size, out, max_len); 255 | 256 | if (ret == -1) { 257 | return -1; 258 | } 259 | switch (ret%4) { 260 | case 0: /* nothing to do */ 261 | return ret; 262 | case 1: 263 | DEBUG("ERROR: INVALID UNPADDED BASE64 STRING\n"); 264 | return -1; 265 | case 2: /* 2 chars in last block, must add 2 padding char */ 266 | if (max_len >= (ret + 2 + 1)) { 267 | out[ret] = code_pad; 268 | out[ret+1] = code_pad; 269 | out[ret+2] = 0; 270 | return ret+2; 271 | } else { 272 | DEBUG("ERROR: not enough room to add padding in bin_to_b64\n"); 273 | return -1; 274 | } 275 | case 3: /* 3 chars in last block, must add 1 padding char */ 276 | if (max_len >= (ret + 1 + 1)) { 277 | out[ret] = code_pad; 278 | out[ret+1] = 0; 279 | return ret+1; 280 | } else { 281 | DEBUG("ERROR: not enough room to add padding in bin_to_b64\n"); 282 | return -1; 283 | } 284 | default: 285 | CRIT("switch default that should not be possible"); 286 | } 287 | } 288 | 289 | int b64_to_bin(const char * in, int size, uint8_t * out, int max_len) { 290 | if (in == NULL) { 291 | DEBUG("ERROR: NULL POINTER AS OUTPUT OR INPUT IN B64_TO_BIN\n"); 292 | return -1; 293 | } 294 | if ((size%4 == 0) && (size >= 4)) { /* potentially padded Base64 */ 295 | if (in[size-2] == code_pad) { /* 2 padding char to ignore */ 296 | return b64_to_bin_nopad(in, size-2, out, max_len); 297 | } else if (in[size-1] == code_pad) { /* 1 padding char to ignore */ 298 | return b64_to_bin_nopad(in, size-1, out, max_len); 299 | } else { /* no padding to ignore */ 300 | return b64_to_bin_nopad(in, size, out, max_len); 301 | } 302 | } else { /* treat as unpadded Base64 */ 303 | return b64_to_bin_nopad(in, size, out, max_len); 304 | } 305 | } 306 | 307 | 308 | /* --- EOF ------------------------------------------------------------------ */ 309 | -------------------------------------------------------------------------------- /util_tx_test/src/base64.c: -------------------------------------------------------------------------------- 1 | /* 2 | / _____) _ | | 3 | ( (____ _____ ____ _| |_ _____ ____| |__ 4 | \____ \| ___ | (_ _) ___ |/ ___) _ \ 5 | _____) ) ____| | | || |_| ____( (___| | | | 6 | (______/|_____)_|_|_| \__)_____)\____)_| |_| 7 | (C)2013 Semtech-Cycleo 8 | 9 | Description: 10 | Base64 encoding & decoding library 11 | 12 | License: Revised BSD License, see LICENSE.TXT file include in the project 13 | Maintainer: Sylvain Miermont 14 | */ 15 | 16 | 17 | /* -------------------------------------------------------------------------- */ 18 | /* --- DEPENDANCIES --------------------------------------------------------- */ 19 | 20 | #include 21 | #include 22 | #include 23 | 24 | #include "base64.h" 25 | 26 | /* -------------------------------------------------------------------------- */ 27 | /* --- PRIVATE MACROS ------------------------------------------------------- */ 28 | 29 | #define ARRAY_SIZE(a) (sizeof(a) / sizeof((a)[0])) 30 | #define CRIT(a) fprintf(stderr, "\nCRITICAL file:%s line:%u msg:%s\n", __FILE__, __LINE__,a);exit(EXIT_FAILURE) 31 | 32 | //#define DEBUG(args...) fprintf(stderr,"debug: " args) /* diagnostic message that is destined to the user */ 33 | #define DEBUG(args...) 34 | 35 | /* -------------------------------------------------------------------------- */ 36 | /* --- PRIVATE CONSTANTS ---------------------------------------------------- */ 37 | 38 | /* -------------------------------------------------------------------------- */ 39 | /* --- PRIVATE MODULE-WIDE VARIABLES ---------------------------------------- */ 40 | 41 | static char code_62 = '+'; /* RFC 1421 standard character for code 62 */ 42 | static char code_63 = '/'; /* RFC 1421 standard character for code 63 */ 43 | static char code_pad = '='; /* RFC 1421 padding character if padding */ 44 | 45 | /* -------------------------------------------------------------------------- */ 46 | /* --- PRIVATE FUNCTIONS DECLARATION ---------------------------------------- */ 47 | 48 | /** 49 | @brief Convert a code in the range 0-63 to an ASCII character 50 | */ 51 | char code_to_char(uint8_t x); 52 | 53 | /** 54 | @brief Convert an ASCII character to a code in the range 0-63 55 | */ 56 | uint8_t char_to_code(char x); 57 | 58 | /* -------------------------------------------------------------------------- */ 59 | /* --- PRIVATE FUNCTIONS DEFINITION ----------------------------------------- */ 60 | 61 | char code_to_char(uint8_t x) { 62 | if (x <= 25) { 63 | return 'A' + x; 64 | } else if ((x >= 26) && (x <= 51)) { 65 | return 'a' + (x-26); 66 | } else if ((x >= 52) && (x <= 61)) { 67 | return '0' + (x-52); 68 | } else if (x == 62) { 69 | return code_62; 70 | } else if (x == 63) { 71 | return code_63; 72 | } else { 73 | DEBUG("ERROR: %i IS OUT OF RANGE 0-63 FOR BASE64 ENCODING\n", x); 74 | exit(EXIT_FAILURE); 75 | } //TODO: improve error management 76 | } 77 | 78 | uint8_t char_to_code(char x) { 79 | if ((x >= 'A') && (x <= 'Z')) { 80 | return (uint8_t)x - (uint8_t)'A'; 81 | } else if ((x >= 'a') && (x <= 'z')) { 82 | return (uint8_t)x - (uint8_t)'a' + 26; 83 | } else if ((x >= '0') && (x <= '9')) { 84 | return (uint8_t)x - (uint8_t)'0' + 52; 85 | } else if (x == code_62) { 86 | return 62; 87 | } else if (x == code_63) { 88 | return 63; 89 | } else { 90 | DEBUG("ERROR: %c (0x%x) IS INVALID CHARACTER FOR BASE64 DECODING\n", x, x); 91 | exit(EXIT_FAILURE); 92 | } //TODO: improve error management 93 | } 94 | 95 | /* -------------------------------------------------------------------------- */ 96 | /* --- PUBLIC FUNCTIONS DEFINITION ------------------------------------------ */ 97 | 98 | int bin_to_b64_nopad(const uint8_t * in, int size, char * out, int max_len) { 99 | int i; 100 | int result_len; /* size of the result */ 101 | int full_blocks; /* number of 3 unsigned chars / 4 characters blocks */ 102 | int last_bytes; /* number of unsigned chars <3 in the last block */ 103 | int last_chars; /* number of characters <4 in the last block */ 104 | uint32_t b; 105 | 106 | /* check input values */ 107 | if ((out == NULL) || (in == NULL)) { 108 | DEBUG("ERROR: NULL POINTER AS OUTPUT IN BIN_TO_B64\n"); 109 | return -1; 110 | } 111 | if (size == 0) { 112 | *out = 0; /* null string */ 113 | return 0; 114 | } 115 | 116 | /* calculate the number of base64 'blocks' */ 117 | full_blocks = size / 3; 118 | last_bytes = size % 3; 119 | switch (last_bytes) { 120 | case 0: /* no byte left to encode */ 121 | last_chars = 0; 122 | break; 123 | case 1: /* 1 byte left to encode -> +2 chars */ 124 | last_chars = 2; 125 | break; 126 | case 2: /* 2 bytes left to encode -> +3 chars */ 127 | last_chars = 3; 128 | break; 129 | default: 130 | CRIT("switch default that should not be possible"); 131 | } 132 | 133 | /* check if output buffer is big enough */ 134 | result_len = (4*full_blocks) + last_chars; 135 | if (max_len < (result_len + 1)) { /* 1 char added for string terminator */ 136 | DEBUG("ERROR: OUTPUT BUFFER TOO SMALL IN BIN_TO_B64\n"); 137 | return -1; 138 | } 139 | 140 | /* process all the full blocks */ 141 | for (i=0; i < full_blocks; ++i) { 142 | b = (0xFF & in[3*i] ) << 16; 143 | b |= (0xFF & in[3*i + 1]) << 8; 144 | b |= 0xFF & in[3*i + 2]; 145 | out[4*i + 0] = code_to_char((b >> 18) & 0x3F); 146 | out[4*i + 1] = code_to_char((b >> 12) & 0x3F); 147 | out[4*i + 2] = code_to_char((b >> 6 ) & 0x3F); 148 | out[4*i + 3] = code_to_char( b & 0x3F); 149 | } 150 | 151 | /* process the last 'partial' block and terminate string */ 152 | i = full_blocks; 153 | if (last_chars == 0) { 154 | out[4*i] = 0; /* null character to terminate string */ 155 | } else if (last_chars == 2) { 156 | b = (0xFF & in[3*i] ) << 16; 157 | out[4*i + 0] = code_to_char((b >> 18) & 0x3F); 158 | out[4*i + 1] = code_to_char((b >> 12) & 0x3F); 159 | out[4*i + 2] = 0; /* null character to terminate string */ 160 | } else if (last_chars == 3) { 161 | b = (0xFF & in[3*i] ) << 16; 162 | b |= (0xFF & in[3*i + 1]) << 8; 163 | out[4*i + 0] = code_to_char((b >> 18) & 0x3F); 164 | out[4*i + 1] = code_to_char((b >> 12) & 0x3F); 165 | out[4*i + 2] = code_to_char((b >> 6 ) & 0x3F); 166 | out[4*i + 3] = 0; /* null character to terminate string */ 167 | } 168 | 169 | return result_len; 170 | } 171 | 172 | int b64_to_bin_nopad(const char * in, int size, uint8_t * out, int max_len) { 173 | int i; 174 | int result_len; /* size of the result */ 175 | int full_blocks; /* number of 3 unsigned chars / 4 characters blocks */ 176 | int last_chars; /* number of characters <4 in the last block */ 177 | int last_bytes; /* number of unsigned chars <3 in the last block */ 178 | uint32_t b; 179 | ; 180 | 181 | /* check input values */ 182 | if ((out == NULL) || (in == NULL)) { 183 | DEBUG("ERROR: NULL POINTER AS OUTPUT OR INPUT IN B64_TO_BIN\n"); 184 | return -1; 185 | } 186 | if (size == 0) { 187 | return 0; 188 | } 189 | 190 | /* calculate the number of base64 'blocks' */ 191 | full_blocks = size / 4; 192 | last_chars = size % 4; 193 | switch (last_chars) { 194 | case 0: /* no char left to decode */ 195 | last_bytes = 0; 196 | break; 197 | case 1: /* only 1 char left is an error */ 198 | DEBUG("ERROR: ONLY ONE CHAR LEFT IN B64_TO_BIN\n"); 199 | return -1; 200 | case 2: /* 2 chars left to decode -> +1 byte */ 201 | last_bytes = 1; 202 | break; 203 | case 3: /* 3 chars left to decode -> +2 bytes */ 204 | last_bytes = 2; 205 | break; 206 | default: 207 | CRIT("switch default that should not be possible"); 208 | } 209 | 210 | /* check if output buffer is big enough */ 211 | result_len = (3*full_blocks) + last_bytes; 212 | if (max_len < result_len) { 213 | DEBUG("ERROR: OUTPUT BUFFER TOO SMALL IN B64_TO_BIN\n"); 214 | return -1; 215 | } 216 | 217 | /* process all the full blocks */ 218 | for (i=0; i < full_blocks; ++i) { 219 | b = (0x3F & char_to_code(in[4*i] )) << 18; 220 | b |= (0x3F & char_to_code(in[4*i + 1])) << 12; 221 | b |= (0x3F & char_to_code(in[4*i + 2])) << 6; 222 | b |= 0x3F & char_to_code(in[4*i + 3]); 223 | out[3*i + 0] = (b >> 16) & 0xFF; 224 | out[3*i + 1] = (b >> 8 ) & 0xFF; 225 | out[3*i + 2] = b & 0xFF; 226 | } 227 | 228 | /* process the last 'partial' block */ 229 | i = full_blocks; 230 | if (last_bytes == 1) { 231 | b = (0x3F & char_to_code(in[4*i] )) << 18; 232 | b |= (0x3F & char_to_code(in[4*i + 1])) << 12; 233 | out[3*i + 0] = (b >> 16) & 0xFF; 234 | if (((b >> 12) & 0x0F) != 0) { 235 | DEBUG("WARNING: last character contains unusable bits\n"); 236 | } 237 | } else if (last_bytes == 2) { 238 | b = (0x3F & char_to_code(in[4*i] )) << 18; 239 | b |= (0x3F & char_to_code(in[4*i + 1])) << 12; 240 | b |= (0x3F & char_to_code(in[4*i + 2])) << 6; 241 | out[3*i + 0] = (b >> 16) & 0xFF; 242 | out[3*i + 1] = (b >> 8 ) & 0xFF; 243 | if (((b >> 6) & 0x03) != 0) { 244 | DEBUG("WARNING: last character contains unusable bits\n"); 245 | } 246 | } 247 | 248 | return result_len; 249 | } 250 | 251 | int bin_to_b64(const uint8_t * in, int size, char * out, int max_len) { 252 | int ret; 253 | 254 | ret = bin_to_b64_nopad(in, size, out, max_len); 255 | 256 | if (ret == -1) { 257 | return -1; 258 | } 259 | switch (ret%4) { 260 | case 0: /* nothing to do */ 261 | return ret; 262 | case 1: 263 | DEBUG("ERROR: INVALID UNPADDED BASE64 STRING\n"); 264 | return -1; 265 | case 2: /* 2 chars in last block, must add 2 padding char */ 266 | if (max_len > (ret + 2 + 1)) { 267 | out[ret] = code_pad; 268 | out[ret+1] = code_pad; 269 | out[ret+2] = 0; 270 | return ret+2; 271 | } else { 272 | DEBUG("ERROR: not enough room to add padding in bin_to_b64\n"); 273 | return -1; 274 | } 275 | case 3: /* 3 chars in last block, must add 1 padding char */ 276 | if (max_len > (ret + 1 + 1)) { 277 | out[ret] = code_pad; 278 | out[ret+1] = 0; 279 | return ret+1; 280 | } else { 281 | DEBUG("ERROR: not enough room to add padding in bin_to_b64\n"); 282 | return -1; 283 | } 284 | default: 285 | CRIT("switch default that should not be possible"); 286 | } 287 | } 288 | 289 | int b64_to_bin(const char * in, int size, uint8_t * out, int max_len) { 290 | if (in == NULL) { 291 | DEBUG("ERROR: NULL POINTER AS OUTPUT OR INPUT IN B64_TO_BIN\n"); 292 | return -1; 293 | } 294 | if ((size%4 == 0) && (size >= 4)) { /* potentially padded Base64 */ 295 | if (in[size-2] == code_pad) { /* 2 padding char to ignore */ 296 | return b64_to_bin_nopad(in, size-2, out, max_len); 297 | } else if (in[size-1] == code_pad) { /* 1 padding char to ignore */ 298 | return b64_to_bin_nopad(in, size-1, out, max_len); 299 | } else { /* no padding to ignore */ 300 | return b64_to_bin_nopad(in, size, out, max_len); 301 | } 302 | } else { /* treat as unpadded Base64 */ 303 | return b64_to_bin_nopad(in, size, out, max_len); 304 | } 305 | } 306 | 307 | 308 | /* --- EOF ------------------------------------------------------------------ */ 309 | -------------------------------------------------------------------------------- /basic_pkt_fwd/src/base64.c: -------------------------------------------------------------------------------- 1 | /* 2 | / _____) _ | | 3 | ( (____ _____ ____ _| |_ _____ ____| |__ 4 | \____ \| ___ | (_ _) ___ |/ ___) _ \ 5 | _____) ) ____| | | || |_| ____( (___| | | | 6 | (______/|_____)_|_|_| \__)_____)\____)_| |_| 7 | (C)2013 Semtech-Cycleo 8 | 9 | Description: 10 | Base64 encoding & decoding library 11 | 12 | License: Revised BSD License, see LICENSE.TXT file include in the project 13 | Maintainer: Sylvain Miermont 14 | */ 15 | 16 | 17 | /* -------------------------------------------------------------------------- */ 18 | /* --- DEPENDANCIES --------------------------------------------------------- */ 19 | 20 | #include 21 | #include 22 | #include 23 | 24 | #include "base64.h" 25 | 26 | /* -------------------------------------------------------------------------- */ 27 | /* --- PRIVATE MACROS ------------------------------------------------------- */ 28 | 29 | #define ARRAY_SIZE(a) (sizeof(a) / sizeof((a)[0])) 30 | #define CRIT(a) fprintf(stderr, "\nCRITICAL file:%s line:%u msg:%s\n", __FILE__, __LINE__,a);exit(EXIT_FAILURE) 31 | 32 | //#define DEBUG(args...) fprintf(stderr,"debug: " args) /* diagnostic message that is destined to the user */ 33 | #define DEBUG(args...) 34 | 35 | /* -------------------------------------------------------------------------- */ 36 | /* --- PRIVATE CONSTANTS ---------------------------------------------------- */ 37 | 38 | /* -------------------------------------------------------------------------- */ 39 | /* --- PRIVATE MODULE-WIDE VARIABLES ---------------------------------------- */ 40 | 41 | static char code_62 = '+'; /* RFC 1421 standard character for code 62 */ 42 | static char code_63 = '/'; /* RFC 1421 standard character for code 63 */ 43 | static char code_pad = '='; /* RFC 1421 padding character if padding */ 44 | 45 | /* -------------------------------------------------------------------------- */ 46 | /* --- PRIVATE FUNCTIONS DECLARATION ---------------------------------------- */ 47 | 48 | /** 49 | @brief Convert a code in the range 0-63 to an ASCII character 50 | */ 51 | char code_to_char(uint8_t x); 52 | 53 | /** 54 | @brief Convert an ASCII character to a code in the range 0-63 55 | */ 56 | uint8_t char_to_code(char x); 57 | 58 | /* -------------------------------------------------------------------------- */ 59 | /* --- PRIVATE FUNCTIONS DEFINITION ----------------------------------------- */ 60 | 61 | char code_to_char(uint8_t x) { 62 | if (x <= 25) { 63 | return 'A' + x; 64 | } else if ((x >= 26) && (x <= 51)) { 65 | return 'a' + (x-26); 66 | } else if ((x >= 52) && (x <= 61)) { 67 | return '0' + (x-52); 68 | } else if (x == 62) { 69 | return code_62; 70 | } else if (x == 63) { 71 | return code_63; 72 | } else { 73 | DEBUG("ERROR: %i IS OUT OF RANGE 0-63 FOR BASE64 ENCODING\n", x); 74 | exit(EXIT_FAILURE); 75 | } //TODO: improve error management 76 | } 77 | 78 | uint8_t char_to_code(char x) { 79 | if ((x >= 'A') && (x <= 'Z')) { 80 | return (uint8_t)x - (uint8_t)'A'; 81 | } else if ((x >= 'a') && (x <= 'z')) { 82 | return (uint8_t)x - (uint8_t)'a' + 26; 83 | } else if ((x >= '0') && (x <= '9')) { 84 | return (uint8_t)x - (uint8_t)'0' + 52; 85 | } else if (x == code_62) { 86 | return 62; 87 | } else if (x == code_63) { 88 | return 63; 89 | } else { 90 | DEBUG("ERROR: %c (0x%x) IS INVALID CHARACTER FOR BASE64 DECODING\n", x, x); 91 | exit(EXIT_FAILURE); 92 | } //TODO: improve error management 93 | } 94 | 95 | /* -------------------------------------------------------------------------- */ 96 | /* --- PUBLIC FUNCTIONS DEFINITION ------------------------------------------ */ 97 | 98 | int bin_to_b64_nopad(const uint8_t * in, int size, char * out, int max_len) { 99 | int i; 100 | int result_len; /* size of the result */ 101 | int full_blocks; /* number of 3 unsigned chars / 4 characters blocks */ 102 | int last_bytes; /* number of unsigned chars <3 in the last block */ 103 | int last_chars; /* number of characters <4 in the last block */ 104 | uint32_t b; 105 | 106 | /* check input values */ 107 | if ((out == NULL) || (in == NULL)) { 108 | DEBUG("ERROR: NULL POINTER AS OUTPUT IN BIN_TO_B64\n"); 109 | return -1; 110 | } 111 | if (size == 0) { 112 | *out = 0; /* null string */ 113 | return 0; 114 | } 115 | 116 | /* calculate the number of base64 'blocks' */ 117 | full_blocks = size / 3; 118 | last_bytes = size % 3; 119 | switch (last_bytes) { 120 | case 0: /* no byte left to encode */ 121 | last_chars = 0; 122 | break; 123 | case 1: /* 1 byte left to encode -> +2 chars */ 124 | last_chars = 2; 125 | break; 126 | case 2: /* 2 bytes left to encode -> +3 chars */ 127 | last_chars = 3; 128 | break; 129 | default: 130 | CRIT("switch default that should not be possible"); 131 | } 132 | 133 | /* check if output buffer is big enough */ 134 | result_len = (4*full_blocks) + last_chars; 135 | if (max_len < (result_len + 1)) { /* 1 char added for string terminator */ 136 | DEBUG("ERROR: OUTPUT BUFFER TOO SMALL IN BIN_TO_B64\n"); 137 | return -1; 138 | } 139 | 140 | /* process all the full blocks */ 141 | for (i=0; i < full_blocks; ++i) { 142 | b = (0xFF & in[3*i] ) << 16; 143 | b |= (0xFF & in[3*i + 1]) << 8; 144 | b |= 0xFF & in[3*i + 2]; 145 | out[4*i + 0] = code_to_char((b >> 18) & 0x3F); 146 | out[4*i + 1] = code_to_char((b >> 12) & 0x3F); 147 | out[4*i + 2] = code_to_char((b >> 6 ) & 0x3F); 148 | out[4*i + 3] = code_to_char( b & 0x3F); 149 | } 150 | 151 | /* process the last 'partial' block and terminate string */ 152 | i = full_blocks; 153 | if (last_chars == 0) { 154 | out[4*i] = 0; /* null character to terminate string */ 155 | } else if (last_chars == 2) { 156 | b = (0xFF & in[3*i] ) << 16; 157 | out[4*i + 0] = code_to_char((b >> 18) & 0x3F); 158 | out[4*i + 1] = code_to_char((b >> 12) & 0x3F); 159 | out[4*i + 2] = 0; /* null character to terminate string */ 160 | } else if (last_chars == 3) { 161 | b = (0xFF & in[3*i] ) << 16; 162 | b |= (0xFF & in[3*i + 1]) << 8; 163 | out[4*i + 0] = code_to_char((b >> 18) & 0x3F); 164 | out[4*i + 1] = code_to_char((b >> 12) & 0x3F); 165 | out[4*i + 2] = code_to_char((b >> 6 ) & 0x3F); 166 | out[4*i + 3] = 0; /* null character to terminate string */ 167 | } 168 | 169 | return result_len; 170 | } 171 | 172 | int b64_to_bin_nopad(const char * in, int size, uint8_t * out, int max_len) { 173 | int i; 174 | int result_len; /* size of the result */ 175 | int full_blocks; /* number of 3 unsigned chars / 4 characters blocks */ 176 | int last_chars; /* number of characters <4 in the last block */ 177 | int last_bytes; /* number of unsigned chars <3 in the last block */ 178 | uint32_t b; 179 | ; 180 | 181 | /* check input values */ 182 | if ((out == NULL) || (in == NULL)) { 183 | DEBUG("ERROR: NULL POINTER AS OUTPUT OR INPUT IN B64_TO_BIN\n"); 184 | return -1; 185 | } 186 | if (size == 0) { 187 | return 0; 188 | } 189 | 190 | /* calculate the number of base64 'blocks' */ 191 | full_blocks = size / 4; 192 | last_chars = size % 4; 193 | switch (last_chars) { 194 | case 0: /* no char left to decode */ 195 | last_bytes = 0; 196 | break; 197 | case 1: /* only 1 char left is an error */ 198 | DEBUG("ERROR: ONLY ONE CHAR LEFT IN B64_TO_BIN\n"); 199 | return -1; 200 | case 2: /* 2 chars left to decode -> +1 byte */ 201 | last_bytes = 1; 202 | break; 203 | case 3: /* 3 chars left to decode -> +2 bytes */ 204 | last_bytes = 2; 205 | break; 206 | default: 207 | CRIT("switch default that should not be possible"); 208 | } 209 | 210 | /* check if output buffer is big enough */ 211 | result_len = (3*full_blocks) + last_bytes; 212 | if (max_len < result_len) { 213 | DEBUG("ERROR: OUTPUT BUFFER TOO SMALL IN B64_TO_BIN\n"); 214 | return -1; 215 | } 216 | 217 | /* process all the full blocks */ 218 | for (i=0; i < full_blocks; ++i) { 219 | b = (0x3F & char_to_code(in[4*i] )) << 18; 220 | b |= (0x3F & char_to_code(in[4*i + 1])) << 12; 221 | b |= (0x3F & char_to_code(in[4*i + 2])) << 6; 222 | b |= 0x3F & char_to_code(in[4*i + 3]); 223 | out[3*i + 0] = (b >> 16) & 0xFF; 224 | out[3*i + 1] = (b >> 8 ) & 0xFF; 225 | out[3*i + 2] = b & 0xFF; 226 | } 227 | 228 | /* process the last 'partial' block */ 229 | i = full_blocks; 230 | if (last_bytes == 1) { 231 | b = (0x3F & char_to_code(in[4*i] )) << 18; 232 | b |= (0x3F & char_to_code(in[4*i + 1])) << 12; 233 | out[3*i + 0] = (b >> 16) & 0xFF; 234 | if (((b >> 12) & 0x0F) != 0) { 235 | DEBUG("WARNING: last character contains unusable bits\n"); 236 | } 237 | } else if (last_bytes == 2) { 238 | b = (0x3F & char_to_code(in[4*i] )) << 18; 239 | b |= (0x3F & char_to_code(in[4*i + 1])) << 12; 240 | b |= (0x3F & char_to_code(in[4*i + 2])) << 6; 241 | out[3*i + 0] = (b >> 16) & 0xFF; 242 | out[3*i + 1] = (b >> 8 ) & 0xFF; 243 | if (((b >> 6) & 0x03) != 0) { 244 | DEBUG("WARNING: last character contains unusable bits\n"); 245 | } 246 | } 247 | 248 | return result_len; 249 | } 250 | 251 | int bin_to_b64(const uint8_t * in, int size, char * out, int max_len) { 252 | int ret; 253 | 254 | ret = bin_to_b64_nopad(in, size, out, max_len); 255 | 256 | if (ret == -1) { 257 | return -1; 258 | } 259 | switch (ret%4) { 260 | case 0: /* nothing to do */ 261 | return ret; 262 | case 1: 263 | DEBUG("ERROR: INVALID UNPADDED BASE64 STRING\n"); 264 | return -1; 265 | case 2: /* 2 chars in last block, must add 2 padding char */ 266 | if (max_len >= (ret + 2 + 1)) { 267 | out[ret] = code_pad; 268 | out[ret+1] = code_pad; 269 | out[ret+2] = 0; 270 | return ret+2; 271 | } else { 272 | DEBUG("ERROR: not enough room to add padding in bin_to_b64\n"); 273 | return -1; 274 | } 275 | case 3: /* 3 chars in last block, must add 1 padding char */ 276 | if (max_len >= (ret + 1 + 1)) { 277 | out[ret] = code_pad; 278 | out[ret+1] = 0; 279 | return ret+1; 280 | } else { 281 | DEBUG("ERROR: not enough room to add padding in bin_to_b64\n"); 282 | return -1; 283 | } 284 | default: 285 | CRIT("switch default that should not be possible"); 286 | } 287 | } 288 | 289 | int b64_to_bin(const char * in, int size, uint8_t * out, int max_len) { 290 | if (in == NULL) { 291 | DEBUG("ERROR: NULL POINTER AS OUTPUT OR INPUT IN B64_TO_BIN\n"); 292 | return -1; 293 | } 294 | if ((size%4 == 0) && (size >= 4)) { /* potentially padded Base64 */ 295 | if (in[size-2] == code_pad) { /* 2 padding char to ignore */ 296 | return b64_to_bin_nopad(in, size-2, out, max_len); 297 | } else if (in[size-1] == code_pad) { /* 1 padding char to ignore */ 298 | return b64_to_bin_nopad(in, size-1, out, max_len); 299 | } else { /* no padding to ignore */ 300 | return b64_to_bin_nopad(in, size, out, max_len); 301 | } 302 | } else { /* treat as unpadded Base64 */ 303 | return b64_to_bin_nopad(in, size, out, max_len); 304 | } 305 | } 306 | 307 | 308 | /* --- EOF ------------------------------------------------------------------ */ 309 | --------------------------------------------------------------------------------