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-2017 Thingsquare AB

#ifndef THSQ_H
#define THSQ_H

Include files

#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"

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

enum thsq_reason {

Type definition of the callback function

typedef 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.

struct 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.

void 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 (THSQ_MAX_VALLEN) bytes long including
the terminator.

void thsq_set_platform(const char *platform);

Serial line module

The serialline module captures input from the UART and posts them as a
s variable serial and writes serial output from the sout command
to the UART.

void thsq_serialline_init(void);

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

typedef 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;
void thsq_lighting_add_callback(struct thsq_lighting_callback *c, thsq_lighting_callback_fn f);
void thsq_schedule_set_default(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);

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.

int thsq_has_time(void);
uint32_t thsq_get_time(void);
int32_t thsq_get_timezone_offset(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

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

Bootloader configuration

The booloader is configured with either of two functions:
bootloader, and 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:
where each pin is named eg IOID_2 for the DIO_2 pin.
Don't forget to include #include "ti-lib.h".

struct 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 */

extern struct thsq_bootloader_params bootloaderparams;
    struct thsq_bootloader_params bootloaderparams \
    __attribute__ ((section(".bootloaderparams")))   \
    __attribute__ ((used))                    \
    = { __VA_ARGS__ }

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

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.

void thsq_push(void);
int thsq_dset(const char *key, int val);
int thsq_dset_str(const char *key, const char *str);
int thsq_sset(const char *key, int val);
int thsq_sset_str(const char *key, const char *str);
int thsq_sset_printf(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);

The maximum size of a variable value

#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

void thsq_set_default_mode(const char *mode);

Undocumented functions

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

The PWM module

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

struct 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);

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

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

  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 *data, int datalen);

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


 * 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.

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);

void thsq_lighting_set_lights(int prio, int r, int g, int b, uint32_t dur);
int thsq_lighting_current_red(void);
int thsq_lighting_current_green(void);
int thsq_lighting_current_blue(void);

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

const char *thsq_zones_get_zone(void);

/* lighting event types */
enum thsq_lighting_type {

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);

#endif /* THSQ_H */