OICSensorBoard: App for Intel Edison Platform.
authorKishen Maloor <kishen.maloor@intel.com>
Mon, 22 Dec 2014 20:09:51 +0000 (12:09 -0800)
committerKishen Maloor <kishen.maloor@intel.com>
Fri, 26 Dec 2014 03:50:07 +0000 (19:50 -0800)
(Please refer to https://oic-review.01.org/gerrit/#/c/668/8/
for prior review status)

Build for OICSensorBoard is NOT included in the
standard Iotivity build.

It requires the Yocto cross-toolchain for
a chosen target, and would therefore be
built separately.

It demonstrates Iotivity Server capabilities through
the integration of an add-on breadboard that hosts
temperature, ambient light and LED sensors.
In addition, there is a command-line Iotivity Client
application to test server functionality from a
separate machine.

The included scons build script expects to build
the client for Linux (tested on Ubuntu 12.04)
and the server to be built via the Yocto
cross-toolchain for Edison.

Brief instructions for constructing this
toolchain are provided in the included README.

Change-Id: I26d12c2334d84a6e0245e0f3689e09a51152fea5
Signed-off-by: Kishen Maloor <kishen.maloor@intel.com>
examples/OICSensorBoard/OICSensorBoardREADME.pdf [new file with mode: 0644]
examples/OICSensorBoard/SConstruct [new file with mode: 0644]
examples/OICSensorBoard/client.cpp [new file with mode: 0644]
examples/OICSensorBoard/client.h [new file with mode: 0644]
examples/OICSensorBoard/namedefs.h [new file with mode: 0644]
examples/OICSensorBoard/observer.cpp [new file with mode: 0644]
examples/OICSensorBoard/observer.h [new file with mode: 0644]
examples/OICSensorBoard/sensors.h [new file with mode: 0644]
examples/OICSensorBoard/server.cpp [new file with mode: 0644]
examples/OICSensorBoard/server.h [new file with mode: 0644]

diff --git a/examples/OICSensorBoard/OICSensorBoardREADME.pdf b/examples/OICSensorBoard/OICSensorBoardREADME.pdf
new file mode 100644 (file)
index 0000000..d5f9f2d
Binary files /dev/null and b/examples/OICSensorBoard/OICSensorBoardREADME.pdf differ
diff --git a/examples/OICSensorBoard/SConstruct b/examples/OICSensorBoard/SConstruct
new file mode 100644 (file)
index 0000000..e9acb2d
--- /dev/null
@@ -0,0 +1,65 @@
+#This script builds edisonclient for Ubuntu and edisonserver for Yocto. 
+
+#Client build for Ubuntu
+#Set IOTIVITY_ROOT to the root of oic-resource on Ubuntu.
+IOTIVITY_ROOT = '' 
+#Set IOTIVITY_LIBS_PATH to path on Ubuntu that contains liboc.so, liboctbstack.so, liboc_logger.so and libcoap.so.               
+IOTIVITY_LIBS_PATH = ''
+
+env = DefaultEnvironment()
+env.AppendUnique(CXXFLAGS = ['-std=c++0x', '-Wall'])
+env.AppendUnique(LINKFLAGS = ['-pthread'])
+env.AppendUnique(LIBS = ['oc', 'octbstack', 'oc_logger', 'coap'])
+
+envClient = env.Clone()
+envClient.AppendUnique(CPPPATH = [
+                IOTIVITY_ROOT + '/resource/include', 
+                IOTIVITY_ROOT + '/resource/csdk/stack/include',
+                IOTIVITY_ROOT + '/resource/csdk/ocsocket/include',
+                IOTIVITY_ROOT + '/resource/oc_logger/include',
+                ])
+envClient.AppendUnique(LIBPATH = [IOTIVITY_LIBS_PATH])
+envClient.Program('edisonclient', 'client.cpp')
+
+#Server build
+envServer = env.Clone()
+'''
+This code injects Yocto cross-compilation flags into scons' default environment
+in order to invoke the relevant tools while performing a build.
+'''
+import os.path, re
+sdk_root = ''
+try:
+    CC = os.environ['CC']
+    sdk_root = re.search(r'--sysroot=\S+', CC).group().split('=')[1]
+    target_prefix = CC.split()[0]
+    target_prefix = target_prefix[:len(target_prefix)-3]
+    tools = {"CC" : target_prefix+"gcc",
+             "CXX" : target_prefix+"g++",
+             "AS" : target_prefix+"as",
+             "LD" : target_prefix+"ld",
+             "GDB" : target_prefix+"gdb",
+             "STRIP" : target_prefix+"strip",
+             "RANLIB" : target_prefix+"ranlib",
+             "OBJCOPY" : target_prefix+"objcopy",
+             "OBJDUMP" : target_prefix+"objdump",
+             "AR" : target_prefix+"ar",
+             "NM" : target_prefix+"nm",
+             "M4" : "m4",
+             "STRINGS": target_prefix+"strings"}
+    PATH = os.environ['PATH'].split(os.pathsep)
+    for tool in tools:
+        if tool in os.environ:
+            for path in PATH:
+                   if os.path.isfile(os.path.join(path, tools[tool])):
+                       envServer[tool] = os.path.join(path, os.environ[tool])
+    envServer.Program('edisonserver', ['server.cpp', 'observer.cpp'])
+    envServer.AppendUnique(LIBS = ['mraa'])
+    envServer.AppendUnique(CPPPATH = [
+                sdk_root + '/usr/include/iotivity/',
+                sdk_root + '/usr/include/iotivity/stack/',
+                sdk_root + '/usr/include/iotivity/ocsocket/',
+                sdk_root + '/usr/include/iotivity/oc_logger/',
+                ])                     
+except:
+    print "ERROR configuring Yocto cross-toolchain environment. This is required for building the server"
diff --git a/examples/OICSensorBoard/client.cpp b/examples/OICSensorBoard/client.cpp
new file mode 100644 (file)
index 0000000..4b7fe85
--- /dev/null
@@ -0,0 +1,383 @@
+//******************************************************************
+//
+// Copyright 2014 Intel Corporation.
+//
+//-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
+//
+// 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 "client.h"
+#include "namedefs.h"
+
+IoTClient::IoTClient()
+{
+    cout << "Running IoTClient constructor" << endl;
+    initializePlatform();
+}
+
+IoTClient::~IoTClient()
+{
+    cout << "Running IoTClient destructor" << endl;
+}
+
+void IoTClient::initializePlatform()
+{
+    m_platformConfig = make_shared<PlatformConfig>(ServiceType::InProc, ModeType::Client, "0.0.0.0",
+                                                   0, OC::QualityOfService::HighQos);
+    OCPlatform::Configure(*m_platformConfig);
+    m_resourceDiscoveryCallback = bind(&IoTClient::discoveredResource, this, placeholders::_1);
+}
+
+void IoTClient::findResource()
+{
+    string coap_multicast_discovery = string(OC_WELL_KNOWN_QUERY "?if=" EDISON_RESOURCE_INTERFACE);
+    OCPlatform::findResource("", coap_multicast_discovery.c_str(), m_resourceDiscoveryCallback,
+                             OC::QualityOfService::LowQos);
+}
+
+void IoTClient::discoveredResource(shared_ptr<OCResource> Resource)
+{
+    try
+    {
+        if (Resource)
+        {
+            string resourceUri = Resource->uri();
+            string hostAddress = Resource->host();
+
+            cout << "\nFound Resource" << endl << "Resource Types:" << endl;
+            for (auto& resourceTypes : Resource->getResourceTypes())
+            {
+                cout << "\t" << resourceTypes << endl;
+            }
+
+            cout << "Resource Interfaces: " << endl;
+            for (auto& resourceInterfaces : Resource->getResourceInterfaces())
+            {
+                cout << "\t" << resourceInterfaces << endl;
+            }
+            cout << "Resource uri: " << resourceUri << endl;
+            cout << "host: " << hostAddress << endl;
+
+            if (resourceUri == TEMPERATURE_RESOURCE_ENDPOINT)
+            {
+                m_temperatureSensor = make_shared<TemperatureSensor>(Resource);
+            }
+            else if (resourceUri == LIGHT_RESOURCE_ENDPOINT)
+            {
+                m_ambientLightSensor = make_shared<AmbientLight>(Resource);
+            }
+            else if (resourceUri == LED_RESOURCE_ENDPOINT)
+            {
+                m_platformLED = make_shared<LED>(Resource);
+            }
+        }
+        IoTClient::DisplayMenu();
+    }
+    catch (OCException& ex)
+    {
+        cerr << "Caught exception in discoveredResource: " << ex.reason() << endl;
+    }
+}
+
+shared_ptr<TemperatureSensor> IoTClient::getTemperatureSensor()
+{
+    return m_temperatureSensor;
+}
+
+shared_ptr<AmbientLight> IoTClient::getAmbientLightSensor()
+{
+    return m_ambientLightSensor;
+}
+
+shared_ptr<LED> IoTClient::getPlatformLED()
+{
+    return m_platformLED;
+}
+
+TemperatureSensor::TemperatureSensor(shared_ptr<OCResource> Resource)
+{
+    m_isObserved = false;
+    m_resourceHandle = Resource;
+    m_GETCallback = bind(&TemperatureSensor::onGet, this, placeholders::_1, placeholders::_2,
+                         placeholders::_3);
+    m_OBSERVECallback = bind(&TemperatureSensor::onObserve, this, placeholders::_1,
+                             placeholders::_2, placeholders::_3, placeholders::_4);
+}
+
+TemperatureSensor::~TemperatureSensor()
+{
+
+}
+
+void TemperatureSensor::startObserve()
+{
+    if (!m_isObserved)
+    {
+        cout << "Starting observing temperature sensor" << endl;
+        m_resourceHandle->observe(ObserveType::Observe, QueryParamsMap(), m_OBSERVECallback);
+    }
+    m_isObserved = true;
+}
+
+void TemperatureSensor::stopObserve()
+{
+    if (m_isObserved)
+    {
+        m_resourceHandle->cancelObserve();
+        cout << "Stopped observing temperature sensor" << endl;
+    }
+    m_isObserved = false;
+}
+
+void TemperatureSensor::onObserve(const HeaderOptions headerOptions, const OCRepresentation& rep,
+                                  int eCode, int sequenceNumber)
+{
+    if (eCode == OC_STACK_OK)
+    {
+        double value;
+        rep.getValue(TEMPERATURE_RESOURCE_KEY, value);
+        cout << "Observing TemperatureSensor: Current temperature reading is " << value << endl;
+        cout << "Sequence number: " << sequenceNumber << endl;
+    }
+    else
+    {
+        cerr << "TemperatureSensor: Observer response error" << endl;
+    }
+}
+
+void TemperatureSensor::get()
+{
+    QueryParamsMap params;
+    m_resourceHandle->get(params, m_GETCallback);
+}
+
+void TemperatureSensor::onGet(const HeaderOptions& headerOptions,
+                              const OCRepresentation& representation, int errCode)
+{
+    if (errCode == OC_STACK_OK)
+    {
+        double value;
+        representation.getValue(TEMPERATURE_RESOURCE_KEY, value);
+        cout << endl << endl << "Current temperature reading: " << value << endl;
+    }
+    else {
+        cerr << endl << endl << "Error in GET response from temperature sensor resource" << endl;
+    }
+    IoTClient::DisplayMenu();
+}
+
+AmbientLight::AmbientLight(shared_ptr<OCResource> Resource)
+{
+    m_isObserved = false;
+    m_resourceHandle = Resource;
+    m_GETCallback = bind(&AmbientLight::onGet, this, placeholders::_1, placeholders::_2,
+                         placeholders::_3);
+    m_OBSERVECallback = bind(&AmbientLight::onObserve, this, placeholders::_1, placeholders::_2,
+                             placeholders::_3, placeholders::_4);
+}
+
+AmbientLight::~AmbientLight()
+{
+
+}
+
+void AmbientLight::startObserve()
+{
+    if (!m_isObserved)
+    {
+        cout << "Started observing ambient light sensor" << endl;
+        m_resourceHandle->observe(ObserveType::Observe, QueryParamsMap(), m_OBSERVECallback);
+    }
+    m_isObserved = true;
+}
+
+void AmbientLight::stopObserve()
+{
+    if (m_isObserved)
+    {
+        m_resourceHandle->cancelObserve();
+        cout << "Stopped observing ambient light sensor" << endl;
+    }
+    m_isObserved = false;
+}
+
+void AmbientLight::onObserve(const HeaderOptions headerOptions, const OCRepresentation& rep,
+                             int eCode, int sequenceNumber)
+{
+    if (eCode == OC_STACK_OK)
+    {
+        int value;
+        rep.getValue(LIGHT_RESOURCE_KEY, value);
+        cout << "Observing AmbientLightSensor: Current ambient light reading is " << value << endl;
+        cout << "Sequence number: " << sequenceNumber << endl;
+    }
+    else
+    {
+        cerr << "TemperatureSensor: Observer response error" << endl;
+    }
+}
+
+void AmbientLight::get()
+{
+    QueryParamsMap params;
+    m_resourceHandle->get(params, m_GETCallback);
+}
+
+void AmbientLight::onGet(const HeaderOptions& headerOptions, const OCRepresentation& representation,
+                         int errCode)
+{
+    if (errCode == OC_STACK_OK)
+    {
+        int value;
+        representation.getValue(LIGHT_RESOURCE_KEY, value);
+        cout << endl << endl << "Current ambient light sensor reading: " << value << endl;
+    }
+    else {
+        cerr << endl << endl << "Error in GET response from ambient light sensor resource" << endl;
+    }
+    IoTClient::DisplayMenu();
+}
+
+LED::LED(shared_ptr<OCResource> Resource)
+{
+    m_resourceHandle = Resource;
+    m_GETCallback = bind(&LED::onGet, this, placeholders::_1, placeholders::_2, placeholders::_3);
+    m_PUTCallback = bind(&LED::onPut, this, placeholders::_1, placeholders::_2, placeholders::_3);
+}
+
+LED::~LED()
+{
+
+}
+
+void LED::get()
+{
+    QueryParamsMap params;
+    m_resourceHandle->get(params, m_GETCallback);
+}
+
+void LED::put(int Switch)
+{
+    QueryParamsMap params;
+    OCRepresentation rep;
+    rep.setValue(LED_RESOURCE_KEY, Switch);
+    m_resourceHandle->put(rep, params, m_PUTCallback);
+}
+
+void LED::onGet(const HeaderOptions& headerOptions, const OCRepresentation& representation,
+                int errCode)
+{
+    if (errCode == OC_STACK_OK)
+    {
+        int value;
+        representation.getValue(LED_RESOURCE_KEY, value);
+        cout << endl << endl << "LED switch state is: " << value << endl;
+    }
+    else {
+        cerr << endl << endl << "Error in GET response from LED resource" << endl;
+    }
+    IoTClient::DisplayMenu();
+}
+
+void LED::onPut(const HeaderOptions& headerOptions, const OCRepresentation& representation,
+                int errCode)
+{
+    if (errCode == OC_STACK_OK)
+    {
+        int value;
+        representation.getValue(LED_RESOURCE_KEY, value);
+        cout << endl << endl << "Set LED switch to: " << value << endl;
+    }
+    else {
+        cerr << endl << endl << "Error in PUT response from LED resource" << endl;
+    }
+    IoTClient::DisplayMenu();
+}
+
+void IoTClient::DisplayMenu()
+{
+    cout << "\nEnter:\n0) Display this menu\n1) Get temperature Reading\n2) Start Temperature Observer\n3) Stop Temperature Observer\n4) Get ambient light reading\n5) Start Ambient Light Observer\n6) Stop Ambient Light Observer\n7) Turn LED ON\n8) Turn LED OFF\n9) Quit\n";
+}
+
+int main()
+{
+    IoTClient client;
+    cout << "Performing Discovery..." << endl;
+    client.findResource();
+    int choice;
+    do
+    {
+        cin >> choice;
+        switch (choice)
+        {
+            case 0:
+                IoTClient::DisplayMenu();
+                break;
+            case 1:
+                if (client.getTemperatureSensor())
+                    client.getTemperatureSensor()->get();
+                else
+                    cout << "Temperature sensor resource not yet discovered" << endl;
+                break;
+            case 2:
+                if (client.getTemperatureSensor())
+                    client.getTemperatureSensor()->startObserve();
+                else
+                    cout << "Temperature sensor resource not yet discovered" << endl;
+                break;
+            case 3:
+                if (client.getTemperatureSensor())
+                    client.getTemperatureSensor()->stopObserve();
+                else
+                    cout << "Temperature sensor resource not yet discovered" << endl;
+                break;
+            case 4:
+                if (client.getAmbientLightSensor())
+                    client.getAmbientLightSensor()->get();
+                else
+                    cout << "Ambient light sensor resource not yet discovered" << endl;
+                break;
+            case 5:
+                if (client.getAmbientLightSensor())
+                    client.getAmbientLightSensor()->startObserve();
+                else
+                    cout << "Ambient light sensor resource not yet discovered" << endl;
+                break;
+            case 6:
+                if (client.getAmbientLightSensor())
+                    client.getAmbientLightSensor()->stopObserve();
+                else
+                    cout << "Ambient light sensor resource not yet discovered" << endl;
+                break;
+            case 7:
+                if (client.getPlatformLED())
+                    client.getPlatformLED()->put(1);
+                else
+                    cout << "LED resource not yet discovered" << endl;
+                break;
+            case 8:
+                if (client.getPlatformLED())
+                    client.getPlatformLED()->put(0);
+                else
+                    cout << "LED resource not yet discovered" << endl;
+                break;
+            case 9:
+            default:
+                return 0;
+        }
+    }
+    while (choice != 9);
+    return 0;
+}
diff --git a/examples/OICSensorBoard/client.h b/examples/OICSensorBoard/client.h
new file mode 100644 (file)
index 0000000..36b85ff
--- /dev/null
@@ -0,0 +1,105 @@
+//******************************************************************
+//
+// Copyright 2014 Intel Corporation.
+//
+//-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
+//
+// 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 CLIENT_H_
+#define CLIENT_H_
+
+#include <string>
+#include <iostream>
+#include <memory>
+#include "ocstack.h"
+#include "OCApi.h"
+#include "OCPlatform.h"
+#include "OCResource.h"
+
+using namespace std;
+using namespace OC;
+
+class LED
+{
+    shared_ptr<OCResource> m_resourceHandle;
+    OCRepresentation m_ledRepresentation;
+    GetCallback m_GETCallback;
+    PutCallback m_PUTCallback;
+    void onGet(const HeaderOptions&, const OCRepresentation&, int);
+    void onPut(const HeaderOptions&, const OCRepresentation&, int);
+public:
+    void get();
+    void put(int);
+    LED(shared_ptr<OCResource> Resource);
+    virtual ~LED();
+};
+
+class TemperatureSensor
+{
+    shared_ptr<OCResource> m_resourceHandle;
+    OCRepresentation m_temperatureRepresentation;
+    GetCallback m_GETCallback;
+    ObserveCallback m_OBSERVECallback;
+    bool m_isObserved;
+    void onObserve(const HeaderOptions headerOptions, const OCRepresentation& rep, int eCode,
+                   int sequenceNumber);
+    void onGet(const HeaderOptions&, const OCRepresentation&, int);
+public:
+    void get();
+    void startObserve();
+    void stopObserve();
+    TemperatureSensor(shared_ptr<OCResource> Resource);
+    virtual ~TemperatureSensor();
+};
+
+class AmbientLight
+{
+    shared_ptr<OCResource> m_resourceHandle;
+    OCRepresentation m_ledRepresentation;
+    GetCallback m_GETCallback;
+    ObserveCallback m_OBSERVECallback;
+    bool m_isObserved;
+    void onObserve(const HeaderOptions headerOptions, const OCRepresentation& rep, int eCode,
+                   int sequenceNumber);
+    void onGet(const HeaderOptions&, const OCRepresentation&, int);
+public:
+    void get();
+    void startObserve();
+    void stopObserve();
+    AmbientLight(shared_ptr<OCResource> Resource);
+    virtual ~AmbientLight();
+};
+
+class IoTClient
+{
+    shared_ptr<TemperatureSensor> m_temperatureSensor;
+    shared_ptr<AmbientLight> m_ambientLightSensor;
+    shared_ptr<LED> m_platformLED;
+    shared_ptr<PlatformConfig> m_platformConfig;
+    FindCallback m_resourceDiscoveryCallback;
+    void initializePlatform();
+    void discoveredResource(shared_ptr<OCResource>);
+public:
+    shared_ptr<TemperatureSensor> getTemperatureSensor();
+    shared_ptr<AmbientLight> getAmbientLightSensor();
+    shared_ptr<LED> getPlatformLED();
+    void findResource();
+    IoTClient();
+    virtual ~IoTClient();
+    static void DisplayMenu();
+};
+
+#endif /* CLIENT_H_ */
diff --git a/examples/OICSensorBoard/namedefs.h b/examples/OICSensorBoard/namedefs.h
new file mode 100644 (file)
index 0000000..cf7aaf8
--- /dev/null
@@ -0,0 +1,35 @@
+//******************************************************************
+//
+// Copyright 2014 Intel Corporation.
+//
+//-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
+//
+// 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 NAMEDEFS_H_
+#define NAMEDEFS_H_
+
+#define EDISON_RESOURCE_INTERFACE "core.edison.resources"
+#define TEMPERATURE_RESOURCE_TYPE "Room.Temperature"
+#define LIGHT_RESOURCE_TYPE "Ambient.Light"
+#define LED_RESOURCE_TYPE "Platform.Led"
+#define TEMPERATURE_RESOURCE_ENDPOINT "/temperature"
+#define LIGHT_RESOURCE_ENDPOINT "/ambientlight"
+#define LED_RESOURCE_ENDPOINT "/led"
+#define TEMPERATURE_RESOURCE_KEY "temperature"
+#define LIGHT_RESOURCE_KEY "ambientlight"
+#define LED_RESOURCE_KEY "switch"
+
+#endif /* NAMEDEFS_H_ */
diff --git a/examples/OICSensorBoard/observer.cpp b/examples/OICSensorBoard/observer.cpp
new file mode 100644 (file)
index 0000000..4e54ebe
--- /dev/null
@@ -0,0 +1,71 @@
+//******************************************************************
+//
+// Copyright 2014 Intel Corporation.
+//
+//-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
+//
+// 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 "observer.h"
+
+IoTObserver::IoTObserver(IoTObserverCb Cb) :
+        m_callback(Cb), m_destroy(false), m_started(false)
+{
+    m_observerThread[0] = thread(&IoTObserver::observerThread, this);
+}
+
+IoTObserver::~IoTObserver()
+{
+    terminate();
+}
+
+void IoTObserver::start()
+{
+    if (!m_started)
+    {
+        {
+            lock_guard<mutex> lock(m_mutex);
+            m_started = true;
+        }
+        m_cond.notify_one();
+    }
+}
+
+void IoTObserver::stop()
+{
+    m_started = false;
+}
+
+void IoTObserver::terminate()
+{
+    m_destroy = true;
+    stop();
+    m_cond.notify_one();
+    m_observerThread[0].join();
+}
+
+void IoTObserver::observerThread()
+{
+    while (!m_destroy)
+    {
+        unique_lock<mutex> lock(m_mutex);
+        if (!m_started)
+            m_cond.wait(lock);
+        while (m_started)
+        {
+            m_callback();
+        }
+    }
+}
diff --git a/examples/OICSensorBoard/observer.h b/examples/OICSensorBoard/observer.h
new file mode 100644 (file)
index 0000000..8329a71
--- /dev/null
@@ -0,0 +1,55 @@
+//******************************************************************
+//
+// Copyright 2014 Intel Corporation.
+//
+//-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
+//
+// 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 OBSERVER_H_
+#define OBSERVER_H_
+
+#include <iostream>
+#include <thread>
+#include <condition_variable>
+#include <mutex>
+#include <functional>
+
+using namespace std;
+
+//Polling callback function prototype.
+typedef function<void(void)> IoTObserverCb;
+
+//Hosts a polling thread which continually calls the specific function
+//supplied to its constructor. Client code simply uses Start/Stop calls
+//to kick off/suspend polling.
+class IoTObserver
+{
+    mutex m_mutex;
+    condition_variable m_cond;
+    IoTObserverCb m_callback;
+    thread m_observerThread[1];
+    bool m_destroy;
+    bool m_started;
+    void observerThread();
+    void terminate();
+public:
+    IoTObserver(IoTObserverCb Cb);
+    virtual ~IoTObserver();
+    void start();
+    void stop();
+};
+
+#endif /* OBSERVER_H_ */
diff --git a/examples/OICSensorBoard/sensors.h b/examples/OICSensorBoard/sensors.h
new file mode 100644 (file)
index 0000000..44ad441
--- /dev/null
@@ -0,0 +1,90 @@
+//******************************************************************
+//
+// Copyright 2014 Intel Corporation.
+//
+//-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
+//
+// 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 <stdlib.h>
+#include <math.h>
+#include "mraa.h"
+
+#define ONBOARD_LED_PIN 13
+#define TEMPERATURE_AIO_PIN 0
+#define LIGHT_SENSOR_AIO_PIN 2
+
+namespace Sensors
+{
+mraa_gpio_context led_gpio = NULL;
+mraa_aio_context tmp_aio = NULL;
+mraa_aio_context light_aio = NULL;
+
+inline void SetupPins()
+{
+    led_gpio = mraa_gpio_init(ONBOARD_LED_PIN); // Initialize pin 13
+    if (led_gpio != NULL)
+        mraa_gpio_dir(led_gpio, MRAA_GPIO_OUT); // Set direction to OUTPUT
+    tmp_aio = mraa_aio_init(TEMPERATURE_AIO_PIN);   // initialize pin 0
+    light_aio = mraa_aio_init(LIGHT_SENSOR_AIO_PIN);   // initialize pin 2
+}
+
+inline void ClosePins()
+{
+    mraa_gpio_close(led_gpio);
+    mraa_aio_close(tmp_aio);
+    mraa_aio_close(light_aio);
+}
+
+inline void SetOnboardLed(int on)
+{
+    if (led_gpio == NULL)
+    {
+        led_gpio = mraa_gpio_init(ONBOARD_LED_PIN); // Initialize pin 13
+        if (led_gpio != NULL)
+            mraa_gpio_dir(led_gpio, MRAA_GPIO_OUT); // Set direction to OUTPUT
+    }
+    if (led_gpio != NULL)
+        mraa_gpio_write(led_gpio, on); // Writes into GPIO
+}
+
+inline float GetTemperatureInC()
+{
+    float ret = 0;
+    if (tmp_aio == NULL)
+    {
+        tmp_aio = mraa_aio_init(TEMPERATURE_AIO_PIN); // initialize pin 0
+    }
+    if (tmp_aio != NULL)
+    {
+        uint16_t adc_value = mraa_aio_read(tmp_aio); // read the raw value
+        //convert reading to temperature
+        float beta = 4090.0; //the beta of the thermistor, magic number
+        ret = beta / (log((4095.0 * 10 / adc_value - 10) / 10) + beta / 298.0) - 273.0;
+    }
+    return ret;
+}
+
+// This function returns light level between 0 and 4095
+inline int GetLightLevel()
+{
+    uint16_t adc_value = 0;
+    if (light_aio == NULL)
+        light_aio = mraa_aio_init(LIGHT_SENSOR_AIO_PIN); // initialize pin 2
+    if (light_aio != NULL)
+        adc_value = mraa_aio_read(light_aio); // read the raw value
+    return adc_value;
+}
+}
diff --git a/examples/OICSensorBoard/server.cpp b/examples/OICSensorBoard/server.cpp
new file mode 100644 (file)
index 0000000..598e370
--- /dev/null
@@ -0,0 +1,359 @@
+//******************************************************************
+//
+// Copyright 2014 Intel Corporation.
+//
+//-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
+//
+// 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 <signal.h>
+#include <thread>
+#include <functional>
+#include "server.h"
+#include "sensors.h"
+#include "namedefs.h"
+using namespace Sensors;
+
+void IoTServer::initializePlatform()
+{
+    cout << "Running IoTServer constructor" << endl;
+    m_platformConfig = make_shared<PlatformConfig>(ServiceType::InProc, ModeType::Server, "0.0.0.0",
+                                                   0, OC::QualityOfService::HighQos);
+    OCPlatform::Configure(*m_platformConfig);
+}
+
+IoTServer::IoTServer()
+{
+    initializePlatform();
+    setupResources();
+    m_temperatureRepresentation.setValue(TEMPERATURE_RESOURCE_KEY, (float) 0.0f);
+    m_ambientLightRepresentation.setValue(LIGHT_RESOURCE_KEY, 0);
+    m_ledRepresentation.setValue(LED_RESOURCE_KEY, 0);
+    SetupPins();
+}
+
+IoTServer::~IoTServer()
+{
+    cout << "Running IoTServer destructor" << endl;
+    ClosePins();
+}
+
+void IoTServer::setupResources()
+{
+    EntityHandler cb1 = bind(&IoTServer::temperatureEntityHandler, this, placeholders::_1);
+    createResource(TEMPERATURE_RESOURCE_ENDPOINT, TEMPERATURE_RESOURCE_TYPE, cb1,
+                   m_temperatureResource);
+    IoTObserverCb tempObsCb = bind(&IoTServer::temperatureObserverLoop, this);
+    m_temperatureObserverLoop = make_shared<IoTObserver>(tempObsCb);
+
+    EntityHandler cb2 = bind(&IoTServer::lightEntityHandler, this, placeholders::_1);
+    createResource(LIGHT_RESOURCE_ENDPOINT, LIGHT_RESOURCE_TYPE, cb2, m_ambientLightResource);
+    IoTObserverCb lightObsCb = bind(&IoTServer::lightObserverLoop, this);
+    m_ambientLightObserverLoop = make_shared<IoTObserver>(lightObsCb);
+
+    EntityHandler cb3 = bind(&IoTServer::LEDEntityHandler, this, placeholders::_1);
+    createResource(LED_RESOURCE_ENDPOINT, LED_RESOURCE_TYPE, cb3, m_ledResource);
+}
+
+void IoTServer::createResource(string Uri, string Type, EntityHandler Cb, OCResourceHandle& Handle)
+{
+    string resourceUri = Uri;
+    string resourceType = Type;
+    string resourceInterface = EDISON_RESOURCE_INTERFACE;
+    uint8_t resourceFlag = OC_DISCOVERABLE | OC_OBSERVABLE;
+
+    OCStackResult result = OCPlatform::registerResource(Handle, resourceUri, resourceType,
+                                                        resourceInterface, Cb, resourceFlag);
+
+    if (result != OC_STACK_OK)
+        cerr << "Could not create " << Type << " resource" << endl;
+    else
+        cout << "Successfully created " << Type << " resource" << endl;
+}
+
+void IoTServer::putLEDRepresentation()
+{
+    int state = 0;
+    m_ledRepresentation.getValue(LED_RESOURCE_KEY, state);
+    SetOnboardLed(state);
+    if (state == 0)
+        cout << "Turned off LED" << endl;
+    else if (state == 1)
+        cout << "Turned on LED" << endl;
+    else
+        cerr << "Invalid request value" << endl;
+}
+
+OCRepresentation IoTServer::getLEDRepresentation()
+{
+    return m_ledRepresentation;
+}
+
+void IoTServer::temperatureObserverLoop()
+{
+    usleep(1500000);
+    cout << "Temperature Observer Callback" << endl;
+    shared_ptr<OCResourceResponse> resourceResponse(new OCResourceResponse());
+    resourceResponse->setErrorCode(200);
+    resourceResponse->setResourceRepresentation(getTemperatureRepresentation(),
+    EDISON_RESOURCE_INTERFACE);
+    OCStackResult result = OCPlatform::notifyListOfObservers(m_temperatureResource,
+                                                             m_temperatureObservers,
+                                                             resourceResponse);
+    if (result == OC_STACK_NO_OBSERVERS)
+    {
+        cout << "No more observers..Stopping observer loop..." << endl;
+        m_temperatureObserverLoop->stop();
+    }
+}
+
+void IoTServer::lightObserverLoop()
+{
+    usleep(1500000);
+    cout << "Light Observer Callback" << endl;
+    shared_ptr<OCResourceResponse> resourceResponse(new OCResourceResponse());
+    resourceResponse->setErrorCode(200);
+    resourceResponse->setResourceRepresentation(getLightRepresentation(),
+    EDISON_RESOURCE_INTERFACE);
+    OCStackResult result = OCPlatform::notifyListOfObservers(m_ambientLightResource,
+                                                             m_ambientLightObservers,
+                                                             resourceResponse);
+    if (result == OC_STACK_NO_OBSERVERS)
+    {
+        cout << "No more observers..Stopping observer loop..." << endl;
+        m_ambientLightObserverLoop->stop();
+    }
+}
+
+OCRepresentation IoTServer::getTemperatureRepresentation()
+{
+    m_temperatureRepresentation.setValue(TEMPERATURE_RESOURCE_KEY, GetTemperatureInC());
+    return m_temperatureRepresentation;
+}
+
+OCRepresentation IoTServer::getLightRepresentation()
+{
+    m_ambientLightRepresentation.setValue(LIGHT_RESOURCE_KEY, GetLightLevel());
+    return m_ambientLightRepresentation;
+}
+
+OCEntityHandlerResult IoTServer::lightEntityHandler(shared_ptr<OCResourceRequest> Request)
+{
+    OCEntityHandlerResult result = OC_EH_ERROR;
+    if (Request)
+    {
+        string requestType = Request->getRequestType();
+        int requestFlag = Request->getRequestHandlerFlag();
+        if (requestFlag & RequestHandlerFlag::RequestFlag)
+        {
+            auto Response = std::make_shared<OC::OCResourceResponse>();
+            Response->setRequestHandle(Request->getRequestHandle());
+            Response->setResourceHandle(Request->getResourceHandle());
+            if (requestType == "GET")
+            {
+                cout << "GET request for ambient light reading" << endl;
+                if (Response)
+                {
+                    Response->setErrorCode(200);
+                    Response->setResponseResult(OC_EH_OK);
+                    Response->setResourceRepresentation(getLightRepresentation());
+                    if (OCPlatform::sendResponse(Response) == OC_STACK_OK)
+                    {
+                        result = OC_EH_OK;
+                    }
+                }
+            }
+            else
+            {
+                Response->setResponseResult(OC_EH_ERROR);
+                OCPlatform::sendResponse(Response);
+                cerr << "Unsupported request type" << endl;
+                return result;
+            }
+        }
+        if (requestFlag & RequestHandlerFlag::ObserverFlag)
+        {
+            ObservationInfo observationInfo = Request->getObservationInfo();
+            if (ObserveAction::ObserveRegister == observationInfo.action)
+            {
+                cout << "Starting observer for ambient light sensor" << endl;
+                m_ambientLightObservers.push_back(observationInfo.obsId);
+                m_ambientLightObserverLoop->start();
+            }
+            else if (ObserveAction::ObserveUnregister == observationInfo.action)
+            {
+                m_ambientLightObservers.erase(
+                        remove(m_ambientLightObservers.begin(), m_ambientLightObservers.end(),
+                               observationInfo.obsId),
+                        m_ambientLightObservers.end());
+            }
+        }
+    }
+    return result;
+}
+
+OCEntityHandlerResult IoTServer::temperatureEntityHandler(shared_ptr<OCResourceRequest> Request)
+{
+    OCEntityHandlerResult result = OC_EH_ERROR;
+    if (Request)
+    {
+        string requestType = Request->getRequestType();
+        int requestFlag = Request->getRequestHandlerFlag();
+        if (requestFlag & RequestHandlerFlag::RequestFlag)
+        {
+            auto Response = std::make_shared<OC::OCResourceResponse>();
+            Response->setRequestHandle(Request->getRequestHandle());
+            Response->setResourceHandle(Request->getResourceHandle());
+            if (requestType == "GET")
+            {
+                cout << "GET request for temperature sensor reading" << endl;
+                if (Response)
+                {
+                    Response->setErrorCode(200);
+                    Response->setResponseResult(OC_EH_OK);
+                    Response->setResourceRepresentation(getTemperatureRepresentation());
+                    if (OCPlatform::sendResponse(Response) == OC_STACK_OK)
+                    {
+                        result = OC_EH_OK;
+                    }
+                }
+            }
+            else
+            {
+                Response->setResponseResult(OC_EH_ERROR);
+                OCPlatform::sendResponse(Response);
+                cerr << "Unsupported request type" << endl;
+                return result;
+            }
+        }
+        if (requestFlag & RequestHandlerFlag::ObserverFlag)
+        {
+            ObservationInfo observationInfo = Request->getObservationInfo();
+            if (ObserveAction::ObserveRegister == observationInfo.action)
+            {
+                cout << "Starting observer for temperature sensor" << endl;
+                m_temperatureObservers.push_back(observationInfo.obsId);
+                m_temperatureObserverLoop->start();
+            }
+            else if (ObserveAction::ObserveUnregister == observationInfo.action)
+            {
+                m_temperatureObservers.erase(
+                        remove(m_temperatureObservers.begin(), m_temperatureObservers.end(),
+                               observationInfo.obsId),
+                        m_temperatureObservers.end());
+            }
+        }
+    }
+    return result;
+}
+
+OCEntityHandlerResult IoTServer::LEDEntityHandler(shared_ptr<OCResourceRequest> Request)
+{
+    OCEntityHandlerResult result = OC_EH_ERROR;
+    if (Request)
+    {
+        string requestType = Request->getRequestType();
+        int requestFlag = Request->getRequestHandlerFlag();
+        if (requestFlag & RequestHandlerFlag::RequestFlag)
+        {
+            auto Response = std::make_shared<OC::OCResourceResponse>();
+            Response->setRequestHandle(Request->getRequestHandle());
+            Response->setResourceHandle(Request->getResourceHandle());
+            if (requestType == "PUT")
+            {
+                cout << "PUT request for platform LED" << endl;
+                OCRepresentation requestRep = Request->getResourceRepresentation();
+                if (requestRep.hasAttribute(LED_RESOURCE_KEY))
+                {
+                    try
+                    {
+                        requestRep.getValue<int>(LED_RESOURCE_KEY);
+                    }
+                    catch (...)
+                    {
+                        Response->setResponseResult(OC_EH_ERROR);
+                        OCPlatform::sendResponse(Response);
+                        cerr << "Client sent invalid resource value type" << endl;
+                        return result;
+                    }
+                }
+                else
+                {
+                    Response->setResponseResult(OC_EH_ERROR);
+                    OCPlatform::sendResponse(Response);
+                    cerr << "Client sent invalid resource key" << endl;
+                    return result;
+                }
+                m_ledRepresentation = requestRep;
+                putLEDRepresentation();
+                if (Response)
+                {
+                    Response->setErrorCode(200);
+                    Response->setResourceRepresentation(getLEDRepresentation());
+                    Response->setResponseResult(OC_EH_OK);
+                    if (OCPlatform::sendResponse(Response) == OC_STACK_OK)
+                    {
+                        result = OC_EH_OK;
+                    }
+                }
+            }
+            else if (requestType == "GET")
+            {
+                cout << "GET request for platform LED" << endl;
+                if (Response)
+                {
+                    Response->setErrorCode(200);
+                    Response->setResourceRepresentation(getLEDRepresentation());
+                    Response->setResponseResult(OC_EH_OK);
+                    if (OCPlatform::sendResponse(Response) == OC_STACK_OK)
+                    {
+                        result = OC_EH_OK;
+                    }
+                }
+            }
+            else
+            {
+                Response->setResponseResult(OC_EH_ERROR);
+                OCPlatform::sendResponse(Response);
+                cerr << "Unsupported request type" << endl;
+            }
+        }
+    }
+    return result;
+}
+
+int quit = 0;
+
+void handle_signal(int signal)
+{
+    quit = 1;
+}
+
+int main()
+{
+    struct sigaction sa;
+    sigfillset(&sa.sa_mask);
+    sa.sa_flags = 0;
+    sa.sa_handler = handle_signal;
+    sigaction(SIGINT, &sa, NULL);
+    cout << "Press Ctrl-C to quit...." << endl;
+    IoTServer server;
+    do
+    {
+        usleep(2000000);
+    }
+    while (quit != 1);
+    return 0;
+}
+
diff --git a/examples/OICSensorBoard/server.h b/examples/OICSensorBoard/server.h
new file mode 100644 (file)
index 0000000..b77325d
--- /dev/null
@@ -0,0 +1,71 @@
+//******************************************************************
+//
+// Copyright 2014 Intel Corporation.
+//
+//-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
+//
+// 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 SERVER_H_
+#define SERVER_H_
+
+#include <string>
+#include <iostream>
+#include <memory>
+#include "ocstack.h"
+#include "observer.h"
+#include "OCPlatform.h"
+#include "OCApi.h"
+
+using namespace std;
+using namespace OC;
+
+class IoTServer
+{
+    shared_ptr<PlatformConfig> m_platformConfig;
+    OCRepresentation m_temperatureRepresentation;
+    OCResourceHandle m_temperatureResource;
+    OCRepresentation m_ambientLightRepresentation;
+    OCResourceHandle m_ambientLightResource;
+    OCRepresentation m_ledRepresentation;
+    OCResourceHandle m_ledResource;
+    ObservationIds m_ambientLightObservers;
+    ObservationIds m_temperatureObservers;
+    shared_ptr<IoTObserver> m_ambientLightObserverLoop;
+    shared_ptr<IoTObserver> m_temperatureObserverLoop;
+
+    void initializePlatform();
+    void setupResources();
+    void createResource(string, string, EntityHandler, OCResourceHandle&);
+
+    OCRepresentation getTemperatureRepresentation();
+    OCRepresentation getLightRepresentation();
+    OCRepresentation getLEDRepresentation();
+    void putLEDRepresentation();
+
+    //Polling threads to periodically query sensor values and notify
+    //subscribers.
+    void temperatureObserverLoop();
+    void lightObserverLoop();
+
+    OCEntityHandlerResult temperatureEntityHandler(shared_ptr<OCResourceRequest>);
+    OCEntityHandlerResult lightEntityHandler(shared_ptr<OCResourceRequest>);
+    OCEntityHandlerResult LEDEntityHandler(shared_ptr<OCResourceRequest>);
+public:
+    IoTServer();
+    virtual ~IoTServer();
+};
+
+#endif /* SERVER_H_ */