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.

Revision:
23:cc2c1d1ed159
Parent:
20:d55e9eb828d4
--- a/src/Helium.cpp	Tue Aug 22 09:43:11 2017 -0700
+++ b/src/Helium.cpp	Tue Sep 05 13:56:03 2017 -0700
@@ -110,15 +110,15 @@
 // Channel
 //
 
-Channel::Channel(Helium * helium)
+Channel::Channel(Helium * h)
 {
-    _helium = helium;
+    helium = h;
 }
 
 int
 Channel::begin(const char * name, uint16_t * token)
 {
-    return helium_channel_create(&_helium->_ctx, name, strlen(name), token);
+    return helium_channel_create(&helium->_ctx, name, strlen(name), token);
 }
 
 int
@@ -143,7 +143,7 @@
 int
 Channel::send(void const * data, size_t len, uint16_t * token)
 {
-    return helium_channel_send(&_helium->_ctx, _channel_id, data, len, token);
+    return helium_channel_send(&helium->_ctx, _channel_id, data, len, token);
 }
 
 
@@ -162,7 +162,7 @@
 int
 Channel::poll_result(uint16_t token, int8_t * result, uint32_t retries)
 {
-    return helium_channel_poll_result(&_helium->_ctx, token, result, retries);
+    return helium_channel_poll_result(&helium->_ctx, token, result, retries);
 }
 
 int
@@ -171,10 +171,224 @@
                    size_t * used,
                    uint32_t retries)
 {
-    return helium_channel_poll_data(&_helium->_ctx,
+    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;
+}