kerberos-io / machinery

(DEPRECATED) An open source image processing framework, which uses your USB-, IP- or RPi-camera to recognize events (e.g. motion).
https://www.kerberos.io
490 stars 103 forks source link

Enable/Disable Monitoring #65

Closed nicolasbisi closed 7 years ago

nicolasbisi commented 7 years ago

Hi. I'm running Kerberos over a Raspbian installation and I'm trying to set up a python script to detect when I'm home (by looking for my cell phone) and then Enable / Disable the monitoring. Basically the same behavior of the On/Off switch on the web page but automated.

1- The script is running on the same device as Kerberos, so I was wondering if there is a command I could use to pause/resume monitoring. I could not find anything on the documentation.

2- What I've tried so far is hijack the PHP (be aware that my PHP/web in general is very poor) and moved the Route::put('condition/enabled', 'Controllers\SettingsController@updateConditionEnabled'); to not require authentication. Using Postman I simulated requests but it didn't work (the state was not changing, but was not returning any error). This is definitely not the best way because it affects security. I also tried to change the condition.xml values and tried to reload it, but didn't work as well.

Any help is appreciated. Cheers.

cedricve commented 7 years ago

Nice feature and use case, I would love to help.

  1. Yes you can do it by using the REST api. You need to send a PUT request to condition/enabled. Make sure you use Basic Authentication in your request (your username and password).
    https://github.com/kerberos-io/web/blob/master/app/api.php#L84

With following JSON content, please note that true or false needs to be a string:

 {
     active: "true"
 }

https://github.com/kerberos-io/web/blob/master/app/controllers/SettingsController.php#L191

  1. The machinery will only reload when the config.xml is updated. This means that if you only update the condition.xml, Kerberos.io will not see this change. However its recommended to work with option 1.

If you need some more help, let me know. Cédric

cedricve commented 7 years ago

Btw @nicolasbisi would this be feasible to integrate in the machinery (with C++)? Don't know if this can be generalised.

nicolasbisi commented 7 years ago

@cedricve Thanks for the quick reply. I'm giving a shot on the authentication with python. I'll let you know the progress as I go on.

I believe this could be added. It's not that complicated I believe. The reason I'm doing in python, its because its faster, and because I'm also using Pushover as a notification system and also uploading the pictures to Dropbox (already had some code written for another project, so I'm just reusing it" Cheers, Nicolas

cedricve commented 7 years ago

Ok great have fun. Let me know if you have time to discuss the use case more in detail.

Thanks for contributing ;) Cédric

nicolasbisi commented 7 years ago

If someone stumble in the same problem, here are a small python script to interact with the API.

import requests
import json
import base64

url = "http://127.0.0.1/api/v1/condition/enabled"
username = "user"
password = "passw"
basicAuth = base64.b64encode('%s:%s' % (username, password))
data = '{"active": "true"}'
headers = {"Authorization": "Basic " + basicAuth, "Content-Type": "application/json"}

#Call REST API
response = requests.put(url, data=data, headers=headers)

print(response.text)

@cedricve Thanks for the help. Unfortunately, I won't have time these next couple days, but after the holidays I'll be keen to discuss more those features. Cheers, Nicolas

cedricve commented 7 years ago

@nicolasbisi thanks 👍 no problem, send me a message once you have time. Enjoy your holidays!

muten84 commented 7 years ago

@nicolasbisi I just notice your needs and i think your use case can be covered using nodered+iftt. Node red should be installed on raspbian and IFTT on your smartphone. I used IFTT app to trigger a web request when i'm exiting from a geolocalized area (my home), then i used nodered to intercept the http request and pipe it to a service start command of a kerberos instance. No need to modify the code simply start the service. I assumed that the service was previously stopped so you wasn't using any kerberosio instance for other purposes such as viewing the live stream with condition disabled.

muten84 commented 7 years ago

If interested this is the JSON flow to import in NodeRed:

[{"id":"514ea1c8.4ff78","type":"http in","z":"bd546469.0853f8","name":"activateKereros","url":"/activateKerberos","method":"get","swaggerDoc":"","x":194,"y":132,"wires":[["4c5f373f.cede28","5c7f90bf.19441","e8988d4.219177","4c27de01.fcaa1"]]},{"id":"4c5f373f.cede28","type":"debug","z":"bd546469.0853f8","name":"","active":true,"console":"false","complete":"false","x":424.5,"y":169,"wires":[]},{"id":"5c7f90bf.19441","type":"exec","z":"bd546469.0853f8","command":"sudo systemctl start kerberosio","addpay":false,"append":"","useSpawn":"","timer":"","name":"startKerberos","x":430,"y":52,"wires":[[],[],[]]},{"id":"4c27de01.fcaa1","type":"http response","z":"bd546469.0853f8","name":"","x":349,"y":247,"wires":[]}]

nicolasbisi commented 7 years ago

Hey, sorry for the late reply, it took me longer to get back than I thought it would. @muten84 The geofence seems like an excellent idea. Have you tried? How reliable is it? My concern is that it takes too long to trigger. Especially the disable (arrived at home) because it needs to be fast enough to disable before I get home and trigger a push message of motion detected.

What I've started to implement is basic ping+arp routine to detect the connected clients. One problem that I already stumbled is that iOs enters in a sleep mode when the device is locked and does not respond to ping. After some testing, I figured out that sending a UDP message to port 9 when iTunes Wifi sync is enabled wakes up the device and then the ping works. My concern here is how the battery will behave. Since I've not finished, I haven't properly tested. Hopefully, by the end of the week, I'll have a better answer. I might try the geofence as well to compare it.

nicolasbisi commented 7 years ago

Hey @muten84 I decided to test your idea, and it appears to be very unreliable on my setup. I set the fences on my phone (iPhone 6s) and the only time it was triggered was in the middle of the night as if I was leaving home. The geo-position inside my home is very accurate so I don't think that's the problem. Although its 1-year-old, I found this thread that people are complaining about the exact same behavior.

muten84 commented 7 years ago

Ho @nicolasbisi i used geofencing on Android devices and it works very well when i need to enable kerberos when exit area is triggered. You are right geofencing to recognize enter area can take some minutes but by using best practices and optmizations it should works as well. For Android development i used this guide https://developer.android.com/training/location/geofencing.html . I don't know if is the same with iOS world but i'm sure that Apple policies are very restrictive and you should use background location to process GPS data...in Android you can do it with a Service to avoid suspend Activity by the OS when the app is not in foreground mode. Hope this helps.

P.S. have you Just tried geofencing from IFTT applet?

nicolasbisi commented 7 years ago

@muten84 It might be some iOS thing then. I used an IFTTT applet, but no luck. Unfortunately, I don't have any Android to play around. I'll just finish my ping+arp detection then. It's more than halfway done. But your idea was excellent and simple. I might return to it in the future.

cedricve commented 7 years ago

@nicolasbisi I can't help with this atm, but if this is IPhone related we need to check if this happens on Android as well @muten84? Do you think your efforts/scripts are reuseable? I think this might be interesting to be added to our documention website, below addons?

nicolasbisi commented 7 years ago

@cedricve There is not much code involved to be honest. If anyone else is willing to try, here is what I did. I set the rules on the IFTTT app for whenever I entered/left my home. Maker would make a simple get request (ip:port/enable or ip:port/disable) to my Raspberry. The Raspberry was running a web server (code below) and it would trigger the changes on Kerberos. I also had to forward the ports on the router. It can be easily tested from the browser (although it doesn't return anything).

from BaseHTTPServer import BaseHTTPRequestHandler, HTTPServer
import urllib2
import json
import requests
import base64

class MyHandler(BaseHTTPRequestHandler):

    def do_GET(self):
        print "Received request"
        url = "http://127.0.0.1/api/v1/condition/enabled"
        username = "username"
        password = "password"
        basicAuth = base64.b64encode('%s:%s' % (username, password))
        data = ""

        if (self.path == "/disable"):
            print "Turning off"
            self.wfile.write("\nDisabled")
            data = '{"active": "false"}'
        elif (self.path == "/enable"):
            print "Turning on"
            self.wfile.write("\nEnabled")
            data = '{"active": "true"}'
        else:
            return

        headers = {"Authorization": "Basic " + basicAuth, "Content-Type": "application/json"}
        #Call REST API
        response = requests.put(url, data=data, headers=headers)
        print(response.text)
        return

HTTP_PORT = 8000
server = HTTPServer(('',HTTP_PORT), MyHandler)
server.serve_forever()
nicolasbisi commented 7 years ago

Just an update on my progress. I did another test with IFTTT and geolocation and multiple triggers. Also, set a reminder on the Reminder App for every time I entered and left my house. Both were unreliable. Sometimes it would work right away. Other times it would take 45 min after the event happened. Sometimes would not trigger at all. I gave up on that.

I also left my ping polling running, waking up the devices with the Wake on Lan for every poll. The iPhone 6S had a way better result than the iPhone 5. The 5 sometimes would not wake up at all for a very long period. The results were very unreliably as well. I gave up on that as well.

My last resort was Bluetooth. By using the command hcitool name [mac address] (I'm using raspberry pi3) I was able to detect right away the iPhone 6S but not the iPhone 5. After I had paired the iPhone 5, I was able to find it. I left it running for a couple of days, polling every 60 seconds and I had a success rate of 100%. I am very impressed by how reliable it is.

muten84 commented 7 years ago

Grest work! Can you provide a list of commands for pairing between iPhone and rPi3?

nicolasbisi commented 7 years ago

@muten84 Not right now. I was in a hurry and did it using the GUI. I'll look into that

nicolasbisi commented 7 years ago

@muten84 I have found a way to do it on the terminal. I'm doing it using the bluetoothctl tool. Here are the steps: $bluetoothctl $power on (not sure the power and agent commands are required. My current configuration is far from default) $agent on (only if you need to find out the phone Bluetooth address $scan off (to stop the scan)

Put the phone Bluetooth on discovery mode

$pair 00:00:00:00:00:00

Accept it on the phone and its done.

$exit (to leave)

If you had previously paired the phone and removed the raspberry from the phone, you will have to remove the device from the raspberry as well before pairing it again. To remove, simply $remove 00:00:00:00:00:00

I found this interface with NodeJS and I'm doing my own on python. If you have interest let me know.

muten84 commented 7 years ago

Thank you, I just have a flow on node-red for enabling and disabling machinery service, that uses geolocation, i will try the bluetooth nodejs wrapper within node-red to try the same flow with bt based proximity. Stay tuned. :)

cedricve commented 7 years ago

hey @muten84 did you had any spare time to test this? Would be great to integrate this on the documentation page as well.

muten84 commented 7 years ago

i wrote some lines of code but i have to test it better, maybe this weekend i can finish the work :)

fdashpop commented 6 years ago

Hi! @nicolasbisi : Can you explain your process using BT. It's not clear for my newbie mind. @muten84 : How do you proceed exactly?

Theses solutions look promising and I'm sure many of us are looking for that.

I would volunteer to document a newb solution for this issue.

Cheers

nicolasbisi commented 6 years ago

@fdashpop Hey, Just so you know, I use a different system now. I use Home Assistant as a centralized hub and that controls everything else. For presence detection, I did quite a few tests and here are some things I found out:

  1. Bluetooth seems to be very reliable to use for presence detection
  2. Wifi is terrible, especially if using ios devices. They have a sleep functionality to preserve battery and make them not respond to pings.
  3. Some wifi routers are sensible to Bluetooth. I have a 3G Airport Express and every time I do a ping with Bluetooth, it makes the network really bad. I heard of a lot of people (different routers) having the same problem. But also heard of a lot of people not having problems (normally newer/more expansive equipment).

With that, I made a simple script that runs on a pi and keeps pinging the known phones over wifi. If it can't find any, it falls back to Bluetooth. But my goal is to find if there is someone in the house, not exactly who is home. You might want to have a look at this thread Same thing but with more frequent polls.

fdashpop commented 6 years ago

Hi @nicolasbisi, Strangely I dicovered and installed hass.io late last night on an other pi. How do you do it to switch on and off your kerberos from it?

I read the last link for using BT as a presence recog and will probably try to fiddle with it but I'm interested in the hass.io and kerberos.io working together.

Cheers

nicolasbisi commented 6 years ago

@fdashpop One way of doing it is using this Hassio will call that script whenever you want to enable/disable it. Or convert that to a shell command and use this from hassio

fdashpop commented 6 years ago

@nicolasbisi Thank you! I'm reading the doc now but, really, thanks, I'm super grateful

fdashpop commented 6 years ago

Hi, It seems that converting to a shell command is the way to go as import requests can't be used inside hassio python_script function.

nicolasbisi commented 6 years ago

@fdashpop Glad it worked. I wasn't sure it was going to work using only python. hassio python is very limited.