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
Diff: thinger/thinger_resource.hpp
- Revision:
- 0:b75d784c7c1a
- Child:
- 4:de51256455f7
diff -r 000000000000 -r b75d784c7c1a thinger/thinger_resource.hpp --- /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