fibaro-beacon-scanner
Version:
Node.js beacon scanner based on noble that speaks to Fibaro
217 lines (172 loc) • 6.68 kB
JavaScript
/****** Begin MODULES definition ******/
// Logger (Winston)
let winston = require('winston');
const logFormatter = function (options) {
return options.timestamp() + ' [' + options.level.toUpperCase() +
'] ' + (options.message ? options.message : '') +
(options.meta && Object.keys(options.meta).length ?
'\n\t' + JSON.stringify(options.meta) : '');
};
const timestamp = function () {
return new Date().toLocaleString();
};
const consoleLogger = new (winston.Logger)({
transports: [
new (winston.transports.Console)({
timestamp: timestamp,
formatter: logFormatter,
json: false,
})
]
});
const fileLogger = new (winston.Logger)({
transports: [
new (winston.transports.File)({
timestamp: timestamp,
formatter: logFormatter,
filename: 'fibaro-beacon-scanner.log',
maxsize: 15000000,
json: false
})
]
});
const consoleAndFileLogger = new (winston.Logger)({
transports: [
new (winston.transports.Console)({
timestamp: timestamp,
formatter: logFormatter,
json: false,
}),
new (winston.transports.File)({
timestamp: timestamp,
formatter: logFormatter,
filename: 'fibaro-beacon-scanner.log',
maxsize: 15000000,
json: false
})
]
});
// Noble (BLE scanner)
let noble = require('noble');
// Fibaro API
var Fibaro = require('fibaro-api');
/****** End MODULES definition ******/
/****** Begin CLASSES definition ******/
function Pi(name, location) {
this.name = name;
this.location = location;
}
function Beacon(name, owner, address) {
this.name = name;
this.owner = owner;
this.address = address;
this.isInRange = function () {
if (this.rssi < rssiTreshold) {
return false;
} else {
return true;
}
}
}
// Timestamp
Date.getTimestamp = function () {
return Math.floor(Date.now() / 1000)
};
/****** End CLASSES definition ******/
/*****************************************************/
/*************** SET YOUR CONFIGURATION HERE ***************/
/****** Begin CONFIGURATION ******/
// Debug mode
let debugMode = true;
// Fibaro HC2
// let hc2IP = "192.168.1.15"; // Home Center 2 IP address
// let hc2User = "admin"; // Home Center 2 admin username
// let hc2Password = "admin"; // Home Center 2 admin password
// let presenceSceneID = 68; // Presence scene ID
let hc2IP = "10.0.1.5"; // Home Center 2 IP address
let hc2User = "jacgalka@icloud.com"; // Home Center 2 admin username
let hc2Password = "J3bimnuC12a"; // Home Center 2 admin password
let presenceSceneID = 44; // Presence scene ID
// Raspberry Pi
let piName = "Sleeping Floor Pi"; // Name of your Raspberry Pi
let piLocation = "sleepingFloor"; // Location of your Raspberry Pi e.g "Kitchen"
let pi = new Pi(piName, piLocation);
// Beacons
// let blackBeacon = new Beacon("black", "eric", "e690ac024a80"); // Beacon name, beacon owner, beacon address
// let greenBeacon = new Beacon("green", "eveline", "d6feeec61549"); // Beacon name, beacon owner, beacon address
let blackBeacon = new Beacon("black", "eric", "d0b5c2febb68"); // Beacon name, beacon owner, beacon address
let greenBeacon = new Beacon("green", "eveline", "04a31604e7a3"); // Beacon name, beacon owner, beacon address
let beacons = [blackBeacon, greenBeacon];
// BLE scanner setings
let rssiTreshold = -1000; // RSSI treshold - When the RSSI of the found beacon is higher than this value the beacon is considered as not in range.
let exitGracePeriod = 10 * 1000; // In miliseconds - when beacon is not found for this amount of time it it considered out of range
/****** End CONFIGURATION ******/
/*****************************************************/
/****** Begin MAIN CODE block ******/
let fibaro = new Fibaro(hc2IP, hc2User, hc2Password);
fibaro.call('settings/info', function (error, response, body) {
if (error === null) {
consoleLogger.info('Connection to HC2 established on ' + hc2IP);
} else {
consoleLogger.error("Couldn't connect to HC2... Check IP, username or password");
process.exit();
}
});
var inRange = [];
consoleLogger.info("Running BLE scanner...");
noble.on('stateChange', function (state) {
if (state === 'poweredOn') {
noble.startScanning([], true);
} else {
noble.stopScanning();
}
});
noble.on('discover', function(foundBeacon) {
if (foundBeacon.rssi < rssiTreshold) {
// ignore
return;
}
for (let beacon of beacons) {
if (foundBeacon.id == beacon.address) {
consoleLogger.info('Test');
var id = foundBeacon.id;
var entered = !inRange[id];
if (entered) {
consoleLogger.info('Test1');
inRange[id] = {
beacon: beacon
};
if (debugMode) {
consoleLogger.info("Beacon entered! Owner: " + beacon.owner + " (" + beacon.name + "), RSSI: " + foundBeacon.rssi + ", Location: " + pi.location);
}
fileLogger.info("Beacon entered! Owner: " + beacon.owner + " (" + beacon.name + "), RSSI: " + foundBeacon.rssi + ", Location: " + pi.location);
fibaro.api.scenes.start(presenceSceneID, {
args: [
"{'name':'" + beacon.name + "', 'owner':'" + beacon.owner + "', 'rssi':'" + foundBeacon.rssi + "', 'status':'entered', 'location':'" + pi.location + "'}"
]
}, function () {}
);
}
inRange[id].lastSeen = Date.now();
}
}
});
setInterval(function() {
for (var id in inRange) {
if (inRange[id].lastSeen < (Date.now() - exitGracePeriod)) {
var beacon = inRange[id].beacon;
if (debugMode) {
consoleLogger.info("Beacon exited! Owner: " + beacon.owner + " (" + beacon.name + "), Location: " + pi.location);
}
fileLogger.info("Beacon exited! Owner: " + beacon.owner + " (" + beacon.name + "), Location: " + pi.location);
fibaro.api.scenes.start(presenceSceneID, {
args: [
"{'name':'" + beacon.name + "', 'owner':'" + beacon.owner + "', 'status':'exited', 'location':'" + pi.location + "'}"
]
}, function () {}
);
delete inRange[id];
}
}
}, exitGracePeriod / 2);
/****** End MAIN CODE block ******/