Fridge example which shows a nice set of the std::bind functionality as well as how...
authorErich Keane <erich.keane@intel.com>
Thu, 18 Sep 2014 22:56:30 +0000 (15:56 -0700)
committerErich Keane <erich.keane@intel.com>
Wed, 24 Sep 2014 17:48:27 +0000 (10:48 -0700)
Patch 2: Resolve Sudarshan's fixes
Patch 3: rebase & remove previous version of code
Change-Id: Ic7c5f3ae5da40cd8e6e82692e0f5e3b878f34489

examples/fridgeclient.cpp [new file with mode: 0644]
examples/fridgeserver.cpp [new file with mode: 0644]
examples/makefile

diff --git a/examples/fridgeclient.cpp b/examples/fridgeclient.cpp
new file mode 100644 (file)
index 0000000..81f360f
--- /dev/null
@@ -0,0 +1,149 @@
+//******************************************************************
+//
+// Copyright 2014 Intel Mobile Communications GmbH 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.
+//
+//-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
+
+/// This fridgeclient represents a client trying to discover the associated
+/// fridgeserver.  The device resource is the only one available for discovery
+/// on the server, so we have to take the fact that we know the device tag
+/// to then generate a Resource object
+
+#include <iostream>
+#include <stdexcept>
+#include <condition_variable>
+#include <mutex>
+#include "OCPlatform.h"
+#include "OCApi.h"
+
+using namespace OC;
+namespace PH = std::placeholders;
+
+class ClientFridge
+{
+    public:
+    ClientFridge(PlatformConfig &cfg) : m_platform(cfg)
+    {
+        std::cout << "Fridge Client has started " <<std::endl;
+        FindCallback f (std::bind(&ClientFridge::foundDevice, this, PH::_1));
+
+        OCStackResult result = m_platform.findResource(
+                "", "coap://224.0.1.187/oc/core?rt=intel.fridge", f);
+
+        if(OC_STACK_OK != result)
+        {
+            throw new std::runtime_error("Fridge Find Resource Failed");
+        }
+
+        std::cout << "Waiting to discover fridge... "<<std::endl;
+        {
+            // we want to block this thread until the client has finished
+            // its duties, so we block on the CV until we have completed
+            // what we are looking to do
+            std::unique_lock<std::mutex> lk(m_mutex);
+            m_cv.wait(lk);
+        }
+    }
+
+    private:
+    void foundDevice(std::shared_ptr<OCResource> resource)
+    {
+        if(resource && resource->uri() == "/device")
+        {
+            std::cout << "Discovered a device object"<<std::endl;
+            std::cout << "\tHost: "<<resource->host()<<std::endl;
+            std::cout << "\tURI:  "<<resource->uri() <<std::endl;
+        }
+
+        // we have now found a resource, so lets create a few resource objects
+        // for the other resources that we KNOW are associated with the intel.fridge
+        // server, and query them.
+        std::vector<std::string> lightTypes = {"intel.fridge.light"};
+        std::vector<std::string> ifaces = {DEFAULT_INTERFACE};
+        OCResource::Ptr light = m_platform.constructResourceObject(resource->host(),
+                                "/light", false, lightTypes, ifaces);
+
+        std::vector<std::string> doorTypes = {"intel.fridge.door"};
+
+        OCResource::Ptr leftdoor = m_platform.constructResourceObject(resource->host(),
+                                "/door/left", false, doorTypes, ifaces);
+        OCResource::Ptr rightdoor = m_platform.constructResourceObject(resource->host(),
+                                "/door/right", false, doorTypes, ifaces);
+
+        light->get(QueryParamsMap(), GetCallback(
+                std::bind(&ClientFridge::getResponse, this, "Fridge Light", PH::_1,
+                    PH::_2, light, 1)
+                ));
+        leftdoor->get(QueryParamsMap(), GetCallback(
+                std::bind(&ClientFridge::getResponse, this, "Left Door", PH::_1,
+                    PH::_2, leftdoor, 2)
+                ));
+        rightdoor->get(QueryParamsMap(), GetCallback(
+                std::bind(&ClientFridge::getResponse, this, "Right Door", PH::_1,
+                    PH::_2, rightdoor, 3)
+                ));
+    }
+
+    // Note that resourceName, resource, and getId are all bound via the std::bind mechanism.
+    // it is possible to attach ANY arbitrary data to do whatever you would like here.  It may,
+    // however be a better fit to wrap each call in an object so a fuller context (and additional
+    // requests) can be easily made inside of a simple context
+    void getResponse(const std::string& resourceName, const OCRepresentation rep, const int eCode,
+            OCResource::Ptr resource, int getId)
+    {
+        std::cout << "Got a response from get from the "<<resourceName<< std::endl;
+        std::cout << "Get ID is "<<getId<<" and resource URI is "<<resource->uri()<<std::endl;
+
+        std::cout << "The Attribute Data is: "<<std::endl;
+
+        switch(getId)
+        {
+            case 1:
+                bool isOn;
+                rep.getValue("on",isOn);
+                std::cout<<"The fridge light is "<< ((isOn)?"":"not ") <<"on"<<std::endl;
+            break;
+            case 2:
+            case 3:
+                bool isOpen;
+                std::string side;
+                rep.getValue("open", isOpen);
+                rep.getValue("side", side);
+                std::cout << "Door is "<<isOpen<<" and is on the "<<side<<std::endl;
+            break;
+        }
+    }
+
+    OCPlatform m_platform;
+    std::mutex m_mutex;
+    std::condition_variable m_cv;
+};
+
+int main()
+{
+    PlatformConfig cfg
+    {
+        ServiceType::InProc,
+        ModeType::Client,
+        "134.134.161.33",
+        56832,
+        QualityOfService::NonConfirmable
+    };
+
+    ClientFridge cf (cfg);
+    return 0;
+}
diff --git a/examples/fridgeserver.cpp b/examples/fridgeserver.cpp
new file mode 100644 (file)
index 0000000..b249174
--- /dev/null
@@ -0,0 +1,305 @@
+//******************************************************************
+//
+// Copyright 2014 Intel Mobile Communications GmbH 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.
+//
+//-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
+
+/// The purpose of this server is to simulate a refridgerator that contains a device resource for
+/// its description, a light resource for the internal light, and 2 door resources for the purpose
+/// of representing the doors attached to this fridge.  This is used by the fridgeclient to
+/// demonstrate using std::bind to attach to instances of a class as well as using
+/// constructResourceObject
+
+#include <chrono>
+#include <iostream>
+#include <thread>
+#include <stdexcept>
+
+#include "OCPlatform.h"
+#include "OCApi.h"
+
+using namespace OC;
+namespace PH = std::placeholders;
+
+class Resource
+{
+    protected:
+    OCResourceHandle m_resourceHandle;
+    OCRepresentation m_rep;
+    virtual void entityHandler(std::shared_ptr<OCResourceRequest> request,
+            std::shared_ptr<OCResourceResponse> response)=0;
+};
+
+class DeviceResource : public Resource
+{
+    public:
+    DeviceResource(OCPlatform& platform)
+    {
+        std::string resourceURI = "/device";
+        std::string resourceTypeName = "intel.fridge";
+        std::string resourceInterface = DEFAULT_INTERFACE;
+        RegisterCallback cb = std::bind(&DeviceResource::entityHandler, this,PH::_1, PH::_2);
+        uint8_t resourceProperty = OC_DISCOVERABLE;
+        OCStackResult result = platform.registerResource(m_resourceHandle,
+            resourceURI,
+            resourceTypeName,
+            resourceInterface,
+            cb,
+            resourceProperty);
+
+        if(OC_STACK_OK != result)
+        {
+            throw std::runtime_error(
+                std::string("Device Resource failed to start")+std::to_string(result));
+        }
+    }
+    private:
+    OCRepresentation get()
+    {
+        m_rep.setValue("device_name", "Intel Powered 2 door, 1 light refridgerator");
+        return m_rep;
+    }
+
+    std::string m_modelName;
+    protected:
+    virtual void entityHandler(std::shared_ptr<OCResourceRequest> request,
+            std::shared_ptr<OCResourceResponse> response)
+    {
+        if(request)
+        {
+            if(request->getRequestHandlerFlag() == RequestHandlerFlag::RequestFlag)
+            {
+                if(request->getRequestType() == "GET")
+                {
+                    if(response)
+                    {
+                        std::cout<<"DeviceResource Get Request"<<std::endl;
+                        response->setErrorCode(200);
+                        response->setResourceRepresentation(get(), "");
+                    }
+                }
+                else
+                {
+                    std::cout <<"DeviceResource unsupported request type "
+                    << request->getRequestType() << std::endl;
+                }
+            }
+            else
+            {
+                std::cout << "DeviceResource unsupported request flag" <<std::endl;
+            }
+        }
+    }
+};
+
+class LightResource : public Resource
+{
+    public:
+    LightResource(OCPlatform& platform)
+    {
+        std::string resourceURI = "/light";
+        std::string resourceTypeName = "intel.fridge.light";
+        std::string resourceInterface = DEFAULT_INTERFACE;
+        RegisterCallback cb = std::bind(&LightResource::entityHandler, this,PH::_1, PH::_2);
+        uint8_t resourceProperty = 0;
+        OCStackResult result = platform.registerResource(m_resourceHandle,
+            resourceURI,
+            resourceTypeName,
+            resourceInterface,
+            cb,
+            resourceProperty);
+
+        if(OC_STACK_OK != result)
+        {
+            throw std::runtime_error(
+                std::string("Light Resource failed to start")+std::to_string(result));
+        }
+    }
+    private:
+    OCRepresentation get()
+    {
+        m_rep.setValue("on", m_isOn);
+        return m_rep;
+    }
+
+    void put(OCRepresentation rep)
+    {
+        rep.getValue("on", m_isOn);
+    }
+
+    bool m_isOn;
+    protected:
+    virtual void entityHandler(std::shared_ptr<OCResourceRequest> request,
+            std::shared_ptr<OCResourceResponse> response)
+    {
+        if(request)
+        {
+            if(request->getRequestHandlerFlag() == RequestHandlerFlag::RequestFlag)
+            {
+                if(request->getRequestType() == "GET")
+                {
+                    if(response)
+                    {
+                        std::cout<<"Light Get Request"<<std::endl;
+                        response->setErrorCode(200);
+                        response->setResourceRepresentation(get(), "");
+                    }
+                }
+                else if(request->getRequestType() == "PUT")
+                {
+                    if(response)
+                    {
+                        std::cout <<"Light Put Request"<<std::endl;
+                        put(request->getResourceRepresentation());
+
+                        response->setErrorCode(200);
+                        response->setResourceRepresentation(get(),"");
+                    }
+                }
+                else
+                {
+                    std::cout <<"Light unsupported request type "
+                    << request->getRequestType() << std::endl;
+                }
+            }
+            else
+            {
+                std::cout << "Light unsupported request flag" <<std::endl;
+            }
+        }
+    }
+};
+
+class DoorResource : public Resource
+{
+    public:
+    DoorResource(OCPlatform& platform, const std::string& side):m_side(side)
+    {
+
+        std::string resourceURI = "/door/"+ side;
+        std::string resourceTypeName = "intel.fridge.door";
+        std::string resourceInterface = DEFAULT_INTERFACE;
+        RegisterCallback cb = std::bind(&DoorResource::entityHandler, this,PH::_1, PH::_2);
+        uint8_t resourceProperty = 0;
+        OCStackResult result = platform.registerResource(m_resourceHandle,
+            resourceURI,
+            resourceTypeName,
+            resourceInterface,
+            cb,
+            resourceProperty);
+
+        if(OC_STACK_OK != result)
+        {
+            throw std::runtime_error(
+                std::string("Door Resource failed to start")+std::to_string(result));
+        }
+    }
+
+    private:
+    OCRepresentation get()
+    {
+        m_rep.setValue("open", m_isOpen);
+        m_rep.setValue("side", m_side);
+        return m_rep;
+    }
+
+    void put(OCRepresentation rep)
+    {
+        rep.getValue("open", m_isOpen);
+        // Note, we won't let the user change the door side!
+    }
+    bool m_isOpen;
+    std::string m_side;
+    protected:
+    virtual void entityHandler(std::shared_ptr<OCResourceRequest> request,
+            std::shared_ptr<OCResourceResponse> response)
+    {
+        if(request)
+        {
+            if(request->getRequestHandlerFlag() == RequestHandlerFlag::RequestFlag)
+            {
+                if(request->getRequestType() == "GET")
+                {
+                    if(response)
+                    {
+                        // note that we know the side because std::bind gives us the
+                        // appropriate object
+                        std::cout<<m_side << " Door Get Request"<<std::endl;
+                        response->setErrorCode(200);
+                        response->setResourceRepresentation(get(), "");
+                    }
+                }
+                else if(request->getRequestType() == "PUT")
+                {
+                    if(response)
+                    {
+                        std::cout <<m_side <<" Door Put Request"<<std::endl;
+                        put(request->getResourceRepresentation());
+                        response->setErrorCode(200);
+                        response->setResourceRepresentation(get(),"");
+                    }
+                }
+                else
+                {
+                    std::cout <<m_side<<" Door unsupported request type "
+                    << request->getRequestType() << std::endl;
+                }
+            }
+            else
+            {
+                std::cout << "Door unsupported request flag" <<std::endl;
+            }
+        }
+    }
+};
+
+class Refridgerator
+{
+    public:
+    Refridgerator(PlatformConfig &cfg)
+        : m_platform(cfg),
+        m_light(m_platform),
+        m_device(m_platform),
+        m_leftdoor(m_platform, "left"),
+        m_rightdoor(m_platform, "right")
+    {
+    }
+    private:
+    OCPlatform m_platform;
+    LightResource m_light;
+    DeviceResource m_device;
+    DoorResource m_leftdoor;
+    DoorResource m_rightdoor;
+};
+
+int main ()
+{
+    PlatformConfig cfg
+    {
+        ServiceType::InProc,
+        ModeType::Server,
+        "134.134.161.33",
+        56832,
+        QualityOfService::NonConfirmable
+    };
+
+    Refridgerator rf(cfg);
+
+    // we will keep the server alive for at most 30 minutes
+    std::this_thread::sleep_for(std::chrono::minutes(30));
+    return 0;
+}
index 66aac8d18c6b776e7849504b7dc49875c4b9dd51..ff86c72ddc4500e4ad61c3f76d8fa79278df21ab 100644 (file)
@@ -37,7 +37,7 @@ CXX_INC         += -I../csdk/logger/include
 CXX_INC          += -I../csdk/libcoap
 
 # Force metatargets to build:
-.PHONY: prep_dirs simpleserver simpleclient simpleclientserver roomserver roomclient presenceserver presenceclient garageserver garageclient ocicuc
+.PHONY: prep_dirs simpleserver simpleclient simpleclientserver roomserver roomclient presenceserver presenceclient garageserver garageclient fridgeserver fridgeclient ocicuc
 
 all: .PHONY
 
@@ -50,6 +50,12 @@ simpleserver: simpleserver.cpp
 simpleclient: simpleclient.cpp
        $(CXX) $(CXX_FLAGS.$(BUILD)) -o $(OUT_DIR)/$@ simpleclient.cpp $(CXX_INC) ../$(BUILD)/obj/liboc.a ../csdk/$(BUILD)/liboctbstack.a
 
+fridgeserver: fridgeserver.cpp
+       $(CXX) $(CXX_FLAGS.$(BUILD)) -o $(OUT_DIR)/$@ fridgeserver.cpp $(CXX_INC) ../$(BUILD)/obj/liboc.a ../csdk/$(BUILD)/liboctbstack.a
+
+fridgeclient: fridgeclient.cpp
+       $(CXX) $(CXX_FLAGS.$(BUILD)) -o $(OUT_DIR)/$@ fridgeclient.cpp $(CXX_INC) ../$(BUILD)/obj/liboc.a ../csdk/$(BUILD)/liboctbstack.a
+
 presenceserver: presenceserver.cpp
        $(CXX) $(CXX_FLAGS.$(BUILD)) -o $(OUT_DIR)/$@ presenceserver.cpp $(CXX_INC) ../$(BUILD)/obj/liboc.a ../csdk/$(BUILD)/liboctbstack.a