schollz / find-lf

Track the location of every Wi-Fi device (:iphone:) in your house using Raspberry Pis and FIND
https://www.internalpositioning.com/plugins/#using-find-without-an-app
GNU Affero General Public License v3.0
994 stars 123 forks source link

Pulling rssi values from ap #32

Open jacobalberty opened 6 years ago

jacobalberty commented 6 years ago

Looking at PR #28 I could easily get that data out of my unifi setup, and even pull from more than just one ap. But of course each client is only going to be seen by one ap, so would that data have any actual value?

If I'm understanding the code correctly it looks like i just need to submit some json like the following

{  
   "node":"ap identifier",
   "signals":[  
      {  
         "mac":"client mac",
         "rssi":"##"
      }
   ],
   "timestamp":"Date.now()"
}

I've already banged out a quick piece of code to extract the data but I don't have a working find cluster yet so I didn't bother writing anything to submit the data yet and wanted to know about the viability of this before proceeding.

jacobalberty commented 6 years ago

Just to keep it from being lost to the ages in case i disappear and someone else wants to pick this up here's the script so far.

const request = require("request").defaults({jar: true});;

var username="admin"
var password="changeme"
var baseurl="https://unifi:8443"
var site = 'default';

var baseOptions = {
    rejectUnauthorized: false
}
var loginOptions = {
    uri: `${baseurl}/api/login`,
    method: "POST",
    json: {
        'username': username,
        'password': password
    }
}
var statOptions = {
    uri: `${baseurl}/api/s/${site}/stat/sta`
}

request(Object.assign({}, baseOptions, loginOptions), function(error, response, body) {
    request(Object.assign({}, baseOptions, statOptions), function(error, response, body) {
        var data = JSON.parse(body).data;
        var payloads = { };
        data.forEach(function(client) {
            if (!client.is_wired) {
                if (payloads[client.ap_mac] == undefined) {
                    payloads[client.ap_mac] = {
                        node: client.ap_mac,
                        signals: [ ],
                        timestamp: Date.now()
                    }
                }
                payloads[client.ap_mac].signals.push(
                    {
                        mac: client.mac,
                        rssi: client.rssi
                    }
                );
            }
        });
        Object.keys(payloads).forEach(function(node) {
            // TODO: Submit each payloads[node] to the find-lf server
            console.log(payloads[node]);
        });
    });
});

edit: changed the code to support invalid certificates and moved sitename into a variable

jacobalberty commented 6 years ago

Alright, got it working, if anyone wants to experiment I made a project for it https://github.com/jacobalberty/find-lf-unifi-source It seems to work pretty decently so far. Admittedly it only gets one source for each client at a time though, I'll add a few rooms and see how accurate it is. But for instant deployment with an existing unifi install its not so bad.

roch23 commented 6 years ago

Good stuff! Much cleaner than the bash script in my PR you mentioned. Curious on how your experience has been from the FIND perspective. I only was using the Bayesian method, but ran into classification problems when mixing the "monitor mode" input values with the "access point" values due to values only coming from 1 AP at a time. But for a home setup, values from the AP are both highly accurate and a free extra node. I didn't end up exploring much further (also had issues with the pi's reporting sporadic data depending on the channel, especially with 5ghz).