From 4872f71428a10bd1e18020249f882a11e4d92a3c Mon Sep 17 00:00:00 2001 From: NADAL Jean-Baptiste Date: Thu, 26 Dec 2019 16:34:26 +0100 Subject: [PATCH] device manager now load data. --- share/domo/capabilities.json | 16 ++++++ share/domo/devices.json | 65 ++++++++++++++++++++++++ share/domo/sequence-ref.json | 84 +++++++++++++++++++++++++++++++ share/domo/sequences.json | 60 ++++++++++++++++++++++ src/CMakeLists.txt | 17 ++++--- src/devices/devices_manager.c | 77 ++++++++++++++++++++++++----- src/devices/devices_manager.h | 4 +- src/devices/outlet_dio.c | 8 ++- src/main.c | 93 ++++++++++++++++++++++++++++++++++- 9 files changed, 398 insertions(+), 26 deletions(-) create mode 100644 share/domo/capabilities.json create mode 100644 share/domo/devices.json create mode 100644 share/domo/sequence-ref.json create mode 100644 share/domo/sequences.json diff --git a/share/domo/capabilities.json b/share/domo/capabilities.json new file mode 100644 index 0000000..96a45da --- /dev/null +++ b/share/domo/capabilities.json @@ -0,0 +1,16 @@ +{ + "capabilities": [ + { + "name": "outlets", + "speech_name": "lumière" + }, + { + "name": "shutters", + "speech_name": "volet" + }, + { + "name": "sprinklers", + "speech_name": "station" + } + ] +} \ No newline at end of file diff --git a/share/domo/devices.json b/share/domo/devices.json new file mode 100644 index 0000000..76bfccf --- /dev/null +++ b/share/domo/devices.json @@ -0,0 +1,65 @@ +{ + "outlets": [ + { + "id": 1, + "name": "Bureau JB", + "speech_name": "bureau", + "state": true, + "zone": "", + "sender": 12797322, + "switch": 0 + }, + { + "id": 2, + "name": "Salon", + "speech_name": "salon", + "state": false, + "zone": "", + "sender": 12797322, + "switch": 1 + }, + { + "id": 3, + "name": "Sapin", + "speech_name": "sapin", + "state": false, + "zone": "", + "sender": 12797322, + "switch": 2 + } + ], + "shutters": [ + { + "id": 1, + "name": "Chambre de JB", + "state": true, + "zone": "", + "sender": 14997046, + "switch": 12, + "speed_up": 20, + "speed_down": 18 + } + ], + "sprinklers": [ + { + "id": 7, + "name": "Zone A", + "state": false + }, + { + "id": 8, + "name": "Zone B", + "state": false + }, + { + "id": 25, + "name": "Zone C", + "state": false + }, + { + "id": 24, + "name": "Zone D", + "state": false + } + ] +} \ No newline at end of file diff --git a/share/domo/sequence-ref.json b/share/domo/sequence-ref.json new file mode 100644 index 0000000..8b151a6 --- /dev/null +++ b/share/domo/sequence-ref.json @@ -0,0 +1,84 @@ +{ + "sequences": [ + { + "id": 1, + "name": "arrosage", + "timer": { + "active": true, + "start_time": "17:30", + "recurrence": 1 + }, + "actions": [ + { + "device_id": "sprinkler/7", + "state": true, + "duration": 2 + }, + { + "device_id": "sprinkler/8", + "state": true, + "duration": 1 + } + ] + }, + { + "id": 2, + "name": "sapin", + "timer": { + "active": false, + "start_time": "21:48", + "recurrence": 0 + }, + "actions": [ + { + "device_id": "light/7", + "state": true, + "duration": 2 + } + ] + }, + { + "id": 2, + "name": "volet", + "timer": { + "active": false, + "start_time": "09:00", + "recurrence": 0 + }, + "actions": [ + [ + { + "device_id": "shutters/1", + "state": true + }, + { + "device_id": "shutters/2", + "state": true + } + ], + { + "duration": 60 + }, + [ + { + "device_id": "shutters/1", + "state": false + }, + { + "device_id": "shutters/2", + "state": false + } + ], + { + "device_id": "shutters/1", + "state": true, + "duration": 60 + }, + { + "device_id": "shutters/1", + "state": false + } + ] + } + ] +} diff --git a/share/domo/sequences.json b/share/domo/sequences.json new file mode 100644 index 0000000..ca38da8 --- /dev/null +++ b/share/domo/sequences.json @@ -0,0 +1,60 @@ +{ + "sequences": [ + { + "id": 1, + "name": "arrosage", + "timer": { + "active": true, + "start_time": "17:30", + "recurrence": 1 + }, + "actions": [ + { + "device_id": "sprinkler/7", + "state": true, + "duration": 2 + }, + { + "device_id": "sprinkler/8", + "state": true, + "duration": 1 + } + ] + }, + { + "id": 2, + "name": "sapin", + "timer": { + "active": false, + "start_time": "21:48", + "recurrence": 0 + }, + "actions": [ + { + "device_id": "light/7", + "state": true, + "duration": 2 + } + ] + }, + { + "id": 2, + "name": "volet", + "timer": { + "active": false, + "start_time": "09:00", + "recurrence": 0 + }, + "actions": [ + { + "device_id": "shutters/1", + "state": true + }, + { + "device_id": "shutters/2", + "state": true + } + ] + } + ] +} \ No newline at end of file diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 02e18cf..2c65e68 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -3,16 +3,16 @@ cmake_minimum_required(VERSION 3.0) project(domo-iot) set (CMAKE_MODULE_PATH "${MODULE_PATH}") - +set(CMAKE_EXPORT_COMPILE_COMMANDS On) link_directories(${CMAKE_SOURCE_DIR}/build/lib) include_directories (${CMAKE_SOURCE_DIR}/domo-iot/lib/include) include_directories (${CMAKE_SOURCE_DIR}/libevent/include) -include_directories (${CMAKE_SOURCE_DIR}/build/libevent/include) +include_directories (${CMAKE_BINARY_DIR}/libevent/include) include_directories (${CMAKE_SOURCE_DIR}/qlibc/include) include_directories (${CMAKE_SOURCE_DIR}/json-c) -include_directories (${CMAKE_SOURCE_DIR}/build/json-c) +include_directories (${CMAKE_BINARY_DIR}/json-c) include_directories (${CMAKE_SOURCE_DIR}/nats.c/src) include_directories (${CMAKE_CURRENT_SOURCE_DIR}) @@ -31,9 +31,9 @@ file( rest/rest_handler.c ) -add_executable (domo-iot ${source_files}) +add_executable (${PROJECT_NAME} ${source_files}) -target_link_libraries (domo-iot +target_link_libraries (${PROJECT_NAME} LINK_PUBLIC nats_static restd-static @@ -44,4 +44,9 @@ target_link_libraries (domo-iot event_pthreads ) -install (TARGETS domo-iot DESTINATION local/bin) +install (TARGETS ${PROJECT_NAME} DESTINATION local/bin) + +add_custom_command(TARGET ${PROJECT_NAME} POST_BUILD + COMMAND cmake -E copy_directory ${CMAKE_CURRENT_SOURCE_DIR}/../share/domo ${CMAKE_BINARY_DIR}/share/domo + COMMENT "Install domo's config files." + ) diff --git a/src/devices/devices_manager.c b/src/devices/devices_manager.c index dabb1ab..a510c75 100644 --- a/src/devices/devices_manager.c +++ b/src/devices/devices_manager.c @@ -29,6 +29,7 @@ /*-------------------------------- INCLUDES ---------------------------------*/ #include +#include #include #include @@ -36,11 +37,14 @@ #include "macro.h" #include "domo.h" +#include "outlet_dio.h" + #include "devices_manager.h" /*----------------------------- LOCAL FUNCTIONS ----------------------------*/ int load_outlets(devices_manager_t *dm, struct json_object *node); +struct json_object *save_outlets(devices_manager_t *dm); int create_outlet(struct json_object *node); int load_shutters(devices_manager_t *dm, struct json_object *node); @@ -64,7 +68,7 @@ devices_manager_t *devices_manager_new(void) bzero((void *)devices_manager, sizeof(devices_manager_t)); // Initialize instance. - devices_manager->outlets = qhashtbl(0, 0); + devices_manager->outlets = qlist(0); devices_manager->shutters = qhashtbl(0, 0); devices_manager->sprinklers = qhashtbl(0, 0); @@ -90,15 +94,28 @@ void devices_manager_free(devices_manager_t *devices_manager) { devices_manager->sprinklers->free(devices_manager->sprinklers); } + + if (devices_manager->file_path != NULL) + { + free(devices_manager->file_path); + } + free(devices_manager); } /*--------------------------------------------------------------------------*/ -int devices_manager_load(devices_manager_t *dm) +int devices_manager_load(devices_manager_t *dm, char *config_path) { struct json_object *the_root_node, *the_value_node; - DEBUG("Devices::load...\n"); + DEBUG("Devices load...\n"); + + if (config_path == NULL) + { + fprintf(stderr, "Couldn't found the device config file.\n"); + return -1; + } + dm->file_path = config_path; the_root_node = json_object_from_file(dm->file_path); if (the_root_node == NULL) @@ -132,8 +149,25 @@ int devices_manager_load(devices_manager_t *dm) int devices_manager_save(devices_manager_t *dm) { - DEBUG("TODO"); - return 0; + int result; + struct json_object *root_node; + DEBUG("Devices save...\n"); + + root_node = json_object_new_object(); + + // Outlets + json_object_object_add(root_node, kOutletEntry, save_outlets(dm)); + // Shutters + //json_object_object_add(the_root_node, kShutterEntry, m_shutters.to_json()); + // Sprinklers + //json_object_object_add(the_root_node, kSprinklerEntry, m_sprinklers.to_json()); + + result = json_object_to_file_ext(dm->file_path, root_node, JSON_C_TO_STRING_PRETTY); + + /* Clean the json object. */ + json_object_put(root_node); + + return result; } /*--------------------------------------------------------------------------*/ @@ -212,13 +246,12 @@ int load_outlets(devices_manager_t *dm, struct json_object *node) length = json_object_array_length(node); for (int i = 0; i < length; i++) { - /* - OutletDio* the_outlet = new OutletDio; - the_outlet_node = json_object_array_get_idx(a_node, i); - the_outlet->from_json(the_outlet_node); - - m_outlets.add(the_outlet); - */ + outlet_dio_t *outlet = outlet_dio_new(); + outlet_node = json_object_array_get_idx(node, i); + if (outlet_dio_from_json(outlet, outlet_node) == 0) + { + qlist_addlast(dm->outlets, outlet, sizeof(outlet_dio_t)); + } } } @@ -227,6 +260,26 @@ int load_outlets(devices_manager_t *dm, struct json_object *node) /*--------------------------------------------------------------------------*/ +struct json_object *save_outlets(devices_manager_t *dm) +{ + struct json_object *root_node; + outlet_dio_t *outlet; + qlist_obj_t obj; + + memset((void *) &obj, 0, sizeof(obj)); + root_node = json_object_new_array(); + + while (qlist_getnext(dm->outlets, &obj, true)) + { + outlet = obj.data; + json_object_array_add(root_node, outlet_dio_to_json_object(outlet)); + } + + return root_node; +} + +/*--------------------------------------------------------------------------*/ + int load_shutters(devices_manager_t *dm, struct json_object *node) { DEBUG("TODO"); diff --git a/src/devices/devices_manager.h b/src/devices/devices_manager.h index 717d154..df8ba65 100644 --- a/src/devices/devices_manager.h +++ b/src/devices/devices_manager.h @@ -48,7 +48,7 @@ struct devices_manager_s { char *file_path; - qhashtbl_t *outlets; + qlist_t *outlets; qhashtbl_t *shutters; qhashtbl_t *sprinklers; }; @@ -58,7 +58,7 @@ struct devices_manager_s extern devices_manager_t *devices_manager_new(void); extern void devices_manager_free(devices_manager_t *devices_manager); -extern int devices_manager_load(devices_manager_t *dm); +extern int devices_manager_load(devices_manager_t *dm, char *config_path); extern int devices_manager_save(devices_manager_t *dm); extern char *devices_manager_get(devices_manager_t *dm, const char *capability); diff --git a/src/devices/outlet_dio.c b/src/devices/outlet_dio.c index 0ac8d01..7d467a6 100644 --- a/src/devices/outlet_dio.c +++ b/src/devices/outlet_dio.c @@ -100,10 +100,6 @@ int outlet_dio_from_json(outlet_dio_t *outlet, struct json_object *node) outlet->switch_id = json_object_get_int(value_node); } - // Sanity checks. - // if ((the_switch == -1) || (the_sender == -1)) - // return -1; - return 0; } @@ -130,7 +126,9 @@ int outlet_dio_to_json(outlet_dio_t *outlet, struct json_object *node) // zone if (outlet->zone != NULL) json_object_object_add(node, k_entry_zone, json_object_new_string(outlet->zone)); - + else + json_object_object_add(node, k_entry_zone, json_object_new_string("")); + // sender json_object_object_add(node, k_entry_sender, json_object_new_int(outlet->sender_id)); // switch diff --git a/src/main.c b/src/main.c index 32c3e03..8de3113 100644 --- a/src/main.c +++ b/src/main.c @@ -28,10 +28,70 @@ /*-------------------------------- INCLUDES ---------------------------------*/ +#include +#include +#include +#include +#include + +#include + #include #include "rest/rest_handler.h" #include "broker/nats_broker.h" +#include "devices/devices_manager.h" + +#define k_max_path_len 200 /* make this larger if you need to. */ + +#define k_devices_file_path "share/domo/devices.json" +#define k_sequences_file_path "share/domo/sequences.json" + +/*--------------------------------------------------------------------------*/ + +char *get_config_path(const char *file_path) +{ + int length; + char full_path[k_max_path_len]; + char *working_path; + char *last_slash; + + length = readlink("/proc/self/exe", full_path, sizeof(full_path)); + + /* Catch some errors: */ + if (length < 0) + { + fprintf(stderr, "Error resolving symlink /proc/self/exe.\n"); + return NULL; + } + if (length >= k_max_path_len) + { + fprintf(stderr, "Path too long. Truncated.\n"); + return NULL; + } + + /* I don't know why, but the string this readlink() function + * returns is appended with a '@'. + */ + full_path[length] = '\0'; /* Strip '@' off the end. */ + + working_path = dirname(full_path); + last_slash = working_path != NULL ? strrchr(working_path, '/') : NULL; + if (last_slash != NULL) + { + full_path[(last_slash - working_path + 1)] = '\0'; + + strcat(full_path, file_path); + if (access(full_path, F_OK) != -1) + { + char *to_str = (char *) malloc(strlen(full_path) + 1); + to_str = strdup(full_path); + return to_str; + } + } + + return NULL; +} /*--------------------------------------------------------------------------*/ @@ -48,6 +108,8 @@ int main(int argc, char **argv) struct event_base *ev_base; restd_server_t *rest_server; nats_broker_t *nats_broker; + devices_manager_t *device_manager; + int ret; if (argc < 2) { @@ -57,6 +119,31 @@ int main(int argc, char **argv) restd_log_level(RESTD_LOG_DEBUG); + // data. + device_manager = devices_manager_new(); + if (device_manager == NULL) + { + fprintf(stderr, "Failed to create the device manager.\n"); + return -1; + } + if (devices_manager_load(device_manager, get_config_path(k_devices_file_path)) != 0) + { + fprintf(stderr, "Failed to Load the devices.\n"); + return -1; + } + devices_manager_save(device_manager); +#if 0 + /* Setup the Sequences Manager. */ + SequencesManager the_sequences_manager(the_config_path + "/sequences.json", &the_devices_manager); + if (the_sequences_manager.load() != 0) + { + fprintf(stderr, "Failed to load timers.\n"); + return -2; + } + + the_sequences_manager.save(); +#endif + /* event loop */ ev_base = event_base_new(); if (!ev_base) @@ -93,5 +180,9 @@ int main(int argc, char **argv) nats_broker_connect(nats_broker, "foo"); /* start the rest server */ - return restd_server_start(rest_server); + ret = restd_server_start(rest_server); + + /* Clean data. */ + + return ret; }