Imported Upstream version 1.1.0
[platform/upstream/iotivity.git] / service / resource-encapsulation / examples / linux / SampleResourceClient.cpp
index 98d7076..1d15dc8 100644 (file)
 #include <iostream>
 
 #include "RCSDiscoveryManager.h"
+#include "RCSRepresentation.h"
 #include "RCSRemoteResourceObject.h"
 #include "RCSResourceAttributes.h"
 #include "RCSAddress.h"
 
 #include "OCPlatform.h"
 
+#define DECLARE_MENU(FUNC, ...) { #FUNC, FUNC }
+
 using namespace OC;
 using namespace OIC::Service;
 
-#define DECLARE_MENU(FUNC, ...) { #FUNC, FUNC, __VA_ARGS__ }
-
-void startMonitoring();
-void startMonitoring();
-void stopMonitoring();
-void getAttributeFromRemoteServer();
-void setAttributeToRemoteServer();
-void startCachingWithoutCallback();
-void startCachingWithCallback();
-void getResourceCacheState();
-void getCachedAttributes();
-void getCachedAttribute();
-void stopCaching();
-void discoverResource();
-void cancelDiscovery();
-int processUserInput();
-void selectResource();
-void printAttributes(const RCSResourceAttributes& attributes);
-
-class MenuList;
-
-class MenuItem
+struct CloseApp {};
+
+struct MenuItem
 {
 private:
-    typedef void(*MenuHandler)();
+    typedef void(*Handler)();
 
 public:
-    MenuItem(const char* funcName, MenuHandler handler = nullptr,
-            MenuHandler optionHandler = nullptr, MenuList* state = nullptr)
-        : m_name(funcName), m_handler(handler), m_optionHandler(optionHandler),
-          m_nextState(state)
-    {
-    }
+    const std::string title;
+    const Handler handler;
+};
 
-    MenuList* command() const
-    {
-        std::cout << m_name << " start.." << std::endl;
-        if(m_handler) m_handler();
+typedef void(*Runner)();
 
-        if(m_optionHandler != nullptr) m_optionHandler();
+constexpr int RESOURCE_TEMP = 1;
+constexpr int RESOURCE_LIGHT = 2;
 
-        return m_nextState;
-    }
+const std::string RESOURCE_TYPE_TEMP = "oic.r.temperaturesensor";
+const std::string RESOURCE_TYPE_LIGHT = "oic.r.light";
 
-    const char* getTitle() const
-    {
-        return m_name.c_str();
-    }
+RCSRemoteResourceObject::Ptr g_selectedResource;
+std::vector<RCSRemoteResourceObject::Ptr> g_discoveredResources;
 
-private:
-    const std::string m_name;
-    const MenuHandler m_handler;
-    const MenuHandler m_optionHandler;
-    MenuList* const m_nextState ;
-};
+std::string g_attrKey;
 
-class MenuList
+Runner g_currentRun;
+
+std::ostream& operator<<(std::ostream& os, const RCSRemoteResourceObject::Ptr& object)
 {
-public:
-    MenuList(std::initializer_list<MenuItem> il)
-        :m_menuItemList(std::move(il))
+    return os << "\turi : " << object->getUri() << std::endl <<
+            "\thost address : " << object->getAddress();
+}
+
+std::ostream& operator<<(std::ostream& os, const MenuItem& item)
+{
+    return os << item.title;
+}
+
+void onSelected(const RCSRemoteResourceObject::Ptr& object)
+{
+    g_selectedResource = object;
+}
+
+void onSelected(const MenuItem& item)
+{
+    std::cout << item.title << " start.." << std::endl;
+    item.handler();
+}
+
+int processUserInput(int min = std::numeric_limits<int>::min(),
+        int max = std::numeric_limits<int>::max())
+{
+    assert(min <= max);
+
+    int input;
+
+    std::cin >> input;
+    std::cin.ignore(std::numeric_limits<std::streamsize>::max(), '\n');
+
+    if (!std::cin.fail() && min <= input && input <= max) return input;
+
+    std::cin.clear();
+    std::cin.ignore(std::numeric_limits<std::streamsize>::max(), '\n');
+
+    throw std::runtime_error("Invalid Input, please try again");
+}
+
+template<typename D>
+void displayItem(int width, int index, const D& data)
+{
+    std::cout.width(width);
+    std::cout << std::right << index << ". ";
+    std::cout << data << std::endl;
+}
+
+template<typename T>
+void displayItems(const std::vector<T>& items)
+{
+    std::cout << std::endl;
+
+    const auto width = (items.size() + 1) / 10 + 1;
+
+    for(size_t i = 0; i < items.size(); ++i)
     {
+        displayItem(width, i + 1, items[i]);
     }
+    displayItem(width, items.size() + 1, "quit");
+}
 
-    void display() const
-    {
-        std::cout << std::endl;
-        int menuNum = 1;
+template<typename T>
+void selectItem(const std::vector<T>& items)
+{
+    int selected = processUserInput(1, items.size() + 1) - 1;
 
-        for(const auto& menuItem : m_menuItemList)
-        {
-            std::cout.width(2);
-            std::cout << std::right << menuNum++ <<  ". ";
-            std::cout << menuItem.getTitle() << std::endl;
-        }
-    }
+    if(selected == static_cast<int>(items.size())) throw CloseApp();
 
-    MenuList* select()
-    {
-        int input = processUserInput();
+    onSelected(items[selected]);
+}
 
-        if(input == static_cast<int>(m_menuItemList.size())) return nullptr;
+template<typename T>
+void handleItems(const std::vector<T>& items)
+{
+    displayItems(items);
+    selectItem(items);
+}
 
-        if(input > static_cast<int>(m_menuItemList.size()) || input <= 0)
-        {
-            std::cout << "Invalid input, please try again" << std::endl;
-            return this;
-        }
-        auto nextMenuList = m_menuItemList[input-1].command();
+std::string inputInterface()
+{
+    std::string interfaceName;
 
-        return nextMenuList == nullptr ? this : nextMenuList;
-    }
+    std::cout << "\tInput the Interface you want to set : ";
+    std::cin >> interfaceName;
 
-private:
-    const std::vector<MenuItem> m_menuItemList;
-};
+    return interfaceName;
+}
 
-constexpr int REQUEST_TEMP = 1;
-constexpr int REQUEST_LIGHT = 2;
+RCSResourceAttributes inputKeyValue()
+{
+    std::string key;
 
-const std::string TEMP = "oic.r.temperaturesensor";
-const std::string LIGHT = "oic.r.light";
+    std::cout << "\tEnter the Key you want to set : ";
+    std::cin >> key;
 
-std::unique_ptr<RCSDiscoveryManager::DiscoveryTask> discoveryTask;
+    std::cout << "\tEnter the value(INT) you want to set :";
+    RCSResourceAttributes attrs;
+    attrs[key] = processUserInput();
 
-std::vector<RCSRemoteResourceObject::Ptr> resourceList;
-RCSRemoteResourceObject::Ptr selectedResource;
+    return attrs;
+}
 
-std::string defaultKey;
+void printAttribute(const std::string& key, const RCSResourceAttributes::Value& value)
+{
+    std::cout << "\tkey : " << key << std::endl
+              << "\tvalue : " << value.toString() << std::endl;
+}
 
-MenuList* currentMenuList;
+void printAttributes(const RCSResourceAttributes& attributes)
+{
+    if (attributes.empty())
+    {
+       std::cout << "\tattributes is empty" << std::endl;
+    }
 
-MenuList resourceMenu = {
-    DECLARE_MENU(startMonitoring),
-    DECLARE_MENU(stopMonitoring),
-    DECLARE_MENU(getAttributeFromRemoteServer),
-    DECLARE_MENU(setAttributeToRemoteServer),
-    DECLARE_MENU(startCachingWithoutCallback),
-    DECLARE_MENU(startCachingWithCallback),
-    DECLARE_MENU(getResourceCacheState),
-    DECLARE_MENU(getCachedAttributes),
-    DECLARE_MENU(getCachedAttribute),
-    DECLARE_MENU(stopCaching),
-    { "quit" }
-};
+    for(const auto& attr : attributes)
+    {
+        printAttribute(attr.key(), attr.value());
+    }
+}
 
-MenuList cancelDiscoveryMenu = {
-    DECLARE_MENU(cancelDiscovery, selectResource, &resourceMenu),
-    { "quit" }
-};
+void print(const std::string& name, const std::vector< std::string >& elements)
+{
+    if (elements.empty())
+    {
+       std::cout << "\t" << name << " is empty" << std::endl;
+       return;
+    }
 
-MenuList discoveryMenu = {
-    DECLARE_MENU(discoverResource, nullptr, &cancelDiscoveryMenu),
-    { "quit" }
-};
+    std::cout << "\t" << name << " : " << std::endl;
+    for(const auto& item : elements)
+    {
+        std::cout << item << " ";
+    }
+    std::cout << std::endl;
+}
+
+void printUri(const std::string& uri)
+{
+    if(uri.empty())
+    {
+        std::cout << "\turi is empty" << std::endl;
+    }
+    else
+    {
+        std::cout << "\turi : " << uri << std::endl;
+    }
+}
 
-void onResourceDiscovered(std::shared_ptr<RCSRemoteResourceObject> discoveredResource)
+void printRepresentation(const RCSRepresentation& rep)
 {
-    std::cout << "onResourceDiscovered callback :: " << std::endl;
+    printUri(rep.getUri());
+    print("interfaces", rep.getInterfaces());
+    print("resourceTypes", rep.getResourceTypes());
+    printAttributes(rep.getAttributes());
 
-    std::cout << "resourceURI : " << discoveredResource->getUri() << std::endl;
-    std::cout << "hostAddress : " << discoveredResource->getAddress() << std::endl;
+    const auto& children = rep.getChildren();
 
-    resourceList.push_back(discoveredResource);
+    if(children.empty())
+    {
+        std::cout << "\tchildren is empty" << std::endl;
+    }
+    else
+    {
+        int cnt = 0;
+        for(const auto& child : children)
+        {
+            std::cout << "========================================================" << std::endl;
+            std::cout << ++cnt << " chlid" << std::endl;
+            printRepresentation(child);
+            std::cout << "========================================================" << std::endl;
+        }
+    }
 }
 
-void onResourceStateChanged(const ResourceState& resourceState)
+void onResourceStateChanged(ResourceState resourceState)
 {
     std::cout << "onResourceStateChanged callback" << std::endl;
 
@@ -218,62 +278,80 @@ void onRemoteAttributesReceived(const RCSResourceAttributes& attributes, int)
     printAttributes(attributes);
 }
 
+void onRemoteGetReceived(const HeaderOpts&, const RCSRepresentation& rep, int)
+{
+    std::cout << "onRemoteGetReceived callback" << std::endl;
+
+    printRepresentation(rep);
+}
+
+void onRemoteSetReceived(const HeaderOpts&, const RCSRepresentation& rep, int)
+{
+    std::cout << "onRemoteSetReceived callback" << std::endl;
+
+    printRepresentation(rep);
+}
+
 void startMonitoring()
 {
-    if (!selectedResource->isMonitoring())
-    {
-        selectedResource->startMonitoring(&onResourceStateChanged);
-        std::cout << "\tHosting Started..." << std::endl;
-    }
-    else
+    if (g_selectedResource->isMonitoring())
     {
         std::cout << "\tAlready Started..." << std::endl;
+        return;
     }
+
+    g_selectedResource->startMonitoring(&onResourceStateChanged);
+    std::cout << "\tMonitoring Started..." << std::endl;
 }
 
 void stopMonitoring()
 {
-    if (selectedResource->isMonitoring())
+    if (!g_selectedResource->isMonitoring())
     {
-        selectedResource->stopMonitoring();
-        std::cout << "\tHosting stopped..." << std::endl;
-    }
-    else
-    {
-       std::cout << "\tHosting not started..." << std::endl;
+        std::cout << "\tMonitoring not started..." << std::endl;
+        return;
     }
+
+    g_selectedResource->stopMonitoring();
+    std::cout << "\tMonitoring stopped..." << std::endl;
 }
 
-void getAttributeFromRemoteServer()
+void getRemoteAttributes()
 {
-    selectedResource->getRemoteAttributes(&onRemoteAttributesReceived);
+    g_selectedResource->getRemoteAttributes(onRemoteAttributesReceived);
 }
 
-void setAttributeToRemoteServer()
+void setRemoteAttributes()
 {
-    std::string key;
-    RCSResourceAttributes setAttribute;
+    g_selectedResource->setRemoteAttributes(inputKeyValue(), onRemoteAttributesReceived);
+}
 
-    std::cout << "\tEnter the Key you want to set : ";
-    std::cin >> key;
-    std::cout << "\tEnter the value(INT) you want to set :";
+void getWithInterface()
+{
+    RCSQueryParams queryParams;
+    queryParams.setResourceInterface(inputInterface());
+
+    g_selectedResource->get(queryParams, onRemoteGetReceived);
+}
+
+void setWithInterface()
+{
+    RCSQueryParams queryParams;
+    queryParams.setResourceInterface(inputInterface());
 
-    setAttribute[key] = processUserInput();
-    selectedResource->setRemoteAttributes(setAttribute,
-                                  &onRemoteAttributesReceived);
+    g_selectedResource->set(queryParams, inputKeyValue(), onRemoteSetReceived);
 }
 
 void startCaching(RCSRemoteResourceObject::CacheUpdatedCallback cb)
 {
-    if (!selectedResource->isCaching())
-    {
-        selectedResource->startCaching(std::move(cb));
-        std::cout << "\tCaching Started..." << std::endl;
-    }
-    else
+    if (g_selectedResource->isCaching())
     {
         std::cout << "\tAlready Started Caching..." << std::endl;
+        return;
     }
+
+    g_selectedResource->startCaching(std::move(cb));
+    std::cout << "\tCaching Started..." << std::endl;
 }
 
 void startCachingWithoutCallback()
@@ -288,7 +366,7 @@ void startCachingWithCallback()
 
 void getResourceCacheState()
 {
-    switch(selectedResource->getCacheState())
+    switch(g_selectedResource->getCacheState())
     {
         case CacheState::READY:
             std::cout << "\tCurrent Cache State : CACHE_STATE::READY" << std::endl;
@@ -310,102 +388,50 @@ void getResourceCacheState()
 
 void getCachedAttributes()
 {
-    try
-    {
-        printAttributes(selectedResource->getCachedAttributes());
-    }
-    catch (const RCSBadRequestException& e)
-    {
-        std::cout << "Exception in getCachedAttributes : " << e.what() << std::endl;
-    }
+    printAttributes(g_selectedResource->getCachedAttributes());
 }
 
 void getCachedAttribute()
 {
-    try
-    {
-        std::cout << "\tkey : " << defaultKey << std::endl
-                  << "\tvalue : " << selectedResource->getCachedAttribute(defaultKey).get< int >()
-                  << std::endl;
-    }
-    catch (const RCSBadRequestException& e)
-    {
-        std::cout << "Exception in getCachedAttribute : " << e.what() << std::endl;
-    }
-    catch (const RCSBadGetException& e)
-    {
-        std::cout << "Exception in getCachedAttribute : " << e.what() << std::endl;
-    }
+    printAttribute(g_attrKey, g_selectedResource->getCachedAttribute(g_attrKey));
 }
 
 void stopCaching()
 {
-    if(selectedResource->isCaching())
-    {
-        selectedResource->stopCaching();
-        std::cout << "\tCaching stopped..." << std::endl;
-    }
-    else
+    if(!g_selectedResource->isCaching())
     {
         std::cout << "\tCaching not started..." << std::endl;
+        return;
     }
-}
-
-void platFormConfigure()
-{
-    PlatformConfig config
-    {
-        OC::ServiceType::InProc, ModeType::Client, "0.0.0.0", 0, OC::QualityOfService::LowQos
-    };
-    OCPlatform::Configure(config);
-}
 
-int processUserInput()
-{
-    int userInput;
-
-    while(true)
-    {
-        std::cin >> userInput;
-        if (std::cin.fail())
-        {
-            std::cin.clear();
-            std::cin.ignore(std::numeric_limits<std::streamsize>::max(), '\n');
-            std::cout << "Invalid Input, please try again" << std::endl;
-        }
-        else break;
-    }
-    return userInput;
+    g_selectedResource->stopCaching();
+    std::cout << "\tCaching stopped..." << std::endl;
 }
 
-bool selectResourceType(std::string& resourceType)
+std::string selectResourceType()
 {
     std::cout << "========================================================" << std::endl;
     std::cout << "1. Temperature Resource Discovery" << std::endl;
     std::cout << "2. Light Resource Discovery" << std::endl;
     std::cout << "========================================================" << std::endl;
 
-    switch (processUserInput())
+    switch (processUserInput(RESOURCE_TEMP, RESOURCE_LIGHT))
     {
-    case REQUEST_TEMP:
-        resourceType = TEMP;
-        defaultKey = "Temperature";
-        return true;
-    case REQUEST_LIGHT:
-        resourceType = LIGHT;
-        defaultKey = "Brightness";
-        return true;
-    default :
-        std::cout << "Invalid input, please try again" << std::endl;
-        return false;
+    case RESOURCE_TEMP:
+        g_attrKey = "Temperature";
+        return RESOURCE_TYPE_TEMP;
+    case RESOURCE_LIGHT:
+        g_attrKey = "Brightness";
+        return RESOURCE_TYPE_LIGHT;
     }
+
+    throw std::logic_error("unreachable");
 }
 
 RCSAddress inputAddress()
 {
     std::cout << "========================================================" << std::endl;
-    std::cout << "Please input address" << std::endl;
-    std::cout << "(default is multicast. when you want to use unicast, input address" << std::endl;
+    std::cout << "Please input address (empty for multicast)" << std::endl;
     std::cout << "========================================================" << std::endl;
 
     std::string address;
@@ -415,96 +441,111 @@ RCSAddress inputAddress()
     return address.empty() ? RCSAddress::multicast() : RCSAddress::unicast(address);
 }
 
-void discoverResource()
+void printDiscoveryInProgress()
 {
-    std::string resourceType = "";
-
-    while(!selectResourceType(resourceType)) {}
-
-    while(!discoveryTask)
-    {
-        try
-        {
-            discoveryTask = RCSDiscoveryManager::getInstance()->discoverResourceByType(
-                    inputAddress(), resourceType, &onResourceDiscovered);
-        }
-        catch (const RCSPlatformException& e)
-        {
-            std::cout << e.what() << std::endl;
-        }
-    }
+    std::cout << "Discovery in progress, press '1' to stop." << std::endl;
 }
 
-void displayResourceList()
+void discoverResource()
 {
-    int cnt = 1;
-    for(const auto& resource : resourceList)
+    auto onResourceDiscovered = [](
+            const RCSRemoteResourceObject::Ptr& discoveredResource)
     {
-        std::cout << cnt++ << ".\tresourceURI : " << resource->getUri() << std::endl <<
-                              "\thostAddress : " << resource->getAddress() << std::endl;
-    }
-}
+        std::cout << "onResourceDiscovered callback :: " << std::endl;
 
-void selectResource()
-{
-    displayResourceList();
+        std::cout << "uri : " << discoveredResource->getUri() << std::endl;
+        std::cout << "host address : " << discoveredResource->getAddress() << std::endl;
+
+        g_discoveredResources.push_back(discoveredResource);
+
+        printDiscoveryInProgress();
+    };
 
-    std::cout << "select Resource..." << std::endl;
+    auto resourceType = selectResourceType();
+    auto address = inputAddress();
 
-    selectedResource = resourceList[processUserInput()-1];
+    printDiscoveryInProgress();
 
-    resourceList.clear();
+    auto discoveryTask = RCSDiscoveryManager::getInstance()->discoverResourceByType(address,
+            resourceType, onResourceDiscovered);
+
+    while(processUserInput() != 1);
+
+    discoveryTask->cancel();
 }
 
-void cancelDiscovery()
+void runResourceControl()
 {
-    if(!discoveryTask)
-    {
-        std::cout << "There is no discovery request..." << std::endl;
-        return;
-    }
-    discoveryTask->cancel();
+    static std::vector<MenuItem> resourceMenuItems {
+        DECLARE_MENU(startMonitoring),
+        DECLARE_MENU(stopMonitoring),
+        DECLARE_MENU(getRemoteAttributes),
+        DECLARE_MENU(setRemoteAttributes),
+        DECLARE_MENU(getWithInterface),
+        DECLARE_MENU(setWithInterface),
+        DECLARE_MENU(startCachingWithoutCallback),
+        DECLARE_MENU(startCachingWithCallback),
+        DECLARE_MENU(getResourceCacheState),
+        DECLARE_MENU(getCachedAttributes),
+        DECLARE_MENU(getCachedAttribute),
+        DECLARE_MENU(stopCaching),
+    };
+
+    handleItems(resourceMenuItems);
 }
 
-void printAttribute(const std::string key, const RCSResourceAttributes::Value& value)
+void runResourceSelection()
 {
-    std::cout << "\tkey : " << key << std::endl
-              << "\tvalue : " << value.toString() << std::endl;
+    handleItems(g_discoveredResources);
+
+    g_currentRun = runResourceControl;
 }
 
-void printAttributes(const RCSResourceAttributes& attributes)
+void runDiscovery()
 {
-    if (attributes.empty())
-    {
-       std::cout << "\tattributes is empty" << std::endl;
-    }
-    for(const auto& attr : attributes)
+    static std::vector<MenuItem> discoveryMenuItems {
+        DECLARE_MENU(discoverResource),
+    };
+
+    handleItems(discoveryMenuItems);
+
+    if (g_discoveredResources.empty()) throw std::runtime_error("No resource found!");
+
+    g_currentRun = runResourceSelection;
+}
+
+void configurePlatform()
+{
+    PlatformConfig config
     {
-        printAttribute(attr.key(), attr.value());
-    }
+        OC::ServiceType::InProc, ModeType::Client, "0.0.0.0", 0, OC::QualityOfService::LowQos
+    };
+    OCPlatform::Configure(config);
 }
 
 int main()
 {
-    platFormConfigure();
+    configurePlatform();
 
-    currentMenuList = &discoveryMenu;
+    g_currentRun = runDiscovery;
 
-    try
+    while (true)
     {
-        while(currentMenuList)
+        try
         {
-            currentMenuList->display();
-
-            currentMenuList = currentMenuList->select();
+            g_currentRun();
+        }
+        catch (const std::exception& e)
+        {
+            std::cout << e.what() << std::endl;
+        }
+        catch (const CloseApp&)
+        {
+            break;
         }
-    }
-    catch (const std::exception& e)
-    {
-        std::cout << "main exception : " << e.what() << std::endl;
     }
 
-    std::cout << "Stopping the Client" << std::endl;
+    std::cout << "Stopping the client" << std::endl;
 
     return 0;
 }