aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJonathan McCrohan <jmccrohan@gmail.com>2012-10-01 21:30:05 +0100
committerJonathan McCrohan <jmccrohan@gmail.com>2012-10-01 21:30:05 +0100
commitcfbdf5c48ba58bb97db1717d0aa852f3cd797cff (patch)
treee5dd4b84498519e1ede570b4e124776c3084fdd0
parent2739fd0e2955872afdf9a5c4ebc3a0c5411f6fcb (diff)
downloadverteco-1.8.tar.gz
Import lightingcontrol.{c,cfg}v1.8
-rw-r--r--src/lightingcontrol.c323
-rw-r--r--src/lightingcontrol.cfg44
2 files changed, 367 insertions, 0 deletions
diff --git a/src/lightingcontrol.c b/src/lightingcontrol.c
new file mode 100644
index 0000000..11384d6
--- /dev/null
+++ b/src/lightingcontrol.c
@@ -0,0 +1,323 @@
+/*
+ * lightingcontrol
+ *
+ * Copyright (C) 2012 Jonathan McCrohan
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+// gcc lightingcontrol.c -o lightingcontrol -lm `pkg-config --libs --cflags libconfig`
+
+#ifndef VERSION_STRING
+#define VERSION_STRING "[undefined version]"
+#endif
+
+#include <stdio.h>
+#include <unistd.h>
+#include <stdlib.h>
+#include <errno.h>
+#include <time.h>
+#include <unistd.h>
+#include <sys/select.h>
+#include <signal.h>
+#include <fcntl.h>
+
+#include <libconfig.h>
+
+#include <sys/ioctl.h>
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <net/if.h>
+#include <string.h>
+
+#include <syslog.h>
+
+#include <termios.h>
+#include <fcntl.h>
+
+// handle SIGALRM by resetting it
+void
+minute_check (int signum)
+{
+ syslog (LOG_DEBUG, "SIGALRM");
+ alarm (60);
+}
+
+int
+main (int argc, char *argv[])
+{
+
+ int SYSLOG_CONSOLE_OUTPUT = 0;
+ int k;
+
+ // check the argv array for strings matching -d
+ for (k = 1; k < argc; k++)
+ {
+ if (strcmp (argv[k], "-d") == 0)
+ {
+ SYSLOG_CONSOLE_OUTPUT = LOG_PERROR;
+ }
+ }
+
+ openlog ("lightingcontrol", SYSLOG_CONSOLE_OUTPUT | LOG_PID | LOG_CONS,
+ LOG_USER);
+
+ syslog (LOG_INFO, "");
+ syslog (LOG_INFO, "lightingcontrol [%s] starting", VERSION_STRING);
+ syslog (LOG_INFO, "");
+
+ const char *configfile = "lightingcontrol.cfg";
+ config_t cfg;
+
+ const char *serial_device_address;
+ int serial_baud_rate;
+ int serial_data_bits;
+ const char *serial_parity;
+ int serial_stop_bits;
+ char *p;
+
+ config_init (&cfg);
+
+ // attempt to read config
+ // loads entire file to memory and destroys file descriptor
+ if (!config_read_file (&cfg, configfile))
+ {
+ fprintf (stderr, "%s:%d - %s\n", config_error_file (&cfg),
+ config_error_line (&cfg), config_error_text (&cfg));
+ config_destroy (&cfg);
+ syslog (LOG_ERR, "Unable to find configfile");
+ return -1;
+ }
+ else
+ {
+ syslog (LOG_INFO, "configfile found successfully");
+ }
+
+ // die if core config file options aren't there
+ if (!(config_lookup_string (&cfg, "serial.device", &serial_device_address)
+ && config_lookup_int (&cfg, "serial.baud", &serial_baud_rate)
+ && config_lookup_int (&cfg, "serial.data_bits", &serial_data_bits)
+ && config_lookup_string (&cfg, "serial.parity", &serial_parity)
+ && config_lookup_int (&cfg, "serial.stop_bits", &serial_stop_bits)))
+ {
+ syslog (LOG_ERR,
+ "Incomplete serial configuration. Check configuration file");
+ closelog ();
+ return -1;
+ }
+
+ syslog (LOG_INFO, "Serial Port=[%s]", serial_device_address);
+ syslog (LOG_INFO, "Serial Port Parameters=[%d %d %c %d]", serial_baud_rate,
+ serial_data_bits, serial_parity[0], serial_stop_bits);
+
+ // SIGALRM used to wake for loop up every 60 secs
+ // sleep puts whole thread to sleep which isn't what we want
+ // other methods involve CPU spinlocks which are inefficient
+ signal (SIGALRM, minute_check);
+ alarm (1);
+
+ for (;;)
+ {
+ // block until SIGARLM
+ select (0, NULL, NULL, NULL, NULL);
+
+ time_t t = time (NULL);
+ struct tm unixtime_min_time_t = *localtime (&t);
+
+ config_setting_t *schedules;
+
+ schedules = config_lookup (&cfg, "schedule");
+
+ // find number of schedules
+ unsigned int num_schedules = config_setting_length (schedules);
+
+ syslog (LOG_DEBUG, "num_schedules=[%d]", num_schedules);
+
+ int i;
+ // cycle through each schedule and pull info from config file
+ for (i = 0; i < num_schedules; ++i)
+ {
+ config_setting_t *scene_element =
+ config_setting_get_elem (schedules, i);
+ int sceneid;
+ config_setting_lookup_int (scene_element, "sceneid", &sceneid);
+ syslog (LOG_DEBUG, "sceneid=[%d]", sceneid);
+ const char *scene_day;
+ char scene_day_lower[20];
+ config_setting_lookup_string (scene_element, "day", &scene_day);
+ strcpy (scene_day_lower, scene_day);
+ p = scene_day_lower;
+ // convert strings to lower case
+ for (; *p; ++p)
+ *p = tolower (*p);
+ syslog (LOG_DEBUG, "scene_day=[%s]", scene_day_lower);
+
+ const char *scene_time;
+ config_setting_lookup_string (scene_element, "time", &scene_time);
+ syslog (LOG_DEBUG, "scene_time=[%s]", scene_time);
+
+ char daystring[20];
+ char timestring[20];
+
+ strftime (daystring, 20, "%A", &unixtime_min_time_t);
+ strftime (timestring, 20, "%H:%M", &unixtime_min_time_t);
+ p = daystring;
+ // convert strings to lower case
+ for (; *p; ++p)
+ *p = tolower (*p);
+
+ syslog (LOG_DEBUG, "current_day=[%s]", daystring);
+ syslog (LOG_DEBUG, "current_time=[%s]", timestring);
+ if ((strcmp (scene_day_lower, daystring) == 0)
+ && (strcmp (scene_time, timestring) == 0))
+
+ {
+
+ // attempt to create new serial connection
+ struct termios term;
+ int serialport = open (serial_device_address,
+ O_RDWR | O_NOCTTY | O_NONBLOCK);
+ if (serialport < 0)
+ {
+ syslog (LOG_ERR, "Unable to create serial object");
+ }
+
+ syslog (LOG_INFO, "serialport=[%d]", serialport);
+
+ if (serial_baud_rate == 115200)
+ {
+ term.c_cflag = B115200;
+ }
+ else if (serial_baud_rate == 57600)
+ {
+ term.c_cflag = B57600;
+ }
+ else if (serial_baud_rate == 38400)
+ {
+ term.c_cflag = B38400;
+ }
+ else if (serial_baud_rate == 19200)
+ {
+ term.c_cflag = B19200;
+ }
+ else if (serial_baud_rate == 9600)
+ {
+ term.c_cflag = B9600;
+ }
+ else if (serial_baud_rate == 4800)
+ {
+ term.c_cflag = B4800;
+ }
+ else if (serial_baud_rate == 2400)
+ {
+ term.c_cflag = B2400;
+ }
+ else if (serial_baud_rate == 1800)
+ {
+ term.c_cflag = B1800;
+ }
+ else if (serial_baud_rate == 1200)
+ {
+ term.c_cflag = B1200;
+ }
+
+
+ if (serial_data_bits == 5)
+ {
+ term.c_cflag |= CS5;
+ }
+ else if (serial_data_bits == 6)
+ {
+ term.c_cflag |= CS6;
+ }
+ else if (serial_data_bits == 7)
+ {
+ term.c_cflag |= CS7;
+ }
+ else
+ {
+ term.c_cflag |= CS8;
+ }
+
+ if (serial_parity == "E")
+ {
+ term.c_cflag |= PARENB;
+ }
+ else if (serial_parity == "O")
+ {
+ term.c_cflag |= PARENB | PARODD;
+ }
+
+ if (serial_stop_bits == 2)
+ {
+ term.c_cflag |= CSTOPB;
+ }
+ term.c_iflag = 0;
+ term.c_oflag = 0;
+ term.c_lflag = 0;
+
+ tcflush (serialport, TCIFLUSH);
+ tcsetattr (serialport, TCSANOW, &term);
+
+ config_setting_t *messagearray;
+ messagearray =
+ config_setting_get_member (scene_element, "message");
+
+ int j, k;
+ // eight byte messages
+ unsigned char serialmsg[8];
+ int nummessages;
+
+ // count number of messages to send
+ nummessages = config_setting_length (messagearray);
+
+ for (j = 0; j < nummessages; j++)
+ {
+ config_setting_t *message;
+ // iterate over each message
+ message = config_setting_get_elem (messagearray, j);
+ // ensure checksum byte is zero'd before calculation
+ serialmsg[7] = 0;
+ for (k = 0; k < 7; k++)
+ {
+ serialmsg[k] = config_setting_get_int_elem (message, k);
+ serialmsg[7] += serialmsg[k];
+ }
+ // checksum calculation
+ serialmsg[7] = (~serialmsg[7] & 0xff) + 1;
+
+ // write message out over serial port
+ write (serialport, serialmsg, sizeof (serialmsg));
+ syslog (LOG_INFO, "MESSAGE SENT");
+ syslog (LOG_INFO,
+ "[%02x][%02x][%02x][%02x][%02x][%02x][%02x][%02x]",
+ serialmsg[0], serialmsg[1], serialmsg[2],
+ serialmsg[3], serialmsg[4], serialmsg[5],
+ serialmsg[6], serialmsg[7]);
+ syslog (LOG_INFO, "SCENEID=[%d] SENT", sceneid);
+ syslog (LOG_INFO, "current_day=[%s]", daystring);
+ syslog (LOG_INFO, "current_time=[%s]", timestring);
+ syslog (LOG_INFO, "nummessages=[%d]", nummessages);
+ usleep (100);
+ }
+
+
+ close (serialport);
+
+ sleep (1);
+
+ }
+ }
+ }
+}
diff --git a/src/lightingcontrol.cfg b/src/lightingcontrol.cfg
new file mode 100644
index 0000000..945a44c
--- /dev/null
+++ b/src/lightingcontrol.cfg
@@ -0,0 +1,44 @@
+cfg_version = 0.99;
+
+serial =
+{
+ device = "/dev/ttyS0";
+ baud = 9600;
+ data_bits = 8;
+ parity = "N";
+ stop_bits = 1;
+};
+
+schedule =
+(
+ {
+ #Scene 1 – Daytime, mall open
+ sceneid = 1;
+ day = "monday"
+ time = "02:06";
+ message = (
+ [0x1c,0x01,0x20,0x03,0x00,0x00,0xff],
+ [0x1c,0x02,0x20,0x03,0x00,0x00,0xff],
+ [0x1c,0x03,0x20,0x03,0x00,0x00,0xff],
+ [0x1c,0x04,0x20,0x03,0x00,0x00,0xff],
+ [0x1c,0x05,0x20,0x03,0x00,0x00,0xff],
+ [0x1c,0x00,0x20,0x03,0x00,0x00,0xff],
+ [0x1c,0x03,0x0a,0x04,0x00,0x00,0xff]
+ );
+ },
+ {
+ #Scene 2 – Nighttime, mall open
+ sceneid = 1;
+ day = "WEDNESDAY"
+ time = "10:12";
+ message = (
+ [0x1c,0x01,0x20,0x03,0x00,0x00,0xff],
+ [0x1c,0x02,0x20,0x03,0x00,0x00,0xff],
+ [0x1c,0x03,0x20,0x03,0x00,0x00,0xff],
+ [0x1c,0x04,0x20,0x03,0x00,0x00,0xff],
+ [0x1c,0x05,0x20,0x03,0x00,0x00,0xff],
+ [0x1c,0x00,0x20,0x03,0x00,0x00,0xff],
+ [0x1c,0x03,0x0a,0x04,0x00,0x00,0xff]
+ );
+ }
+);