From 3b0eae7462d23123f980b813395373cd53ab9fbd Mon Sep 17 00:00:00 2001 From: Sebastian Hildebrandt Date: Wed, 31 Dec 2025 12:43:50 +0100 Subject: [PATCH] batteries enimeration issue (windows) wip --- lib/battery.js | 232 +++++++++++++++++++++++++---------------------- lib/bluetooth.js | 127 +++++++++++++++++++------- 2 files changed, 219 insertions(+), 140 deletions(-) diff --git a/lib/battery.js b/lib/battery.js index eced143..17e0127 100644 --- a/lib/battery.js +++ b/lib/battery.js @@ -17,19 +17,20 @@ const exec = require('child_process').exec; const fs = require('fs'); const util = require('./util'); -let _platform = process.platform; +const _platform = process.platform; -const _linux = (_platform === 'linux' || _platform === 'android'); -const _darwin = (_platform === 'darwin'); -const _windows = (_platform === 'win32'); -const _freebsd = (_platform === 'freebsd'); -const _openbsd = (_platform === 'openbsd'); -const _netbsd = (_platform === 'netbsd'); -const _sunos = (_platform === 'sunos'); +const _linux = _platform === 'linux' || _platform === 'android'; +const _darwin = _platform === 'darwin'; +const _windows = _platform === 'win32'; +const _freebsd = _platform === 'freebsd'; +const _openbsd = _platform === 'openbsd'; +const _netbsd = _platform === 'netbsd'; +const _sunos = _platform === 'sunos'; function parseWinBatteryPart(lines, designedCapacity, fullChargeCapacity) { const result = {}; - let status = util.getValue(lines, 'BatteryStatus', ':').trim(); + let status = parseInt(util.getValue(lines, 'BatteryStatus', ':').trim(), 10) || 0; + // let status = util.getValue(lines, 'BatteryStatus', ':').trim(); // 1 = "Discharging" // 2 = "On A/C" // 3 = "Fully Charged" @@ -47,11 +48,11 @@ function parseWinBatteryPart(lines, designedCapacity, fullChargeCapacity) { result.hasBattery = true; result.maxCapacity = fullChargeCapacity || parseInt(util.getValue(lines, 'DesignCapacity', ':') || 0); result.designedCapacity = parseInt(util.getValue(lines, 'DesignCapacity', ':') || designedCapacity); - result.voltage = parseInt(util.getValue(lines, 'DesignVoltage', ':') || 0) / 1000.0; + result.voltage = (parseInt(util.getValue(lines, 'DesignVoltage', ':'), 10) || 0) / 1000; result.capacityUnit = 'mWh'; - result.percent = parseInt(util.getValue(lines, 'EstimatedChargeRemaining', ':') || 0); - result.currentCapacity = parseInt(result.maxCapacity * result.percent / 100); - result.isCharging = (statusValue >= 6 && statusValue <= 9) || statusValue === 11 || ((statusValue !== 3) && (statusValue !== 1) && result.percent < 100); + result.percent = parseInt(util.getValue(lines, 'EstimatedChargeRemaining', ':'), 10) || 0; + result.currentCapacity = parseInt((result.maxCapacity * result.percent) / 100); + result.isCharging = (statusValue >= 6 && statusValue <= 9) || statusValue === 11 || (statusValue !== 3 && statusValue !== 1 && result.percent < 100); result.acConnected = result.isCharging || statusValue === 2; result.model = util.getValue(lines, 'DeviceID', ':'); } else { @@ -61,9 +62,8 @@ function parseWinBatteryPart(lines, designedCapacity, fullChargeCapacity) { return result; } -module.exports = function (callback) { - - return new Promise((resolve) => { +module.exports = (callback) => + new Promise((resolve) => { process.nextTick(() => { let result = { hasBattery: false, @@ -105,22 +105,24 @@ module.exports = function (callback) { } if (battery_path) { - fs.readFile(battery_path + 'uevent', function (error, stdout) { + fs.readFile(battery_path + 'uevent', (error, stdout) => { if (!error) { let lines = stdout.toString().split('\n'); - result.isCharging = (util.getValue(lines, 'POWER_SUPPLY_STATUS', '=').toLowerCase() === 'charging'); + result.isCharging = util.getValue(lines, 'POWER_SUPPLY_STATUS', '=').toLowerCase() === 'charging'; result.acConnected = acConnected || result.isCharging; result.voltage = parseInt('0' + util.getValue(lines, 'POWER_SUPPLY_VOLTAGE_NOW', '='), 10) / 1000000.0; result.capacityUnit = result.voltage ? 'mWh' : 'mAh'; result.cycleCount = parseInt('0' + util.getValue(lines, 'POWER_SUPPLY_CYCLE_COUNT', '='), 10); - result.maxCapacity = Math.round(parseInt('0' + util.getValue(lines, 'POWER_SUPPLY_CHARGE_FULL', '=', true, true), 10) / 1000.0 * (result.voltage || 1)); + result.maxCapacity = Math.round((parseInt('0' + util.getValue(lines, 'POWER_SUPPLY_CHARGE_FULL', '=', true, true), 10) / 1000.0) * (result.voltage || 1)); const desingedMinVoltage = parseInt('0' + util.getValue(lines, 'POWER_SUPPLY_VOLTAGE_MIN_DESIGN', '='), 10) / 1000000.0; - result.designedCapacity = Math.round(parseInt('0' + util.getValue(lines, 'POWER_SUPPLY_CHARGE_FULL_DESIGN', '=', true, true), 10) / 1000.0 * (desingedMinVoltage || result.voltage || 1)); - result.currentCapacity = Math.round(parseInt('0' + util.getValue(lines, 'POWER_SUPPLY_CHARGE_NOW', '='), 10) / 1000.0 * (result.voltage || 1)); + result.designedCapacity = Math.round( + (parseInt('0' + util.getValue(lines, 'POWER_SUPPLY_CHARGE_FULL_DESIGN', '=', true, true), 10) / 1000.0) * (desingedMinVoltage || result.voltage || 1) + ); + result.currentCapacity = Math.round((parseInt('0' + util.getValue(lines, 'POWER_SUPPLY_CHARGE_NOW', '='), 10) / 1000.0) * (result.voltage || 1)); if (!result.maxCapacity) { result.maxCapacity = parseInt('0' + util.getValue(lines, 'POWER_SUPPLY_ENERGY_FULL', '=', true, true), 10) / 1000.0; - result.designedCapacity = parseInt('0' + util.getValue(lines, 'POWER_SUPPLY_ENERGY_FULL_DESIGN', '=', true, true), 10) / 1000.0 | result.maxCapacity; + result.designedCapacity = (parseInt('0' + util.getValue(lines, 'POWER_SUPPLY_ENERGY_FULL_DESIGN', '=', true, true), 10) / 1000.0) | result.maxCapacity; result.currentCapacity = parseInt('0' + util.getValue(lines, 'POWER_SUPPLY_ENERGY_NOW', '='), 10) / 1000.0; } const percent = util.getValue(lines, 'POWER_SUPPLY_CAPACITY', '='); @@ -133,41 +135,47 @@ module.exports = function (callback) { if (result.maxCapacity && result.currentCapacity) { result.hasBattery = true; if (!percent) { - result.percent = 100.0 * result.currentCapacity / result.maxCapacity; + result.percent = (100.0 * result.currentCapacity) / result.maxCapacity; } } if (result.isCharging) { result.hasBattery = true; } if (energy && power) { - result.timeRemaining = Math.floor(energy / power * 60); + result.timeRemaining = Math.floor((energy / power) * 60); } else if (current && charge) { - result.timeRemaining = Math.floor(charge / current * 60); + result.timeRemaining = Math.floor((charge / current) * 60); } else if (current && result.currentCapacity) { - result.timeRemaining = Math.floor(result.currentCapacity / current * 60); + result.timeRemaining = Math.floor((result.currentCapacity / current) * 60); } result.type = util.getValue(lines, 'POWER_SUPPLY_TECHNOLOGY', '='); result.model = util.getValue(lines, 'POWER_SUPPLY_MODEL_NAME', '='); result.manufacturer = util.getValue(lines, 'POWER_SUPPLY_MANUFACTURER', '='); result.serial = util.getValue(lines, 'POWER_SUPPLY_SERIAL_NUMBER', '='); - if (callback) { callback(result); } + if (callback) { + callback(result); + } resolve(result); } else { - if (callback) { callback(result); } + if (callback) { + callback(result); + } resolve(result); } }); } else { - if (callback) { callback(result); } + if (callback) { + callback(result); + } resolve(result); } } if (_freebsd || _openbsd || _netbsd) { - exec('sysctl -i hw.acpi.battery hw.acpi.acline', function (error, stdout) { + exec('sysctl -i hw.acpi.battery hw.acpi.acline', (error, stdout) => { let lines = stdout.toString().split('\n'); const batteries = parseInt('0' + util.getValue(lines, 'hw.acpi.battery.units'), 10); const percent = parseInt('0' + util.getValue(lines, 'hw.acpi.battery.life'), 10); - result.hasBattery = (batteries > 0); + result.hasBattery = batteries > 0; result.cycleCount = null; result.isCharging = util.getValue(lines, 'hw.acpi.acline') !== '1'; result.acConnected = result.isCharging; @@ -175,55 +183,64 @@ module.exports = function (callback) { result.currentCapacity = null; result.capacityUnit = 'unknown'; result.percent = batteries ? percent : null; - if (callback) { callback(result); } + if (callback) { + callback(result); + } resolve(result); }); } if (_darwin) { - exec('ioreg -n AppleSmartBattery -r | egrep "CycleCount|IsCharging|DesignCapacity|MaxCapacity|CurrentCapacity|DeviceName|BatterySerialNumber|Serial|TimeRemaining|Voltage"; pmset -g batt | grep %', function (error, stdout) { - if (stdout) { - let lines = stdout.toString().replace(/ +/g, '').replace(/"+/g, '').replace(/-/g, '').split('\n'); - result.cycleCount = parseInt('0' + util.getValue(lines, 'cyclecount', '='), 10); - result.voltage = parseInt('0' + util.getValue(lines, 'voltage', '='), 10) / 1000.0; - result.capacityUnit = result.voltage ? 'mWh' : 'mAh'; - result.maxCapacity = Math.round(parseInt('0' + util.getValue(lines, 'applerawmaxcapacity', '='), 10) * (result.voltage || 1)); - result.currentCapacity = Math.round(parseInt('0' + util.getValue(lines, 'applerawcurrentcapacity', '='), 10) * (result.voltage || 1)); - result.designedCapacity = Math.round(parseInt('0' + util.getValue(lines, 'DesignCapacity', '='), 10) * (result.voltage || 1)); - result.manufacturer = 'Apple'; - result.serial = util.getValue(lines, 'BatterySerialNumber', '=') || util.getValue(lines, 'Serial', '='); - result.model = util.getValue(lines, 'DeviceName', '='); - let percent = null; - const line = util.getValue(lines, 'internal', 'Battery'); - let parts = line.split(';'); - if (parts && parts[0]) { - let parts2 = parts[0].split('\t'); - if (parts2 && parts2[1]) { - percent = parseFloat(parts2[1].trim().replace(/%/g, '')); + exec( + 'ioreg -n AppleSmartBattery -r | egrep "CycleCount|IsCharging|DesignCapacity|MaxCapacity|CurrentCapacity|DeviceName|BatterySerialNumber|Serial|TimeRemaining|Voltage"; pmset -g batt | grep %', + (error, stdout) => { + if (stdout) { + let lines = stdout.toString().replace(/ +/g, '').replace(/"+/g, '').replace(/-/g, '').split('\n'); + result.cycleCount = parseInt('0' + util.getValue(lines, 'cyclecount', '='), 10); + result.voltage = parseInt('0' + util.getValue(lines, 'voltage', '='), 10) / 1000.0; + result.capacityUnit = result.voltage ? 'mWh' : 'mAh'; + result.maxCapacity = Math.round(parseInt('0' + util.getValue(lines, 'applerawmaxcapacity', '='), 10) * (result.voltage || 1)); + result.currentCapacity = Math.round(parseInt('0' + util.getValue(lines, 'applerawcurrentcapacity', '='), 10) * (result.voltage || 1)); + result.designedCapacity = Math.round(parseInt('0' + util.getValue(lines, 'DesignCapacity', '='), 10) * (result.voltage || 1)); + result.manufacturer = 'Apple'; + result.serial = util.getValue(lines, 'BatterySerialNumber', '=') || util.getValue(lines, 'Serial', '='); + result.model = util.getValue(lines, 'DeviceName', '='); + let percent = null; + const line = util.getValue(lines, 'internal', 'Battery'); + let parts = line.split(';'); + if (parts && parts[0]) { + let parts2 = parts[0].split('\t'); + if (parts2 && parts2[1]) { + percent = parseFloat(parts2[1].trim().replace(/%/g, '')); + } + } + if (parts && parts[1]) { + result.isCharging = parts[1].trim() === 'charging'; + result.acConnected = parts[1].trim() !== 'discharging'; + } else { + result.isCharging = util.getValue(lines, 'ischarging', '=').toLowerCase() === 'yes'; + result.acConnected = result.isCharging; + } + if (result.maxCapacity && result.currentCapacity) { + result.hasBattery = true; + result.type = 'Li-ion'; + result.percent = percent !== null ? percent : Math.round((100.0 * result.currentCapacity) / result.maxCapacity); + if (!result.isCharging) { + result.timeRemaining = parseInt('0' + util.getValue(lines, 'TimeRemaining', '='), 10); + } } } - if (parts && parts[1]) { - result.isCharging = (parts[1].trim() === 'charging'); - result.acConnected = (parts[1].trim() !== 'discharging'); - } else { - result.isCharging = util.getValue(lines, 'ischarging', '=').toLowerCase() === 'yes'; - result.acConnected = result.isCharging; - } - if (result.maxCapacity && result.currentCapacity) { - result.hasBattery = true; - result.type = 'Li-ion'; - result.percent = percent !== null ? percent : Math.round(100.0 * result.currentCapacity / result.maxCapacity); - if (!result.isCharging) { - result.timeRemaining = parseInt('0' + util.getValue(lines, 'TimeRemaining', '='), 10); - } + if (callback) { + callback(result); } + resolve(result); } - if (callback) { callback(result); } - resolve(result); - }); + ); } if (_sunos) { - if (callback) { callback(result); } + if (callback) { + callback(result); + } resolve(result); } if (_windows) { @@ -232,30 +249,30 @@ module.exports = function (callback) { workload.push(util.powerShell('Get-CimInstance Win32_Battery | select BatteryStatus, DesignCapacity, DesignVoltage, EstimatedChargeRemaining, DeviceID | fl')); workload.push(util.powerShell('(Get-WmiObject -Class BatteryStaticData -Namespace ROOT/WMI).DesignedCapacity')); workload.push(util.powerShell('(Get-CimInstance -Class BatteryFullChargedCapacity -Namespace ROOT/WMI).FullChargedCapacity')); - util.promiseAll( - workload - ).then((data) => { + util.promiseAll(workload).then((data) => { if (data) { - let parts = data.results[0].split(/\n\s*\n/); - let batteries = []; - const hasValue = value => /\S/.test(value); + const parts = data.results[0].split(/\n\s*\n/); + const batteries = []; + const hasValue = (value) => /\S/.test(value); for (let i = 0; i < parts.length; i++) { - if (hasValue(parts[i]) && (!batteries.length || !hasValue(parts[i - 1]))) { - batteries.push([]); - } + // if (hasValue(parts[i]) && (!batteries.length || !hasValue(parts[i - 1]))) { + // batteries.push([]); + // } if (hasValue(parts[i])) { - batteries[batteries.length - 1].push(parts[i]); + // batteries[batteries.length - 1].push(parts[i]); + batteries.push(parts[i]); } } - let designCapacities = data.results[1].split('\r\n').filter(e => e); - let fullChargeCapacities = data.results[2].split('\r\n').filter(e => e); + const designCapacities = data.results[1].split('\r\n').filter((e) => e); + const fullChargeCapacities = data.results[2].split('\r\n').filter((e) => e); if (batteries.length) { let first = false; - let additionalBatteries = []; + const additionalBatteries = []; for (let i = 0; i < batteries.length; i++) { - let lines = batteries[i][0].split('\r\n'); - const designedCapacity = designCapacities && designCapacities.length >= (i + 1) && designCapacities[i] ? util.toInt(designCapacities[i]) : 0; - const fullChargeCapacity = fullChargeCapacities && fullChargeCapacities.length >= (i + 1) && fullChargeCapacities[i] ? util.toInt(fullChargeCapacities[i]) : 0; + // let lines = batteries[i][0].split('\r\n'); + const lines = batteries[i].split('\r\n'); + const designedCapacity = designCapacities && designCapacities.length >= i + 1 && designCapacities[i] ? util.toInt(designCapacities[i]) : 0; + const fullChargeCapacity = fullChargeCapacities && fullChargeCapacities.length >= i + 1 && fullChargeCapacities[i] ? util.toInt(fullChargeCapacities[i]) : 0; const parsed = parseWinBatteryPart(lines, designedCapacity, fullChargeCapacity); if (!first && parsed.status > 0 && parsed.status !== 10) { result.hasBattery = parsed.hasBattery; @@ -270,24 +287,22 @@ module.exports = function (callback) { result.model = parsed.model; first = true; } else if (parsed.status !== -1) { - additionalBatteries.push( - { - hasBattery: parsed.hasBattery, - maxCapacity: parsed.maxCapacity, - designedCapacity: parsed.designedCapacity, - voltage: parsed.voltage, - capacityUnit: parsed.capacityUnit, - percent: parsed.percent, - currentCapacity: parsed.currentCapacity, - isCharging: parsed.isCharging, - timeRemaining: null, - acConnected: parsed.acConnected, - model: parsed.model, - type: '', - manufacturer: '', - serial: '' - } - ); + additionalBatteries.push({ + hasBattery: parsed.hasBattery, + maxCapacity: parsed.maxCapacity, + designedCapacity: parsed.designedCapacity, + voltage: parsed.voltage, + capacityUnit: parsed.capacityUnit, + percent: parsed.percent, + currentCapacity: parsed.currentCapacity, + isCharging: parsed.isCharging, + timeRemaining: null, + acConnected: parsed.acConnected, + model: parsed.model, + type: '', + manufacturer: '', + serial: '' + }); } } if (!first && additionalBatteries.length) { @@ -299,14 +314,17 @@ module.exports = function (callback) { } } } - if (callback) { callback(result); } + if (callback) { + callback(result); + } resolve(result); }); - } catch (e) { - if (callback) { callback(result); } + } catch { + if (callback) { + callback(result); + } resolve(result); } } }); }); -}; diff --git a/lib/bluetooth.js b/lib/bluetooth.js index a6236db..ee3b974 100644 --- a/lib/bluetooth.js +++ b/lib/bluetooth.js @@ -22,28 +22,50 @@ const fs = require('fs'); let _platform = process.platform; -const _linux = (_platform === 'linux' || _platform === 'android'); -const _darwin = (_platform === 'darwin'); -const _windows = (_platform === 'win32'); -const _freebsd = (_platform === 'freebsd'); -const _openbsd = (_platform === 'openbsd'); -const _netbsd = (_platform === 'netbsd'); -const _sunos = (_platform === 'sunos'); +const _linux = _platform === 'linux' || _platform === 'android'; +const _darwin = _platform === 'darwin'; +const _windows = _platform === 'win32'; +const _freebsd = _platform === 'freebsd'; +const _openbsd = _platform === 'openbsd'; +const _netbsd = _platform === 'netbsd'; +const _sunos = _platform === 'sunos'; function parseBluetoothType(str) { let result = ''; - if (str.indexOf('keyboard') >= 0) { result = 'Keyboard'; } - if (str.indexOf('mouse') >= 0) { result = 'Mouse'; } - if (str.indexOf('trackpad') >= 0) { result = 'Trackpad'; } - if (str.indexOf('speaker') >= 0) { result = 'Speaker'; } - if (str.indexOf('headset') >= 0) { result = 'Headset'; } - if (str.indexOf('phone') >= 0) { result = 'Phone'; } - if (str.indexOf('macbook') >= 0) { result = 'Computer'; } - if (str.indexOf('imac') >= 0) { result = 'Computer'; } - if (str.indexOf('ipad') >= 0) { result = 'Tablet'; } - if (str.indexOf('watch') >= 0) { result = 'Watch'; } - if (str.indexOf('headphone') >= 0) { result = 'Headset'; } + if (str.indexOf('keyboard') >= 0) { + result = 'Keyboard'; + } + if (str.indexOf('mouse') >= 0) { + result = 'Mouse'; + } + if (str.indexOf('trackpad') >= 0) { + result = 'Trackpad'; + } + if (str.indexOf('speaker') >= 0) { + result = 'Speaker'; + } + if (str.indexOf('headset') >= 0) { + result = 'Headset'; + } + if (str.indexOf('phone') >= 0) { + result = 'Phone'; + } + if (str.indexOf('macbook') >= 0) { + result = 'Computer'; + } + if (str.indexOf('imac') >= 0) { + result = 'Computer'; + } + if (str.indexOf('ipad') >= 0) { + result = 'Tablet'; + } + if (str.indexOf('watch') >= 0) { + result = 'Watch'; + } + if (str.indexOf('headphone') >= 0) { + result = 'Headset'; + } // to be continued ... return result; @@ -52,13 +74,27 @@ function parseBluetoothType(str) { function parseBluetoothManufacturer(str) { let result = str.split(' ')[0]; str = str.toLowerCase(); - if (str.indexOf('apple') >= 0) { result = 'Apple'; } - if (str.indexOf('ipad') >= 0) { result = 'Apple'; } - if (str.indexOf('imac') >= 0) { result = 'Apple'; } - if (str.indexOf('iphone') >= 0) { result = 'Apple'; } - if (str.indexOf('magic mouse') >= 0) { result = 'Apple'; } - if (str.indexOf('magic track') >= 0) { result = 'Apple'; } - if (str.indexOf('macbook') >= 0) { result = 'Apple'; } + if (str.indexOf('apple') >= 0) { + result = 'Apple'; + } + if (str.indexOf('ipad') >= 0) { + result = 'Apple'; + } + if (str.indexOf('imac') >= 0) { + result = 'Apple'; + } + if (str.indexOf('iphone') >= 0) { + result = 'Apple'; + } + if (str.indexOf('magic mouse') >= 0) { + result = 'Apple'; + } + if (str.indexOf('magic track') >= 0) { + result = 'Apple'; + } + if (str.indexOf('macbook') >= 0) { + result = 'Apple'; + } // to be continued ... return result; @@ -86,7 +122,9 @@ function parseLinuxBluetoothInfo(lines, macAddr1, macAddr2) { function parseDarwinBluetoothDevices(bluetoothObject, macAddr2) { const result = {}; - const typeStr = ((bluetoothObject.device_minorClassOfDevice_string || bluetoothObject.device_majorClassOfDevice_string || bluetoothObject.device_minorType || '') + (bluetoothObject.device_name || '')).toLowerCase(); + const typeStr = ( + (bluetoothObject.device_minorClassOfDevice_string || bluetoothObject.device_majorClassOfDevice_string || bluetoothObject.device_minorType || '') + (bluetoothObject.device_name || '') + ).toLowerCase(); result.device = bluetoothObject.device_services || ''; result.name = bluetoothObject.device_name || ''; @@ -116,7 +154,6 @@ function parseWindowsBluetooth(lines) { } function bluetoothDevices(callback) { - return new Promise((resolve) => { process.nextTick(() => { let result = []; @@ -152,11 +189,17 @@ function bluetoothDevices(callback) { } if (_darwin) { let cmd = 'system_profiler SPBluetoothDataType -json'; - exec(cmd, function (error, stdout) { + exec(cmd, (error, stdout) => { if (!error) { try { const outObj = JSON.parse(stdout.toString()); - if (outObj.SPBluetoothDataType && outObj.SPBluetoothDataType.length && outObj.SPBluetoothDataType[0] && outObj.SPBluetoothDataType[0]['device_title'] && outObj.SPBluetoothDataType[0]['device_title'].length) { + if ( + outObj.SPBluetoothDataType && + outObj.SPBluetoothDataType.length && + outObj.SPBluetoothDataType[0] && + outObj.SPBluetoothDataType[0]['device_title'] && + outObj.SPBluetoothDataType[0]['device_title'].length + ) { // missing: host BT Adapter macAddr () let macAddr2 = null; if (outObj.SPBluetoothDataType[0]['local_device_title'] && outObj.SPBluetoothDataType[0].local_device_title.general_address) { @@ -173,8 +216,17 @@ function bluetoothDevices(callback) { } }); } - if (outObj.SPBluetoothDataType && outObj.SPBluetoothDataType.length && outObj.SPBluetoothDataType[0] && outObj.SPBluetoothDataType[0]['device_connected'] && outObj.SPBluetoothDataType[0]['device_connected'].length) { - const macAddr2 = outObj.SPBluetoothDataType[0].controller_properties && outObj.SPBluetoothDataType[0].controller_properties.controller_address ? outObj.SPBluetoothDataType[0].controller_properties.controller_address.toLowerCase().replace(/-/g, ':') : null; + if ( + outObj.SPBluetoothDataType && + outObj.SPBluetoothDataType.length && + outObj.SPBluetoothDataType[0] && + outObj.SPBluetoothDataType[0]['device_connected'] && + outObj.SPBluetoothDataType[0]['device_connected'].length + ) { + const macAddr2 = + outObj.SPBluetoothDataType[0].controller_properties && outObj.SPBluetoothDataType[0].controller_properties.controller_address + ? outObj.SPBluetoothDataType[0].controller_properties.controller_address.toLowerCase().replace(/-/g, ':') + : null; outObj.SPBluetoothDataType[0]['device_connected'].forEach((element) => { const obj = element; const objKey = Object.keys(obj); @@ -187,8 +239,17 @@ function bluetoothDevices(callback) { } }); } - if (outObj.SPBluetoothDataType && outObj.SPBluetoothDataType.length && outObj.SPBluetoothDataType[0] && outObj.SPBluetoothDataType[0]['device_not_connected'] && outObj.SPBluetoothDataType[0]['device_not_connected'].length) { - const macAddr2 = outObj.SPBluetoothDataType[0].controller_properties && outObj.SPBluetoothDataType[0].controller_properties.controller_address ? outObj.SPBluetoothDataType[0].controller_properties.controller_address.toLowerCase().replace(/-/g, ':') : null; + if ( + outObj.SPBluetoothDataType && + outObj.SPBluetoothDataType.length && + outObj.SPBluetoothDataType[0] && + outObj.SPBluetoothDataType[0]['device_not_connected'] && + outObj.SPBluetoothDataType[0]['device_not_connected'].length + ) { + const macAddr2 = + outObj.SPBluetoothDataType[0].controller_properties && outObj.SPBluetoothDataType[0].controller_properties.controller_address + ? outObj.SPBluetoothDataType[0].controller_properties.controller_address.toLowerCase().replace(/-/g, ':') + : null; outObj.SPBluetoothDataType[0]['device_not_connected'].forEach((element) => { const obj = element; const objKey = Object.keys(obj);