summaryrefslogtreecommitdiff
path: root/recipes-connectivity/lora
diff options
context:
space:
mode:
Diffstat (limited to 'recipes-connectivity/lora')
-rw-r--r--recipes-connectivity/lora/lora-packet-forwarder/lora-packet-forwarder-duty-cycle.patch76
1 files changed, 76 insertions, 0 deletions
diff --git a/recipes-connectivity/lora/lora-packet-forwarder/lora-packet-forwarder-duty-cycle.patch b/recipes-connectivity/lora/lora-packet-forwarder/lora-packet-forwarder-duty-cycle.patch
new file mode 100644
index 0000000..ee9ecf4
--- /dev/null
+++ b/recipes-connectivity/lora/lora-packet-forwarder/lora-packet-forwarder-duty-cycle.patch
@@ -0,0 +1,76 @@
+diff --git a/lora_pkt_fwd/src/lora_pkt_fwd.c b/lora_pkt_fwd/src/lora_pkt_fwd.c
+index 801f28d..7b63b8f 100644
+--- a/lora_pkt_fwd/src/lora_pkt_fwd.c
++++ b/lora_pkt_fwd/src/lora_pkt_fwd.c
+@@ -134,7 +134,13 @@ static char serv_port_up[8] = STR(DEFAULT_PORT_UP); /* server port for upstream traffic */
+ static char serv_port_down[8] = STR(DEFAULT_PORT_DW); /* server port for downstream traffic */
+ static int keepalive_time = DEFAULT_KEEPALIVE; /* send a PULL_DATA request every X seconds, negative = disabled */
+
++static bool duty_cycle_enabled = true;
++static uint32_t duty_cycle_time_avail = 0;
++static uint32_t duty_cycle_period = 3600; // seconds in one hour
++static double duty_cycle_ratio = 0.10; // 10%
++static uint32_t duty_cycle_time_max = 3600 * 0.10 * 1000u; // max time-on-air in window
++
+ /* statistics collection configuration variables */
+ static unsigned stat_interval = DEFAULT_STAT; /* time interval (in sec) at which statistics are collected and displayed */
+
+@@ -729,8 +746,32 @@ static int parse_gateway_configuration(const char * conf_file) {
+ push_timeout_half.tv_usec = 500 * (long int)json_value_get_number(val);
+ MSG("INFO: upstream PUSH_DATA time-out is configured to %u ms\n", (unsigned)(push_timeout_half.tv_usec / 500));
+ }
++
++ /* duty-cycle limiting */
++ val = json_object_get_value(conf_obj, "duty_cycle_enabled");
++ if (json_value_get_type(val) == JSONBoolean) {
++ duty_cycle_enabled = (bool)json_value_get_boolean(val);
++ }
++ MSG("INFO: duty cycle will%s be enforced\n", (duty_cycle_enabled ? "" : " NOT"));
++
++ if (duty_cycle_enabled) {
++ val = json_object_get_value(conf_obj, "duty_cycle_period");
++ if (val != NULL) {
++ duty_cycle_period = (unsigned)json_value_get_number(val);
++ }
++ MSG("INFO: duty cycle period %u s\n", (duty_cycle_period));
++
++ val = json_object_get_value(conf_obj, "duty_cycle_ratio");
++ if (val != NULL) {
++ duty_cycle_ratio = (double)json_value_get_number(val);
++ }
++ MSG("INFO: duty cycle %f %%\n", (duty_cycle_ratio * 100));
++
++ duty_cycle_time_max = duty_cycle_period * 1000u * duty_cycle_ratio;
++ }
++
+
+ /* packet filtering parameters */
+ val = json_object_get_value(conf_obj, "forward_crc_valid");
+ if (json_value_get_type(val) == JSONBoolean) {
+ fwd_valid_pkt = (bool)json_value_get_boolean(val);
+@@ -2833,6 +2921,25 @@ void thread_valid(void) {
+ while (!exit_sig && !quit_sig) {
+ wait_ms(1000);
+
++ if (duty_cycle_enabled) {
++ static struct timespec last = { 0, 0 };
++ struct timespec now;
++ clock_gettime(CLOCK_MONOTONIC, &now);
++
++ if (last.tv_sec != 0) {
++ // uint64(now.tv_sec) * 1000 + now.tv_nsec / 1000000
++
++ duty_cycle_time_avail += difftimespec(now, last) * 1000u * duty_cycle_ratio;
++
++ if (duty_cycle_time_avail > duty_cycle_time_max) {
++ duty_cycle_time_avail = duty_cycle_time_max;
++ }
++ }
++
++ last = now;
++ }
++
++
+ /* calculate when the time reference was last updated */
+ pthread_mutex_lock(&mx_timeref);
+ gps_ref_age = (long)difftime(time(NULL), time_reference_gps.systime);