UNPKG

homebridge-am43-blinds-bluez

Version:

A homebridge plugin to control AM43 based shade motors in HomeKit. These include the A OK and Zemismart bluetooth based motors. This plugin requires a Homebridge host that supports Bluetooth 4.0

93 lines (92 loc) 4.24 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.ble = void 0; const node_ble_1 = require("node-ble"); const values_1 = require("./values"); class BLE { constructor() { const { bluetooth, destroy } = (0, node_ble_1.createBluetooth)(); this.bluetooth = bluetooth; this.destroy = destroy; this.adapter = this.bluetooth.defaultAdapter(); this.uuidToDeviceAndGatt = {}; this.callbackToCharacteristic = new WeakMap(); } async discover(wait = 8) { const adapter = await this.adapter; // 0000fe50-0000-1000-8000-00805f9b34fb if (!(await adapter.isDiscovering())) await adapter.startDiscovery(["fe50"]); await new Promise((res, rej) => setTimeout(res, wait * 1000)); if (await adapter.isDiscovering()) await adapter.stopDiscovery(); const devices = (await adapter.devices()) || []; return devices; } async connectToDevice(uuid) { const adapter = await this.adapter; const deviceAndGatt = this.uuidToDeviceAndGatt[uuid]; if (deviceAndGatt && (await deviceAndGatt.device.isConnected())) return deviceAndGatt; const device = await adapter.waitDevice(uuid.toUpperCase()); if (!device) throw Error(`Failed to connect to device ${uuid}`); await device.connect(); const gattServer = await device.gatt(); this.uuidToDeviceAndGatt[uuid] = { device, gattServer }; return { device, gattServer }; } async getServiceAndCharacteristicUUIDs(uuid) { const { gattServer } = await this.connectToDevice(uuid); const services = await gattServer.services(); const longServiceUUID = services.find((s) => s.startsWith(`0000${values_1.DeviceValues.AM43_SERVICE_ID}`)); if (!longServiceUUID) throw new Error(`Failed to get service UUID from ${uuid}`); const service = await gattServer.getPrimaryService(longServiceUUID); const characteristics = await service.characteristics(); const longCharacteristicUUID = characteristics.find((s) => s.startsWith(`0000${values_1.DeviceValues.AM43_CHARACTERISTIC_ID}`)); if (!longCharacteristicUUID) throw new Error(`Failed to find control characteristic on ${uuid}`); return { serviceUUID: longServiceUUID, characteristicUUID: longCharacteristicUUID, }; } async disconnectDevice(uuid) { const { device } = await this.connectToDevice(uuid); await device.disconnect(); } async writeValue(uuid, primaryServiceUUID, characteristicUUID, value) { const { gattServer } = await this.connectToDevice(uuid); const service = await gattServer.getPrimaryService(primaryServiceUUID); const characteristic = await service.getCharacteristic(characteristicUUID); await characteristic.writeValue(value); const buffer = await characteristic.readValue(); } async readValue(uuid, primaryServiceUUID, characteristicUUID) { const { gattServer } = await this.connectToDevice(uuid); const service = await gattServer.getPrimaryService(primaryServiceUUID); const characteristic = await service.getCharacteristic(characteristicUUID); const buffer = await characteristic.readValue(); return buffer; } async subscribe(uuid, primaryServiceUUID, characteristicUUID, callback) { const { gattServer } = await this.connectToDevice(uuid); const service = await gattServer.getPrimaryService(primaryServiceUUID); const characteristic = await service.getCharacteristic(characteristicUUID); await characteristic.startNotifications(); characteristic.on("valuechanged", callback); this.callbackToCharacteristic.set(callback, characteristic); } async unsubscribe(callback) { if (this.callbackToCharacteristic.has(callback)) { const characteristic = this.callbackToCharacteristic.get(callback); characteristic?.stopNotifications(); } } destroyBluetooth() { this.destroy(); } } const ble = new BLE(); exports.ble = ble;