Skip to content

Commit

Permalink
Save tracker state (#50)
Browse files Browse the repository at this point in the history
* Save device tracker state across restarts.

* Save device tracker state across restarts.

* Save device tracker state across restarts.
  • Loading branch information
twrecked authored Jan 24, 2023
1 parent 08f6c4c commit 4805502
Show file tree
Hide file tree
Showing 6 changed files with 121 additions and 16 deletions.
38 changes: 31 additions & 7 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,8 +7,9 @@ Virtual components for testing Home Assistant systems.
### **Breaking Changes**

I've added persistent support to `binary_sensor`, `fan`, `light`, `lock`,
`sensor` and `switch`. The persistent saving of state is turned *on* by default.
If you do not want this set `persistent: False` in the entity configuration.
`sensor`, `switch` and `device_tracker`. The persistent saving of state is
turned *on* by default. If you do not want this set `persistent: False` in the
entity configuration.


## Table Of Contents
Expand Down Expand Up @@ -194,9 +195,9 @@ lock:
```

- Persistent Configuration
- `initial_availibilty`: optional, default `True`; is device available at start up
- `initial_value`: optional, default `locked`; any other value will result in the lock
being unlocked at start up
- `initial_availibilty`: optional, default `True`; is device available at start up
- `initial_value`: optional, default `locked`; any other value will result in the lock
being unlocked at start up
- Per Run Configuration
- `name`: _required_; device name
- `locking_time`: optional, default `0` seconds; any positive value will result in a
Expand Down Expand Up @@ -231,6 +232,31 @@ Only `name` is required. You only need one of `speed` or `speed_count`.

To add a virtual device tracker use the following:

```yaml
device_tracker:
- platform: virtual
devices:
- name: virtual_user1
peristent: True
location: home
- name: virtual_user2
peristent: False
location: not_home
```

Only `name` is required.
- `persistent`: default `True`; if `True` then entity location is remembered
across restarts otherwise entity always starts at `location`
- `location`: default `home`; this sets the device location when it is created
or if the device is not `persistent`

Use the `device_tracker.see` service to change device locations.


#### Old Style Configuration
The old style configuration will still work. They will be moved to home on
initial creation and their location will survive restarts.

```yaml
device_tracker:
- platform: virtual
Expand All @@ -239,5 +265,3 @@ device_tracker:
- virtual_user2
```

They will be moved to home on reboot. Use the `device_tracker.see` service to
change device locations.
1 change: 1 addition & 0 deletions changelog
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
0.8.0a3: save device tracker location
0.8.0a2: added locking/unlocking state to locks
0.8.0a1: Added state restore to all but device tracker.
[thanks to SergeyPomelov for the push on this]
Expand Down
2 changes: 1 addition & 1 deletion custom_components/virtual/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@
COMPONENT_SERVICES
)

__version__ = '0.8.0a2'
__version__ = '0.8.0a3'

_LOGGER = logging.getLogger(__name__)

Expand Down
89 changes: 84 additions & 5 deletions custom_components/virtual/device_tracker.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,22 +4,101 @@
"""

import logging
import json

from homeassistant.const import CONF_DEVICES, STATE_HOME
from . import COMPONENT_DOMAIN
from homeassistant.components.device_tracker import DOMAIN
from homeassistant.helpers.event import async_track_state_change_event
from .const import (
COMPONENT_DOMAIN,
CONF_NAME,
CONF_PERSISTENT,
DEFAULT_PERSISTENT,
)

_LOGGER = logging.getLogger(__name__)

CONF_LOCATION = 'location'
DEFAULT_LOCATION = 'home'

DEPENDENCIES = [COMPONENT_DOMAIN]
STATE_FILE = "/config/.storage/virtual.restore_state"

tracker_states = {}


def _write_state():
global tracker_states
try:
with open(STATE_FILE, 'w') as f:
json.dump(tracker_states, f)
except:
pass


def _state_changed(event):
entity_id = event.data.get('entity_id', None)
new_state = event.data.get('new_state', None)
if entity_id is None or new_state is None:
_LOGGER.info(f'state changed error')
return

# update database
_LOGGER.info(f"moving {entity_id} to {new_state.state}")
global tracker_states
tracker_states[entity_id] = new_state.state
_write_state()


def _shutting_down(event):
_LOGGER.info(f'shutting down {event}')
_write_state()


async def async_setup_scanner(hass, config, async_see, _discovery_info=None):
"""Set up the virtual tracker."""

# Move all configured devices home
for dev_id in config[CONF_DEVICES]:
_LOGGER.info("moving {} home".format(dev_id))
see_args = {"dev_id": dev_id, "source_type": COMPONENT_DOMAIN, "location_name": STATE_HOME}
# Read in the last known states.
old_tracker_states = {}
try:
with open(STATE_FILE, 'r') as f:
old_tracker_states = json.load(f)
except:
pass

new_tracker_states = {}
for device in config[CONF_DEVICES]:
if not isinstance(device, dict):
device = {
CONF_NAME: device,
}

name = device.get(CONF_NAME, 'unknown')
location = device.get(CONF_LOCATION, DEFAULT_LOCATION)
peristent = device.get(CONF_PERSISTENT, DEFAULT_PERSISTENT)
entity_id = f"{DOMAIN}.{name}"

if peristent:
location = old_tracker_states.get(entity_id, location)
new_tracker_states[entity_id] = location
_LOGGER.info(f"setting persistent {entity_id} to {location}")
else:
_LOGGER.info(f"setting ephemeral {entity_id} to {location}")

see_args = {
"dev_id": name,
"source_type": COMPONENT_DOMAIN,
"location_name": location,
}
hass.async_create_task(async_see(**see_args))

# Start listening if there are persistent entities.
global tracker_states
tracker_states = new_tracker_states
if tracker_states:
async_track_state_change_event(hass, tracker_states.keys(), _state_changed)
hass.bus.async_listen("homeassistant_stop", _shutting_down)
else:
_write_state()

return True
2 changes: 1 addition & 1 deletion custom_components/virtual/manifest.json
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,6 @@
"codeowners": [
"@twrecked"
],
"version": "0.8.0a2",
"version": "0.8.0a3",
"iot_class": "local_push"
}
5 changes: 3 additions & 2 deletions info.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,8 +7,9 @@ Virtual components for testing Home Assistant systems.
### **Breaking Changes**

I've added persistent support to `binary_sensor`, `fan`, `light`, `lock`,
`sensor` and `switch`. The persistent saving of state is turned *on* by default.
If you do not want this set `persistent: False` in the entity configuration.
`sensor`, `switch` and `device_tracker`. The persistent saving of state is
turned *on* by default. If you do not want this set `persistent: False` in the
entity configuration.


## Features
Expand Down

0 comments on commit 4805502

Please sign in to comment.