├── configuration.yaml ├── config.py ├── app.py └── README.md /configuration.yaml: -------------------------------------------------------------------------------- 1 | sensor: 2 | - platform: rest 3 | name: Jarvis 4 | resource: http://192.168.0.69:5000/api/search/00:A0:C9:14:C8:29 -------------------------------------------------------------------------------- /config.py: -------------------------------------------------------------------------------- 1 | # Please set all your variables here 2 | 3 | ################ Required !!! ################################## 4 | 5 | # mac address of device to track (Required) 6 | bleAddr = "00:A0:C9:14:C8:29" 7 | 8 | # detection threshold to classify device as away (number of times device has to be scanned as away) 9 | threshold = 3 10 | 11 | # number of seconds to sleep between scans in seconds 12 | scan_sleep_time = 5 13 | 14 | ################################################################ 15 | 16 | ################ Optional ###################################### 17 | 18 | ## set to True if you want to enable extra feature 19 | # the ability to use the botton on itag bluetooth tracker 20 | # to control a home assistant endpoint 21 | itag = True 22 | 23 | ### Only need to fill in if itag is set to True 24 | 25 | # the url you want to call if itag button is pressed 26 | url = "https://homeass.duckdns.org/api/services/light/toggle" 27 | 28 | # the entity_id you want to call 29 | entity_id = "light.bedroom" 30 | 31 | # your hass password 32 | hassPasswd = "password" 33 | 34 | 35 | ################################################################ 36 | 37 | 38 | 39 | 40 | 41 | 42 | -------------------------------------------------------------------------------- /app.py: -------------------------------------------------------------------------------- 1 | ################ 2 | # Python3 script for tracking bluetooth devices 3 | # Creates a rest endpoint for home-assistant to check whether you are home or not 4 | # Also contains and add on to toggle your lights with the button on itag if paired (may work with other ble tags with buttons, still to test) 5 | ################ 6 | from flask import Flask 7 | from bluepy.btle import Scanner, DefaultDelegate, Peripheral 8 | import time 9 | import _thread 10 | import requests 11 | import config 12 | 13 | 14 | # flask init 15 | app = Flask(__name__) 16 | 17 | 18 | 19 | 20 | # for scanning device 21 | class ScanDelegate(DefaultDelegate): 22 | def __init__(self): 23 | DefaultDelegate.__init__(self) 24 | 25 | def handleDiscovery(self, dev, isNewDev, isNewData): 26 | return() 27 | 28 | # for handling when itag button is pressed 29 | def handleNotification(slef, cHandle, data): 30 | print(data, cHandle, slef) 31 | try: 32 | requests.post(config.url, json = {"entity_id": config.entity_id}, headers = {"x-ha-access": config.hassPasswd, "Content-Type": "application/json"}) 33 | print("Lights toggled") 34 | except Exception as e: 35 | print(e) 36 | 37 | 38 | # global vars 39 | status_counter = 0 40 | status = "home" 41 | 42 | 43 | # return the status 44 | @app.route('/api/search/', methods=['GET']) 45 | def device_scan(mac_addr): 46 | global status 47 | return status 48 | 49 | 50 | # handle errors 51 | @app.errorhandler(404) 52 | def not_found(error): 53 | return("Not Found ", error) 54 | 55 | 56 | # This is the code that is used to connect to itag 57 | def tracker_connect(addr): 58 | try: 59 | # try to connect 60 | dev = Peripheral() 61 | dev.connect(addr) 62 | print("coneccted") 63 | 64 | # Once connected enable notification handling and loop through 65 | dev.setDelegate(ScanDelegate()) 66 | while True: 67 | dev.waitForNotifications(10) 68 | 69 | dev.disconnect() 70 | print("Disconnected!") 71 | # if fail, go back to scanning, or if diconnects 72 | except Exception as e: 73 | print(e) 74 | 75 | 76 | 77 | # scan for the device 78 | def device_scanner(treshold, scan_sleep_time): 79 | global status_counter 80 | global status 81 | addr = config.bleAddr 82 | while True: 83 | # run the scanner 84 | scanner = Scanner().withDelegate(ScanDelegate()) 85 | devices = scanner.scan(5.0) 86 | found = False 87 | # if device in the list set status_counter to threshold (since if its home, it cant be false detection) 88 | for dev in devices: 89 | if dev.addr == addr: 90 | status_counter = treshold 91 | found = True 92 | 93 | # else subtract 1 from it, since we dont mind if the away automation takes time, this gives us room for failure to detect devices 94 | if found == False: 95 | status_counter = status_counter - 1 96 | 97 | # now set global vars if home 98 | if status_counter >= treshold: 99 | status_counter = treshold 100 | status = "home" 101 | 102 | # now set global vars if not dectected for -treshold value (away) 103 | if status_counter <= -treshold: 104 | status_counter = -treshold 105 | status = "away" 106 | print("Device Status: ", status, "Current Value:", status_counter) 107 | # if its an itag device and its home, try to connect 108 | if config.itag == True: 109 | # if home, try to connect to device 110 | if (status_counter == treshold) & (status=="home"): 111 | tracker_connect(addr) 112 | 113 | # sleep 114 | time.sleep(scan_sleep_time) 115 | 116 | # run the thread 117 | _thread.start_new_thread(device_scanner, (config.threshold, config.scan_sleep_time)) 118 | 119 | if __name__ == '__main__': 120 | app.run(host='0.0.0.0', debug=False) 121 | 122 | 123 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Home Assistant Custom Bluteooth Tracker 2 | 3 | 4 | ## Introduction 5 | 6 | The following repo is a simple python3 script that works as a bluetooth tracker on home assistant. This was made since I wasn't able to find a reliable platform that was able to get me location tracking and let my home assistant know when i was home or away without any false triggers. This script is optimezed to know exactly when you are home and away, and can be tuned to avoid any false away notifcations. 7 | 8 | What the script does is it initializes a thread that keeps track of your bluetooth device. If there are any false scans that don't discover the device, it will wait for a period of attempts before marking your device as away. You can simply modify the variables in the config files to suit your needs, but the current values should already be good enough. 9 | 10 | The script should work with any bluetooth device. 11 | 12 | In addition to tracking whether the device is available when a bluetooth scan is made from a raspberry pi, this script can also can connect to some bluetooth trackers. Currently I use the itag device which is a cheap bluetooth tracker that can be bought online for next to nothing. An image of the device is attached below. 13 | 14 | ![alt text](https://img.grouponcdn.com/deal/bp7UEqswiaeiVTaBTbhi/n8-1666x1000/v1/c700x420.jpg) 15 | 16 | This itag device is a cheap tracker that you do not need to charge for a few months, and in addition to help with location tracking it comes with a toggle button. The extra feature is the ability to customize what this button does, with any action on your home assistant. 17 | 18 | Currently the script only tracks one particular device, however if the ability to track more devices are needed, feel free to create an ISSUE and I can build it out when I find some time 19 | 20 | 21 | ## What You Need 22 | 23 | 1) You will require a raspberry pi with bluetooth. I currently use the same pi running home assistant in a python virtual environment. 24 | 25 | 2) You will also need to run this as root or modify permissions to be able to use the bluetooth as any user on the pi 26 | 27 | ## I am Running HASSIO 28 | 29 | If you are running hassio, I currently havent figured out how to make this an add-on due to some permission issues with the bluetooth driver in hassio. A current method of still being able to implement this would be installing this on a raspberry pi w , and when you reach step 9, simply change the config of your hassio and point it to your raspberry pi w's ip address 30 | 31 | ## Installation: 32 | 33 | 34 | 1) ``` sudo apt install bluetooth libbluetooth-dev pkg-config libboost-python-dev libboost-thread-dev libglib2.0-dev python-dev ``` 35 | 36 | 2) ``` git clone https://github.com/araa47/hass_bletracker.git ``` 37 | 38 | 3) ``` pip3 install flask bluepy requests ``` 39 | 40 | 4) Identify the mac address of the device you want to track, you can run ```hcitool scan``` 41 | 42 | 5) Now you can modify the config.py file and set the mac address of your device in that file. You can also modify threshold and scan_sleep_time, but this can be tuned later on if you have issues with the current values. If you are using a normal bluetooth device skip to step 7. 43 | 44 | 6) If you are using an itag device you may want to enable itag to True, and also set the require home assistant url, password, and entity_id if you want to toggle your smart devices using the button on the itag. 45 | 46 | 7) Run the program by typing in ``` sudo python3 app.py ``` 47 | 48 | 8) This should start an api on port 5000 of your device. You can simply send requests to the following url to check whether the program is working ```pi_ip:5000/api/search/mac_addr ```, where pi_ip is the ip of your raspberry pi and mac_addr is the mac address of the device in the config file you are tracking. 49 | 50 | 9) Now that the tracker is active, simple add the lines in the ```configuration.yaml``` file attached in this repo. 51 | 52 | 10) Your device should show up on home assistant, enjoy! 53 | 54 | 55 | ## Notes 56 | 57 | If you are using the itag device and enabled pairing, when you walk out of range from the pi with the itag tacker, it will start beeping. This is pretty annoying right now, but seems to be a firmware feature on the itag so I havent been enable to disable this. If you are annoyed by this noise, you could aways open up the device and disconnect the buzzer. 58 | 59 | ## Future Updates 60 | 61 | Currently this script only supports tracking a single device, but it shouldn't be too difficult to add multiple device support. Will be adding this in once I get some more time. 62 | 63 | 64 | 65 | 66 | 67 | 68 | --------------------------------------------------------------------------------