bin_PROGRAMS = wakeup pwm curtain lightswitch lightcontrol read_serial
sbin_SCRIPTS = startpwm
-wakeup_SOURCES = wakeup.cpp event.cpp logging.cpp
+wakeup_SOURCES = wakeup.cpp event.cpp logging.cpp sunrise.cpp
pwm_SOURCES = pwm.c
curtain_SOURCES = curtain.c
lightswitch_SOURCES = lightswitch.c
lightcontrol_SOURCES = lightcontrol.cpp logging.cpp
-sunrise_SOURCES = sunrise.cpp
read_serial_SOURCES = read_serial.cpp
LDADD = -lTachyon -lACL
+
+install-exec-hook:
+ chmod u+s $(DESTDIR)$(bindir)/curtain
}
};
+class Curtainstep : public Action
+{
+ virtual String command_line(void)
+ {
+ String cmd("curtain ");
+ cmd += parameters;
+ return cmd;
+ }
+
+ virtual int execute()
+ {
+ String cmd("curtain ");
+ cmd += parameters;
+ return system(cmd);
+ }
+};
+
+class Exitstep : public Action
+{
+ virtual String command_line(void)
+ {
+ String cmd("exit");
+ cmd += parameters;
+ return cmd;
+ }
+
+ virtual int execute()
+ {
+ exit(0);
+ }
+};
+
class Sleepstep : public Action
{
virtual String command_line(void)
int main(int argc, char *argv[])
{
- int i;
-
- // Set up gpi pointer for direct register access
- setup_io();
-
- // Initialize the IO pins.
- INP_GPIO(OPEN_OUT); // must use INP_GPIO before we can use OUT_GPIO
- OUT_GPIO(OPEN_OUT);
- INP_GPIO(OPEN_IN);
-
- INP_GPIO(CLOSE_OUT); // must use INP_GPIO before we can use OUT_GPIO
- OUT_GPIO(CLOSE_OUT);
- INP_GPIO(CLOSE_IN);
-
// Scan the arguments.
- const char *usage = "Usage: curtain [-c close_seconds] [-o open_seconds]\n";
+ const char *usage = "Usage: curtain [-t] [-c close_seconds] [-o open_seconds]\n";
int option;
- int pulse_time;
+ int option_close = 0;
+ int option_open = 0;
+ int option_test = 0;
- while ((option = getopt(argc, argv, "c:o:")) != -1)
+ while ((option = getopt(argc, argv, "c:o:t")) != -1)
{
switch (option)
{
case 'c':
- pulse_time = atoi(optarg);
- GPIO_SET = 1 << CLOSE_OUT; // Close the switch
- sleep(pulse_time);
- GPIO_CLR = 1 << CLOSE_OUT; // Open the switch
+ option_close = atoi(optarg);
break;
case 'o':
- pulse_time = atoi(optarg);
- GPIO_SET = 1 << OPEN_OUT; // Close the switch
- sleep(pulse_time);
- GPIO_CLR = 1 << OPEN_OUT; // Open the switch
+ option_open = atoi(optarg);
+ break;
+
+ case 't':
+ option_test = 1;
break;
case '?':
}
}
+ if (option_test == 0)
+ {
+ // Set up gpi pointer for direct register access
+ setup_io();
+
+ // Initialize the IO pins.
+ INP_GPIO(OPEN_OUT); // must use INP_GPIO before we can use OUT_GPIO
+ OUT_GPIO(OPEN_OUT);
+ INP_GPIO(OPEN_IN);
+
+ INP_GPIO(CLOSE_OUT); // must use INP_GPIO before we can use OUT_GPIO
+ OUT_GPIO(CLOSE_OUT);
+ INP_GPIO(CLOSE_IN);
+
+ if (option_close != 0)
+ {
+ GPIO_SET = 1 << CLOSE_OUT; // Close the switch
+ sleep(option_close);
+ GPIO_CLR = 1 << CLOSE_OUT; // Open the switch
+ }
+ if (option_open != 0)
+ {
+ GPIO_SET = 1 << OPEN_OUT; // Close the switch
+ sleep(option_open);
+ GPIO_CLR = 1 << OPEN_OUT; // Open the switch
+ }
+ }
+ else
+ {
+ /* test mode */
+
+ printf("Curtain close: %d seconds.\n", option_close);
+ printf("Curtain open: %d seconds.\n", option_open);
+ }
return 0;
}
+#include <configuration.h>
+
#include "event.h"
#include "logging.h"
extern logstream Log;
+extern configuration Config;
+
void Event::FromXML(xml_element x)
{
std::vector<xml_element> elems;
std::vector<xml_element> recur;
+ std::map<String, String> attr;
+
+ attr = x.attributes();
+
+ label = attr[String("id")];
elems = x["start"];
start_time = elems[0].content();
xml_text += "'>\n";
xml_text += " <start>";
- xml_text += start_time.format();
+ xml_text += start_time;
xml_text += "</start>\n";
if (pattern != "none")
int separation;
separation = command.index(' ');
- to_execute = command(0, separation);
- parameters = command << separation + 1;
+ if (separation > 0)
+ {
+ to_execute = command(0, separation);
+ parameters = command << separation + 1;
+ }
+ else
+ {
+ to_execute = command;
+ }
if (to_execute == "lightcontrol")
{
act->set_parameters(parameters);
sequence.push_back(act);
}
+ else if (to_execute == "curtain")
+ {
+ Curtainstep *act;
+ act = new Curtainstep;
+
+ act->set_parameters(parameters);
+ sequence.push_back(act);
+ }
else if (to_execute == "sleep")
{
Sleepstep *act;
act->set_parameters(parameters);
sequence.push_back(act);
}
+ else if (to_execute == "exit")
+ {
+ Exitstep *act;
+ act = new Exitstep;
+ sequence.push_back(act);
+ }
+ else
+ {
+ Log << "Action " + to_execute + " not recognized";
+ }
}
void Event::run_sequence()
}
}
-UTC Event::next_occurance(UTC after)
+UTC Event::next_occurance(UTC after, Location loc)
{
- UTC next;
+ UTC next;
+
- //std::cout << "Next occ after " << after << ", pattern = " << pattern << "\n";
- next = start_time;
+ if (start_time == "sunrise")
+ {
+ hour sunrise_at = loc.calculate_sunrise(date(after));
+ next = loc.utc_to_localtime(date(after), sunrise_at);
+ }
+ else if (start_time == "sunset")
+ {
+ hour sunset_at = loc.calculate_sunset(date(after));
+ next = loc.utc_to_localtime(date(after), sunset_at);
+ }
+ else
+ {
+ next = start_time;
+ }
if (pattern != "none")
{
for (unsigned int i = 0; i < alarms.size(); i++)
{
- Event alarm("name");
+ Event alarm;
alarm.FromXML(alarms[i]);
collected_alarms.push_back(alarm);
#include <xml.h>
#include <date.h>
+#include "location.h"
#include "action.h"
class Event
{
String label;
- UTC start_time;
+ String start_time;
String pattern; // for recurrance
UTC recurrance_interval;
void FromXML(xml_element x);
String ToXML(void);
+ String id()
+ {
+ return label;
+ }
+
+ void start_at(UTC st)
+ {
+ start_time = st.format();
+ }
+
void add_action(String command);
void run_sequence();
- UTC next_occurance(UTC after);
+ UTC next_occurance(UTC after, Location loc);
};
std::list<Event> read_alarms(const char *filename);
--- /dev/null
+/*
+ * Location dependent sunrise and sunset calculations
+ */
+
+class Location
+{
+ double latitude;
+ double longitude;
+
+public:
+
+ Location(double lat, double lon)
+ {
+ latitude = lat;
+ longitude = lon;
+ }
+
+ hour calculate_sunrise(date when);
+ hour calculate_sunset(date when);
+ UTC utc_to_localtime(date when, hour utc_time);
+};
+
timestamp = Now();
destination << timestamp << ": " << msg << "\n";
+ destination.flush();
return *this;
}
timestamp = Now();
destination << timestamp << ": " << msg << "\n";
+ destination.flush();
return *this;
}
#include <date.h>
#include <iostream>
+#include "location.h"
+
// Calculate the time of sunrise in timezone UTC.
-hour calculate_sunrise(double latitude, double longitude, date when)
+hour Location::calculate_sunrise(date when)
{
float Declanation;
float solaroffset;
// Calculate the time of sunset in timezone UTC.
-hour calculate_sunset(double latitude, double longitude, date when)
+hour Location::calculate_sunset(date when)
{
float Declanation;
float solaroffset;
}
+UTC Location::utc_to_localtime(date when, hour utc_time)
+{
+ struct tm tp_utc;
+ time_t utc_t;
+ struct tm *local_tm;
+
+
+ tp_utc.tm_year = when.Year() - 1900;
+ tp_utc.tm_mon = when.Month() - 1;
+ tp_utc.tm_mday = when.Day();
+ tp_utc.tm_hour = utc_time.Hour();
+ tp_utc.tm_min = utc_time.Minute();
+ tp_utc.tm_sec = utc_time.Second();
+ tp_utc.tm_isdst = -1;
+
+ utc_t = timegm(&tp_utc);
+
+ local_tm = localtime(&utc_t);
+ UTC local_time(mktime(local_tm));
+
+ return local_time;
+
+}
+
<?xml version='1.0'?>
<wakeup version='0.0.1'>
+ <location>
+ <latitude>51.821366</latitude>
+ <longitude>4.844401</longitude>
+ </location>
<logging>
<method>file</method>
- <destination>.</destination>
+ <destination>/var/log</destination>
<level>0</level>
</logging>
<alarms>
- <filename>wakeup_alarms.xml</filename>
+ <filename>/usr/local/etc/wakeup_alarms.xml</filename>
</alarms>
</wakeup>
#include <signal.h>
+#include <sys/types.h>
+#include <unistd.h>
+
#include <configuration.h>
#include <Tachyon.h>
logstream Log;
Tachyon Timebase;
-std::list<Event> calculate_occurances(std::list<Event> alarms)
+std::list<Event> calculate_occurances(std::list<Event> alarms, Location loc)
{
std::list<Event> future_alarms;
std::list<Event>::iterator alarm;
{
UTC next_time;
- next_time = alarm->next_occurance(Now());
+ next_time = alarm->next_occurance(UTC(Timebase.time()), loc);
//DEBUG
std::cout << "Next alarm after will be " << next_time << ".\n";
if ( next_time != UTC(date(0,0,0), hour(0)))
void reload()
{
+ Log << "Reloading configuration.";
Config.read("wakeup");
}
void sighup_handler(int sig)
{
std::cout << "Caught signal " << sig << "\n";
+ Log << "SIGHUP received.";
}
int main()
runfile << Timebase.name() << "\n";
runfile.close();
+ std::ofstream pidfile("wakeup.pid");
+ pidfile << getpid() << "\n";
+ pidfile.close();
+
Log << "wakeup started";
std::list<Event> set_alarms;
std::list<Event> pending_alarms;
alarms_file = Config.find_parameter("alarms", "filename");
+ Log << "Reading alarms from " + alarms_file;
set_alarms = read_alarms(alarms_file);
- pending_alarms = calculate_occurances(set_alarms);
- // DEBUG
- std::cout << alarms_to_XML(pending_alarms);
- // Find the next alarm
-
- Event next_alarm;
- std::list<Event>::iterator alarm;
+ double latitude = Config.find_parameter("location", "latitude");
+ double longitude = Config.find_parameter("location", "longitude");
+ Location local(latitude, longitude);
- alarm = pending_alarms.begin();
- next_alarm = *alarm;
- while (alarm != pending_alarms.end())
+ while (true)
{
- if (alarm->next_occurance(Now()) < next_alarm.next_occurance(Now()))
+ UTC this_moment = UTC(Timebase.time());
+
+ pending_alarms = calculate_occurances(set_alarms, local);
+ // DEBUG
+ //std::cout << alarms_to_XML(pending_alarms);
+
+ // Find the next alarm
+
+ Event next_alarm;
+ std::list<Event>::iterator alarm;
+
+ alarm = pending_alarms.begin();
+ next_alarm.start_at(UTC("01-01-2030 00:00:00"));
+
+ while (alarm != pending_alarms.end())
+ {
+ if (alarm->next_occurance(this_moment, local) < next_alarm.next_occurance(this_moment, local))
+ {
+ next_alarm = *alarm;
+ }
+ alarm++;
+ }
+
+ UTC next_time = next_alarm.next_occurance(this_moment, local);
+ // DEBUG
+ //std::cout << "Sleep from " << this_moment << " until " << next_time << " (" << next_time - this_moment << " seconds)\n";
+ if (Timebase.nanosleep(next_time - this_moment) == 0)
{
- next_alarm = *alarm;
+ Log << "Alarm " + next_alarm.id() + " triggered at " + next_time.format();
+ next_alarm.run_sequence();
}
- alarm++;
+ else
+ {
+ alarms_file = Config.find_parameter("alarms", "filename");
+ Log << "Reading alarms from " + alarms_file;
+ set_alarms = read_alarms(alarms_file);
+ }
+
}
- // DEBUG
- std::cout << "Sleep until " << next_alarm.next_occurance(Now()) << "\n";
- Timebase.nanosleep(3000);
std::cout << "wakeup exitting.\n";
remove("wakeup.run");
<?xml version='1.0'?>
<wakeup>
- <event id='recurr-workdays'>
+ <event id='lightson_workdays'>
<start>2020-04-02 06:00</start>
<recurrance>
<pattern>weekdays</pattern>
<number>1,2,3,4,5</number>
</recurrance>
- <action>lightcontrol -r 100 -f 200</action>
- <action>lightcontrol -g 100 -f 200</action>
- <action>lightcontrol -w 100 -f 200</action>
+ <action>lightcontrol -r 100 -f 300</action>
+ <action>lightcontrol -g 100 -f 300</action>
+ <action>lightcontrol -w 100 -f 300</action>
+ </event>
+ <event id='sunrise'>
+ <start>sunrise</start>
+ <action>curtain -o 2</action>
+ <action>lightcontrol -r 0 -g 0 -w 0-f 200</action>
+ <recurrance>
+ <pattern>weekdays</pattern>
+ <number>1,2,3,4,5</number>
+ </recurrance>
+ </event>
+ <event id='open_curtains'>
+ <start>2020-04-02 09:00</start>
+ <recurrance>
+ <pattern>days</pattern>
+ <number>1</number>
+ </recurrance>
+ <action>curtain -o 1</action>
+ </event>
+ <event id='sunset'>
+ <start>sunset</start>
+ <action>curtain -c 1</action>
+ <action>lightcontrol -b 99 -w 50</action>
+ <recurrance>
+ <pattern>days</pattern>
+ <number>1</number>
+ </recurrance>
+ </event>
+ <event id='evening_dim'>
+ <start>2020-04-02 22:00</start>
+ <recurrance>
+ <pattern>days</pattern>
+ <number>1</number>
+ </recurrance>
+ <action>lightcontrol -b 50 -w 0 -f 900</action>
+ </event>
+ <event id='lights_off'>
+ <start>2020-04-02 22:30</start>
+ <recurrance>
+ <pattern>days</pattern>
+ <number>1</number>
+ </recurrance>
+ <action>lightcontrol -b 0 -f 1800</action>
</event>
</wakeup>
-TESTS = lightctrl lightctrl-oor lightctrl-fade $(check_PROGRAMS) check_output
+TESTS = lightctrl lightctrl-oor lightctrl-fade \
+ wakeup_load_events sunrise_test event_recurrance event_run_sequence \
+ wakeup_winter sunset_winter \
+ check_output
AM_CPPFLAGS = -I../src
LDADD = -lTachyon -lACL
-check_PROGRAMS = wakeup_load_events sunrise_test event_recurrance event_run_sequence
+check_PROGRAMS = wakeup_load_events sunrise_test event_recurrance event_run_sequence \
+ log_retime
-wakeup_load_events_SOURCES = wakeup_load_events.cpp ../src/event.cpp ../src/logging.cpp
-event_recurrance_SOURCES = event_recurrance.cpp ../src/event.cpp ../src/logging.cpp
-event_run_sequence_SOURCES = event_run_sequence.cpp ../src/event.cpp ../src/logging.cpp
+wakeup_load_events_SOURCES = wakeup_load_events.cpp ../src/event.cpp ../src/logging.cpp ../src/sunrise.cpp
+event_recurrance_SOURCES = event_recurrance.cpp ../src/event.cpp ../src/logging.cpp ../src/sunrise.cpp
+event_run_sequence_SOURCES = event_run_sequence.cpp ../src/event.cpp ../src/logging.cpp ../src/sunrise.cpp
sunrise_test_SOURCES = sunrise_test.cpp ../src/sunrise.cpp
+
+log_retime_SOURCES = log_retime.cpp
#include "event.h"
-#include "assert.h"
#include "logging.h"
+#include <assert.h>
logstream Log;
UTC time_to_check;
UTC time_expected;
UTC next_time;
+ Location dummy(0, 0);
Log.open("event_recurrance.log2");
// Check before the alarm time
time_to_check = UTC(date(20, 3, 2020), hour(2, 2, 2));
time_expected = UTC(date(22, 3, 2020), hour(6, 0, 0));
- next_time = alarm->next_occurance(time_to_check);
+ next_time = alarm->next_occurance(time_to_check, dummy);
std::cout << "Next alarm after " << time_to_check << " will be " << next_time << "\n";
assert(next_time == time_expected);
// Check after the alarm time
time_to_check = UTC(date(22, 3, 2020), hour(6, 2, 2));
time_expected = UTC(date(0, 0, 0), hour(0, 0, 0));
- next_time = alarm->next_occurance(time_to_check);
+ next_time = alarm->next_occurance(time_to_check, dummy);
std::cout << "Next alarm after " << time_to_check << " will be " << next_time << "\n";
std::cout.flush();
assert(next_time == time_expected);
time_to_check = UTC(date(20, 5, 2020), hour(2, 2, 2));
time_expected = UTC(date(24, 5, 2020), hour(8, 0, 0));
- next_time = alarm->next_occurance(time_to_check);
+ next_time = alarm->next_occurance(time_to_check, dummy);
std::cout << "Next alarm after " << time_to_check << " will be " << next_time << "\n";
std::cout.flush();
assert(next_time == time_expected);
time_to_check = UTC(date(24, 5, 2020), hour(8, 2, 2));
time_expected = UTC(date(31, 5, 2020), hour(8, 0, 0));
- next_time = alarm->next_occurance(time_to_check);
+ next_time = alarm->next_occurance(time_to_check, dummy);
std::cout << "Next alarm after " << time_to_check << " will be " << next_time << "\n";
std::cout.flush();
assert(next_time == time_expected);
time_to_check = UTC(date(25, 11, 2020), hour(2, 2, 2));
time_expected = UTC(date(29, 11, 2020), hour(8, 0, 0));
- next_time = alarm->next_occurance(time_to_check);
+ next_time = alarm->next_occurance(time_to_check, dummy);
std::cout << "Next alarm after " << time_to_check << " will be " << next_time << "\n";
std::cout.flush();
assert(next_time == time_expected);
time_to_check = UTC(date(20, 3, 2020), hour(2, 2, 2));
time_expected = UTC(date( 2, 4, 2020), hour(7, 0, 0)); // the first Thursday
- next_time = alarm->next_occurance(time_to_check);
+ next_time = alarm->next_occurance(time_to_check, dummy);
std::cout << "Next alarm after " << time_to_check << " will be " << next_time << ". Expected " << time_expected << "\n";
std::cout.flush();
assert(next_time == time_expected);
time_to_check = UTC(date( 2, 4, 2020), hour(7, 2, 2));
time_expected = UTC(date( 3, 4, 2020), hour(7, 0, 0)); // the next Friday
- next_time = alarm->next_occurance(time_to_check);
+ next_time = alarm->next_occurance(time_to_check, dummy);
std::cout << "Next alarm after " << time_to_check << " will be " << next_time << ". Expected " << time_expected << "\n";
std::cout.flush();
assert(next_time == time_expected);
time_to_check = UTC(date( 3, 4, 2020), hour(7, 2, 2));
time_expected = UTC(date( 7, 4, 2020), hour(7, 0, 0)); // the next Tuesday
- next_time = alarm->next_occurance(time_to_check);
+ next_time = alarm->next_occurance(time_to_check, dummy);
std::cout << "Next alarm after " << time_to_check << " will be " << next_time << ". Expected " << time_expected << "\n";
std::cout.flush();
assert(next_time == time_expected);
sleep 1
read TACHYON_NAME <lightcontrol.run
-#tachyon -a 4.0 $TACHYON_NAME
+tachyon -a 4.0 $TACHYON_NAME
while [ -f lightcontrol.run ]
do
0 0 0 0
0 0 0 0
-0 0 0 0
0 1 0 1
+2 3 1 3
3 4 2 4
+3 5 2 5
5 7 3 7
+6 8 4 8
+6 9 4 9
8 11 5 11
-10 14 7 14
+9 12 6 12
+9 13 6 13
+11 15 7 15
+12 16 8 16
13 18 9 18
-15 21 10 21
+14 19 9 19
+15 20 10 20
+16 22 11 22
+17 23 11 23
18 24 12 24
+19 26 13 26
+20 27 13 27
21 28 14 28
+22 30 15 30
23 31 15 31
+24 32 16 32
+25 34 17 34
26 35 17 35
+27 37 18 37
28 38 19 38
-Receiving message.
-The message is A10.000000.
+29 39 19 39
30 40 20 40
PASS lightctrl-fade (exit status: 0)
--- /dev/null
+/*
+ * Read a log file and change time time stamps to relative timestamps
+ * from the beginning of the log.
+ */
+
+#include <fstream>
+#include <date.h>
+
+int main(int argc, char *argv[])
+{
+ std::ifstream logfile;
+ String firstline, logline;
+ String timefield;
+ UTC firsttime, logtime;
+
+ logfile.open(argv[1]);
+
+ logfile >> firstline;
+ timefield = firstline(0,19);
+ firsttime = UTC(timefield);
+ logfile.seekg(0);
+
+ while (logfile >> logline)
+ {
+ String logfield;
+
+ timefield = logline(0,19);
+ logfield = logline << 21;
+
+ logtime = UTC(timefield);
+
+ std::cout << logtime - firsttime << " " << logfield << "\n";
+ }
+
+ return 0;
+}
#include <assert.h>
+#include "location.h"
+
// Hardinxveld:
const double latitude = 51.821366;
const double longitude = 4.844401;
-extern hour calculate_sunrise(double latitude, double longtitude, date when);
-extern hour calculate_sunset(double latitude, double longtitude, date when);
int main()
{
date when;
hour sunrise_at, sunset_at;
+ Location loc(latitude, longitude);
+ UTC local_sunrise;
+ UTC local_sunset;
when = date(1, 1, 2020);
std::cout << "On the date " << when << ":\n";
- sunrise_at = calculate_sunrise(latitude, longitude, when);
+ sunrise_at = loc.calculate_sunrise(when);
std::cout << "Sunrise : " << sunrise_at << " UTC.\n";
- sunset_at = calculate_sunset(latitude, longitude, when);
+
+ local_sunrise = loc.utc_to_localtime(when, sunrise_at);
+ std::cout << "Sunrise : " << local_sunrise << " local time.\n";
+
+ sunset_at = loc.calculate_sunset(when);
std::cout << "Sunset : " << sunset_at << " UTC.\n";
+ local_sunset = loc.utc_to_localtime(when, sunset_at);
+ std::cout << "Sunset : " << local_sunset << " local time.\n";
+
assert(sunrise_at == hour(7, 51, 29));
assert(sunset_at == hour(15, 29, 47));
when = date(30, 6, 2020);
std::cout << "On the date " << when << ":\n";
- sunrise_at = calculate_sunrise(latitude, longitude, when);
+ sunrise_at = loc.calculate_sunrise(when);
std::cout << "Sunrise : " << sunrise_at << " UTC.\n";
- sunset_at = calculate_sunset(latitude, longitude, when);
+ local_sunrise = loc.utc_to_localtime(when, sunrise_at);
+ std::cout << "Sunrise : " << local_sunrise << " local time.\n";
+
+ sunset_at = loc.calculate_sunset(when);
std::cout << "Sunset : " << sunset_at << " UTC.\n";
+ local_sunset = loc.utc_to_localtime(when, sunset_at);
+ std::cout << "Sunset : " << local_sunset << " local time.\n";
+
assert(sunrise_at == hour(3, 29, 3));
assert(sunset_at == hour(19, 52, 13));
}
On the date 01-01-2020:
Sunrise : 07:51:29 UTC.
+Sunrise : 01-01-2020 08:51:29 local time.
Sunset : 15:29:47 UTC.
+Sunset : 01-01-2020 16:29:47 local time.
On the date 30-06-2020:
Sunrise : 03:29:03 UTC.
+Sunrise : 30-06-2020 05:29:03 local time.
Sunset : 19:52:13 UTC.
+Sunset : 30-06-2020 21:52:13 local time.
PASS sunrise_test (exit status: 0)
--- /dev/null
+<?xml version='1.0'?>
+<wakeup>
+ <event id='sunset'>
+ <start>sunset</start>
+ <action>curtain -c 1 -t</action>
+ <action>lightcontrol -b 99 -w 50</action>
+ <recurrance>
+ <pattern>days</pattern>
+ <number>1</number>
+ </recurrance>
+ </event>
+ <event id='evening_dim'>
+ <start>2020-04-02 22:00</start>
+ <recurrance>
+ <pattern>days</pattern>
+ <number>1</number>
+ </recurrance>
+ <action>lightcontrol -b 50 -w 0 -f 9</action>
+ </event>
+ <event id='lights_off'>
+ <start>2020-04-02 22:30</start>
+ <recurrance>
+ <pattern>days</pattern>
+ <number>1</number>
+ </recurrance>
+ <action>lightcontrol -b 0 -f 18</action>
+ </event>
+ <event id='end_test'>
+ <start>2020-04-08 11:00</start>
+ <recurrance>
+ <pattern>days</pattern>
+ <number>7</number>
+ </recurrance>
+ <action>exit</action>
+ </event>
+</wakeup>
--- /dev/null
+#!/bin/bash
+#
+# Test the wakeup sequence in winter.
+#
+set -m
+PATH=../src:$PATH
+
+# Reset the lights and clear the log files
+
+lightcontrol -r 0 -g 0 -b 0 -w 0
+> lightcontrol.log
+> wakeup.log
+
+ln -f -s wakeup_empty.xml wakeup_link.xml
+
+wakeup &
+sleep 1
+
+read TACHYON_NAME <wakeup.run
+Time=`date --date '2020-12-17 15:00' +%s`
+tachyon -t $Time $TACHYON_NAME
+tachyon -a 100 $TACHYON_NAME
+
+ln -f -s sunset_alarms.xml wakeup_link.xml
+
+kill -HUP `cat wakeup.pid`
+
+fg %1
+#kill `cat wakeup.pid`
+
+# Remove timestamps from the log.
+cut -c 22- wakeup.log >sunset_winter.log.test
+
+diff sunset_winter.log.test sunset_winter.log.expect
+
+
+exit $?
--- /dev/null
+wakeup started
+Reading alarms from wakeup_link.xml
+SIGHUP received.
+Reading alarms from wakeup_link.xml
+Alarm sunset triggered at 2020-12-17 16:27:00
+Executing curtain -c 1 -t
+Executing lightcontrol -b 99 -w 50
+Alarm evening_dim triggered at 2020-12-17 22:00:00
+Executing lightcontrol -b 50 -w 0 -f 9
+Alarm lights_off triggered at 2020-12-17 22:30:00
+Executing lightcontrol -b 0 -f 18
+Alarm sunset triggered at 2020-12-18 16:27:00
+Executing curtain -c 1 -t
+Executing lightcontrol -b 99 -w 50
+Alarm evening_dim triggered at 2020-12-18 22:00:00
+Executing lightcontrol -b 50 -w 0 -f 9
+Alarm lights_off triggered at 2020-12-18 22:30:00
+Executing lightcontrol -b 0 -f 18
+Alarm sunset triggered at 2020-12-19 16:26:53
+Executing curtain -c 1 -t
+Executing lightcontrol -b 99 -w 50
+Alarm evening_dim triggered at 2020-12-19 22:00:00
+Executing lightcontrol -b 50 -w 0 -f 9
+Alarm lights_off triggered at 2020-12-19 22:30:00
+Executing lightcontrol -b 0 -f 18
+Alarm sunset triggered at 2020-12-20 16:26:48
+Executing curtain -c 1 -t
+Executing lightcontrol -b 99 -w 50
+Alarm evening_dim triggered at 2020-12-20 22:00:00
+Executing lightcontrol -b 50 -w 0 -f 9
+Alarm lights_off triggered at 2020-12-20 22:30:00
+Executing lightcontrol -b 0 -f 18
+Alarm sunset triggered at 2020-12-21 16:26:47
+Executing curtain -c 1 -t
+Executing lightcontrol -b 99 -w 50
+Alarm evening_dim triggered at 2020-12-21 22:00:00
+Executing lightcontrol -b 50 -w 0 -f 9
+Alarm lights_off triggered at 2020-12-21 22:30:00
+Executing lightcontrol -b 0 -f 18
+Alarm sunset triggered at 2020-12-22 16:26:48
+Executing curtain -c 1 -t
+Executing lightcontrol -b 99 -w 50
+Alarm evening_dim triggered at 2020-12-22 22:00:00
+Executing lightcontrol -b 50 -w 0 -f 9
+Alarm lights_off triggered at 2020-12-22 22:30:00
+Executing lightcontrol -b 0 -f 18
+Alarm end_test triggered at 2020-12-23 11:00:00
+Executing exit
<?xml version='1.0'?>
<wakeup version='0.0.1'>
+ <location>
+ <latitude>51.821366</latitude>
+ <longitude>4.844401</longitude>
+ </location>
<logging>
<method>file</method>
<destination>.</destination>
<level>0</level>
</logging>
<alarms>
- <filename>wakeup_alarms.xml</filename>
+ <filename>wakeup_link.xml</filename>
</alarms>
</wakeup>
<?xml version='1.0'?>
<wakeup>
- <event id='recurr-workdays'>
+ <event id='lightson_workdays'>
<start>2020-04-02 06:00</start>
<recurrance>
<pattern>weekdays</pattern>
<number>1,2,3,4,5</number>
</recurrance>
- <action>lightcontrol -r 100 -f 200</action>
- <action>lightcontrol -g 100 -f 200</action>
- <action>lightcontrol -w 100 -f 200</action>
+ <action>lightcontrol -r 10 -f 2</action>
+ <action>lightcontrol -g 10 -f 2</action>
+ <action>lightcontrol -w 10 -f 2</action>
+ </event>
+ <event id='sunrise'>
+ <start>sunrise</start>
+ <action>curtain -o 2 -t</action>
+ <action>lightcontrol -r 0 -g 0 -w 0-f 2</action>
+ <recurrance>
+ <pattern>weekdays</pattern>
+ <number>1,2,3,4,5</number>
+ </recurrance>
+ </event>
+ <event id='open_curtains'>
+ <start>2020-04-02 09:00</start>
+ <recurrance>
+ <pattern>days</pattern>
+ <number>1</number>
+ </recurrance>
+ <action>curtain -o 1 -t</action>
+ </event>
+ <event id='end_test'>
+ <start>2020-04-08 11:00</start>
+ <recurrance>
+ <pattern>days</pattern>
+ <number>7</number>
+ </recurrance>
+ <action>exit</action>
</event>
</wakeup>
--- /dev/null
+<?xml version='1.0'?>
+<!--
+An empty list of events to start a test with.
+The test scenario will set an appropriate time and load a different
+list of events.
+-->
+<wakeup>
+</wakeup>
std::list<Event> set_alarms;
set_alarms = read_alarms("wakeup-01.xml");
-
std::cout << alarms_to_XML(set_alarms);
set_alarms = read_alarms("wakeup-02.xml");
+ std::cout << alarms_to_XML(set_alarms);
+ set_alarms = read_alarms("wakeup_empty.xml");
std::cout << alarms_to_XML(set_alarms);
}
<?xml version='1.0'?>
<wakeup>
- <event id='name'>
- <start>2020-03-22 06:00:00</start>
+ <event id='monday_wakeup'>
+ <start>2020-03-22 06:00</start>
<action>lightcontrol -r 100 -f 200</action>
<action>lightcontrol -g 100 -f 200</action>
<action>lightcontrol -w 100 -f 200</action>
</wakeup>
<?xml version='1.0'?>
<wakeup>
- <event id='name'>
- <start>2020-03-22 06:00:00</start>
+ <event id='non-recurring'>
+ <start>2020-03-22 06:00</start>
<action>lightcontrol -r 100 -f 200</action>
</event>
- <event id='name'>
- <start>2020-05-24 08:00:00</start>
+ <event id='recurr-weekly'>
+ <start>2020-05-24 08:00</start>
<pattern>days</pattern>
<number>7</number>
<action>lightcontrol -g 100 -f 200</action>
</event>
- <event id='name'>
- <start>2020-04-02 07:00:00</start>
+ <event id='recurr-somedays'>
+ <start>2020-04-02 07:00</start>
<pattern>weekdays</pattern>
<number>2,4,5</number>
<action>lightcontrol -g 100 -f 200</action>
</event>
</wakeup>
+<?xml version='1.0'?>
+<wakeup>
+</wakeup>
PASS wakeup_load_events (exit status: 0)
--- /dev/null
+#!/bin/bash
+#
+# Test the wakeup sequence in winter.
+#
+set -m
+PATH=../src:$PATH
+
+# Reset the lights and clear the log files
+
+lightcontrol -r 0 -g 0 -b 0 -w 0
+> lightcontrol.log
+> wakeup.log
+
+ln -f -s wakeup_empty.xml wakeup_link.xml
+
+wakeup &
+sleep 1
+
+read TACHYON_NAME <wakeup.run
+Time=`date --date '2020-12-17 05:00' +%s`
+tachyon -t $Time $TACHYON_NAME
+tachyon -a 100 $TACHYON_NAME
+
+ln -f -s wakeup_alarms.xml wakeup_link.xml
+
+kill -HUP `cat wakeup.pid`
+
+fg %1
+#kill `cat wakeup.pid`
+
+# Remove timestamps from the log.
+cut -c 22- wakeup.log >wakeup_winter.log.test
+
+diff wakeup_winter.log.test wakeup_winter.log.expect
+
+exit $?
--- /dev/null
+wakeup started
+Reading alarms from wakeup_link.xml
+SIGHUP received.
+Reading alarms from wakeup_link.xml
+Alarm lightson_workdays triggered at 2020-12-17 06:00:00
+Executing lightcontrol -r 10 -f 2
+Executing lightcontrol -g 10 -f 2
+Executing lightcontrol -w 10 -f 2
+Alarm sunrise triggered at 2020-12-17 08:54:16
+Executing curtain -o 2 -t
+Executing lightcontrol -r 0 -g 0 -w 0-f 2
+Alarm open_curtains triggered at 2020-12-17 09:00:00
+Executing curtain -o 1 -t
+Alarm lightson_workdays triggered at 2020-12-18 06:00:00
+Executing lightcontrol -r 10 -f 2
+Executing lightcontrol -g 10 -f 2
+Executing lightcontrol -w 10 -f 2
+Alarm sunrise triggered at 2020-12-18 08:54:23
+Executing curtain -o 2 -t
+Executing lightcontrol -r 0 -g 0 -w 0-f 2
+Alarm open_curtains triggered at 2020-12-18 09:00:00
+Executing curtain -o 1 -t
+Alarm open_curtains triggered at 2020-12-19 09:00:00
+Executing curtain -o 1 -t
+Alarm open_curtains triggered at 2020-12-20 09:00:00
+Executing curtain -o 1 -t
+Alarm lightson_workdays triggered at 2020-12-21 06:00:00
+Executing lightcontrol -r 10 -f 2
+Executing lightcontrol -g 10 -f 2
+Executing lightcontrol -w 10 -f 2
+Alarm sunrise triggered at 2020-12-21 08:54:28
+Executing curtain -o 2 -t
+Executing lightcontrol -r 0 -g 0 -w 0-f 2
+Alarm open_curtains triggered at 2020-12-21 09:00:00
+Executing curtain -o 1 -t
+Alarm lightson_workdays triggered at 2020-12-22 06:00:00
+Executing lightcontrol -r 10 -f 2
+Executing lightcontrol -g 10 -f 2
+Executing lightcontrol -w 10 -f 2
+Alarm sunrise triggered at 2020-12-22 08:54:23
+Executing curtain -o 2 -t
+Executing lightcontrol -r 0 -g 0 -w 0-f 2
+Alarm open_curtains triggered at 2020-12-22 09:00:00
+Executing curtain -o 1 -t
+Alarm lightson_workdays triggered at 2020-12-23 06:00:00
+Executing lightcontrol -r 10 -f 2
+Executing lightcontrol -g 10 -f 2
+Executing lightcontrol -w 10 -f 2
+Alarm sunrise triggered at 2020-12-23 08:54:16
+Executing curtain -o 2 -t
+Executing lightcontrol -r 0 -g 0 -w 0-f 2
+Alarm open_curtains triggered at 2020-12-23 09:00:00
+Executing curtain -o 1 -t
+Alarm end_test triggered at 2020-12-23 11:00:00
+Executing exit