Although I recently started working with HA + AppDeamon, I would like to share some small apps that I have so far, and maybe get some feedback (I’m a novice python developer).
App #1: Doorbell notification
Send me a notification when someone presses the doorbell, but don’t notify me after every press. Each notification must have an interval of at least 30 seconds.
import appdaemon.plugins.hass.hassapi as hass
from datetime import datetime, timedelta
class DoorBellNotification(hass.Hass):
def initialize(self):
self.log('initializing')
# initialize last_ring variable to avoid extra `If` condition
self.last_ring = datetime.now() - timedelta(seconds= 35)
self.listen_state(self.on_doorbell_press, self.args["sensor"], new="on")
def on_doorbell_press(self, entity, attribute, old, new, kwargs):
if self.last_ring < datetime.now() - timedelta(seconds= 30):
self.last_ring = datetime.now()
self.log('sending notification')
Happy coding!
Humberto
Note:
This solution is not final or complete but maybe ca helpnew members starting with HA+AppDaemon. Suggestions or recommendations to improve the implementation are welcome! (|'m still learning )
Edit #1: Adopt a more pythonic naming convention. Thanks @SupahNoob Edit #2 Avoid hardcode entities names in the automation code. Thanks @swiftlyfalling@Burningstone
This is a great start Humberto! What should happen if the doorbell was pressed twice within 30s?
I would write your condition a little bit differently, but your way absolutely works. My take on it would be to care for any failures of the event coming in - this way you can handle it and let everything else act normally. Additionally, I’ve initialized the variable self.last_ring as None when we’ve never seen it pressed. It’s a totally optional, pedantic way of writing the logic, but it’s arguably a bit more pythonic - as is naming the variable with an underscore, and the renaming of the callback from “state changed” to “doorbell pressed”.
...
def initialize(self):
self.log('initializing')
self.last_ring = None
self.listen_state(self.state_change, "sensor.doorbell", new="PRESSED")
self.log('listening doorbell PRESSED state change')
def on_doorbell_press(self, entity, attribute, old, new, kwargs):
now = datetime.now()
if self.last_ring is not None:
if self.last_ring > now - timedelta(seconds=30):
self.log('what should happen here?')
return
self.last_ring = now
self.log('sending notification')
Again, all of these are totally minor, and you’ve done well to express your idea! Keep it up. Things to think about in the future … a totally different action could be taken if the doorbell was rang twice (or N times) within a short duration. This could give you a “panic mode” or something that’s discreet, but still expressive.
HA should send me only one notification. Just imagine the case that I am on way to the door, I don’t want to receive multiple notifications if can reach the door in less than 30 seconds. So, those extra rings should be discarded.
Thanks for all your suggestions to improve the code . Maybe initializing self.last_ring with None indeed is more pythonic, but in this case, I think it’s more clear without an extra layer of IF conditions (at least for me).
Thanks for sharing this! It inspired me to make a script to get a critical alert message via the iOS app when someone presses the doorbell. Yesterday I was in the garden and my phone was on silent and I did not notice the messages that someone pressed the doorbell (although vibration is on).
I used your app and rewrote it so that I get a critical alert (that also makes noise even if the phone is on silent) when I am at home. If I am not at home, I will get a normal message. When I press that message using 3d Touch I get a live stream of the camera at the door
Here is the code if someone is interested.
app.yaml
doorbell:
module: doorbell_notification
class: DoorBellNotification
# values used in doorbell_notification
id: switch.deurbel
g_home: device_tracker.gerard
notifier: notify/mobile_app_iphone_7
title: Deurbel
message: "Er is aangebeld -> klik om de camera te bekijken"
doorbell_notification.py
import appdaemon.plugins.hass.hassapi as hass
from datetime import datetime, timedelta
class DoorBellNotification(hass.Hass):
def initialize(self):
self.last_ring = None
self.listen_event(self.on_doorbell_press, "button_pressed", entity_id=self.args['id'])
def on_doorbell_press(self, entity, data, kwargs):
now = datetime.now()
if self.last_ring is not None:
if self.last_ring > now - timedelta(seconds=10):
self.log('De bel is binnen 10 seconden opnieuw ingedrukt, de laatste wordt genegeerd')
return
self.last_ring = now
is_g_home = self.get_state(self.args['g_home'])
if is_g_home == "home":
self.call_service(self.args['notifier'],
title=self.args['title'],
message=self.args['message'],
data={"push":
{"sound":
{"critical":1, "name":"default", "volume":0.8},
"category": "camera"},
"entity_id":"camera.camera_buiten"
})
else:
self.call_service(self.args['notifier'],
title=self.args['title'],
message=self.args['message'],
data={"push":
{"category": "camera"},
"entity_id":"camera.camera_buiten"
})