${CMAKE_CURRENT_SOURCE_DIR}/thirdparty/libjson/_internal/Source/JSONDefs)
add_subdirectory(thirdparty)
-pkg_check_modules(PROXY_REQ_PKGS REQUIRED dlog boost notification)
+pkg_check_modules(PROXY_REQ_PKGS REQUIRED dlog boost systemd glib-2.0 smart-deadlock global-function)
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wall -Wno-unused-result -std=c++11") #-Werror
#ifndef IOTSWC_NETWORK_MANAGER_H_
#define IOTSWC_NETWORK_MANAGER_H_
+#include <memory>
+
#include "nm_types.h"
#include "i_network_manager.h"
+#include "push_notification.h"
namespace iotswsec
{
typedef NM_ErrorCode (*GetDevicePolicyFunc)(NM_hContext, const char* devId, const char * agentId, char** policy);
typedef NM_ErrorCode (*SetDevicePolicyFunc)(NM_hContext, const char* devId, const char* policy);
typedef NM_ErrorCode (*GetDeviceAgentsFunc)(NM_hContext, const char* devId, char** agents);
+ typedef NM_ErrorCode (*DeleteAppFunc)(NM_hContext ctx, const char* dev_id, const char* app_name);
public:
-
NetworkManager();
NetworkManager(const NetworkManager&) = delete;
GetDeviceInfoByIdFunc m_nmGetDeviceInfoByIdFunc;
OwnDeviceByIdFunc m_nmOwnDeviceByIdFunc;
UnOwnDeviceByIdFunc m_nmUnownDeviceByIdFunc;
-
+ DeleteAppFunc m_nmDeleteAppFunc;
};
DeviceList ToDeviceList(char** uuids);
ErrorCode UnsubscribeOnNotifications();
ErrorCode GetPolicy(const std::string& devId, const std::string& agentId, std::string& policy);
+ static void PushNotificationCallback(NM_NotificationData data, void* userData);
+
private:
ModuleSymbols m_moduleSymbols;
NM_hContext m_context;
std::vector<NotificationCallback> m_notificationCallbackList;
+ std::shared_ptr<PushNotification> m_pushNotification;
};
} //namespace iotswsec
@par Copyright: (c) Samsung Electronics Co, Ltd 2017. All rights reserved.
**/
-#ifndef PUSH_NOTIFICATION_H_
-#define PUSH_NOTIFICATION_H_
+#ifndef __PUSH_NOTIFICATION_H__
+#define __PUSH_NOTIFICATION_H__
+#include <functional>
#include <string>
-
-#include <notification.h>
+#include <utility>
namespace iotswsec
{
+using NotificationHandler = std::function<void(int)>;
+
class PushNotification
{
public:
- PushNotification(const std::string& title, const std::string& body);
+ PushNotification(const std::string& app_name, NotificationHandler&& handler = NotificationHandler{});
virtual ~PushNotification();
PushNotification(const PushNotification& obj) = delete;
PushNotification& operator=(const PushNotification&) = delete;
/**
- @brief Push Tizen notification.
- @return 0 on success, otherwise any other value on failure
- */
- int push() const;
+ * @brief Push Tizen notification.
+ * @param title [in] notification title
+ * @param description [in] notification body
+ * @param buttons_caption [in] notification buttons text
+ * @return 0 on success, otherwise any other value on failure
+ */
+ int push(const std::string& title, const std::string& description, const std::string& button1_caption, const std::string& button2_caption);
+
+ /**
+ * @brief Set handler.
+ * @param handler [in] callback
+ */
+ void setHandler(NotificationHandler&& handler);
+
+ /**
+ * @brief Remove handler.
+ */
+ void removeHandler();
private:
- notification_h m_notification;
+ static void onButtonClickCB(int item_id, int button_index, void* user_data);
+ static void onNotificationTimeOutCB(int item_id, void* user_data);
+ static void onNotificationHideCB(char* app_name, void* user_data);
+
+ std::string m_app_name;
+ NotificationHandler m_handler;
};
}
-#endif /* PUSH_NOTIFICATION_H_ */
+#endif /* __PUSH_NOTIFICATION_H__ */
--- /dev/null
+<?xml version="1.0" encoding="utf-8"?>
+<manifest xmlns="http://tizen.org/ns/packages" api-version="3.0" package="@PACKAGE_NAME@" version="@VERSION@" install-location="internal-only">
+ <label>iot-manager-dashboard-proxy</label>
+ <description>iot-manager-dashboard-proxy</description>
+ <service-application appid="@PACKAGE_NAME@" exec="@BINDIR@/@PROJECT_NAME@" nodisplay="true" type="c++app" >
+ <label>iot-manager-dashboard-proxy</label>
+ </service-application>
+ <privileges>
+ <privilege>http://tizen.org/privilege/notification</privilege>
+ </privileges>
+</manifest>
BuildRequires: cmake >= 2.8
BuildRequires: gtest
BuildRequires: gtest-devel
+BuildRequires: pkgconfig(systemd)
+BuildRequires: pkgconfig(glib-2.0)
+BuildRequires: pkgconfig(smart-deadlock)
+BuildRequires: pkgconfig(global-function)
BuildRequires: pkgconfig(capi-appfw-application)
-BuildRequires: pkgconfig(notification)
%define _proxy_packagedir /usr/apps/%{name}
%define _proxy_bindir %{_proxy_packagedir}/bin
@par and "Samsung Electronics Co", Ltd (Seoul, Republic of Korea)
@par Copyright: (c) Samsung Electronics Co, Ltd 2016. All rights reserved.
**/
-
-#include "unistd.h"
+#include <unistd.h>
#include <thread>
#include <chrono>
+#include <systemd/sd-daemon.h>
+#include <glib.h>
+#include <smart-deadlock.h>
+#include <signal.h>
+
#include "utils/log.h"
#include "uipepper_connector.h"
#include "presenter.h"
using namespace iotswsec;
+#define NOTIFY_TIME 5000
+
static const short int TCPUIPort = 17000;
static const short int TCPProxyPort = 17001;
static std::shared_ptr<iotswsec::Model> modelPtr; ///< Pointer to model instance
static std::shared_ptr<iotswsec::UIConnector> connectorPtr; ///< Pointer to con-tor instance
+static gboolean notify_callback(gpointer data)
+{
+ smart_deadlock_watchdog_notify();
+ return TRUE;
+}
+
static void UIConnectorWebViewCallback(const std::string& command, const std::string& data)
{
LOG_DBG("BEGIN");
LOG_DBG("END");
}
-int main()
+static void thread_func()
{
- LOG_DBG("Starting daemon main");
-
- pid_t forkPid = fork();
+ LOG_DBG("BEGIN");
- switch (forkPid)
- {
- case 0: //Forked process;
+ try
{
- LOG_INFO("Forkind succeded");
-
- setsid(); //New session;
-
- //Close streams;
- close(STDIN_FILENO);
- close(STDOUT_FILENO);
- close(STDERR_FILENO);
+ connectorPtr = std::make_shared<UIConnector>(TCPProxyPort, TCPUIPort);
+ // Initialize presenter.
+ presenterPtr = std::make_shared<iotswsec::Presenter>();
try
{
- connectorPtr = std::make_shared<UIConnector>(TCPProxyPort, TCPUIPort);
- // Initialize presenter.
- presenterPtr = std::make_shared<iotswsec::Presenter>();
+ // Initialize model.
+ modelPtr = std::make_shared<iotswsec::Model>();
+ }
+ catch(const std::runtime_error& ex)
+ {
+ LOG_ERR("Couldn't create service, exception was thrown: %s", ex.what());
+ return;
+ }
- try
+ // Bind model to presenter.
+ presenterPtr->SetModel(modelPtr);
+ // Initialize view.
+ webViewPtr = std::make_shared<iotswsec::WebView>(presenterPtr, WebViewCallback);
+ // Bind view to presenter.
+ presenterPtr->AddView(webViewPtr);
+
+ //TODO: Rework message processing
+ while (true)
+ {
+ if (!connectorPtr->IsConnected())
{
- // Initialize model.
- modelPtr = std::make_shared<iotswsec::Model>();
+ LOG_INFO("Waiting for a connection");
+ connectorPtr->AcceptConnection();
}
- catch(const std::runtime_error& ex)
- {
- LOG_ERR("Couldn't create service, exception was thrown: %s", ex.what());
- return -1;
- }
+ LOG_INFO("Waiting for a message");
+ auto inputMessage = connectorPtr->ReceiveMessage();
- // Bind model to presenter.
- presenterPtr->SetModel(modelPtr);
- // Initialize view.
- webViewPtr = std::make_shared<iotswsec::WebView>(presenterPtr, WebViewCallback);
- // Bind view to presenter.
- presenterPtr->AddView(webViewPtr);
+ LOG_INFO("Message parsed %s, %s", inputMessage.command.c_str(), inputMessage.jsonData.c_str());
- //TODO: Rework message processing
- while (true)
- {
- if (!connectorPtr->IsConnected())
- {
- LOG_INFO("Waiting for a connection");
- connectorPtr->AcceptConnection();
- }
+ UIConnectorWebViewCallback(inputMessage.command, inputMessage.jsonData);
+ }
+ }
+ catch(const std::exception& ex)
+ {
+ LOG_ERR("exception: %s", ex.what());
+ return;
+ }
+ catch(...)
+ {
+ LOG_ERR("Caught exception");
+ return;
+ }
- LOG_INFO("Waiting for a message");
- auto inputMessage = connectorPtr->ReceiveMessage();
+ LOG_DBG("END");
+}
- LOG_INFO("Message parsed %s, %s", inputMessage.command.c_str(), inputMessage.jsonData.c_str());
+int main()
+{
+ LOG_DBG("Starting daemon main");
- UIConnectorWebViewCallback(inputMessage.command, inputMessage.jsonData);
- }
- }
- catch(const std::exception& ex)
- {
- LOG_INFO("exception: %s", ex.what());
+ pid_t forkPid = fork();
- return 1;
- }
- catch (...)
+ switch (forkPid)
+ {
+ case 0: //Forked process;
{
- LOG_INFO("Caught exception");
+ LOG_INFO("Forkind succeded");
- return 1;
- }
+ setsid(); //New session;
+
+ //Close streams;
+ close(STDIN_FILENO);
+ close(STDOUT_FILENO);
+ close(STDERR_FILENO);
+
+ LOG_INFO("START");
+
+#if !GLIB_CHECK_VERSION(2,35,0)
+ g_type_init();
+#endif
+
+ GMainLoop* mainLoop = g_main_loop_new(NULL, FALSE);
+ if(mainLoop)
+ {
+ smart_deadlock_register_watchdog_service(60);
+ g_timeout_add(NOTIFY_TIME, notify_callback, mainLoop);
+
+ std::thread thr(thread_func);
+
+ g_main_loop_run(mainLoop);
+ g_main_loop_unref(mainLoop);
+ }
+ else
+ {
+ LOG_ERR("Main loop failed");
+ }
+
+ LOG_INFO("STOP");
return 0;
}
case -1: //Forking failed;
{
- LOG_INFO("Forkind failed");
+ LOG_ERR("Forkind failed");
return 1;
}
{
return 0;
}
- } //switch
+ } //switch
}
@par Copyright: (c) Samsung Electronics Co, Ltd 2017. All rights reserved.
**/
+#include <string>
+#include <stdexcept>
+
+#include <app.h>
+#include <app_control.h>
+
#include "network/network_manager.h"
#include "utils/log.h"
#include "utils/to_string.h"
#include "utils/assert_return.h"
-#include "push_notification.h"
#include <dlfcn.h>
+#define SELF_APP_NAME "iot-manager-dashboard-proxy"
+#define DASHBOARD_APP_ID "62UffoiBtd.Dashboard"
+
#define NMLIB_MODULE_NAME "/usr/lib/libnmlib.so"
#define NM_INIT_FUNC_NAME "NM_init"
#define NM_GET_DEV_INFO_BY_ID_FUNC_NAME "NM_getDeviceInfoEx"
#define NM_OWN_DEV_BY_ID_FUNC_NAME "NM_ownDeviceEx"
#define NM_UNOWN_DEV_BY_ID_FUNC_NAME "NM_unOwnDeviceEx"
+#define NM_DELETE_APP_FUNC_NAME "NM_deleteApp"
namespace iotswsec
{
m_nmFreeDevArrayFunc(nullptr),
m_nmGetDeviceInfoByIdFunc(nullptr),
m_nmOwnDeviceByIdFunc(nullptr),
- m_nmUnownDeviceByIdFunc(nullptr)
+ m_nmUnownDeviceByIdFunc(nullptr),
+ m_nmDeleteAppFunc(nullptr)
{
if (LoadModule() != ErrorCode::Success)
{
dlsym(this->m_module, NM_UNOWN_DEV_BY_ID_FUNC_NAME));
m_nmFreeDevArrayFunc = reinterpret_cast<FreeDeviceArrayFunc>(
dlsym(this->m_module, NM_FREE_DEV_UUID_ARR_FUNC_NAME));
+ m_nmDeleteAppFunc = reinterpret_cast<DeleteAppFunc>(
+ dlsym(this->m_module, NM_DELETE_APP_FUNC_NAME));
if (!m_nmInitFunc ||
!m_nmCleanUpFunc ||
!m_nmGetDeviceInfoByIdFunc ||
!m_nmOwnDeviceByIdFunc ||
!m_nmUnownDeviceByIdFunc ||
- !m_nmFreeDevArrayFunc)
+ !m_nmFreeDevArrayFunc ||
+ !m_nmDeleteAppFunc)
{
LOG_ERR("Couldn't load one of the functions due to error: %s", dlerror());
m_nmOwnDeviceByIdFunc = nullptr;
m_nmUnownDeviceByIdFunc = nullptr;
m_nmFreeDevArrayFunc = nullptr;
+ m_nmDeleteAppFunc = nullptr;
if (dlclose(m_module) == 0)
{
NetworkManager::NetworkManager():
m_moduleSymbols(),
m_context(nullptr),
- m_notificationCallbackList()
+ m_notificationCallbackList(),
+ m_pushNotification(nullptr)
{
NM_ErrorCode res;
throw std::runtime_error(std::string(std::string("couldn't init network manager context, error code: ")
+ std::to_string(res)).c_str());
};
+
+ m_pushNotification = std::make_shared<PushNotification>(SELF_APP_NAME);
}
-static void PushNotificationCallback(NM_NotificationData data, void* userData)
+void NetworkManager::PushNotificationCallback(NM_NotificationData data, void* userData)
{
LOG_DBG("BEGIN");
+ ASSERT_RETURN_NOTHING(userData, "incorrect user data");
+
+ NetworkManager* nm = static_cast<NetworkManager*>(userData);
+ ASSERT_RETURN_NOTHING(nm->m_pushNotification, "incorrect pushNotification object");
+
switch(data.type)
{
case NT_Notify:
{
if(data.title && data.message)
{
- try
- {
- PushNotification(data.title, data.message).push();
- }
- catch(const std::runtime_error& ex)
- {
- LOG_ERR("Failed to push notification, exception was thrown: %s", ex.what());
- }
+ nm->m_pushNotification->setHandler([](int button_index){
+
+ LOG_INFO("notification handler : button_index [%d]", button_index);
+
+ if(button_index == 0)
+ {
+ LOG_INFO("try to launch dashboard application");
+
+ app_control_h app_control;
+
+ app_control_create(&app_control);
+ app_control_set_operation(app_control, APP_CONTROL_OPERATION_DEFAULT);
+ app_control_set_app_id(app_control, DASHBOARD_APP_ID);
+
+ if (app_control_send_launch_request(app_control, NULL, NULL) == APP_CONTROL_ERROR_NONE)
+ LOG_INFO("dashboard application launched");
+ else
+ LOG_ERR("failed to launch dashboard application");
+
+ app_control_destroy(app_control);
+ }
+ });
+ nm->m_pushNotification->push(data.title, data.message, "Show more", "Dismiss");
}
else
{
case NT_RemoveAppRequest:
{
+ ASSERT_RETURN_NOTHING(nm->m_moduleSymbols.m_nmDeleteAppFunc, "function isn't loaded");
+ if(data.title && data.message && data.duid && data.appname)
+ {
+ std::string device_id{data.duid};
+ std::string app_name{data.appname};
+ nm->m_pushNotification->setHandler([nm, device_id, app_name](int button_index){
+
+ LOG_INFO("notification handler : button_index [%d]", button_index);
+
+ if(button_index == 0)
+ {
+ LOG_INFO("try to uninstall application [%s], device_id [%s]", app_name.c_str(), device_id.c_str());
+
+ if(nm->m_moduleSymbols.m_nmDeleteAppFunc(nm->m_context, device_id.c_str(), app_name.c_str()) == NM_ErrorCode::EC_OK)
+ LOG_INFO("application uninstalled");
+ else
+ LOG_ERR("failed to uninstall application");
+ }
+ });
+ nm->m_pushNotification->push(data.title, data.message, "Uninstall", "Cancel");
+ }
+ else
+ {
+ LOG_ERR("Invalid notification data.");
+ }
}
break;
ASSERT_RETURN(m_moduleSymbols.m_nmSubsOnNotifFunc, "function isn't loaded", ErrorCode::FunctionNotFound);
NM_ErrorCode res;
- if ((res = m_moduleSymbols.m_nmSubsOnNotifFunc(m_context, PushNotificationCallback, nullptr)) != NM_ErrorCode::EC_OK)
+ if ((res = m_moduleSymbols.m_nmSubsOnNotifFunc(m_context, PushNotificationCallback, this)) != NM_ErrorCode::EC_OK)
{
LOG_ERR("Couln't subscribe on notifications, nmanager returned: %s", std::to_string(res).c_str());
@par Copyright: (c) Samsung Electronics Co, Ltd 2017. All rights reserved.
**/
+#include <iostream>
#include <stdexcept>
-#include <cassert>
-#include <app_control.h>
-#include <notification.h>
-#include <notification_internal.h>
+#include <notification_data_manager.h>
#include "common_types.h"
#include "utils/log.h"
+#include "utils/assert_return.h"
#include "push_notification.h"
-#define DASHBOARD_APP_ID "62UffoiBtd.Dashboard"
-
namespace iotswsec
{
-PushNotification::PushNotification(const std::string& title, const std::string& body) : m_notification(nullptr)
+PushNotification::PushNotification(const std::string& app_name, NotificationHandler&& handler) : m_app_name{app_name}, m_handler{handler}
{
LOG_DBG("BEGIN");
- if((m_notification = notification_create(NOTIFICATION_TYPE_NOTI)) == nullptr)
+ if(init_notification_data_manager(const_cast<char*>(m_app_name.c_str()), COMMON_MAIN_LOOP) != 0)
{
throw std::runtime_error("Couldn't create notification instance.");
}
- notification_set_display_applist(m_notification, NOTIFICATION_DISPLAY_APP_ACTIVE);
- notification_set_layout(m_notification, NOTIFICATION_LY_NONE);
- notification_set_auto_remove(m_notification, false);
- notification_set_time(m_notification, time(NULL));
- notification_set_hide_timeout(m_notification, 60);
-
- notification_set_text(m_notification, NOTIFICATION_TEXT_TYPE_TITLE, title.c_str(), NULL, NOTIFICATION_VARIABLE_TYPE_NONE);
- notification_set_text(m_notification, NOTIFICATION_TEXT_TYPE_CONTENT, body.c_str(), NULL, NOTIFICATION_VARIABLE_TYPE_NONE);
- notification_add_button(m_notification, NOTIFICATION_BUTTON_1);
- notification_set_text(m_notification, NOTIFICATION_TEXT_TYPE_BUTTON_1, "Show more", NULL, NOTIFICATION_VARIABLE_TYPE_NONE);
- notification_add_button(m_notification, NOTIFICATION_BUTTON_2);
- notification_set_text(m_notification, NOTIFICATION_TEXT_TYPE_BUTTON_2, "Dismiss", NULL, NOTIFICATION_VARIABLE_TYPE_NONE);
- notification_set_default_button(m_notification, NOTIFICATION_BUTTON_1);
-
- app_control_h app_control = NULL;
- app_control_create(&app_control);
- if(!app_control)
- {
- throw std::runtime_error("Couldn't create app_control instance.");
- }
- app_control_set_app_id(app_control, DASHBOARD_APP_ID);
- app_control_set_operation(app_control, APP_CONTROL_OPERATION_DEFAULT);
- notification_set_event_handler(m_notification, NOTIFICATION_EVENT_TYPE_CLICK_ON_BUTTON_1, app_control);
- app_control_destroy(app_control);
-
- app_control = NULL;
- app_control_create(&app_control);
- if(!app_control)
- {
- throw std::runtime_error("Couldn't create app_control instance.");
- }
- notification_set_event_handler(m_notification, NOTIFICATION_EVENT_TYPE_CLICK_ON_BUTTON_2, app_control);
- app_control_destroy(app_control);
+ register_notification_button_callback(onButtonClickCB, this);
+ register_notification_timeout_callback(onNotificationTimeOutCB, this);
+ register_notofication_hide_callback(onNotificationHideCB, this);
LOG_DBG("END");
}
PushNotification::~PushNotification()
{
- notification_delete(m_notification);
- notification_free(m_notification);
- m_notification = nullptr;
+ close_notification_data_manager();
}
-int PushNotification::push() const
+int PushNotification::push(const std::string& title, const std::string& description, const std::string& button1_caption, const std::string& button2_caption)
{
- assert(m_notification);
- return notification_post(m_notification);
+ LOG_DBG("BEGIN");
+
+ notification_item_info_s notiItemInfo = {0};
+
+ notiItemInfo.pAppName = const_cast<char*>(m_app_name.c_str());
+ notiItemInfo.nItemId = 0;
+ notiItemInfo.bFlagAutoDelete = 1;
+ notiItemInfo.bFlagBannerShow = 1;
+ notiItemInfo.nBannerHideAlarmDuration = 120;
+ notiItemInfo.nItemType = ITEM_TYPE_TEXT;
+ notiItemInfo.nDefaultFocus = 0;
+
+ notiItemInfo.pTitleText = const_cast<char*>(title.c_str());
+ notiItemInfo.pDescriptionText = const_cast<char*>(description.c_str());
+
+ notiItemInfo.nButtonNum = 2;
+ notiItemInfo.pFirstButtonText = const_cast<char*>(button1_caption.c_str());
+ notiItemInfo.pSecondButtonText = const_cast<char*>(button2_caption.c_str());
+
+ int res = add_notification_data(¬iItemInfo);
+
+ LOG_DBG("END");
+
+ return res;
+}
+
+void PushNotification::setHandler(NotificationHandler&& handler)
+{
+ m_handler = std::move(handler);
+}
+
+void PushNotification::removeHandler()
+{
+ m_handler = NotificationHandler{};
+}
+
+void PushNotification::onButtonClickCB(int item_id, int button_index, void* user_data)
+{
+ LOG_DBG("BEGIN");
+
+ ASSERT_RETURN_NOTHING(user_data, "user_data");
+
+ PushNotification* pn = static_cast<PushNotification*>(user_data);
+
+ if((bool)pn->m_handler)
+ pn->m_handler(button_index);
+
+ LOG_DBG("END");
+}
+void PushNotification::onNotificationTimeOutCB(int item_id, void* user_data)
+{
+ LOG_DBG("BEGIN");
+ LOG_DBG("END");
+}
+void PushNotification::onNotificationHideCB(char* app_name, void* user_data)
+{
+ LOG_DBG("BEGIN");
+ LOG_DBG("END");
}
} //namespace iotswsec
project(${PROXY_PROJ_NAME}-ut C CXX)
-pkg_check_modules(${PROJECT_NAME}_REQ_PKGS REQUIRED dlog boost notification)
+pkg_check_modules(${PROJECT_NAME}_REQ_PKGS REQUIRED dlog boost global-function)
GENERATE_UT_STRUCTURE_VARIABLE(../ ${PROXY_PROJ_NAME})