Helium / helium
Revision:
23:cc2c1d1ed159
Parent:
20:d55e9eb828d4
diff -r 062758492f31 -r cc2c1d1ed159 src/Helium.cpp
--- 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;
+}