Added client/server multiple-resource program; fixed reflection exception namespaces.
authorJesse Williamson <jesse.f.williamson@intel.com>
Mon, 18 Aug 2014 17:29:23 +0000 (10:29 -0700)
committerJesse Williamson <jesse.f.williamson@intel.com>
Tue, 19 Aug 2014 17:30:40 +0000 (10:30 -0700)
Change-Id: Ibdcf3b722c31f5f5040e8b594431b943274b743d

OCLib/OCProperties.cpp
examples/makefile
examples/ocicuc/Makefile [new file with mode: 0644]
examples/ocicuc/Makefile.debug [new file with mode: 0644]
examples/ocicuc/client.cpp [new file with mode: 0644]
examples/ocicuc/driver.cpp [new file with mode: 0644]
examples/ocicuc/exec.hpp [new file with mode: 0644]
examples/ocicuc/server.cpp [new file with mode: 0644]
examples/old_tests/MyMultiResourceHandler.cpp
examples/old_tests/MyResourceHandler.cpp
examples/reflect/test_OCReflect.cpp

index 6681352..b172def 100644 (file)
@@ -213,7 +213,7 @@ pd_iter_tuple consume_typecheck(const property_type expected_pt, const OC::OCRef
   {
     std::ostringstream os;
     os << "type error: " << "expected " << expected_pt << ", found " << found_pt;
-    throw OC::OCReflect::reflection_exception(os.str());
+    throw OC::reflection_exception(os.str());
   }
 
  return std::forward_as_tuple(++begin, in.end());
index 6f947c7..33fbbc1 100644 (file)
@@ -36,7 +36,7 @@ LIB_SRC1 += ../OCLib/OCServer.cpp
 
 CXX_LIBS := -Lboost_regex
 
-.PHONY: prep_dirs ocreflect test_OCReflect test_OCClient test_properties
+.PHONY: prep_dirs ocreflect test_OCReflect test_OCClient test_properties ocicuc
 
 all: .PHONY
 
@@ -55,6 +55,9 @@ test_OCReflect:
 test_OCClient:
        $(CXX) $(CXX_FLAGS.$(BUILD)) -o $(OUT_DIR)/$@ reflect/test_OCClient.cpp $(LIB_SRC0) $(CXX_INC) $(CXX_LIBS)
 
+ocicuc:
+       cd ocicuc && $(MAKE)
+
 clean: clean_legacy
        -rm -rf release/*
        -rm -rf release/obj/*.o
@@ -64,6 +67,7 @@ clean:        clean_legacy
        -rm -rf debug/obj/*.o
        -rm -rf debug/obj/*.a
        -rmdir debug
+       cd ocicuc && $(MAKE) clean
 
 clean_legacy:
        -rm -f -v test_properties test_OCReflect test_OCClient
diff --git a/examples/ocicuc/Makefile b/examples/ocicuc/Makefile
new file mode 100644 (file)
index 0000000..b8bcf2d
--- /dev/null
@@ -0,0 +1,54 @@
+
+# Please note that many of these settings are unused at the moment on account of the rush to get this out the door-- look carefully
+# at the actual commands to see which are relevant:
+
+OC_CSDK=../../../ccf-resource/csdk
+OC_STACK=$(OC_CSDK)/stack
+OC_OCCOAP=$(OC_CSDK)/occoap
+OC_SOCKET=$(OC_CSDK)/ocsocket
+OC_RANDOM=$(OC_CSDK)/ocrandom
+OC_LOGGER=$(OC_CSDK)/logger
+OC_LIB=$(OC_CSDK)/liboctbstack.a
+
+OCLIB=../..
+OCLIB_LIB=../../release/obj/OCLib.a #$(OCLIB)/release/obj/OCLib.a
+
+BOOST_BASE=/usr/local/boost
+BOOST_INC=$(BOOST_BASE)/include
+BOOST_LIB=$(BOOST_BASE)/lib
+
+CXX_CC=g++ -std=c++0x -ggdb
+#CXX_CC=clang -std=c++0x -lstdc++
+
+CXX_FLAGS=-Wall 
+
+# There's probably nicer Makefile magic for this, but hopefully it will suffice:
+CXX_INC=-I$(OCLIB)/include -I$(OC_STACK)/include -I$(OC_SOCKET)/include -I$(OC_RANDOM)/include -I$(OC_LOGGER)/include -I$(OC_OCCOAP)/include -I$(BOOST_INC)
+
+CXX_LIBS=-L$(BOOST_LIB) $(OC_LIB) $(OCLIB_LIB) -lpthread -lboost_program_options
+
+CXX=$(CXX_CC) $(CXX_FLAGS) $(CXX_INC) $(CXX_LIBS)
+
+.PHONY: init driver client server
+
+all: init driver client server
+       @echo Remember to \"export LD_LIBRARY_PATH=$(BOOST_LIB)\:\$$LD_LIBRARY_PATH\"
+       
+init:
+       rm -f *.o ./client ./server
+
+driver:
+       $(CXX_CC) -Wall -pthread  -c driver.cpp -I../../include/ -I../../csdk/stack/include -I../../csdk/ocsocket/include -I../../csdk/ocrandom/include -I../../csdk/logger/include -I/usr/local/include/boost/ 
+
+client:
+       $(CXX_CC) -pthread  -c client.cpp -I../../include/ -I../../csdk/stack/include -I../../csdk/ocsocket/include -I../../csdk/ocrandom/include -I../../csdk/logger/include -I/usr/local/include/boost/ -I/usr/local/include $(CXX_INC) $(CXX_FLAGS)
+
+       $(CXX_CC) -std=c++0x -Wall -L/usr/local/boost/lib/ -I/usr/local/boost/include -pthread  -o client driver.o client.o ../../release/obj/OCLib.a ../../csdk/release/liboctbstack.a -lboost_program_options $(CXX_INC) $(CXX_FLAGS) 
+
+server:
+       $(CXX_CC) -pthread  -c server.cpp -I../../include/ -I../../csdk/stack/include -I../../csdk/ocsocket/include -I../../csdk/ocrandom/include -I../../csdk/logger/include -I/usr/local/include/boost/ -I/usr/local/include $(CXX_INC) 
+
+       $(CXX_CC) -std=c++0x -Wall -L/usr/local/boost/lib/ -I/usr/local/boost/include -pthread  -o server driver.o server.o ../../release/obj/OCLib.a ../../csdk/release/liboctbstack.a -lboost_program_options $(CXX_INC) 
+
+clean:
+       rm -f server.o client.o driver.o server client
diff --git a/examples/ocicuc/Makefile.debug b/examples/ocicuc/Makefile.debug
new file mode 100644 (file)
index 0000000..8567182
--- /dev/null
@@ -0,0 +1,50 @@
+
+OC_CSDK=../../../ccf-resource/csdk
+OC_STACK=$(OC_CSDK)/stack
+OC_OCCOAP=$(OC_CSDK)/occoap
+OC_SOCKET=$(OC_CSDK)/ocsocket
+OC_RANDOM=$(OC_CSDK)/ocrandom
+OC_LOGGER=$(OC_CSDK)/logger
+OC_LIB=$(OC_CSDK)/liboctbstack.a
+
+OCLIB=../..
+OCLIB_LIB=../../debug/obj/OCLib.a #$(OCLIB)/debug/obj/OCLib.a
+
+BOOST_BASE=/usr/local/boost
+BOOST_INC=$(BOOST_BASE)/include
+BOOST_LIB=$(BOOST_BASE)/lib
+
+
+CXX_CC=g++ -std=c++0x
+#CXX_CC=clang -std=c++0x -lstdc++
+
+CXX_FLAGS=-Wall -O0 -ggdb
+
+# There's probably nicer Makefile magic for this, but hopefully it will suffice:
+CXX_INC=-I$(OCLIB)/include -I$(OC_STACK)/include -I$(OC_SOCKET)/include -I$(OC_RANDOM)/include -I$(OC_LOGGER)/include -I$(OC_OCCOAP)/include -I$(BOOST_INC)
+
+CXX_LIBS=-L$(BOOST_LIB) $(OC_LIB) $(OCLIB_LIB) -lpthread -lboost_program_options
+
+CXX=$(CXX_CC) $(CXX_FLAGS) $(CXX_INC) $(CXX_LIBS)
+
+.PHONY: init driver client server
+
+all: init driver client server
+       @echo Remember to \"export LD_LIBRARY_PATH=$(BOOST_LIB)\:\$$LD_LIBRARY_PATH\"
+       
+init:
+       rm -f \*\.o ./client ./server
+
+driver:
+       $(CXX_CC) -Wall -pthread  -c driver.cpp -I../../include/ -I../../csdk/stack/include -I../../csdk/ocsocket/include -I../../csdk/ocrandom/include -I../../csdk/logger/include -I/usr/local/include/boost/ -O0 -g
+
+client:
+       $(CXX_CC) -pthread  -c client.cpp -I../../include/ -I../../csdk/stack/include -I../../csdk/ocsocket/include -I../../csdk/ocrandom/include -I../../csdk/logger/include -I/usr/local/include/boost/ -I/usr/local/include $(CXX_INC) $(CXX_FLAGS)
+
+       $(CXX_CC) -std=c++0x -Wall -L/usr/local/boost/lib/ -I/usr/local/boost/include -pthread  -o client driver.o client.o ../../debug/obj/OCLib.a ../../csdk/liboctbstack.a -lboost_program_options $(CXX_INC) $(CXX_FLAGS) -O0 -g
+
+server:
+       $(CXX_CC) -pthread  -c server.cpp -I../../include/ -I../../csdk/stack/include -I../../csdk/ocsocket/include -I../../csdk/ocrandom/include -I../../csdk/logger/include -I/usr/local/include/boost/ -I/usr/local/include $(CXX_INC) -O0 -g
+
+       $(CXX_CC) -std=c++0x -Wall -L/usr/local/boost/lib/ -I/usr/local/boost/include -pthread  -o server driver.o server.o ../../debug/obj/OCLib.a ../../csdk/liboctbstack.a -lboost_program_options $(CXX_INC) -O0 -g
+
diff --git a/examples/ocicuc/client.cpp b/examples/ocicuc/client.cpp
new file mode 100644 (file)
index 0000000..af01153
--- /dev/null
@@ -0,0 +1,414 @@
+//******************************************************************
+//
+// Copyright 2014 Intel Corporation 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.
+//
+//-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
+
+#include <map>
+#include <string>
+#include <memory>
+#include <utility>
+#include <ostream>
+#include <sstream>
+#include <iostream>
+
+#include <boost/program_options.hpp>
+
+#include "OCApi.h"
+#include "OCResource.h"
+#include "OCPlatform.h"
+
+#include "exec.hpp"
+
+namespace Intel { namespace OCDemo {
+
+auto make_description()
+    -> boost::program_options::options_description 
+{
+ using std::string;
+ using std::vector;
+
+ namespace po = boost::program_options;
+
+ po::options_description desc("Client options");
+
+ desc.add_options()
+    ("nres",        po::value<unsigned long>()->default_value(1),           "number of resources to use for testing")
+    ("host_ip",     po::value<string>()->default_value("134.134.161.33"),   "IP of host")
+    ("host_port",   po::value<uint16_t>()->default_value(5683),             "port of host")
+    ("interface",   po::value<string>()->default_value("eth0"),             "network interface name")
+    ("uri",         po::value<vector<string>>(),                            "remote resource URI")
+    ;
+
+ return desc;
+}
+
+// Prettyprinter for AttributeMaps:
+std::ostream& operator<<(std::ostream& os, const OC::AttributeMap& attrs)
+{
+ for(const auto& attr : attrs)
+  {
+        os << "Attribute \"" << attr.first << "\": ";
+
+        for(const auto& val : attr.second)
+         os << val << "; ";
+  }
+
+ return os;
+}
+
+int observe_count()
+{
+ static unsigned long long oc = 0;
+ return ++oc;
+}
+
+/* Helpers for measuring request times: */
+typedef std::pair< 
+                    std::chrono::time_point<std::chrono::high_resolution_clock>, 
+                    std::chrono::time_point<std::chrono::high_resolution_clock> 
+                 > clock_interval;
+
+struct call_times
+{
+ static map<string, clock_interval> timings;
+
+ void reset(const std::string& entry) { timings[entry] = make_pair(chrono::high_resolution_clock::now(), chrono::high_resolution_clock::time_point()); }
+
+ void mark(const std::string& name)
+ {
+    auto e = timings.find(name);
+
+    if(timings.end() == e)
+     {
+        reset(name);
+        return;
+     }
+
+    auto& tp = (*e).second;
+
+    if(tp.first > tp.second)
+     timings[name].second = chrono::high_resolution_clock::now();
+  }
+
+  void report()
+  {
+    cout << "Time marks:\n";
+
+    for_each(begin(timings), end(timings), [](const std::pair<std::string, clock_interval>& tm) -> void {
+        using namespace std::chrono;
+
+    const std::string& name     { tm.first };
+
+    const std::chrono::time_point<std::chrono::high_resolution_clock>& request_time    { tm.second.first };
+    const std::chrono::time_point<std::chrono::high_resolution_clock>& response_time   { tm.second.second };
+
+    cout << '\t' << name << ": ";
+
+    if(request_time > response_time)
+     {
+        cout << "<waiting>\n";
+        return;
+     }
+
+    auto elapsed_ms = std::chrono::duration_cast<std::chrono::milliseconds>(response_time - request_time).count();
+    cout << elapsed_ms << "ms (";
+
+    auto elapsed_us = std::chrono::duration_cast<std::chrono::microseconds>(response_time - request_time).count();
+    cout << elapsed_us << "us)\n";
+   });
+  }
+
+  void report_and_reset(const string& name)
+  {
+       mark(name), report(), reset(name);
+  }
+
+} call_timer;
+
+map<string, clock_interval> call_times::timings;
+
+class resource_handler;
+
+class resource_handle
+{
+ friend class resource_handler;
+ private:
+ const std::string                     URI;
+ std::shared_ptr<OC::OCResource>       resource;
+
+ public:
+ resource_handle(const std::string& URI_, std::shared_ptr<OC::OCResource> resource_)
+  : URI(URI_),
+    resource(resource_)
+ {}
+
+ resource_handle(const std::string& URI_)
+  : resource_handle(URI_, nullptr)
+ {}
+
+ // Callbacks (note that the signature after binding will match exactly:
+ private:
+ void onFoundResource(std::shared_ptr<OC::OCResource> in_resource);
+ void onResourceGet(OC::AttributeMap attr_map, const int error_code);
+ void onResourcePut(OC::AttributeMap attribute_map, const int error_code);
+ void onObserve(const OC::AttributeMap attribute_map, const int error_code, const int& sequence_number);
+};
+
+class resource_handler
+{
+ OC::OCPlatform& platform;
+
+ static std::vector<std::shared_ptr<resource_handle>> resources;    // URI -> Maybe resource
+
+ public:
+ resource_handler(OC::OCPlatform& platform_, const std::vector<std::string>& resource_URIs_);
+ resource_handler(OC::OCPlatform& platform_);
+
+ public:
+ bool has(const std::string& URI)
+ {
+    for(const auto& r : resources)
+     {
+      if(URI == r->URI)
+       return true;
+     }
+
+    return false;
+ }
+
+ void add(const std::string& URI)
+ {
+    if(!has(URI))
+     resources.emplace_back(std::make_shared<resource_handle>(URI));
+ }
+
+ void find_resources()
+ {
+        for(const auto& resource : resources)
+         {
+                std::cout << "* Finding resources \"" << resource->URI << "\".\n";
+
+                call_timer.mark("find_resources");
+
+                platform.findResource("", resource->URI, 
+                                      std::bind(&resource_handle::onFoundResource, resource, std::placeholders::_1));
+         } 
+ }
+};
+
+std::vector<std::shared_ptr<resource_handle>> resource_handler::resources;
+
+resource_handler::resource_handler(OC::OCPlatform& platform_, const std::vector<std::string>& resource_URIs)
+ : platform(platform_)
+{
+ for(const auto& URI : resource_URIs)
+  add(URI);
+}
+
+resource_handler::resource_handler(OC::OCPlatform& platform_)
+  : resource_handler::resource_handler(platform_, {})
+{}
+
+int exec(const boost::program_options::variables_map& vm)
+{
+ using namespace std;
+
+ OC::OCPlatform platform({ 
+                          OC::ServiceType::InProc,              // in-process server
+                          OC::ModeType::Client,                 // client mode
+                          vm["host_ip"].as<string>(),           // host
+                          vm["host_port"].as<uint16_t>()        // port
+                        });
+
+ vector<string> resource_URIs;
+
+ if(0 == vm.count("uri"))
+  {
+    std::cout << "No URI specified, looking for everything in \"core\".\n";
+
+    // Find all resources:
+    resource_URIs.push_back("coap://224.0.1.187/oc/core");
+
+    /* Example of finding specific resources: 
+    const auto& nprops = vm["nres"].as<unsigned long>();
+
+    for(unsigned long instance_number = 1;
+        instance_number <= nprops;
+        instance_number++)
+     {
+        ostringstream uri;
+
+
+        uri << "coap://" << vm["host_ip"].as<string>() << "/oc/core?rt=core.light" << '_' << instance_number;
+        resource_URIs.push_back(uri.str()); // ie. "coap://224.0.1.187/oc/core?rt=core.light_1");
+     }
+    */
+  }
+ else
+  {
+    const vector<string>& input_URIs = vm["uri"].as< vector<string> >();
+    copy(begin(input_URIs), end(input_URIs), back_inserter(resource_URIs));
+  }
+
+ std::cout << "Requesting " << resource_URIs.size() << " URIs:\n";
+
+ for(const auto& resource_URI : resource_URIs)
+  cout << resource_URI << '\n';
+
+ resource_handler resources(platform, resource_URIs);
+
+ // Register callbacks and wait for resources:
+ resources.find_resources();
+
+ // Allow the client to receive events from the server:
+ for(;;)
+  ;
+
+ return 0;
+}
+
+void resource_handle::onFoundResource(std::shared_ptr<OC::OCResource> in_resource)
+{
+ using std::cout;
+
+ cout << "* onFoundResource():\n";
+
+ try
+  {
+       if(nullptr == in_resource)
+        throw OC::OCException("invalid resource passed to client callback");
+
+       call_timer.report_and_reset("find_resources");
+
+       // Now, fixup our own representation:
+       resource = in_resource;
+
+       /* Note: You can combine the host and URI to get a unique identifier, for
+       example to filter out events you aren't interested in. Here, we just report the
+       data: */
+       cout << "resource URI: " << resource->uri() << "; "
+            << "host address: " << resource->host() << '\n';
+
+       call_timer.mark("get_resource");
+
+       resource->get(std::bind(&resource_handle::onResourceGet, this, 
+                               std::placeholders::_1, std::placeholders::_2));
+  }
+ catch(OC::OCException& e)
+  {
+        std::cerr << "onFoundResource(): exception " << e.reason() << ": " << e.what() << '\n';
+  }
+ catch(std::exception& e)
+  {
+        std::cerr << "onFoundResource(): exception: " << e.what() << '\n';
+  }
+}
+
+void resource_handle::onResourceGet(const OC::AttributeMap attr_map, const int error_code)
+{
+ using std::cout;
+
+ cout << "onResourceGet():\n";
+
+ call_timer.report_and_reset("get_resource");
+
+ if(error_code)
+  {
+        std::cerr << "onResourceGet(): error: " << error_code << '\n';
+        return;
+  }
+
+ if(nullptr == resource)
+  {
+        std::cerr << "onResourceGet(): empty resource pointer.\n";
+        return;
+  }
+
+ std::cout << attr_map << '\n';
+
+ // Now, make a change to the light representation (replacing, rather than parsing): 
+ OC::AttributeMap attrs {
+                         { "state", { "true" } },
+                         { "power", { "10" } }
+                        };
+
+ call_timer.mark("put_resource");
+
+ resource->put(attrs, OC::QueryParamsMap(), 
+               std::bind(&resource_handle::onResourcePut, this, std::placeholders::_1, std::placeholders::_2));
+}
+
+void resource_handle::onResourcePut(const OC::AttributeMap attribute_map, const int error_code)
+{
+ std::cout << "onResourcePut():\n";
+
+ call_timer.report_and_reset("put_resource");
+
+ if(0 != error_code)
+  {
+        std::ostringstream os;
+
+        os << "onResourcePut(): error code " << error_code << " from server response.";
+
+        throw OC::OCException(os.str());
+  }
+
+ std::cout << attribute_map << '\n';
+
+ call_timer.mark("observe_resource");
+
+ // Start an observer:
+ resource->observe(OC::ObserveType::Observe,
+                    std::bind(&resource_handle::onObserve, this, std::placeholders::_1, std::placeholders::_2, std::placeholders::_3));
+}
+
+void resource_handle::onObserve(const OC::AttributeMap attribute_map, const int error_code, const int& sequence_number)
+{
+ if(0 != error_code)
+  {
+    std::ostringstream os;
+    os << "onObserve(): error " << error_code << " from callback.\n";
+    throw OC::OCException(os.str());
+  }
+
+ std::cout << "onObserve(): sequence number: " << sequence_number << ":\n";
+
+ call_timer.report_and_reset("observe_resource");
+
+ std::cout << attribute_map << '\n';
+
+ const auto oc = observe_count();
+
+ std::cout << "onObserve(): observation count is: " << oc << '\n';
+
+ // We don't want to be observed forever for purposes of this demo:
+ if(10 <= oc)
+  {
+    std::cout << "onObserve(): cancelling observation.\n";
+
+    const auto result = resource->cancelObserve();
+
+    std::cout << "onObserve(): result of cancellation: " << result << ".\n";
+    
+    this_thread::sleep_for(chrono::seconds(10));
+  }
+}
+
+}} // namespace Intel::OCDemo
+
diff --git a/examples/ocicuc/driver.cpp b/examples/ocicuc/driver.cpp
new file mode 100644 (file)
index 0000000..218f9d0
--- /dev/null
@@ -0,0 +1,60 @@
+
+#include <iostream>
+
+#include <ifaddrs.h>
+#include <sys/types.h>
+#include <sys/socket.h>
+
+#include <boost/program_options.hpp>
+
+#include "exec.hpp"
+
+namespace Intel { namespace OCDemo {
+
+auto parse_options(boost::program_options::options_description& desc, int argc, char *argv[]) 
+    -> boost::program_options::variables_map 
+{
+ namespace po = boost::program_options;
+
+ po::positional_options_description popts;
+ popts.add("uri", -1);
+
+ po::variables_map vm;
+
+ po::store(po::command_line_parser(argc,argv).options(desc).positional(popts).run(), 
+           vm);
+
+ // JFW: po::store(po::parse_command_line(argc, argv, desc), vm);
+ po::notify(vm);
+
+ return vm;
+}
+
+}} // namespace Intel::OCDemo
+
+int main(int argc, char *argv[])
+try
+{
+ using namespace std;
+ auto desc = Intel::OCDemo::make_description();
+ auto vm   = Intel::OCDemo::parse_options(desc, argc, argv);
+
+ if(1 == argc || vm.count("help"))
+  {
+    std::cerr << desc << '\n';
+    return 1;
+  }
+
+ return Intel::OCDemo::exec(vm);
+}
+catch(std::exception& e)
+{
+ std::cerr << "Unhandled exception: " << e.what() << '\n';
+ return 1;
+}
+catch(...)
+{
+ std::cerr << "Unhandled exception.\n";
+ return 1;
+}
diff --git a/examples/ocicuc/exec.hpp b/examples/ocicuc/exec.hpp
new file mode 100644 (file)
index 0000000..5c9cc7f
--- /dev/null
@@ -0,0 +1,38 @@
+//******************************************************************
+//
+// Copyright 2014 Intel Corporation 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.
+//
+//-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
+
+#ifndef __EXEC_HPP
+ #define __EXEC_HPP 1
+
+#include <boost/program_options.hpp>
+
+namespace Intel { namespace OCDemo {
+
+int exec(const boost::program_options::variables_map& vm);
+
+auto make_description()
+    -> boost::program_options::options_description;
+
+auto parse_options(boost::program_options::options_description& desc, int argc, char *argv[]) 
+    -> boost::program_options::variables_map;
+
+}} // namespace Intel::OCDemo
+
+#endif
diff --git a/examples/ocicuc/server.cpp b/examples/ocicuc/server.cpp
new file mode 100644 (file)
index 0000000..b2ff83c
--- /dev/null
@@ -0,0 +1,379 @@
+//******************************************************************
+//
+// Copyright 2014 Intel Corporation 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.
+//
+//-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
+
+#include <map>
+#include <atomic>
+#include <thread>
+#include <string>
+#include <ostream>
+#include <sstream>
+#include <iostream>
+#include <functional>
+
+#include <boost/program_options.hpp>
+
+#include "OCApi.h"
+#include "OCResource.h"
+#include "OCPlatform.h"
+
+#include "exec.hpp"
+
+namespace Intel { namespace OCDemo {
+
+auto make_description()
+    -> boost::program_options::options_description 
+{
+ using std::string;
+
+ namespace po = boost::program_options;
+
+ po::options_description desc("Server options");
+
+ desc.add_options()
+    ("nres",        po::value<unsigned long>()->default_value(1),         "number of resources to use for testing")
+    ("host_ip",     po::value<string>()->default_value("134.134.161.33"), "IP of host")
+    ("host_port",   po::value<uint16_t>()->default_value(56832),          "port of host")
+    ("interface",   po::value<string>()->default_value("eth0"),           "network interface name") 
+    ("uri",     po::value<vector<string>>(),                              "resource URI")
+    ;
+
+ return desc;
+}
+
+}} // namespace Intel::OCDemo
+
+namespace Intel { namespace OCDemo {
+
+using namespace OC;
+using namespace std;
+
+/// This class represents a single resource named 'lightResource'. This resource has
+/// two simple properties named 'state' and 'power'
+class LightResource
+{
+ public:
+    bool m_state;       // off or on?
+    int m_power;        // power level
+
+    private:
+    atomic<bool> m_observation; // are we under observation?
+
+    private:
+    static atomic<bool> shutdown_flag;
+    static thread observe_thread;
+
+    private:
+    OCResourceHandle m_resourceHandle;
+
+    public:
+    LightResource()
+     : m_state(false), 
+       m_power(0),
+       m_observation(false)
+    {}
+
+    ~LightResource()
+    {
+        shutdown_flag = true;
+
+        if(observe_thread.joinable())
+         observe_thread.join();
+    }
+
+    private:
+    std::string make_URI(const unsigned int resource_number) const
+    {
+        return std::string("/a/light") + "_" + std::to_string(resource_number); 
+    }
+
+    public:
+    // This function internally calls registerResource API.
+    void createResource(OC::OCPlatform& platform, const unsigned int resource_number);
+
+    OCResourceHandle getHandle() const { return m_resourceHandle; }
+
+    void setRepresentation(AttributeMap& attributeMap);
+    void getRepresentation(AttributeMap& attributeMap) const;
+
+    void addType(const OC::OCPlatform& platform, const std::string& type) const;
+    void addInterface(const OC::OCPlatform& platform, const std::string& interface) const;
+
+    private:
+    void entityHandler(std::shared_ptr<OCResourceRequest> request, std::shared_ptr<OCResourceResponse> response);
+
+    private:
+    void observe_function();
+
+    // Request handlers:
+    private:
+    void dispatch_request(const std::string& request_type, std::shared_ptr<OCResourceRequest> request, std::shared_ptr<OCResourceResponse> response);
+     void handle_get_request(std::shared_ptr<OCResourceRequest> request, std::shared_ptr<OCResourceResponse> response);
+     void handle_put_request(std::shared_ptr<OCResourceRequest> request, std::shared_ptr<OCResourceResponse> response);
+     void handle_post_request(std::shared_ptr<OCResourceRequest> request, std::shared_ptr<OCResourceResponse> response);
+     void handle_delete_request(std::shared_ptr<OCResourceRequest> request, std::shared_ptr<OCResourceResponse> response);
+     void handle_observe_event(std::shared_ptr<OCResourceRequest> request, std::shared_ptr<OCResourceResponse> response);
+};
+
+atomic<bool> LightResource::shutdown_flag(false);
+thread LightResource::observe_thread;
+
+void LightResource::setRepresentation(AttributeMap& attributeMap)
+{
+ cout << "\t\t\t" << "Received representation: " << endl;
+ cout << "\t\t\t\t" << "power: " << attributeMap["power"][0] << endl;
+ cout << "\t\t\t\t" << "state: " << attributeMap["state"][0] << endl;
+
+ m_state = attributeMap["state"][0].compare("true") == 0;
+ m_power = std::stoi(attributeMap["power"][0]);
+}
+
+void LightResource::getRepresentation(AttributeMap& attributeMap) const
+{
+ attributeMap["state"] = { (m_state ? "true" : "false") };
+ attributeMap["power"] = { to_string(m_power) };
+}
+
+void LightResource::addType(const OC::OCPlatform& platform, const std::string& type) const
+{
+ OCStackResult result = platform.bindTypeToResource(m_resourceHandle, type);
+ if(OC_STACK_OK != result)
+  cout << "Binding TypeName to Resource was unsuccessful, result was " << result << '\n';
+}
+
+void LightResource::addInterface(const OC::OCPlatform& platform, const std::string& interface) const
+{
+ OCStackResult result = platform.bindInterfaceToResource(m_resourceHandle, interface);
+
+ if(OC_STACK_OK != result)
+  cout << "Binding TypeName to Resource was unsuccessful, result was " << result << '\n';
+}
+
+void LightResource::createResource(OC::OCPlatform& platform, const unsigned int resource_number)
+{
+ string resourceURI      { make_URI(resource_number) };
+ string resourceTypeName { "core.light" };
+
+ cout << "registering resource: " << resourceURI << '\n';
+ cout << "registering type name \"" << resourceTypeName << "\".\n";
+
+ // This will internally create and register the resource, binding the current instance's method as a callback:
+ OCStackResult result = platform.registerResource(
+                                            m_resourceHandle, resourceURI, resourceTypeName,
+                                            DEFAULT_INTERFACE, 
+                                            std::bind(&LightResource::entityHandler, this, std::placeholders::_1, std::placeholders::_2), 
+                                            OC_DISCOVERABLE | OC_OBSERVABLE);
+
+  if (OC_STACK_OK != result)
+   std::cout << "Resource creation failed.\n";
+}
+
+void LightResource::observe_function()
+{
+ cerr << "Observation thread is spinning up.\n";
+
+ while(!shutdown_flag)
+  {
+    std::this_thread::sleep_for(std::chrono::seconds(2));
+
+    if(!m_observation)
+     continue;
+
+    m_power += 10;
+
+    const auto result = OCPlatform::notifyObservers(getHandle());
+
+    // Stop notifications when there are no more observers:
+    if(OC_STACK_NO_OBSERVERS == result)
+     {
+        m_observation = 0;
+     }
+  }
+
+ cerr << "Observation thread is shutting down.\n";
+}
+
+// This is just a sample implementation of entity handler.
+// Entity handler can be implemented in several ways by the manufacturer
+void LightResource::entityHandler(std::shared_ptr<OCResourceRequest> request, std::shared_ptr<OCResourceResponse> response)
+{
+    if(!request)
+     {
+        cerr << "entityHandler(): Received invalid request object.\n";
+        return;
+     }
+
+    if(!response)
+     {
+        cerr << "entityHandler(): Received invalid response object.\n";
+        return;
+     }
+
+    switch(request->getRequestHandlerFlag())   
+    {
+        default:
+                cerr << "entityHandler(): invalid request flag\n";
+                break;
+
+        case RequestHandlerFlag::InitFlag:
+                cerr << "entityHandler(): Initialization requested.\n";
+                break;
+
+        case RequestHandlerFlag::RequestFlag:
+                dispatch_request(request->getRequestType(), request, response);
+                break;
+
+        case RequestHandlerFlag::ObserverFlag:
+                handle_observe_event(request, response);
+                break;
+    }
+}
+
+void LightResource::dispatch_request(const std::string& request_type, std::shared_ptr<OCResourceRequest> request, std::shared_ptr<OCResourceResponse> response) 
+{
+ std::cout << "dispatch_request(): " << request_type << '\n';
+
+ if("GET" == request_type)
+  return handle_get_request(request, response);
+
+ if("PUT" == request_type)
+  return handle_put_request(request, response);
+
+ if("POST" == request_type)
+  return handle_post_request(request, response);
+
+ if("DELETE" == request_type)
+  return handle_delete_request(request, response);
+
+ cerr << "entityHandler(): Invalid request type \"" << request_type << "\".\n";
+}
+
+void LightResource::handle_get_request(std::shared_ptr<OCResourceRequest> request, std::shared_ptr<OCResourceResponse> response) 
+{
+ cout << "handle_get_request():\n";
+
+ const auto query_params_map = request->getQueryParameters();
+
+ // ...do any processing of the query here...
+
+ // Get a representation of the resource and send it back as a response:
+ AttributeMap attribute_map;
+
+ getRepresentation(attribute_map);
+
+ response->setErrorCode(200);
+ response->setResourceRepresentation(attribute_map);
+}
+
+void LightResource::handle_put_request(std::shared_ptr<OCResourceRequest> request, std::shared_ptr<OCResourceResponse> response) 
+{
+ const auto query_params_map = request->getQueryParameters();
+
+ // ...do something with the query parameters...
+
+ auto attribute_map = request->getResourceRepresentation();
+
+ setRepresentation(attribute_map);
+
+ getRepresentation(attribute_map);
+
+ response->setErrorCode(200);
+ response->setResourceRepresentation(attribute_map); 
+}
+
+void LightResource::handle_post_request(std::shared_ptr<OCResourceRequest> request, std::shared_ptr<OCResourceResponse> response)
+{
+ // ...demo-code...
+ response->setErrorCode(200);
+
+ auto attribute_map = request->getResourceRepresentation();
+ getRepresentation(attribute_map);
+ response->setResourceRepresentation(attribute_map);
+}
+
+void LightResource::handle_delete_request(std::shared_ptr<OCResourceRequest> request, std::shared_ptr<OCResourceResponse> response) 
+{
+ // ...demo-code...
+ response->setErrorCode(200);
+
+ auto attribute_map = request->getResourceRepresentation();
+ getRepresentation(attribute_map);
+ response->setResourceRepresentation(attribute_map);
+}
+
+// Set up observation in a separate thread:
+void LightResource::handle_observe_event(std::shared_ptr<OCResourceRequest> request, std::shared_ptr<OCResourceResponse> response) 
+{
+ if(observe_thread.joinable())
+  return; 
+
+ observe_thread = thread(bind(&LightResource::observe_function, this));
+ observe_thread.detach();
+}
+
+int exec(const boost::program_options::variables_map& vm)
+{
+ using namespace std;
+
+ std::cout << "Starting platform: " << std::flush;
+
+ OC::OCPlatform platform({ 
+                          OC::ServiceType::InProc,              // in-process server
+                          OC::ModeType::Both,                   // run as server and as client
+                          vm["host_ip"].as<string>(),           // host
+                          vm["host_port"].as<uint16_t>()        // port
+                        });
+
+ std::cout << "Ok." << std::endl;
+
+ vector<string> resource_URIs;
+
+ vector<shared_ptr<LightResource>> lights;
+
+ const unsigned long& nresources = vm["nres"].as<unsigned long>();
+
+ lights.resize(nresources);
+
+ for(unsigned int resource_number = 1; nresources >= resource_number; resource_number++)
+  {
+        cout << "Registering resource " << resource_number << ": " << std::flush;
+
+        auto lr = make_shared<LightResource>();
+
+        lr->createResource(platform, resource_number);
+        lr->addType(platform, std::string("core.brightlight"));
+        lr->addInterface(platform, std::string("oc.mi.ll"));
+
+        lights.push_back(lr);
+
+        cout << "Ok." << std::endl;
+  }
+
+ // Perform app tasks
+ while(true)
+ {
+    std::this_thread::sleep_for(std::chrono::seconds(5));
+ }
+
+ return 1;
+}
+
+}} // namespace Intel::OCDemo
+
index 157dc51..c822507 100644 (file)
@@ -96,7 +96,7 @@ void OC::MyMultiResourceHandler::performDimmerOperations(OC::OCResource myResour
                //Example to unobserve a property
                unbind_observer(&myObserverHandler, myResource, "powerState");
        }
-       catch(OC::OCReflect::reflection_exception& e)
+       catch(OC::reflection_exception& e)
        {
                log(e.what());
        }
@@ -137,7 +137,7 @@ void OC::MyMultiResourceHandler::performDoorOperations(OC::OCResource myResource
                // Canonical one-step approach to access a property
                std::string manufacturer = update->property<std::string>("manufacturer");
        }
-       catch(OC::OCReflect::reflection_exception& e)
+       catch(OC::reflection_exception& e)
        {
                log(e.what());
        }
index 5ac79f0..2ea89cb 100644 (file)
@@ -90,7 +90,7 @@ void MyResourceHandler::onFoundResource(OCResourceResult *update, void *params){
                //Example to unobserve a property
                unbind_observer(&myObserverHandler, myResource, "PowerState");
        }
-       catch(OC::OCReflect::reflection_exception& e)
+       catch(OC::reflection_exception& e)
        {
                log(e.what());
        }
index d2eabac..3f1b610 100644 (file)
@@ -256,7 +256,7 @@ int main()
        light l;
        l.bindTo(server, "/foo/");
   }
- catch(OC::OCReflect::reflection_exception& e)
+ catch(OC::reflection_exception& e)
   {
        std::cerr << "Oops: " << e.what() << '\n';
   }