diff --git a/.editorconfig b/.editorconfig new file mode 100644 index 0000000..ab2168d --- /dev/null +++ b/.editorconfig @@ -0,0 +1,12 @@ +# EditorConfig is awesome: +https://EditorConfig.org + +# top-most EditorConfig file +root = true + +# Unix-style newlines with a newline ending every file +[*] +end_of_line = lf +insert_final_newline = true +indent_style = space +indent_size = 4 diff --git a/CMakeLists.txt b/CMakeLists.txt index 01efe82..7b625e5 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1,6 +1,6 @@ cmake_minimum_required (VERSION 3.7) project(core - VERSION 0.2.0 + VERSION 0.2.1 LANGUAGES C) add_executable(core src/main.c) diff --git a/include/command.h b/include/command.h index 01b045f..e69b7ff 100644 --- a/include/command.h +++ b/include/command.h @@ -13,4 +13,7 @@ command_set_controller_name(controller_t *controller); int command_send(controller_t *controller, int command_code, char *payload, uint32_t payload_size); +int +command_pulse(relay_t *relay, uint8_t duration); + #endif /* CORE_COMMAND_H */ diff --git a/include/endpoints/api_v1_controllers.h b/include/endpoints/api_v1_controllers.h index d487e58..6430079 100644 --- a/include/endpoints/api_v1_controllers.h +++ b/include/endpoints/api_v1_controllers.h @@ -27,4 +27,7 @@ api_v1_controllers_STR_relays_INT_GET(struct mg_connection *nc, struct http_mess void api_v1_controllers_STR_relays_INT_PUT(struct mg_connection *nc, struct http_message *hm, endpoint_args_t *args, endpoint_response_t *response); +void +api_v1_controllers_STR_relays_INT_pulse_POST(struct mg_connection *nc, struct http_message *hm, endpoint_args_t *args, endpoint_response_t *response); + #endif /* CORE_ENDPOINTS_API_V1_CONTROLLERS_H */ diff --git a/include/enums.h b/include/enums.h index 943efa7..a51ff31 100644 --- a/include/enums.h +++ b/include/enums.h @@ -16,6 +16,7 @@ typedef enum COMMAND_MAPPING_SCHEDULE_ID = 4, COMMAND_MAPPING_PERIODS_COUNT = 5, COMMAND_MAPPING_PERIODS_BLOB = 6, + COMMAND_MAPPING_PULSE_DURATION = 7, } control_mapping_t; typedef enum @@ -28,6 +29,7 @@ typedef enum COMMAND_CODE_GET_SCHEDULE = 103, COMMAND_CODE_SET_RELAY_NAME = 104, COMMAND_CODE_GET_RELAY_NAME = 105, + COMMAND_CODE_PULSE = 200, } command_code_t; typedef enum diff --git a/src/command.c b/src/command.c index 7c8075c..860f9b1 100644 --- a/src/command.c +++ b/src/command.c @@ -139,3 +139,47 @@ command_send(controller_t *controller, int command_code, char *payload, uint32_t close(fd_controller); return 0; } + +int +command_pulse(relay_t *relay, uint8_t duration) +{ + controller_t *controller = controller_get_by_id(relay->controller_id); + if(!controller) + { + LOG_ERROR("couldn't find controller\n"); + return 1; + } + + char* payload; + size_t payload_size; + mpack_writer_t writer; + mpack_writer_init_growable(&writer, &payload, &payload_size); + + // 3 = code, relay num, relay name, schedules(array) + mpack_start_map(&writer, 3); + + mpack_write_uint(&writer, COMMAND_MAPPING_CODE); + mpack_write_u8(&writer, COMMAND_CODE_PULSE); + + mpack_write_uint(&writer, COMMAND_MAPPING_RELAY_NUM); + mpack_write_u8(&writer, relay->number); + + mpack_write_uint(&writer, COMMAND_MAPPING_PULSE_DURATION); + mpack_write_u8(&writer, duration); + + mpack_finish_map(&writer); + + // finish writing + if (mpack_writer_destroy(&writer) != mpack_ok) + { + LOG_ERROR("an error occurred encoding the data"); + controller_free(controller); + return 1; + } + + int result = command_send(controller, COMMAND_CODE_PULSE, payload, payload_size); + + controller_free(controller); + free(payload); + return result; +} diff --git a/src/endpoints/api_v1_controllers_STR_relays_INT_pulse.c b/src/endpoints/api_v1_controllers_STR_relays_INT_pulse.c new file mode 100644 index 0000000..05efe7a --- /dev/null +++ b/src/endpoints/api_v1_controllers_STR_relays_INT_pulse.c @@ -0,0 +1,68 @@ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +void +api_v1_controllers_STR_relays_INT_pulse_POST(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)) + { + LOG_DEBUG("failed to unparse uid\n"); + + static const char content[] = "given id was invalid"; + endpoint_response_text(response, 400, content, STRLEN(content)); + return; + } + + controller_t* controller = controller_get_by_uid(target_uid); + + if(!controller) + { + LOG_DEBUG("could not find a controller for uid '%s'\n", args[0].value.v_str); + + static const char content[] = "no controller for id found"; + endpoint_response_text(response, 404, content, STRLEN(content)); + return; + } + + relay_t* relay = relay_get_for_controller(controller->id, args[1].value.v_int); + + if(!relay) + { + LOG_DEBUG("could not find a relay with num %d for controller '%s'\n", args[1].value.v_int, args[0].value.v_str); + + static const char content[] = "no relay for this controller found"; + endpoint_response_text(response, 404, content, STRLEN(content)); + return; + } + + uint8_t duration = 0; + cJSON *json = cJSON_ParseWithLength(hm->body.p, hm->body.len); + + if(json) + { + cJSON *json_duration = cJSON_GetObjectItemCaseSensitive(json, "duration"); + if(cJSON_IsNumber(json_duration) && json_duration->valueint) + { + duration = json_duration->valueint & 0xFF; + } + cJSON_Delete(json); + } + + command_pulse(relay, duration); + + endpoint_response_text(response, 200, "", 0); + relay_free(relay); + controller_free(controller); +} diff --git a/src/main.c b/src/main.c index a6618c8..c005696 100644 --- a/src/main.c +++ b/src/main.c @@ -146,7 +146,7 @@ main(int argc, const char** argv) for (;;) { - mg_mgr_poll(&mgr, 1000); + mg_mgr_poll(&mgr, 200); if(time(NULL) - timer >= 10) { status_broadcast(&mgr); diff --git a/src/router.c b/src/router.c index 809668e..10fa4f4 100644 --- a/src/router.c +++ b/src/router.c @@ -80,6 +80,7 @@ router_init() router_register_endpoint("/api/v1/controllers/{str}/relays/", HTTP_METHOD_GET, api_v1_controllers_STR_relays_GET); router_register_endpoint("/api/v1/controllers/{str}/relays/{int}", HTTP_METHOD_GET, api_v1_controllers_STR_relays_INT_GET); router_register_endpoint("/api/v1/controllers/{str}/relays/{int}", HTTP_METHOD_PUT, api_v1_controllers_STR_relays_INT_PUT); + router_register_endpoint("/api/v1/controllers/{str}/relays/{int}/pulse", HTTP_METHOD_POST, api_v1_controllers_STR_relays_INT_pulse_POST); router_register_endpoint("/api/v1/relays/", HTTP_METHOD_GET, api_v1_relays_GET); router_register_endpoint("/api/v1/relays/tag/{str}", HTTP_METHOD_GET, api_v1_relays_tag_STR_GET); @@ -88,7 +89,6 @@ router_init() router_register_endpoint("/api/v1/tags/{str}", HTTP_METHOD_GET, api_v1_tags_STR_GET); router_register_endpoint("/api/v1/tags/{str}", HTTP_METHOD_DELETE, api_v1_tags_STR_DELETE); - router_register_endpoint("/api/v1/ws/relays", HTTP_METHOD_WEBSOCKET, api_v1_ws_relays); }