add: macro endpoint for execution

This commit is contained in:
Tobias Reisinger 2020-09-06 13:12:33 +02:00
parent 01ffb1d58d
commit d3fd48b35a
9 changed files with 110 additions and 26 deletions

View file

@ -18,4 +18,7 @@ api_v1_macros_STR_PUT(struct mg_connection *nc, struct http_message *hm, endpoin
void void
api_v1_macros_STR_DELETE(struct mg_connection *nc, struct http_message *hm, endpoint_args_t *args, endpoint_response_t *response); 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 */ #endif /* CORE_ENDPOINTS_API_V1_MACROS_H */

View file

@ -6,7 +6,6 @@
#include <cJSON.h> #include <cJSON.h>
#include <constants.h> #include <constants.h>
#include <models/period.h>
#include <models/macro_action.h> #include <models/macro_action.h>
typedef struct typedef struct
@ -43,4 +42,7 @@ macro_get_by_uid(uuid_t uid);
macro_t** macro_t**
macro_get_all(); macro_get_all();
int*
macro_get_target_relay_ids(int macro_id);
#endif /* CORE_MACRO_H */ #endif /* CORE_MACRO_H */

View file

@ -18,6 +18,9 @@ macro_action_delete_for_macro(int macro_id);
macro_action_t** macro_action_t**
macro_action_get_for_macro(int macro_id); macro_action_get_for_macro(int macro_id);
int
macro_action_execute(macro_action_t *macro_action);
void void
macro_action_free_list(macro_action_t **macro_actions); macro_action_free_list(macro_action_t **macro_actions);

View file

@ -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"); cJSON *json_actions = cJSON_GetObjectItemCaseSensitive(json, "actions");
if(cJSON_IsArray(json_actions)) if(cJSON_IsArray(json_actions))
{ {
macro_action_delete_for_macro(macro->id);
cJSON *json_action; cJSON *json_action;
cJSON_ArrayForEach(json_action, json_actions) cJSON_ArrayForEach(json_action, json_actions)
{ {

View file

@ -0,0 +1,64 @@
#include <cJSON.h>
#include <macros.h>
#include <constants.h>
#include <endpoints/api_v1_macros.h>
#include <logger.h>
#include <command.h>
#include <models/macro_action.h>
#include <models/macro.h>
#include <models/relay.h>
#include <models/tag.h>
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");
}

View file

@ -95,7 +95,7 @@ junction_relay_schedule_get_relay_ids_with_schedule(int schedule_id)
{ {
sqlite3_stmt *stmt; 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); sqlite3_bind_int(stmt, 1, schedule_id);
return database_helper_get_ids(stmt); return database_helper_get_ids(stmt);

View file

@ -160,28 +160,6 @@ macro_remove(macro_t *macro)
return rc != SQLITE_DONE; 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 void
macro_free(macro_t *macro) macro_free(macro_t *macro)
{ {
@ -339,3 +317,14 @@ macro_get_all()
return macro_db_select(stmt); 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);
}

View file

@ -123,6 +123,28 @@ macro_action_get_for_macro(int macro_id)
return macro_action_db_select(stmt); 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 void
macro_action_free_list(macro_action_t **macro_actions) macro_action_free_list(macro_action_t **macro_actions)
{ {

View file

@ -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_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_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}", 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); router_register_endpoint("/api/v1/ws/relays", HTTP_METHOD_WEBSOCKET, api_v1_ws_relays);
} }