#include <stdlib.h> #include <string.h> #include <stdio.h> #include <time.h> #include <lmdb.h> #include <signal.h> #include <syslog.h> #include <logger.h> #include <mongoose.h> #include <models/controller.h> #include <database.h> #include <config.h> #include <connections.h> #include <constants.h> #include <handlers.h> #include <drivers.h> #include <enums.h> #include <runners.h> #include <helpers.h> #include <wiringPi.h> #include <piFace.h> #include <wiring_debug.h> #include <confini.h> config_t global_config; static struct mg_mgr mgr; static void terminate(int signum) { LOGGER_INFO("terminating controller (%d)\n", signum); // TODO fix mg_mgr_free() causing loop (can't terminate) //LOGGER_DEBUG("freeing mongoose manager\n"); //mg_mgr_free(&mgr); LOGGER_DEBUG("closing database\n"); database_free(); LOGGER_DEBUG("freeing global controller\n"); controller_free(global_controller); LOGGER_DEBUG("freeing relay configs config\n"); free(global_config.relay_configs); exit(signum); } /** * @brief The main function * * @param argc UNUSED * @param argv UNUSED * * @return Statuscode to indicate success (0) or failure (!0) */ int main(int argc, const char** argv) { (void)argc; (void)argv; signal(SIGINT, terminate); signal(SIGABRT, terminate); signal(SIGTERM, terminate); setlogmask(LOG_UPTO(LOG_INFO)); /******************** LOAD CONFIG ********************/ global_config.file = "controller.ini"; global_config.discovery_port = 4421; global_config.mqtt_port = 1885; global_config.relay_count = 0; global_config.relays_init = -1; global_config.log_level = LOG_INFO; global_config.log_file = stdout; strcpy(global_config.user, ""); strcpy(global_config.group, ""); helper_parse_cli(argc, argv, &global_config); FILE * const ini_file = fopen(global_config.file, "rb"); if(ini_file == NULL) { LOGGER_CRIT("config file '%s' was not found\n", global_config.file); exit(1); } if(load_ini_file( ini_file, INI_DEFAULT_FORMAT, NULL, config_load, &global_config)) { LOGGER_CRIT("unable to parse ini file\n"); exit(1); } fclose(ini_file); if(global_config.log_file == NULL) { global_config.log_file = stdout; } openlog("emgauwa-controller", 0, LOG_USER); if(sizeof(time_t) < 8) { LOGGER_WARNING("this system is not using 8-bit time\n"); } /******************** INIT DATABASE, SOCKETS AND THIS CONTROLLER ********************/ mg_mgr_init(&mgr, NULL); database_init(); global_controller = controller_load(); if(!global_controller) { global_controller = controller_create(); controller_save(); } connection_discovery_bind(&mgr); connection_mqtt_connect(&mgr); struct mg_connection *c_command = connection_command_bind(&mgr); if(global_controller->command_port == 0) { global_controller->command_port = helper_get_port(c_command->sock); controller_save(); } controller_debug(global_controller); helper_drop_privileges(); /******************** SETUP WIRINGPI ********************/ wiringPiSetup(); int piface_setup = 0; for(uint_fast8_t i = 0; i < global_config.relay_count; ++i) { int relay_default = global_config.relay_configs[i].init; if(relay_default == -1) { relay_default = global_config.relays_init; } if(relay_default == -1) { relay_default = global_config.relay_configs[i].inverted; } if(global_config.relay_configs[i].driver == RELAY_DRIVER_GPIO) { pinMode(global_config.relay_configs[i].pin, OUTPUT); driver_gpio_set(global_config.relay_configs[i].pin, relay_default); } if(global_config.relay_configs[i].driver == RELAY_DRIVER_PIFACE) { if(!piface_setup) { piFaceSetup(PIFACE_GPIO_BASE); piface_setup = 1; } driver_piface_set(global_config.relay_configs[i].pin, relay_default); } } /******************** CHECK FOR TESTING RUN ********************/ if(global_config.run_type == RUN_TYPE_TEST) { runner_test(global_controller); terminate(0); } /******************** START MAIN LOOP ********************/ time_t timer = 0; for (;;) { mg_mgr_poll(&mgr, 200); if(time(NULL) - timer >= 1) { if(!global_connection_mqtt) { connection_mqtt_connect(&mgr); } handler_loop(global_connection_mqtt); timer = time(NULL); } } terminate(0); return 0; }