-
Notifications
You must be signed in to change notification settings - Fork 3.9k
Add Home Assistant device tracker #5701
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,59 @@ | ||
| # | ||
| # Copyright (c) 2018 Johannes Falke | ||
| # This is free software, licensed under the GNU General Public License v3. | ||
| # | ||
|
|
||
| include $(TOPDIR)/rules.mk | ||
|
|
||
| PKG_NAME:=hass | ||
| PKG_VERSION:=0.1 | ||
| PKG_RELEASE:=1 | ||
| PKG_LICENSE:=GPL-3.0+ | ||
| PKG_MAINTAINER:=Johannes Falke <johannesfalke@gmail.com> | ||
|
|
||
| include $(INCLUDE_DIR)/package.mk | ||
|
|
||
| define Package/hass | ||
| SECTION:=net | ||
| CATEGORY:=Network | ||
| TITLE:=Wireless device tracker for Home Assistant | ||
| DEPENDS:=+hostapd-utils +curl | ||
| PKGARCH:=all | ||
| endef | ||
|
|
||
| define Package/hass/description | ||
| Wireless device tracker for Home Assistant (home-assistant.io). Monitors wifi APs for devices via hooking into hostapd events. The info is then sent to the Home Assistant API via a simple POST. | ||
|
|
||
| endef | ||
|
|
||
| define Package/hass/conffiles | ||
| /etc/config/hass | ||
| endef | ||
|
|
||
| define Build/Prepare | ||
| endef | ||
|
|
||
| define Build/Configure | ||
| endef | ||
|
|
||
| define Build/Compile | ||
| endef | ||
|
|
||
| define Package/hass/install | ||
| $(INSTALL_DIR) $(1)/usr/bin | ||
| $(INSTALL_BIN) ./files/hassd.sh $(1)/usr/bin/ | ||
|
|
||
| $(INSTALL_DIR) $(1)/usr/lib | ||
| $(INSTALL_DIR) $(1)/usr/lib/hass | ||
| $(INSTALL_BIN) ./files/functions.sh $(1)/usr/lib/hass/ | ||
| $(INSTALL_BIN) ./files/push_event.sh $(1)/usr/lib/hass/ | ||
|
|
||
| $(INSTALL_DIR) $(1)/etc/init.d | ||
| $(INSTALL_BIN) ./files/hass.init $(1)/etc/init.d/hass | ||
|
|
||
| $(INSTALL_DIR) $(1)/etc/config | ||
| $(INSTALL_CONF) ./files/hass.conf $(1)/etc/config/hass | ||
|
|
||
| endef | ||
|
|
||
| $(eval $(call BuildPackage,hass)) | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,109 @@ | ||
| function err_msg { | ||
| logger -t $0 -p error $@ | ||
| echo $1 1>&2 | ||
| } | ||
|
|
||
| function register_hook { | ||
| logger -t $0 -p debug "register_hook $@" | ||
| if [ "$#" -ne 1 ]; then | ||
| err_msg "register_hook missing interface" | ||
| exit 1 | ||
| fi | ||
| interface=$1 | ||
|
|
||
| hostapd_cli -i$interface -a/usr/lib/hass/push_event.sh & | ||
| } | ||
|
|
||
| function post { | ||
| logger -t $0 -p debug "post $@" | ||
| if [ "$#" -ne 1 ]; then | ||
| err_msg "POST missing payload" | ||
| exit 1 | ||
| fi | ||
| payload=$1 | ||
|
|
||
| config_get hass_host global host | ||
| config_get hass_pw global pw | ||
|
|
||
| resp=$(curl "$hass_host/api/services/device_tracker/see" -sfSX POST \ | ||
| -H 'Content-Type: application/json' \ | ||
| -H "X-HA-Access: $hass_pw" \ | ||
| --data-binary "$payload" 2>&1) | ||
|
|
||
| if [ $? -eq 0 ]; then | ||
| level=debug | ||
| else | ||
| level=error | ||
| fi | ||
|
|
||
| logger -t $0 -p $level "post response $resp" | ||
| } | ||
|
|
||
| function build_payload { | ||
| logger -t $0 -p debug "build_payload $@" | ||
| if [ "$#" -ne 3 ]; then | ||
| err_msg "Invalid payload parameters" | ||
| logger -t $0 -p warning "push_event not handled" | ||
| exit 1 | ||
| fi | ||
| mac=$1 | ||
| host=$2 | ||
| consider_home=$3 | ||
|
|
||
| echo "{\"mac\":\"$mac\",\"host_name\":\"$host\",\"consider_home\":\"$consider_home\",\"source_type\":\"router\"}" | ||
| } | ||
|
|
||
| function get_ip { | ||
| # get ip for mac | ||
| grep "0x2\s\+$1" /proc/net/arp | cut -f 1 -s -d" " | ||
| } | ||
|
|
||
| function get_host_name { | ||
| # get hostname for mac | ||
| nslookup "$(get_ip $1)" | grep -oP "(?<=name = ).*$" | ||
| } | ||
|
|
||
| function push_event { | ||
| logger -t $0 -p debug "push_event $@" | ||
| if [ "$#" -ne 3 ]; then | ||
| err_msg "Illegal number of push_event parameters" | ||
| exit 1 | ||
| fi | ||
| iface=$1 | ||
| msg=$2 | ||
| mac=$3 | ||
|
|
||
| config_get hass_timeout_conn global timeout_conn | ||
| config_get hass_timeout_disc global timeout_disc | ||
|
|
||
| case $msg in | ||
| "AP-STA-CONNECTED") | ||
| timeout=$hass_timeout_conn | ||
| ;; | ||
| "AP-STA-POLL-OK") | ||
| timeout=$hass_timeout_conn | ||
| ;; | ||
| "AP-STA-DISCONNECTED") | ||
| timeout=$hass_timeout_disc | ||
| ;; | ||
| *) | ||
| logger -t $0 -p warning "push_event not handled" | ||
| return | ||
| ;; | ||
| esac | ||
|
|
||
| post $(build_payload "$mac" "$(get_host_name $mac)" "$timeout") | ||
| } | ||
|
|
||
| function sync_state { | ||
| logger -t $0 -p debug "sync_state $@" | ||
|
|
||
| config_get hass_timeout_conn global timeout_conn | ||
|
|
||
| for interface in `iw dev | grep Interface | cut -f 2 -s -d" "`; do | ||
| maclist=`iw dev $interface station dump | grep Station | cut -f 2 -s -d" "` | ||
| for mac in $maclist; do | ||
| post $(build_payload "$mac" "$(get_host_name $mac)" "$hass_timeout_conn") & | ||
| done | ||
| done | ||
| } |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,5 @@ | ||
| config hass 'global' | ||
| option host 'ip.or.name.example:8123' | ||
| option pw '' | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. if that's password, please just use password, instead of making people guess. |
||
| option timeout_conn '24:00' | ||
| option timeout_disc '00:03' | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,34 @@ | ||
| #!/bin/sh /etc/rc.common | ||
|
|
||
| START=50 | ||
| USE_PROCD=1 | ||
| PROG=/usr/bin/hassd.sh | ||
| PIDFILE=/var/run/hass.pid | ||
|
|
||
| start_service() { | ||
| procd_open_instance hass | ||
| procd_set_param command $PROG | ||
| procd_set_param pidfile $PIDFILE | ||
| procd_close_instance | ||
| } | ||
|
|
||
| all_child_pids() { | ||
| pid=$1 | ||
| echo $pid | ||
|
|
||
| for child_pid in $(pgrep -P $pid); do | ||
| echo "$(all_child_pids $child_pid)" | ||
| done | ||
| } | ||
|
|
||
| stop_service() { | ||
| for pid in $(all_child_pids $(cat $PIDFILE)); do | ||
| kill $pid | ||
| done | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. what did you do that procd isn't handling this for you? consider fixing your scripts that you don't need this sort of procedure to die politely.
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. The way I'm spawning processes, procd does not correctly kill all child processes, that's why I wrote this. |
||
| } | ||
|
|
||
| reload_service() | ||
| { | ||
| stop | ||
| start | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 99% sure you don't need this, as you're doing the default implentation. |
||
| } | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,29 @@ | ||
| #!/bin/sh | ||
| # todo: hostapd white (black) list so we don't have to listen to all APs | ||
|
|
||
| source /lib/functions.sh | ||
| config_load hass | ||
|
|
||
| logger -t $0 -p info "Starting up" | ||
|
|
||
| source /usr/lib/hass/functions.sh | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. you've "" quoted above, but not here. I don't care which you use, but consistency is nice.
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. you're right, just copied the upper part everywhere. |
||
|
|
||
| logger -t $0 -p info "Hooking onto existing interfaces" | ||
| for interface in `iw dev | grep Interface | cut -f 2 -s -d" "` | ||
| do | ||
| register_hook $interface | ||
| done | ||
|
|
||
| sync_state | ||
|
|
||
| # will run in subshell | ||
| ubus listen ubus.object.add | \ | ||
| while read line ; do | ||
| interface=$(echo "$line" | grep -oP '"path":"hostapd\.\K[^"]*(?="\} \}$)') | ||
| if [ $? = 0 ] | ||
| then | ||
| logger -t $0 -p info "$interface is up, setting up hook" | ||
| register_hook $interface | ||
| fi | ||
|
|
||
| done | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,7 @@ | ||
| #!/bin/sh | ||
|
|
||
| source /lib/functions.sh | ||
| config_load hass | ||
|
|
||
| source /usr/lib/hass/functions.sh | ||
| push_event $@ |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
ok, I missed this earlier. If this package is just the wireless device tracker, and not Home Assistant itself, then Shouldn't the package name be something like "hass-device-tracker" or something? not just "hass" itself?