Skip to content

Instantly share code, notes, and snippets.

@diginfo
Last active November 29, 2019 00:33
Show Gist options
  • Save diginfo/b95f809bb308a5d350e1c1b13cd28385 to your computer and use it in GitHub Desktop.
Save diginfo/b95f809bb308a5d350e1c1b13cd28385 to your computer and use it in GitHub Desktop.
const cl = console.log;
const noble = require('@abandonware/noble');
function buf2arr(bufdata){
var buffer = Buffer.from(bufdata)
return Array.prototype.slice.call(buffer, 0)
}
// use manufacturer data, no connect.
function readMfgData(peripheral) {
/*
tempdata: [0,26,6,0,71,3]
mfgdata: [
{0,26,6,0,71,3},
{23},
{205,215,81,21,15,126}
]
*/
const result = {
counter : new Date().getTime(),
id : peripheral.id,
mac : peripheral.address,
raw : peripheral.advertisement.manufacturerData,
mfgdata : buf2arr(peripheral.advertisement.manufacturerData),
};
result.tmphum = result.mfgdata.slice(0,6);
result.event = {
data: {
batt : result.mfgdata[6],
rssi : peripheral.rssi,
tmp : result.tmphum[1]+result.tmphum[2]/10,
hum : result.tmphum[4]+result.tmphum[5]/10,
stamp : new Date().getTime()
}
}
return result;
}
//var gwmod = ''; // change later for running as a script.
var gwmod = '/home/pi/mozilla-iot/gateway/node_modules/';
const {
Adapter,
Device,
Property
} = require(`${gwmod}gateway-addon`);
class TemperatureHumiditySensor extends Device {
constructor(adapter, manifest, id) {
//super(adapter, `${manifest.display_name}-${id}`);
super(adapter,id);
this['@context'] = 'https://iot.mozilla.org/schemas/';
this['@type'] = ['TemperatureSensor'];
this.name = manifest.display_name;
//this.name = id;
//this.description = manifest.description;
this.description = 'room1';
this.addProperty({
type: 'number',
'@type': 'TemperatureProperty',
minimum: -127.99,
maximum: 127.99,
multipleOf: 0.1,
unit: 'degree celsius',
title: 'temperature',
description: 'The ambient temperature',
readOnly: true
});
this.addProperty({
type: 'number',
minimum: 0,
maximum: 100,
multipleOf: 0.1,
unit: '%',
title: 'humidity',
description: 'The relative humidity',
readOnly: true
});
this.addProperty({
type: 'number',
minimum: -100,
maximum: 0,
multipleOf: 0.1,
unit: 'dbi',
title: 'rssi',
description: 'Signal Strength',
readOnly: true
});
this.addProperty({
type: 'number',
minimum: 0,
maximum: 100,
multipleOf: 0.1,
unit: '%',
title: 'batt',
description: 'Battery Level',
readOnly: true
});
}
// function.
addProperty(description) {
const property = new Property(this, description.title, description);
this.properties.set(description.title, property);
}
// this function should get & set data ???
setData(data) {
cl(`${data.id}.setData(${JSON.stringify(data.event.data,null,2)})`);
if(isdev) this.adapter.manager.sendPropertyChangedNotification = function (property){};
/*
{
mac: '',
capability: '',
raw: [ 0, 28, 4, 0, 66, 0 ],
event: {
raw: [ 0, 28, 4, 0, 66, 0 ],
data: {
batt: 41,
rssi: -67,
tmp: 28.4,
hum: 66,
stamp: 1574738827049
}
}
}
*/
const result = data;
//const result = readServiceData(serviceData.data);
if (result.event && result.event.data) {
const data = result.event.data;
if (data.batt) {
const batt = result.event.data.batt;
const property = this.properties.get('batt');
property.setCachedValue(batt);
this.notifyPropertyChanged(property);
}
if (data.rssi) {
const rssi = result.event.data.rssi;
const property = this.properties.get('rssi');
property.setCachedValue(rssi);
this.notifyPropertyChanged(property);
}
if (data.tmp) {
const temperature = result.event.data.tmp;
const property = this.properties.get('temperature');
property.setCachedValue(temperature);
this.notifyPropertyChanged(property);
}
if (data.hum) {
const humidity = result.event.data.hum;
const property = this.properties.get('humidity');
property.setCachedValue(humidity);
this.notifyPropertyChanged(property);
}
}
}
}
class TemperatureHumiditySensorAdapter extends Adapter {
/**
* Example process ro remove a device from the adapter.
* The important part is to call: `this.handleDeviceRemoved(device)`
* @param {String} deviceId ID of the device to remove.
* @return {Promise} which resolves to the device removed.
*/
removeDevice(deviceId) {
cl('@@ removeDevice():',deviceId);
return new Promise((resolve, reject) => {
const device = this.devices[deviceId];
if (device) {
this.handleDeviceRemoved(device);
resolve(device);
} else {
reject(`Device: ${deviceId} not found.`);
}
});
}
/**
* Unpaira the provided the device from the adapter.
* @param {Object} device Device to unpair with
*/
removeThing(device) {
cl('remove Device:', this.name, 'id', this.id,'removeThing(', device.id, ') started');
this.removeDevice(device.id).then(() => {
cl('ExampleAdapter: device:', device.id, 'was unpaired.');
}).catch((err) => {
cl('ExampleAdapter: unpairing', device.id, 'failed');
cl(err);
});
}
constructor(addonManager, manifest) {
super(addonManager, TemperatureHumiditySensorAdapter.name, manifest.name);
addonManager.addAdapter(this);
// manifest.moziot.config.pollInterval is null !
//this.pollInterval = manifest.moziot.config.pollInterval;
this.pollInterval = 15; // seconds
this.knownDevices = {};
const me = this;
// initialise
noble.on('stateChange', (state) => {
const duplicates = true;
console.log('Noble adapter is %s', state);
if (state === 'poweredOn') noble.startScanning(['aa20'],duplicates);
});
// discovered
noble.on('discover', (peripheral) => {
const id = peripheral.id;
let knownDevice = this.knownDevices[id];
// if unknown then add it.
if (!knownDevice) {
//cl(`Detected new Sensor ${id}`);
knownDevice = new TemperatureHumiditySensor(this, manifest, id);
this.handleDeviceAdded(knownDevice);
this.knownDevices[id] = knownDevice;
}
// NO-CONNECT use manufacturer's data (no connect)
var data = readMfgData(peripheral);
var now = new Date().getTime();
// limit update frequency
if(! knownDevice._last || now - knownDevice._last > (this.pollInterval * 1000)){
knownDevice.setData(data);
this.knownDevices[id]._last = now;
}
});
}
}
// Run this as a stand-alone script for development
// node /home/pi/.mozilla-iot/addons/xiaomi-temperature-humidity-sensor-adapter/xiaomi-temperature-humidity-sensor-adapter.js
// sudo systemctl restart bluetooth; sudo systemctl restart mozilla-iot-gateway.service; journalctl -f | grep xiaomi
var isdev = false;
const debug = 1;
if(require.main === module){
isdev = true;
gwmod = '/home/pi/mozilla-iot/gateway/node_modules/';
const manifest = require('/home/pi/.mozilla-iot/addons/xiaomi-temperature-humidity-sensor-adapter/manifest.json');
//if(!manifest.moziot) manifest.moziot = {config:{pollInterval:15}};
process.on('SIGINT', function() {
cl("Quitting Noble.");
noble.stopScanning();
process.exit();
});
const addonManager = {
handleDeviceAdded: function(knownDevice){
cl('handleDeviceAdded()')
},
addAdapter: function(){
cl('addAdapter()')
}
};
//
jinou = new TemperatureHumiditySensorAdapter(addonManager,manifest);
}
module.exports = TemperatureHumiditySensorAdapter;
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment