-.device
\ No newline at end of file
+.device-agent
\ No newline at end of file
/**
* @brief NM_getDeviceReport get report for specified device
- * @param dev_list [in] handle to device list containing this device
* @param dev_id [in] device id
* @param report [out] pointer to buffer whith report data (as ASCII-Z)
* @return error code
*/
-//NM_ErrorCode NM_getDeviceReport(NM_hDeviceList dev_list, const char* dev_id, char** report);
+NM_ErrorCode NM_getDeviceReport(NM_hContext ctx, const char* dev_id, char** report);
/**
* @brief NM_freeCharBuffer free memory
* @param report [out] pointer to buffer
*/
-//void NM_freeCharBuffer(char** buffer);
+void NM_freeCharBuffer(char* buffer);
/**
* @brief NM_getDeviceReport get policy for specified device
LOG_E(TAG, "Unsubscribe notifications error: %s", e.what());
}
}
+
+
+NM_ErrorCode NM_getDeviceReport(NM_hContext ctx, const char* dev_id, char** report)
+{
+ if (ctx == nullptr) return EC_NULL_POINTER;
+
+ try
+ {
+ *report = nullptr;
+ std::string result = ctx->instance->getDeviceReport(dev_id);
+ if (!result.empty())
+ {
+ *report = new char[result.length() + 1];
+ (*report)[result.length()] = '\0';
+ result.copy(*report, result.length());
+ }
+ }
+ catch(NMexception& e)
+ {
+ LOG_E(TAG, "Get device report error: %s, error code %d", e.what(), e.errorCode());
+ return static_cast<NM_ErrorCode>(e.errorCode());
+ }
+ catch (std::exception& e)
+ {
+ LOG_E(TAG, "Get device report error: %s", e.what());
+ return EC_INTERNAL_ERROR;
+ }
+
+ return EC_OK;
+}
+
+void NM_freeCharBuffer(char* buffer)
+{
+ if (buffer != nullptr) delete[] buffer;
+}
* @brief getDeviceID returns device id (DUID) from iotivity persistant storage
* @return string that indicates duid
*/
- std::string getDeviceID();
+ const std::string& getDeviceID();
/**
* @brief subscribeNotifications subscribes to secure server notifications
*/
std::string getPersistentStoragePath();
+ /**
+ * @brief getDeviceReport return report for specified device
+ * @param uuid [in] device identifier
+ * @return report in JSON format or throw exception on error
+ */
+ std::string getDeviceReport(const std::string& uuid);
+
+ /**
+ * @brief postReport Post report to server. Used in IoTivity for test puposes
+ * @param report [in] report in JSON format
+ */
+ void postReport(const std::string& report);
+
private:
void guardUnauthorized();
--- /dev/null
+#ifndef REPORT_CLIENT_H
+#define REPORT_CLIENT_H
+
+#include <string>
+#include <memory>
+#include <mutex>
+#include <condition_variable>
+#include <OCApi.h>
+#include <OCPlatform.h>
+
+namespace NetworkManager
+{
+
+class ReportClient
+{
+ std::shared_ptr<OC::OCResource> resource;
+ std::mutex report_mutex;
+ std::condition_variable signal;
+public:
+ ReportClient(const std::string& host);
+
+ operator bool() const;
+
+ std::string getReport(const OC::QueryParamsMap& params);
+
+ void postReport(const std::string& report);
+private:
+ void foundResourceCb(std::shared_ptr<OC::OCResource> found_resource);
+
+ void onReportObserveCb(const OC::HeaderOptions options, const OC::OCRepresentation& rep,
+ const int& eCode, const int& sequenceNumber);
+};
+
+} // namespace NetworkManager
+
+
+#endif // REPORT_CLIENT_H
#include <functional>
#include <thread>
#include <chrono>
+#include <sstream>
+#include <iomanip>
#include "nmlib.h"
+#include "report_client.h"
#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Wreorder"
PresenceHook presence_hook;
std::mutex owned_mutex;
std::shared_ptr<OCResource> notificationResource;
+ std::shared_ptr<ReportClient> reportClient;
+ std::string device_id;
std::mutex notificationMtx;
};
return signedIn;
}
-string IoTivity::getDeviceID()
+const string& IoTivity::getDeviceID()
{
- OCUUIdentity deviceId;
- guardErrorCode(OC::OCPlatform::getDeviceId(&deviceId), "OCPlatform::getDeviceId()");
-
- char s[128];
- unsigned char *id = deviceId.id;
-
- snprintf(s, sizeof(s), "%02x%02x%02x%02x-%02x%02x-%02x%02x-%02x%02x-%02x%02x%02x%02x%02x%02x",
- id[0], id[1], id[2], id[3],
- id[4], id[5], id[6], id[7],
- id[8], id[9], id[10], id[11],
- id[12], id[13], id[14], id[15]);
+ if (params->device_id.empty())
+ {
+ OCUUIdentity deviceId;
+ if (OC_STACK_OK == OC::OCPlatform::getDeviceId(&deviceId))
+ {
+ unsigned char* id = deviceId.id;
+ ostringstream os;
+ os << hex << setfill('0');
+ os << setw(2) << (unsigned)id[0];
+ os << setw(2) << (unsigned)id[1];
+ os << setw(2) << (unsigned)id[2];
+ os << setw(2) << (unsigned)id[3] << '-';
+
+ os << setw(2) << (unsigned)id[4];
+ os << setw(2) << (unsigned)id[5] << '-';
+
+ os << setw(2) << (unsigned)id[6];
+ os << setw(2) << (unsigned)id[7] << '-';
+
+ os << setw(2) << (unsigned)id[8];
+ os << setw(2) << (unsigned)id[9] << '-';
+
+ os << setw(2) << (unsigned)id[10];
+ os << setw(2) << (unsigned)id[11];
+ os << setw(2) << (unsigned)id[12];
+ os << setw(2) << (unsigned)id[13];
+ os << setw(2) << (unsigned)id[14];
+ os << setw(2) << (unsigned)id[15];
+ params->device_id = os.str();
+ }
+ }
- return string(s);
+ return params->device_id;
}
}
}
+std::string IoTivity::getDeviceReport(const std::string& uuid)
+{
+ if (!params->reportClient)
+ {
+ params->reportClient = make_shared<ReportClient>(oAuthCred.host);
+ }
+
+ if (!bool(*(params->reportClient)))
+ {
+ LOG_E(TAG, "Report resource not found");
+ params->reportClient.reset();
+ throw IoTInternalError("Report resource not found");
+ }
+
+ QueryParamsMap qp{{"did", uuid}};
+
+ return params->reportClient->getReport(qp);
+}
+
+void IoTivity::postReport(const std::string& report)
+{
+ if (!params->reportClient)
+ {
+ params->reportClient = make_shared<ReportClient>(oAuthCred.host);
+ }
+
+ if (!bool(*(params->reportClient)))
+ {
+ LOG_E(TAG, "Report resource not found");
+ params->reportClient.reset();
+ throw IoTInternalError("Report resource not found");
+ }
+
+ params->reportClient->postReport(report);
+}
+
void IoTivity::setPersistentStoragePath(std::string newPath)
{
persistentStoragePath = newPath;
--- /dev/null
+
+#include "report_client.h"
+#include "logging.h"
+#include <functional>
+#include <chrono>
+#include "iotivity.h"
+
+using namespace OC;
+
+namespace PH = std::placeholders;
+
+#define TAG "NetworkManager"
+
+namespace NetworkManager
+{
+
+ReportClient::ReportClient(const std::string& host)
+{
+ std::string requestURI{OC_RSRVD_WELL_KNOWN_URI};
+ std::unique_lock<std::mutex> lock(report_mutex);
+ OCPlatform::findResource(host, requestURI, CT_DEFAULT, std::bind(&ReportClient::foundResourceCb, this, PH::_1));
+ signal.wait_for(lock, std::chrono::seconds(3));
+}
+
+ReportClient::operator bool() const
+{
+ return (bool)resource;
+}
+
+std::string ReportClient::getReport(const QueryParamsMap& query)
+{
+ std::string report;
+ std::unique_lock<std::mutex> lock(report_mutex);
+
+ if(resource)
+ {
+ resource->get(query, [this, &report](const HeaderOptions& hopts, const OCRepresentation& rep, const int eCode)
+ {
+ try
+ {
+ if(eCode == OC_STACK_OK)
+ {
+ rep.getValue("report", report);
+ }
+ else
+ {
+ LOG_E(TAG, "Error (ReportClient::getReport): code=%d", eCode);
+ }
+ }
+ catch(std::exception& e)
+ {
+ LOG_E(TAG, "Exception (ReportClient::getReport): %s", e.what());
+ }
+
+ signal.notify_one();
+ });
+ }
+
+ signal.wait_for(lock, std::chrono::seconds(1));
+
+ return report;
+}
+
+void ReportClient::postReport(const std::string& report)
+{
+ if (!resource)
+ {
+ LOG_E(TAG, "Resource not found");
+ return;
+ }
+
+ OCRepresentation repr;
+ repr.setValue("report", report);
+
+ QueryParamsMap query{{"did", IoTivity::getInstance()->getDeviceID()}};
+
+ std::unique_lock<std::mutex> lock(report_mutex);
+
+ resource->post("core.security", DEFAULT_INTERFACE, repr, query,
+ [this] (const HeaderOptions & /*ho*/, const OCRepresentation &rep, const int eCode)
+ {
+ LOG_I(TAG, "post report return code=%d", eCode);
+ signal.notify_one();
+ }
+ );
+
+ signal.wait_for(lock, std::chrono::seconds(1));
+}
+
+void ReportClient::foundResourceCb(std::shared_ptr<OCResource> found_resource)
+{
+ try
+ {
+ std::unique_lock<std::mutex> lock(report_mutex);
+
+ if(!resource && found_resource)
+ {
+ for(auto &resource_type : found_resource->getResourceTypes())
+ {
+ if(resource_type == "core.security")
+ {
+ if (found_resource->connectivityType() & OCConnectivityType::CT_ADAPTER_TCP)
+ {
+ resource = found_resource;
+ LOG_I(TAG, "Address of selected report resource: %s", found_resource->host().c_str());
+ signal.notify_one();
+ }
+ }
+ }
+ }
+
+ }
+ catch(std::exception& e)
+ {
+ LOG_E(TAG, "Exception in foundResource: %s", e.what());
+ }
+}
+
+void ReportClient::onReportObserveCb(const HeaderOptions /*headerOptions*/, const OCRepresentation& rep,
+ const int& eCode, const int& sequenceNumber)
+{
+ try
+ {
+ if(eCode == OC_STACK_OK && sequenceNumber <= MAX_SEQUENCE_NUMBER)
+ {
+ if(sequenceNumber == OC_OBSERVE_REGISTER)
+ {
+ LOG_I(TAG, "Observe registration action is successful");
+ }
+ }
+ else
+ {
+ if(eCode == OC_STACK_OK)
+ {
+ LOG_D(TAG, "Observe registration failed");
+ }
+ else
+ {
+ LOG_E(TAG, "Observe response error: %d", eCode);
+ }
+ }
+ }
+ catch(std::exception& e)
+ {
+ LOG_E(TAG, "Observe exception: %s", e.what());
+ }
+
+}
+
+} // namespace NetworkManager
set(app ${ProjectId})
file(GLOB SRCS *.cpp)
+pkg_check_modules(REQUIRED sqlite3 jsoncpp)
+
include_directories(
../iotivity_lib/inc
../ctrl_app_lib/inc
add_executable(${app} ${SRCS})
target_link_libraries(${app}
${IOTIVITY_LIB_PROJECT_NAME}
+ sqlite3
+ jsoncpp
)
install(TARGETS ${app} DESTINATION ${TESTS_DIR})
--- /dev/null
+#ifndef MACRO_H
+#define MACRO_H
+
+#define STRINGIZE(x) STRINGIZE2(x)
+#define STRINGIZE2(x) #x
+
+#endif // MACRO_H
--- /dev/null
+#include "sqlitedb.h"
+#include "report.h"
+#include "macro.h"
+#include <stdexcept>
+
+using namespace std;
+
+Report::Report()
+ : pk(-1)
+ , did("")
+ , name("")
+ , date("")
+ , data("")
+ , result(0)
+ , modified(false)
+{
+
+}
+
+Report::Report(const string& id, const string& name, const string& date, const string& report, int result)
+ : pk(-1)
+ , did(id)
+ , name(name)
+ , date(date)
+ , data(report)
+ , result(result)
+ , modified(false)
+{
+
+}
+
+void Report::registerModel()
+{
+ ostringstream os;
+ os << "CREATE TABLE IF NOT EXISTS " << Report::TABLE_NAME
+ << "(id INTEGER PRIMARY KEY AUTOINCREMENT,"
+ << "did CHAR(36) NOT NULL,"
+ << "name CHAR(32) NOT NULL,"
+ << "date CHAR(32) NOT NULL,"
+ << "data TEXT NOT NULL,"
+ << "result INTEGER);";
+ SQLiteDB::inst().exec(os.str(), &selecter, nullptr);
+}
+
+void Report::save()
+{
+ if (pk == -1)
+ {
+ ostringstream os;
+ os << "INSERT INTO " << TABLE_NAME << " (did,name,date,data,result) "
+ << "VALUES ('" << did << "', '" << name << "', '" << date << "', '"
+ << data << "', " << result << ");";
+ SQLiteDB::inst().exec(os.str(), &selecter, nullptr);
+ pk = SQLiteDB::inst().last_row_id();
+ }
+ else if (modified)
+ {
+ ostringstream os;
+ os << "UPDATE " << TABLE_NAME << " set did = '" << did
+ << "', name = '" << name
+ << "', date = '" << date
+ << "', data = '" << data
+ << "', result = " << result
+ << " WHERE id=" << pk << ";";
+ SQLiteDB::inst().exec(os.str(), &selecter, nullptr);
+ }
+ modified = false;
+}
+
+SelectQuery<Report> Report::get()
+{
+ SelectQuery<Report> q(&selecter);
+ return q;
+}
+
+void Report::setDid(const string& new_id)
+{
+ if (did != new_id)
+ {
+ did = new_id;
+ modified = true;
+ }
+}
+
+void Report::setName(const string& new_name)
+{
+ if (name != new_name)
+ {
+ name = new_name;
+ modified = true;
+ }
+}
+
+void Report::setDate(const string& new_date)
+{
+ if (date != new_date)
+ {
+ date = new_date;
+ modified = true;
+ }
+}
+
+void Report::setData(const string& new_report)
+{
+ if (data != new_report)
+ {
+ data = new_report;
+ modified = true;
+ }
+}
+
+void Report::setResult(int new_result)
+{
+ if (result != new_result)
+ {
+ result = new_result;
+ modified = true;
+ }
+}
+
+int Report::selecter(void* data, int argc, char **argv, char **col_name)
+{
+ if (data == nullptr) return 0;
+ vector<Report>* v = reinterpret_cast<vector<Report>*>(data);
+
+ if (argc != 6) throw logic_error("Wrong \"Report\" table format");
+
+ Report r;
+
+ for(int i = 0; i < argc; i++)
+ {
+
+ const char* arg = argv[i] == nullptr ? "" : argv[i];
+
+ if (r.pk_name == col_name[i])
+ {
+ r.pk = stol(arg);
+ }
+ else if (r.did_name == col_name[i])
+ {
+ r.did = arg;
+ }
+ else if (r.name_name == col_name[i])
+ {
+ r.name = arg;
+ }
+ else if (r.date_name == col_name[i])
+ {
+ r.date = arg;
+ }
+ else if (r.data_name == col_name[i])
+ {
+ r.data = arg;
+ }
+ else if (r.result_name == col_name[i])
+ {
+ r.result = stoi(arg);
+ }
+ else
+ {
+ throw logic_error(string{"Unknown column name: "} + col_name[i]);
+ }
+ }
+
+ v->push_back(r);
+
+ return 0;
+}
+
+const string Report::TABLE_NAME{STRINGIZE(Report) "s"};
+
+ostream& operator << (ostream& os, const Report& r)
+{
+ os << "[Report]" << endl
+ << "\tdid: " << r.did << endl
+ << "\tname: " << r.name << endl
+ << "\tdate: " << r.date << endl
+ << "\tdata: " << r.data << endl
+ << "\tresult: " << r.result;
+ return os;
+}
--- /dev/null
+#ifndef REPORT_H
+#define REPORT_H
+
+#include "selectquery.h"
+
+class Report
+{
+public:
+ static const std::string TABLE_NAME;
+
+ Report();
+
+ Report(const std::string& id, const std::string& name, const std::string& date, const std::string& data, int result);
+
+ static void registerModel();
+
+ void save();
+
+ static SelectQuery<Report> get();
+
+ void setDid(const std::string& new_id);
+
+ void setName(const std::string& new_name);
+
+ void setDate(const std::string& new_date);
+
+ void setData(const std::string& new_data);
+
+ void setResult(int new_result);
+
+ const std::string& getDid() const
+ {
+ return did;
+ }
+
+ const std::string& getName() const
+ {
+ return name;
+ }
+
+ const std::string& getDate() const
+ {
+ return date;
+ }
+
+ const std::string& getData() const
+ {
+ return data;
+ }
+
+ int getResult() const
+ {
+ return result;
+ }
+
+ friend std::ostream& operator << (std::ostream&, const Report&);
+
+private:
+ static int selecter(void* data, int argc, char **argv, char **col_name);
+
+ long long pk;
+ std::string did;
+ std::string name;
+ std::string date;
+ std::string data;
+ int result;
+ bool modified;
+
+ const std::string pk_name{"id"};
+ const std::string did_name{"did"};
+ const std::string name_name{"name"};
+ const std::string date_name{"date"};
+ const std::string data_name{"data"};
+ const std::string result_name{"result"};
+};
+
+#endif // REPORT_H
--- /dev/null
+/**
+ * @brief Server report reasource
+ * @date Created 17.05.2017
+ * @author Created 2017 in Samsung Ukraine R&D Center (SURC) under a contract
+ * between LLC "Samsung Electronics Ukraine Company" (Kiev, Ukraine)
+ * and "Samsung Electronics Co", Ltd (Seoul, Republic of Korea).
+ * Copyright: (c) Samsung Electronics Co, Ltd 2017. All rights reserved.
+ * @author Mail to: <A HREF="mailto:d.lomtev@samsung.com">Dmytro Lomtev, d.lomtev@samsung.com</A>
+ */
+
+#include <functional>
+//#include <mutex>
+#include <vector>
+#include <memory>
+#include "OCPlatform.h"
+#include "OCApi.h"
+#include "report_resource.h"
+#include "sqlitedb.h"
+#include "report.h"
+#include <stdexcept>
+#include <jsoncpp/json/reader.h>
+
+using namespace OC;
+using namespace std;
+namespace PH = std::placeholders;
+
+void sql_test()
+{
+ try
+ {
+ Report::registerModel();
+ Report r1{"9b5287b3-fe92-46fc-a924-488d2339c2ba", "sim", "17-05-2017 05:32:30", "Alert! Alles caput!", 3};
+ Report r2{"11223344-fe92-46fc-a924-488d2339c2ba", "alert", "17-05-2017 05:32:30", "Deus vult", 77};
+ Report r3{"00000000-fe92-46fc-a924-488d2339c2ba", "sim", "17-05-2017 05:32:30", "Spartaaaaa!", 0};
+ r1.save();
+ r2.save();
+ r3.save();
+
+ auto v = Report::get().filter("name", "sim").all();
+
+ cout << "SELECT 1 returned " << v.size() << " records" << endl;
+ int i = 1;
+
+ for (auto rec : v)
+ {
+ cout << "#" << i++ << endl << rec << endl;
+ }
+
+ v = Report::get().all();
+
+ cout << "SELECT 2 returned " << v.size() << " records" << endl;
+ i = 1;
+
+ for (auto rec : v)
+ {
+ cout << "#" << i++ << endl << rec << endl;
+ }
+
+ v = Report::get().filter("did", "00000000-fe92-46fc-a924-488d2339c2ba").filter("name", "sim").filter("result", 0).all();
+
+ cout << "SELECT 3 returned " << v.size() << " records" << endl;
+ i = 1;
+
+ for (auto rec : v)
+ {
+ cout << "#" << i++ << endl << rec << endl;
+ }
+ }
+ catch (exception& e)
+ {
+ cout << "SQLite test Exception: " << e.what() << endl;
+ }
+}
+
+
+ReportResource::ReportResource()
+ : m_reportUri("/a/report"), m_resourceHandle(nullptr)
+{
+ m_reportRep.setValue("report", "");
+ Report::registerModel();
+ Report r1{"9b5287b3-fe92-46fc-a924-488d2339c2ba", "sim", "17-05-2017 05:32:30", "Alert! Alles caput!", 3};
+ Report r2{"11223344-fe92-46fc-a924-488d2339c2ba", "alert", "17-05-2017 05:32:30", "Deus vult", 77};
+ Report r3{"9b5287b3-fe92-46fc-a924-488d2339c2ba", "sim", "17-05-2017 05:32:30", "Spartaaaaa!", 0};
+ r1.save();
+ r2.save();
+ r3.save();
+}
+
+void ReportResource::registerResource()
+{
+ string resourceTypeName = "core.security";
+
+ uint8_t resourceProperty = OC_DISCOVERABLE | OC_OBSERVABLE;
+
+ EntityHandler cb = std::bind(&ReportResource::entityHandler, this,PH::_1);
+
+ OCStackResult result = OCPlatform::registerResource(
+ m_resourceHandle, m_reportUri, resourceTypeName,
+ DEFAULT_INTERFACE, cb, resourceProperty);
+
+ if (OC_STACK_OK != result)
+ {
+ cout << "Security Resource creation was unsuccessful\n";
+ }
+ else
+ {
+ cout << "Report resource created\n";
+ }
+}
+
+OCResourceHandle ReportResource::getHandle()
+{
+ return m_resourceHandle;
+}
+
+Json::Value reportAsJson(const Report& r)
+{
+ Json::Value report;
+ report["did"] = r.getDid();
+ report["name"] = r.getName();
+ report["date"] = r.getDate();
+ report["data"] = r.getData();
+ report["result"] = r.getResult();
+ return report;
+}
+
+OCRepresentation ReportResource::get()
+{
+ cout << "IN > ReportResource::get()" <<endl;
+ auto records = Report::get().all();
+ Json::Value root;
+
+ for (auto r : records)
+ {
+ root.append(reportAsJson(r));
+ }
+
+ m_reportRep.setValue("report", root.toStyledString());
+ return m_reportRep;
+}
+
+OCRepresentation ReportResource::get(const QueryParamsMap& params)
+{
+ cout << "IN > ReportResource::get(const QueryParamsMap& params)" <<endl;
+ auto query = Report::get();
+
+ for (auto p: params)
+ {
+ cout << p.first << ": " << p.second <<endl;
+ query.filter(p.first, p.second);
+ }
+
+ auto records = query.all();
+
+ Json::Value root;
+
+ for (auto r : records)
+ {
+ root.append(reportAsJson(r));
+ }
+
+ if (records.empty())
+ {
+ m_reportRep.setValue("report", "");
+ }
+ else
+ {
+ m_reportRep.setValue("report", root.toStyledString());
+ }
+ return m_reportRep;
+}
+
+OCEntityHandlerResult ReportResource::entityHandler(std::shared_ptr<OCResourceRequest> request)
+{
+ OCEntityHandlerResult ehResult = OC_EH_ERROR;
+
+ if(request)
+ {
+ std::string requestType = request->getRequestType();
+ int requestFlag = request->getRequestHandlerFlag();
+
+ if(requestFlag & RequestHandlerFlag::RequestFlag)
+ {
+ auto pResponse = make_shared<OC::OCResourceResponse>();
+ pResponse->setRequestHandle(request->getRequestHandle());
+ pResponse->setResourceHandle(request->getResourceHandle());
+
+ if(requestType == "GET")
+ {
+ QueryParamsMap queries = request->getQueryParameters();
+ pResponse->setErrorCode(200);
+ pResponse->setResponseResult(OC_EH_OK);
+ pResponse->setResourceRepresentation(get(queries));
+ if(OC_STACK_OK == OCPlatform::sendResponse(pResponse))
+ {
+ ehResult = OC_EH_OK;
+ }
+
+ }
+ else if(requestType == "PUT")
+ {
+ pResponse->setErrorCode(403);
+
+ if(OC_STACK_OK == OCPlatform::sendResponse(pResponse))
+ {
+ ehResult = OC_EH_OK;
+ }
+ }
+ else if(requestType == "POST")
+ {
+ const auto& rep = request->getResourceRepresentation();
+ std::string new_report;
+
+ int rcode = 400;
+
+ if (rep.getValue("report", new_report))
+ {
+ rcode = 200;
+ Json::Value root;
+ Json::Reader reader;
+
+ std::cout << "[Report]" << std::endl << new_report << std::endl;
+
+ if (!reader.parse(new_report, root))
+ {
+ std::cout << "[ERROR] Wrong report format" << std::endl;
+ rcode = 400;
+ }
+ else
+ {
+ QueryParamsMap qm = request->getQueryParameters();
+ std::cout << "Query parameters:" << std::endl;
+
+ for (auto q : qm)
+ {
+ std::cout << q.first << ": " << q.second << std::endl;
+ }
+
+ std::string id = root["id"].asString();
+ std::string date = root["date"].asString();
+ std::string name = root["name"].asString();
+ int result = root["id"].asInt();
+ std::string data = root["data"].asString();
+
+ try
+ {
+ Report{id,name,date,data,result}.save();
+ }
+ catch(std::exception& e)
+ {
+ std::cout <<"DB save error: " << e.what() << std::endl;
+ }
+
+// pResponse->setResourceRepresentation(get());
+ pResponse->setResponseResult(OC_EH_OK);
+ }
+
+
+ }
+
+ pResponse->setErrorCode(rcode);
+
+
+ if(OC_STACK_OK == OCPlatform::sendResponse(pResponse))
+ {
+ ehResult = OC_EH_OK;
+ }
+ }
+ else if(requestType == "DELETE")
+ {
+ }
+ }
+ }
+ else
+ {
+ std::cout << "Invalid request" << std::endl;
+ }
+
+ return ehResult;
+}
--- /dev/null
+/**
+ * @brief Server report reasource
+ * @date Created 17.05.2017
+ * @author Created 2017 in Samsung Ukraine R&D Center (SURC) under a contract
+ * between LLC "Samsung Electronics Ukraine Company" (Kiev, Ukraine)
+ * and "Samsung Electronics Co", Ltd (Seoul, Republic of Korea).
+ * Copyright: (c) Samsung Electronics Co, Ltd 2017. All rights reserved.
+ * @author Mail to: <A HREF="mailto:d.lomtev@samsung.com">Dmytro Lomtev, d.lomtev@samsung.com</A>
+ */
+
+#include "OCPlatform.h"
+#include "OCApi.h"
+#include <string>
+
+
+using namespace OC;
+
+void sql_test();
+
+class ReportResource
+{
+private:
+ std::string m_reportUri;
+ OCResourceHandle m_resourceHandle;
+ OCRepresentation m_reportRep;
+
+public:
+ /**
+ * Constructor
+ */
+ ReportResource();
+
+ /**
+ * Register resource to make IOTivity clients to find it
+ */
+ void registerResource();
+
+ /**
+ * Getter for resource handle
+ *
+ * @return OCResourceHandle object (used to publish resource on IoT cloud)
+ */
+ OCResourceHandle getHandle();
+
+ /**
+ * Gets the updated representation.
+ *
+ * @return representation object
+ */
+ OCRepresentation get();
+
+ /**
+ * Gets the representation.
+ *
+ * @param params [in] Specific request parameters
+ * @return representation object
+ */
+ OCRepresentation get(const QueryParamsMap& params);
+
+private:
+ OCEntityHandlerResult entityHandler(std::shared_ptr<OCResourceRequest> request);
+};
#include <OCPlatform.h>
#include "iotivity.h"
#include "notification_resource.h"
+#include "report_resource.h"
using namespace OC;
using namespace NetworkManager;
bool isSecured = false;
NotificationResource notifResource(isSecured);
notifResource.registerResource();
+ ReportResource reportResouce;
+ reportResouce.registerResource();
resourceHandles.push_back(notifResource.getHandle());
+ resourceHandles.push_back(reportResouce.getHandle());
guardErrorCode(RDClient::Instance().publishResourceToRD(host, OCConnectivityType::CT_ADAPTER_TCP, resourceHandles,
&onPublish), "Notification resource publishResourceToRD()");
int main(int argc, char* argv[])
{
+// std::cout << "SQLite test start" << std::endl;
+// sql_test();
+// std::cout << "SQLite test finish" << std::endl;
try
{
mainLoop();
--- /dev/null
+#ifndef SELECTQUERY_H
+#define SELECTQUERY_H
+
+#include <type_traits>
+#include <string>
+#include <vector>
+#include <sstream>
+
+template<class T>
+class SelectQuery
+{
+public:
+ SelectQuery<T>(sqlite_exec_callback cb): callback(cb) {}
+
+ template<class R>
+ SelectQuery& filter(const std::string& name, const R& value)
+ {
+ filter(name, value, std::is_integral<R>());
+ return *this;
+ }
+
+ std::vector<T> all()
+ {
+ std::vector<T> v;
+ std::ostringstream os;
+ os << "SELECT * FROM " << T::TABLE_NAME;
+
+ if (!filters.empty())
+ {
+ auto it = filters.cbegin();
+ os << " WHERE " << *it;
+
+ while (++it != filters.cend())
+ {
+ os << " AND " << *it;
+ }
+ }
+
+ os << ';';
+
+ SQLiteDB::inst().exec(os.str(), callback, &v);
+ return v;
+ }
+
+private:
+ template<class R>
+ void filter(const std::string& name, const R& value, std::true_type)
+ {
+ filters.emplace_back(name + " = " + std::to_string(value));
+ }
+
+ template<class R>
+ void filter(const std::string& name, const R& value, std::false_type)
+ {
+ filters.emplace_back(name + " = '" + std::string{value} + "'");
+ }
+
+
+ sqlite_exec_callback callback;
+ std::vector<std::string> filters;
+};
+
+#endif // SELECTQUERY_H
--- /dev/null
+#include "sqlitedb.h"
+#include <sqlite3.h>
+#include <stdexcept>
+
+using namespace std;
+
+SQLiteDB::~SQLiteDB()
+{
+ sqlite3_close(db);
+}
+
+void SQLiteDB::exec(const string& SQL, sqlite_exec_callback cb, void* data)
+{
+ char* error_msg;
+ int ecode = sqlite3_exec(db, SQL.c_str(), cb, data, &error_msg);
+
+ if (ecode != SQLITE_OK)
+ {
+ string serr{error_msg};
+ sqlite3_free(error_msg);
+ throw runtime_error(serr.c_str());
+ }
+}
+
+SQLiteDB& SQLiteDB::inst()
+{
+ if (instance.db == nullptr)
+ {
+ int ecode = sqlite3_open(":memory:", &instance.db);
+ if (ecode != SQLITE_OK) throw runtime_error("Can not create memory data base");
+ }
+
+ return instance;
+}
+
+long long SQLiteDB::last_row_id()
+{
+ return sqlite3_last_insert_rowid(db);
+}
+
+SQLiteDB::SQLiteDB() : db(nullptr)
+{
+
+}
+
+SQLiteDB SQLiteDB::instance;
--- /dev/null
+#ifndef SQLITEDB_H
+#define SQLITEDB_H
+
+#include <string>
+
+typedef int (*sqlite_exec_callback)(void *user_data, int argc, char **argv, char **col_name);
+struct sqlite3;
+
+class SQLiteDB
+{
+public:
+ ~SQLiteDB();
+
+ void exec(const std::string& SQL, sqlite_exec_callback cb, void* data);
+
+ static SQLiteDB& inst();
+
+ long long last_row_id();
+
+private:
+ SQLiteDB();
+ sqlite3* db;
+ static SQLiteDB instance;
+};
+
+#endif // SQLITEDB_H
std::this_thread::sleep_for(std::chrono::seconds(1));
ASSERT_EQ(EC_OK, NM_freeDeviceList(&dev_list));
}
+
+TEST_F(IoTDevManagerTest, reportTest)
+{
+ char* report = nullptr;
+ ASSERT_EQ(EC_OK, NM_getDeviceReport(ctx, "9b5287b3-fe92-46fc-a924-488d2339c2ba", &report));
+// std::cout << report << std::endl;
+
+ const std::string must_be = "[\n {\n \"data\" : \"Alert! Alles caput!\",\n\
+ \"date\" : \"17-05-2017 05:32:30\",\n \"did\" : \"9b5287b3-fe92-46fc-a924-488d2339c2ba\",\n\
+ \"name\" : \"sim\",\n \"result\" : 3\n },\n {\n \"data\" : \"Spartaaaaa!\",\n\
+ \"date\" : \"17-05-2017 05:32:30\",\n \"did\" : \"9b5287b3-fe92-46fc-a924-488d2339c2ba\",\n\
+ \"name\" : \"sim\",\n \"result\" : 0\n }\n]\n";
+ ASSERT_EQ(must_be, report);
+ ASSERT_NO_THROW(NM_freeCharBuffer(report));
+}
+
+TEST_F(IoTDevManagerTest, reportTestWrongDid)
+{
+ char* report = nullptr;
+ ASSERT_EQ(EC_OK, NM_getDeviceReport(ctx, "wrong device id", &report));
+ ASSERT_EQ(nullptr, report);
+ ASSERT_NO_THROW(NM_freeCharBuffer(report));
+ ASSERT_NO_THROW(NM_freeCharBuffer(nullptr));
+}