Started on execution of actions
authorArjen Baart <arjen@andromeda.nl>
Sun, 2 Aug 2020 07:08:01 +0000 (09:08 +0200)
committerArjen Baart <arjen@andromeda.nl>
Sun, 2 Aug 2020 07:08:01 +0000 (09:08 +0200)
18 files changed:
doc/wakeup-classes.svg
src/Makefile.am
src/action.h
src/event.cpp
src/event.h
src/lightswitch.c [new file with mode: 0644]
src/logging.h
src/wakeup.conf [new file with mode: 0644]
src/wakeup.cpp
src/wakeup_alarms.xml [new file with mode: 0644]
test/Makefile.am
test/event_recurrance.cpp
test/event_run_sequence.cpp [new file with mode: 0644]
test/lightctrl-fade
test/wakeup-03.xml [new file with mode: 0644]
test/wakeup.conf [new file with mode: 0644]
test/wakeup_alarms.xml [new file with mode: 0644]
test/wakeup_load_events.cpp

index 379d44f..d75d0c9 100644 (file)
@@ -26,7 +26,7 @@
      inkscape:pageopacity="0.0"
      inkscape:pageshadow="2"
      inkscape:zoom="1.2271424"
-     inkscape:cx="233.1688"
+     inkscape:cx="66.928924"
      inkscape:cy="743.6865"
      inkscape:document-units="mm"
      inkscape:current-layer="layer1"
          x="46.571613"
          y="108.98867"
          style="stroke-width:0.26458332px">parameters</tspan></text>
+    <text
+       xml:space="preserve"
+       style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:3.52777767px;line-height:125%;font-family:sans-serif;-inkscape-font-specification:sans-serif;font-variant-ligatures:normal;font-variant-caps:normal;font-variant-numeric:normal;font-feature-settings:normal;text-align:center;letter-spacing:0px;word-spacing:0px;writing-mode:lr-tb;text-anchor:middle;fill:#000000;fill-opacity:1;stroke:none;stroke-width:0.26458332px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
+       x="50.883797"
+       y="76.000443"
+       id="text5120"><tspan
+         sodipodi:role="line"
+         id="tspan5118"
+         x="50.883797"
+         y="76.000443"
+         style="stroke-width:0.26458332px">run_sequence()</tspan></text>
   </g>
 </svg>
index 268461c..337d117 100644 (file)
@@ -1,9 +1,10 @@
-bin_PROGRAMS = wakeup pwm curtain lightcontrol read_serial
+bin_PROGRAMS = wakeup pwm curtain lightswitch lightcontrol read_serial
 sbin_SCRIPTS = startpwm
 
-wakeup_SOURCES = wakeup.cpp event.cpp
+wakeup_SOURCES = wakeup.cpp event.cpp logging.cpp
 pwm_SOURCES = pwm.c
 curtain_SOURCES = curtain.c
+lightswitch_SOURCES = lightswitch.c
 lightcontrol_SOURCES = lightcontrol.cpp logging.cpp
 
 sunrise_SOURCES = sunrise.cpp
index 797ab80..d05c423 100644 (file)
@@ -18,7 +18,8 @@ public:
    {
       return String("no command");
    }
-//virtual void execute() = 0;
+
+   virtual int execute() = 0;
 
 };
 
@@ -30,6 +31,13 @@ class Lightstep : public Action
       cmd += parameters;
       return cmd;
    }
+
+   virtual int execute()
+   {
+      String cmd("lightcontrol ");
+      cmd += parameters;
+      return system(cmd);
+   }
 };
 
 class Sleepstep : public Action
@@ -40,5 +48,12 @@ class Sleepstep : public Action
       cmd += parameters;
       return cmd;
    }
+
+   virtual int execute()
+   {
+      String cmd("sleep ");
+      cmd += parameters;
+      return system(cmd);
+   }
 };
 
index dde8372..1009070 100644 (file)
@@ -1,4 +1,7 @@
 #include "event.h"
+#include "logging.h"
+
+extern logstream     Log;
 
 void Event::FromXML(xml_element x)
 {
@@ -138,6 +141,17 @@ void Event::add_action(String command)
    }
 }
 
+void Event::run_sequence()
+{
+   std::list<Action *>::iterator cmd;
+
+   for (cmd = sequence.begin(); cmd != sequence.end(); cmd++)
+   {
+      Log << "Executing " + (*cmd)->command_line();
+      (*cmd)->execute();
+   }
+}
+
 UTC Event::next_occurance(UTC after)
 {
    UTC next;
index 72f4f3a..2351aa5 100644 (file)
@@ -35,6 +35,7 @@ public:
    String ToXML(void);
 
    void  add_action(String command);
+   void  run_sequence();
 
    UTC   next_occurance(UTC after);
 };
diff --git a/src/lightswitch.c b/src/lightswitch.c
new file mode 100644 (file)
index 0000000..7b81626
--- /dev/null
@@ -0,0 +1,113 @@
+#include <sys/stat.h>
+#include <sys/types.h>
+#include <fcntl.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <sys/mman.h>
+#include <unistd.h>
+#include <errno.h>
+#include <time.h>
+#include <getopt.h>
+
+#define PAGE_SIZE (4*1024)
+#define BLOCK_SIZE (4*1024)
+/*  Direct access to GPIO hardware  */
+
+// Access from ARM Running Linux
+// For Raspberry Pi 2 and Pi 3, change BCM2708_PERI_BASE to 0x3F000000 for the code to work.
+//#define BCM2708_PERI_BASE        0x20000000
+#define BCM2708_PERI_BASE        0x3F000000
+#define GPIO_BASE                (BCM2708_PERI_BASE + 0x200000) /* GPIO controller */
+// I/O access
+volatile unsigned *gpio;
+// GPIO setup macros. Always use INP_GPIO(x) before using OUT_GPIO(x) or SET_GPIO_ALT(x,y)
+#define INP_GPIO(g) *(gpio+((g)/10)) &= ~(7<<(((g)%10)*3))
+#define OUT_GPIO(g) *(gpio+((g)/10)) |=  (1<<(((g)%10)*3))
+#define SET_GPIO_ALT(g,a) *(gpio+(((g)/10))) |= (((a)<=3?(a)+4:(a)==4?3:2)<<(((g)%10)*3))
+#define GPIO_SET *(gpio+7)  // sets   bits which are 1 ignores bits which are 0
+#define GPIO_CLR *(gpio+10) // clears bits which are 1 ignores bits which are 0
+#define GET_GPIO(g) (*(gpio+13)&(1<<g)) // 0 if LOW, (1<<g) if HIGH
+#define GPIO_PULL *(gpio+37) // Pull up/pull down
+#define GPIO_PULLCLK0 *(gpio+38) // Pull up/pull down clock
+void setup_io();
+
+
+/*  GPIO pin assignments */
+
+#define SWITCH_IN    2
+
+
+int main(int argc, char *argv[])
+{
+   int i;
+   struct timespec interval;
+
+   interval.tv_sec   = 2;
+   interval.tv_nsec  = 0;
+
+   // Set up gpi pointer for direct register access
+   setup_io();
+   // Initialize the IO pins.
+   INP_GPIO(SWITCH_IN);
+
+   //  Scan the arguments.
+   while (1)
+   {
+      printf("%d", GET_GPIO(SWITCH_IN));
+      nanosleep(&interval, NULL);
+   }
+
+   return 0;
+}
+
+//
+// Set up a memory regions to access GPIO
+//
+void setup_io()
+{
+   void *gpio_map;
+   int  mem_fd;
+
+   /* open /dev/mem */
+   if ((mem_fd = open("/dev/mem", O_RDWR|O_SYNC) ) < 0)
+   {
+      printf("can't open /dev/mem \n");
+      exit(-1);
+   }
+   /* mmap GPIO */
+   gpio_map = mmap(
+      NULL,             //Any adddress in our space will do
+      BLOCK_SIZE,       //Map length
+      PROT_READ|PROT_WRITE,// Enable reading & writting to mapped memory
+      MAP_SHARED,       //Shared with other processes
+      mem_fd,           //File to map
+      GPIO_BASE         //Offset to GPIO peripheral
+   );
+   close(mem_fd); //No need to keep mem_fd open after mmap
+   if (gpio_map == MAP_FAILED)
+   {
+      printf("mmap error %d, errno = %d\n", gpio_map, errno);//errno also set!
+      exit(-1);
+   }
+   // Always use volatile pointer!
+   gpio = (volatile unsigned *)gpio_map;
+} // setup_io
index 8998cf9..67fd0a3 100644 (file)
@@ -1,17 +1,26 @@
 #include <fstream>
 #include <String.h>
 
-class logstream : public std::ofstream
+class logstream
 {
    std::ofstream destination;
 
 public:
 
+   logstream()
+   {
+   }
+
    logstream(const char * filename)
    { 
       destination.open(filename, std::ios_base::app);
    }
 
+   void open(const char * filename)
+   { 
+      destination.open(filename, std::ios_base::app);
+   }
+
    logstream & operator << (const char *msg);
    logstream & operator << (const String &msg);
 };
diff --git a/src/wakeup.conf b/src/wakeup.conf
new file mode 100644 (file)
index 0000000..fe64aa2
--- /dev/null
@@ -0,0 +1,12 @@
+<?xml version='1.0'?>
+<wakeup version='0.0.1'>
+   <logging>
+      <method>file</method>
+      <destination>.</destination>
+      <level>0</level>
+   </logging>
+   <alarms>
+      <filename>wakeup_alarms.xml</filename>
+   </alarms>
+</wakeup>
+
index 7dd048f..5ccbe74 100644 (file)
+#include <signal.h>
+
+#include <configuration.h>
+#include <Tachyon.h>
+
+#include "logging.h"
 #include "event.h"
 
+//  Global objects
+
+configuration Config;
+logstream     Log;
+Tachyon       Timebase;
+
+std::list<Event> calculate_occurances(std::list<Event> alarms)
+{
+   std::list<Event>           future_alarms;
+   std::list<Event>::iterator alarm;
+
+   for (alarm = alarms.begin(); alarm != alarms.end(); alarm++)
+   {
+      UTC next_time;
+
+      next_time = alarm->next_occurance(Now());
+      //DEBUG
+      std::cout << "Next alarm after will be " << next_time << ".\n";
+      if ( next_time != UTC(date(0,0,0), hour(0)))
+      {
+         future_alarms.push_back(*alarm);
+      }
+   }
+
+   return future_alarms;
+}
+
+//  Reload the configuration and list of events.
+
+void reload()
+{
+   Config.read("wakeup");
+}
+
+// Signal handler for SIGHUP: reload the configuration,
+//  event list and recalculate the next event.
+
+void sighup_handler(int sig)
+{
+   std::cout << "Caught signal " << sig << "\n";
+}
+
 int main()
 {
+   String          logdir;
+   String          alarms_file;
+
+   reload();
+
+   signal(SIGHUP, sighup_handler);
+
+   logdir = Config.find_parameter("logging", "destination");
+   if (logdir == "")
+   {
+      logdir = ".";   // default to current dir
+   }
+   Log.open(logdir + "/wakeup.log");
+
+   std::ofstream runfile("wakeup.run");
+   runfile << Timebase.name() << "\n";
+   runfile.close();
+
+   Log << "wakeup started";
+
    std::list<Event>   set_alarms;
+   std::list<Event>   pending_alarms;
+
+   alarms_file = Config.find_parameter("alarms", "filename");
+   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;
 
-   set_alarms = read_alarms("wakeup_alarms.xml");
+   alarm = pending_alarms.begin();
+   next_alarm = *alarm;
+   while (alarm != pending_alarms.end())
+   {
+      if (alarm->next_occurance(Now()) < next_alarm.next_occurance(Now()))
+      {
+         next_alarm = *alarm;
+      }
+      alarm++;
+   }
+   // DEBUG
+   std::cout << "Sleep until " << next_alarm.next_occurance(Now()) << "\n";
+   Timebase.nanosleep(3000);
 
-   std::cout << alarms_to_XML(set_alarms);
+   std::cout << "wakeup exitting.\n";
+   remove("wakeup.run");
 }
diff --git a/src/wakeup_alarms.xml b/src/wakeup_alarms.xml
new file mode 100644 (file)
index 0000000..6038304
--- /dev/null
@@ -0,0 +1,13 @@
+<?xml version='1.0'?>
+<wakeup>
+  <event id='recurr-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>
+  </event>
+</wakeup>
index 6e8b0fe..30b6217 100644 (file)
@@ -2,8 +2,9 @@ TESTS = lightctrl lightctrl-oor lightctrl-fade $(check_PROGRAMS) check_output
 
 AM_CPPFLAGS = -I../src
 LDADD = -lTachyon -lACL
-check_PROGRAMS = wakeup_load_events sunrise_test event_recurrance
+check_PROGRAMS = wakeup_load_events sunrise_test event_recurrance event_run_sequence
 
-wakeup_load_events_SOURCES = wakeup_load_events.cpp ../src/event.cpp
-event_recurrance_SOURCES = event_recurrance.cpp ../src/event.cpp
+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
 sunrise_test_SOURCES = sunrise_test.cpp ../src/sunrise.cpp
index 3f12c0e..9598113 100644 (file)
@@ -1,5 +1,8 @@
 #include "event.h"
 #include "assert.h"
+#include "logging.h"
+
+logstream  Log;
 
 int main()
 {
@@ -9,6 +12,8 @@ int main()
    UTC                time_expected;
    UTC                next_time;
 
+   Log.open("event_recurrance.log2");
+
    set_alarms = read_alarms("wakeup-02.xml");
 
    // The first alarm at 2020-03-22 06:00 does not recurr
diff --git a/test/event_run_sequence.cpp b/test/event_run_sequence.cpp
new file mode 100644 (file)
index 0000000..ec52214
--- /dev/null
@@ -0,0 +1,34 @@
+#include "event.h"
+#include "assert.h"
+#include "logging.h"
+
+logstream  Log;
+
+int main()
+{
+   String PATH;
+
+   std::list<Event>   set_alarms;
+   std::list<Event>::iterator alarm;
+   UTC                time_to_check;
+   UTC                time_expected;
+   UTC                next_time;
+
+   Log.open("event_run_sequence.log2");
+
+   //  Make sure we execute in our own directory
+
+   PATH = getenv("PATH");
+   PATH = "PATH=../src:" + PATH;
+   putenv(PATH);
+
+   set_alarms = read_alarms("wakeup-03.xml");
+
+   // The first alarm at 2020-03-22 06:00 has a sequence of 3 actions
+
+   alarm = set_alarms.begin();
+
+   // Time of the alarm is irrelevant, just run the sequence
+   alarm->run_sequence();
+
+}
index 58a4f29..e423a69 100755 (executable)
@@ -10,7 +10,7 @@ lightcontrol -r 30 -g 40 -b 20 -w 40 -f 120 &
 sleep 1
 
 read TACHYON_NAME <lightcontrol.run
-tachyon -a 10 $TACHYON_NAME
+#tachyon -a 4.0 $TACHYON_NAME
 
 while [ -f lightcontrol.run ]
 do
diff --git a/test/wakeup-03.xml b/test/wakeup-03.xml
new file mode 100644 (file)
index 0000000..dfac0ca
--- /dev/null
@@ -0,0 +1,10 @@
+<?xml version='1.0'?>
+<wakeup>
+  <event id='non-recurring'>
+    <start>2020-03-22 06:00</start>
+    <action>lightcontrol -r 100 -f 20</action>
+    <action>sleep 30</action>
+    <action>lightcontrol -r 0</action>
+  </event>
+
+</wakeup>
diff --git a/test/wakeup.conf b/test/wakeup.conf
new file mode 100644 (file)
index 0000000..fe64aa2
--- /dev/null
@@ -0,0 +1,12 @@
+<?xml version='1.0'?>
+<wakeup version='0.0.1'>
+   <logging>
+      <method>file</method>
+      <destination>.</destination>
+      <level>0</level>
+   </logging>
+   <alarms>
+      <filename>wakeup_alarms.xml</filename>
+   </alarms>
+</wakeup>
+
diff --git a/test/wakeup_alarms.xml b/test/wakeup_alarms.xml
new file mode 100644 (file)
index 0000000..6038304
--- /dev/null
@@ -0,0 +1,13 @@
+<?xml version='1.0'?>
+<wakeup>
+  <event id='recurr-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>
+  </event>
+</wakeup>
index 6e7a7d0..ed8e2ff 100644 (file)
@@ -1,7 +1,12 @@
 #include "event.h"
+#include "logging.h"
+
+logstream  Log;
 
 int main()
 {
+   Log.open("wakeup_load_events.log2");
+
    std::list<Event>   set_alarms;
 
    set_alarms = read_alarms("wakeup-01.xml");