Vacation mode

So I have had a KNX system managing all lighting in my house since 2001 and never got the automations I want. I have tried different open source as well as commercial systems. That is until now! I found Home Assistant two weeks ago and it was so easy to get it up and running. Thank you to all contributors to this fantastic system!

The first automation I always wanted is a vacation mode that replays all light activity from say a week ago. By creating a very simple app with AppDaemon that reads the event database and triggers lights on/off combined with the person presence detection it could not have been easier. So I would like to share this with anyone in need of something similar.

Regards
/Martin

11 Likes

How do you install this app and what exactly is needed?

i like the idea, although i am not sure if your app can work yet. For example, if you turned on several lights, there is no guarantee that they will all be turned off. Or am I missing something? Maybe it would be better to load all on and off times of the desired period once a day and then start the schedulers?

Install AppDaemon
https://appdaemon.readthedocs.io/en/stable/
Save the python script to the AppDaemon apps folder
Modify the apps.yaml
If you have presence detection, create a Persons group, otherwise change the script to trigger on something else.

I see, multiple lights on/off at the same time does not work, I have light groups in KNX so I only ever get one separate on/off event so it works for me. I’ll change the code to do batch processing instead.

I have a person detection and I’m using a randomizer but I can’t figure out how I would go about using your app…

Also your .py only looks at light not switches is that correct?

Here is an example of an automation I’ve made:

automation:
  - alias: Occupancy Simulator-Random Timed Lights (Sunset)
    initial_state: 'on'
    trigger:
      - platform: sun
        event: sunset
        offset: '00:15:00'
    condition:
      - condition: state
        entity_id: input_boolean.enable_occupancy_simulator
        state: 'on'
      - condition: template
        value_template: "{{ is_state('device_tracker.galaxy_s8','not_home') and is_state('device_tracker.rowess7lan','not_home') }}"
    action:
      - delay: '00:{{ range(10,40) | random | int }}:00'
      - service: homeassistant.turn_on
        data:    
        # Turn ON Kitchen Light
          entity_id: switch.inovelli_lzw30_switch_switch	
          brightness: 255
      - delay: '00:0{{ range(9) | random | int }}:{{ range(10,58) | random | int }}'
      - service: homeassistant.turn_off
        data:
        # Turn OFF Kitchen Light
          entity_id: switch.inovelli_lzw30_switch_switch

You should be able to modify my script to look for switch. in the database instead of light. as I do. I created on single state with a group tp enabe the automation but it should be easy to modify my script to use different states in a similar way to yours.

1 Like

Changed scheduling to create a batch everu hour, fixes problem where many lights are switched at the same time.

This was an excellent idea. I was looking at doing some simulation, but I think it’s hard to beat just using pass history. I modified your code some. I added a few more parameters to make it more flexible as I use switches and not lights, so you can pass this as a configuration variable. You were looking at a group to see if someone was home, but I only wanted to have it kick off if I set it to kick off based on an HA input variable. I also made it so that the number of days back could be based on an HA input variable. Using the HA input variables allows you to changes the values from the HA GUI. The database stores events in UTC not localtime and so as the code was events were going off at the wrong hour, so I changed this. The code has defaults for all configuration parameters, so the configuration parameters are optional. I’ll do a git pull and push you the changes in case you want to integrate them. I think your app should be in the list of apps that can be pulled straight from the HA gui. Great work.

1 Like

Great update, thank you, the pull requests has been merged! I appreciate you taking the time to add functionality and fixing my errors.

I’d be interested in taking a look at this app. Any chance of this making it into HACS?

1 Like

Martin the following https://hacs.xyz/docs/publish/start has information on what is required to get into HACS. It doesn’t look like you have to do much, however there is an assumption that the repo has a specific structure with a few required files. I think you had a great approach and this is worth considering as I don’t think there is an alternative solution in HACS, which resulted in me finding your code base.

2 Likes

Thanks for the pointer, I have changed my repo to be compliant with HACS and submitted a pull request for the addition of it. Any ideas how I can point to the example apps yaml when installing? When I installed it from a custom repo I didn’t get the full readme where the example is described so the settings needed in apps.yaml are a bit hard to find…

1 Like

I don’t think you can point the application to the example_apps.yaml, as the expectation is the person installing the app would be expected to update apps.yaml with the correct information for their installation. I think the best that can be done is provide more details in the readme file for the parameters. I’ll look at expanding your readme later today. I’ll also probably provide you one more small update on the code that handles cases where you have smart plugs in sockets with dumb wall switches, and the wall switches are sometime used to poweroff the plug.

Hi,

Trying to set this code up but having an issue it seems with a connection? I am using the MariaDB addon, have the MySql listing the in the appdaemon config of the addon, default homeassistant. I am not sure if I have the right syntax for the hassDir of the yaml file, and /or do I use localhost as the databaseHost: or the docker ip?

Thanks

Appdeamon Config:

system_packages: []
python_packages:
  - PyMySQL
init_commands: []

MariDB config:

databases:

  • homeassistant
    logins:
  • username: homeassistant
    password: xxxx
    rights:
  • username: homeassistant
    database: homeassistant

Yaml for replay_lights:

replay_lights:
hassDir: ‘mysql://homeassistant:xxxx@core-mariadb/homeassistant?charset=utf8mb4’
databaseType: MariaDB
databaseHost: “172.30.33.7”
databaseUser: “homeassistant”
databasePassword: “xxxx”
databaseSchema: “homeassistant”
module: replay_lights
class: ReplayLights
numberOfDaysBack: 7
deviceType: “light”
enableTag: “input_boolean.holidays_ad”
enableVal: “on”
excludeList: “switch.garage_door_223,switch.coffee_745”
constrain_input_boolean: input_boolean.holidays_ad

Appdaemon Error Log:

> 2021-03-12 16:28:59.067772 WARNING replay_lights: ------------------------------------------------------------
> 2021-03-12 17:28:59.064922 WARNING replay_lights: ------------------------------------------------------------
> 2021-03-12 17:28:59.065061 WARNING replay_lights: Unexpected error in worker for App replay_lights:
> 2021-03-12 17:28:59.065203 WARNING replay_lights: Worker Ags: {'id': '3015ba52469846a3b0db4033592a8e2a', 'name': 'replay_lights', 'objectid': '273e7dd8ae054f7e93db53c25337a483', 'type': 'scheduler', 'function': <bound method ReplayLights.scheduleNextEventBatch of <replay_lights.ReplayLights object at 0x7fdb4117a8e0>>, 'pin_app': True, 'pin_thread': 61, 'kwargs': {'interval': 3600, '__thread_id': 'thread-61'}}
> 2021-03-12 17:28:59.065337 WARNING replay_lights: ------------------------------------------------------------
> 2021-03-12 17:28:59.065581 WARNING replay_lights: Traceback (most recent call last):
>   File "/usr/lib/python3.8/site-packages/pymysql/connections.py", line 613, in connect
>     sock = socket.create_connection(
>   File "/usr/lib/python3.8/socket.py", line 808, in create_connection
>     raise err
>   File "/usr/lib/python3.8/socket.py", line 796, in create_connection
>     sock.connect(sa)
> ConnectionRefusedError: [Errno 111] Connection refused
> 
> During handling of the above exception, another exception occurred:
> 
> Traceback (most recent call last):
>   File "/usr/lib/python3.8/site-packages/appdaemon/threading.py", line 887, in worker
>     funcref(self.AD.sched.sanitize_timer_kwargs(app, args["kwargs"]))
>   File "/config/appdaemon/apps/house_mode/replay_lights.py", line 99, in scheduleNextEventBatch
>     conn = pymysql.connect(host=self.databaseHost, user=self.databaseUser, password=self.databasePassword, db=self.databaseSchema, charset='utf8')
>   File "/usr/lib/python3.8/site-packages/pymysql/connections.py", line 353, in __init__
>     self.connect()
>   File "/usr/lib/python3.8/site-packages/pymysql/connections.py", line 664, in connect
>     raise exc
> pymysql.err.OperationalError: (2003, "Can't connect to MySQL server on '172.30.33.7' ([Errno 111] Connection refused)")
> 
> 2021-03-12 17:28:59.065715 WARNING replay_lights: ------------------------------------------------------------
> 2021-03-12 18:28:59.158521 WARNING replay_lights: ------------------------------------------------------------
> 2021-03-12 18:28:59.158716 WARNING replay_lights: Unexpected error in worker for App replay_lights:
> 2021-03-12 18:28:59.158937 WARNING replay_lights: Worker Ags: {'id': '3015ba52469846a3b0db4033592a8e2a', 'name': 'replay_lights', 'objectid': '273e7dd8ae054f7e93db53c25337a483', 'type': 'scheduler', 'function': <bound method ReplayLights.scheduleNextEventBatch of <replay_lights.ReplayLights object at 0x7fdb4117a8e0>>, 'pin_app': True, 'pin_thread': 61, 'kwargs': {'interval': 3600, '__thread_id': 'thread-61'}}
> 2021-03-12 18:28:59.159074 WARNING replay_lights: ------------------------------------------------------------
> 2021-03-12 18:28:59.160612 WARNING replay_lights: Traceback (most recent call last):
>   File "/usr/lib/python3.8/site-packages/pymysql/connections.py", line 613, in connect
>     sock = socket.create_connection(
>   File "/usr/lib/python3.8/socket.py", line 808, in create_connection
>     raise err
>   File "/usr/lib/python3.8/socket.py", line 796, in create_connection
>     sock.connect(sa)
> ConnectionRefusedError: [Errno 111] Connection refused
> 
> During handling of the above exception, another exception occurred:
> 
> Traceback (most recent call last):
>   File "/usr/lib/python3.8/site-packages/appdaemon/threading.py", line 887, in worker
>     funcref(self.AD.sched.sanitize_timer_kwargs(app, args["kwargs"]))
>   File "/config/appdaemon/apps/house_mode/replay_lights.py", line 99, in scheduleNextEventBatch
>     conn = pymysql.connect(host=self.databaseHost, user=self.databaseUser, password=self.databasePassword, db=self.databaseSchema, charset='utf8')
>   File "/usr/lib/python3.8/site-packages/pymysql/connections.py", line 353, in __init__
>     self.connect()
>   File "/usr/lib/python3.8/site-packages/pymysql/connections.py", line 664, in connect
>     raise exc
> pymysql.err.OperationalError: (2003, "Can't connect to MySQL server on '172.30.33.7' ([Errno 111] Connection refused)")

Hi Grant, from a quick look at your yaml configuration I take it you have set hassDir to your HA db_url. hassDir actually sets the sqlite3 location and is unused and does nothing when using MariaDB. I does give me an idea though and that is your db_url does not exactly match your databaseXxx settings.

db_url: mysql://root:password@localhost/homeassistant?charset=utf8

should match

  databaseHost: "localhost"
  databaseUser: "root"
  databasePassword: "password"
  databaseSchema: "homeassistant"

another thing I see is that you use charset utf8mb4 and the connection is unfortunately hard coded to utf8 right now. I don’t think it matters but you can try to change it in replay_lights.py, line 99.
/Martin

1 Like

This looks great. Thanks

Hi Martin,

Thanks for the quick reply - tried a few things you suggested with no luck. Hass dir back to /config, changed line 99, the db url matched the yaml.
Changed Database Host to “localhost” and then the database cannot be found.

2021-03-13 08:04:34.111245 WARNING replay_lights: ------------------------------------------------------------
2021-03-13 08:12:21.064842 WARNING replay_lights: ------------------------------------------------------------
2021-03-13 08:12:21.064986 WARNING replay_lights: Unexpected error in worker for App replay_lights:
2021-03-13 08:12:21.065130 WARNING replay_lights: Worker Ags: {'id': '558ee778e99b4568a440d7845313fe9d', 'name': 'replay_lights', 'objectid': '8556cd0f40d04c058967db67b3da3ce4', 'type': 'scheduler', 'function': <bound method ReplayLights.scheduleNextEventBatch of <replay_lights.ReplayLights object at 0x7f7524a1d0a0>>, 'pin_app': True, 'pin_thread': 61, 'kwargs': {'interval': 3600, '__thread_id': 'thread-61'}}
2021-03-13 08:12:21.065259 WARNING replay_lights: ------------------------------------------------------------
2021-03-13 08:12:21.065518 WARNING replay_lights: Traceback (most recent call last):
  File "/usr/lib/python3.8/site-packages/pymysql/connections.py", line 613, in connect
    sock = socket.create_connection(
  File "/usr/lib/python3.8/socket.py", line 808, in create_connection
    raise err
  File "/usr/lib/python3.8/socket.py", line 796, in create_connection
    sock.connect(sa)
OSError: [Errno 99] Address not available

During handling of the above exception, another exception occurred:

Traceback (most recent call last):
  File "/usr/lib/python3.8/site-packages/appdaemon/threading.py", line 887, in worker
    funcref(self.AD.sched.sanitize_timer_kwargs(app, args["kwargs"]))
  File "/config/appdaemon/apps/house_mode/replay_lights.py", line 99, in scheduleNextEventBatch
    conn = pymysql.connect(host=self.databaseHost, user=self.databaseUser, password=self.databasePassword, db=self.databaseSchema, charset='utf8')
  File "/usr/lib/python3.8/site-packages/pymysql/connections.py", line 353, in __init__
    self.connect()
  File "/usr/lib/python3.8/site-packages/pymysql/connections.py", line 664, in connect
    raise exc
pymysql.err.OperationalError: (2003, "Can't connect to MySQL server on 'localhost' ([Errno 99] Address not available)")

Sorry to hear that. Unfortunately I still use sqlite myself and another user added the MariaDB connection to my code so I can not test this myself. It looks like you have separate hosts for HA and MariaDB and your error messages suggests that MariaDB is not allowing connection from remote hosts but that would mean that HA should also be unable to connect. A quick google found this for a similar error message:


if you have Linux on your host.
/M

All good and thanks for your help, switched back to Occusim for now - will look at it another time.

Cheers