Navigation Menu

Skip to content

Instantly share code, notes, and snippets.

@anaisbetts
Created January 1, 2022 17:28
Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save anaisbetts/50f1985a66426e7d239b88d0344872f2 to your computer and use it in GitHub Desktop.
Save anaisbetts/50f1985a66426e7d239b88d0344872f2 to your computer and use it in GitHub Desktop.
Doorbell Automation
namespace HomeDotAnaisDotDev;
using System;
using System.Linq;
using System.Reactive.Disposables;
using System.Reactive.Linq;
using HomeAssistantGenerated;
using NetDaemon.Common;
using NetDaemon.HassModel.Common;
using ReactiveUI;
using Splat;
[NetDaemonApp]
public class AutomaticBuzzerHandler : ReactiveObject, IDisposable
{
CompositeDisposable disp = new();
public AutomaticBuzzerHandler(IHaContext haContext)
{
void d(IDisposable disposable) { disp.Add(disposable); }
var home = new Entities(haContext);
var notify = new NotifyServices(haContext);
this.Log().Info("Starting up AutomaticBuzzerHandler");
var shouldUnlockDoor = home.BinarySensor.Dingdong.BooleanForEntity()
.Where(x => {
// Only trigger on off => on
if (!x) return false;
// If no one is at home, bail
if (home.AlarmControlPanel.Alarmo.State != "disarmed" &&
home.InputSelect.HomeAwayOverride.State != "Force Home") return false;
// If they jump on the buzzer, bail
if (home.Switch.DoorBuzzerSwitch.State != "off") return false;
// If it's night time, bail
var now = DateTime.Now;
if (now.Hour < 8 || now.Hour > 19) return false;
return true;
});
// Re-poll locations as soon as someone presses a button
d(shouldUnlockDoor.Subscribe(x => {
notify.MobileAppAdelineSPhone("request_location_update");
notify.MobileAppPixel3("request_location_update");
notify.MobileAppSmG981u1("request_location_update");
notify.MobileAppSmG991b("request_location_update");
}));
// Wait a few seconds before unlocking the door
var prng = new Random();
var doorWithDelay = shouldUnlockDoor
.Select(x => Observable.Return(x).Delay(TimeSpan.FromMilliseconds(prng.Next(1000, 2000))))
.Switch();
// Buzz the door
d(doorWithDelay.Subscribe(_ => {
//home.Switch.DoorBuzzerSwitch.TurnOn();
this.Log().Warn("WOULDVE BUZZED DOOR!");
notify.Slack("Experimental: Would've buzzed door!");
}));
// Figure out if anyone has come home recently
var anyoneChangedHomeAway = Observable.Merge(
new[] { home.Person.Ani, home.Person.Adeline, home.Person.Effie, home.Person.Ulrike }.Select(x => x.StateChanges().Select(y => $"{x.EntityId}: {y.New?.State}"))
);
d(anyoneChangedHomeAway.Subscribe(x => {
notify.Slack("Experimental: " + x);
}));
// Whenever anyone comes home, for the next 10 minutes, allow the elevator
// to be called
d(anyoneChangedHomeAway
.Where(x => x == "home")
.Select(_ => {
this.Log().Info("Someone has come home, allowing elevator to be called");
notify.Slack("Experimental: enabling elevator call code");
// Whenever anyone presses the outer door button, for the next 2 minutes,
// any subsequent press will call the elevator
return doorWithDelay
.Decay(TimeSpan.FromSeconds(2 * 60), RxApp.TaskpoolScheduler)
.Delay(TimeSpan.FromSeconds(3), RxApp.TaskpoolScheduler)
.TakeUntil(Observable.Timer(TimeSpan.FromMinutes(10), RxApp.TaskpoolScheduler));
})
.Switch()
.Repeat()
.Subscribe(_ => {
//home.Switch.CallElevatorSwitch.TurnOn();
this.Log().Warn("WOULDVE CALLED ELEVATOR");
notify.Slack("Experimental: Would've called elevator!");
}));
}
public void Dispose()
{
disp.Dispose();
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment