diff --git a/include/endpoints/api_v1_macros.h b/include/endpoints/api_v1_macros.h index 2809c69..9a79271 100644 --- a/include/endpoints/api_v1_macros.h +++ b/include/endpoints/api_v1_macros.h @@ -18,4 +18,7 @@ api_v1_macros_STR_PUT(struct mg_connection *nc, struct http_message *hm, endpoin void api_v1_macros_STR_DELETE(struct mg_connection *nc, struct http_message *hm, endpoint_args_t *args, endpoint_response_t *response); +void +api_v1_macros_STR_execute_PUT(struct mg_connection *nc, struct http_message *hm, endpoint_args_t *args, endpoint_response_t *response); + #endif /* CORE_ENDPOINTS_API_V1_MACROS_H */ diff --git a/include/models/macro.h b/include/models/macro.h index 0ceb1ca..d532902 100644 --- a/include/models/macro.h +++ b/include/models/macro.h @@ -6,7 +6,6 @@ #include #include -#include #include typedef struct @@ -43,4 +42,7 @@ macro_get_by_uid(uuid_t uid); macro_t** macro_get_all(); +int* +macro_get_target_relay_ids(int macro_id); + #endif /* CORE_MACRO_H */ diff --git a/include/models/macro_action.h b/include/models/macro_action.h index 22ddd63..bd61d09 100644 --- a/include/models/macro_action.h +++ b/include/models/macro_action.h @@ -18,6 +18,9 @@ macro_action_delete_for_macro(int macro_id); macro_action_t** macro_action_get_for_macro(int macro_id); +int +macro_action_execute(macro_action_t *macro_action); + void macro_action_free_list(macro_action_t **macro_actions); diff --git a/src/endpoints/api_v1_macros_STR.c b/src/endpoints/api_v1_macros_STR.c index e2d228f..44a5e18 100644 --- a/src/endpoints/api_v1_macros_STR.c +++ b/src/endpoints/api_v1_macros_STR.c @@ -86,11 +86,11 @@ api_v1_macros_STR_PUT(struct mg_connection *nc, struct http_message *hm, endpoin } } + macro_action_delete_for_macro(macro->id); + cJSON *json_actions = cJSON_GetObjectItemCaseSensitive(json, "actions"); if(cJSON_IsArray(json_actions)) { - macro_action_delete_for_macro(macro->id); - cJSON *json_action; cJSON_ArrayForEach(json_action, json_actions) { diff --git a/src/endpoints/api_v1_macros_STR_execute.c b/src/endpoints/api_v1_macros_STR_execute.c new file mode 100644 index 0000000..33f3952 --- /dev/null +++ b/src/endpoints/api_v1_macros_STR_execute.c @@ -0,0 +1,64 @@ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +void +api_v1_macros_STR_execute_PUT(struct mg_connection *nc, struct http_message *hm, endpoint_args_t *args, endpoint_response_t *response) +{ + (void)hm; + (void)nc; + + uuid_t target_uid; + if(uuid_parse(args[0].value.v_str, target_uid)) + { + M_RESPONSE_400_NO_VALID_ID(response); + return; + } + + macro_t* macro = macro_get_by_uid(target_uid); + + if(!macro) + { + M_RESPONSE_404_NO_MACRO_FOUND_FOR_ID(response); + return; + } + + macro_action_t** macro_actions = macro_action_get_for_macro(macro->id); + + database_transaction_lock lock; + database_transaction_begin(&lock); + + for(int i = 0; macro_actions[i] != NULL; ++i) + { + macro_action_execute(macro_actions[i]); + } + + database_transaction_commit(&lock); + + int *target_relay_ids = macro_get_target_relay_ids(macro->id); + for(int i = 0; target_relay_ids[i] != 0; ++i) + { + relay_t *target_relay = relay_get_by_id(target_relay_ids[i]); + if(!target_relay) + { + LOGGER_ERR("failed to load target relay from database\n"); + continue; + } + command_relay_schedules_set(target_relay); + + relay_free(target_relay); + } + + free(target_relay_ids); + macro_action_free_list(macro_actions); + macro_free(macro); + + M_RESPONSE_TEXT_STATIC(LOGGER_DEBUG, response, 200, "macro got executed"); +} diff --git a/src/models/junction_relay_schedule.c b/src/models/junction_relay_schedule.c index f0854bf..50bedb7 100644 --- a/src/models/junction_relay_schedule.c +++ b/src/models/junction_relay_schedule.c @@ -95,7 +95,7 @@ junction_relay_schedule_get_relay_ids_with_schedule(int schedule_id) { sqlite3_stmt *stmt; - sqlite3_prepare_v2(global_database, "SELECT relay_id FROM junction_relay_schedule WHERE schedule_id=?1;", -1, &stmt, NULL); + sqlite3_prepare_v2(global_database, "SELECT DISTINCT relay_id FROM junction_relay_schedule WHERE schedule_id=?1;", -1, &stmt, NULL); sqlite3_bind_int(stmt, 1, schedule_id); return database_helper_get_ids(stmt); diff --git a/src/models/macro.c b/src/models/macro.c index 5bffdb3..0d19075 100644 --- a/src/models/macro.c +++ b/src/models/macro.c @@ -160,28 +160,6 @@ macro_remove(macro_t *macro) return rc != SQLITE_DONE; } -int -macro_is_protected(macro_t *macro) -{ - uuid_t tmp_uuid; - - memset(tmp_uuid, 0, sizeof(uuid_t)); - memcpy(tmp_uuid, "off", 3); - if(uuid_compare(macro->uid, tmp_uuid) == 0) - { - return 1; - } - - memset(tmp_uuid, 0, sizeof(uuid_t)); - memcpy(tmp_uuid, "on", 2); - if(uuid_compare(macro->uid, tmp_uuid) == 0) - { - return 1; - } - - return 0; -} - void macro_free(macro_t *macro) { @@ -339,3 +317,14 @@ macro_get_all() return macro_db_select(stmt); } + +int* +macro_get_target_relay_ids(int macro_id) +{ + sqlite3_stmt *stmt; + + sqlite3_prepare_v2(global_database, "SELECT DISTINCT relay_id FROM macro_actions WHERE macro_id=?1;", -1, &stmt, NULL); + sqlite3_bind_int(stmt, 1, macro_id); + + return database_helper_get_ids(stmt); +} diff --git a/src/models/macro_action.c b/src/models/macro_action.c index eb07116..97cbfc6 100644 --- a/src/models/macro_action.c +++ b/src/models/macro_action.c @@ -123,6 +123,28 @@ macro_action_get_for_macro(int macro_id) return macro_action_db_select(stmt); } +int +macro_action_execute(macro_action_t *macro_action) +{ + schedule_t *schedule = schedule_get_by_id(macro_action->schedule_id); + if(!schedule) + { + return 1; + } + + relay_t *relay = relay_get_by_id(macro_action->relay_id); + if(!relay) + { + free(schedule); + return 1; + } + + schedule_free(relay->schedules[macro_action->weekday]); + relay->schedules[macro_action->weekday] = schedule; + + return relay_save(relay); +} + void macro_action_free_list(macro_action_t **macro_actions) { diff --git a/src/router.c b/src/router.c index 23ef95d..13b8299 100644 --- a/src/router.c +++ b/src/router.c @@ -96,6 +96,7 @@ router_init() router_register_endpoint("/api/v1/macros/{str}", HTTP_METHOD_GET, api_v1_macros_STR_GET); router_register_endpoint("/api/v1/macros/{str}", HTTP_METHOD_PUT, api_v1_macros_STR_PUT); router_register_endpoint("/api/v1/macros/{str}", HTTP_METHOD_DELETE, api_v1_macros_STR_DELETE); + router_register_endpoint("/api/v1/macros/{str}/execute", HTTP_METHOD_PUT, api_v1_macros_STR_execute_PUT); router_register_endpoint("/api/v1/ws/relays", HTTP_METHOD_WEBSOCKET, api_v1_ws_relays); }