2020-05-05 23:05:36 +00:00
|
|
|
#include <stdlib.h>
|
|
|
|
#include <string.h>
|
|
|
|
#include <sqlite3.h>
|
|
|
|
|
|
|
|
#include <cJSON.h>
|
|
|
|
#include <logger.h>
|
|
|
|
#include <database.h>
|
|
|
|
#include <models/relay.h>
|
|
|
|
#include <models/controller.h>
|
|
|
|
#include <models/schedule.h>
|
|
|
|
#include <models/junction_tag.h>
|
|
|
|
#include <models/junction_relay_schedule.h>
|
|
|
|
#include <models/tag.h>
|
|
|
|
|
|
|
|
static int
|
|
|
|
db_update_insert(relay_t *relay, sqlite3_stmt *stmt)
|
|
|
|
{
|
|
|
|
int rc;
|
|
|
|
|
|
|
|
sqlite3_bind_int(stmt, 1, relay->id);
|
|
|
|
sqlite3_bind_int(stmt, 2, relay->number);
|
|
|
|
sqlite3_bind_text(stmt, 3, relay->name, -1, SQLITE_STATIC);
|
|
|
|
sqlite3_bind_int(stmt, 4, relay->controller_id);
|
|
|
|
|
|
|
|
rc = sqlite3_step(stmt);
|
|
|
|
|
|
|
|
sqlite3_finalize(stmt);
|
|
|
|
|
|
|
|
return rc != SQLITE_DONE;
|
|
|
|
}
|
|
|
|
static relay_t*
|
|
|
|
relay_db_select_mapper(sqlite3_stmt *stmt)
|
|
|
|
{
|
|
|
|
relay_t *new_relay = malloc(sizeof(relay_t));
|
|
|
|
for(int i = 0; i < sqlite3_column_count(stmt); i++)
|
|
|
|
{
|
|
|
|
const char *name = sqlite3_column_name(stmt, i);
|
|
|
|
switch(name[0])
|
|
|
|
{
|
|
|
|
case 'c': // controller_id
|
|
|
|
new_relay->controller_id = sqlite3_column_int(stmt, i);
|
|
|
|
break;
|
|
|
|
case 'i':
|
|
|
|
new_relay->id = sqlite3_column_int(stmt, i);
|
|
|
|
break;
|
|
|
|
case 'n':
|
|
|
|
switch(name[1])
|
|
|
|
{
|
|
|
|
case 'a': // name
|
|
|
|
strncpy(new_relay->name, (const char*)sqlite3_column_text(stmt, i), 127);
|
|
|
|
break;
|
|
|
|
case 'u': // number
|
|
|
|
new_relay->number = sqlite3_column_int(stmt, i);
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
default: // ignore columns not implemented
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
2020-05-19 22:51:16 +00:00
|
|
|
|
|
|
|
schedule_t **schedules = schedule_get_relay_weekdays(new_relay->id);
|
2020-05-05 23:05:36 +00:00
|
|
|
for(int i = 0; i < 7; ++i)
|
|
|
|
{
|
2020-05-19 22:51:16 +00:00
|
|
|
if(schedules[i] == NULL)
|
|
|
|
{
|
|
|
|
LOG_ERROR("got only %d/7 schedules for relay_id %d\n", i, new_relay->id);
|
|
|
|
relay_free(new_relay);
|
|
|
|
free(schedules);
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
new_relay->schedules[i] = schedules[i];
|
2020-05-05 23:05:36 +00:00
|
|
|
}
|
2020-05-19 22:51:16 +00:00
|
|
|
free(schedules); // don't free list, because contents are kept in relay->schedules
|
|
|
|
|
2020-05-06 20:49:22 +00:00
|
|
|
relay_reload_active_schedule(new_relay);
|
2020-05-05 23:05:36 +00:00
|
|
|
|
|
|
|
return new_relay;
|
|
|
|
}
|
|
|
|
|
|
|
|
static relay_t**
|
|
|
|
relay_db_select(sqlite3_stmt *stmt)
|
|
|
|
{
|
|
|
|
relay_t **all_relays = malloc(sizeof(relay_t*));
|
|
|
|
|
|
|
|
int row = 0;
|
|
|
|
|
|
|
|
while(true)
|
|
|
|
{
|
|
|
|
int s;
|
|
|
|
|
|
|
|
s = sqlite3_step(stmt);
|
|
|
|
if (s == SQLITE_ROW)
|
|
|
|
{
|
|
|
|
relay_t *new_relay = relay_db_select_mapper(stmt);
|
|
|
|
row++;
|
|
|
|
|
|
|
|
all_relays = (relay_t**)realloc(all_relays, sizeof(relay_t*) * (row + 1));
|
|
|
|
all_relays[row - 1] = new_relay;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
if(s == SQLITE_DONE)
|
|
|
|
{
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
LOG_ERROR("error selecting relays from database: %s\n", sqlite3_errstr(s));
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
sqlite3_finalize(stmt);
|
|
|
|
all_relays[row] = NULL;
|
|
|
|
return all_relays;
|
|
|
|
}
|
|
|
|
|
|
|
|
int
|
|
|
|
relay_save(relay_t *relay)
|
|
|
|
{
|
|
|
|
sqlite3_stmt *stmt;
|
|
|
|
if(relay->id)
|
|
|
|
{
|
|
|
|
sqlite3_prepare_v2(global_database, "UPDATE relays set number = ?2, name = ?3, controller_id = ?4 WHERE id = ?1;", -1, &stmt, NULL);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
sqlite3_prepare_v2(global_database, "INSERT INTO relays(number, name, controller_id) values (?2, ?3, ?4);", -1, &stmt, NULL);
|
|
|
|
}
|
|
|
|
|
|
|
|
int result = db_update_insert(relay, stmt);
|
|
|
|
|
|
|
|
if(result)
|
|
|
|
{
|
|
|
|
if(relay->id)
|
|
|
|
{
|
|
|
|
LOG_ERROR("error inserting data: %s\n", sqlite3_errmsg(global_database));
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
LOG_ERROR("error updating data: %s\n", sqlite3_errmsg(global_database));
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2020-05-19 16:03:44 +00:00
|
|
|
if(relay->id == 0)
|
|
|
|
{
|
|
|
|
relay->id = sqlite3_last_insert_rowid(global_database);
|
|
|
|
}
|
2020-05-05 23:05:36 +00:00
|
|
|
}
|
2020-05-19 16:03:44 +00:00
|
|
|
|
|
|
|
junction_relay_schedule_remove_for_relay(relay->id);
|
|
|
|
for(int i = 0; i < 7; ++i)
|
|
|
|
{
|
|
|
|
junction_relay_schedule_insert(i, relay->id, relay->schedules[i]->id);
|
|
|
|
}
|
|
|
|
|
2020-05-05 23:05:36 +00:00
|
|
|
return result;
|
|
|
|
}
|
|
|
|
|
|
|
|
int
|
|
|
|
relay_remove(relay_t *relay)
|
|
|
|
{
|
|
|
|
sqlite3_stmt *stmt;
|
|
|
|
if(!relay->id)
|
|
|
|
{
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
sqlite3_prepare_v2(global_database, "DELETE FROM relays WHERE id=?1;", -1, &stmt, NULL);
|
|
|
|
sqlite3_bind_int(stmt, 1, relay->id);
|
|
|
|
|
|
|
|
int rc = sqlite3_step(stmt);
|
|
|
|
|
|
|
|
sqlite3_finalize(stmt);
|
|
|
|
|
|
|
|
return rc != SQLITE_DONE;
|
|
|
|
}
|
|
|
|
|
2020-05-06 20:49:22 +00:00
|
|
|
void
|
|
|
|
relay_reload_active_schedule(relay_t *relay)
|
|
|
|
{
|
2020-05-06 23:38:13 +00:00
|
|
|
time_t timestamp = time(NULL);
|
|
|
|
struct tm *time_struct = localtime(×tamp);
|
|
|
|
relay->active_schedule = relay->schedules[helper_get_weekday(time_struct)];
|
2020-05-06 20:49:22 +00:00
|
|
|
}
|
|
|
|
|
2020-05-05 23:05:36 +00:00
|
|
|
void
|
|
|
|
relay_free(relay_t *relay)
|
|
|
|
{
|
|
|
|
for(int i = 0; i < 7; ++i)
|
|
|
|
{
|
|
|
|
schedule_free(relay->schedules[i]);
|
|
|
|
}
|
|
|
|
free(relay);
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
|
|
|
relay_free_list(relay_t **relays)
|
|
|
|
{
|
|
|
|
for(int i = 0; relays[i] != NULL; ++i)
|
|
|
|
{
|
|
|
|
relay_free(relays[i]);
|
|
|
|
}
|
|
|
|
free(relays);
|
|
|
|
}
|
|
|
|
|
|
|
|
cJSON*
|
|
|
|
relay_to_json(relay_t *relay)
|
|
|
|
{
|
2020-05-06 20:49:22 +00:00
|
|
|
relay_reload_active_schedule(relay);
|
|
|
|
|
2020-05-05 23:05:36 +00:00
|
|
|
cJSON *json = cJSON_CreateObject();
|
|
|
|
|
|
|
|
cJSON *json_number = cJSON_CreateNumber(relay->number);
|
|
|
|
if(json_number == NULL)
|
|
|
|
{
|
2020-05-06 20:49:22 +00:00
|
|
|
LOG_DEBUG("failed to make number\n");
|
2020-05-05 23:05:36 +00:00
|
|
|
cJSON_Delete(json);
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
cJSON_AddItemToObject(json, "number", json_number);
|
|
|
|
|
|
|
|
cJSON *json_name = cJSON_CreateString(relay->name);
|
|
|
|
if(json_name == NULL)
|
|
|
|
{
|
2020-05-06 20:49:22 +00:00
|
|
|
LOG_DEBUG("failed to make name\n");
|
2020-05-05 23:05:36 +00:00
|
|
|
cJSON_Delete(json);
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
cJSON_AddItemToObject(json, "name", json_name);
|
|
|
|
|
2020-05-06 20:49:22 +00:00
|
|
|
controller_t *controller = controller_get_by_id(relay->controller_id);
|
2020-05-05 23:05:36 +00:00
|
|
|
if(!controller)
|
|
|
|
{
|
2020-05-28 00:12:39 +00:00
|
|
|
LOG_WARN("failed to get controller\n");
|
2020-05-05 23:05:36 +00:00
|
|
|
cJSON_Delete(json);
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
char uuid_str[UUID_STR_LEN];
|
|
|
|
uuid_unparse(controller->uid, uuid_str);
|
2020-05-06 20:49:22 +00:00
|
|
|
cJSON *json_controller_id = cJSON_CreateString(uuid_str);
|
|
|
|
if(json_controller_id == NULL)
|
2020-05-05 23:05:36 +00:00
|
|
|
{
|
2020-05-06 20:49:22 +00:00
|
|
|
LOG_DEBUG("failed to make controller id\n");
|
2020-05-05 23:05:36 +00:00
|
|
|
cJSON_Delete(json);
|
|
|
|
return NULL;
|
|
|
|
}
|
2020-05-06 20:49:22 +00:00
|
|
|
cJSON_AddItemToObject(json, "controller_id", json_controller_id);
|
|
|
|
|
|
|
|
controller_free(controller);
|
|
|
|
|
|
|
|
cJSON_AddItemToObject(json, "active_schedule", schedule_to_json(relay->active_schedule));
|
|
|
|
|
|
|
|
cJSON *json_schedules = cJSON_CreateArray();
|
|
|
|
for(int i = 0; i < 7; ++i)
|
|
|
|
{
|
|
|
|
cJSON_AddItemToArray(json_schedules, schedule_to_json(relay->schedules[i]));
|
|
|
|
}
|
|
|
|
cJSON_AddItemToObject(json, "schedules", json_schedules);
|
2020-05-05 23:05:36 +00:00
|
|
|
|
|
|
|
cJSON *json_tags = cJSON_CreateArray();
|
|
|
|
int *tags_ids = junction_tag_get_tags_for_relay_id(relay->id);
|
|
|
|
if(tags_ids != NULL)
|
|
|
|
{
|
|
|
|
for(int i = 0; tags_ids[i] != 0; ++i)
|
|
|
|
{
|
|
|
|
char *tag = tag_get_tag(tags_ids[i]);
|
|
|
|
if(tag == NULL)
|
|
|
|
{
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
|
|
|
|
cJSON *json_tag = cJSON_CreateString(tag);
|
|
|
|
if (json_tag == NULL)
|
|
|
|
{
|
|
|
|
LOG_DEBUG("failed to add tag from string '%s'\n", tag);
|
|
|
|
free(tag);
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
cJSON_AddItemToArray(json_tags, json_tag);
|
|
|
|
free(tag);
|
|
|
|
}
|
|
|
|
free(tags_ids);
|
|
|
|
}
|
|
|
|
cJSON_AddItemToObject(json, "tags", json_tags);
|
|
|
|
|
|
|
|
return json;
|
|
|
|
}
|
|
|
|
|
|
|
|
relay_t*
|
|
|
|
relay_get_by_id(int id)
|
|
|
|
{
|
|
|
|
sqlite3_stmt *stmt;
|
|
|
|
|
|
|
|
sqlite3_prepare_v2(global_database, "SELECT * FROM relays WHERE id = ?1;", -1, &stmt, NULL);
|
|
|
|
sqlite3_bind_int(stmt, 1, id);
|
|
|
|
|
|
|
|
relay_t **sql_result = relay_db_select(stmt);
|
|
|
|
|
|
|
|
relay_t *result = sql_result[0];
|
|
|
|
free(sql_result);
|
|
|
|
|
|
|
|
return result;
|
|
|
|
}
|
|
|
|
|
|
|
|
relay_t*
|
|
|
|
relay_get_by_uid(uuid_t uid)
|
|
|
|
{
|
|
|
|
sqlite3_stmt *stmt;
|
|
|
|
|
|
|
|
sqlite3_prepare_v2(global_database, "SELECT * FROM relays WHERE uid = ?1;", -1, &stmt, NULL);
|
|
|
|
sqlite3_bind_blob(stmt, 1, uid, sizeof(uuid_t), SQLITE_STATIC);
|
|
|
|
|
|
|
|
relay_t **sql_result = relay_db_select(stmt);
|
|
|
|
|
|
|
|
relay_t *result = sql_result[0];
|
|
|
|
free(sql_result);
|
|
|
|
|
|
|
|
return result;
|
|
|
|
}
|
|
|
|
|
|
|
|
relay_t**
|
|
|
|
relay_get_all()
|
|
|
|
{
|
|
|
|
sqlite3_stmt *stmt;
|
|
|
|
|
|
|
|
sqlite3_prepare_v2(global_database, "SELECT * FROM relays;", -1, &stmt, NULL);
|
|
|
|
|
|
|
|
return relay_db_select(stmt);
|
|
|
|
}
|
|
|
|
|
2020-05-19 22:51:16 +00:00
|
|
|
relay_t**
|
|
|
|
relay_get_with_schedule(int schedule_id)
|
|
|
|
{
|
|
|
|
sqlite3_stmt *stmt;
|
|
|
|
|
|
|
|
sqlite3_prepare_v2(global_database, "SELECT DISTINCT relays.* FROM relays INNER JOIN junction_relay_schedule ON relays.id == junction_relay_schedule.relay_id WHERE junction_relay_schedule.schedule_id = ?1;", -1, &stmt, NULL);
|
|
|
|
sqlite3_bind_int(stmt, 1, schedule_id);
|
|
|
|
|
|
|
|
return relay_db_select(stmt);
|
|
|
|
}
|
|
|
|
|
2020-05-06 20:49:22 +00:00
|
|
|
relay_t*
|
|
|
|
relay_get_for_controller(int controller_id, int relay_num)
|
|
|
|
{
|
|
|
|
sqlite3_stmt *stmt;
|
|
|
|
|
|
|
|
sqlite3_prepare_v2(global_database, "SELECT * FROM relays WHERE controller_id = ?1 AND number = ?2;", -1, &stmt, NULL);
|
|
|
|
sqlite3_bind_int(stmt, 1, controller_id);
|
|
|
|
sqlite3_bind_int(stmt, 2, relay_num);
|
|
|
|
|
|
|
|
relay_t **sql_result = relay_db_select(stmt);
|
|
|
|
|
|
|
|
relay_t *result = sql_result[0];
|
|
|
|
free(sql_result);
|
|
|
|
|
|
|
|
return result;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
2020-05-05 23:05:36 +00:00
|
|
|
relay_t**
|
|
|
|
relay_get_by_controller_id(int controller_id)
|
|
|
|
{
|
|
|
|
sqlite3_stmt *stmt;
|
|
|
|
|
2020-05-06 20:49:22 +00:00
|
|
|
sqlite3_prepare_v2(global_database, "SELECT * FROM relays WHERE controller_id = ?1;", -1, &stmt, NULL);
|
2020-05-05 23:05:36 +00:00
|
|
|
sqlite3_bind_int(stmt, 1, controller_id);
|
|
|
|
|
|
|
|
return relay_db_select(stmt);
|
|
|
|
|
|
|
|
}
|