Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Bluetooth device creation #921

Merged
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
29 changes: 2 additions & 27 deletions server/services/bluetooth/lib/commands/bluetooth.connectDevices.js
Original file line number Diff line number Diff line change
Expand Up @@ -11,35 +11,10 @@ const logger = require('../../../../utils/logger');
async function connectDevices() {
logger.debug(`Bluetooth: subscribing to existing devices...`);
const devices = await this.gladys.device.get({
service_id: this.serviceId,
service: 'bluetooth',
});

return Promise.map(
devices,
(device) => {
const [, peripheralUuid] = device.external_id.split(':');

const subscribe = (peripheral) => {
return Promise.map(
device.features,
(feature) => {
const [, , serviceUuid, characteristicUuid] = feature.external_id.split(':');
return this.subscribePeripheral(peripheral, serviceUuid, characteristicUuid, feature);
},
{ concurrency: 1 },
).catch((e) => {
logger.error(e.message);
return Promise.resolve();
});
};

return this.applyOnPeripheral(peripheralUuid, subscribe, true).catch((e) => {
logger.error(e.message);
return Promise.resolve();
});
},
{ concurrency: 1 },
);
return Promise.map(devices, (device) => this.postCreate(device), { concurrency: 1 });
}

module.exports = {
Expand Down
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
const Promise = require('bluebird');

const { discoverServices } = require('./peripheral/bluetooth.discoverServices');
const { discoverCharacteristics } = require('./service/bluetooth.discoverCharacteristics');
const { discoverServices } = require('../utils/peripheral/bluetooth.discoverServices');
const { discoverCharacteristics } = require('../utils/service/bluetooth.discoverCharacteristics');

/**
* @description Connects to peripheral, discovers all needed, to applu action.
Expand Down
46 changes: 46 additions & 0 deletions server/services/bluetooth/lib/commands/bluetooth.poll.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
const Promise = require('bluebird');

const logger = require('../../../../utils/logger');
const { EVENTS } = require('../../../../utils/constants');

const { decodeValue } = require('../device/bluetooth.information');

/**
* @description Poll value of a Bluetooth device
* @param {Object} device - The device to control.
* @returns {Promise} Promise of all read values.
* @example
* await bluetooth.poll({ external_id: 'bluetooth:uuid'});
*/
async function poll(device) {
const [, peripheralUuid] = device.external_id.split(':');

const readFeature = (feature, peripheral) => {
const featureExternalId = feature.external_id;
const [, , serviceUuid, characteristicUuid] = featureExternalId.split(':');

return this.readDevice(peripheral, serviceUuid, characteristicUuid)
.then((value) => {
const state = decodeValue(serviceUuid, characteristicUuid, feature, value);
this.gladys.event.emit(EVENTS.DEVICE.NEW_STATE, {
device_feature_external_id: featureExternalId,
state,
});
return state;
})
.catch((e) => {
logger.warn(e.message);
return Promise.resolve();
});
};

const readFeatures = (peripheral) => {
return Promise.map(device.features, (feature) => readFeature(feature, peripheral), { concurrency: 1 });
};

return this.applyOnPeripheral(peripheralUuid, readFeatures);
}

module.exports = {
poll,
};
47 changes: 47 additions & 0 deletions server/services/bluetooth/lib/commands/bluetooth.postCreate.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
const Promise = require('bluebird');

const logger = require('../../../../utils/logger');
const { EVENTS } = require('../../../../utils/constants');
const { decodeValue } = require('../device/bluetooth.information');

/**
* @description Subscribe to peripheral notification on device creation.
* @param {Object} device - Newly created Gladys device.
* @returns {Promise} All subscription promises.
* @example
* await bluetooth.postCreate(device);
*/
async function postCreate(device) {
const [, peripheralUuid] = device.external_id.split(':');

const subscribe = (peripheral) => {
return Promise.map(
device.features,
(feature) => {
const [, , serviceUuid, characteristicUuid] = feature.external_id.split(':');

const onNotify = (value) => {
this.gladys.event.emit(EVENTS.DEVICE.NEW_STATE, {
device_feature_external_id: feature.external_id,
state: decodeValue(serviceUuid, characteristicUuid, feature, value),
});
};

return this.subscribeDevice(peripheral, serviceUuid, characteristicUuid, onNotify);
},
{ concurrency: 1 },
).catch((e) => {
logger.error(e.message);
return Promise.resolve();
});
};

return this.applyOnPeripheral(peripheralUuid, subscribe, true).catch((e) => {
logger.error(e.message);
return Promise.resolve();
});
}

module.exports = {
postCreate,
};
37 changes: 37 additions & 0 deletions server/services/bluetooth/lib/commands/bluetooth.postDelete.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
const Promise = require('bluebird');

const logger = require('../../../../utils/logger');

/**
* @description Unsubscribe to peripheral notification on device delete.
* @param {Object} device - Newly created Gladys device.
* @returns {Promise} All subscription promises.
* @example
* await bluetooth.postDelete(device);
*/
async function postDelete(device) {
const [, peripheralUuid] = device.external_id.split(':');

const unsubscribe = (peripheral) => {
return Promise.map(
device.features,
(feature) => {
const [, , serviceUuid, characteristicUuid] = feature.external_id.split(':');
return this.unsubscribeDevice(peripheral, serviceUuid, characteristicUuid);
},
{ concurrency: 1 },
).catch((e) => {
logger.error(e.message);
return Promise.resolve();
});
};

return this.applyOnPeripheral(peripheralUuid, unsubscribe, true).catch((e) => {
logger.error(e.message);
return Promise.resolve();
});
}

module.exports = {
postDelete,
};
45 changes: 8 additions & 37 deletions server/services/bluetooth/lib/commands/bluetooth.readDevice.js
Original file line number Diff line number Diff line change
@@ -1,47 +1,18 @@
const Promise = require('bluebird');

const logger = require('../../../../utils/logger');
const { EVENTS } = require('../../../../utils/constants');

const { decodeValue } = require('../device/bluetooth.information');
const { read } = require('../utils/characteristic/bluetooth.read');
const { getCharacteristic } = require('../utils/bluetooth.getCharacteristic');

/**
* @description Poll value of a Bluetooth device
* @param {Object} device - The device to control.
* @description Read value of a Bluetooth device
* @param {string} peripheral - Connected Noble peripheral.
* @param {string} serviceUuid - Service UUID.
* @param {string} characteristicUuid - Characteristic UUID.
* @returns {Promise} Promise of all read values.
* @example
* await bluetooth.readDevice({ external_id: 'bluetooth:uuid'});
*/
async function readDevice(device) {
const [, peripheralUuid] = device.external_id.split(':');

const readFeature = (feature, peripheral) => {
const featureExternalId = feature.external_id;
const [, , serviceUuid, characteristicUuid] = featureExternalId.split(':');

return getCharacteristic(peripheral, serviceUuid, characteristicUuid)
.then((characteristic) => read(characteristic))
.then((value) => {
const state = decodeValue(serviceUuid, characteristicUuid, feature, value);
this.gladys.event.emit(EVENTS.DEVICE.NEW_STATE, {
device_feature_external_id: featureExternalId,
state,
});
return state;
})
.catch((e) => {
logger.warn(e.message);
return Promise.resolve();
});
};

const readFeatures = (peripheral) => {
return Promise.map(device.features, (feature) => readFeature(feature, peripheral), { concurrency: 1 });
};

return this.applyOnPeripheral(peripheralUuid, readFeatures);
async function readDevice(peripheral, serviceUuid, characteristicUuid) {
return this.getCharacteristic(peripheral, serviceUuid, characteristicUuid).then((characteristic) =>
read(characteristic),
);
}

module.exports = {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,6 @@ const { setDeviceParam } = require('../../../../utils/setDeviceParam');
const { INFORMATION_SERVICES } = require('../device/bluetooth.information');
const { PARAMS } = require('../utils/bluetooth.constants');
const { read } = require('../utils/characteristic/bluetooth.read');
const { getCharacteristic } = require('../utils/bluetooth.getCharacteristic');

/**
* @description Look for peripheral details.
Expand All @@ -34,7 +33,7 @@ async function scanDevice(peripheralUuid) {
Promise.map(
Object.keys(INFORMATION_SERVICES[serviceUuid]),
(characteristicUuid) => {
return getCharacteristic(peripheral, serviceUuid, characteristicUuid)
return this.getCharacteristic(peripheral, serviceUuid, characteristicUuid)
.then((characteristic) => {
const actionMapper = INFORMATION_SERVICES[serviceUuid][characteristicUuid];

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
const Promise = require('bluebird');

const { subscribe } = require('../utils/characteristic/bluetooth.subscribe');
const { read } = require('../utils/characteristic/bluetooth.read');

/**
* @description Subscribes to peripheral characteristic.
* @param {Object} peripheral - Connected Noble peripheral.
* @param {string} serviceUuid - Service UUID.
* @param {string} characteristicUuid - Characteristic UUID.
* @param {Object} onNotify - Value callback.
* @returns {Promise<Object>} The write value.
* @example
* await subscribeDevice({ uuid: 'peripheral' }, 'service1', 'char1', () => console.log('done'))
*/
async function subscribeDevice(peripheral, serviceUuid, characteristicUuid, onNotify) {
return this.getCharacteristic(peripheral, serviceUuid, characteristicUuid).then((characteristic) =>
subscribe(characteristic, onNotify).then(() => read(characteristic).then((value) => onNotify(value))),
);
}

module.exports = {
subscribeDevice,
};

This file was deleted.

Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
const Promise = require('bluebird');

const { unsubscribe } = require('../utils/characteristic/bluetooth.unsubscribe');

/**
* @description Unsubscribes to peripheral characteristic.
* @param {Object} peripheral - Connected Noble peripheral.
* @param {string} serviceUuid - Service UUID.
* @param {string} characteristicUuid - Characteristic UUID.
* @returns {Promise<Object>} Unscription status.
* @example
* await subscribeDevice({ uuid: 'peripheral' }, 'service1', 'char1')
*/
async function unsubscribeDevice(peripheral, serviceUuid, characteristicUuid) {
return this.getCharacteristic(peripheral, serviceUuid, characteristicUuid).then((characteristic) =>
unsubscribe(characteristic),
);
}

module.exports = {
unsubscribeDevice,
};
10 changes: 4 additions & 6 deletions server/services/bluetooth/lib/commands/bluetooth.writeDevice.js
Original file line number Diff line number Diff line change
@@ -1,21 +1,19 @@
const Promise = require('bluebird');

const { write } = require('../utils/characteristic/bluetooth.write');
const { getCharacteristic } = require('../utils/bluetooth.getCharacteristic');

/**
* @description Write specific value to requested characteristic.
* @param {string} peripheral - Connected Noble peripheral.
* @param {string} serviceUuid - Service UUID.
* @param {string} characteristicUuid - Characteristic UUID.
* @param {Array | Buffer} value - Value to send to peripheral.
* @param {boolean} withoutResponse - Use "write without response" property (default false).
* @returns {Promise<Object>} The write value.
* @example
* await writeDevice({ uuid: 'peripheral' }, 'service1', 'char1')
*/
async function writeDevice(peripheral, serviceUuid, characteristicUuid, value) {
return getCharacteristic(peripheral, serviceUuid, characteristicUuid).then((characteristic) =>
write(characteristic, value),
async function writeDevice(peripheral, serviceUuid, characteristicUuid, value, withoutResponse = false) {
return this.getCharacteristic(peripheral, serviceUuid, characteristicUuid).then((characteristic) =>
write(characteristic, value, withoutResponse),
);
}

Expand Down
Loading