Sample implementation of ocf_light 75/23375/18
authorGeorge Nash <george.nash@intel.com>
Fri, 9 Feb 2018 22:57:25 +0000 (14:57 -0800)
committerGeorge Nash <george.nash@intel.com>
Wed, 28 Feb 2018 18:02:50 +0000 (18:02 +0000)
This sample borrows a lot of code from the server
sample generated from the DeviceBuilder project
https://github.com/openconnectivityfoundation/DeviceBuilder

Change-Id: I4fa40119fb8fdc1594905491fa362ae33a7cc7fc
Signed-off-by: George Nash <george.nash@intel.com>
21 files changed:
resource/examples/SConscript
resource/examples/ocf_light/BinarySwitchResource.cpp [new file with mode: 0644]
resource/examples/ocf_light/BinarySwitchResource.h [new file with mode: 0644]
resource/examples/ocf_light/DimmingLightServer.cpp [new file with mode: 0644]
resource/examples/ocf_light/DimmingLightServer.h [new file with mode: 0644]
resource/examples/ocf_light/DimmingResource.cpp [new file with mode: 0644]
resource/examples/ocf_light/DimmingResource.h [new file with mode: 0644]
resource/examples/ocf_light/PICS.json [new file with mode: 0644]
resource/examples/ocf_light/Platform.cpp [new file with mode: 0644]
resource/examples/ocf_light/Platform.h [new file with mode: 0644]
resource/examples/ocf_light/Resource.h [new file with mode: 0644]
resource/examples/ocf_light/SConscript [new file with mode: 0644]
resource/examples/ocf_light/dimming_light_server.cpp [new file with mode: 0644]
resource/examples/ocf_light/oic_svr_db_server_mvjustworks.dat [new file with mode: 0644]
resource/examples/ocf_light/readme.md [new file with mode: 0644]
resource/examples/ocf_light/server_introspection.dat [new file with mode: 0644]
resource/examples/ocf_light/server_security.dat [new file with mode: 0644]
resource/examples/ocf_light/server_security.dat-org [new file with mode: 0644]
resource/examples/ocf_light/svr_server-justworks.json [new file with mode: 0644]
resource/examples/ocf_light/svr_server.json [new file with mode: 0644]
resource/examples/ocf_light/svr_server.json.cbor [new file with mode: 0644]

index 4c55fe8..fb387eb 100644 (file)
@@ -148,6 +148,8 @@ if target_os in ['msys_nt', 'windows']:
         mediaserver = examples_env.Program('mediaserver', 'mediaserver.cpp')
         examples += [mediaserver]
 
+examples_env. SConscript('ocf_light/SConscript', exports='examples_env')
+
 examples_env.Alias("examples", examples)
 examples_env.AppendTarget('examples')
 examples_env.Alias("install", examples)
diff --git a/resource/examples/ocf_light/BinarySwitchResource.cpp b/resource/examples/ocf_light/BinarySwitchResource.cpp
new file mode 100644 (file)
index 0000000..4a6046d
--- /dev/null
@@ -0,0 +1,389 @@
+/*
+ * BinarySwitchResource.cpp
+ */
+#include <iostream>
+#include <vector>
+#include <thread>
+
+#include "BinarySwitchResource.h"
+#include "OCPlatform.h"
+
+#define INTERFACE_KEY "if"
+
+using namespace OC;
+namespace PH = std::placeholders;
+
+BinarySwitchResource::BinarySwitchResource():
+        m_notify_thread_active{true},
+        m_notify_thread{nullptr},
+        m_send_notification_flag{false},
+        m_cv_mutex{},
+        m_cv{},
+        m_nr_resource_types{1},
+        m_nr_resource_interfaces{2},
+        m_interestedObservers{},
+        m_var_value_rt{},
+        m_var_value_n{},
+        m_var_value_if{},
+        m_var_value_value{}
+{
+    std::cout << "- Running: BinarySwitchResource constructor" << std::endl;
+    std::string resourceURI = "/binaryswitch";
+
+    // VS2013 will fail list initialization so use array initialization
+    m_RESOURCE_TYPE[0] = "oic.r.switch.binary";
+    m_RESOURCE_INTERFACE[0] = "oic.if.baseline";
+    m_RESOURCE_INTERFACE[1] = "oic.if.a";
+    m_IF_UPDATE[0] = "oic.if.a";
+    m_IF_UPDATE[1] = "oic.if.rw";
+    m_IF_UPDATE[2] = "oic.if.baseline";
+    m_var_name_rt = "rt";
+    m_var_name_n = "n";
+    m_var_name_if = "if";
+    m_var_name_value = "value";
+
+    // initialize member variables /binaryswitch
+    // initialize vector rt
+    m_var_value_rt.push_back("oic.r.switch.binary");
+    m_var_value_n = "";  // current value of property "n"
+    // initialize vector if
+    m_var_value_if.push_back("oic.if.baseline");
+    m_var_value_if.push_back("oic.if.a");
+
+    m_var_value_value = true; // current value of property "value"
+
+    EntityHandler cb = std::bind(&BinarySwitchResource::entityHandler, this,PH::_1);
+    //uint8_t resourceProperty = 0;
+    OCStackResult result = OCPlatform::registerResource(m_resourceHandle,
+            resourceURI,
+            m_RESOURCE_TYPE[0],
+            m_RESOURCE_INTERFACE[0],
+            cb,
+            OC_DISCOVERABLE | OC_OBSERVABLE | OC_SECURE );
+
+    // add the additional interfaces
+    std::cout << "\t" << "# resource interfaces: " << m_nr_resource_interfaces << std::endl;
+    std::cout << "\t" << "# resource types     : " << m_nr_resource_types << std::endl;
+    for( int a = 1; a < m_nr_resource_interfaces; a++)
+    {
+        OCStackResult result1 = OCBindResourceInterfaceToResource(m_resourceHandle, m_RESOURCE_INTERFACE[a].c_str());
+        if (result1 != OC_STACK_OK)
+            std::cerr << "Could not bind interface:" << m_RESOURCE_INTERFACE[a] << std::endl;
+    }
+    // add the additional resource types
+    for( int a = 1; a < m_nr_resource_types; a++ )
+    {
+        OCStackResult result2 = OCBindResourceTypeToResource(m_resourceHandle, m_RESOURCE_TYPE[a].c_str());
+        if (result2 != OC_STACK_OK)
+            std::cerr << "Could not bind resource type:" << m_RESOURCE_INTERFACE[a] << std::endl;
+    }
+
+    if(OC_STACK_OK != result)
+    {
+        throw std::runtime_error(
+                std::string("BinarySwitchResource failed to start")+std::to_string(result));
+    }
+
+    m_send_notification_flag = false;
+    m_notify_thread_active = true;
+    m_notify_thread = new std::thread(&BinarySwitchResource::notifyObservers, this);
+
+}
+
+BinarySwitchResource::~BinarySwitchResource()
+{
+    m_notify_thread_active = false;
+    m_cv.notify_all();
+    if(m_notify_thread->joinable())
+    {
+        m_notify_thread->join();
+    }
+}
+
+OC::OCRepresentation BinarySwitchResource::get(OC::QueryParamsMap queries)
+{
+    OC_UNUSED(queries);
+
+    m_rep.setValue(m_var_name_rt,  m_var_value_rt );
+    m_rep.setValue(m_var_name_n, m_var_value_n );
+    m_rep.setValue(m_var_name_if,  m_var_value_if );
+    m_rep.setValue(m_var_name_value, m_var_value_value );
+
+    return m_rep;
+}
+
+OCEntityHandlerResult BinarySwitchResource::post(OC::QueryParamsMap queries, const OC::OCRepresentation& rep)
+{
+    OCEntityHandlerResult ehResult = OC_EH_OK;
+    OC_UNUSED(queries);
+
+    try {
+        if (rep.hasAttribute(m_var_name_value))
+        {
+            // value exist in payload
+
+        }
+    }
+    catch (std::exception& e)
+    {
+        std::cout << e.what() << std::endl;
+    }
+
+    // TODO add check on array contents out of range, etc..
+
+    if (ehResult == OC_EH_OK)
+    {
+        // no error: assign the variables
+
+        // array only works for integer, boolean, numbers and strings
+        // TODO: make it also work with array of objects
+        try {
+            if (rep.hasAttribute(m_var_name_rt))
+            {
+                rep.getValue(m_var_name_rt, m_var_value_rt);
+                int first = 1;
+                std::cout << "\t\t" << "property 'rt' : " ;
+                for(auto myvar: m_var_value_rt)
+                {
+                    if(first)
+                    {
+                        std::cout << myvar;
+                        first = 0;
+                    }
+                    else
+                    {
+                        std::cout << "," << myvar;
+                    }
+                }
+                std::cout <<  std::endl;
+                m_send_notification_flag = true;
+            }
+            else
+            {
+                std::cout << "\t\t" << "property 'rt' not found in the representation" << std::endl;
+            }
+        }
+        catch (std::exception& e)
+        {
+            std::cout << e.what() << std::endl;
+        }
+
+        try {
+            if (rep.getValue(m_var_name_n, m_var_value_n ))
+            {
+                std::cout << "\t\t" << "property 'n' : " << m_var_value_n << std::endl;
+                m_send_notification_flag = true;
+            }
+            else
+            {
+                std::cout << "\t\t" << "property 'n' not found in the representation" << std::endl;
+            }
+        }
+        catch (std::exception& e)
+        {
+            std::cout << e.what() << std::endl;
+        }
+
+        // array only works for integer, boolean, numbers and strings
+        // TODO: make it also work with array of objects
+        try {
+            if (rep.hasAttribute(m_var_name_if))
+            {
+                rep.getValue(m_var_name_if, m_var_value_if);
+                int first = 1;
+                std::cout << "\t\t" << "property 'if' : " ;
+                for(auto myvar: m_var_value_if)
+                {
+                    if(first)
+                    {
+                        std::cout << myvar;
+                        first = 0;
+                    }
+                    else
+                    {
+                        std::cout << "," << myvar;
+                    }
+                }
+                std::cout <<  std::endl;
+                m_send_notification_flag = true;
+            }
+            else
+            {
+                std::cout << "\t\t" << "property 'if' not found in the representation" << std::endl;
+            }
+        }
+        catch (std::exception& e)
+        {
+            std::cout << e.what() << std::endl;
+        }
+
+        try {
+            if (rep.getValue(m_var_name_value, m_var_value_value ))
+            {
+                std::cout << "\t\t" << "property 'value': " << m_var_value_value << std::endl;
+                m_send_notification_flag = true;
+            }
+            else
+            {
+                std::cout << "\t\t" << "property 'value' not found in the representation" << std::endl;
+            }
+        }
+        catch (std::exception& e)
+        {
+            std::cout << e.what() << std::endl;
+        }
+        if (m_send_notification_flag)
+        {
+            m_cv.notify_all();
+        }
+    }
+    return ehResult;
+}
+
+void BinarySwitchResource::notifyObservers(void) {
+    // TODO add code to handle the other resource properties.
+    //std::vector<std::string> prev_rt = m_var_value_rt;
+    //std::string prev_n = m_var_value_n;
+    //std::vector<std::string> prev_if = m_var_value_if;
+    bool prev_value = this->m_var_value_value;
+    std::unique_lock<std::mutex> cv_lock(m_cv_mutex);
+    while (m_notify_thread_active)
+    {
+        m_cv.wait(cv_lock);
+        if(m_send_notification_flag)
+        {
+            m_send_notification_flag = false;
+            std::cout << this->m_var_value_n << " Changed:" << std::endl;
+            std::cout << "\t Switch value - from " << (prev_value ? "ON" : "OFF") << " to " << (this->m_var_value_value ? "ON" : "OFF") << std::endl;
+
+            prev_value = this->m_var_value_value;
+
+            OCPlatform::notifyAllObservers(this->m_resourceHandle);
+        }
+    }
+}
+
+OCEntityHandlerResult BinarySwitchResource::entityHandler(std::shared_ptr<OC::OCResourceRequest> request)
+{
+    OCEntityHandlerResult ehResult = OC_EH_ERROR;
+    //std::cout << "In entity handler for BinarySwitchResource " << std::endl;
+
+    if(request)
+    {
+        std::cout << "In entity handler for BinarySwitchResource, URI is : "
+                << request->getResourceUri() << std::endl;
+
+        // Check for query params (if any)
+        QueryParamsMap queries = request->getQueryParameters();
+        if (!queries.empty())
+        {
+            std::cout << "\nQuery processing up to entityHandler" << std::endl;
+        }
+        for (auto it : queries)
+        {
+            std::cout << "Query key: " << it.first << " value : " << it.second
+                    << std::endl;
+        }
+        // get the value, so that we can AND it to check which flags are set
+        int requestFlag = request->getRequestHandlerFlag();
+
+        if(requestFlag & RequestHandlerFlag::RequestFlag)
+        {
+            // request flag is set
+            auto pResponse = std::make_shared<OC::OCResourceResponse>();
+            pResponse->setRequestHandle(request->getRequestHandle());
+            pResponse->setResourceHandle(request->getResourceHandle());
+
+            if(request->getRequestType() == "GET")
+            {
+                std::cout<<"BinarySwitchResource Get Request"<< std::endl;
+
+                pResponse->setResourceRepresentation(get(queries), "");
+                if(OC_STACK_OK == OCPlatform::sendResponse(pResponse))
+                {
+                    ehResult = OC_EH_OK;
+                }
+            }
+
+            else if(request->getRequestType() == "POST")
+            {
+                std::cout <<"BinarySwitchResource Post Request"<<std::endl;
+                bool  handle_post = true;
+
+                if (queries.size() > 0)
+                {
+                    for (const auto &eachQuery : queries)
+                    {
+                        std::string key = eachQuery.first;
+                        if (key.compare(INTERFACE_KEY) == 0)
+                        {
+                            std::string value = eachQuery.second;
+                            if (in_updatable_interfaces(value) == false)
+                            {
+                                std::cout << "Update request received via interface: " << value
+                                        << " . This interface is not authorized to update resource!!" << std::endl;
+                                pResponse->setResponseResult(OCEntityHandlerResult::OC_EH_FORBIDDEN);
+                                handle_post = false;
+                                ehResult = OC_EH_ERROR;
+                                break;
+                            }
+                        }
+                    }
+                }
+                if (handle_post)
+                {
+                    ehResult = post(queries, request->getResourceRepresentation());
+                    if (ehResult == OC_EH_OK)
+                    {
+                        pResponse->setResourceRepresentation(get(queries), "");
+                    }
+                    else
+                    {
+                        pResponse->setResponseResult(OCEntityHandlerResult::OC_EH_ERROR);
+                    }
+                    if(OC_STACK_OK == OCPlatform::sendResponse(pResponse))
+                    {
+                        // TODO: if there are observers inform the observers
+                        //OCStackResult sResult;
+                        // update all observers with the new value
+                        // not sure if this is an blocking call
+                        //sResult = OCPlatform::notifyListOfObservers(   m_resourceHandle,
+                        //                                               m_interestedObservers,
+                        //                                               pResponse);
+                    }
+                }
+            }
+            else
+            {
+                std::cout << "BinarySwitchResource unsupported request type (delete,put,..)"
+                        << request->getRequestType() << std::endl;
+                pResponse->setResponseResult(OC_EH_ERROR);
+                OCPlatform::sendResponse(pResponse);
+                ehResult = OC_EH_ERROR;
+            }
+        }
+
+        if(requestFlag & RequestHandlerFlag::ObserverFlag)
+        {
+            // observe flag is set
+            std::cout << "\t\trequestFlag : Observer\n" << std::endl;
+            ObservationInfo observationInfo = request->getObservationInfo();
+            if(ObserveAction::ObserveRegister == observationInfo.action)
+            {
+                // add observer
+                m_interestedObservers.push_back(observationInfo.obsId);
+            }
+            else if(ObserveAction::ObserveUnregister == observationInfo.action)
+            {
+                // delete observer
+                m_interestedObservers.erase(std::remove(
+                        m_interestedObservers.begin(),
+                        m_interestedObservers.end(),
+                        observationInfo.obsId),
+                        m_interestedObservers.end());
+            }
+            ehResult = OC_EH_OK;
+        }
+    }
+    return ehResult;
+}
diff --git a/resource/examples/ocf_light/BinarySwitchResource.h b/resource/examples/ocf_light/BinarySwitchResource.h
new file mode 100644 (file)
index 0000000..7a81b4a
--- /dev/null
@@ -0,0 +1,97 @@
+/*
+ * BinarySwitchResource.h
+ */
+
+#ifndef EXAMPLE_OCF_LIGHT_BINARYSWITCHRESOURCE_H_
+#define EXAMPLE_OCF_LIGHT_BINARYSWITCHRESOURCE_H_
+
+#include <vector>
+#include <atomic>
+#include <thread>
+#include <condition_variable>
+
+#include "Resource.h"
+
+#include "OCApi.h"
+#include "OCRepresentation.h"
+
+class BinarySwitchResource : public Resource
+{
+    public:
+        /*
+        * constructor
+        */
+        BinarySwitchResource();
+        virtual ~BinarySwitchResource();
+
+    private:
+
+        /*
+        * function to make the payload for the retrieve function (e.g. GET) /binaryswitch
+        * @param queries  the query parameters for this call
+        */
+        OC::OCRepresentation get(OC::QueryParamsMap queries);
+
+        /*
+        * function to parse the payload for the update function (e.g. POST) /binaryswitch
+        * @param queries  the query parameters for this call
+        * @param rep  the response to get the property values from
+        * @return OCEntityHandlerResult ok or not ok indication
+        */
+        OCEntityHandlerResult post(OC::QueryParamsMap queries, const OC::OCRepresentation& rep);
+
+        std::atomic<bool> m_notify_thread_active;
+        std::thread* m_notify_thread;
+
+        std::atomic<bool> m_send_notification_flag;
+        std::mutex m_cv_mutex;
+        std::condition_variable m_cv;
+        void notifyObservers(void);
+
+        // resource types and interfaces as array..
+        std::string m_RESOURCE_TYPE[1]; // rt value (as an array)
+        std::string m_RESOURCE_INTERFACE[2]; // interface if (as an array)
+        std::string m_IF_UPDATE[3]; // updateble interfaces
+        int m_nr_resource_types;
+        int m_nr_resource_interfaces;
+        OC::ObservationIds m_interestedObservers;
+
+        // member variables for path: /binaryswitch
+
+        std::vector<std::string>  m_var_value_rt;
+        std::string m_var_name_rt; // the name for the attribute
+
+        std::string m_var_value_n; // the value for the attribute
+        std::string m_var_name_n; // the name for the attribute
+
+
+        std::vector<std::string>  m_var_value_if;
+        std::string m_var_name_if; // the name for the attribute
+
+        bool m_var_value_value; // the value for the attribute
+        std::string m_var_name_value; // the name for the attribute
+        protected:
+        /*
+        * function to check if the interface is
+        * @param  interface_name the interface name used during the request
+        * @return true: updatable interface
+        */
+        bool in_updatable_interfaces(std::string interface_name)
+        {
+            for (int i=0; i<3; i++)
+            {
+                if (m_IF_UPDATE[i].compare(interface_name) == 0)
+                    return true;
+            }
+            return false;
+        }
+
+        /*
+        * the entity handler for this resource
+        * @param request the incoming request to handle
+        * @return OCEntityHandlerResult ok or not ok indication
+        */
+        virtual OCEntityHandlerResult entityHandler(std::shared_ptr<OC::OCResourceRequest> request);
+};
+
+#endif /* EXAMPLE_OCF_LIGHT_BINARYSWITCHRESOURCE_H_ */
diff --git a/resource/examples/ocf_light/DimmingLightServer.cpp b/resource/examples/ocf_light/DimmingLightServer.cpp
new file mode 100644 (file)
index 0000000..c046c8e
--- /dev/null
@@ -0,0 +1,21 @@
+/*
+ * DimmingLightServer.cpp
+ */
+#include <iostream>
+
+#include "DimmingLightServer.h"
+#include "OCPlatform.h"
+
+using namespace OC;
+
+DimmingLightServer::DimmingLightServer(void):
+m_binaryswitchInstance(),
+m_dimmingInstance()
+{
+    std::cout << "Running DimmingLightServer constructor" << std::endl;
+}
+
+DimmingLightServer::~DimmingLightServer(void)
+{
+    std::cout << "Running DimmingLightServer destructor" << std::endl;
+}
diff --git a/resource/examples/ocf_light/DimmingLightServer.h b/resource/examples/ocf_light/DimmingLightServer.h
new file mode 100644 (file)
index 0000000..e78633b
--- /dev/null
@@ -0,0 +1,32 @@
+/*
+ * DimmingLightServer.h
+ */
+
+#ifndef EXAMPLE_OCF_LIGHT_DIMMINGLIGHTSERVER_H_
+#define EXAMPLE_OCF_LIGHT_DIMMINGLIGHTSERVER_H_
+
+#include "BinarySwitchResource.h"
+#include "DimmingResource.h"
+
+class DimmingLightServer
+{
+public:
+    /**
+     *  constructor
+     *  creates all resources from the resource classes.
+     */
+    DimmingLightServer(void);
+
+    /**
+     *  destructor
+     *
+     */
+    ~DimmingLightServer(void);
+
+private:
+    // Resources that are part of this server
+    BinarySwitchResource  m_binaryswitchInstance;
+    DimmingResource  m_dimmingInstance;
+};
+
+#endif /* EXAMPLE_OCF_LIGHT_DIMMINGLIGHTSERVER_H_ */
diff --git a/resource/examples/ocf_light/DimmingResource.cpp b/resource/examples/ocf_light/DimmingResource.cpp
new file mode 100644 (file)
index 0000000..1a0fbcc
--- /dev/null
@@ -0,0 +1,390 @@
+/*
+ * DimmingResource.cpp
+ */
+#include <iostream>
+
+#include "DimmingResource.h"
+#include "OCPlatform.h"
+
+#define INTERFACE_KEY "if"
+
+using namespace OC;
+namespace PH = std::placeholders;
+
+DimmingResource::DimmingResource():
+        m_notify_thread_active{true},
+        m_notify_thread{nullptr},
+        m_send_notification_flag{false},
+        m_cv_mutex{},
+        m_cv{},
+        m_nr_resource_types{1},
+        m_nr_resource_interfaces{2},
+        m_interestedObservers{},
+        m_var_value_dimmingSetting{100},
+        m_var_value_n{},
+        m_var_value_if{},
+        m_var_value_rt{}
+{
+    std::cout << "- Running: DimmingResource constructor" << std::endl;
+    std::string resourceURI = "/dimming";
+
+    // VS2013 will fail list initialization so use array initialization
+    m_RESOURCE_TYPE[0] = "oic.r.light.dimming";
+    m_RESOURCE_INTERFACE[0] = "oic.if.baseline";
+    m_RESOURCE_INTERFACE[1] = "oic.if.a";
+    m_IF_UPDATE[0] = "oic.if.a";
+    m_IF_UPDATE[1] = "oic.if.rw";
+    m_IF_UPDATE[2] = "oic.if.baseline";
+    m_var_name_dimmingSetting = "dimmingSetting";
+    m_var_name_n = "n";
+    m_var_name_if = "if";
+    m_var_name_rt = "rt";
+
+    // initialize member variables /dimming
+    m_var_value_dimmingSetting = 0; // current value of property "dimmingSetting"
+    m_var_value_n = "";  // current value of property "n"
+    // initialize vector if
+    m_var_value_if.push_back("oic.if.baseline");
+    m_var_value_if.push_back("oic.if.a");
+    // initialize vector rt
+    m_var_value_rt.push_back("oic.r.light.dimming");
+
+    EntityHandler cb = std::bind(&DimmingResource::entityHandler, this,PH::_1);
+    //uint8_t resourceProperty = 0;
+    OCStackResult result = OCPlatform::registerResource(m_resourceHandle,
+            resourceURI,
+            m_RESOURCE_TYPE[0],
+            m_RESOURCE_INTERFACE[0],
+            cb,
+            OC_DISCOVERABLE | OC_OBSERVABLE | OC_SECURE );
+
+    // add the additional interfaces
+    std::cout << "\t" << "# resource interfaces: " << m_nr_resource_interfaces << std::endl;
+    std::cout << "\t" << "# resource types     : " << m_nr_resource_types << std::endl;
+    for( int a = 1; a < m_nr_resource_interfaces; a++)
+    {
+        OCStackResult result1 = OCBindResourceInterfaceToResource(m_resourceHandle, m_RESOURCE_INTERFACE[a].c_str());
+        if (result1 != OC_STACK_OK)
+            std::cerr << "Could not bind interface:" << m_RESOURCE_INTERFACE[a] << std::endl;
+    }
+    // add the additional resource types
+    for( int a = 1; a < m_nr_resource_types; a++ )
+    {
+        OCStackResult result2 = OCBindResourceTypeToResource(m_resourceHandle, m_RESOURCE_TYPE[a].c_str());
+        if (result2 != OC_STACK_OK)
+            std::cerr << "Could not bind resource type:" << m_RESOURCE_INTERFACE[a] << std::endl;
+    }
+
+    if(OC_STACK_OK != result)
+    {
+        throw std::runtime_error(
+                std::string("DimmingResource failed to start")+std::to_string(result));
+    }
+
+    m_send_notification_flag = false;
+    m_notify_thread_active = true;
+    m_notify_thread = new std::thread(&DimmingResource::notifyObservers, this);
+}
+
+DimmingResource::~DimmingResource()
+{
+    m_notify_thread_active = false;
+    m_cv.notify_all();
+    if(m_notify_thread->joinable())
+    {
+        m_notify_thread->join();
+    }
+}
+
+OC::OCRepresentation DimmingResource::get(OC::QueryParamsMap queries)
+{
+    OC_UNUSED(queries);
+
+    m_rep.setValue(m_var_name_dimmingSetting, m_var_value_dimmingSetting );
+    m_rep.setValue(m_var_name_n, m_var_value_n );
+    m_rep.setValue(m_var_name_if,  m_var_value_if );
+    m_rep.setValue(m_var_name_rt,  m_var_value_rt );
+
+    return m_rep;
+}
+
+OCEntityHandlerResult DimmingResource::post(OC::QueryParamsMap queries, const OC::OCRepresentation& rep)
+{
+    OCEntityHandlerResult ehResult = OC_EH_OK;
+    OC_UNUSED(queries);
+
+    try {
+        if (rep.hasAttribute(m_var_name_dimmingSetting))
+        {
+            // allocate the variable
+            int value;
+            // get the actual value from the payload
+            rep.getValue(m_var_name_dimmingSetting, value);
+
+            // value exist in payload
+        }
+    }
+    catch (std::exception& e)
+    {
+        std::cout << e.what() << std::endl;
+    }
+
+    // TODO add check on array contents out of range, etc..
+    if (ehResult == OC_EH_OK)
+    {
+        // no error: assign the variables
+
+        try {
+            // value exist in payload
+            if (rep.getValue(m_var_name_dimmingSetting, m_var_value_dimmingSetting ))
+            {
+                std::cout << "\t\t" << "property 'dimmingSetting': " << m_var_value_dimmingSetting << std::endl;
+                m_send_notification_flag = true;
+            }
+            else
+            {
+                std::cout << "\t\t" << "property 'dimmingSetting' not found in the representation" << std::endl;
+            }
+        }
+        catch (std::exception& e)
+        {
+            std::cout << e.what() << std::endl;
+        }
+
+        try {
+            if (rep.getValue(m_var_name_n, m_var_value_n ))
+            {
+                std::cout << "\t\t" << "property 'n' : " << m_var_value_n << std::endl;
+                m_send_notification_flag = true;
+            }
+            else
+            {
+                std::cout << "\t\t" << "property 'n' not found in the representation" << std::endl;
+            }
+        }
+        catch (std::exception& e)
+        {
+            std::cout << e.what() << std::endl;
+        }
+
+        // array only works for integer, boolean, numbers and strings
+        // TODO: make it also work with array of objects
+        try {
+            if (rep.hasAttribute(m_var_name_if))
+            {
+                rep.getValue(m_var_name_if, m_var_value_if);
+                int first = 1;
+                std::cout << "\t\t" << "property 'if' : " ;
+                for(auto myvar: m_var_value_if)
+                {
+                    if(first)
+                    {
+                        std::cout << myvar;
+                        first = 0;
+                    }
+                    else
+                    {
+                        std::cout << "," << myvar;
+                    }
+                }
+                std::cout <<  std::endl;
+                m_send_notification_flag = true;
+            }
+            else
+            {
+                std::cout << "\t\t" << "property 'if' not found in the representation" << std::endl;
+            }
+        }
+        catch (std::exception& e)
+        {
+            std::cout << e.what() << std::endl;
+        }
+
+        // array only works for integer, boolean, numbers and strings
+        // TODO: make it also work with array of objects
+        try {
+            if (rep.hasAttribute(m_var_name_rt))
+            {
+                rep.getValue(m_var_name_rt, m_var_value_rt);
+                int first = 1;
+                std::cout << "\t\t" << "property 'rt' : " ;
+                for(auto myvar: m_var_value_rt)
+                {
+                    if(first)
+                    {
+                        std::cout << myvar;
+                        first = 0;
+                    }
+                    else
+                    {
+                        std::cout << "," << myvar;
+                    }
+                }
+                std::cout <<  std::endl;
+                m_send_notification_flag = true;
+            }
+            else
+            {
+                std::cout << "\t\t" << "property 'rt' not found in the representation" << std::endl;
+            }
+        }
+        catch (std::exception& e)
+        {
+            std::cout << e.what() << std::endl;
+        }
+        if (m_send_notification_flag)
+        {
+            m_cv.notify_all();
+        }
+    }
+    return ehResult;
+}
+
+void DimmingResource::notifyObservers(void) {
+    // TODO add code to handle the other resource properties.
+    //std::vector<std::string> prev_rt = m_var_value_rt;
+    //std::string prev_n = m_var_value_n;
+    //std::vector<std::string> prev_if = m_var_value_if;
+    int prev_dimmingSetting = this->m_var_value_dimmingSetting;
+    std::unique_lock<std::mutex> cv_lock(m_cv_mutex);
+    while (m_notify_thread_active)
+    {
+        m_cv.wait(cv_lock);
+        std::this_thread::sleep_for(std::chrono::seconds(1));
+        if(m_send_notification_flag)
+        {
+            m_send_notification_flag = false;
+            std::cout << this->m_var_value_n << " Changed:" << std::endl;
+            std::cout << "\t Switch value - from " << prev_dimmingSetting << " to " << this->m_var_value_dimmingSetting << std::endl;
+
+            prev_dimmingSetting = this->m_var_value_dimmingSetting;
+
+            OCPlatform::notifyAllObservers(this->m_resourceHandle);
+        }
+    }
+}
+
+OCEntityHandlerResult DimmingResource::entityHandler(std::shared_ptr<OC::OCResourceRequest> request)
+{
+    OCEntityHandlerResult ehResult = OC_EH_ERROR;
+    //std::cout << "In entity handler for DimmingResource " << std::endl;
+
+    if(request)
+    {
+        std::cout << "In entity handler for DimmingResource, URI is : "
+                << request->getResourceUri() << std::endl;
+
+        // Check for query params (if any)
+        QueryParamsMap queries = request->getQueryParameters();
+        if (!queries.empty())
+        {
+            std::cout << "\nQuery processing up to entityHandler" << std::endl;
+        }
+        for (auto it : queries)
+        {
+            std::cout << "Query key: " << it.first << " value : " << it.second
+                    << std::endl;
+        }
+        // get the value, so that we can AND it to check which flags are set
+        int requestFlag = request->getRequestHandlerFlag();
+
+        if(requestFlag & RequestHandlerFlag::RequestFlag)
+        {
+            // request flag is set
+            auto pResponse = std::make_shared<OC::OCResourceResponse>();
+            pResponse->setRequestHandle(request->getRequestHandle());
+            pResponse->setResourceHandle(request->getResourceHandle());
+
+            if(request->getRequestType() == "GET")
+            {
+                std::cout<<"DimmingResource Get Request"<< std::endl;
+
+                pResponse->setResourceRepresentation(get(queries), "");
+                if(OC_STACK_OK == OCPlatform::sendResponse(pResponse))
+                {
+                    ehResult = OC_EH_OK;
+                }
+            }
+
+            else if(request->getRequestType() == "POST")
+            {
+                std::cout <<"DimmingResource Post Request"<<std::endl;
+                bool  handle_post = true;
+
+                if (queries.size() > 0)
+                {
+                    for (const auto &eachQuery : queries)
+                    {
+                        std::string key = eachQuery.first;
+                        if (key.compare(INTERFACE_KEY) == 0)
+                        {
+                            std::string value = eachQuery.second;
+                            if (in_updatable_interfaces(value) == false)
+                            {
+                                std::cout << "Update request received via interface: " << value
+                                        << " . This interface is not authorized to update resource!!" << std::endl;
+                                pResponse->setResponseResult(OCEntityHandlerResult::OC_EH_FORBIDDEN);
+                                handle_post = false;
+                                ehResult = OC_EH_ERROR;
+                                break;
+                            }
+                        }
+                    }
+                }
+                if (handle_post)
+                {
+                    ehResult = post(queries, request->getResourceRepresentation());
+                    if (ehResult == OC_EH_OK)
+                    {
+                        pResponse->setResourceRepresentation(get(queries), "");
+                    }
+                    else
+                    {
+                        pResponse->setResponseResult(OCEntityHandlerResult::OC_EH_ERROR);
+                    }
+                    if(OC_STACK_OK == OCPlatform::sendResponse(pResponse))
+                    {
+                        // TODO: if there are observers inform the observers
+                        //OCStackResult sResult;
+                        // update all observers with the new value
+                        // not sure if this is an blocking call
+                        //sResult = OCPlatform::notifyListOfObservers(   m_resourceHandle,
+                        //                                               m_interestedObservers,
+                        //                                               pResponse);
+                    }
+                }
+            }
+            else
+            {
+                std::cout << "DimmingResource unsupported request type (delete,put,..)"
+                        << request->getRequestType() << std::endl;
+                pResponse->setResponseResult(OC_EH_ERROR);
+                OCPlatform::sendResponse(pResponse);
+                ehResult = OC_EH_ERROR;
+            }
+        }
+
+        if(requestFlag & RequestHandlerFlag::ObserverFlag)
+        {
+            // observe flag is set
+            std::cout << "\t\trequestFlag : Observer\n" << std::endl;
+            ObservationInfo observationInfo = request->getObservationInfo();
+            if(ObserveAction::ObserveRegister == observationInfo.action)
+            {
+                // add observer
+                m_interestedObservers.push_back(observationInfo.obsId);
+            }
+            else if(ObserveAction::ObserveUnregister == observationInfo.action)
+            {
+                // delete observer
+                m_interestedObservers.erase(std::remove(
+                        m_interestedObservers.begin(),
+                        m_interestedObservers.end(),
+                        observationInfo.obsId),
+                        m_interestedObservers.end());
+            }
+            ehResult = OC_EH_OK;
+        }
+    }
+    return ehResult;
+}
diff --git a/resource/examples/ocf_light/DimmingResource.h b/resource/examples/ocf_light/DimmingResource.h
new file mode 100644 (file)
index 0000000..1406c6a
--- /dev/null
@@ -0,0 +1,97 @@
+/*
+ * DimmingResource.h
+ */
+
+#ifndef EXAMPLE_OCF_LIGHT_DIMMINGRESOURCE_H_
+#define EXAMPLE_OCF_LIGHT_DIMMINGRESOURCE_H_
+
+#include <vector>
+#include <atomic>
+#include <thread>
+#include <condition_variable>
+
+#include "Resource.h"
+
+#include "OCApi.h"
+#include "OCRepresentation.h"
+
+class DimmingResource : public Resource
+{
+public:
+    /*
+     * constructor
+     */
+    DimmingResource();
+    virtual ~DimmingResource();
+private:
+
+    /*
+     * function to make the payload for the retrieve function (e.g. GET) /dimming
+     * @param queries  the query parameters for this call
+     */
+    OC::OCRepresentation get(OC::QueryParamsMap queries);
+
+    /*
+     * function to parse the payload for the update function (e.g. POST) /dimming
+     * @param queries  the query parameters for this call
+     * @param rep  the response to get the property values from
+     * @return OCEntityHandlerResult ok or not ok indication
+     */
+    OCEntityHandlerResult post(OC::QueryParamsMap queries, const OC::OCRepresentation& rep);
+
+
+    std::atomic<bool> m_notify_thread_active;
+    std::thread* m_notify_thread;
+
+    std::atomic<bool> m_send_notification_flag;
+    std::mutex m_cv_mutex;
+    std::condition_variable m_cv;
+    void notifyObservers(void);
+
+    // resource types and interfaces as array..
+    std::string m_RESOURCE_TYPE[1]; // rt value (as an array)
+    std::string m_RESOURCE_INTERFACE[2]; // interface if (as an array)
+    std::string m_IF_UPDATE[3]; // updateble interfaces
+    int m_nr_resource_types;
+    int m_nr_resource_interfaces;
+    OC::ObservationIds m_interestedObservers;
+
+    // member variables for path: /dimming
+    int m_var_value_dimmingSetting; // the value for the attribute
+    std::string m_var_name_dimmingSetting; // the name for the attribute
+
+    std::string m_var_value_n; // the value for the attribute
+    std::string m_var_name_n; // the name for the attribute
+
+
+    std::vector<std::string>  m_var_value_if;
+    std::string m_var_name_if; // the name for the attribute
+
+
+    std::vector<std::string>  m_var_value_rt;
+    std::string m_var_name_rt; // the name for the attribute
+protected:
+    /*
+     * function to check if the interface is
+     * @param  interface_name the interface name used during the request
+     * @return true: updatable interface
+     */
+    bool in_updatable_interfaces(std::string interface_name)
+    {
+        for (int i=0; i<3; i++)
+        {
+            if (m_IF_UPDATE[i].compare(interface_name) == 0)
+                return true;
+        }
+        return false;
+    }
+
+    /*
+     * the entity handler for this resource
+     * @param request the incoming request to handle
+     * @return OCEntityHandlerResult ok or not ok indication
+     */
+    virtual OCEntityHandlerResult entityHandler(std::shared_ptr<OC::OCResourceRequest> request);
+};
+
+#endif /* EXAMPLE_OCF_LIGHT_DIMMINGRESOURCE_H_ */
diff --git a/resource/examples/ocf_light/PICS.json b/resource/examples/ocf_light/PICS.json
new file mode 100644 (file)
index 0000000..81a9751
--- /dev/null
@@ -0,0 +1,30 @@
+{\r
+    "device": "test1",\r
+    "company": "Open Connectivity Foundation",\r
+    "role": "Server",\r
+    "supportedVerticalProfile": [\r
+        "Smart Home"\r
+    ],\r
+    "supportedDeviceTypes": [\r
+        "oic.d.light"\r
+    ],\r
+    "icv": "ocf.1.0.0",\r
+    "dmv": "ocf.res.1.3.0, ocf.sh.1.3.0",\r
+    "resources": [\r
+    \r
+  \r
+"oic.r.switch.binary",\r
+  \r
+"oic.r.light.dimming"\r
+],\r
+    "jurisdictionSwitch": false,\r
+    "OTM": [\r
+        "oic.sec.doxm.jw"\r
+    ],\r
+    "contentFormatVersion": [ "1.0.0" ],\r
+    "acceptVersion": [ "1.0.0" ],\r
+\r
+    "multiValueQuerySupport": false,\r
+    "observableOICRES": true,\r
+    "persistentDeviceuuid": false\r
+}
\ No newline at end of file
diff --git a/resource/examples/ocf_light/Platform.cpp b/resource/examples/ocf_light/Platform.cpp
new file mode 100644 (file)
index 0000000..21218a8
--- /dev/null
@@ -0,0 +1,201 @@
+/*
+ * Platform.cpp
+ *
+ *  Created on: Feb 12, 2018
+ *      Author: georgena
+ */
+#include <iostream>
+
+#include "OCPlatform.h"
+#include "Platform.h"
+
+using namespace OC;
+
+/**
+ *  server_fopen
+ *  opens file
+ *  implements redirection to open:
+ * - initial security settings
+ * - introspection file
+ * @param path path+filename of the file to open
+ * @param mode mode of the file to open
+ * @return the filehandle of the opened file (or error)
+ */
+FILE* server_fopen(const char* path, const char* mode)
+{
+    FILE* fileptr = NULL;
+
+    if (0 == strcmp(path, OC_SECURITY_DB_DAT_FILE_NAME))
+    {
+        // reading the security initial setup file
+        fileptr = fopen("server_security.dat", mode);
+        std::cout << "reading security file 'server_security.dat' ptr: " << fileptr << std::endl;
+        return fileptr;
+    }
+    else if (0 == strcmp(path, OC_INTROSPECTION_FILE_NAME))
+    {
+        // reading the introspection file
+        fileptr = fopen("server_introspection.dat", mode);
+        std::cout << "reading introspection file  'server_introspection.dat' ptr: " << fileptr << std::endl;
+        return fileptr;
+    }
+    else
+    {
+        std::cout << "persistent storage - server_fopen: " << path << std::endl;
+        return fopen(path, mode);
+    }
+}
+
+// Create persistent storage handlers
+OCPersistentStorage ps{server_fopen, fread, fwrite, fclose, unlink};
+
+Platform::Platform(void)
+{
+    std::cout << "Running Platform constructor" << std::endl;
+    dataModelVersions.push_back("ocf.res.1.3.0");
+    dataModelVersions.push_back("ocf.sh.1.3.0");
+    // create the platform
+    PlatformConfig cfg
+    {
+        ServiceType::InProc,
+        ModeType::Server,
+        &ps
+    };
+    OCPlatform::Configure(cfg);
+    setPlatformInfo(m_platformId, m_manufacturerName, m_manufacturerLink,
+                    m_modelNumber, m_dateOfManufacture, m_platformVersion, m_operatingSystemVersion,
+                    m_hardwareVersion, m_firmwareVersion, m_supportLink, m_systemTime);
+
+}
+
+Platform::~Platform(void)
+{
+    std::cout << "Running Platform destructor" << std::endl;
+    deletePlatformInfo();
+}
+
+OCStackResult Platform::start(void)
+{
+    return OCPlatform::start();
+}
+
+OCStackResult Platform::registerPlatformInfo(void)
+{
+    OCStackResult result = OC_STACK_ERROR;
+    result = OCPlatform::registerPlatformInfo(platformInfo);
+    return result;
+}
+
+
+OCPlatformInfo* Platform::getPlatformInfo(void)
+{
+    return &platformInfo;
+}
+
+OCStackResult Platform::stop(void)
+{
+    return OCPlatform::stop();
+}
+
+/**
+ *  DuplicateString
+ *
+ * @param targetString  destination string, will be allocated
+ * @param sourceString  source string, e.g. will be copied
+
+ *  TODO: don't use strncpy
+ */
+void DuplicateString(char ** targetString, std::string sourceString)
+{
+    *targetString = new char[sourceString.length() + 1];
+    strncpy(*targetString, sourceString.c_str(), (sourceString.length() + 1));
+}
+
+void Platform::setPlatformInfo(std::string platformID, std::string manufacturerName,
+        std::string manufacturerUrl, std::string modelNumber, std::string dateOfManufacture,
+        std::string platformVersion, std::string operatingSystemVersion,
+        std::string hardwareVersion, std::string firmwareVersion, std::string supportUrl,
+        std::string systemTime)
+{
+    DuplicateString(&platformInfo.platformID, platformID);
+    DuplicateString(&platformInfo.manufacturerName, manufacturerName);
+    DuplicateString(&platformInfo.manufacturerUrl, manufacturerUrl);
+    DuplicateString(&platformInfo.modelNumber, modelNumber);
+    DuplicateString(&platformInfo.dateOfManufacture, dateOfManufacture);
+    DuplicateString(&platformInfo.platformVersion, platformVersion);
+    DuplicateString(&platformInfo.operatingSystemVersion, operatingSystemVersion);
+    DuplicateString(&platformInfo.hardwareVersion, hardwareVersion);
+    DuplicateString(&platformInfo.firmwareVersion, firmwareVersion);
+    DuplicateString(&platformInfo.supportUrl, supportUrl);
+    DuplicateString(&platformInfo.systemTime, systemTime);
+}
+
+void Platform::deletePlatformInfo(void)
+{
+    delete[] platformInfo.platformID;
+    delete[] platformInfo.manufacturerName;
+    delete[] platformInfo.manufacturerUrl;
+    delete[] platformInfo.modelNumber;
+    delete[] platformInfo.dateOfManufacture;
+    delete[] platformInfo.platformVersion;
+    delete[] platformInfo.operatingSystemVersion;
+    delete[] platformInfo.hardwareVersion;
+    delete[] platformInfo.firmwareVersion;
+    delete[] platformInfo.supportUrl;
+    delete[] platformInfo.systemTime;
+}
+
+/**
+ *  SetDeviceInfo
+ *  Sets the device information ("oic/d"), from the globals
+
+ * @return OC_STACK_ERROR or OC_STACK_OK
+ */
+OCStackResult Platform::setDeviceInfo()
+{
+    OCStackResult result = OC_STACK_ERROR;
+
+    OCResourceHandle handle = OCGetResourceHandleAtUri(OC_RSRVD_DEVICE_URI);
+    if (handle == NULL)
+    {
+        std::cout << "Failed to find resource " << OC_RSRVD_DEVICE_URI << std::endl;
+        return result;
+    }
+    result = OCBindResourceTypeToResource(handle, deviceType.c_str());
+    if (result != OC_STACK_OK)
+    {
+        std::cout << "Failed to add device type" << std::endl;
+        return result;
+    }
+
+    result = OCPlatform::setPropertyValue(PAYLOAD_TYPE_DEVICE, OC_RSRVD_DATA_MODEL_VERSION,
+            dataModelVersions);
+    if (result != OC_STACK_OK)
+    {
+        std::cout << "Failed to set data model versions" << std::endl;
+        return result;
+    }
+
+    result = OCPlatform::setPropertyValue(PAYLOAD_TYPE_DEVICE, OC_RSRVD_SPEC_VERSION, specVersion);
+    if (result != OC_STACK_OK)
+    {
+        std::cout << "Failed to set spec version" << std::endl;
+        return result;
+    }
+
+    result = OCPlatform::setPropertyValue(PAYLOAD_TYPE_DEVICE, OC_RSRVD_PROTOCOL_INDEPENDENT_ID,
+            protocolIndependentID);
+    if (result != OC_STACK_OK)
+    {
+        std::cout << "Failed to set piid" << std::endl;
+        return result;
+    }
+
+    result = OCPlatform::setPropertyValue(PAYLOAD_TYPE_DEVICE, OC_RSRVD_DEVICE_NAME, deviceName);
+    if (result != OC_STACK_OK)
+    {
+        std::cout << "Failed to set device name" << std::endl;
+        return result;
+    }
+    return OC_STACK_OK;
+}
diff --git a/resource/examples/ocf_light/Platform.h b/resource/examples/ocf_light/Platform.h
new file mode 100644 (file)
index 0000000..fe2ff3f
--- /dev/null
@@ -0,0 +1,84 @@
+/*
+ * Platform.h
+ */
+
+#ifndef EXAMPLE_OCF_LIGHT_PLATFORM_H_
+#define EXAMPLE_OCF_LIGHT_PLATFORM_H_
+
+#include <vector>
+#include <string>
+#include "OCPlatform.h"
+
+class Platform
+{
+public:
+    Platform(void);
+    virtual ~Platform(void);
+
+    OCStackResult start(void);
+    OCStackResult registerPlatformInfo(void);
+    OCPlatformInfo* getPlatformInfo(void);
+    OCStackResult stop(void);
+
+    /**
+     *  SetDeviceInfo
+     *  Sets the device information ("oic/d"), from the globals
+
+     * @return OC_STACK_ERROR or OC_STACK_OK
+     */
+    OCStackResult setDeviceInfo(void);
+
+private:
+    // Set of strings for each of platform Info fields
+    std::string m_platformId = "0A3E0D6F-DBF5-404E-8719-D6880042463A";
+    std::string m_manufacturerName = "ocf";
+    std::string m_manufacturerLink = "https://ocf.org/";
+    std::string m_modelNumber = "ModelNumber";
+    std::string m_dateOfManufacture = "2017-12-01";
+    std::string m_platformVersion = "1.0";
+    std::string m_operatingSystemVersion = "myOS";
+    std::string m_hardwareVersion = "1.0";
+    std::string m_firmwareVersion = "1.0";
+    std::string m_supportLink = "https://ocf.org/";
+    std::string m_systemTime = "2017-12-01T12:00:00.52Z";
+
+    /**
+     *  SetPlatformInfo
+     *  Sets the platform information ("oic/p"), from the globals
+
+     * @param platformID the platformID
+     * @param manufacturerName the manufacturerName
+     * @param manufacturerUrl the manufacturerUrl
+     * @param modelNumber the modelNumber
+     * @param platformVersion the platformVersion
+     * @param operatingSystemVersion the operatingSystemVersion
+     * @param hardwareVersion the hardwareVersion
+     * @param firmwareVersion the firmwareVersion
+     * @param supportUrl the supportUrl
+     * @param systemTime the systemTime
+     */
+    void setPlatformInfo(std::string platformID, std::string manufacturerName,
+            std::string manufacturerUrl, std::string modelNumber, std::string dateOfManufacture,
+            std::string platformVersion, std::string operatingSystemVersion,
+            std::string hardwareVersion, std::string firmwareVersion, std::string supportUrl,
+            std::string systemTime);
+
+    /**
+     *  deletePlatformInfo
+     *  Deletes the allocated platform information
+     */
+    void deletePlatformInfo(void);
+    // OCPlatformInfo Contains all the platform info to be stored
+    OCPlatformInfo platformInfo;
+
+public:
+    std::string  protocolIndependentID = "fa008167-3bbf-4c9d-8604-c9bcb96cb712";
+
+    // Set of strings for each of device info fields
+    std::string  deviceName = "Binary Switch";
+    std::string  deviceType = "oic.d.light";
+    std::string  specVersion = "ocf.1.0.0";
+    std::vector<std::string> dataModelVersions;
+};
+
+#endif /* EXAMPLE_OCF_LIGHT_PLATFORM_H_ */
diff --git a/resource/examples/ocf_light/Resource.h b/resource/examples/ocf_light/Resource.h
new file mode 100644 (file)
index 0000000..ed2fe61
--- /dev/null
@@ -0,0 +1,24 @@
+/*
+ * resource.h
+ */
+#ifndef EXAMPLE_OCF_LIGHT_RESOURCE_H_
+#define EXAMPLE_OCF_LIGHT_RESOURCE_H_
+
+#include "octypes.h"
+#include "OCRepresentation.h"
+#include "OCResourceRequest.h"
+
+/*
+* default class, so that we have to define less variables/functions.
+*/
+class Resource
+{
+public:
+    virtual ~Resource() { };
+protected:
+    OCResourceHandle m_resourceHandle;
+    OC::OCRepresentation m_rep;
+    virtual OCEntityHandlerResult entityHandler(std::shared_ptr<OC::OCResourceRequest> request)=0;
+};
+
+#endif /* EXAMPLE_OCF_LIGHT_RESOURCE_H_ */
diff --git a/resource/examples/ocf_light/SConscript b/resource/examples/ocf_light/SConscript
new file mode 100644 (file)
index 0000000..b1e0165
--- /dev/null
@@ -0,0 +1,36 @@
+#******************************************************************
+#
+# Copyright 2018 Intel All Rights Reserved.
+#
+#-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+#      http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+#-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
+
+Import('examples_env')
+
+examples_env.AppendUnique(CPPPATH=[
+    Dir('.').srcnode().path
+])
+
+ocf_light_files = [
+    'dimming_light_server.cpp',
+    'BinarySwitchResource.cpp',
+    'DimmingLightServer.cpp',
+    'DimmingResource.cpp',
+    'Platform.cpp',
+]
+
+output = examples_env.Program(ocf_light_files)
+
diff --git a/resource/examples/ocf_light/dimming_light_server.cpp b/resource/examples/ocf_light/dimming_light_server.cpp
new file mode 100644 (file)
index 0000000..c76f110
--- /dev/null
@@ -0,0 +1,95 @@
+//******************************************************************\r
+//\r
+// Copyright 2017 Open Connectivity Foundation\r
+//\r
+//-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=\r
+//\r
+// Licensed under the Apache License, Version 2.0 (the "License");\r
+// you may not use this file except in compliance with the License.\r
+// You may obtain a copy of the License at\r
+//\r
+//      http://www.apache.org/licenses/LICENSE-2.0\r
+//\r
+// Unless required by applicable law or agreed to in writing, software\r
+// distributed under the License is distributed on an "AS IS" BASIS,\r
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\r
+// See the License for the specific language governing permissions and\r
+// limitations under the License.\r
+//\r
+//-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=\r
+#include <signal.h>\r
+#include <string>\r
+#include <iostream>\r
+\r
+#ifdef HAVE_WINDOWS_H\r
+#include <windows.h>\r
+#endif\r
+\r
+#include "DimmingLightServer.h"\r
+#include "Platform.h"\r
+\r
+using namespace OC;\r
+\r
+#define INTERFACE_KEY "if"\r
+\r
+#ifdef __unix__\r
+// global needs static, otherwise it can be compiled out and then Ctrl-C does not work\r
+static int quit = 0;\r
+// handler for the signal to stop the application\r
+void handle_signal(int signal)\r
+{\r
+    OC_UNUSED(signal);\r
+    quit = 1;\r
+}\r
+#endif\r
+\r
+// main application\r
+// starts the server \r
+int main()\r
+{\r
+    Platform platform;\r
+    OC_VERIFY(platform.start() == OC_STACK_OK);\r
+    std::cout << "oic/p" << std::endl;\r
+    // initialize "oic/p"\r
+    if(platform.registerPlatformInfo() != OC_STACK_OK)\r
+    {\r
+        std::cout << "Platform Registration (oic/p) failed\n";\r
+    }\r
+    // initialize "oic/d"\r
+    std::cout << "oic/d" << std::endl;\r
+    if(platform.setDeviceInfo() != OC_STACK_OK)\r
+    {\r
+        std::cout << "Device Registration (oic/d) failed\n";\r
+    }\r
+\r
+    std::cout << "device type: " <<  platform.deviceType << std::endl;\r
+    std::cout << "platformID: " <<  platform.getPlatformInfo()->platformID << std::endl;\r
+    std::cout << "platform independent: " << platform.protocolIndependentID << std::endl;\r
+\r
+    // create the server\r
+    DimmingLightServer server;\r
+\r
+#ifdef __unix__\r
+    struct sigaction sa;\r
+    sigfillset(&sa.sa_mask);\r
+    sa.sa_flags = 0;\r
+    sa.sa_handler = handle_signal;\r
+    sigaction(SIGINT, &sa, NULL);\r
+\r
+    std::cout << "Press Ctrl-C to quit...." << std::endl;\r
+    do\r
+    {\r
+        usleep(2000000);\r
+    }\r
+    while (quit != 1);\r
+#endif\r
+\r
+#if defined(_WIN32)\r
+    std::cout << "Press Ctrl-C to quit...." << std::endl;\r
+    // we will keep the server alive for at most 30 minutes\r
+    std::this_thread::sleep_for(std::chrono::minutes(30));\r
+#endif\r
+    OC_VERIFY(platform.stop() == OC_STACK_OK);\r
+\r
+    return 0;\r
+}\r
diff --git a/resource/examples/ocf_light/oic_svr_db_server_mvjustworks.dat b/resource/examples/ocf_light/oic_svr_db_server_mvjustworks.dat
new file mode 100644 (file)
index 0000000..f00b2d8
Binary files /dev/null and b/resource/examples/ocf_light/oic_svr_db_server_mvjustworks.dat differ
diff --git a/resource/examples/ocf_light/readme.md b/resource/examples/ocf_light/readme.md
new file mode 100644 (file)
index 0000000..52f3c9d
--- /dev/null
@@ -0,0 +1,181 @@
+# Template: IOTivity C++ server\r
+\r
+The generated code acts as an simulator:\r
+- it creates values at start update\r
+- handles incoming requests, \r
+    - stores the values on POST\r
+    - respond on GET by giving out the stored values\r
+\r
+## what is generated:\r
+        \r
+- server.cpp implementation code\r
+    - per resource an class is generated.\r
+        - constructor\r
+            - creates the resource\r
+        - has entity handler\r
+            - get function to use the variables to create the return payload\r
+            - post function to assign the variables from the request payload\r
+                - single type: integer, number and strings \r
+                - arrays \r
+                    - array members are set for an GET\r
+                    - array members are retrieved from an POST\r
+                    - only arrays of a single type are handled.\r
+                        e.g. array of int, array of strings, array of number\r
+                        NOT handled: array of objects.\r
+                        - TODO: add complex objecs, see garage example of how to next objects (see client and server side)\r
+                - checks on minimum, maximum and readOnly, no update of the value if this occurs \r
+                - check if the correct interface is used (oic.if.a or oic.if.rw)\r
+    - main \r
+        - creates all classes\r
+        - creates the device\r
+        - installs the reader for\r
+            - introspection device data file (IDD)\r
+            - security file (SVR) contents\r
+            these files needs to be installed/copied where the the executable is.\r
+           \r
+- svr_server.json  - not used !!!\r
+    default json definition of the secure virtual resources (svr)\r
+    - just works\r
+    - not onboarded\r
+    - not tested, not used yet.\r
+- oic_svr_db_server_mvjustworks.dat\r
+    - copy from iotivity-1.3.1\resource\csdk\security\provisioning\r
+    - security: just works\r
+    - used in CTT testing (e.g. it can onboard the device!), and CTT can talk to the device.\r
+- PICS.json\r
+    - pics for CTT testing\r
+    - security: just works.\r
\r
+          \r
+            \r
+## what is missing/incorrect:\r
+- handling query params (none interfaces)\r
+- handling observe\r
+- manual update of resource data, e.g. out of bounds so that one can trigger this to pass CTT.\r
+- creation/deletion of resources (PUT/DELETE functions)\r
+- no correct makefile/scons file, so we do not yet know how to insert this in the IOTivity tree and then compile\r
+    - see for manual changes below\r
+\r
+# notes:\r
+- only tested on windows\r
+- readOnly params like: "precision", "maximumsaturation" from oic.r.colour.chroma is crashing the device when running the CTT\r
+    - to avoid this: remove these properties from the generated device.\r
+\r
+\r
+## SCONS adaption in resource/examples\r
+\r
+old :\r
+```\r
+######################################################################\r
+# Source files and Targets\r
+######################################################################\r
+example_names = [\r
+    'simpleserver', 'simpleclient',\r
+    'simpleclientserver',\r
+    'directpairingclient',\r
+    'devicediscoveryserver', 'devicediscoveryclient',\r
+    'simpleserverHQ', 'simpleclientHQ',\r
+    ]\r
+\r
+if target_os not in ['windows', 'msys_nt']:\r
+    example_names += [\r
+        'fridgeserver', 'fridgeclient',\r
+        'presenceserver', 'presenceclient',\r
+        'roomserver', 'roomclient',\r
+        'garageserver',\r
+        'garageclient',\r
+        'groupserver',\r
+        'groupclient',\r
+        'lightserver',\r
+        'threadingsample',\r
+        'server',\r
+        'observer',\r
+        ]\r
+    if 'CLIENT' in examples_env.get('RD_MODE'):\r
+        examples_env.AppendUnique(CPPPATH = ['../csdk/resource-directory/include'])\r
+        examples_env.AppendUnique(LIBS = ['resource_directory'])\r
+        example_names += ['rdclient']\r
+\r
+examples = map(make_single_file_cpp_program, example_names)\r
+\r
+```\r
+new :\r
+```\r
+######################################################################\r
+# Source files and Targets\r
+######################################################################\r
+example_names = [\r
+    'server', \r
+    ]\r
+\r
+if target_os not in ['windows', 'msys_nt']:\r
+    example_names += [\r
+        'fridgeserver', 'fridgeclient',\r
+        'presenceserver', 'presenceclient',\r
+        'roomserver', 'roomclient',\r
+        'garageserver',\r
+        'garageclient',\r
+        'groupserver',\r
+        'groupclient',\r
+        'lightserver',\r
+        'threadingsample',\r
+        'server',\r
+        'observer',\r
+        ]\r
+    if 'CLIENT' in examples_env.get('RD_MODE'):\r
+        examples_env.AppendUnique(CPPPATH = ['../csdk/resource-directory/include'])\r
+        examples_env.AppendUnique(LIBS = ['resource_directory'])\r
+        example_names += ['rdclient']\r
+\r
+examples = map(make_single_file_cpp_program, example_names)\r
+```\r
+\r
+## WINDOWS run.bat changes:\r
+```\r
+REM *** BUILD OPTIONS ***\r
+\r
+if "!RUN_ARG!"=="server" (\r
+  cd %BUILD_DIR%\resource\examples\r
+  REM %DEBUG% simpleserver.exe\r
+  %DEBUG% server.exe\r
+) else if "!RUN_ARG!"=="client" (\r
+```\r
+\r
+# build on windows\r
+in top directory:\r
+```\r
+run.bat build server -noTest\r
+```\r
+\r
+# run on windows\r
+in top directory:\r
+```\r
+run.bat server\r
+```\r
+\r
+\r
+## CTT info\r
+\r
+When CTT pops up:\r
+"reset to onboarding state" means one needs to: \r
+1. Stop your device\r
+2. Reset/replace security databases with a new/unowned one.\r
+    e.g. copy the ORIGINAL security file to the executable directory.\r
+3. Start your device.\r
+\r
+Note if the IUT crashes during testing one has to reset the security state to not onboarded.\r
+this is mentioned in the test case log of CTT when the CTT can't reset the device state properly.\r
+\r
+\r
+# CTT PICS information\r
+\r
+- IOTivity implements the next optional virtual security resources\r
+    currently there is no mechanism available to remove those from the implementatino.\r
+    hence they must be listed in the PICS:\r
+    - oic.r.crl, oic.r.csr, oic.r.roles \r
+- oic/res\r
+    This resource must be listed as none observable.\r
+    \r
+    \r
+\r
+\r
diff --git a/resource/examples/ocf_light/server_introspection.dat b/resource/examples/ocf_light/server_introspection.dat
new file mode 100644 (file)
index 0000000..f37e3b3
Binary files /dev/null and b/resource/examples/ocf_light/server_introspection.dat differ
diff --git a/resource/examples/ocf_light/server_security.dat b/resource/examples/ocf_light/server_security.dat
new file mode 100644 (file)
index 0000000..1b6beca
Binary files /dev/null and b/resource/examples/ocf_light/server_security.dat differ
diff --git a/resource/examples/ocf_light/server_security.dat-org b/resource/examples/ocf_light/server_security.dat-org
new file mode 100644 (file)
index 0000000..1b6beca
Binary files /dev/null and b/resource/examples/ocf_light/server_security.dat-org differ
diff --git a/resource/examples/ocf_light/svr_server-justworks.json b/resource/examples/ocf_light/svr_server-justworks.json
new file mode 100644 (file)
index 0000000..2912645
--- /dev/null
@@ -0,0 +1,62 @@
+{\r
+    "acl": {\r
+        "aclist2": [\r
+            {\r
+                "aceid": 1,\r
+                "subject": { "conntype": "anon-clear" },\r
+                "resources": [\r
+                    { "href": "/oic/res" },\r
+                    { "href": "/oic/d" },\r
+                    { "href": "/oic/p"}\r
+                ],\r
+                "permission": 2\r
+            },\r
+            {\r
+                "aceid": 2,\r
+                "subject": { "conntype": "auth-crypt" },\r
+                "resources": [\r
+                    { "href": "/oic/res" },\r
+                    { "href": "/oic/d" },\r
+                    { "href": "/oic/p"}\r
+                ],\r
+                "permission": 2\r
+            },\r
+            {\r
+                "aceid": 3,\r
+                "subject": { "conntype": "anon-clear" },\r
+                "resources": [\r
+                    { "href": "/oic/sec/doxm" }\r
+                ],\r
+                "permission": 14\r
+            },\r
+            {\r
+                "aceid": 4,\r
+                "subject": { "conntype": "auth-crypt" },\r
+                "resources": [\r
+                    { "href": "/oic/sec/doxm" },\r
+                    { "href": "/oic/sec/roles" }\r
+                ],\r
+                "permission": 14\r
+            }\r
+        ],\r
+        "rowneruuid": "00000000-0000-0000-0000-000000000000"\r
+    },\r
+    "pstat": {\r
+        "dos": { "s": 1, "p": false },\r
+        "isop": false,\r
+        "cm": 2,\r
+        "tm": 0,\r
+        "om": 4,\r
+        "sm": 4,\r
+        "rowneruuid": "00000000-0000-0000-0000-000000000000"\r
+    },\r
+    "doxm": {\r
+        "oxms": [0],\r
+        "oxmsel": 0,\r
+        "sct": 9,\r
+        "owned": false,\r
+        "deviceuuid": "12345678-1234-1234-1234-123456789012",\r
+        "devowneruuid": "00000000-0000-0000-0000-000000000000",\r
+        "rowneruuid": "00000000-0000-0000-0000-000000000000"\r
+    }\r
+}\r
diff --git a/resource/examples/ocf_light/svr_server.json b/resource/examples/ocf_light/svr_server.json
new file mode 100644 (file)
index 0000000..5d03542
--- /dev/null
@@ -0,0 +1,76 @@
+{\r
+    "acl": {\r
+        "aclist2": [\r
+            {\r
+                "aceid": 1,\r
+                "subject": { "conntype": "anon-clear" },\r
+                "resources": [\r
+                    { "href": "/oic/res" },\r
+                    { "href": "/oic/d" },\r
+                    { "href": "/oic/p" },\r
+                    { "href": "/oic/sec/doxm" }\r
+                ],\r
+                "permission": 2\r
+            },\r
+            {\r
+                "aceid": 2,\r
+                "subject": { "conntype": "auth-crypt" },\r
+                "resources": [\r
+                    { "href": "/oic/res" },\r
+                    { "href": "/oic/d" },\r
+                    { "href": "/oic/p" },\r
+                    { "href": "/oic/sec/doxm" }\r
+                ],\r
+                "permission": 2\r
+            },\r
+            {\r
+                "aceid": 5,\r
+                "subject": {"uuid": "32323232-3232-3232-3232-323232323232"},\r
+                "resources":[\r
+                    { "href":"/a/led"}\r
+                ],\r
+                "permission": 7\r
+            }\r
+        ],\r
+        "rowneruuid": "32323232-3232-3232-3232-323232323232",\r
+        "rt": ["oic.r.acl"],\r
+        "if": ["oic.if.baseline"]\r
+    },\r
+    "pstat": {\r
+        "dos": { "s": 3, "p": false },\r
+        "isop": true,\r
+        "cm": 0,\r
+        "tm": 0,\r
+        "om": 4,\r
+        "sm": 4,\r
+        "rowneruuid": "132323232-3232-3232-3232-323232323232",\r
+        "rt": ["oic.r.pstat"],\r
+        "if": ["oic.if.baseline"]\r
+    },\r
+    "doxm": {\r
+        "oxms": [0],\r
+        "oxmsel": 0,\r
+        "sct": 1,\r
+        "owned": true,\r
+        "deviceuuid": "12345678-1234-1234-1234-123456789012",\r
+        "devowneruuid": "32323232-3232-3232-3232-323232323232",\r
+        "rowneruuid": "32323232-3232-3232-3232-323232323232",\r
+        "rt": ["oic.r.doxm"],\r
+        "if": ["oic.if.baseline"]\r
+    },\r
+    "cred":{\r
+        "creds": [\r
+            {\r
+                "credid": 1,\r
+                "subjectuuid": "32323232-3232-3232-3232-323232323232",\r
+                "credtype": 1,\r
+                "privatedata":{\r
+                    "data":"AAAAAAAAAAAAAAAA",\r
+                    "encoding": "oic.sec.encoding.raw"\r
+                }\r
+            }],\r
+        "rowneruuid": "32323232-3232-3232-3232-323232323232",\r
+        "rt": ["oic.r.cred"],\r
+        "if": ["oic.if.baseline"]\r
+    }\r
+}
\ No newline at end of file
diff --git a/resource/examples/ocf_light/svr_server.json.cbor b/resource/examples/ocf_light/svr_server.json.cbor
new file mode 100644 (file)
index 0000000..1b6beca
Binary files /dev/null and b/resource/examples/ocf_light/svr_server.json.cbor differ