Skip to content

Thingsquare firmware SDK header file

This is the main header file for the Thingsquare firmware SDK. It
contains headers for the functions that a user application can call.

User applications may also use other APIs provided by the underlying
Contiki OS as well as the hardware libraries for the specific
hardware platform used.

Copyright 2012-2022 Thingsquare AB

```c#ifndef THSQ_H

define THSQ_H

### Include files

```c#include <stdint.h>
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include "contiki.h"
#include "contiki-lib.h"
#include "contiki-net.h"
#include "net/rpl/rpl.h"
#include "dev/leds.h"
#include "dev/watchdog.h"

Thingsquare event callbacks

A user application may provide one or more callback functions that
are called by the Thingsquare system when events occur. Examples of
events is when a new variable is set, a new command is received, or
when GPIO input changes.

Callback functions are added with the thsq_add_callback() function.

Thingsquare event definitions

Events of the enum thsq_reason type are passed along with the
callbacks.

```cenum thsq_reason {
THSQ_INITED,
THSQ_ERROR,
THSQ_PONG_RECEIVED,
THSQ_KEYVAL,
THSQ_AUTH,
THSQ_SERVER_CONNECTED,
THSQ_COMMAND,
THSQ_ZONEMSG,
THSQ_PERIOD,
THSQ_STATS,
THSQ_GPIO_INPUT,
THSQ_ACKED,
THSQ_BUTTONACTION
};

### Type definition of the callback function

```ctypedef void (*thsq_callback_fn)(enum thsq_reason reason, const char *str, int len);

Internal structure of the list of thsq callbacks

This data structure is to be configured as an opaque structure.

```cstruct thsq_callback {
struct thsq_callback *next;
thsq_callback_fn callback;
};

### Add a callback function

This function sets up a callback function to be called whenvever something happens.
The `struct thsq_callback` must be statically allocated by the caller.


```cvoid thsq_add_callback(struct thsq_callback *callback, thsq_callback_fn function);

Set platform name

The thsq_set_platform() function is used to inform the frontend what
platform the current device is running.

Typically, each customer's device type has a unique name that is used to
identify specific device behavior and firmware updates for the device.

The platform name is a non-NULL pointer to a printable-ASCII-string
that is NULL-terminated, and is at max 32 bytes long including
the terminator.

```cvoid thsq_set_platform(const char *platform);

## Serial line module

Captures input from UART, and enables an application to get line-buffered application callbacks.

```c
typedef void (*thsq_serialline_callback_fn)(const char *msg);
struct thsq_serialline_callback {
  struct thsq_serialline_callback *next;
  thsq_serialline_callback_fn callback;
};
void thsq_serialline_init(struct thsq_serialline_callback *c, thsq_serialline_callback_fn f);

Button actions module

The button actions module implements a set of commonly triggered device
actions by monitoring for button clicks.
Normal button clicks are available to handle at will by the application via the
THSQ_BUTTONACTION event. Button click series that are followed with a long press
trigger system operations such as 0) sending sensor data and BLE auth beacons,
1) push real good, 2) soft-unbonding, and 3) rebooting device.

```cvoid thsq_buttonactions_booted(int button_down);
void thsq_buttonactions_register(int button_down);

## The lighting control module

The lighting control module is a framework that provides zoned
lighting, lighting schedules, and prioritized triggers for light
switches, PIR sensors, and local controls.

The lighting module is initialized with `thsq_lighting_init()` and
`thsq_lighting_set_lamp()` (for lamps), and uses a complex set of local
and remote control mechanism to achieve
zoned lighting triggers across zones as well as remote control and
time-synchronized schedules.

The user hooks into the lighting control module with a callback
function that is registered with the `thsq_lighting_set_callback()`
function. The lighting callback receives a set of red, green, and
blue dimming values from 0 to 100. The callback should set the
output device's dimming levels accordingly.


### Type definition of the lighting module callback function

```ctypedef void (*thsq_lighting_callback_fn)(const uint8_t *rgb, int len, const char *reason);

void thsq_lighting_init(void);
void thsq_lighting_set_lamp(void);
struct thsq_lighting_callback {
  struct thsq_lighting_callback *next;
  thsq_lighting_callback_fn callback;
};
struct thsq_schedule;
void thsq_lighting_add_callback(struct thsq_lighting_callback *c, thsq_lighting_callback_fn f);
void thsq_lighting_set_default_lschedule(uint8_t *sched, int len);
void thsq_schedule_set_default(struct thsq_schedule *s, uint8_t *sched, int len);
void thsq_schedule_build_schedule_action(uint8_t *buf, int mon, int tue,
                                         int wed, int thu, int fri, int sat,
                                         int sun, uint8_t hours,
                                         uint8_t minutes, uint8_t red,
                                         uint8_t green, uint8_t blue);
void thsq_lighting_post_lights_variable(int active);

void thsq_lighting_lan_control_init(void);

Network time synchronization

If the device is time synchronized as indicated by thsq_has_time() == 1,
then thsq_get_time() returns the current Unix time (UTC) and
thsq_get_timezone_offset() the current timezone's seconds offset from UTC.
thsq_get_time_fine() returns the current Unix time in clock_time_t precision.

```cint thsq_has_time(void);
uint32_t thsq_get_time(void);
int32_t thsq_get_timezone_offset(void);
void thsq_set_time(uint32_t utc, int32_t tz_offset);
uint64_t thsq_get_time_high_precision(void);

## The general purpose I/O module

The general purpose I/O module provides a simple way to sample one
digital input pin and/or one analog input pin and to control one
digital output pin and/or one digital PWM output pin.

The general purpose I/O module uses a pin configuration setting that
can either be supplied via the `d` variable `pinconf`, which can be
set from the backend server, or from locally calling the function
`thsq_gpio_set_default()`.


```cvoid thsq_gpio_init(void);
void thsq_gpio_set_default(const char *def);

Bootloader configuration

The booloader can beconfigured with
BOOTLOADERPARAMS_OVERRIDE_XMEM_CONF(), which sets
up the flash chip configuration for the bootloader.

On platforms using cc13xx or cc26xx, the call has the following syntax:
BOOTLOADERPARAMS_OVERRIDE_XMEM_CONF(MISO, MOSI, CLK, CS);
where each pin is named eg IOID_2 for the DIO_2 pin.
Don't forget to include #include "ti-lib.h".

```cstruct thsq_bootloader_params
{
uint8_t bootloaderparams_active; / 0: false, 1: use config /

/ xmem configuration /
uint8_t xmem_conf; / 0: use defaults, 1: use below, 2: disable /
uint8_t xmem_miso; / xmem SPI MISO /
uint8_t xmem_mosi; / xmem SPI MOSI /
uint8_t xmem_clk; / xmem SPI CLK /
uint8_t xmem_cs; / xmem SPI CS /

uint8_t secure_boot_aes[16]; / secure boot AES key /

uint8_t reserved[9];
};

extern struct thsq_bootloader_params bootloaderparams;
#define BOOTLOADERPARAMS_OVERRIDE(active, conf, miso, mosi, clk, cs) \
struct thsq_bootloader_params bootloaderparams \
attribute ((section(".bootloaderparams"))) \
attribute ((used)) \
= {active, conf, miso, mosi, clk, cs, \
{ 0xff, 0xff, 0xff, 0xff, \
0xff, 0xff, 0xff, 0xff, \
0xff, 0xff, 0xff, 0xff, \
0xff, 0xff, 0xff, 0xff }, \
{ 0xff, 0xff, 0xff, 0xff, \
0xff, 0xff, 0xff, 0xff, \
0xff }}

#define BOOTLOADERPARAMS_OVERRIDE_XMEM_CONF(miso, mosi, clk, cs) \
BOOTLOADERPARAMS_OVERRIDE(1, 1, miso, mosi, clk, cs)

#define BOOTLOADERPARAMS_OVERRIDE_XMEM_DISABLE() \
BOOTLOADERPARAMS_OVERRIDE(1, 1, 0xff, 0xff, 0xff, 0xff)

## Server interaction functions

A device interacts with the backend server through a set of variables
and commands. Variables come in two forms: `d` variables and `s`
variables. `d` variables are shared between the device and the backend
and are synchronized when a device boots up. `s` variables are only
maintained on the server, but can be set from the device. Commands are
sent from the server to the device.

A device may set either `d` or `s` variables. After setting variables,
the new variables must be pushed to the server by calling the
`thsq_push()` function.

When a device received a new `d` variable, or a new value for an
existing variable, all application callbacks, that have been
previously registered with `thsq_add_callback()`, are called.

The value of a `d` variable may be read by calling the `thsq_get()` or
`thsq_get_to_buf()` functions.

A `d` variable is set with the `thsq_dset()` or `thsq_dest_str()`
functions. An `s` variable is set with the `thsq_sset()` or
`thsq_sset_str()` functions.

A variable must be at most `THSQ_MAX_VALLEN` bytes long.


```cvoid thsq_push(void);
enum thsq_err thsq_dset(const char *key, int val);
enum thsq_err thsq_dset_str(const char *key, const char *str);
enum thsq_err thsq_sset(const char *key, int val);
enum thsq_err thsq_sset_str(const char *key, const char *str);
enum thsq_err thsq_sset_printf(const char *key, const char *format, ...);
enum thsq_err thsq_sset_ptr(const char *key, const uint8_t *val, uint16_t vallen, int important);
enum thsq_err thsq_sset_ptr_timestamp(uint32_t timestamp, const char *key, const uint8_t *val, uint16_t vallen, int important);
enum thsq_err thsq_sset_timestamp(uint32_t timestamp, const char *key, int val);
enum thsq_err thsq_sset_str_timestamp(uint32_t timestamp, const char *key, const char *str);
enum thsq_err thsq_sset_printf_timestamp(uint32_t timestamp, const char *key, const char *format, ...);
enum thsq_err thsq_sset_printf_important_timestamp(uint32_t timestamp, const char *key, const char *format, ...);

int thsq_get(const char *key);
int thsq_get_to_buf(const char *key, uint8_t *buf, int buflen);

int thsq_equals(const char *key, const uint8_t *match, int matchlen);
int thsq_equals_str(const char *key, const char *match);

Get configuration options via d variable

Given that a d variable with the name "key" exists, and the value
has the string "substr" followed by a ':' character, this function
returns the long integer value that follows the ':' character.

```clong thsq_get_substr_long_arg(const char key, const char substr, int argnum, long default_val);

## Get a floating point option via d variable

Given that a d variable with the name "key" exists, and the value
has the string "substr" followed by a ':' character, this function
returns the float value that follows the ':' character.


```cfloat thsq_get_substr_float_arg(const char *key, const char *substr, int argnum, float default_val);

The maximum size of a variable value

```c#define THSQ_MAX_VALLEN 128

## Set device default mode

A device may be in either of three modes: `feather`, `connected`, and
`deadleaf`. The default mode is `feather`. In `feather` mode, the
device is responsive to variables and commands from the backend. In
`connected` mode, the device maintains a TLS connection to the
backend. This is primarily used to send firmware updates to individual
devices. In `deadleaf` mode, the device is off most of the time and
wakes up only now and then to receive new data from the backend. In
`deadleaf` mode, a device does not route packets through the mesh.

The mode of a device may be set from the backend by setting the `d`
variable called `mode`. If no `mode` variable is set, the device
defaults to the mode that has been set by the
`thsq_set_default_mode()` function

```cvoid thsq_set_default_mode(const char *mode);

Set device default power variable value, d.power

```cvoid thsq_set_default_power_conf(const char *powerconf);

## Disable the requirement for a valid digital signature for over-the-air firmware updates

By default, all binaries loaded over the air have a digital
signature that ensures that they were produced by the same entity
the produced the product they operate in. While this is essential
for deployed products, it may be problematic during product
development, before a solid key management policy has been
established.

This function allows the user application to override the
requirement for a valid digital signature. After calling this
function, the device will accept invalid signatures when loading
binaries over the air.


```cvoid thsq_disable_digital_signature(void);

Undocumented functions

These functions should not be used in production code as they may change.

Queue important variables module

The queue important variable module enables an application to queue up
timestamped important variables that are later sent to the server.
A queue is defined using the THSQ_QUEUE() macro, and must be initialized
using thsq_queue_init() before used. New data is added to the queue
with the thsq_queue_add() function.

#include "lib/list.h"
#include "lib/memb.h"
#include "sys/cc.h"

#define THSQ_QUEUE(name, structure, elements, send_callback) \
  struct CC_CONCAT(name,_meta) { \
    struct CC_CONCAT(name,_meta) *next; \
    clock_time_t timestamp; \
    const char *key; \
    structure data; \
  }; \
  MEMB(CC_CONCAT(name,_memb), struct CC_CONCAT(name,_meta), elements); \
  LIST(CC_CONCAT(name,_list)); \
  static struct thsq_queue name = { \
    NULL, \
    sizeof(structure), \
    0, \
    send_callback, \
    &CC_CONCAT(name,_memb), \
    (list_t *)&CC_CONCAT(name,_list) \
  }

struct thsq_queue;
typedef int (* thsq_queue_send_callback_t)(struct thsq_queue *q, uint32_t timestamp, const char *key, void *data); /* Returns 1 if sent */
struct thsq_queue {
  struct thsq_queue *next;
  int size;
  uint16_t internal;
  thsq_queue_send_callback_t send_callback;
  struct memb *memb;
  list_t *list;
};

void thsq_queue_init(struct thsq_queue *q);
int thsq_queue_free(struct thsq_queue *q); /* Number of available queue elements */
int thsq_queue_used(struct thsq_queue *q); /* Number of used queue elements */
enum thsq_err thsq_queue_add(struct thsq_queue *q, const char *key, void *element); /* Add new element to queue, returns 0 at success */
void thsq_queue_pause(struct thsq_queue *q, int paused); /* Pause sending data from queue */

void thsq_queue_send_reject_when_full(struct thsq_queue *q, int enabled); /* Reject elements when queue is full, instead of dropping oldest elements */
void thsq_queue_dont_pack_same_keys(struct thsq_queue *q, int dontpack);

Xmem queue xmem module

The xmem queue module enables an application to store application data in a queue in xmem.
As opposed to the regular queue module, elements that are stored in xmem survive device reboots.
Xmem also offers more data to be stored.
Features include: * Can store elements prior to receiving time synch * Support sending multiple elements in a single data packet, via thsq-queue * Similar API as thsq-queue

typedef int16_t thsq_xmem_page_t;

struct thsq_xmem_timestamps {
  uint32_t utc;
  clock_time_t clock;
} __attribute__((aligned(4)));

struct thsq_xmem_aes_ctx {
  uint8_t cbcmac[16];
  uint32_t ctr;
  uint32_t addr;
  thsq_xmem_page_t page;
} __attribute__((aligned(4)));

struct thsq_xmem_queue_header {
  uint8_t flags;
  uint8_t keyidx;
  struct thsq_xmem_timestamps timestamps;
};

struct thsq_xmem_stats {
  uint16_t count_waiting;
  uint16_t count_discarded;
  uint16_t count_acked;

  uint32_t count_tot_writes;
  uint32_t count_tot_sends;
  uint32_t count_tot_acks;
  uint32_t count_bad_entries;
  uint32_t count_not_found;
  uint32_t count_queue_full;
  uint32_t count_bad_acks;
} __attribute__((aligned(4)));

struct thsq_xmem_queue;
typedef enum thsq_err (* thsq_xmem_queue_send_callback_t)(struct thsq_xmem_queue *q, uint32_t timestamp, const char *key, void *data);

#define THSQ_XMEM_MAX_PAYLOAD_SIZE 256
#define THSQ_XMEM_SOFT_QUEUE_LEN 8
#define THSQ_XMEM_KEY_MEMORY_LENGTH 128
#define THSQ_XMEM_QUEUE(name, structure, send_callback, startpage, nrpages) \
  static struct thsq_xmem_queue name = { \
    NULL, \
    MIN(sizeof(structure),THSQ_XMEM_MAX_PAYLOAD_SIZE), \
    send_callback, \
    startpage, \
    nrpages, \
    { 0 }, \
    { 0 }, 0, \
    { { 0 }, 0, 0, 0 }, { { 0 }, 0, 0, 0 }, \
    0 \
  };

struct thsq_xmem_queue {
  struct thsq_xmem_queue *next;
  int data_size;
  thsq_xmem_queue_send_callback_t send_callback;

  thsq_xmem_page_t xmem_start_page;
  thsq_xmem_page_t xmem_nr_pages;

  struct thsq_xmem_stats stats;

  char key_memory[THSQ_XMEM_KEY_MEMORY_LENGTH];
  int key_count;

  struct thsq_xmem_aes_ctx aes_write;
  struct thsq_xmem_aes_ctx aes_read;

  uint8_t flags;
};

enum thsq_err thsq_xmem_queue_init(struct thsq_xmem_queue *xq);
enum thsq_err thsq_xmem_queue_validate(struct thsq_xmem_queue *q);

unsigned int thsq_xmem_queue_nr_used(struct thsq_xmem_queue *q);
unsigned int thsq_xmem_queue_nr_discarded(struct thsq_xmem_queue *q);
unsigned int thsq_xmem_queue_nr_acked(struct thsq_xmem_queue *q);
unsigned int thsq_xmem_queue_nr_waiting(struct thsq_xmem_queue *q);
unsigned int thsq_xmem_queue_nr_total(struct thsq_xmem_queue *q);
unsigned int thsq_xmem_queue_nr_free(struct thsq_xmem_queue *q);
uint32_t thsq_xmem_queue_nr_tot_writes(struct thsq_xmem_queue *q);
uint32_t thsq_xmem_queue_nr_tot_sends(struct thsq_xmem_queue *q);
uint32_t thsq_xmem_queue_nr_tot_acks(struct thsq_xmem_queue *q);
uint32_t thsq_xmem_queue_nr_bad_entries(struct thsq_xmem_queue *q);
uint32_t thsq_xmem_queue_nr_not_found(struct thsq_xmem_queue *q);
uint32_t thsq_xmem_queue_nr_queue_full(struct thsq_xmem_queue *q);
int thsq_xmem_queue_nr_keys(struct thsq_xmem_queue *q);

enum thsq_err thsq_xmem_queue_format(struct thsq_xmem_queue *q);
enum thsq_err thsq_xmem_queue_add(struct thsq_xmem_queue *q, const char* variable, void *element);

void thsq_xmem_queue_enable_remote_commands(void);

The GPIO input module

```cenum thsq_gpi_pull_type {
THSQ_GPI_PULL_UP,
THSQ_GPI_PULL_DOWN,
THSQ_GPI_PULL_NONE,
};
struct thsq_gpi_conf;
typedef void ( thsq_gpi_callback_t)(struct thsq_gpi_conf c, int val);
struct thsq_gpi_conf {
struct thsq_gpi_conf next;
uint32_t pin;
volatile uint8_t triggered, triggered_val;
uint8_t last_val;
thsq_gpi_callback_t callback_interrupt;
thsq_gpi_callback_t callback_user;
clock_time_t debouncetimeout;
struct etimer debouncetimer;
};
void thsq_gpi_cc26xx_cc13xx_conf(struct thsq_gpi_conf
c, uint32_t pin,
enum thsq_gpi_pull_type pulltype,
thsq_gpi_callback_t cb_interrupt,
thsq_gpi_callback_t cb_user,
clock_time_t debouncetimeout);
void thsq_gpi_unconf(struct thsq_gpi_conf c);
int thsq_gpi_value(struct thsq_gpi_conf
c);

void thsq_stats_blink_network_state(void);

## The GPIO output module

```cstruct thsq_gpo_conf;
struct thsq_gpo_conf {
  uint32_t pin;
};
void thsq_gpo_cc26xx_cc13xx_conf(struct thsq_gpo_conf *c, uint32_t pin);
void thsq_gpo_unconf(struct thsq_gpo_conf *c);
void thsq_gpo_set_value(struct thsq_gpo_conf *c, int val);

The ADC module

The ADC modules uses the built-in ADC for conversions. The implementation
and details vary depending on platform.

On CC13xx (eg CC1310, CC1352P), a conversion is blocking, and uses the 4.3V
internal reference. Since the ADC is 12-bit, the resulting range is
0..4096 LSB. To convert to mV, scale by 4300/4096. By default, the shortest
conversion time is used.

```cstruct thsq_adc_conf {
uint32_t pin;
uint8_t sampletime;
};
void thsq_adc_cc26xx_cc13xx_conf(struct thsq_adc_conf c, uint32_t pin);
void thsq_adc_unconf(struct thsq_adc_conf
c);
uint16_t thsq_adc_value(struct thsq_adc_conf *c);

## The I2C module

```cstruct thsq_i2c_conf {
  uint8_t slave_address;
  uint8_t interface;
  uint32_t pin_sda;
  uint32_t pin_scl;
  uint32_t speed;
};
void thsq_i2c_cc26xx_cc13xx_conf(struct thsq_i2c_conf *c,
                                 uint8_t slave_address,
                                 uint32_t sda, uint32_t scl,
                                 uint32_t speed);
void thsq_i2c_unconf(struct thsq_i2c_conf *c);
int thsq_i2c_write_read(struct thsq_i2c_conf *c, uint8_t *out, int outlen,
                        uint8_t *in, int inlen);

The SPI module

```cstruct thsq_spi_conf {
uint32_t cs; / if IOID_UNUSED, caller handles this pin /
uint32_t miso;
uint32_t mosi;
uint32_t clk;
uint32_t speed; / has a default, but can be overridden before any rw-call /
uint32_t mode;
uint8_t index;
};

enum thsq_spi_mode {
/ note: don't change order since this follows x0/x2 drivers /
THSQ_SPI_CPOL_0_CPHA_0 = 0,
THSQ_SPI_CPOL_0_CPHA_1,
THSQ_SPI_CPOL_1_CPHA_0,
THSQ_SPI_CPOL_1_CPHA_1,
};

define THSQ_SPI_DEFAULT_MODE THSQ_SPI_CPOL_0_CPHA_0

define THSQ_SPI_DEFAULT_SPEED 4000000ul

void thsq_spi_conf(struct thsq_spi_conf c,
uint32_t cs, uint32_t miso, uint32_t mosi, uint32_t clk,
uint32_t speed, enum thsq_spi_mode mode);
void thsq_spi_unconf(struct thsq_spi_conf
c);
int thsq_spi_write_read(struct thsq_spi_conf c, const uint8_t out, int outlen,
uint8_t in, int inlen);
int thsq_spi_write_read_with_prefix(struct thsq_spi_conf
c, const uint8_t preout,
int preoutlen, const uint8_t
out, int outlen, uint8_t in, int inlen);
int thsq_spi_transfer(struct thsq_spi_conf
c, const uint8_t from,
uint8_t
to, int len);

/ Legacy function, for backwards compability /
void thsq_spi_cc26xx_cc13xx_conf(struct thsq_spi_conf *c, uint32_t cs,
uint32_t miso, uint32_t mosi, uint32_t clk);

## The PWM module

The PWM module provides a simple way to configure pulse-width modulation (PWM) pins.


```cstruct thsq_pwm_conf {
  uint8_t port;
  int pin;
  int dutycycle;
  uint8_t timer;
  uint32_t gpt_base;
  unsigned long freq;
  int configured;
  int running;
};

void thsq_pwm_cc2538_conf(struct thsq_pwm_conf *c, uint8_t port, uint8_t pin,
                          uint8_t timer, unsigned long freq, int dutycycle);
void thsq_pwm_cc26xx_cc13xx_conf(struct thsq_pwm_conf *c, int pin,
                                 unsigned long freq, uint32_t gpt_base,
                                 int dutycycle);
void thsq_pwm_set_dutycycle(struct thsq_pwm_conf *c, int dutycycle);
void thsq_pwm_set_freq(struct thsq_pwm_conf *c, int freq);

The schedule module

```cstruct thsq_schedule;

typedef void ( thsq_schedule_callback_t)(struct thsq_schedule s, uint8_t *payload, int len);

struct thsq_schedule {
struct thsq_schedule next;
int payload_length;
thsq_schedule_callback_t cb;
const char
varname;
struct ctimer next_wakeup;
};

void thsq_schedule_init(struct thsq_schedule s, const char varname, thsq_schedule_callback_t callback);

void thsq_scheduled_offline_init(void);

enum thsq_err {
THSQ_ERR_OK = 1,
THSQ_ERR_BUFSIZE = -1,
THSQ_ERR_KEYVAL_MEM = -2,
THSQ_ERR_ALLOC = -3,
THSQ_ERR_QUEUE_EMPTY = -4,
THSQ_ERR_QUEUE_PAUSED = -5,
THSQ_ERR_QUEUE_WAITING = -6,
THSQ_ERR_QUEUE_FULL = -7,
THSQ_ERR_FATAL = -8,
};

define THSQ_ERR_IS_ERROR(err) ((err) < 0)

enum thsq_err thsq_dset_ptr(const char key, const uint8_t val, uint16_t vallen);
enum thsq_err thsq_sset_str_important(const char key, const char str);
enum thsq_err thsq_sset_printf_important(const char key, const char format, ...);
enum thsq_err thsq_sset_printf_important_timestamp(uint32_t timestamp, const char key, const char format, ...);
enum thsq_err thsq_sset_ulong(const char key, uint32_t val);
int32_t thsq_get_long(const char
key);
int thsq_exists(const char *key);

void thsq_set_default_rpl_mode(enum rpl_mode mode);
void thsq_format(void);
void thsq_bonding_release(void);
int thsq_bonding_is_bonded(void);
const char *thsq_platform(void);
void thsq_soft_release_bond(void);

void thsq_set_bond_key(const uint8_t key);
void thsq_set_fingerprint(const char
host, const uint8_t fingerprint);
void thsq_set_server_certificate(const uint8_t
cert);

/*
flags field:

+-------------------------------+
| R | R | R | A | S | S | S | S |
+-------------------------------+

R: reserved
A: auth
S: state

If A is set, the first 16 bytes of the data field contains the auth code.

If state is 0, the first 4 bytes of the data field contains a random
ID is to be used when inviting the device to the network. The
remaining 22 bytes contains a the name of the platform.
*/

define THSQ_BEACON_FLAG_AUTH 0x10

define THSQ_BEACON_FLAG_DATA 0x20

struct thsq_beacon {
uint8_t flags;
uint8_t data[17];
};

/ Create a beacon message from the current thsq state in the supplied struct /
int thsq_beacon_create(struct thsq_beacon b);
int thsq_beacon_create_databeacon(struct thsq_beacon
b, uint8_t flags,
uint8_t *data, int datalen);

void thsq_beacon_send_advbeacon(uint8_t advdata, int advlen);
void thsq_beacon_send_beacon(uint8_t
beacondata, int beaconlen);

define THSQ_BEACON_MAX_PAYLOAD 31

/
* Check the current state of the device. May be used for UI purposes, eg show
* an error, or unbonded device. The current state can be retrieved
* with thsq_get_current_state(). The following list is the set of states.
/

define THSQ_STATE_WAITING_FOR_BOND 0

define THSQ_STATE_WAITING_FOR_MUCHA 1

define THSQ_STATE_WAITING_FOR_RPL 2

define THSQ_STATE_WAITING_FOR_MASTER 3

define THSQ_STATE_WAITING_FOR_PONG 4

define THSQ_STATE_WAITING_FOR_DNS 5

define THSQ_STATE_WAITING_FOR_TLS 6

define THSQ_STATE_WAITING_FOR_AUTH 7

define THSQ_STATE_WAITING_FOR_NOTHING 8

define THSQ_STATE_WAITING_FOR_CABLE 9

define THSQ_STATE_WAITING_FOR_NETWORK 10

int thsq_get_current_state(void);

/
* Apply lighting settings from before last reboot, if such can successfully be
* retrieved. This depends on for how long the device was powered off or in reset.
/
void thsq_lighting_apply_last(void);

typedef enum thsq_lighting_prio {
THSQ_LIGHTING_PRIO_0 = 0, / lowest prio /
THSQ_LIGHTING_PRIO_1 = 1,
THSQ_LIGHTING_PRIO_2 = 2,
THSQ_LIGHTING_PRIO_3 = 3,
THSQ_LIGHTING_PRIO_4 = 4, / max prio /
} thsq_lighting_prio_t;

void thsq_lighting_set_lights(thsq_lighting_prio_t prio, int r, int g, int b, uint32_t dur);

void thsq_lighting_set_default_zone_control(thsq_lighting_prio_t prio, uint32_t duration);
void thsq_lighting_set_default_switch(thsq_lighting_prio_t prio, uint32_t duration);
void thsq_lighting_set_default_pir(thsq_lighting_prio_t prio, uint32_t duration, int red, int green, int blue);
void thsq_lighting_set_default_schedule(thsq_lighting_prio_t prio);
void thsq_lighting_set_default_lc(thsq_lighting_prio_t prio, uint32_t duration);

const char *thsq_zones_get_zone(void);

/ lighting event types /
enum thsq_lighting_type {
THSQ_LIGHTING_PIR,
THSQ_LIGHTING_SWITCH,
THSQ_LIGHTING_LC,
THSQ_LIGHTING_IDFY,
};

int thsq_lighting_send(enum thsq_lighting_type t,
const uint8_t zones, int zoneslen,
const uint8_t
data, int datalen, int via_parent);

void thsq_gpio_push_input_events(int enabled); / s.gpi /
void thsq_gpio_push_adc_periodically(int enabled); / s.adc /
rtimer_clock_t thsq_gpio_input_duration_high(void);
rtimer_clock_t thsq_gpio_input_timestamp(void);
void thsq_gpio_input_duration_reset(void);
void thsq_gpio_input_invert(int enabled);

/ Make the GPIO module listen to events from the lighting module. /
void thsq_gpio_attach_lighting(void);
void thsq_gpio_trigger_pir_on_gpio(int trigger);
void thsq_gpio_trigger_switch_on_gpio(int trigger);

struct thsq_pwm_conf thsq_gpio_get_pwm_red(void);
struct thsq_pwm_conf
thsq_gpio_get_pwm_green(void);
struct thsq_pwm_conf *thsq_gpio_get_pwm_blue(void);

int thsq_gpio_get_adc(void);
int thsq_gpio_get_gpio(void);
int thsq_gpio_set_gpio(int high);

void thsq_sniffer_init(void);

long thsq_get_long_arg(const char *key, int argnum, long na);

/ THSQ_POWER_LEVEL_DUTYCYCLED: Device tries to preserve power by keeping radio receiver off when possible.
* THSQ_POWER_LEVEL_ALWAYS_ON: Device keeps radio receiver on all the time.
/
enum thsq_power_level {
THSQ_POWER_LEVEL_DUTYCYCLED = 0,
THSQ_POWER_LEVEL_LOW = 0,
THSQ_POWER_LEVEL_ALWAYS_ON = 1,
THSQ_POWER_LEVEL_HIGH = 1
};
enum thsq_power_level thsq_get_power_level(void);
void thsq_set_power_level(enum thsq_power_level p);
void thsq_set_default_power_level(enum thsq_power_level p);

enum thsq_freq_conf {
THSQ_FREQ_CONF_DEFAULT,
THSQ_FREQ_CONF_ETSI,
THSQ_FREQ_CONF_FCC,
THSQ_FREQ_CONF_CUSTOM
};
enum thsq_freq_conf thsq_get_freq_conf(void);
void thsq_set_freq_conf(enum thsq_freq_conf f);
void thsq_set_default_freq_conf(enum thsq_freq_conf f);

void thsq_peui_init(void);
void thsq_feui_init(void);
void thsq_stats_dbgstats_init(void);
void thsq_mesh_debug_init(void);

struct thsq_chunk;

typedef void ( thsq_chunk_callback_t)(struct thsq_chunk c, void *ptr, uint32_t count, int maxsize);

struct thsq_chunk {
struct thsq_chunk next;
const char
name;
void *ptr;
thsq_chunk_callback_t callback;
uint32_t count;
};

void thsq_chunk_init(struct thsq_chunk c, const char name, thsq_chunk_callback_t callback, void ptr);
int thsq_chunk_send(struct thsq_chunk
c, const uint8_t data, int datalen);
int thsq_chunk_send_timestamp(struct thsq_chunk
c, const uint8_t *data, int datalen, uint32_t timestamp);

void thsq_enable_invites(void);
void thsq_enable_configurable_server_addresses(void);

void thsq_invite(uint8_t txpower, char *bondid);
void thsq_listen_for_bond_messages(clock_time_t duration);
void thsq_listen_for_bond_messages_always(void);
void thsq_listen_for_bond_messages_never(void);
void thsq_request_invite(void);

void thsq_prod_init(void);
void thsq_prod_default_commands(void);
void thsq_prod_comm_commands(void);
void thsq_prod_set_progress(char code, const char fmt, ...);

define thsq_prod_set_error(...) thsq_prod_set_progress("err", VA_ARGS)

void thsq_prod_runner_serial_init(void);
void thsq_prod_runner_standalone_init(const char *tests);
#define THSQ_PROD_CODE(msg, code) \
((size_t)len >= 4 + strlen(code) && strncmp(msg, "test", 4) == 0 && strncmp(&msg[4], code, strlen(code)) == 0)
#define THSQ_PROD_CODE_DONE(msg) \
THSQ_PROD_CODE(msg, "done")

void thsq_txpower_init(void);

struct thsq_dc {
struct energest_extension e;
};

typedef void (thsq_ble_scan_callback_fn)(const uint8_t buf, int len, int rssi);
void thsq_ble_enable_background_scan(thsq_ble_scan_callback_fn callback);
void thsq_ble_whitelist(uint8_t *adv_address);

void thsq_dc_on(struct thsq_dc );
void thsq_dc_off(struct thsq_dc
);
void thsq_dc_add(struct thsq_dc *);

void thsq_set_default_server(void);
void thsq_set_server(const char *newserver);

define thsq_fft_scalar int16_t

typedef struct {
thsq_fft_scalar r;
thsq_fft_scalar i;
} thsq_fft_freq;
int thsq_fft_run(thsq_fft_scalar samples, int len, thsq_fft_freq output);
int16_t thsq_fft_hannwdw_128(int index, int16_t val);

int thsq_cbor_append_indefarr(uint8_t buf, uint8_t end);
int thsq_cbor_append_indefmap(uint8_t buf, uint8_t end);
int thsq_cbor_append_break(uint8_t buf, uint8_t end);
int thsq_cbor_append_str(uint8_t buf, uint8_t end, const char str);
int thsq_cbor_append_int(uint8_t
buf, uint8_t end, int32_t val);
int thsq_cbor_append_float(uint8_t
buf, uint8_t end, float val);
int thsq_cbor_append_true(uint8_t
buf, uint8_t end);
int thsq_cbor_append_false(uint8_t
buf, uint8_t *end);

enum thsq_rf_interface_type {
THSQ_RF_INTERFACE_PRIMARY, / e.g. Sub-GHz /
THSQ_RF_INTERFACE_BLE, / secondary radio interface /
};

enum thsq_rf_callback_event {
THSQ_RF_RADIO_OFF,
THSQ_RF_RADIO_TX_PRE,
THSQ_RF_RADIO_TX_POST,
THSQ_RF_RADIO_RX_PRE,
THSQ_RF_RADIO_RX_POST,
THSQ_RF_RADIO_RX_PACKET,
THSQ_RF_RADIO_EVENT,
};

typedef void (thsq_rf_callback_fn)(enum thsq_rf_interface_type interface, enum thsq_rf_callback_event event);
struct thsq_rf_callback {
struct thsq_rf_callback
next;
thsq_rf_callback_fn callback;
};

void thsq_rf_add_callback(struct thsq_rf_callback *c, thsq_rf_callback_fn f);

void thsq_rf_blacklist_channels(const char *blacklist_hex, int blacklist_len);

/ Antenna bias /

define THSQ_RF_BIAS_INTERNAL 0

define THSQ_RF_BIAS_EXTERNAL 1

/ Antenna front-end mode /

define THSQ_RF_FEM_DIFFERENTIAL 0

define THSQ_RF_FEM_SINGLE_RFP 1

define THSQ_RF_FEM_SINGLE_RFN 2

/ ccw - send modulated or not? /

define THSQ_RF_UNMODULATED_CCW 0

define THSQ_RF_MODULATED_CCW 1

/ the only channels we support sending BLE over /

define THSQ_RF_BLE_ADVCHANNEL_LOW 37

define THSQ_RF_BLE_ADVCHANNEL_MID 38

define THSQ_RF_BLE_ADVCHANNEL_HIGH 39

/
* Set antenna bias.
* * On CC13xx and CC26xx platforms, the antenna bias can be set as internal or
* external accordingly. The default value is according to the base platform
* (ie, Launchpad/Sensortag).
* * interface is the interface to be configured
* bias == 0, internal bias is used
* bias == 1, external bias is used
/
void thsq_rf_set_bias(enum thsq_rf_interface_type interface, int bias);

/
* Set the antenna frontend mode for a given RF interface.
* * interface is the interface to be configured
* mode is the mode to be used
* must be one of the valid modes for the platform in use, see each
* technical reference manual or datasheet
*
* Typical usage: override the init_radio() function from the client application
* and use this to configure.
*
* #include "ti-lib.h"
* void
* init_radio(void)
* {
* // update frontend mode
* thsq_rf_set_frontend_mode(THSQ_RF_INTERFACE_PRIMARY, 0x02);
* thsq_rf_set_frontend_mode(THSQ_RF_INTERFACE_BLE, 0x01);
* }
/
void thsq_rf_set_frontend_mode(enum thsq_rf_interface_type interface, int mode);

/
* Set maximum transmission power setting.
* NB: for best effect it should run before netstack is inited, eg in init_radio()
* * The setting is expressed in percent, from 1 to 100 (inclusive).
* Typical use cases,
* 1) lowering the maximum output power for regulation or hardware purposes
* 2) development and debugging purposes
*
* Note the following,
* a) mapping may not be linear (ie 50 != twice of 25)
* b) depends on the radio capabilities and underlying libraries
* c) is often stepped, depending on the underlying driver for the radio
* d) other radio interfaces may not be affected (eg secondary RF interfaces such as BLE)
* e) may not be supported on all platforms
* f) a setting may not equal the same setting on another platform (eg 100 @ CC1310 != 100 @ CC1350)
/
void thsq_rf_set_max_txpower(unsigned int txp);

/
* Set current transmission power setting.
* * The setting is expressed in percent, from 1 to 100 (inclusive).
* Typical use cases,
* 1) development and debugging purposes
* * Note the following,
* a) mapping may not be linear (ie 50 != twice of 25)
* b) depends on the radio capabilities and underlying libraries
* c) is often stepped, depending on the underlying driver for the radio
* d) other radio interfaces may not be affected (eg secondary RF interfaces such as BLE)
* e) may not be supported on all platforms
* f) a setting may not equal the same setting on another platform (eg 100 @ CC1310 != 100 @ CC1350)
/
void thsq_rf_set_txpower(unsigned int txp);

/
* Set the RF switch GPIO pins.
* * Platforms with dual radio interfaces (eg CC1350) may have a RF switch.
* Such a switch typically has a GPIO to control what signal path is used
* (eg sub-GHz or 2.4 GHz), and may be powered over another GPIO. This function
* allows setting the pins in use and inits the RF switch.
* * If power pin is not used, use the IOID_UNUSED value for that argument.
* Will also initialize the rf switch driver.
* * Typical usage: override the init_radio() function from the client application
* and use this to set and init the rf switch:
* * #include "ti-lib.h"
* void
* init_radio(void)
* {
* thsq_rf_set_rf_switch(IOID_30, IOID_1);
* }
/
void thsq_rf_set_rf_switch(int power, int select);

/
* Enable PA and/or LNA output on GPIOs.
* * If either is not in use, or applicable, use IOID_UNUSED as value.
* The PA pin is normally low, goes high to enable Power Amplifier for transmissions
* The LNA pin is normally low, goes high to enable Low Noise Amplifier when listening
* * Note, this cannot be used to disable LNA/PA once enabled.
/
void thsq_rf_enable_lna_pa(int lna, int pa);

/
* Override frequency hopping and rf frequency configurations
* * freqs: list of channel frequencies (kHz) of all logical channels to be used
* num: number of elements in freqs (default and max: 50)
* sync: 3 channel indices (default 0, 24, 49)
/
void thsq_rf_override_freqhopping_channels(const uint32_t freqs, int num, int sync);

/
* Activate CC1352P-mode iff this is an CC1352P, ie safe to run on everything.
* Note that RF switch implementation is needed too.
* Must happen before any use of radio, so in eg init_radio().
/
void thsq_rf_prop_check_and_set_cc1352p(void);

int thsq_rf_is_cc1352p(void);
int thsq_rf_boost_mode_enabled(void);
int thsq_rf_cc1352p_20dbm_is_possible(void);

/
* Returns non-zero if thsq_rf_override_freqhopping_channels() has
* been used to set up a custom frequency hopping configuration.
/
int thsq_rf_has_custom_freq(void);

/
* Set the BLE beacon transmission power setting.
* May not take effect immediately, but eg at next BLE setup.
*
* cc1350/cc2650: raw value, no sanity check performed
* cc1352x: percent [1..100]
/
void thsq_rf_ble_set_txpower(uint16_t txp);

/
* Parse an ASCII string with hex data into a binary buffer.
/
int thsq_parse_hex(const char hexstring, int hexstringlen, uint8_t buffer, int bufferlen);

void thsq_remotecontrol_init(void);
void thsq_gateway_rssi_logging_init(void);
void thsq_rplconf_init(void);

struct thsq_minmax_uint32 {
uint32_t min, max;
uint32_t min_timestamp, max_timestamp;
uint64_t sum;
uint32_t count;
double ewma;
uint8_t ewma_initialized;
};

struct thsq_minmax_int32 {
int32_t min, max;
uint32_t min_timestamp, max_timestamp;
uint64_t sum;
uint32_t count;
double ewma;
uint8_t ewma_initialized;
};

struct thsq_minmax_float {
float min, max;
uint32_t min_timestamp, max_timestamp;
float sum;
uint32_t count;
double ewma;
uint8_t ewma_initialized;
};

void thsq_minmax_uint32_update(struct thsq_minmax_uint32 minmax, uint32_t data, double ewma_alpha);
void thsq_minmax_int32_update(struct thsq_minmax_int32
minmax, int32_t data, double ewma_alpha);
void thsq_minmax_float_update(struct thsq_minmax_float minmax, float data, double ewma_alpha);
void thsq_minmax_uint32_init(struct thsq_minmax_uint32
minmax);
void thsq_minmax_int32_init(struct thsq_minmax_int32 minmax);
void thsq_minmax_float_init(struct thsq_minmax_float
minmax);

void thsq_range_mapper_init(void);
int thsq_range_mapper_is_running(void);
void thsq_range_mapper_start(void);
void thsq_range_mapper_stop(void);

## Thingsquare commands over Bluetooth Low Energy (BLE)

The thsq commands over BLE functionality allows commands to be sent
over BLE from a smartphone to a nearby device. This works only on
BLE-enabled platforms such as the CC1352.

Commands over BLE are encrypted with a shared key that is stored in
the s.blekey variable. This variable is generated with the call to
the thsq_ble_commands_init() and is stored in nvstorage for
subsequent accesse.

Receiving BLE commands require significant power, so this feature
should only be enabled for short moments.

Call the thsq_ble_commands_enable() function to start receiving
commands. The function takes a time parameter. After this time, the
functionality is automatically disabled. If the parameter is 0, the
functionality is enabled indefinitely. The
thsq_ble_commands_disable() function switches off the
functionality.


```cvoid thsq_ble_commands_init(uint8_t led_indicator);
void thsq_ble_commands_enable(clock_time_t time_or_zero);
void thsq_ble_commands_disable(void);
int thsq_ble_commands_is_enabled(void);

void thsq_ble_transfer_init(void);
void thsq_ble_transfer_enable(void (* callback)(const uint8_t *data, int datalen));
void thsq_ble_transfer_disable(void);
int thsq_ble_transfer_is_enabled(void);

void thsq_force_radio_on(int force);

void thsq_ping6_init(void);

int nvstorage_read(const char *key, uint8_t *val, int max_len);
int nvstorage_write(const char *key, uint8_t *val, uint8_t vallen);
int nvstorage_remove(const char *key);
int nvstorage_contains(const char *key);

void thsq_reboot(const char *reason);

#endif /* THSQ_H */