Thinger.io Client Library for ARM mbed platform. This is a generic library that provides a base class that can be used to other develop hardware specific libraries.

Fork of ThingerClient by Alvaro Luis Bustamante

Revision:
0:b75d784c7c1a
Child:
4:de51256455f7
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/thinger/thinger_resource.hpp	Thu Dec 24 13:18:08 2015 +0000
@@ -0,0 +1,275 @@
+// The MIT License (MIT)
+//
+// Copyright (c) 2015 THINGER LTD
+// Author: alvarolb@gmail.com (Alvaro Luis Bustamante)
+//
+// Permission is hereby granted, free of charge, to any person obtaining a copy
+// of this software and associated documentation files (the "Software"), to deal
+// in the Software without restriction, including without limitation the rights
+// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+// copies of the Software, and to permit persons to whom the Software is
+// furnished to do so, subject to the following conditions:
+//
+// The above copyright notice and this permission notice shall be included in
+// all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+// THE SOFTWARE.
+
+#ifndef THINGER_RESOURCE_HPP
+#define THINGER_RESOURCE_HPP
+
+#include "thinger_map.hpp"
+#include "pson.h"
+#include "thinger_message.hpp"
+
+namespace thinger{
+
+
+class thinger_resource {
+
+public:
+    enum io_type {
+        none                = 0,
+        run                 = 1,
+        pson_in             = 2,
+        pson_out            = 3,
+        pson_in_pson_out    = 4
+    };
+
+    enum access_type{
+        PRIVATE     = 0,
+        PROTECTED   = 1,
+        PUBLIC      = 2,
+        NONE        = 3
+    };
+
+    static int get_streaming_counter(){
+        return streaming_count_;
+    }
+
+private:
+
+    // calback for function, input, output, or input/output
+    union callback{
+        void (*run)();
+        void (*pson_in)(protoson::pson& in);
+        void (*pson_out)(protoson::pson& out);
+        void (*pson_in_pson_out)(protoson::pson& in, protoson::pson& out);
+    };
+
+    // used for defining the resource
+    io_type io_type_;
+    access_type access_type_;
+    callback callback_;
+
+    // used for allowing resource streaming (both periodically or by events)
+    uint16_t stream_id_;
+
+    // used for periodic stream events
+    unsigned long streaming_freq_;
+    unsigned long last_streaming_;
+
+    // used to know the total number of streams
+    static unsigned int streaming_count_;
+
+    // TODO change to pointer so it is not using more than a pointer size if not used?
+    thinger_map<thinger_resource> sub_resources_;
+
+    void enable_streaming(uint16_t stream_id, unsigned long streaming_freq){
+        stream_id_ = stream_id;
+        streaming_freq_ = streaming_freq;
+        last_streaming_ = 0;
+        streaming_count_++;
+    }
+
+public:
+    thinger_resource() : io_type_(none), access_type_(PRIVATE), stream_id_(0), streaming_freq_(0), last_streaming_(0)
+    {}
+
+    void disable_streaming(){
+        stream_id_ = 0;
+        streaming_freq_ = 0;
+        streaming_count_--;
+    }
+
+    bool stream_enabled(){
+        return stream_id_ > 0;
+    }
+
+    uint32_t get_stream_id(){
+        return stream_id_;
+    }
+
+    bool stream_required(unsigned long timestamp){
+        // sample interval is activated
+        if(streaming_freq_>0){
+            if(timestamp-last_streaming_>=streaming_freq_){
+                last_streaming_ = timestamp;
+                return true;
+            }
+        }
+        return false;
+    }
+
+    thinger_resource * find(const char* res)
+    {
+        return sub_resources_.find(res);
+    }
+
+    thinger_resource & operator[](const char* res){
+        return sub_resources_[res];
+    }
+
+    thinger_resource & operator()(access_type type){
+        access_type_ = type;
+        return *this;
+    }
+
+    io_type get_io_type(){
+        return io_type_;
+    }
+
+    access_type get_access_type(){
+        return access_type_;
+    }
+
+    void fill_api(protoson::pson_object& content){
+        if(io_type_!=none){
+            content["al"] = access_type_;
+            content["fn"] = io_type_;
+        }
+        thinger_map<thinger_resource>::entry* current = sub_resources_.begin();
+        if(current!=NULL){
+            protoson::pson_object& actions = content["/"];
+            do{
+                current->value_.fill_api(actions[current->key_]);
+                current = current->next_;
+            }while(current!=NULL);
+        }
+    }
+
+    void fill_api_io(protoson::pson_object& content){
+        if(io_type_ == pson_in){
+            callback_.pson_in(content["in"]);
+        }else if(io_type_ == pson_out){
+            callback_.pson_out(content["out"]);
+        }else if(io_type_ == pson_in_pson_out){
+            callback_.pson_in_pson_out(content["in"], content["out"]);
+        }
+    }
+
+public:
+
+    /**
+     * Establish a function without input or output parameters
+     */
+    void operator=(void (*run_function)()){
+        io_type_ = run;
+        callback_.run = run_function;
+    }
+
+    /**
+     * Establish a function without input or output parameters
+     */
+    void set_function(void (*run_function)()){
+        io_type_ = run;
+        callback_.run = run_function;
+    }
+
+    /**
+     * Establish a function with input parameters
+     */
+    void operator<<(void (*in_function)(protoson::pson& in)){
+        io_type_ = pson_in;
+        callback_.pson_in = in_function;
+    }
+
+    /**
+     * Establish a function with input parameters
+     */
+    void set_input(void (*in_function)(protoson::pson& in)){
+        io_type_ = pson_in;
+        callback_.pson_in = in_function;
+    }
+
+    /**
+     * Establish a function that only generates an output
+     */
+    void operator>>(void (*out_function)(protoson::pson& out)){
+        io_type_ = pson_out;
+        callback_.pson_out = out_function;
+    }
+
+    /**
+     * Establish a function that only generates an output
+     */
+    void set_output(void (*out_function)(protoson::pson& out)){
+        io_type_ = pson_out;
+        callback_.pson_out = out_function;
+    }
+
+    /**
+     * Establish a function that can receive input parameters and generate an output
+     */
+    void operator=(void (*pson_in_pson_out_function)(protoson::pson& in, protoson::pson& out)){
+        io_type_ = pson_in_pson_out;
+        callback_.pson_in_pson_out = pson_in_pson_out_function;
+    }
+
+    /**
+     * Establish a function that can receive input parameters and generate an output
+     */
+    void set_input_output(void (*pson_in_pson_out_function)(protoson::pson& in, protoson::pson& out)){
+        io_type_ = pson_in_pson_out;
+        callback_.pson_in_pson_out = pson_in_pson_out_function;
+    }
+
+    /**
+     * Handle a request and fill a possible response
+     */
+    void handle_request(thinger_message& request, thinger_message& response){
+        switch(request.get_signal_flag()){
+            // default action over the stream (run the resource)
+            case thinger_message::NONE:
+                switch (io_type_){
+                    case run:
+                        callback_.run();
+                        break;
+                    case pson_in:
+                        callback_.pson_in(request);
+                        break;
+                    case pson_out:
+                        callback_.pson_out(response);
+                        break;
+                    case pson_in_pson_out:
+                        callback_.pson_in_pson_out(request, response);
+                        break;
+                    case none:
+                        break;
+                }
+                break;
+            // flag for starting a resource stream
+            case thinger_message::START_STREAM:
+                enable_streaming(request.get_stream_id(), request.get_data());
+                break;
+            // flat for stopping a resource stream
+            case thinger_message::STOP_STREAM:
+                disable_streaming();
+                break;
+            default:
+                break;
+        }
+    }
+};
+
+    unsigned int thinger_resource::streaming_count_ = 0;
+
+}
+
+#endif