Last active
June 30, 2021 21:15
-
-
Save thoukydides/27eb6abd1bb84c78f2f9a4f0d9d111a2 to your computer and use it in GitHub Desktop.
Low-latency button press and motion events for homebridge-skybell
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
# /etc/default/skybell-sniff | |
# Copyright © 2017 Alexander Thoukydides | |
# SkyBell HD doorbell hostname (or IP address) and name | |
SKYBELL_HOST=skybell | |
SKYBELL_NAME='Doorbell' | |
# Configuration for homebridge-skybell webhooks | |
HOMEBRIDGE_SKYBELL_PORT=47569 | |
HOMEBRIDGE_SKYBELL_SECRET='My webhooks secret' | |
# Gateway/router hostname and ssh username | |
ROUTER_HOST=192.168.0.1 | |
ROUTER_USER=root | |
# Command used to sniff the doorbell traffic | |
SKYBELL_CMD_TCPDUMP="ssh ${ROUTER_USER}@${ROUTER_HOST} \"/usr/sbin/tcpdump -lpnttti eth0 host ${SKYBELL_HOST} and port 5683\"" | |
# Command executed when a button press or motion is detected | |
SKYBELL_CMD_MOTION="curl -d '{\"secret\":\"${HOMEBRIDGE_SKYBELL_SECRET}\",\"name\":\"${SKYBELL_NAME}\"}' http://localhost:${HOMEBRIDGE_SKYBELL_PORT}/homebridge-skybell/trigger/motion" |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#!/usr/bin/perl | |
# Copyright © 2017 Alexander Thoukydides | |
use strict; | |
use warnings; | |
use Socket; | |
# Ensure that standard output is not buffered | |
$| = 1, select $_ for select STDOUT; | |
# Process the command line, substituting environment variables | |
die "$0 SKYBELL-HOST TCPDUMP-COMMAND MOTION-COMMAND\n" unless scalar @ARGV == 3; | |
foreach my $arg (@ARGV) | |
{ | |
$arg =~ s/\$\{(\w+)}/$ENV{$1}/ge; | |
} | |
my ($skybell_host, $cmd_tcpdump, $cmd_motion) = @ARGV; | |
# Timeout (in seconds) to recognise a packet sequence | |
my $timeout = 10; | |
# Resolve hostname to a numeric IP address (since that is what tcpdump outputs) | |
my $skybell_ip_packed = gethostbyname($skybell_host) | |
or die "Failed to resolve $skybell_host: $!\n"; | |
my $skybell_ip = inet_ntoa($skybell_ip_packed); | |
# Start monitoring the SkyBell HD CoAP traffic | |
open(my $pipe, '-|', $cmd_tcpdump) | |
or die "Failed to spawn '$cmd_tcpdump': $!\n"; | |
# Monitor the SkyBell traffic | |
print "Monitoring SkyBell HD $skybell_host ($skybell_ip)\n"; | |
my $state = 'idle'; | |
my $time = 0; | |
while (<$pipe>) | |
{ | |
# Parse the tcpdump output | |
if (!/(\d+):(\d+):(\d+.\d+) IP (\d+(?:\.\d+){3})\.\d+ > [\.\d]+: UDP, length (\d+)\s*$/) | |
{ | |
print "Unexpected tcpdump format: $_"; | |
next; | |
} | |
my $time_delta = (($1 *60) + $2) * 60 + $3; | |
my $from_skybell = $4 eq $skybell_ip; | |
my $length = $5 + 0; | |
#printf "%10.6f seconds %4d bytes %4s %s\n", | |
# $time_delta, $length, ($from_skybell ? 'from' : 'to'), $skybell_host; | |
# Check for a timeout from the start of the sequence | |
if ($state ne 'idle' and $timeout < ($time += $time_delta)) | |
{ | |
print "(Returning to idle)\n"; | |
$state = 'idle'; | |
$time = 0; | |
} | |
# Process the sniffed packet | |
if ($state eq 'idle') | |
{ | |
if ($from_skybell and $length == 465) | |
{ | |
print "(Possible motion detected)\n"; | |
$state = 'armed'; | |
} | |
elsif (not $from_skybell and 800 < $length) | |
{ | |
print "On-demand requested\n"; | |
$state = 'on-demand'; | |
} | |
} | |
elsif ($state eq 'armed') | |
{ | |
if(not $from_skybell and $length == 49) | |
{ | |
print "Motion detected\n"; | |
$state = 'motion'; | |
system($cmd_motion) == 0 | |
or warn "Failed to execute command: $?\n"; | |
} | |
} | |
} | |
# Should never reach this point | |
die "tcpdump process died unexpectedly\n"; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
# /etc/systemd/system/skybell-sniff.service | |
# Copyright © 2017 Alexander Thoukydides | |
[Unit] | |
Description=SkyBell HD event detection | |
After=network-online.target | |
[Service] | |
Type=simple | |
User=root | |
EnvironmentFile=/etc/default/skybell-sniff | |
ExecStart=/usr/local/bin/skybell-sniff.pl ${SKYBELL_HOST} ${SKYBELL_CMD_TCPDUMP} ${SKYBELL_CMD_MOTION} | |
StandardOutput=journal | |
Restart=on-failure | |
RestartSec=10 | |
KillMode=process | |
[Install] | |
WantedBy=multi-user.target |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Hi, it seems that there's a new issue with Skybell binary_sensors. As some of you here really know what you're talking about, please take a look here:
home-assistant/core#11975
Thank you!