{
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());
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
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
-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
--- /dev/null
+
+# 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
--- /dev/null
+
+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
+
--- /dev/null
+//******************************************************************
+//
+// 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
+
--- /dev/null
+
+#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;
+}
--- /dev/null
+//******************************************************************
+//
+// 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
--- /dev/null
+//******************************************************************
+//
+// 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
+
//Example to unobserve a property
unbind_observer(&myObserverHandler, myResource, "powerState");
}
- catch(OC::OCReflect::reflection_exception& e)
+ catch(OC::reflection_exception& e)
{
log(e.what());
}
// 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());
}
//Example to unobserve a property
unbind_observer(&myObserverHandler, myResource, "PowerState");
}
- catch(OC::OCReflect::reflection_exception& e)
+ catch(OC::reflection_exception& e)
{
log(e.what());
}
light l;
l.bindTo(server, "/foo/");
}
- catch(OC::OCReflect::reflection_exception& e)
+ catch(OC::reflection_exception& e)
{
std::cerr << "Oops: " << e.what() << '\n';
}