An mbed wrapper around the helium-client to communicate with the Helium Atom
Helium for ARM mbed
This code repository exposes an mbed library for the Helium Atom module. The Helium Atom makes it easy to securely connect IoT devices and applications to back-end IoT services.
Getting Started
See a getting started guide on the Helium site.
Supported Boards
The Helium mbed client should work with any mbed board with an available serial port.
Example Setup
Example applications can be found in the mbed Helium team.
Getting Help
If you have any questions or ideas about how to use this code - or any part of Helium - head over to the Helium Community Slack. We're standing by to help.
Contributing
Want to contribute to helium-mbed? That's awesome!
Please see CONTRIBUTING.md in this repository for details.
src/Helium.cpp
- Committer:
- Marc Nijdam
- Date:
- 2017-09-05
- Revision:
- 23:cc2c1d1ed159
- Parent:
- 20:d55e9eb828d4
File content as of revision 23:cc2c1d1ed159:
#include "Helium.h" #include "helium-client/helium-client.h" bool helium_serial_readable(void * param) { BufferedSerial * serial = (BufferedSerial *)param; return serial->readable() > 0; } bool helium_serial_getc(void * param, uint8_t * ch) { BufferedSerial * serial = (BufferedSerial *)param; int val = serial->getc(); *ch = val; return val >= 0; } bool helium_serial_putc(void * param, uint8_t ch) { BufferedSerial * serial = (BufferedSerial *)param; serial->putc(ch); return true; } void helium_wait_us(void * param, uint32_t us) { (void)param; wait_us(us); } Helium::Helium(PinName tx, PinName rx) : serial(tx, rx, 9600) { helium_init(&_ctx, (void *)&serial); } int Helium::baud(enum helium_baud baud) { int result = helium_baud(&_ctx, baud); uint32_t serial_baud = 9600; switch (baud) { case helium_baud_b9600: serial_baud = 9600; break; case helium_baud_b14400: serial_baud = 14400; break; case helium_baud_b19200: serial_baud = 19200; break; case helium_baud_b38400: serial_baud = 38400; break; case helium_baud_b57600: serial_baud = 57600; break; case helium_baud_b115200: serial_baud = 115200; break; } serial.baud(serial_baud); return result; } int Helium::info(struct helium_info * info) { return helium_info(&_ctx, info); } int Helium::connect(struct connection * connection, uint32_t retries) { return helium_connect(&_ctx, connection, retries); } bool Helium::connected() { return helium_connected(&_ctx) == helium_connected_CONNECTED; } int Helium::sleep(struct connection * connection) { return helium_sleep(&_ctx, connection); } bool Helium::needs_reset() { return helium_needs_reset(&_ctx); } int Helium::reset() { return helium_reset(&_ctx); } // // Channel // Channel::Channel(Helium * h) { helium = h; } int Channel::begin(const char * name, uint16_t * token) { return helium_channel_create(&helium->_ctx, name, strlen(name), token); } int Channel::begin(const char * name, int8_t * result) { uint16_t token; int status = begin(name, &token); _channel_id = -1; if (helium_status_OK == status) { status = poll_result(token, &_channel_id); } if (result) { *result = status == helium_status_OK && _channel_id > 0 ? 0 : _channel_id; } return status; } int Channel::send(void const * data, size_t len, uint16_t * token) { return helium_channel_send(&helium->_ctx, _channel_id, data, len, token); } int Channel::send(void const * data, size_t len, int8_t * result) { uint16_t token; int status = send(data, len, &token); if (helium_status_OK == status) { status = poll_result(token, result); } return status; } int Channel::poll_result(uint16_t token, int8_t * result, uint32_t retries) { return helium_channel_poll_result(&helium->_ctx, token, result, retries); } int Channel::poll_data(void * data, size_t len, size_t * used, uint32_t retries) { return helium_channel_poll_data(&helium->_ctx, _channel_id, data, len, used, retries); } // // Config // Config::Config(Channel * channel) { _channel = channel; } int Config::get(const char * key, uint16_t * token) { return helium_channel_config_get(&_channel->helium->_ctx, _channel->_channel_id, key, token); } int Config::_get(const char * config_key, enum helium_config_type config_type, void * value, size_t value_len, void * default_value, size_t default_value_len, uint32_t retries) { uint16_t token; int status = get(config_key, &token); int8_t result = 0; if (helium_status_OK == status) { status = poll_get_result(token, config_key, config_type, value, value_len, default_value, default_value_len, &result, retries); } if (helium_status_OK == status && result != 0) { status = helium_status_ERR_COMMUNICATION; } return status; } /** Context for the poll_get handlder * * An instance of this if filled in the #Config::poll_get_result * implementation and the result of the poll handler is returned in * the status field */ struct _poll_get_context { //! The config key to look for const char * filter_key; //! The config type to check for enum helium_config_type filter_type; //! The destination buffer void * dest; //! The length of the destination buffer size_t dest_len; //! The default value. Assumed to be the same type as filter_type void * default_value; //! The length of the default_value size_t default_value_len; //! The result status of the result handler enum config_poll_get_status status; }; static bool _poll_get_result_handler(void * handler_ctx, const char * key, enum helium_config_type value_type, void * value) { struct _poll_get_context * ctx = (struct _poll_get_context *)handler_ctx; size_t len = ctx->dest_len; void * src = value; if (strcmp(ctx->filter_key, key) != 0) { // Not the right key, keep going return true; } if (value_type == ctx->filter_type) { // Found and the right type // Use the given value and the destination buffer size ctx->status = config_status_POLL_FOUND; } else { // Found but not the right type, return an error ctx->status = config_status_POLL_ERR_TYPE; // And use the context's default value_type = ctx->filter_type; // Us the default value as the source src = ctx->default_value; // Check for a shorter default value length (only really valid for // strings) len = len > ctx->default_value_len ? ctx->default_value_len : len; } switch (value_type) { case helium_config_bool: case helium_config_f32: case helium_config_i32: case helium_config_str: break; case helium_config_null: ctx->status = config_status_POLL_FOUND_NULL; len = 0; break; } memcpy(ctx->dest, src, len); return false; } int Config::poll_get_result(uint16_t token, const char * config_key, helium_config_type config_type, void * value, size_t value_len, void * default_value, size_t default_value_len, int8_t * result, uint32_t retries) { struct _poll_get_context handler_ctx = { .filter_key = config_key, .filter_type = config_type, .dest = value, .dest_len = value_len, .default_value = default_value, .default_value_len = default_value_len, .status = config_status_POLL_FOUND_NULL, }; int status = helium_channel_config_get_poll_result(&_channel->helium->_ctx, token, _poll_get_result_handler, &handler_ctx, result, retries); if (helium_status_OK == status) { status = handler_ctx.status; } return status; } int Config::set(const char * config_key, helium_config_type config_type, void * value, uint16_t * token) { return helium_channel_config_set(&_channel->helium->_ctx, _channel->_channel_id, config_key, config_type, value, token); } int Config::poll_set_result(uint16_t token, int8_t * result, uint32_t retries) { return helium_channel_config_set_poll_result(&_channel->helium->_ctx, token, result, retries); } int Config::_set(const char * config_key, enum helium_config_type value_type, void * value, uint32_t retries) { uint16_t token; int status = set(config_key, value_type, value, &token); int8_t result = 0; if (helium_status_OK == status) { status = poll_set_result(token, &result, retries); } if (helium_status_OK == status && result != 0) { status = helium_status_ERR_COMMUNICATION; } return status; } bool Config::is_stale() { bool result = false; helium_channel_config_poll_invalidate(&_channel->helium->_ctx, _channel->_channel_id, &result, 0); return result; }