local_timezone

system_timezone

I generally run my rules on my Linux Workstation. As this machine sits on my desk, its internal clock is set to reflect my local time. I set both the local_timezone and the system_timezone to US/Pacific . That tells my rule system that no time translations are required However, if were to instead run my Rule System on the Raspberry Pi that also runs the Things Gateway, I'd have have to specify the system_timezone as UTC . My local_timezone remains US/Pacific .

$ export local_timezone=US/Pacific $ export system_timezone=US/Pacific $ ./my_rules.py --help

$ ./my_rules.py --local_timezone=US/Pacific --system_timezone=US/Pacific

$ cat config.ini local_timezone=US/Pacific system_timezone=US/Pacific $ ./my_rules.py --admin.config=config.ini

register_trigger

class EveningPorchLightRule ( Rule ): def register_triggers ( self ): self .sunset_trigger = DailySolarEventsTrigger( self .config, " sunset_trigger " , ( " sunset " , ), ( 44.562951 , - 123.3535762 ), " US/Pacific " , 70.0 , " 10m " # ten minutes ) self .ten_pm_trigger = AbsoluteTimeTrigger( self .config, ' ten_pm_trigger ' , ' 22:00:00 ' ) return ( self .sunset_trigger, self .ten_pm_trigger) def action ( self , the_triggering_thing , * args ): if the_triggering_thing is self .sunset_trigger: self .Philips_HUE_01.on = True else : self .Philips_HUE_01.on = False (see this code in situ in the solar_event_rules.py file in the pywot rule system demo directory

DailySolarEventsTrigger

sunset_trigger

sunset

sunset

DailySolarEventsTrigger

AbsoluteTimeTrigger

action

action

the_triggering_thing

sunset_trigger

action

ten_pm_trigger

action

class RahukaalamRule ( Rule ): def register_triggers ( self ): rahukaalam_trigger = DailySolarEventsTrigger( self .config, " rahukaalam_trigger " , ( " rahukaalam_start " , " rahukaalam_end " , ), ( 44.562951 , - 123.3535762 ), " US/Pacific " , 70.0 , ) return (rahukaalam_trigger,) def action ( self , the_triggering_thing , the_trigger , * args ): if the_trigger == " rahukaalam_start " : logging.info( ' %s starts ' , self .name) self .Philips_HUE_02.on = True self .Philips_HUE_02.color = " #FF9900 " else : logging.info( ' %s ends ' , self .name) self .Philips_HUE_02.on = False (this code is not part of the demo scripts, however, the next very similar script is.)

register_trigger

rahukaalam_start

rahukaalam_end

the_trigger

class RahukaalamRule ( Rule ): def register_triggers ( self ): rahukaalam_trigger = DailySolarEventsTrigger( self .config, " rahukaalam_trigger " , ( " rahukaalam_start " , " rahukaalam_end " , ), ( 44.562951 , - 123.3535762 ), " US/Pacific " , 70.0 , " -2250s " ) return (rahukaalam_trigger,) async def blink ( self , number_of_seconds ): number_of_blinks = number_of_seconds / 3 for i in range ( int (number_of_blinks)): self .Philips_HUE_02.on = True await asyncio.sleep( 2 ) self .Philips_HUE_02.on = False await asyncio.sleep( 1 ) self .Philips_HUE_02.on = True def action ( self , the_triggering_thing , the_trigger , * args ): if the_trigger == " rahukaalam_start " : logging.info( ' %s starts ' , self .name) self .Philips_HUE_02.on = True self .Philips_HUE_02.color = " #FF9900 " asyncio.ensure_future( self .blink( 30 )) else : logging.info( ' %s ends ' , self .name) self .Philips_HUE_02.on = False (see this code in situ in the solar_event_rules.py file in the pywot rule system demo directory

action

blink

In my previous blog post , I introduced Time Triggers to demonstrate time based home automation. Sometimes, however, pegging an action down to a specific time doesn't work: darkness falls at different times every evening as one season follows another. How do you calculate sunset time? It's complicated, but there are several Python packages that can do it: I chose Astral The Things Gateway doesn't know where it lives. The Raspberry Pi distribution that includes the Things Gateway doesn't automatically know and understand your timezone when it is booted. Instead, it uses UTC, essentially Greenwich Mean Time, with none of those confounding Daylight Savings rules. Yet when viewing the Things Gateway from within a browser, the times in the GUI Rule System automatically reflect your local timezone. The presentation layer of the Web App served by the Things Gateway is responsible for showing you the correct time for your location. Beware, when you travel and access your Things Gateway GUI rules remotely from a different timezone, any references to time will display in your remote timezone. They'll still work properly at their appropriate times, but they will look weird during travel.My own homegrown rule system uses a different tactic: it nails down a timezone for your Things Gateway. In the configuration, you specify two timezones: the timezone where your Things Gateway is physically located,, and the timezone that is the default on the computer's clock running the the external rule system,. Here's two examples to show why both need to be specified.These configuration parameters can be set in several ways. You can create environment variables:Or they can be command line parameters:Or they can be in a configuration file:My next blog post will cover more on how to set configuration and run this rule system on either the same Raspberry Pi that runs the Things Gateway or some other machine.Meanwhile, let's talk about solar events. Once the Rule System knows where the Things Gateway is, it can calculate sunrise, sunset along with a host of other solar events that happen on a daily basis. That's where the Python package Astral comes in. Given the latitude, longitude, elevation and the local timezone, it will calculate the times for: blue_hour sunset , and twilight I created a trigger object that wraps Astral so it can be specified in themethod of the Rule System. Here's a rule that will turn a porch light on ten minutes after sunset every day:Like the other rules that I've created, I start by creating my trigger, in this case, an instance of theclass. It is given the name "" and the solar event, "". The rule can trigger on multiple solar events, but in this case, since I want only one, "" appears alone in a tuple. Next I specify the latitude and longitude of my home city, Corvallis, OR. That's in the US/Pacific timezone and about 70 meters above sea level. Finally, I specify a string representing 10 minutes.After the, I create another trigger,to handle turning the light off at 10pm. I could have created a second rule to do this, but a single rule to handle both ends of the operation seemed more satisfying.In thepart of the rule, I needed to differentiate from the two types of actions. Both triggers will call thefunction, each identifying itself as the value of the parameter,. If it was thecalling, it turns the porch light on. If it was thecalling, the light gets turned off. I think the implementation begs for a better dispatch method, but Python doesn't help much with that.Some of the solar events are not just a single instant in time like a sunset, some represent periods during the day. One example is Rahukaalam . According to a Wikipedia article, in the realm of Vedic Astrology , Rahukaalam is an "inauspicious time" during which it is unwise to embark on new endeavors. It's based on dividing the daylight hours into eight periods. One of the periods is marked as the inauspicious one based on the day of the week. For example, it's the fourth period on Fridays and the seventh on Tuesdays. Since the length of the daylight hours changes every day, the lengths of the periods change and it gets hard to remember when it's okay to start something new.Here's a rule that will control a warning light. The light being on indicates that the current time is within the start and end of the Rahukaalam time for the given global location and elevationLike all rules, it has two parts: registering triggers and responding to trigger actions. In, I subscribe to theandsolar events for my town location, timezone and elevation. In the action, I just look toto see which of the two possible triggers fired. It results in a suitably cautious orange light illuminating during the Rahukaalam period.Could we make the light blink for the first 30 seconds, just so we ensure that we notice the warning?Here I created an async method that will turn the lamp on for two seconds and off for a second as many times as it can in 30 seconds. The method is fired off by themethod when the light is initially turned on. Once theroutine has finished blinking, it silently quits.Perhaps one of the best things about the Things Gateway is that the Things Framework allows nearly any programming language to participate.Thanks this week goes to the authors and contributors to the Python package Astral . Readily available fun packages like Astral contribute immensely to the sheer joy of Open Source programming.Now it looks like I've only got twenty minutes to publish this before I enter an inauspicious time... D'oh, too late...