From 1eebea8720de4e941ce9d2f74c07ee9c1700486a Mon Sep 17 00:00:00 2001 From: Damian Date: Fri, 7 Jun 2019 18:02:46 +0100 Subject: [PATCH 1/4] Sunset/Sunrise offset If you are like me and have a partner who complains that the lights aren't coming on soon enough, then this change will get you back in the good books. Set an offset to Sunset or Sunrise up to a value of 60 mins that will allow you to fine tune the actions that are triggered by the sunset or sunrise events or the dark property. --- package.json | 39 ++++++++++++++++++++++++++++++--------- pkg/config.py | 4 ++++ pkg/date_device.py | 18 +++++++++++++++++- 3 files changed, 51 insertions(+), 10 deletions(-) diff --git a/package.json b/package.json index 3f469ed..2f1d8a2 100644 --- a/package.json +++ b/package.json @@ -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": { @@ -72,12 +82,23 @@ "type": "string", "description": "Horizon example. '-0:34'=(just below horizon), -6=civil twilight, -12=nautical or -18=astronomical" }, + "sunset_offset_mins": { + "type": "number", + "description": "Fine tune the sunset event by adding or subtracting minutes from the actual sunset event time." + }, + "sunrise_offset_mins": { + "type": "number", + "description": "Fine tune the sunset event by adding or subtracting minutes from the actual sunset event time." + }, "log_level": { - "type": "string", - "enum": [ "INFO", "DEBUG" ], + "type": "string", + "enum": [ + "INFO", + "DEBUG" + ], "description": "Log level. Use INFO as standard" - } + } } } } -} +} \ No newline at end of file diff --git a/pkg/config.py b/pkg/config.py index caa8c1b..3a8a448 100644 --- a/pkg/config.py +++ b/pkg/config.py @@ -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() @@ -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) diff --git a/pkg/date_device.py b/pkg/date_device.py index 6fb26d9..1ad57a1 100644 --- a/pkg/date_device.py +++ b/pkg/date_device.py @@ -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, \ @@ -70,7 +71,22 @@ def __init__(self, adapter, _id, _config): self.dt = DT(_config.timezone, _config.lat, _config.lng, _config.horizon) self.sunrise = self.dt.calc_sunrise() self.sunset = self.dt.calc_sunset() - logging.info('sunset: %s sunrise: %s', self.sunset, self.sunrise) + + logging.info('Actual sunset: %s sunrise: %s', self.sunset, self.sunrise) + + if _config.sunrise_offset_mins is not None: + if _config.sunrise_offset_mins < 0: + self.sunrise = self.sunrise - datetime.timedelta(minutes=-_config.sunrise_offset_mins) + if _config.sunrise_offset_mins > 0: + self.sunrise = self.sunrise + datetime.timedelta(minutes=_config.sunrise_offset_mins) + + if _config.sunset_offset_mins is not None: + if _config.sunset_offset_mins < 0: + self.sunset = self.sunset - datetime.timedelta(minutes=-_config.sunset_offset_mins) + if _config.sunset_offset_mins > 0: + self.sunset = self.sunset + datetime.timedelta(minutes=_config.sunset_offset_mins) + + logging.info('Offset sunset: %s sunrise: %s', self.sunset, self.sunrise) self.add_property(DateWeekendProperty(self, self.dt)) self.add_property(DateEvenHourProperty(self, self.dt)) From dc2d8c283176f463f168a8ca2184c1b179414492 Mon Sep 17 00:00:00 2001 From: Damian Date: Fri, 7 Jun 2019 23:24:36 +0100 Subject: [PATCH 2/4] Revert "Sunset/Sunrise offset" This reverts commit 1eebea8720de4e941ce9d2f74c07ee9c1700486a. --- package.json | 39 +++++++++------------------------------ pkg/config.py | 4 ---- pkg/date_device.py | 18 +----------------- 3 files changed, 10 insertions(+), 51 deletions(-) diff --git a/package.json b/package.json index 2f1d8a2..3f469ed 100644 --- a/package.json +++ b/package.json @@ -46,24 +46,14 @@ "plugin": true, "exec": "python3 {path}/bootstrap.py", "config": { - "timezone": "UTC", - "lat": "", - "lng": "", - "horizon": "-0:34", - "sunrise_offset_mins": 0, - "sunset_offset_mins": 0, - "log_level": "INFO" + "timezone": "UTC", + "lat": "", + "lng": "", + "horizon": "-0:34", + "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": { @@ -82,23 +72,12 @@ "type": "string", "description": "Horizon example. '-0:34'=(just below horizon), -6=civil twilight, -12=nautical or -18=astronomical" }, - "sunset_offset_mins": { - "type": "number", - "description": "Fine tune the sunset event by adding or subtracting minutes from the actual sunset event time." - }, - "sunrise_offset_mins": { - "type": "number", - "description": "Fine tune the sunset event by adding or subtracting minutes from the actual sunset event time." - }, "log_level": { - "type": "string", - "enum": [ - "INFO", - "DEBUG" - ], + "type": "string", + "enum": [ "INFO", "DEBUG" ], "description": "Log level. Use INFO as standard" - } + } } } } -} \ No newline at end of file +} diff --git a/pkg/config.py b/pkg/config.py index 3a8a448..caa8c1b 100644 --- a/pkg/config.py +++ b/pkg/config.py @@ -9,8 +9,6 @@ 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() @@ -24,8 +22,6 @@ 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) diff --git a/pkg/date_device.py b/pkg/date_device.py index 1ad57a1..6fb26d9 100644 --- a/pkg/date_device.py +++ b/pkg/date_device.py @@ -3,7 +3,6 @@ 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, \ @@ -71,22 +70,7 @@ def __init__(self, adapter, _id, _config): self.dt = DT(_config.timezone, _config.lat, _config.lng, _config.horizon) self.sunrise = self.dt.calc_sunrise() self.sunset = self.dt.calc_sunset() - - logging.info('Actual sunset: %s sunrise: %s', self.sunset, self.sunrise) - - if _config.sunrise_offset_mins is not None: - if _config.sunrise_offset_mins < 0: - self.sunrise = self.sunrise - datetime.timedelta(minutes=-_config.sunrise_offset_mins) - if _config.sunrise_offset_mins > 0: - self.sunrise = self.sunrise + datetime.timedelta(minutes=_config.sunrise_offset_mins) - - if _config.sunset_offset_mins is not None: - if _config.sunset_offset_mins < 0: - self.sunset = self.sunset - datetime.timedelta(minutes=-_config.sunset_offset_mins) - if _config.sunset_offset_mins > 0: - self.sunset = self.sunset + datetime.timedelta(minutes=_config.sunset_offset_mins) - - logging.info('Offset sunset: %s sunrise: %s', self.sunset, self.sunrise) + logging.info('sunset: %s sunrise: %s', self.sunset, self.sunrise) self.add_property(DateWeekendProperty(self, self.dt)) self.add_property(DateEvenHourProperty(self, self.dt)) From d4dee84196212339238aa991a2762bd56d565a5a Mon Sep 17 00:00:00 2001 From: Damian Date: Fri, 7 Feb 2020 17:37:12 +0000 Subject: [PATCH 3/4] Draft CHANGES --- .gitignore | 4 ++- manifest.json | 80 ++++++++++++++++++++++++++++++++++++++++++++++ package.json | 49 +++++++++++++++++++++------- package.sh | 2 +- pkg/config.py | 4 +++ pkg/date_device.py | 60 ++++++++++++++++++++++++++++++++-- pkg/util.py | 15 ++++++--- 7 files changed, 193 insertions(+), 21 deletions(-) create mode 100644 manifest.json diff --git a/.gitignore b/.gitignore index 56b4b5c..e695ee4 100644 --- a/.gitignore +++ b/.gitignore @@ -2,4 +2,6 @@ *.swp *.tgz *~ - +lib/ +package/ +package-to-manifest.py \ No newline at end of file diff --git a/manifest.json b/manifest.json new file mode 100644 index 0000000..b5c881f --- /dev/null +++ b/manifest.json @@ -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" +} \ No newline at end of file diff --git a/package.json b/package.json index 3f469ed..4dd72f9 100644 --- a/package.json +++ b/package.json @@ -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", @@ -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", @@ -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": { @@ -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" - } + } } } } -} +} \ No newline at end of file diff --git a/package.sh b/package.sh index a5d724a..12094b3 100755 --- a/package.sh +++ b/package.sh @@ -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 diff --git a/pkg/config.py b/pkg/config.py index caa8c1b..3a8a448 100644 --- a/pkg/config.py +++ b/pkg/config.py @@ -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() @@ -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) diff --git a/pkg/date_device.py b/pkg/date_device.py index 6fb26d9..09c8e83 100644 --- a/pkg/date_device.py +++ b/pkg/date_device.py @@ -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, \ @@ -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): @@ -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)) @@ -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 ' + 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 ' + 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() @@ -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): @@ -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)) diff --git a/pkg/util.py b/pkg/util.py index a7ee9c0..4cd9b0b 100644 --- a/pkg/util.py +++ b/pkg/util.py @@ -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 @@ -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): @@ -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): @@ -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 \ No newline at end of file From d67392bfc06105c18b3bce25d91477a75804bcad Mon Sep 17 00:00:00 2001 From: Damian Date: Mon, 10 Feb 2020 07:41:01 -0800 Subject: [PATCH 4/4] Release 1.0.1 --- README.md | 4 ++++ pkg/date_device.py | 4 ++-- 2 files changed, 6 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index b2adccc..97f094e 100644 --- a/README.md +++ b/README.md @@ -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' diff --git a/pkg/date_device.py b/pkg/date_device.py index 09c8e83..b46d997 100644 --- a/pkg/date_device.py +++ b/pkg/date_device.py @@ -99,7 +99,7 @@ def __init__(self, adapter, _id, _config): }) if self.sunset_offset_mins is not None and self.sunset_offset_mins is not 0: - title = 'Sunset ' + str(self.sunset_offset_mins) + ' mins' + 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', @@ -107,7 +107,7 @@ def __init__(self, adapter, _id, _config): }) if self.sunrise_offset_mins is not None and self.sunrise_offset_mins is not 0: - title = 'Sunrise ' + str(self.sunset_offset_mins) + ' mins' + 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',