Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 3 additions & 1 deletion .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -2,4 +2,6 @@
*.swp
*.tgz
*~

lib/
package/
package-to-manifest.py
4 changes: 4 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,10 @@ After upgrade the addon the pages must be reloaded before the new attributes are
After upgrade to version 1.0.0 check existing rules because some properties are changed.

## Release notes ##
1.0.1
* Add Sunrise Offset Minutes and Sunset Offset Minutes config which if set, generates a Sunrise/Sunset event offset from the actual Sunrise/Sunset event.
* When creating rules simply Select your offset event i.e. Event "Sunset -n mins"

1.0.0
* Added event 'Sunset'/'Sunrise'
* Added property enum 'Weekday'
Expand Down
80 changes: 80 additions & 0 deletions manifest.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,80 @@
{
"author": "tomasy",
"description": "Date Time addon for Mozilla IoT Gateway\nBecause of a bug in rule engine after adding a 'Dark' or 'Weekend' to the rule, change state for them manually. See https://github.com/tomasy/date-time-adapter",
"gateway_specific_settings": {
"webthings": {
"exec": "python3 {path}/bootstrap.py",
"primary_type": "adapter",
"strict_max_version": "*",
"strict_min_version": "0.10.0"
}
},
"homepage_url": "https://github.com/tomasy/date-time-adapter",
"id": "date-time-adapter",
"license": "MPL-2.0",
"manifest_version": 1,
"name": "DateTime Adapter",
"options": {
"default": {
"horizon": "-0:34",
"lat": "",
"lng": "",
"log_level": "INFO",
"sunrise_offset_mins": 0,
"sunset_offset_mins": 0,
"timezone": "UTC"
},
"schema": {
"description": "Configuration for sunset and sunrise",
"properties": {
"horizon": {
"description": "Horizon example. '-0:34'=(just below horizon), -6=civil twilight, -12=nautical or -18=astronomical",
"type": "string"
},
"lat": {
"description": "Latitude (e.g. 57.67 for Gothenburg, Sweden) ",
"type": "string"
},
"lng": {
"description": "Longitude (e.g. 11.89 for Gothenburg, Sweden)",
"type": "string"
},
"log_level": {
"description": "Log level. Use INFO as standard",
"enum": [
"INFO",
"DEBUG"
],
"type": "string"
},
"sunrise_offset_mins": {
"description": "Create a secondary sunrise event that occurs n minutes before or after the adding actual sunset event.",
"maximum": 60,
"minimum": -60,
"type": "number"
},
"sunset_offset_mins": {
"description": "Create a secondary sunset event that occurs n minutes before or after the adding actual sunset event.",
"maximum": 60,
"minimum": -60,
"type": "number"
},
"timezone": {
"description": "Timezone. (e.g. Europe/Stockholm)",
"type": "string"
}
},
"required": [
"timezone",
"lat",
"lng",
"horizon",
"sunset_offset_mins",
"sunrise_offset_mins"
],
"type": "object"
}
},
"short_name": "DateTime Ada",
"version": "1.0.1"
}
49 changes: 37 additions & 12 deletions package.json
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
{
"name": "date-time-adapter",
"display_name": "DateTime Adapter",
"version": "1.0.0",
"version": "1.0.1",
"description": "Date Time addon for Mozilla IoT Gateway\nBecause of a bug in rule engine after adding a 'Dark' or 'Weekend' to the rule, change state for them manually. See https://github.com/tomasy/date-time-adapter",
"author": "tomasy",
"main": "main.py",
Expand All @@ -22,11 +22,11 @@
"url": "https://github.com/tomasy/date-time-adapter/issues"
},
"files": [
"LICENSE",
"SHA256SUMS",
"LICENSE",
"bootstrap.py",
"main.py",
"package.json",
"manifest.json",
"pkg/__init__.py",
"pkg/config.py",
"pkg/date_adapter.py",
Expand All @@ -46,14 +46,24 @@
"plugin": true,
"exec": "python3 {path}/bootstrap.py",
"config": {
"timezone": "UTC",
"lat": "",
"lng": "",
"horizon": "-0:34",
"log_level": "INFO"
"timezone": "UTC",
"lat": "",
"lng": "",
"horizon": "-0:34",
"sunrise_offset_mins": 0,
"sunset_offset_mins": 0,
"log_level": "INFO"
},
"schema": {
"type": "object",
"required": [
"timezone",
"lat",
"lng",
"horizon",
"sunset_offset_mins",
"sunrise_offset_mins"
],
"description": "Configuration for sunset and sunrise",
"properties": {
"timezone": {
Expand All @@ -72,12 +82,27 @@
"type": "string",
"description": "Horizon example. '-0:34'=(just below horizon), -6=civil twilight, -12=nautical or -18=astronomical"
},
"sunset_offset_mins": {
"type": "number",
"description": "Create a secondary sunset event that occurs n minutes before or after the adding actual sunset event.",
"minimum": -60,
"maximum": 60
},
"sunrise_offset_mins": {
"type": "number",
"description": "Create a secondary sunrise event that occurs n minutes before or after the adding actual sunset event.",
"minimum": -60,
"maximum": 60
},
"log_level": {
"type": "string",
"enum": [ "INFO", "DEBUG" ],
"type": "string",
"enum": [
"INFO",
"DEBUG"
],
"description": "Log level. Use INFO as standard"
}
}
}
}
}
}
}
2 changes: 1 addition & 1 deletion package.sh
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ pip3 install -r requirements.txt -t lib --no-binary pyHS100 --prefix ""

# Put package together
#cp -r lib pkg LICENSE README.md package.json *.py package/
cp -r pkg LICENSE README.md package.json *.py requirements.txt setup.cfg package/
cp -r pkg LICENSE README.md package.json manifest.json *.py requirements.txt setup.cfg package/
find package -type f -name '*.pyc' -delete
find package -type d -empty -delete

Expand Down
4 changes: 4 additions & 0 deletions pkg/config.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,8 @@ def __init__(self, package_name):
self.lat = None
self.lng = None
self.horizon = None
self.sunset_offset_mins = None
self.sunrise_offset_mins = None
self.log_level = None
self.open()
self.load()
Expand All @@ -22,6 +24,8 @@ def load(self):
self.lat = config['lat']
self.lng = config['lng']
self.horizon = config['horizon']
self.sunset_offset_mins = config['sunset_offset_mins']
self.sunrise_offset_mins = config['sunrise_offset_mins']
self.log_level = config['log_level']
except Exception as ex:
logging.exception('Strange config', config)
60 changes: 57 additions & 3 deletions pkg/date_device.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
import logging
import threading
import time
import datetime
from gateway_addon import Device, Event
from .util import DT
from .date_property import DateWeekendProperty, DateEvenHourProperty, DateEvenMinuteProperty, \
Expand Down Expand Up @@ -54,7 +55,7 @@ def poll(self):
logging.error('THREAD ERR Exception %s', ex)
logging.exception('Exception %s', ex)
continue
logging.info('POLL STOPED for device: %s', self.name)
logging.info('POLL STOPPED for device: %s', self.name)


class DateTimeDevice(DTDevice):
Expand All @@ -67,9 +68,14 @@ def __init__(self, adapter, _id, _config):
DTDevice.__init__(self, adapter, _id)
self._context = 'https://iot.mozilla.org/schemas'
self._type = ['BinarySensor', 'MultiLevelSensor']
self.dt = DT(_config.timezone, _config.lat, _config.lng, _config.horizon)
self.dt = DT(_config.timezone, _config.lat, _config.lng, _config.horizon, _config.sunset_offset_mins, _config.sunrise_offset_mins)
self.sunrise = self.dt.calc_sunrise()
self.sunset = self.dt.calc_sunset()
self.sunset_offset_mins = _config.sunset_offset_mins
self.sunrise_offset_mins = _config.sunrise_offset_mins
self.sunset_offset_active = False;
self.sunrise_offset_active = False;

logging.info('sunset: %s sunrise: %s', self.sunset, self.sunrise)

self.add_property(DateWeekendProperty(self, self.dt))
Expand All @@ -91,6 +97,23 @@ def __init__(self, adapter, _id, _config):
'description': 'An event for new sunrise',
'type': 'string',
})

if self.sunset_offset_mins is not None and self.sunset_offset_mins is not 0:
title = 'Sunset offset ' + str(self.sunset_offset_mins) + ' mins'
self.add_event('sunset_offset', {
'title': title, 'label': 'Sunset_Offset',
'description': 'An event for new offset sunset',
'type': 'string',
})

if self.sunrise_offset_mins is not None and self.sunrise_offset_mins is not 0:
title = 'Sunrise offset ' + str(self.sunset_offset_mins) + ' mins'
self.add_event('sunrise_offset', {
'title': title, 'label': 'Sunrise_Offset',
'description': 'An event for new offset sunrise',
'type': 'string',
})

self.name = 'DateTime'
self.description = 'DateTime desc'
self.init()
Expand All @@ -99,16 +122,47 @@ def __init__(self, adapter, _id, _config):
def check(self):
self.check_sunrise()
self.check_sunset()
self.check_offset_sunrise()
self.check_offset_sunset()

def check_sunrise(self):
if self.dt.now() > self.sunrise:
self.check_send_event(self.sunrise, 'sunrise')
self.sunrise = self.dt.calc_sunrise()
self.sunrise_offset_active = False

def check_sunset(self):
if self.dt.now() > self.sunset:
self.check_send_event(self.sunset, 'sunset')
self.sunset = self.dt.calc_sunset()
self.sunset_offset_active = False

def check_offset_sunrise(self):
if self.sunrise_offset_mins is not None and self.sunrise_offset_active is False:
offset_sunrise = None
if self.sunrise_offset_mins < 0:
offset_sunrise = self.sunrise - datetime.timedelta(minutes=-self.sunrise_offset_mins)
if self.sunrise_offset_mins > 0:
offset_sunrise = self.sunrise + datetime.timedelta(minutes=self.sunrise_offset_mins)

if offset_sunrise is not None:
if self.dt.now() > offset_sunrise:
self.check_send_event(self.sunrise, 'sunrise_offset')
self.sunrise_offset_active = True

def check_offset_sunset(self):
if self.sunset_offset_mins is not None and self.sunset_offset_active is False:
offset_sunset = None
if self.sunset_offset_mins < 0:
offset_sunset = self.sunset - datetime.timedelta(minutes=-self.sunset_offset_mins)
if self.sunset_offset_mins > 0:
offset_sunset = self.sunset + datetime.timedelta(minutes=self.sunset_offset_mins)

if offset_sunset is not None:
if self.dt.now() > offset_sunset:
self.check_send_event(self.sunset, 'sunset_offset')
self.sunset_offset_active = True;


""" Check if the sunset/sunrise time occured and if so send event """
def check_send_event(self, next_sunset_sunrise, event_name):
Expand All @@ -127,7 +181,7 @@ def __init__(self, adapter, _id, _config):
DTDevice.__init__(self, adapter, _id)
self._context = 'https://iot.mozilla.org/schemas'
self._type = ['BinarySensor', 'MultiLevelSensor']
self.dt = DT(_config.timezone, _config.lat, _config.lng, _config.horizon)
self.dt = DT(_config.timezone, _config.lat, _config.lng, _config.horizon, _config.sunset_offset_mins, _config.sunrise_offset_mins)

self.add_property(DTMinuteProperty(self,self.dt))

Expand Down
15 changes: 11 additions & 4 deletions pkg/util.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@
import pytz

class DT():
def __init__(self, timezone, lat, lng, horizon):
def __init__(self, timezone, lat, lng, horizon, sunset_offset_mins, sunrise_offset_mins):
self.timezone = timezone
self.lat = lat
self.lng = lng
Expand Down Expand Up @@ -87,7 +87,7 @@ def calc_sunrise(self):
sunrise = observer_today.next_rising(ephem.Sun())
sunrise_local = self.to_localtime(sunrise.datetime())
logging.info('CALC_SUNRISE today.utc: %s sunrise: %s sunrise_local: %s', observer_today.date, sunrise, sunrise_local)
logging.debug('DTSRISE lat: %s lng: %s observer_today: %s', self.lat, self.lng, observer_today)
logging.debug('DTSRISE lat: %s lng: %s observer_today: %s', self.lat, self.lng, observer_today)
return sunrise_local

def sunrise(self):
Expand All @@ -101,7 +101,14 @@ def calc_sunset(self):
sunset = observer_today.next_setting(ephem.Sun())
sunset_local = self.to_localtime(sunset.datetime())
logging.info('CALC_SUNSET today.utc: %s sunset: %s sunset_local: %s', observer_today.date, sunset, sunset_local)
logging.debug('DTSET lat: %s lng: %s observer_today: %s', self.lat, self.lng, observer_today)

# if self.sunset_offset_mins is not None:
# if self.sunset_offset_mins < 0:
# sunset_local = sunset_local - datetime.timedelta(minutes=-self.sunset_offset_mins)
# if self.sunset_offset_mins > 0:
# sunset_local = sunset_local+ datetime.timedelta(minutes=self.sunset_offset_mins)
# logging.info('CALC_SUNSET_OFFSET override_mins: %s mins override_sunset: %s', self.sunset_offset_mins, sunset_local)

return sunset_local

def sunset(self):
Expand All @@ -117,4 +124,4 @@ def to_localtime(self, dt):
dt_utc = dt.replace(tzinfo=utc)
# convert to localtimezone
dt_local = dt_utc.astimezone(local_timezone)
return dt_local
return dt_local