compile_commands.json
CTestTestfile.cmake
.vscode
+.cproject
+.project
+.settings/
+.tproject
+html/
+latex/
\ No newline at end of file
CMAKE_MINIMUM_REQUIRED(VERSION 2.6)
+option(CMD_MGR_TESTING "Build with testing connection manager" OFF)
+
ADD_SUBDIRECTORY(common)
ADD_SUBDIRECTORY(daemon)
ADD_SUBDIRECTORY(lib)
${COMMON_INCLUDES}
)
+if(CMD_MGR_TESTING)
+ add_definitions(-DTTD_CMD_MGR_TESTING)
+endif(CMD_MGR_TESTING)
+
# Install
INSTALL(TARGETS ${DAEMON} DESTINATION ${INSTALL_BIN_DIR})
INSTALL(FILES ${CMAKE_CURRENT_SOURCE_DIR}/res/${TTD_CONF_FILE} DESTINATION ${INSTALL_CONF_DIR})
#include "ttd-worker-interface.h"
#include "ttd-worker-handle.h"
#include "ttd-http.h"
+#include "ttd-cmd-mgr.h"
#include "common-util.h"
#define DEFAULT_DURATION 600
_D("[delay] start-to-ready - %.3lf(ms)",
(double)(_get_monotonic_time() - start)/1000);
+
+#ifdef TTD_CMD_MGR_TESTING
+ ttd_cmd_mgr_init();
+#endif
+
g_main_loop_run(d_data->mainloop);
g_main_loop_unref(d_data->mainloop);
free(d_data);
d_data = NULL;
+#ifdef TTD_CMD_MGR_TESTING
+ ttd_cmd_mgr_fini();
+#endif
+
ttd_conn_mgr_fini();
ttd_http_fini();
ttd_config_fini();
#define RESULT_WAIT_IN_SEC (10)
#define RESULT_WAIT_TIME (RESULT_WAIT_IN_SEC * 1000000)
#define RESULT_WAIT_TRY_MAX (10)
-
+#define CMD_MGR_GET_TESTING_INTERVAL_SEC (10)
// #define CMD_FETCH_TEST
typedef struct _ttd_result_data_s {
int ret = 0;
guint64 until = 0;
unsigned int retry = 0;
-
- until = common_get_monotonic_coarse_time() +
- CMD_MGR_GET_INTERVAL_SEC * G_TIME_SPAN_SECOND;
- _D("thread blocked for 3 hours");
+ unsigned int blocking_time = CMD_MGR_GET_INTERVAL_SEC;
+#ifdef TTD_CMD_MGR_TESTING
+ blocking_time = CMD_MGR_GET_TESTING_INTERVAL_SEC;
+#endif
+ until = common_get_monotonic_coarse_time() + blocking_time * G_TIME_SPAN_SECOND;
+ _D("thread blocked for %d seconds", blocking_time);
g_cond_wait_until(&handle->get_cond, &handle->get_mutex, until);
_D("thread unblocked");
retv_if(!tmp_gkf, -1);
if (!g_key_file_load_from_file(tmp_gkf, CONF_PATH, G_KEY_FILE_NONE, NULL)) {
- _E("Failed to load conf file");
+ _E("Failed to load config file (%s)", CONF_PATH);
g_key_file_free(tmp_gkf);
return -1;
}
curl = curl_easy_init();
- retvm_if(!curl, NULL, "failed to curl_easy_init()");
+ retvm_if(!curl, -1, "failed to curl_easy_init()");
curl_easy_setopt(curl, CURLOPT_URL, url);
curl_easy_setopt(curl, CURLOPT_CAPATH, CERT_FILE_PATH);
curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, _response_write);
curl_easy_setopt(curl, CURLOPT_WRITEDATA, (void *)response);
+#ifdef TTD_CMD_MGR_TESTING
+ curl_easy_setopt(curl, CURLOPT_VERBOSE, 1);
+#endif //TTD_CMD_MGR_TESTING
res = curl_easy_perform(curl);
if (res != CURLE_OK) {
curl = curl_easy_init();
- retvm_if(!curl, NULL, "failed to curl_easy_init()");
+ retvm_if(!curl, -1, "failed to curl_easy_init()");
/* TODO : what should I do before post result */
if (headers)
curl_easy_setopt(curl, CURLOPT_POSTFIELDS, msg_body);
curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, _response_write);
curl_easy_setopt(curl, CURLOPT_WRITEDATA, (void *)&response);
+#ifdef TTD_CMD_MGR_TESTING
+ curl_easy_setopt(curl, CURLOPT_VERBOSE, 1);
+#endif //TTD_CMD_MGR_TESTING
res = curl_easy_perform(curl);
if (res != CURLE_OK) {
curl = curl_easy_init();
- retvm_if(!curl, NULL, "failed to curl_easy_init()");
+ retvm_if(!curl, -1, "failed to curl_easy_init()");
curl_easy_setopt(curl, CURLOPT_URL, url);
curl_easy_setopt(curl, CURLOPT_CAPATH, CERT_FILE_PATH);
#define TTD_CMD_KEY_CONTENT "content"
#define TTD_CMD_KEY_CONTENT_ACTION "action"
#define TTD_CMD_KEY_CONTENT_INFO "info"
+#define TTD_CMD_KEY_CONTENT_JSON "json"
#define TTD_CMD_KEY_EXTRA "extra"
static int __parse_cmd_get_action(json_object *obj)
static int __parse_cmd_info(json_object *obj, ttd_cmd_data *cmd)
{
+ json_object *content_obj = NULL;
+ json_object *json_obj = NULL;
+ void *json_data = NULL;
int action = 0;
int ret = 0;
switch (action) {
case TTD_CMD_INFO_GET_SYSINFO:
case TTD_CMD_INFO_GET_TASKINFO:
+
+ content_obj = json_object_object_get(obj, TTD_CMD_KEY_CONTENT);
+ retvm_if(!content_obj, -1, "%s", "failed to get content");
+
+ json_obj = json_object_object_get(content_obj, TTD_CMD_KEY_CONTENT_JSON);
+ retvm_if(!json_obj, -1, "failed to get content json");
+ json_data = g_strdup(json_object_get_string(json_obj));
+ if (json_data)
+ ttd_cmd_set_data(cmd, json_data, strlen(json_data), g_free);
+ else {
+ _E("failed to get json from content");
+ return -1;
+ }
+
ret = ttd_cmd_set_command(cmd, action);
break;
case TTD_CMD_INFO_GET_MAX:
items_obj = json_object_object_get(root_obj, TTD_CMD_KEY_ITEMS);
items_type = json_object_get_type(items_obj);
if (items_type != json_type_array) {
- _E("cmd items are not array type");
+ _E("cmd items are not array type (is %d)", items_type);
json_object_put(root_obj);
return -1;
}
#include "ttd-cmd.h"
#include "ttd-log.h"
+#include <string.h>
+#include <stdlib.h>
+#include <unistd.h>
+
#define WORKER_PKG_MGR "org.tizen.package-manager-worker"
#define WORKER_INFO_SYS "ttd-worker-system"
#define WORKER_INFO_TASK "org.tizen.task-worker"
+#define WORKER_INFO_TASK_NAME "task-worker"
+#define WORKER_INFO_TASK_PATH "/usr/bin/task-worker"
-int ttd_worker_handle_info(ttd_cmd_data *c_data)
+static int _exec_application_sysinfo(const char *cmd_id)
{
app_control_h ac_h = NULL;
- int ac_ret = APP_CONTROL_ERROR_NONE;
- int ret = 0;
- const char *cmd_id = NULL;
- const char *app_id = NULL;
+ int ac_ret = app_control_create(&ac_h);
+ if (ac_ret != APP_CONTROL_ERROR_NONE) {
+ return -1;
+ }
+ app_control_set_operation(ac_h, APP_CONTROL_OPERATION_DEFAULT);
+ app_control_set_app_id(ac_h, WORKER_INFO_SYS);
- cmd_id = ttd_cmd_get_id(c_data);
- retv_if(!cmd_id, -1);
+ app_control_add_extra_data(ac_h, "id", cmd_id);
- switch (ttd_cmd_get_command(c_data)) {
- case TTD_CMD_INFO_GET_SYSINFO:
- app_id = WORKER_INFO_SYS;
- break;
- case TTD_CMD_INFO_GET_TASKINFO:
- app_id = WORKER_INFO_TASK;
- break;
- case TTD_CMD_INFO_GET_MAX:
- default:
+ ac_ret = app_control_send_launch_request(ac_h, NULL, NULL);
+ if (ac_ret != APP_CONTROL_ERROR_NONE) {
+ if (ac_h)
+ app_control_destroy(ac_h);
return -1;
- break;
}
+ return 0;
+}
+
+static int _exec_application_pkgmgr(const char *cmd_id,const char *op,const char *extra)
+{
+ app_control_h ac_h = NULL;
+ int ac_ret = app_control_create(&ac_h);
- ac_ret = app_control_create(&ac_h);
if (ac_ret != APP_CONTROL_ERROR_NONE) {
- ret = -1;
- goto FREE_N_RETURN;
+ return -1;
}
app_control_set_operation(ac_h, APP_CONTROL_OPERATION_DEFAULT);
- app_control_set_app_id(ac_h, app_id);
-
+ app_control_set_app_id(ac_h, WORKER_PKG_MGR);
+ app_control_add_extra_data(ac_h, "operation", op);
app_control_add_extra_data(ac_h, "id", cmd_id);
+ if (extra)
+ app_control_add_extra_data(ac_h, "meta", extra);
+
ac_ret = app_control_send_launch_request(ac_h, NULL, NULL);
if (ac_ret != APP_CONTROL_ERROR_NONE) {
- ret = -1;
- goto FREE_N_RETURN;
+ if (ac_h)
+ app_control_destroy(ac_h);
+ return -1;
}
+ return 0;
+}
-FREE_N_RETURN:
- if (ac_h)
- app_control_destroy(ac_h);
+static int _exec_process(const char *path, const char *name, const char *cmd_id, const char *data)
+{
+ const char * const args[4] = {name, cmd_id, data, NULL};
+ int child = fork();
+ if (child == -1)
+ {
+ _D("Failed to fork");
+ return -3;
+ }
+ else if (child > 0)
+ {
+ _D("Forked succesfully");
+ return 0;
+ }
+ else
+ {
+ execv(path, (char * const*) args);
+ _D("Failed to exec %s", path);
+ exit(EXIT_FAILURE);
+ }
+}
+
+int ttd_worker_handle_info(ttd_cmd_data *c_data)
+{
+ int ret = 0;
+ const char *cmd_id = NULL;
+ unsigned int l = 0;
+ void *data = NULL;
+
+ cmd_id = ttd_cmd_get_id(c_data);
+ retv_if(!cmd_id, -1);
+
+ switch (ttd_cmd_get_command(c_data)) {
+ case TTD_CMD_INFO_GET_SYSINFO:
+ ret = _exec_application_sysinfo(cmd_id);
+ break;
+ case TTD_CMD_INFO_GET_TASKINFO:
+ ttd_cmd_get_data(c_data, &data, &l);
+ ret = _exec_process(WORKER_INFO_TASK_PATH, WORKER_INFO_TASK_NAME, cmd_id, data);
+ break;
+ case TTD_CMD_INFO_GET_MAX:
+ default:
+ return -1;
+ break;
+ }
return ret;
}
int ttd_worker_handle_pkgmgr(ttd_cmd_data *c_data)
{
- app_control_h ac_h = NULL;
- int ac_ret = APP_CONTROL_ERROR_NONE;
const char *op = NULL;
char *extra = NULL;
unsigned int length = 0;
return -1;
}
- ac_ret = app_control_create(&ac_h);
- if (ac_ret != APP_CONTROL_ERROR_NONE) {
- ret = -1;
- goto FREE_N_RETURN;
- }
- app_control_set_operation(ac_h, APP_CONTROL_OPERATION_DEFAULT);
- app_control_set_app_id(ac_h, WORKER_PKG_MGR);
- app_control_add_extra_data(ac_h, "operation", op);
- app_control_add_extra_data(ac_h, "id", cmd_id);
-
- if (extra)
- app_control_add_extra_data(ac_h, "meta", extra);
-
- ac_ret = app_control_send_launch_request(ac_h, NULL, NULL);
- if (ac_ret != APP_CONTROL_ERROR_NONE) {
- ret = -1;
- goto FREE_N_RETURN;
- }
-
-FREE_N_RETURN:
- if (ac_h)
- app_control_destroy(ac_h);
+ ret = _exec_application_pkgmgr(cmd_id, op, extra);
if (extra)
g_free(extra);
--- /dev/null
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<?eclipse-pydev version="1.0"?><pydev_project>
+<pydev_pathproperty name="org.python.pydev.PROJECT_SOURCE_PATH">
+<path>/${PROJECT_DIR_NAME}</path>
+</pydev_pathproperty>
+<pydev_property name="org.python.pydev.PYTHON_PROJECT_VERSION">python interpreter</pydev_property>
+<pydev_property name="org.python.pydev.PYTHON_PROJECT_INTERPRETER">python2.7</pydev_property>
+</pydev_project>
--- /dev/null
+import requests
+import ConfigParser
+import getopt
+import sys
+from enum import Enum
+
+config_filename = "config.ini"
+
+
+class CMD_TYPE(Enum):
+ POWER = 0
+ CONFIG = 1
+ PACKAGE = 2
+ DIAGNOSIS = 3
+ INFO = 4
+ LOCAL = 5
+
+
+class CMD_POWER(Enum):
+ OFF = 0
+ RESTART = 1
+
+
+class CMD_CONFIG(Enum):
+ SET_SERVER_URL = 0
+ SET_APP_ID = 1
+
+
+class CMD_PACKAGE(Enum):
+ INSTALL = 0
+ REMOVE = 1
+ GET_APP_LIST = 2
+ GET_PACKAGE_LIST = 3
+
+
+class CMD_DIAGNOSIS(Enum):
+ GET_LOG = 0
+
+
+class CMD_INFO(Enum):
+ GET_SYSINFO = 0
+ GET_TASKINFO = 1
+
+
+class CMD_LOCAL(Enum):
+ SOMETHING = 0
+ GET_CMD = 1
+
+
+def _ConfigSectionMap(section, Config):
+ opt_dict = {}
+ options = Config.options(section)
+ for option in options:
+ try:
+ opt_dict[option] = Config.get(section, option)
+ except BaseException:
+ print("exception on %s!" % option)
+ opt_dict[option] = None
+ return opt_dict
+
+
+switchopt = {
+ '-t': 'type',
+ '-type': 'type',
+ '-a': 'action',
+ '-action': 'action',
+ '-c': 'content',
+ '-content': 'content',
+ '-d': 'device',
+ '-device': 'device',
+ '-s': 'server',
+ '-server': 'server',
+ '-p': 'port',
+ '-port': 'port',
+ '-n': 'name',
+ '-name': 'name'
+}
+
+switchtype = {
+ "power": CMD_TYPE.POWER,
+ "config": CMD_TYPE.CONFIG,
+ "package": CMD_TYPE.PACKAGE,
+ "diagnosis": CMD_TYPE.DIAGNOSIS,
+ "info": CMD_TYPE.INFO,
+ "local": CMD_TYPE.LOCAL
+}
+
+switchpower = {
+ "off": CMD_POWER.OFF,
+ "restart": CMD_POWER.RESTART
+}
+
+switchconfig = {
+ "set_server_url": CMD_CONFIG.SET_SERVER_URL,
+ "set_app_id": CMD_CONFIG.SET_APP_ID
+}
+
+switchpackage = {
+ "install": CMD_PACKAGE.INSTALL,
+ "remove": CMD_PACKAGE.REMOVE,
+ "get_app_list": CMD_PACKAGE.GET_APP_LIST,
+ "get_package_list": CMD_PACKAGE.GET_PACKAGE_LIST
+}
+
+switchdiagnosis = {
+ "get_log": CMD_DIAGNOSIS.GET_LOG
+}
+
+switchinfo = {
+ "get_sysinfo": CMD_INFO.GET_SYSINFO,
+ "get_taskinfo": CMD_INFO.GET_TASKINFO
+}
+
+switchlocal = {
+ "something": CMD_LOCAL.SOMETHING,
+ "get_cmd": CMD_LOCAL.GET_CMD
+}
+
+
+def _usage():
+ sys.exit(
+ "usage: cloudinjector.sh -t type -a action -d device [-c content] [-s server] [-p port] [-n name]")
+
+
+def _send_post(options):
+
+ payload = {
+ "type": options["type"].value,
+ "action": options["action"].value,
+ "device": options["device"]}
+ if("content" in options):
+ tup = options["content"].split('=')
+ payload[tup[0]] = tup[1]
+ r = requests.post(
+ 'http://%s:%s/api/cmd?deviceId=%s' %
+ (options["server"],
+ options["port"],
+ options["name"]),
+ json=payload)
+ if(r.status_code >= 200 and r.status_code < 300):
+ print("Command sent!")
+ else:
+ sys.exit("POST command failed")
+
+
+def _send_power(options):
+ try:
+ options["action"] = switchpower[options["action"].lower()]
+ except BaseException:
+ sys.exit("Unknown action %s for type %s" %
+ (options["action"], options["type"].name))
+ _send_post(options)
+ pass
+
+
+def _send_config(options):
+ try:
+ options["action"] = switchconfig[options["action"].lower()]
+ except BaseException:
+ sys.exit("Unknown action %s for type %s" %
+ (options["action"], options["type"].name))
+ _send_post(options)
+ pass
+
+
+def _send_package(options):
+ try:
+ options["action"] = switchpackage[options["action"].lower()]
+ except BaseException:
+ sys.exit("Unknown action %s for type %s" %
+ (options["action"], options["type"].name))
+ _send_post(options)
+ pass
+
+
+def _send_diagnosis(options):
+ try:
+ options["action"] = switchdiagnosis[options["action"].lower()]
+ except BaseException:
+ sys.exit("Unknown action %s for type %s" %
+ (options["action"], options["type"].name))
+ _send_post(options)
+ pass
+
+
+def _send_info(options):
+ try:
+ options["action"] = switchinfo[options["action"].lower()]
+ except BaseException:
+ sys.exit("Unknown action %s for type %s" %
+ (options["action"], options["type"].name))
+ _send_post(options)
+ pass
+
+
+def _send_local(options):
+ try:
+ options["action"] = switchlocal[options["action"].lower()]
+ except BaseException:
+ sys.exit("Unknown action %s for type %s" %
+ (options["action"], options["type"].name))
+ _send_post(options)
+ pass
+
+
+switchfun = {
+ CMD_TYPE.POWER: _send_power,
+ CMD_TYPE.CONFIG: _send_config,
+ CMD_TYPE.PACKAGE: _send_package,
+ CMD_TYPE.DIAGNOSIS: _send_diagnosis,
+ CMD_TYPE.INFO: _send_info,
+ CMD_TYPE.LOCAL: _send_local
+}
+
+
+def main():
+ Config = ConfigParser.ConfigParser()
+ Config.read(config_filename)
+ defaults = _ConfigSectionMap("Defaults", Config)
+ options = dict(defaults)
+ (optlist, args) = getopt.getopt(sys.argv[1:], "t:a:c:d:s:p:n:", [
+ 'type', 'action', 'content', 'device', 'server', 'port', 'name'])
+ for tup in optlist:
+ options[switchopt[tup[0]]] = tup[1]
+ print(options)
+ if("type" not in options):
+ _usage()
+ if("action" not in options):
+ _usage()
+ if("device" not in options):
+ _usage()
+ try:
+ options["type"] = switchtype[options["type"].lower()]
+ except KeyError:
+ sys.exit("Incorrect type")
+ switchfun[options["type"]](options)
--- /dev/null
+[Defaults]
+server = 127.0.0.1
+port = 5000
+name = cloud-injector
--- /dev/null
+*.project
+*.pydevproject
+/REST/**/*
+*.pyc
--- /dev/null
+from command import Command
+from deviceinfo import DeviceInfo
+from threading import Lock
+import regex
+from jsonpickle import encode, decode
+from logger import cloudlog
+
+
+def _get_device_name(commandId):
+ (deviceId, commandNo) = commandId.split(" ")
+ return deviceId
+
+
+class CloudData:
+ 'TTD cloud data'
+
+ def __init__(self, clouddata_filename="data/clouddata",
+ commands_filename="data/commands"):
+ self.idlock = Lock()
+ self.cmdlock = Lock()
+ self.zwidth = 7
+ self._load_data(clouddata_filename, commands_filename)
+
+ def get_commands(self, deviceId):
+ if(deviceId not in self.devices_dict):
+ self.register_device(deviceId)
+ return self.devices_dict[deviceId].get_prepared_commands()
+
+ def enqueue(self, deviceId, ctype, ccontent, source_device=""):
+ self._queue_command(
+ Command(deviceId + " " + str(self._get_id()), ctype, ccontent, source_device))
+
+ def process_report(self, dict_json):
+ self._update_command(dict_json)
+ try:
+ devicename = _get_device_name(dict_json["commandId"])
+ cloudlog("Got report from " + devicename)
+ except KeyError:
+ cloudlog("No commandId in JSON", "Error")
+
+ def register_device(self, deviceId):
+ if(deviceId in self.devices_dict):
+ cloudlog("Device " + deviceId + " already registered")
+ else:
+ cloudlog("Registering device " + deviceId)
+ self.devices_dict[deviceId] = DeviceInfo(deviceId)
+
+ def _load_data(self, clouddata_filename, commands_filename):
+ self.clouddata_filename = clouddata_filename
+ self.commands_filename = commands_filename
+ cloudlog("Opening " + clouddata_filename)
+ try:
+ self.file = open(clouddata_filename, "r")
+ except BaseException:
+ cloudlog(
+ "No file " +
+ clouddata_filename +
+ " found - creating default",
+ "Warning")
+ self.file = open(clouddata_filename, "w+")
+ self._maxid = 1
+ self.file.write("maxid=" + str(self._maxid).zfill(self.zwidth))
+ self.file.close()
+ return
+ m = regex.search('^maxid=(\d+)$', self.file.readline())
+ try:
+ self._maxid = int(m.group(1))
+ except AttributeError:
+ cloudlog(
+ "%s corrupted. Maxid=1" %
+ self.clouddata_filename, "Error")
+ self._maxid = 1
+ self.devices_dict = {}
+ cloudlog("Loading data")
+ cloudlog("Opening " + commands_filename)
+ try:
+ self.file = open(commands_filename, 'r')
+ except BaseException:
+ cloudlog(
+ "No commands file %s - generating new" %
+ commands_filename, "Warning")
+ return
+ for line in self.file:
+ try:
+ cmd = decode(line)
+ deviceId = _get_device_name(cmd.id)
+ if(deviceId not in self.devices_dict):
+ self.register_device(deviceId)
+ device = self._get_device(deviceId)
+ device.add_replace_command(cmd)
+ except BaseException:
+ cloudlog(
+ "%s is corrupted - stopped reading" %
+ self.commands_filename, "Error")
+ break
+ self.file.close()
+
+ def _get_id(self):
+ self.idlock.acquire()
+ try:
+ self._maxid = self._maxid + 1
+ self.file = open(self.clouddata_filename, "w+")
+ self.file.write(
+ "maxid=" + str(self._maxid).zfill(self.zwidth) + "\n")
+ self.file.close()
+ _id = self._maxid
+ finally:
+ self.idlock.release()
+ return _id
+
+ def _queue_command(self, command):
+ devicename = _get_device_name(command.id)
+ if(devicename not in self.devices_dict):
+ self.register_device(devicename)
+ device = self._get_device(devicename)
+ self._save_command(command)
+ device.add_command(command)
+ cloudlog("Enqueued command " + command.id + " on " + devicename)
+
+ def _update_command(self, dict_json):
+ commandId = ""
+ self.cmdlock.acquire()
+ try:
+ commandId = dict_json["commandId"]
+ cloudlog("Updating command %s" % commandId)
+ device = self._get_device_from_command(commandId)
+ command = device.pop_command(commandId)
+ command.state = dict_json["state"]
+ self._save_command(command)
+ device.add_command(command)
+ cloudlog("Updated %s" % commandId, "Info")
+ except KeyError:
+ cloudlog("_update_command: Wrong Fromat of JSON", "Error")
+ raise
+ finally:
+ self.cmdlock.release()
+
+ def _get_device_from_command(self, commandId):
+ return self._get_device(_get_device_name(commandId))
+
+ def _get_device(self, deviceId):
+ try:
+ device = self.devices_dict[deviceId]
+ return device
+ except KeyError:
+ cloudlog("_get_device: No device " + deviceId + " found", "Error")
+ raise
+
+ def _save_command(self, command):
+ self.file = open(self.commands_filename, 'a+')
+ self.file.seek(0, 2)
+ self.file.write(encode(command) + "\n")
+ self.file.close()
--- /dev/null
+from enum import Enum
+from logger import cloudlog
+
+
+def dictionarize_command(command):
+ cloudlog(command)
+ json_ob = {
+ "id": command.id,
+ "type": command.type,
+ "content": command.content.__dict__}
+ return json_ob
+
+
+def dictionarize_commands(commands):
+ json_ob = {"Items": list(map(lambda o: dictionarize_command(o), commands))}
+ return json_ob
+
+
+def compare_commands(cmd1, cmd2):
+ return cmd1.id == cmd2.id and cmd1.type == cmd2.type
+
+
+def update_command(cmd, dict_json):
+ if(not compare_commands(cmd, dict_json)):
+ raise ValueError
+ cmd.state = dict_json["state"]
+ cmd.content.code = dict_json["content"]["code"]
+ if ("data" in dict_json["content"]):
+ cmd.content.data = dict_json["content"]["data"]
+ if ("desc" in dict_json["content"]):
+ cmd.content.desc = dict_json["content"]["desc"]
+
+
+class CMD_STATE(Enum):
+ TTD_CMD_STATE_UNKNOWN = -1
+ TTD_CMD_STATE_CREATED = 0
+ TTD_CMD_STATE_RUNNING = 1
+ TTD_CMD_STATE_DONE = 2
+ TTD_CMD_STATE_FAILED = 3
+ TTD_CMD_STATE_CANCELED = 4
+
+
+class CMD_TYPE(Enum):
+ TTD_CMD_TYPE_UNKNOWN = -1
+ TTD_CMD_TYPE_POWER = 0
+ TTD_CMD_TYPE_CONFIG = 1
+ TTD_CMD_TYPE_PACKAGE = 2
+ TTD_CMD_TYPE_DIAGNOSIS = 3
+ TTD_CMD_TYPE_INFO = 4
+ TTD_CMD_TYPE_LOCAL = 5
+ TTD_CMD_TYPE_MAX = 6
+
+
+class CMD_POWER(Enum):
+ TTD_CMD_POWER_OFF = 0
+ TTD_CMD_POWER_RESTART = 1
+ TTD_CMD_POWER_MAX = 2
+
+
+class CMD_CONFIG(Enum):
+ TTD_CMD_CONFIG_SET = 0
+ TTD_CMD_CONFIG_MAX = 1
+
+
+class CMD_CONFIG_ACTION(Enum):
+ TTD_CMD_CONFIG_SET_SERVER_URL = 0
+ TTD_CMD_CONFIG_SET_APP_ID = 1
+ TTD_CMD_CONFIG_ACTION_MAX = 2
+
+
+class CMD_PACKAGE(Enum):
+ TTD_CMD_PACKAGE_INSTALL = 0
+ TTD_CMD_PACKAGE_REMOVE = 1
+ TTD_CMD_PACKAGE_GET_APP_LIST = 2
+ TTD_CMD_PACKAGE_GET_PACKAGE_LIST = 3
+ TTD_CMD_PACKAGE_MAX = 4
+
+
+class CMD_DIAGNOSIS(Enum):
+ TTD_CMD_DIAGNOSIS_GET_LOG = 0
+ TTD_CMD_DIAGNOSIS_MAX = 1
+
+
+class CMD_INFO(Enum):
+ TTD_CMD_INFO_GET_SYSINFO = 0
+ TTD_CMD_INFO_GET_TASKINFO = 1
+ TTD_CMD_INFO_GET_MAX = 2
+
+
+class CMD_LOCAL(Enum):
+ TTD_CMD_LOCAL_SOMETHING = 0
+ TTD_CMD_LOCAL_GET_CMD = 1
+ TTD_CMD_LOCAL_MAX = 2
+
+
+class CMD_RESULT(Enum):
+ TTD_CMD_RESULT_RUNNING = 0
+ TTD_CMD_RESULT_SUCCESS = 1
+ TTD_CMD_RESULT_FAIL = 2
+
+
+class CommandContent:
+ def __init__(self, action, **kwargs):
+ self.action = action
+ self.__dict__.update(kwargs)
+ self.code = None
+ self.data = None
+ self.desc = None
+
+
+class Command:
+ 'TTD command data'
+
+ def __init__(self, cid, ctype, content, source_deviceId):
+ self.id = cid
+ self.type = ctype
+ self.content = content
+ self.state = None
+ self.sourceId = source_deviceId
--- /dev/null
+from command import CMD_STATE
+from logger import cloudlog
+
+
+class DeviceInfo:
+ 'Stores info about device'
+
+ def __init__(self, deviceId, commands=[]):
+ self.id = deviceId
+ self.prepared_commands = {}
+ self.running_commands = {}
+ self.finished_commands = {}
+ if(isinstance(commands, dict)):
+ commands = commands.values()
+ for c in commands:
+ self.add_command(c)
+
+ def add_command(self, command):
+ if(command.id not in self._choose_dict(command)):
+ self._choose_dict(command)[command.id] = command
+ cloudlog("Added command %s to %s" % (command.id, self.id))
+ else:
+ cloudlog(
+ "add_command: Command already existing on " +
+ self.id,
+ "Error")
+ raise KeyError
+
+ def add_replace_command(self, command):
+ if(command.id not in self._choose_dict(command)):
+ self._choose_dict(command)[command.id] = command
+ cloudlog("Added command %s to %s" % (command.id, self.id))
+ else:
+ self._choose_dict(command)[command.id] = command
+ cloudlog("Replaced command %s on %s " % (command.id, self.id))
+
+ def pop_command(self, commandId):
+ cloudlog("Popping " + commandId)
+ to_return = self._find_dict_by_id(commandId).pop(commandId, None)
+ if(to_return is None):
+ cloudlog("pop_command: No command %s" % commandId, "Error")
+ raise KeyError
+ return to_return
+
+ def get_prepared_commands(self):
+ return self.prepared_commands.values()
+
+ def _choose_dict(self, command):
+ if(command.state in (CMD_STATE.TTD_CMD_STATE_DONE.value, CMD_STATE.TTD_CMD_STATE_FAILED.value, CMD_STATE.TTD_CMD_STATE_CANCELED.value)):
+ return self.finished_commands
+ elif(command.state == CMD_STATE.TTD_CMD_STATE_RUNNING.value):
+ return self.running_commands
+ else:
+ return self.prepared_commands
+
+ def _find_dict_by_id(self, commandId):
+ if(commandId in self.prepared_commands):
+ return self.prepared_commands
+ if(commandId in self.finished_commands):
+ return self.finished_commands
+ if(commandId in self.running_commands):
+ return self.running_commands
+ cloudlog("_find_dict_by_id: No command " + commandId, "Error")
--- /dev/null
+import logging
+
+logging.basicConfig(level=logging.DEBUG, datefmt="%Y-%m-%d %H:%M:%S")
+logger = logging.getLogger("logger")
+handler = logging.FileHandler('cloud.log')
+handler.setLevel(logging.DEBUG)
+formatter = logging.Formatter(
+ '%(asctime)s - %(levelname)s: %(message)s',
+ "%Y-%m-%d %H:%M:%S")
+handler.setFormatter(formatter)
+logger.addHandler(handler)
+
+
+def cloudlog(text, level="Debug"):
+ to_log = str(text)
+ if(level == "Debug"):
+ logger.debug(to_log)
+ elif(level == "Error"):
+ logger.error(to_log)
+ elif(level == "Warning"):
+ logger.warning(to_log)
+ elif(level == "Critical"):
+ logger.critical(to_log)
+ elif(level == "Info"):
+ logger.info(to_log)
+ else:
+ logger.debug(to_log)
--- /dev/null
+from flask import Flask, jsonify
+from flask_restful import Api, Resource
+from flask.globals import request
+from command import dictionarize_commands, CommandContent
+from clouddata import CloudData
+from logger import cloudlog
+import traceback
+
+
+def main():
+
+ app = Flask(__name__)
+ cloudlog("Build cloud data", "Info")
+ clouddata = CloudData()
+
+ class TTDApiCommands(Resource):
+
+ def get(self):
+ try:
+ cloudlog(
+ "GET request " +
+ request.url +
+ " from " +
+ request.remote_addr,
+ "Info")
+ deviceId = request.args.get('deviceId', '')
+ if(deviceId == ''):
+ cloudlog("Request with no deviceId", "Warning")
+ return "Specify deviceId", 404
+ json_response = jsonify(
+ dictionarize_commands(
+ clouddata.get_commands(deviceId)))
+ cloudlog(
+ "GET request " +
+ request.url +
+ " from " +
+ request.remote_addr +
+ " return: \n" +
+ json_response.response[0],
+ "Info")
+ return json_response
+ except BaseException:
+ cloudlog(
+ "GET request " +
+ request.url +
+ " from " +
+ request.remote_addr +
+ " failed",
+ "Error")
+ cloudlog(traceback.format_exc())
+ return None, 404
+
+ def post(self):
+ try:
+ cloudlog("POST request " +
+ request.url +
+ " from " +
+ request.remote_addr +
+ "\n" +
+ str(request.get_data()), "Info")
+ source_deviceId = request.args.get('deviceId', '')
+ json_content = request.get_json()
+ action = json_content.pop("action", None)
+ ctype = json_content.pop("type", None)
+ deviceId = json_content.pop("device", None)
+ if(ctype is None):
+ cloudlog(
+ "POST request " +
+ request.url +
+ " from " +
+ request.remote_addr +
+ " failed - no type",
+ "Error")
+ return None, 404
+ if(action is None):
+ cloudlog(
+ "POST request " +
+ request.url +
+ " from " +
+ request.remote_addr +
+ " failed - no action",
+ "Error")
+ return None, 404
+ if(deviceId is None):
+ cloudlog(
+ "POST request " +
+ request.url +
+ " from " +
+ request.remote_addr +
+ " failed - no target device",
+ "Error")
+ return None, 404
+ ccontent = CommandContent(action, **json_content)
+ clouddata.enqueue(
+ deviceId, int(ctype), ccontent, source_deviceId)
+ cloudlog(
+ "POST request " +
+ request.url +
+ " from " +
+ request.remote_addr +
+ " succeded",
+ "Info")
+ return "OK", 200
+ except BaseException:
+ cloudlog(
+ "POST request " +
+ request.url +
+ " from " +
+ request.remote_addr +
+ " failed",
+ "Error")
+ cloudlog(traceback.format_exc())
+ return None, 404
+
+ class TTDApiReports(Resource):
+ def post(self):
+ try:
+ cloudlog("POST request " +
+ request.url +
+ " from " +
+ request.remote_addr +
+ "\n" +
+ str(request.get_data()), "Info")
+ clouddata.process_report(request.get_json())
+ cloudlog(
+ "POST request " +
+ request.url +
+ " from " +
+ request.remote_addr +
+ " succeded",
+ "Info")
+ return "OK", 200
+ except BaseException:
+ cloudlog(
+ "POST request " +
+ request.url +
+ " from " +
+ request.remote_addr +
+ " failed",
+ "Error")
+ cloudlog(traceback.format_exc())
+ return None, 404
+
+ api = Api(app)
+ api.add_resource(TTDApiCommands, "/api/cmd")
+ api.add_resource(TTDApiReports, "/api/report/cmd")
+ app.run(host="106.120.63.28", port=5000, debug=True)
+
+
+if(__name__ == "__main__"):
+ main()
--- /dev/null
+# -*- mode: python -*-
+
+block_cipher = None
+
+
+a = Analysis(['main.py'],
+ pathex=['/home/k.wieclaw/eclipse-workspace/CloudMockup'],
+ binaries=[],
+ datas=[],
+ hiddenimports=[],
+ hookspath=[],
+ runtime_hooks=[],
+ excludes=[],
+ win_no_prefer_redirects=False,
+ win_private_assemblies=False,
+ cipher=block_cipher)
+pyz = PYZ(a.pure, a.zipped_data,
+ cipher=block_cipher)
+exe = EXE(pyz,
+ a.scripts,
+ exclude_binaries=True,
+ name='main',
+ debug=False,
+ strip=False,
+ upx=True,
+ console=True )
+coll = COLLECT(exe,
+ a.binaries,
+ a.zipfiles,
+ a.datas,
+ strip=False,
+ upx=True,
+ name='main')