#include #include #include #include #include #include #include #include #include typedef enum { COMMAND_CODE_CONTROLLER_ID_GET = 0, COMMAND_CODE_CONTROLLER_TIME_GET = 1, COMMAND_CODE_CONTROLLER_NAME_SET = 2, COMMAND_CODE_CONTROLLER_NAME_GET = 3, COMMAND_CODE_RELAY_SCHEDULES_SET = 100, COMMAND_CODE_RELAY_SCHEDULES_GET = 101, COMMAND_CODE_RELAY_NAME_SET = 102, COMMAND_CODE_RELAY_NAME_GET = 103, COMMAND_CODE_RELAY_PULSE = 200, COMMAND_CODE_SCHEDULE_UPDATE = 300 } command_code_t; typedef enum { COMMAND_MAPPING_CODE = 0, COMMAND_MAPPING_NAME = 1, COMMAND_MAPPING_RELAY_NUM = 2, COMMAND_MAPPING_SCHEDULES_ARRAY = 3, COMMAND_MAPPING_SCHEDULE_ID = 4, COMMAND_MAPPING_PERIODS_COUNT = 5, COMMAND_MAPPING_PERIODS_BLOB = 6, COMMAND_MAPPING_PULSE_DURATION = 7, } control_mapping_t; int command_schedule_update(schedule_t *schedule) { char* payload; size_t payload_size; mpack_writer_t writer; mpack_writer_init_growable(&writer, &payload, &payload_size); // 4 = code, periods_count, schedule_id, periods_blob mpack_start_map(&writer, 4); mpack_write_uint(&writer, COMMAND_MAPPING_CODE); mpack_write_u16(&writer, COMMAND_CODE_SCHEDULE_UPDATE); uint16_t *periods_blob = schedule_periods_to_blob(schedule); uint16_t periods_count = periods_blob[0]; mpack_write_uint(&writer, COMMAND_MAPPING_PERIODS_COUNT); mpack_write_u16(&writer, periods_count); mpack_write_uint(&writer, COMMAND_MAPPING_SCHEDULE_ID); mpack_write_bin(&writer, (char*)schedule->uid, sizeof(uuid_t)); mpack_write_uint(&writer, COMMAND_MAPPING_PERIODS_BLOB); // periods + 1 to skip length in periods[0] // periods_count * 2 because each uint16_t is a timestamp. 2 are start and end mpack_write_bin(&writer, (char*)(periods_blob + 1), sizeof(uint16_t) * periods_count * 2); free(periods_blob); mpack_finish_array(&writer); mpack_finish_map(&writer); // finish writing if (mpack_writer_destroy(&writer) != mpack_ok) { LOGGER_ERR("an error occurred encoding the data"); return 1; } int result = 0; relay_t **relays = relay_get_with_schedule(schedule->id); for(int i = 0; relays[i] != NULL; ++i) { controller_t *controller = controller_get_by_id(relays[i]->controller_id); if(!controller) { LOGGER_ERR("couldn't find controller for relay %d\n", relays[i]->id); continue; } LOGGER_DEBUG("sending command to controller %s\n", controller->name); result |= command_send(controller, payload, payload_size); controller_free(controller); } relay_free_list(relays); free(payload); return result; } int command_relay_schedules_set(relay_t *relay) { controller_t *controller = controller_get_by_id(relay->controller_id); if(!controller) { LOGGER_ERR("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_u16(&writer, COMMAND_CODE_RELAY_SCHEDULES_SET); mpack_write_uint(&writer, COMMAND_MAPPING_RELAY_NUM); mpack_write_u8(&writer, relay->number); mpack_write_uint(&writer, COMMAND_MAPPING_SCHEDULES_ARRAY); // 7 = days of week mpack_start_array(&writer, 7); for(int i = 0; i < 7; ++i) { // 3 = uid, periods count, periods blob mpack_start_map(&writer, 3); uint16_t *periods_blob = schedule_periods_to_blob(relay->schedules[i]); uint16_t periods_count = periods_blob[0]; mpack_write_uint(&writer, COMMAND_MAPPING_SCHEDULE_ID); mpack_write_bin(&writer, (char*)relay->schedules[i]->uid, sizeof(uuid_t)); mpack_write_uint(&writer, COMMAND_MAPPING_PERIODS_COUNT); mpack_write_u16(&writer, periods_count); mpack_write_uint(&writer, COMMAND_MAPPING_PERIODS_BLOB); // periods + 1 to skip length in periods[0] // periods_count * 2 because each uint16_t is a timestamp. 2 are start and end mpack_write_bin(&writer, (char*)(periods_blob + 1), sizeof(uint16_t) * periods_count * 2); free(periods_blob); mpack_finish_map(&writer); } mpack_finish_array(&writer); mpack_finish_map(&writer); // finish writing if (mpack_writer_destroy(&writer) != mpack_ok) { LOGGER_ERR("an error occurred encoding the data"); controller_free(controller); return 1; } LOGGER_DEBUG("sending command to controller %s\n", controller->name); int result = command_send(controller, payload, payload_size); controller_free(controller); free(payload); return result; } int command_controller_name_set(controller_t *controller) { char* payload; size_t payload_size; mpack_writer_t writer; mpack_writer_init_growable(&writer, &payload, &payload_size); // write the example on the msgpack homepage mpack_start_map(&writer, 2); mpack_write_uint(&writer, COMMAND_MAPPING_CODE); mpack_write_u16(&writer, COMMAND_CODE_CONTROLLER_NAME_SET); mpack_write_uint(&writer, COMMAND_MAPPING_NAME); mpack_write_cstr(&writer, controller->name); mpack_finish_map(&writer); // finish writing if (mpack_writer_destroy(&writer) != mpack_ok) { LOGGER_ERR("an error occurred encoding the data"); return 1; } LOGGER_DEBUG("sending command to controller %s\n", controller->name); int result = command_send(controller, payload, payload_size); free(payload); return result; } int command_send(controller_t *controller, char *payload, uint32_t payload_size) { int bytes_transferred; int fd_controller = helper_connect_tcp_server(controller->ip, controller->port); if(fd_controller == -1) { LOGGER_ERR("can't open command socket %s:%d\n", controller->ip, controller->port); return 1; } if((bytes_transferred = send(fd_controller, &payload_size, sizeof(payload_size), 0)) <= 0) { LOGGER_ERR("error during sending size\n"); return 1; } if((bytes_transferred = send(fd_controller, payload, payload_size, 0)) <= 0) { LOGGER_ERR("error during sending\n"); return 1; } close(fd_controller); return 0; } int command_relay_pulse(relay_t *relay, uint8_t duration) { controller_t *controller = controller_get_by_id(relay->controller_id); if(!controller) { LOGGER_ERR("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_u16(&writer, COMMAND_CODE_RELAY_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) { LOGGER_ERR("an error occurred encoding the data\n"); controller_free(controller); return 1; } LOGGER_DEBUG("sending command to controller %s\n", controller->name); int result = command_send(controller, payload, payload_size); controller_free(controller); free(payload); return result; }