wmic refactoring (windows codepage issues)

This commit is contained in:
Sebastian Hildebrandt 2021-10-17 17:37:45 +02:00
parent a4bb6f0a02
commit e214f3297c
14 changed files with 10726 additions and 10615 deletions

View File

@ -1,219 +1,219 @@
'use strict'; 'use strict';
// @ts-check // @ts-check
// ================================================================================== // ==================================================================================
// audio.js // audio.js
// ---------------------------------------------------------------------------------- // ----------------------------------------------------------------------------------
// Description: System Information - library // Description: System Information - library
// for Node.js // for Node.js
// Copyright: (c) 2014 - 2021 // Copyright: (c) 2014 - 2021
// Author: Sebastian Hildebrandt // Author: Sebastian Hildebrandt
// ---------------------------------------------------------------------------------- // ----------------------------------------------------------------------------------
// License: MIT // License: MIT
// ================================================================================== // ==================================================================================
// 16. audio // 16. audio
// ---------------------------------------------------------------------------------- // ----------------------------------------------------------------------------------
const exec = require('child_process').exec; const exec = require('child_process').exec;
const execSync = require('child_process').execSync; const execSync = require('child_process').execSync;
const util = require('./util'); const util = require('./util');
// const fs = require('fs'); // const fs = require('fs');
let _platform = process.platform; let _platform = process.platform;
const _linux = (_platform === 'linux'); const _linux = (_platform === 'linux');
const _darwin = (_platform === 'darwin'); const _darwin = (_platform === 'darwin');
const _windows = (_platform === 'win32'); const _windows = (_platform === 'win32');
const _freebsd = (_platform === 'freebsd'); const _freebsd = (_platform === 'freebsd');
const _openbsd = (_platform === 'openbsd'); const _openbsd = (_platform === 'openbsd');
const _netbsd = (_platform === 'netbsd'); const _netbsd = (_platform === 'netbsd');
const _sunos = (_platform === 'sunos'); const _sunos = (_platform === 'sunos');
function parseAudioType(str, input, output) { function parseAudioType(str, input, output) {
let result = ''; let result = '';
if (str.indexOf('speak') >= 0) { result = 'Speaker'; } if (str.indexOf('speak') >= 0) { result = 'Speaker'; }
if (str.indexOf('laut') >= 0) { result = 'Speaker'; } if (str.indexOf('laut') >= 0) { result = 'Speaker'; }
if (str.indexOf('loud') >= 0) { result = 'Speaker'; } if (str.indexOf('loud') >= 0) { result = 'Speaker'; }
if (str.indexOf('head') >= 0) { result = 'Headset'; } if (str.indexOf('head') >= 0) { result = 'Headset'; }
if (str.indexOf('mic') >= 0) { result = 'Microphone'; } if (str.indexOf('mic') >= 0) { result = 'Microphone'; }
if (str.indexOf('mikr') >= 0) { result = 'Microphone'; } if (str.indexOf('mikr') >= 0) { result = 'Microphone'; }
if (str.indexOf('phone') >= 0) { result = 'Phone'; } if (str.indexOf('phone') >= 0) { result = 'Phone'; }
if (str.indexOf('controll') >= 0) { result = 'Controller'; } if (str.indexOf('controll') >= 0) { result = 'Controller'; }
if (str.indexOf('line o') >= 0) { result = 'Line Out'; } if (str.indexOf('line o') >= 0) { result = 'Line Out'; }
if (str.indexOf('digital o') >= 0) { result = 'Digital Out'; } if (str.indexOf('digital o') >= 0) { result = 'Digital Out'; }
if (!result && output) { if (!result && output) {
result = 'Speaker'; result = 'Speaker';
} else if (!result && input) { } else if (!result && input) {
result = 'Microphone'; result = 'Microphone';
} }
return result; return result;
} }
function getLinuxAudioPci() { function getLinuxAudioPci() {
let cmd = 'lspci -v 2>/dev/null'; let cmd = 'lspci -v 2>/dev/null';
let result = []; let result = [];
try { try {
const parts = execSync(cmd).toString().split('\n\n'); const parts = execSync(cmd).toString().split('\n\n');
for (let i = 0; i < parts.length; i++) { for (let i = 0; i < parts.length; i++) {
const lines = parts[i].split('\n'); const lines = parts[i].split('\n');
if (lines && lines.length && lines[0].toLowerCase().indexOf('audio') >= 0) { if (lines && lines.length && lines[0].toLowerCase().indexOf('audio') >= 0) {
const audio = {}; const audio = {};
audio.slotId = lines[0].split(' ')[0]; audio.slotId = lines[0].split(' ')[0];
audio.driver = util.getValue(lines, 'Kernel driver in use', ':', true) || util.getValue(lines, 'Kernel modules', ':', true); audio.driver = util.getValue(lines, 'Kernel driver in use', ':', true) || util.getValue(lines, 'Kernel modules', ':', true);
result.push(audio); result.push(audio);
} }
} }
return result; return result;
} catch (e) { } catch (e) {
return result; return result;
} }
} }
function parseLinuxAudioPciMM(lines, audioPCI) { function parseLinuxAudioPciMM(lines, audioPCI) {
const result = {}; const result = {};
const slotId = util.getValue(lines, 'Slot'); const slotId = util.getValue(lines, 'Slot');
const pciMatch = audioPCI.filter(function (item) { return item.slotId === slotId; }); const pciMatch = audioPCI.filter(function (item) { return item.slotId === slotId; });
result.id = slotId; result.id = slotId;
result.name = util.getValue(lines, 'SDevice'); result.name = util.getValue(lines, 'SDevice');
// result.type = util.getValue(lines, 'Class'); // result.type = util.getValue(lines, 'Class');
result.manufacturer = util.getValue(lines, 'SVendor'); result.manufacturer = util.getValue(lines, 'SVendor');
result.revision = util.getValue(lines, 'Rev'); result.revision = util.getValue(lines, 'Rev');
result.driver = pciMatch && pciMatch.length === 1 && pciMatch[0].driver ? pciMatch[0].driver : ''; result.driver = pciMatch && pciMatch.length === 1 && pciMatch[0].driver ? pciMatch[0].driver : '';
result.default = null; result.default = null;
result.channel = 'PCIe'; result.channel = 'PCIe';
result.type = parseAudioType(result.name, null, null); result.type = parseAudioType(result.name, null, null);
result.in = null; result.in = null;
result.out = null; result.out = null;
result.status = 'online'; result.status = 'online';
return result; return result;
} }
function parseDarwinChannel(str) { function parseDarwinChannel(str) {
let result = ''; let result = '';
if (str.indexOf('builtin') >= 0) { result = 'Built-In'; } if (str.indexOf('builtin') >= 0) { result = 'Built-In'; }
if (str.indexOf('extern') >= 0) { result = 'Audio-Jack'; } if (str.indexOf('extern') >= 0) { result = 'Audio-Jack'; }
if (str.indexOf('hdmi') >= 0) { result = 'HDMI'; } if (str.indexOf('hdmi') >= 0) { result = 'HDMI'; }
if (str.indexOf('displayport') >= 0) { result = 'Display-Port'; } if (str.indexOf('displayport') >= 0) { result = 'Display-Port'; }
if (str.indexOf('usb') >= 0) { result = 'USB'; } if (str.indexOf('usb') >= 0) { result = 'USB'; }
if (str.indexOf('pci') >= 0) { result = 'PCIe'; } if (str.indexOf('pci') >= 0) { result = 'PCIe'; }
return result; return result;
} }
function parseDarwinAudio(audioObject, id) { function parseDarwinAudio(audioObject, id) {
const result = {}; const result = {};
const channelStr = ((audioObject.coreaudio_device_transport || '') + ' ' + (audioObject._name || '')).toLowerCase(); const channelStr = ((audioObject.coreaudio_device_transport || '') + ' ' + (audioObject._name || '')).toLowerCase();
result.id = id; result.id = id;
result.name = audioObject._name; result.name = audioObject._name;
result.manufacturer = audioObject.coreaudio_device_manufacturer; result.manufacturer = audioObject.coreaudio_device_manufacturer;
result.revision = null; result.revision = null;
result.driver = null; result.driver = null;
result.default = !!(audioObject.coreaudio_default_audio_input_device || '') || !!(audioObject.coreaudio_default_audio_output_device || ''); result.default = !!(audioObject.coreaudio_default_audio_input_device || '') || !!(audioObject.coreaudio_default_audio_output_device || '');
result.channel = parseDarwinChannel(channelStr); result.channel = parseDarwinChannel(channelStr);
result.type = parseAudioType(result.name, !!(audioObject.coreaudio_device_input || ''), !!(audioObject.coreaudio_device_output || '')); result.type = parseAudioType(result.name, !!(audioObject.coreaudio_device_input || ''), !!(audioObject.coreaudio_device_output || ''));
result.in = !!(audioObject.coreaudio_device_input || ''); result.in = !!(audioObject.coreaudio_device_input || '');
result.out = !!(audioObject.coreaudio_device_output || ''); result.out = !!(audioObject.coreaudio_device_output || '');
result.status = 'online'; result.status = 'online';
return result; return result;
} }
function parseWindowsAudio(lines) { function parseWindowsAudio(lines) {
const result = {}; const result = {};
const status = util.getValue(lines, 'StatusInfo', '='); const status = util.getValue(lines, 'StatusInfo', ':');
// const description = util.getValue(lines, 'Description', '='); // const description = util.getValue(lines, 'Description', ':');
result.id = util.getValue(lines, 'DeviceID', '='); // PNPDeviceID?? result.id = util.getValue(lines, 'DeviceID', ':'); // PNPDeviceID??
result.name = util.getValue(lines, 'name', '='); result.name = util.getValue(lines, 'name', ':');
result.manufacturer = util.getValue(lines, 'manufacturer', '='); result.manufacturer = util.getValue(lines, 'manufacturer', ':');
result.revision = null; result.revision = null;
result.driver = null; result.driver = null;
result.default = null; result.default = null;
result.channel = null; result.channel = null;
result.type = parseAudioType(result.name, null, null); result.type = parseAudioType(result.name, null, null);
result.in = null; result.in = null;
result.out = null; result.out = null;
result.status = status; result.status = status;
return result; return result;
} }
function audio(callback) { function audio(callback) {
return new Promise((resolve) => { return new Promise((resolve) => {
process.nextTick(() => { process.nextTick(() => {
let result = []; let result = [];
if (_linux || _freebsd || _openbsd || _netbsd) { if (_linux || _freebsd || _openbsd || _netbsd) {
let cmd = 'lspci -vmm 2>/dev/null'; let cmd = 'lspci -vmm 2>/dev/null';
exec(cmd, function (error, stdout) { exec(cmd, function (error, stdout) {
// PCI // PCI
if (!error) { if (!error) {
const audioPCI = getLinuxAudioPci(); const audioPCI = getLinuxAudioPci();
const parts = stdout.toString().split('\n\n'); const parts = stdout.toString().split('\n\n');
for (let i = 0; i < parts.length; i++) { for (let i = 0; i < parts.length; i++) {
const lines = parts[i].split('\n'); const lines = parts[i].split('\n');
if (util.getValue(lines, 'class', ':', true).toLowerCase().indexOf('audio') >= 0) { if (util.getValue(lines, 'class', ':', true).toLowerCase().indexOf('audio') >= 0) {
const audio = parseLinuxAudioPciMM(lines, audioPCI); const audio = parseLinuxAudioPciMM(lines, audioPCI);
result.push(audio); result.push(audio);
} }
} }
} }
if (callback) { if (callback) {
callback(result); callback(result);
} }
resolve(result); resolve(result);
}); });
} }
if (_darwin) { if (_darwin) {
let cmd = 'system_profiler SPAudioDataType -json'; let cmd = 'system_profiler SPAudioDataType -json';
exec(cmd, function (error, stdout) { exec(cmd, function (error, stdout) {
if (!error) { if (!error) {
try { try {
const outObj = JSON.parse(stdout.toString()); const outObj = JSON.parse(stdout.toString());
if (outObj.SPAudioDataType && outObj.SPAudioDataType.length && outObj.SPAudioDataType[0] && outObj.SPAudioDataType[0]['_items'] && outObj.SPAudioDataType[0]['_items'].length) { if (outObj.SPAudioDataType && outObj.SPAudioDataType.length && outObj.SPAudioDataType[0] && outObj.SPAudioDataType[0]['_items'] && outObj.SPAudioDataType[0]['_items'].length) {
for (let i = 0; i < outObj.SPAudioDataType[0]['_items'].length; i++) { for (let i = 0; i < outObj.SPAudioDataType[0]['_items'].length; i++) {
const audio = parseDarwinAudio(outObj.SPAudioDataType[0]['_items'][i], i); const audio = parseDarwinAudio(outObj.SPAudioDataType[0]['_items'][i], i);
result.push(audio); result.push(audio);
} }
} }
} catch (e) { } catch (e) {
util.noop(); util.noop();
} }
} }
if (callback) { if (callback) {
callback(result); callback(result);
} }
resolve(result); resolve(result);
}); });
} }
if (_windows) { if (_windows) {
util.wmic('path Win32_SoundDevice get /value').then((stdout, error) => { util.powerShell('Get-WmiObject Win32_SoundDevice | fl *').then((stdout, error) => {
if (!error) { if (!error) {
const parts = stdout.toString().split(/\n\s*\n/); const parts = stdout.toString().split(/\n\s*\n/);
for (let i = 0; i < parts.length; i++) { for (let i = 0; i < parts.length; i++) {
if (util.getValue(parts[i].split('\n'), 'name', '=')) { if (util.getValue(parts[i].split('\n'), 'name', ':')) {
result.push(parseWindowsAudio(parts[i].split('\n'))); result.push(parseWindowsAudio(parts[i].split('\n')));
} }
} }
} }
if (callback) { if (callback) {
callback(result); callback(result);
} }
resolve(result); resolve(result);
}); });
} }
if (_sunos) { if (_sunos) {
resolve(null); resolve(null);
} }
}); });
}); });
} }
exports.audio = audio; exports.audio = audio;

View File

@ -1,309 +1,309 @@
'use strict'; 'use strict';
// @ts-check; // @ts-check;
// ================================================================================== // ==================================================================================
// battery.js // battery.js
// ---------------------------------------------------------------------------------- // ----------------------------------------------------------------------------------
// Description: System Information - library // Description: System Information - library
// for Node.js // for Node.js
// Copyright: (c) 2014 - 2021 // Copyright: (c) 2014 - 2021
// Author: Sebastian Hildebrandt // Author: Sebastian Hildebrandt
// ---------------------------------------------------------------------------------- // ----------------------------------------------------------------------------------
// License: MIT // License: MIT
// ================================================================================== // ==================================================================================
// 6. Battery // 6. Battery
// ---------------------------------------------------------------------------------- // ----------------------------------------------------------------------------------
const exec = require('child_process').exec; const exec = require('child_process').exec;
const fs = require('fs'); const fs = require('fs');
const util = require('./util'); const util = require('./util');
let _platform = process.platform; let _platform = process.platform;
const _linux = (_platform === 'linux'); const _linux = (_platform === 'linux');
const _darwin = (_platform === 'darwin'); const _darwin = (_platform === 'darwin');
const _windows = (_platform === 'win32'); const _windows = (_platform === 'win32');
const _freebsd = (_platform === 'freebsd'); const _freebsd = (_platform === 'freebsd');
const _openbsd = (_platform === 'openbsd'); const _openbsd = (_platform === 'openbsd');
const _netbsd = (_platform === 'netbsd'); const _netbsd = (_platform === 'netbsd');
const _sunos = (_platform === 'sunos'); const _sunos = (_platform === 'sunos');
function parseWinBatteryPart(lines, designedCapacity, fullChargeCapacity) { function parseWinBatteryPart(lines, designedCapacity, fullChargeCapacity) {
const result = {}; const result = {};
let status = util.getValue(lines, 'BatteryStatus', '=').trim(); let status = util.getValue(lines, 'BatteryStatus', ':').trim();
// 1 = "Discharging" // 1 = "Discharging"
// 2 = "On A/C" // 2 = "On A/C"
// 3 = "Fully Charged" // 3 = "Fully Charged"
// 4 = "Low" // 4 = "Low"
// 5 = "Critical" // 5 = "Critical"
// 6 = "Charging" // 6 = "Charging"
// 7 = "Charging High" // 7 = "Charging High"
// 8 = "Charging Low" // 8 = "Charging Low"
// 9 = "Charging Critical" // 9 = "Charging Critical"
// 10 = "Undefined" // 10 = "Undefined"
// 11 = "Partially Charged" // 11 = "Partially Charged"
if (status >= 0) { if (status >= 0) {
const statusValue = status ? parseInt(status) : 0; const statusValue = status ? parseInt(status) : 0;
result.status = statusValue; result.status = statusValue;
result.hasBattery = true; result.hasBattery = true;
result.maxCapacity = fullChargeCapacity || parseInt(util.getValue(lines, 'DesignCapacity', '=') || 0); result.maxCapacity = fullChargeCapacity || parseInt(util.getValue(lines, 'DesignCapacity', ':') || 0);
result.designedCapacity = parseInt(util.getValue(lines, 'DesignCapacity', '=') || designedCapacity); 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', ':') || 0) / 1000.0;
result.capacityUnit = 'mWh'; result.capacityUnit = 'mWh';
result.percent = parseInt(util.getValue(lines, 'EstimatedChargeRemaining', '=') || 0); result.percent = parseInt(util.getValue(lines, 'EstimatedChargeRemaining', ':') || 0);
result.currentCapacity = parseInt(result.maxCapacity * result.percent / 100); result.currentCapacity = parseInt(result.maxCapacity * result.percent / 100);
result.isCharging = (statusValue >= 6 && statusValue <= 9) || statusValue === 11 || (!(statusValue === 3) && !(statusValue === 1) && 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.acConnected = result.isCharging || statusValue === 2;
result.model = util.getValue(lines, 'DeviceID', '='); result.model = util.getValue(lines, 'DeviceID', ':');
} else { } else {
result.status = -1; result.status = -1;
} }
return result; return result;
} }
module.exports = function (callback) { module.exports = function (callback) {
return new Promise((resolve) => { return new Promise((resolve) => {
process.nextTick(() => { process.nextTick(() => {
let result = { let result = {
hasBattery: false, hasBattery: false,
cycleCount: 0, cycleCount: 0,
isCharging: false, isCharging: false,
designedCapacity: 0, designedCapacity: 0,
maxCapacity: 0, maxCapacity: 0,
currentCapacity: 0, currentCapacity: 0,
voltage: 0, voltage: 0,
capacityUnit: '', capacityUnit: '',
percent: 0, percent: 0,
timeRemaining: null, timeRemaining: null,
acConnected: true, acConnected: true,
type: '', type: '',
model: '', model: '',
manufacturer: '', manufacturer: '',
serial: '' serial: ''
}; };
if (_linux) { if (_linux) {
let battery_path = ''; let battery_path = '';
if (fs.existsSync('/sys/class/power_supply/BAT1/uevent')) { if (fs.existsSync('/sys/class/power_supply/BAT1/uevent')) {
battery_path = '/sys/class/power_supply/BAT1/'; battery_path = '/sys/class/power_supply/BAT1/';
} else if (fs.existsSync('/sys/class/power_supply/BAT0/uevent')) { } else if (fs.existsSync('/sys/class/power_supply/BAT0/uevent')) {
battery_path = '/sys/class/power_supply/BAT0/'; battery_path = '/sys/class/power_supply/BAT0/';
} }
let acConnected = false; let acConnected = false;
let acPath = ''; let acPath = '';
if (fs.existsSync('/sys/class/power_supply/AC/online')) { if (fs.existsSync('/sys/class/power_supply/AC/online')) {
acPath = '/sys/class/power_supply/AC/online'; acPath = '/sys/class/power_supply/AC/online';
} else if (fs.existsSync('/sys/class/power_supply/AC0/online')) { } else if (fs.existsSync('/sys/class/power_supply/AC0/online')) {
acPath = '/sys/class/power_supply/AC0/online'; acPath = '/sys/class/power_supply/AC0/online';
} }
if (acPath) { if (acPath) {
const file = fs.readFileSync(acPath); const file = fs.readFileSync(acPath);
acConnected = file.toString().trim() === '1'; acConnected = file.toString().trim() === '1';
} }
if (battery_path) { if (battery_path) {
fs.readFile(battery_path + 'uevent', function (error, stdout) { fs.readFile(battery_path + 'uevent', function (error, stdout) {
if (!error) { if (!error) {
let lines = stdout.toString().split('\n'); 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.acConnected = acConnected || result.isCharging;
result.voltage = parseInt('0' + util.getValue(lines, 'POWER_SUPPLY_VOLTAGE_NOW', '='), 10) / 1000000.0; result.voltage = parseInt('0' + util.getValue(lines, 'POWER_SUPPLY_VOLTAGE_NOW', '='), 10) / 1000000.0;
result.capacityUnit = result.voltage ? 'mWh' : 'mAh'; result.capacityUnit = result.voltage ? 'mWh' : 'mAh';
result.cycleCount = parseInt('0' + util.getValue(lines, 'POWER_SUPPLY_CYCLE_COUNT', '='), 10); 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; 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.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.currentCapacity = Math.round(parseInt('0' + util.getValue(lines, 'POWER_SUPPLY_CHARGE_NOW', '='), 10) / 1000.0 * (result.voltage || 1));
if (!result.maxCapacity) { if (!result.maxCapacity) {
result.maxCapacity = parseInt('0' + util.getValue(lines, 'POWER_SUPPLY_ENERGY_FULL', '=', true, true), 10) / 1000.0; 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; result.currentCapacity = parseInt('0' + util.getValue(lines, 'POWER_SUPPLY_ENERGY_NOW', '='), 10) / 1000.0;
} }
const percent = util.getValue(lines, 'POWER_SUPPLY_CAPACITY', '='); const percent = util.getValue(lines, 'POWER_SUPPLY_CAPACITY', '=');
const energy = parseInt('0' + util.getValue(lines, 'POWER_SUPPLY_ENERGY_NOW', '='), 10); const energy = parseInt('0' + util.getValue(lines, 'POWER_SUPPLY_ENERGY_NOW', '='), 10);
const power = parseInt('0' + util.getValue(lines, 'POWER_SUPPLY_POWER_NOW', '='), 10); const power = parseInt('0' + util.getValue(lines, 'POWER_SUPPLY_POWER_NOW', '='), 10);
const current = parseInt('0' + util.getValue(lines, 'POWER_SUPPLY_CURRENT_NOW', '='), 10); const current = parseInt('0' + util.getValue(lines, 'POWER_SUPPLY_CURRENT_NOW', '='), 10);
result.percent = parseInt('0' + percent, 10); result.percent = parseInt('0' + percent, 10);
if (result.maxCapacity && result.currentCapacity) { if (result.maxCapacity && result.currentCapacity) {
result.hasBattery = true; result.hasBattery = true;
if (!percent) { if (!percent) {
result.percent = 100.0 * result.currentCapacity / result.maxCapacity; result.percent = 100.0 * result.currentCapacity / result.maxCapacity;
} }
} }
if (result.isCharging) { if (result.isCharging) {
result.hasBattery = true; result.hasBattery = true;
} }
if (energy && power) { if (energy && power) {
result.timeRemaining = Math.floor(energy / power * 60); result.timeRemaining = Math.floor(energy / power * 60);
} else if (current && result.currentCapacity) { } 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.type = util.getValue(lines, 'POWER_SUPPLY_TECHNOLOGY', '=');
result.model = util.getValue(lines, 'POWER_SUPPLY_MODEL_NAME', '='); result.model = util.getValue(lines, 'POWER_SUPPLY_MODEL_NAME', '=');
result.manufacturer = util.getValue(lines, 'POWER_SUPPLY_MANUFACTURER', '='); result.manufacturer = util.getValue(lines, 'POWER_SUPPLY_MANUFACTURER', '=');
result.serial = util.getValue(lines, 'POWER_SUPPLY_SERIAL_NUMBER', '='); result.serial = util.getValue(lines, 'POWER_SUPPLY_SERIAL_NUMBER', '=');
if (callback) { callback(result); } if (callback) { callback(result); }
resolve(result); resolve(result);
} else { } else {
if (callback) { callback(result); } if (callback) { callback(result); }
resolve(result); resolve(result);
} }
}); });
} else { } else {
if (callback) { callback(result); } if (callback) { callback(result); }
resolve(result); resolve(result);
} }
} }
if (_freebsd || _openbsd || _netbsd) { if (_freebsd || _openbsd || _netbsd) {
exec('sysctl hw.acpi.battery hw.acpi.acline', function (error, stdout) { exec('sysctl hw.acpi.battery hw.acpi.acline', function (error, stdout) {
let lines = stdout.toString().split('\n'); let lines = stdout.toString().split('\n');
const batteries = parseInt('0' + util.getValue(lines, 'hw.acpi.battery.units'), 10); const batteries = parseInt('0' + util.getValue(lines, 'hw.acpi.battery.units'), 10);
const percent = parseInt('0' + util.getValue(lines, 'hw.acpi.battery.life'), 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.cycleCount = null;
result.isCharging = util.getValue(lines, 'hw.acpi.acline') !== '1'; result.isCharging = util.getValue(lines, 'hw.acpi.acline') !== '1';
result.acConnected = result.isCharging; result.acConnected = result.isCharging;
result.maxCapacity = null; result.maxCapacity = null;
result.currentCapacity = null; result.currentCapacity = null;
result.capacityUnit = 'unknown'; result.capacityUnit = 'unknown';
result.percent = batteries ? percent : null; result.percent = batteries ? percent : null;
if (callback) { callback(result); } if (callback) { callback(result); }
resolve(result); resolve(result);
}); });
} }
if (_darwin) { if (_darwin) {
exec('ioreg -n AppleSmartBattery -r | egrep "CycleCount|IsCharging|DesignCapacity|MaxCapacity|CurrentCapacity|BatterySerialNumber|TimeRemaining|Voltage"; pmset -g batt | grep %', function (error, stdout) { exec('ioreg -n AppleSmartBattery -r | egrep "CycleCount|IsCharging|DesignCapacity|MaxCapacity|CurrentCapacity|BatterySerialNumber|TimeRemaining|Voltage"; pmset -g batt | grep %', function (error, stdout) {
if (stdout) { if (stdout) {
let lines = stdout.toString().replace(/ +/g, '').replace(/"+/g, '').replace(/-/g, '').split('\n'); let lines = stdout.toString().replace(/ +/g, '').replace(/"+/g, '').replace(/-/g, '').split('\n');
result.cycleCount = parseInt('0' + util.getValue(lines, 'cyclecount', '='), 10); result.cycleCount = parseInt('0' + util.getValue(lines, 'cyclecount', '='), 10);
result.voltage = parseInt('0' + util.getValue(lines, 'voltage', '='), 10) / 1000.0; result.voltage = parseInt('0' + util.getValue(lines, 'voltage', '='), 10) / 1000.0;
result.capacityUnit = result.voltage ? 'mWh' : 'mAh'; result.capacityUnit = result.voltage ? 'mWh' : 'mAh';
result.maxCapacity = Math.round(parseInt('0' + util.getValue(lines, 'maxcapacity', '='), 10) * (result.voltage || 1)); result.maxCapacity = Math.round(parseInt('0' + util.getValue(lines, 'maxcapacity', '='), 10) * (result.voltage || 1));
result.currentCapacity = Math.round(parseInt('0' + util.getValue(lines, 'currentcapacity', '='), 10) * (result.voltage || 1)); result.currentCapacity = Math.round(parseInt('0' + util.getValue(lines, 'currentcapacity', '='), 10) * (result.voltage || 1));
result.designedCapacity = Math.round(parseInt('0' + util.getValue(lines, 'DesignCapacity', '='), 10) * (result.voltage || 1)); result.designedCapacity = Math.round(parseInt('0' + util.getValue(lines, 'DesignCapacity', '='), 10) * (result.voltage || 1));
result.manufacturer = 'Apple'; result.manufacturer = 'Apple';
result.serial = util.getValue(lines, 'BatterySerialNumber', '='); result.serial = util.getValue(lines, 'BatterySerialNumber', '=');
let percent = null; let percent = null;
const line = util.getValue(lines, 'internal', 'Battery'); const line = util.getValue(lines, 'internal', 'Battery');
let parts = line.split(';'); let parts = line.split(';');
if (parts && parts[0]) { if (parts && parts[0]) {
let parts2 = parts[0].split('\t'); let parts2 = parts[0].split('\t');
if (parts2 && parts2[1]) { if (parts2 && parts2[1]) {
percent = parseFloat(parts2[1].trim().replace(/%/g, '')); percent = parseFloat(parts2[1].trim().replace(/%/g, ''));
} }
} }
if (parts && parts[1]) { if (parts && parts[1]) {
result.isCharging = (parts[1].trim() === 'charging'); result.isCharging = (parts[1].trim() === 'charging');
result.acConnected = (parts[1].trim() !== 'discharging'); result.acConnected = (parts[1].trim() !== 'discharging');
} else { } else {
result.isCharging = util.getValue(lines, 'ischarging', '=').toLowerCase() === 'yes'; result.isCharging = util.getValue(lines, 'ischarging', '=').toLowerCase() === 'yes';
result.acConnected = result.isCharging; result.acConnected = result.isCharging;
} }
if (result.maxCapacity && result.currentCapacity) { if (result.maxCapacity && result.currentCapacity) {
result.hasBattery = true; result.hasBattery = true;
result.type = 'Li-ion'; result.type = 'Li-ion';
result.percent = percent !== null ? percent : Math.round(100.0 * result.currentCapacity / result.maxCapacity); result.percent = percent !== null ? percent : Math.round(100.0 * result.currentCapacity / result.maxCapacity);
if (!result.isCharging) { if (!result.isCharging) {
result.timeRemaining = parseInt('0' + util.getValue(lines, 'TimeRemaining', '='), 10); result.timeRemaining = parseInt('0' + util.getValue(lines, 'TimeRemaining', '='), 10);
} }
} }
} }
if (callback) { callback(result); } if (callback) { callback(result); }
resolve(result); resolve(result);
}); });
} }
if (_sunos) { if (_sunos) {
if (callback) { callback(result); } if (callback) { callback(result); }
resolve(result); resolve(result);
} }
if (_windows) { if (_windows) {
try { try {
const workload = []; const workload = [];
workload.push(util.wmic('Path Win32_Battery Get /value')); workload.push(util.powerShell('Get-WmiObject Win32_Battery | fl *'));
workload.push(util.powerShell('(Get-WmiObject -Class BatteryStaticData -Namespace ROOT/WMI).DesignedCapacity')); workload.push(util.powerShell('(Get-WmiObject -Class BatteryStaticData -Namespace ROOT/WMI).DesignedCapacity'));
workload.push(util.powerShell('(Get-WmiObject -Class BatteryFullChargedCapacity -Namespace ROOT/WMI).FullChargedCapacity')); workload.push(util.powerShell('(Get-WmiObject -Class BatteryFullChargedCapacity -Namespace ROOT/WMI).FullChargedCapacity'));
util.promiseAll( util.promiseAll(
workload workload
).then(data => { ).then(data => {
if (data) { if (data) {
// let parts = data.results[0].split(/\n\s*\n/); // let parts = data.results[0].split(/\n\s*\n/);
let parts = data.results[0].split('\r\n'); let parts = data.results[0].split(/\n\s*\n/);
let batteries = []; let batteries = [];
const hasValue = value => /\S/.test(value); const hasValue = value => /\S/.test(value);
for (let i = 0; i < parts.length; i++) { for (let i = 0; i < parts.length; i++) {
if (hasValue(parts[i]) && (!batteries.length || !hasValue(parts[i - 1]))) { if (hasValue(parts[i]) && (!batteries.length || !hasValue(parts[i - 1]))) {
batteries.push([]); batteries.push([]);
} }
if (hasValue(parts[i])) { if (hasValue(parts[i])) {
batteries[batteries.length - 1].push(parts[i]); batteries[batteries.length - 1].push(parts[i]);
} }
} }
let designCapacities = data.results[1].split('\r\n'); let designCapacities = data.results[1].split('\r\n');
let fullChargeCapacities = data.results[2].split('\r\n'); let fullChargeCapacities = data.results[2].split('\r\n');
if (batteries.length) { if (batteries.length) {
let first = false; let first = false;
let additionalBatteries = []; let additionalBatteries = [];
for (let i = 0; i < batteries.length; i++) { for (let i = 0; i < batteries.length; i++) {
let lines = batteries[i]; let lines = batteries[i];
const designedCapacity = designCapacities && designCapacities.length >= (i + 1) && designCapacities[i] ? util.toInt(designCapacities[i]) : 0; 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 fullChargeCapacity = fullChargeCapacities && fullChargeCapacities.length >= (i + 1) && fullChargeCapacities[i] ? util.toInt(fullChargeCapacities[i]) : 0;
const parsed = parseWinBatteryPart(lines, designedCapacity, fullChargeCapacity); const parsed = parseWinBatteryPart(lines, designedCapacity, fullChargeCapacity);
if (!first && parsed.status > 0 && parsed.status !== 10) { if (!first && parsed.status > 0 && parsed.status !== 10) {
result.hasBattery = parsed.hasBattery; result.hasBattery = parsed.hasBattery;
result.maxCapacity = parsed.maxCapacity; result.maxCapacity = parsed.maxCapacity;
result.designedCapacity = parsed.designedCapacity; result.designedCapacity = parsed.designedCapacity;
result.voltage = parsed.voltage; result.voltage = parsed.voltage;
result.capacityUnit = parsed.capacityUnit; result.capacityUnit = parsed.capacityUnit;
result.percent = parsed.percent; result.percent = parsed.percent;
result.currentCapacity = parsed.currentCapacity; result.currentCapacity = parsed.currentCapacity;
result.isCharging = parsed.isCharging; result.isCharging = parsed.isCharging;
result.acConnected = parsed.acConnected; result.acConnected = parsed.acConnected;
result.model = parsed.model; result.model = parsed.model;
first = true; first = true;
} else if (parsed.status !== -1) { } else if (parsed.status !== -1) {
additionalBatteries.push( additionalBatteries.push(
{ {
hasBattery: parsed.hasBattery, hasBattery: parsed.hasBattery,
maxCapacity: parsed.maxCapacity, maxCapacity: parsed.maxCapacity,
designedCapacity: parsed.designedCapacity, designedCapacity: parsed.designedCapacity,
voltage: parsed.voltage, voltage: parsed.voltage,
capacityUnit: parsed.capacityUnit, capacityUnit: parsed.capacityUnit,
percent: parsed.percent, percent: parsed.percent,
currentCapacity: parsed.currentCapacity, currentCapacity: parsed.currentCapacity,
isCharging: parsed.isCharging, isCharging: parsed.isCharging,
timeRemaining: null, timeRemaining: null,
acConnected: parsed.acConnected, acConnected: parsed.acConnected,
model: parsed.model, model: parsed.model,
type: '', type: '',
manufacturer: '', manufacturer: '',
serial: '' serial: ''
} }
); );
} }
} }
if (!first && additionalBatteries.length) { if (!first && additionalBatteries.length) {
result = additionalBatteries[0]; result = additionalBatteries[0];
additionalBatteries.shift(); additionalBatteries.shift();
} }
if (additionalBatteries.length) { if (additionalBatteries.length) {
result.additionalBatteries = additionalBatteries; result.additionalBatteries = additionalBatteries;
} }
} }
} }
if (callback) { callback(result); } if (callback) { callback(result); }
resolve(result); resolve(result);
}); });
} catch (e) { } catch (e) {
if (callback) { callback(result); } if (callback) { callback(result); }
resolve(result); resolve(result);
} }
} }
}); });
}); });
}; };

View File

@ -1,183 +1,183 @@
'use strict'; 'use strict';
// @ts-check // @ts-check
// ================================================================================== // ==================================================================================
// audio.js // audio.js
// ---------------------------------------------------------------------------------- // ----------------------------------------------------------------------------------
// Description: System Information - library // Description: System Information - library
// for Node.js // for Node.js
// Copyright: (c) 2014 - 2021 // Copyright: (c) 2014 - 2021
// Author: Sebastian Hildebrandt // Author: Sebastian Hildebrandt
// ---------------------------------------------------------------------------------- // ----------------------------------------------------------------------------------
// License: MIT // License: MIT
// ================================================================================== // ==================================================================================
// 17. bluetooth // 17. bluetooth
// ---------------------------------------------------------------------------------- // ----------------------------------------------------------------------------------
const exec = require('child_process').exec; const exec = require('child_process').exec;
const execSync = require('child_process').execSync; const execSync = require('child_process').execSync;
const path = require('path'); const path = require('path');
const util = require('./util'); const util = require('./util');
const fs = require('fs'); const fs = require('fs');
let _platform = process.platform; let _platform = process.platform;
const _linux = (_platform === 'linux'); const _linux = (_platform === 'linux');
const _darwin = (_platform === 'darwin'); const _darwin = (_platform === 'darwin');
const _windows = (_platform === 'win32'); const _windows = (_platform === 'win32');
const _freebsd = (_platform === 'freebsd'); const _freebsd = (_platform === 'freebsd');
const _openbsd = (_platform === 'openbsd'); const _openbsd = (_platform === 'openbsd');
const _netbsd = (_platform === 'netbsd'); const _netbsd = (_platform === 'netbsd');
const _sunos = (_platform === 'sunos'); const _sunos = (_platform === 'sunos');
function parseBluetoothTyoe(str) { function parseBluetoothType(str) {
let result = ''; let result = '';
if (str.indexOf('keyboard') >= 0) { result = 'Keyboard'; } if (str.indexOf('keyboard') >= 0) { result = 'Keyboard'; }
if (str.indexOf('mouse') >= 0) { result = 'Mouse'; } if (str.indexOf('mouse') >= 0) { result = 'Mouse'; }
if (str.indexOf('speaker') >= 0) { result = 'Speaker'; } if (str.indexOf('speaker') >= 0) { result = 'Speaker'; }
if (str.indexOf('headset') >= 0) { result = 'Headset'; } if (str.indexOf('headset') >= 0) { result = 'Headset'; }
if (str.indexOf('phone') >= 0) { result = 'Phone'; } if (str.indexOf('phone') >= 0) { result = 'Phone'; }
// to be continued ... // to be continued ...
return result; return result;
} }
function parseLinuxBluetoothInfo(lines, macAddr1, macAddr2) { function parseLinuxBluetoothInfo(lines, macAddr1, macAddr2) {
const result = {}; const result = {};
result.device = null; result.device = null;
result.name = util.getValue(lines, 'name', '='); result.name = util.getValue(lines, 'name', '=');
result.manufacturer = null; result.manufacturer = null;
result.macDevice = macAddr1; result.macDevice = macAddr1;
result.macHost = macAddr2; result.macHost = macAddr2;
result.batteryPercent = null; result.batteryPercent = null;
result.type = parseBluetoothTyoe(result.name.toLowerCase()); result.type = parseBluetoothType(result.name.toLowerCase());
result.connected = false; result.connected = false;
return result; return result;
} }
function parseDarwinBluetoothDevices(bluetoothObject, macAddr2) { function parseDarwinBluetoothDevices(bluetoothObject, macAddr2) {
const result = {}; const result = {};
const typeStr = ((bluetoothObject.device_minorClassOfDevice_string || bluetoothObject.device_majorClassOfDevice_string || '') + (bluetoothObject.device_name || '')).toLowerCase(); const typeStr = ((bluetoothObject.device_minorClassOfDevice_string || bluetoothObject.device_majorClassOfDevice_string || '') + (bluetoothObject.device_name || '')).toLowerCase();
result.device = bluetoothObject.device_services || ''; result.device = bluetoothObject.device_services || '';
result.name = bluetoothObject.device_name || ''; result.name = bluetoothObject.device_name || '';
result.manufacturer = bluetoothObject.device_manufacturer || ''; result.manufacturer = bluetoothObject.device_manufacturer || '';
result.macDevice = (bluetoothObject.device_addr || '').toLowerCase().replace(/-/g, ':'); result.macDevice = (bluetoothObject.device_addr || '').toLowerCase().replace(/-/g, ':');
result.macHost = macAddr2; result.macHost = macAddr2;
result.batteryPercent = bluetoothObject.device_batteryPercent || null; result.batteryPercent = bluetoothObject.device_batteryPercent || null;
result.type = parseBluetoothTyoe(typeStr); result.type = parseBluetoothType(typeStr);
result.connected = bluetoothObject.device_isconnected === 'attrib_Yes' || false; result.connected = bluetoothObject.device_isconnected === 'attrib_Yes' || false;
return result; return result;
} }
function parseWindowsBluetooth(lines) { function parseWindowsBluetooth(lines) {
const result = {}; const result = {};
result.device = null; result.device = null;
result.name = util.getValue(lines, 'name', '='); result.name = util.getValue(lines, 'name', ':');
result.manufacturer = util.getValue(lines, 'manufacturer', '='); result.manufacturer = util.getValue(lines, 'manufacturer', ':');
result.macDevice = null; result.macDevice = null;
result.macHost = null; result.macHost = null;
result.batteryPercent = null; result.batteryPercent = null;
result.type = parseBluetoothTyoe(result.name.toLowerCase()); result.type = parseBluetoothType(result.name.toLowerCase());
result.connected = null; result.connected = null;
return result; return result;
} }
function bluetoothDevices(callback) { function bluetoothDevices(callback) {
return new Promise((resolve) => { return new Promise((resolve) => {
process.nextTick(() => { process.nextTick(() => {
let result = []; let result = [];
if (_linux) { if (_linux) {
// get files in /var/lib/bluetooth/ recursive // get files in /var/lib/bluetooth/ recursive
const btFiles = util.getFilesInPath('/var/lib/bluetooth/'); const btFiles = util.getFilesInPath('/var/lib/bluetooth/');
for (let i = 0; i < btFiles.length; i++) { for (let i = 0; i < btFiles.length; i++) {
const filename = path.basename(btFiles[i]); const filename = path.basename(btFiles[i]);
const pathParts = btFiles[i].split('/'); const pathParts = btFiles[i].split('/');
const macAddr1 = pathParts.length >= 6 ? pathParts[pathParts.length - 2] : null; const macAddr1 = pathParts.length >= 6 ? pathParts[pathParts.length - 2] : null;
const macAddr2 = pathParts.length >= 7 ? pathParts[pathParts.length - 3] : null; const macAddr2 = pathParts.length >= 7 ? pathParts[pathParts.length - 3] : null;
if (filename === 'info') { if (filename === 'info') {
const infoFile = fs.readFileSync(btFiles[i], { encoding: 'utf8' }).split('\n'); const infoFile = fs.readFileSync(btFiles[i], { encoding: 'utf8' }).split('\n');
result.push(parseLinuxBluetoothInfo(infoFile, macAddr1, macAddr2)); result.push(parseLinuxBluetoothInfo(infoFile, macAddr1, macAddr2));
} }
} }
// determine "connected" with hcitool con // determine "connected" with hcitool con
try { try {
const hdicon = execSync('hcitool con').toString().toLowerCase(); const hdicon = execSync('hcitool con').toString().toLowerCase();
for (let i = 0; i < result.length; i++) { for (let i = 0; i < result.length; i++) {
if (result[i].macDevice && result[i].macDevice.length > 10 && hdicon.indexOf(result[i].macDevice.toLowerCase()) >= 0) { if (result[i].macDevice && result[i].macDevice.length > 10 && hdicon.indexOf(result[i].macDevice.toLowerCase()) >= 0) {
result[i].connected = true; result[i].connected = true;
} }
} }
} catch (e) { } catch (e) {
util.noop(); util.noop();
} }
if (callback) { if (callback) {
callback(result); callback(result);
} }
resolve(result); resolve(result);
} }
if (_darwin) { if (_darwin) {
let cmd = 'system_profiler SPBluetoothDataType -json'; let cmd = 'system_profiler SPBluetoothDataType -json';
exec(cmd, function (error, stdout) { exec(cmd, function (error, stdout) {
if (!error) { if (!error) {
try { try {
const outObj = JSON.parse(stdout.toString()); 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 () // missing: host BT Adapter macAddr ()
let macAddr2 = null; let macAddr2 = null;
if (outObj.SPBluetoothDataType[0]['local_device_title'] && outObj.SPBluetoothDataType[0].local_device_title.general_address) { if (outObj.SPBluetoothDataType[0]['local_device_title'] && outObj.SPBluetoothDataType[0].local_device_title.general_address) {
macAddr2 = outObj.SPBluetoothDataType[0].local_device_title.general_address.toLowerCase().replace(/-/g, ':'); macAddr2 = outObj.SPBluetoothDataType[0].local_device_title.general_address.toLowerCase().replace(/-/g, ':');
} }
for (let i = 0; i < outObj.SPBluetoothDataType[0]['device_title'].length; i++) { for (let i = 0; i < outObj.SPBluetoothDataType[0]['device_title'].length; i++) {
const obj = outObj.SPBluetoothDataType[0]['device_title'][i]; const obj = outObj.SPBluetoothDataType[0]['device_title'][i];
const objKey = Object.keys(obj); const objKey = Object.keys(obj);
if (objKey && objKey.length === 1) { if (objKey && objKey.length === 1) {
const innerObject = obj[objKey[0]]; const innerObject = obj[objKey[0]];
innerObject.device_name = objKey[0]; innerObject.device_name = objKey[0];
const bluetoothDevice = parseDarwinBluetoothDevices(innerObject, macAddr2); const bluetoothDevice = parseDarwinBluetoothDevices(innerObject, macAddr2);
result.push(bluetoothDevice); result.push(bluetoothDevice);
} }
} }
} }
} catch (e) { } catch (e) {
util.noop(); util.noop();
} }
} }
if (callback) { if (callback) {
callback(result); callback(result);
} }
resolve(result); resolve(result);
}); });
} }
if (_windows) { if (_windows) {
util.wmic('path Win32_PNPEntity get /value').then((stdout, error) => { util.powerShell('Get-WmiObject Win32_PNPEntity | fl *').then((stdout, error) => {
if (!error) { if (!error) {
const parts = stdout.toString().split(/\n\s*\n/); const parts = stdout.toString().split(/\n\s*\n/);
for (let i = 0; i < parts.length; i++) { for (let i = 0; i < parts.length; i++) {
if (util.getValue(parts[i].split('\n'), 'PNPClass', '=') === 'Bluetooth') { if (util.getValue(parts[i].split('\n'), 'PNPClass', ':') === 'Bluetooth') {
result.push(parseWindowsBluetooth(parts[i].split('\n'))); result.push(parseWindowsBluetooth(parts[i].split('\n')));
} }
} }
} }
if (callback) { if (callback) {
callback(result); callback(result);
} }
resolve(result); resolve(result);
}); });
} }
if (_freebsd || _netbsd || _openbsd || _sunos) { if (_freebsd || _netbsd || _openbsd || _sunos) {
resolve(null); resolve(null);
} }
}); });
}); });
} }
exports.bluetoothDevices = bluetoothDevices; exports.bluetoothDevices = bluetoothDevices;

3248
lib/cpu.js

File diff suppressed because it is too large Load Diff

2530
lib/filesystem.js Executable file → Normal file

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@ -1,212 +1,212 @@
'use strict'; 'use strict';
// @ts-check // @ts-check
// ================================================================================== // ==================================================================================
// printers.js // printers.js
// ---------------------------------------------------------------------------------- // ----------------------------------------------------------------------------------
// Description: System Information - library // Description: System Information - library
// for Node.js // for Node.js
// Copyright: (c) 2014 - 2021 // Copyright: (c) 2014 - 2021
// Author: Sebastian Hildebrandt // Author: Sebastian Hildebrandt
// ---------------------------------------------------------------------------------- // ----------------------------------------------------------------------------------
// License: MIT // License: MIT
// ================================================================================== // ==================================================================================
// 15. printers // 15. printers
// ---------------------------------------------------------------------------------- // ----------------------------------------------------------------------------------
const exec = require('child_process').exec; const exec = require('child_process').exec;
// const execSync = require('child_process').execSync; // const execSync = require('child_process').execSync;
const util = require('./util'); const util = require('./util');
// const fs = require('fs'); // const fs = require('fs');
let _platform = process.platform; let _platform = process.platform;
const _linux = (_platform === 'linux'); const _linux = (_platform === 'linux');
const _darwin = (_platform === 'darwin'); const _darwin = (_platform === 'darwin');
const _windows = (_platform === 'win32'); const _windows = (_platform === 'win32');
const _freebsd = (_platform === 'freebsd'); const _freebsd = (_platform === 'freebsd');
const _openbsd = (_platform === 'openbsd'); const _openbsd = (_platform === 'openbsd');
const _netbsd = (_platform === 'netbsd'); const _netbsd = (_platform === 'netbsd');
const _sunos = (_platform === 'sunos'); const _sunos = (_platform === 'sunos');
const winPrinterStatus = { const winPrinterStatus = {
1: 'Other', 1: 'Other',
2: 'Unknown', 2: 'Unknown',
3: 'Idle', 3: 'Idle',
4: 'Printing', 4: 'Printing',
5: 'Warmup', 5: 'Warmup',
6: 'Stopped Printing', 6: 'Stopped Printing',
7: 'Offline', 7: 'Offline',
}; };
function parseLinuxCupsHeader(lines) { function parseLinuxCupsHeader(lines) {
const result = {}; const result = {};
if (lines && lines.length) { if (lines && lines.length) {
if (lines[0].indexOf(' CUPS v') > 0) { if (lines[0].indexOf(' CUPS v') > 0) {
const parts = lines[0].split(' CUPS v'); const parts = lines[0].split(' CUPS v');
result.cupsVersion = parts[1]; result.cupsVersion = parts[1];
} }
} }
return result; return result;
} }
function parseLinuxCupsPrinter(lines) { function parseLinuxCupsPrinter(lines) {
const result = {}; const result = {};
const printerId = util.getValue(lines, 'PrinterId', ' '); const printerId = util.getValue(lines, 'PrinterId', ' ');
result.id = printerId ? parseInt(printerId, 10) : null; result.id = printerId ? parseInt(printerId, 10) : null;
result.name = util.getValue(lines, 'Info', ' '); result.name = util.getValue(lines, 'Info', ' ');
result.model = lines.length > 0 && lines[0] ? lines[0].split(' ')[0] : ''; result.model = lines.length > 0 && lines[0] ? lines[0].split(' ')[0] : '';
result.uri = util.getValue(lines, 'DeviceURI', ' '); result.uri = util.getValue(lines, 'DeviceURI', ' ');
result.uuid = util.getValue(lines, 'UUID', ' '); result.uuid = util.getValue(lines, 'UUID', ' ');
result.status = util.getValue(lines, 'State', ' '); result.status = util.getValue(lines, 'State', ' ');
result.local = util.getValue(lines, 'Location', ' ').toLowerCase().startsWith('local'); result.local = util.getValue(lines, 'Location', ' ').toLowerCase().startsWith('local');
result.default = null; result.default = null;
result.shared = util.getValue(lines, 'Shared', ' ').toLowerCase().startsWith('yes'); result.shared = util.getValue(lines, 'Shared', ' ').toLowerCase().startsWith('yes');
return result; return result;
} }
function parseLinuxLpstatPrinter(lines, id) { function parseLinuxLpstatPrinter(lines, id) {
const result = {}; const result = {};
result.id = id; result.id = id;
result.name = util.getValue(lines, 'Description', ':', true); result.name = util.getValue(lines, 'Description', ':', true);
result.model = lines.length > 0 && lines[0] ? lines[0].split(' ')[0] : ''; result.model = lines.length > 0 && lines[0] ? lines[0].split(' ')[0] : '';
result.uri = null; result.uri = null;
result.uuid = null; result.uuid = null;
result.status = lines.length > 0 && lines[0] ? (lines[0].indexOf(' idle') > 0 ? 'idle' : (lines[0].indexOf(' printing') > 0 ? 'printing' : 'unknown')) : null; result.status = lines.length > 0 && lines[0] ? (lines[0].indexOf(' idle') > 0 ? 'idle' : (lines[0].indexOf(' printing') > 0 ? 'printing' : 'unknown')) : null;
result.local = util.getValue(lines, 'Location', ':', true).toLowerCase().startsWith('local'); result.local = util.getValue(lines, 'Location', ':', true).toLowerCase().startsWith('local');
result.default = null; result.default = null;
result.shared = util.getValue(lines, 'Shared', ' ').toLowerCase().startsWith('yes'); result.shared = util.getValue(lines, 'Shared', ' ').toLowerCase().startsWith('yes');
return result; return result;
} }
function parseDarwinPrinters(printerObject, id) { function parseDarwinPrinters(printerObject, id) {
const result = {}; const result = {};
const uriParts = printerObject.uri.split('/'); const uriParts = printerObject.uri.split('/');
result.id = id; result.id = id;
result.name = printerObject._name; result.name = printerObject._name;
result.model = uriParts.length ? uriParts[uriParts.length - 1] : ''; result.model = uriParts.length ? uriParts[uriParts.length - 1] : '';
result.uri = printerObject.uri; result.uri = printerObject.uri;
result.uuid = null; result.uuid = null;
result.status = printerObject.status; result.status = printerObject.status;
result.local = printerObject.printserver === 'local'; result.local = printerObject.printserver === 'local';
result.default = printerObject.default === 'yes'; result.default = printerObject.default === 'yes';
result.shared = printerObject.shared === 'yes'; result.shared = printerObject.shared === 'yes';
return result; return result;
} }
function parseWindowsPrinters(lines, id) { function parseWindowsPrinters(lines, id) {
const result = {}; const result = {};
const status = parseInt(util.getValue(lines, 'PrinterStatus', '='), 10); const status = parseInt(util.getValue(lines, 'PrinterStatus', ':'), 10);
result.id = id; result.id = id;
result.name = util.getValue(lines, 'name', '='); result.name = util.getValue(lines, 'name', ':');
result.model = util.getValue(lines, 'DriverName', '='); result.model = util.getValue(lines, 'DriverName', ':');
result.uri = null; result.uri = null;
result.uuid = null; result.uuid = null;
result.status = winPrinterStatus[status] ? winPrinterStatus[status] : null; result.status = winPrinterStatus[status] ? winPrinterStatus[status] : null;
result.local = util.getValue(lines, 'Local', '=') === 'TRUE'; result.local = util.getValue(lines, 'Local', ':').toUpperCase() === 'TRUE';
result.default = util.getValue(lines, 'Default', '=') === 'TRUE'; result.default = util.getValue(lines, 'Default', ':').toUpperCase() === 'TRUE';
result.shared = util.getValue(lines, 'Shared', '=') === 'TRUE'; result.shared = util.getValue(lines, 'Shared', ':').toUpperCase() === 'TRUE';
return result; return result;
} }
function printer(callback) { function printer(callback) {
return new Promise((resolve) => { return new Promise((resolve) => {
process.nextTick(() => { process.nextTick(() => {
let result = []; let result = [];
if (_linux || _freebsd || _openbsd || _netbsd) { if (_linux || _freebsd || _openbsd || _netbsd) {
let cmd = 'cat /etc/cups/printers.conf 2>/dev/null'; let cmd = 'cat /etc/cups/printers.conf 2>/dev/null';
exec(cmd, function (error, stdout) { exec(cmd, function (error, stdout) {
// printers.conf // printers.conf
if (!error) { if (!error) {
const parts = stdout.toString().split('<Printer '); const parts = stdout.toString().split('<Printer ');
const printerHeader = parseLinuxCupsHeader(parts[0]); const printerHeader = parseLinuxCupsHeader(parts[0]);
for (let i = 1; i < parts.length; i++) { for (let i = 1; i < parts.length; i++) {
const printers = parseLinuxCupsPrinter(parts[i].split('\n')); const printers = parseLinuxCupsPrinter(parts[i].split('\n'));
if (printers.name) { if (printers.name) {
printers.engine = 'CUPS'; printers.engine = 'CUPS';
printers.engineVersion = printerHeader.cupsVersion; printers.engineVersion = printerHeader.cupsVersion;
result.push(printers); result.push(printers);
} }
} }
} }
if (result.length === 0) { if (result.length === 0) {
if (_linux) { if (_linux) {
cmd = 'export LC_ALL=C; lpstat -lp 2>/dev/null; unset LC_ALL'; cmd = 'export LC_ALL=C; lpstat -lp 2>/dev/null; unset LC_ALL';
// lpstat // lpstat
exec(cmd, function (error, stdout) { exec(cmd, function (error, stdout) {
const parts = ('\n' + stdout.toString()).split('\nprinter '); const parts = ('\n' + stdout.toString()).split('\nprinter ');
for (let i = 1; i < parts.length; i++) { for (let i = 1; i < parts.length; i++) {
const printers = parseLinuxLpstatPrinter(parts[i].split('\n'), i); const printers = parseLinuxLpstatPrinter(parts[i].split('\n'), i);
result.push(printers); result.push(printers);
} }
}); });
if (callback) { if (callback) {
callback(result); callback(result);
} }
resolve(result); resolve(result);
} else { } else {
if (callback) { if (callback) {
callback(result); callback(result);
} }
resolve(result); resolve(result);
} }
} else { } else {
if (callback) { if (callback) {
callback(result); callback(result);
} }
resolve(result); resolve(result);
} }
}); });
} }
if (_darwin) { if (_darwin) {
let cmd = 'system_profiler SPPrintersDataType -json'; let cmd = 'system_profiler SPPrintersDataType -json';
exec(cmd, function (error, stdout) { exec(cmd, function (error, stdout) {
if (!error) { if (!error) {
try { try {
const outObj = JSON.parse(stdout.toString()); const outObj = JSON.parse(stdout.toString());
if (outObj.SPPrintersDataType && outObj.SPPrintersDataType.length) { if (outObj.SPPrintersDataType && outObj.SPPrintersDataType.length) {
for (let i = 0; i < outObj.SPPrintersDataType.length; i++) { for (let i = 0; i < outObj.SPPrintersDataType.length; i++) {
const printer = parseDarwinPrinters(outObj.SPPrintersDataType[i], i); const printer = parseDarwinPrinters(outObj.SPPrintersDataType[i], i);
result.push(printer); result.push(printer);
} }
} }
} catch (e) { } catch (e) {
util.noop(); util.noop();
} }
} }
if (callback) { if (callback) {
callback(result); callback(result);
} }
resolve(result); resolve(result);
}); });
} }
if (_windows) { if (_windows) {
util.wmic('printer get /value').then((stdout, error) => { util.powerShell('Get-WmiObject Win32_Printer | fl *').then((stdout, error) => {
if (!error) { if (!error) {
const parts = stdout.toString().split(/\n\s*\n/); const parts = stdout.toString().split(/\n\s*\n/);
for (let i = 0; i < parts.length; i++) { for (let i = 0; i < parts.length; i++) {
const printer = parseWindowsPrinters(parts[i].split('\n'), i); const printer = parseWindowsPrinters(parts[i].split('\n'), i);
if (printer.name || printer.model) { if (printer.name || printer.model) {
result.push(parseWindowsPrinters(parts[i].split('\n'), i)); result.push(parseWindowsPrinters(parts[i].split('\n'), i));
} }
} }
} }
if (callback) { if (callback) {
callback(result); callback(result);
} }
resolve(result); resolve(result);
}); });
} }
if (_sunos) { if (_sunos) {
resolve(null); resolve(null);
} }
}); });
}); });
} }
exports.printer = printer; exports.printer = printer;

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@ -1,305 +1,305 @@
'use strict'; 'use strict';
// @ts-check // @ts-check
// ================================================================================== // ==================================================================================
// usb.js // usb.js
// ---------------------------------------------------------------------------------- // ----------------------------------------------------------------------------------
// Description: System Information - library // Description: System Information - library
// for Node.js // for Node.js
// Copyright: (c) 2014 - 2021 // Copyright: (c) 2014 - 2021
// Author: Sebastian Hildebrandt // Author: Sebastian Hildebrandt
// ---------------------------------------------------------------------------------- // ----------------------------------------------------------------------------------
// License: MIT // License: MIT
// ================================================================================== // ==================================================================================
// 16. usb // 16. usb
// ---------------------------------------------------------------------------------- // ----------------------------------------------------------------------------------
const exec = require('child_process').exec; const exec = require('child_process').exec;
// const execSync = require('child_process').execSync; // const execSync = require('child_process').execSync;
const util = require('./util'); const util = require('./util');
// const fs = require('fs'); // const fs = require('fs');
let _platform = process.platform; let _platform = process.platform;
const _linux = (_platform === 'linux'); const _linux = (_platform === 'linux');
const _darwin = (_platform === 'darwin'); const _darwin = (_platform === 'darwin');
const _windows = (_platform === 'win32'); const _windows = (_platform === 'win32');
const _freebsd = (_platform === 'freebsd'); const _freebsd = (_platform === 'freebsd');
const _openbsd = (_platform === 'openbsd'); const _openbsd = (_platform === 'openbsd');
const _netbsd = (_platform === 'netbsd'); const _netbsd = (_platform === 'netbsd');
const _sunos = (_platform === 'sunos'); const _sunos = (_platform === 'sunos');
function getLinuxUsbType(type, name) { function getLinuxUsbType(type, name) {
let result = type; let result = type;
const str = (name + ' ' + type).toLowerCase(); const str = (name + ' ' + type).toLowerCase();
if (str.indexOf('camera') >= 0) { result = 'Camera'; } if (str.indexOf('camera') >= 0) { result = 'Camera'; }
else if (str.indexOf('hub') >= 0) { result = 'Hub'; } else if (str.indexOf('hub') >= 0) { result = 'Hub'; }
else if (str.indexOf('keybrd') >= 0) { result = 'Keyboard'; } else if (str.indexOf('keybrd') >= 0) { result = 'Keyboard'; }
else if (str.indexOf('keyboard') >= 0) { result = 'Keyboard'; } else if (str.indexOf('keyboard') >= 0) { result = 'Keyboard'; }
else if (str.indexOf('mouse') >= 0) { result = 'Mouse'; } else if (str.indexOf('mouse') >= 0) { result = 'Mouse'; }
else if (str.indexOf('stora') >= 0) { result = 'Storage'; } else if (str.indexOf('stora') >= 0) { result = 'Storage'; }
else if (str.indexOf('mic') >= 0) { result = 'Microphone'; } else if (str.indexOf('mic') >= 0) { result = 'Microphone'; }
else if (str.indexOf('headset') >= 0) { result = 'Audio'; } else if (str.indexOf('headset') >= 0) { result = 'Audio'; }
else if (str.indexOf('audio') >= 0) { result = 'Audio'; } else if (str.indexOf('audio') >= 0) { result = 'Audio'; }
return result; return result;
} }
function parseLinuxUsb(usb) { function parseLinuxUsb(usb) {
const result = {}; const result = {};
const lines = usb.split('\n'); const lines = usb.split('\n');
if (lines && lines.length && lines[0].indexOf('Device') >= 0) { if (lines && lines.length && lines[0].indexOf('Device') >= 0) {
const parts = lines[0].split(' '); const parts = lines[0].split(' ');
result.bus = parseInt(parts[0], 10); result.bus = parseInt(parts[0], 10);
if (parts[2]) { if (parts[2]) {
result.deviceId = parseInt(parts[2], 10); result.deviceId = parseInt(parts[2], 10);
} else { } else {
result.deviceId = null; result.deviceId = null;
} }
} else { } else {
result.bus = null; result.bus = null;
result.deviceId = null; result.deviceId = null;
} }
const idVendor = util.getValue(lines, 'idVendor', ' ', true).trim(); const idVendor = util.getValue(lines, 'idVendor', ' ', true).trim();
let vendorParts = idVendor.split(' '); let vendorParts = idVendor.split(' ');
vendorParts.shift(); vendorParts.shift();
const vendor = vendorParts.join(' '); const vendor = vendorParts.join(' ');
const idProduct = util.getValue(lines, 'idProduct', ' ', true).trim(); const idProduct = util.getValue(lines, 'idProduct', ' ', true).trim();
let productParts = idProduct.split(' '); let productParts = idProduct.split(' ');
productParts.shift(); productParts.shift();
const product = productParts.join(' '); const product = productParts.join(' ');
const interfaceClass = util.getValue(lines, 'bInterfaceClass', ' ', true).trim(); const interfaceClass = util.getValue(lines, 'bInterfaceClass', ' ', true).trim();
let interfaceClassParts = interfaceClass.split(' '); let interfaceClassParts = interfaceClass.split(' ');
interfaceClassParts.shift(); interfaceClassParts.shift();
const usbType = interfaceClassParts.join(' '); const usbType = interfaceClassParts.join(' ');
const iManufacturer = util.getValue(lines, 'iManufacturer', ' ', true).trim(); const iManufacturer = util.getValue(lines, 'iManufacturer', ' ', true).trim();
let iManufacturerParts = iManufacturer.split(' '); let iManufacturerParts = iManufacturer.split(' ');
iManufacturerParts.shift(); iManufacturerParts.shift();
const manufacturer = iManufacturerParts.join(' '); const manufacturer = iManufacturerParts.join(' ');
result.id = (idVendor.startsWith('0x') ? idVendor.split(' ')[0].substr(2, 10) : '') + ':' + (idProduct.startsWith('0x') ? idProduct.split(' ')[0].substr(2, 10) : ''); result.id = (idVendor.startsWith('0x') ? idVendor.split(' ')[0].substr(2, 10) : '') + ':' + (idProduct.startsWith('0x') ? idProduct.split(' ')[0].substr(2, 10) : '');
result.name = product; result.name = product;
result.type = getLinuxUsbType(usbType, product); result.type = getLinuxUsbType(usbType, product);
result.removable = null; result.removable = null;
result.vendor = vendor; result.vendor = vendor;
result.manufacturer = manufacturer; result.manufacturer = manufacturer;
result.maxPower = util.getValue(lines, 'MaxPower', ' ', true); result.maxPower = util.getValue(lines, 'MaxPower', ' ', true);
result.serialNumber = null; result.serialNumber = null;
return result; return result;
} }
// bus // bus
// deviceId // deviceId
// id // id
// name(product) // name(product)
// type(bInterfaceClass) // type(bInterfaceClass)
// removable / hotplug // removable / hotplug
// vendor // vendor
// manufacturer // manufacturer
// maxpower(linux) // maxpower(linux)
function getDarwinUsbType(name) { function getDarwinUsbType(name) {
let result = ''; let result = '';
if (name.indexOf('camera') >= 0) { result = 'Camera'; } if (name.indexOf('camera') >= 0) { result = 'Camera'; }
else if (name.indexOf('touch bar') >= 0) { result = 'Touch Bar'; } else if (name.indexOf('touch bar') >= 0) { result = 'Touch Bar'; }
else if (name.indexOf('controller') >= 0) { result = 'Controller'; } else if (name.indexOf('controller') >= 0) { result = 'Controller'; }
else if (name.indexOf('headset') >= 0) { result = 'Audio'; } else if (name.indexOf('headset') >= 0) { result = 'Audio'; }
else if (name.indexOf('keyboard') >= 0) { result = 'Keyboard'; } else if (name.indexOf('keyboard') >= 0) { result = 'Keyboard'; }
else if (name.indexOf('trackpad') >= 0) { result = 'Trackpad'; } else if (name.indexOf('trackpad') >= 0) { result = 'Trackpad'; }
else if (name.indexOf('sensor') >= 0) { result = 'Sensor'; } else if (name.indexOf('sensor') >= 0) { result = 'Sensor'; }
else if (name.indexOf('bthusb') >= 0) { result = 'Bluetooth'; } else if (name.indexOf('bthusb') >= 0) { result = 'Bluetooth'; }
else if (name.indexOf('bth') >= 0) { result = 'Bluetooth'; } else if (name.indexOf('bth') >= 0) { result = 'Bluetooth'; }
else if (name.indexOf('rfcomm') >= 0) { result = 'Bluetooth'; } else if (name.indexOf('rfcomm') >= 0) { result = 'Bluetooth'; }
else if (name.indexOf('usbhub') >= 0) { result = 'Hub'; } else if (name.indexOf('usbhub') >= 0) { result = 'Hub'; }
else if (name.indexOf(' hub') >= 0) { result = 'Hub'; } else if (name.indexOf(' hub') >= 0) { result = 'Hub'; }
else if (name.indexOf('mouse') >= 0) { result = 'Mouse'; } else if (name.indexOf('mouse') >= 0) { result = 'Mouse'; }
else if (name.indexOf('mic') >= 0) { result = 'Microphone'; } else if (name.indexOf('mic') >= 0) { result = 'Microphone'; }
else if (name.indexOf('removable') >= 0) { result = 'Storage'; } else if (name.indexOf('removable') >= 0) { result = 'Storage'; }
return result; return result;
} }
function parseDarwinUsb(usb, id) { function parseDarwinUsb(usb, id) {
const result = {}; const result = {};
result.id = id; result.id = id;
usb = usb.replace(/ \|/g, ''); usb = usb.replace(/ \|/g, '');
usb = usb.trim(); usb = usb.trim();
let lines = usb.split('\n'); let lines = usb.split('\n');
lines.shift(); lines.shift();
try { try {
for (let i = 0; i < lines.length; i++) { for (let i = 0; i < lines.length; i++) {
lines[i] = lines[i].trim(); lines[i] = lines[i].trim();
lines[i] = lines[i].replace(/=/g, ':'); lines[i] = lines[i].replace(/=/g, ':');
if (lines[i] !== '{' && lines[i] !== '}' && lines[i + 1] && lines[i + 1].trim() !== '}') { if (lines[i] !== '{' && lines[i] !== '}' && lines[i + 1] && lines[i + 1].trim() !== '}') {
lines[i] = lines[i] + ','; lines[i] = lines[i] + ',';
} }
lines[i] = lines[i].replace(': Yes,', ': "Yes",'); lines[i] = lines[i].replace(': Yes,', ': "Yes",');
lines[i] = lines[i].replace(': No,', ': "No",'); lines[i] = lines[i].replace(': No,', ': "No",');
} }
const usbObj = JSON.parse(lines.join('\n')); const usbObj = JSON.parse(lines.join('\n'));
const removableDrive = usbObj['Built-In'].toLowerCase() !== 'yes' && usbObj['non-removable'].toLowerCase() === 'no'; const removableDrive = usbObj['Built-In'].toLowerCase() !== 'yes' && usbObj['non-removable'].toLowerCase() === 'no';
result.bus = null; result.bus = null;
result.deviceId = null; result.deviceId = null;
result.id = usbObj['USB Address'] || null; result.id = usbObj['USB Address'] || null;
result.name = usbObj['kUSBProductString'] || usbObj['USB Product Name'] || null; result.name = usbObj['kUSBProductString'] || usbObj['USB Product Name'] || null;
result.type = getDarwinUsbType((usbObj['kUSBProductString'] || usbObj['USB Product Name'] || '').toLowerCase() + (removableDrive ? ' removable' : '')); result.type = getDarwinUsbType((usbObj['kUSBProductString'] || usbObj['USB Product Name'] || '').toLowerCase() + (removableDrive ? ' removable' : ''));
result.removable = usbObj['non-removable'].toLowerCase() === 'no'; result.removable = usbObj['non-removable'].toLowerCase() === 'no';
result.vendor = usbObj['kUSBVendorString'] || usbObj['USB Vendor Name'] || null; result.vendor = usbObj['kUSBVendorString'] || usbObj['USB Vendor Name'] || null;
result.manufacturer = usbObj['kUSBVendorString'] || usbObj['USB Vendor Name'] || null; result.manufacturer = usbObj['kUSBVendorString'] || usbObj['USB Vendor Name'] || null;
result.maxPower = null; result.maxPower = null;
result.serialNumber = usbObj['kUSBSerialNumberString'] || null; result.serialNumber = usbObj['kUSBSerialNumberString'] || null;
if (result.name) { if (result.name) {
return result; return result;
} else { } else {
return null; return null;
} }
} catch (e) { } catch (e) {
return null; return null;
} }
} }
// function getWindowsUsbType(service) { // function getWindowsUsbType(service) {
// let result = '' // let result = ''
// if (service.indexOf('usbhub3') >= 0) { result = 'Hub'; } // if (service.indexOf('usbhub3') >= 0) { result = 'Hub'; }
// else if (service.indexOf('usbstor') >= 0) { result = 'Storage'; } // else if (service.indexOf('usbstor') >= 0) { result = 'Storage'; }
// else if (service.indexOf('hidusb') >= 0) { result = 'Input'; } // else if (service.indexOf('hidusb') >= 0) { result = 'Input'; }
// else if (service.indexOf('usbccgp') >= 0) { result = 'Controller'; } // else if (service.indexOf('usbccgp') >= 0) { result = 'Controller'; }
// else if (service.indexOf('usbxhci') >= 0) { result = 'Controller'; } // else if (service.indexOf('usbxhci') >= 0) { result = 'Controller'; }
// else if (service.indexOf('usbehci') >= 0) { result = 'Controller'; } // else if (service.indexOf('usbehci') >= 0) { result = 'Controller'; }
// else if (service.indexOf('kbdhid') >= 0) { result = 'Keyboard'; } // else if (service.indexOf('kbdhid') >= 0) { result = 'Keyboard'; }
// else if (service.indexOf('keyboard') >= 0) { result = 'Keyboard'; } // else if (service.indexOf('keyboard') >= 0) { result = 'Keyboard'; }
// else if (service.indexOf('pointing') >= 0) { result = 'Mouse'; } // else if (service.indexOf('pointing') >= 0) { result = 'Mouse'; }
// else if (service.indexOf('disk') >= 0) { result = 'Storage'; } // else if (service.indexOf('disk') >= 0) { result = 'Storage'; }
// else if (service.indexOf('usbhub') >= 0) { result = 'Hub'; } // else if (service.indexOf('usbhub') >= 0) { result = 'Hub'; }
// else if (service.indexOf('bthusb') >= 0) { result = ''; } // else if (service.indexOf('bthusb') >= 0) { result = ''; }
// else if (service.indexOf('bth') >= 0) { result = ''; } // else if (service.indexOf('bth') >= 0) { result = ''; }
// else if (service.indexOf('rfcomm') >= 0) { result = ''; } // else if (service.indexOf('rfcomm') >= 0) { result = ''; }
// return result; // return result;
// } // }
function getWindowsUsbTypeCreation(creationclass, name) { function getWindowsUsbTypeCreation(creationclass, name) {
let result = ''; let result = '';
if (name.indexOf('storage') >= 0) { result = 'Storage'; } if (name.indexOf('storage') >= 0) { result = 'Storage'; }
else if (name.indexOf('speicher') >= 0) { result = 'Storage'; } else if (name.indexOf('speicher') >= 0) { result = 'Storage'; }
else if (creationclass.indexOf('usbhub') >= 0) { result = 'Hub'; } else if (creationclass.indexOf('usbhub') >= 0) { result = 'Hub'; }
else if (creationclass.indexOf('storage') >= 0) { result = 'Storage'; } else if (creationclass.indexOf('storage') >= 0) { result = 'Storage'; }
else if (creationclass.indexOf('usbcontroller') >= 0) { result = 'Controller'; } else if (creationclass.indexOf('usbcontroller') >= 0) { result = 'Controller'; }
else if (creationclass.indexOf('keyboard') >= 0) { result = 'Keyboard'; } else if (creationclass.indexOf('keyboard') >= 0) { result = 'Keyboard'; }
else if (creationclass.indexOf('pointing') >= 0) { result = 'Mouse'; } else if (creationclass.indexOf('pointing') >= 0) { result = 'Mouse'; }
else if (creationclass.indexOf('disk') >= 0) { result = 'Storage'; } else if (creationclass.indexOf('disk') >= 0) { result = 'Storage'; }
return result; return result;
} }
function parseWindowsUsb(lines, id) { function parseWindowsUsb(lines, id) {
const usbType = getWindowsUsbTypeCreation(util.getValue(lines, 'CreationClassName', '=').toLowerCase(), util.getValue(lines, 'name', '=').toLowerCase()); const usbType = getWindowsUsbTypeCreation(util.getValue(lines, 'CreationClassName', ':').toLowerCase(), util.getValue(lines, 'name', ':').toLowerCase());
if (usbType) { if (usbType) {
const result = {}; const result = {};
result.bus = null; result.bus = null;
result.deviceId = util.getValue(lines, 'deviceid', '='); result.deviceId = util.getValue(lines, 'deviceid', ':');
result.id = id; result.id = id;
result.name = util.getValue(lines, 'name', '='); result.name = util.getValue(lines, 'name', ':');
result.type = usbType; result.type = usbType;
result.removable = null; result.removable = null;
result.vendor = null; result.vendor = null;
result.manufacturer = util.getValue(lines, 'Manufacturer', '='); result.manufacturer = util.getValue(lines, 'Manufacturer', ':');
result.maxPower = null; result.maxPower = null;
result.serialNumber = null; result.serialNumber = null;
return result; return result;
} else { } else {
return null; return null;
} }
} }
function usb(callback) { function usb(callback) {
return new Promise((resolve) => { return new Promise((resolve) => {
process.nextTick(() => { process.nextTick(() => {
let result = []; let result = [];
if (_linux) { if (_linux) {
const cmd = 'export LC_ALL=C; lsusb -v 2>/dev/null; unset LC_ALL'; const cmd = 'export LC_ALL=C; lsusb -v 2>/dev/null; unset LC_ALL';
exec(cmd, { maxBuffer: 1024 * 1024 * 128 }, function (error, stdout) { exec(cmd, { maxBuffer: 1024 * 1024 * 128 }, function (error, stdout) {
if (!error) { if (!error) {
const parts = ('\n\n' + stdout.toString()).split('\n\nBus '); const parts = ('\n\n' + stdout.toString()).split('\n\nBus ');
for (let i = 1; i < parts.length; i++) { for (let i = 1; i < parts.length; i++) {
const usb = parseLinuxUsb(parts[i]); const usb = parseLinuxUsb(parts[i]);
result.push(usb); result.push(usb);
} }
} }
if (callback) { if (callback) {
callback(result); callback(result);
} }
resolve(result); resolve(result);
}); });
} }
if (_darwin) { if (_darwin) {
let cmd = 'ioreg -p IOUSB -c AppleUSBRootHubDevice -w0 -l'; let cmd = 'ioreg -p IOUSB -c AppleUSBRootHubDevice -w0 -l';
exec(cmd, { maxBuffer: 1024 * 1024 * 128 }, function (error, stdout) { exec(cmd, { maxBuffer: 1024 * 1024 * 128 }, function (error, stdout) {
if (!error) { if (!error) {
const parts = (stdout.toString()).split(' +-o '); const parts = (stdout.toString()).split(' +-o ');
for (let i = 1; i < parts.length; i++) { for (let i = 1; i < parts.length; i++) {
const usb = parseDarwinUsb(parts[i]); const usb = parseDarwinUsb(parts[i]);
if (usb) { if (usb) {
result.push(usb); result.push(usb);
} }
} }
if (callback) { if (callback) {
callback(result); callback(result);
} }
resolve(result); resolve(result);
} }
if (callback) { if (callback) {
callback(result); callback(result);
} }
resolve(result); resolve(result);
}); });
} }
if (_windows) { if (_windows) {
util.wmic('Path CIM_LogicalDevice where "Description like \'USB%\'" get /value').then((stdout, error) => { util.powerShell('Get-WmiObject CIM_LogicalDevice | where { $_.Description -match "^USB"}').then((stdout, error) => {
if (!error) { if (!error) {
const parts = stdout.toString().split(/\n\s*\n/); const parts = stdout.toString().split(/\n\s*\n/);
for (let i = 0; i < parts.length; i++) { for (let i = 0; i < parts.length; i++) {
const usb = parseWindowsUsb(parts[i].split('\n'), i); const usb = parseWindowsUsb(parts[i].split('\n'), i);
if (usb) { if (usb) {
result.push(usb); result.push(usb);
} }
} }
} }
if (callback) { if (callback) {
callback(result); callback(result);
} }
resolve(result); resolve(result);
}); });
// util.powerShell("gwmi Win32_USBControllerDevice |\%{[wmi]($_.Dependent)}").then(data => { // util.powerShell("gwmi Win32_USBControllerDevice |\%{[wmi]($_.Dependent)}").then(data => {
// const parts = data.toString().split(/\n\s*\n/); // const parts = data.toString().split(/\n\s*\n/);
// for (let i = 0; i < parts.length; i++) { // for (let i = 0; i < parts.length; i++) {
// const usb = parseWindowsUsb(parts[i].split('\n'), i) // const usb = parseWindowsUsb(parts[i].split('\n'), i)
// if (usb) { // if (usb) {
// result.push(usb) // result.push(usb)
// } // }
// } // }
// if (callback) { // if (callback) {
// callback(result); // callback(result);
// } // }
// resolve(result); // resolve(result);
// }); // });
} }
if (_sunos || _freebsd || _openbsd || _netbsd) { if (_sunos || _freebsd || _openbsd || _netbsd) {
resolve(null); resolve(null);
} }
}); });
}); });
} }
exports.usb = usb; exports.usb = usb;

View File

@ -26,43 +26,43 @@ const _openbsd = (_platform === 'openbsd');
const _netbsd = (_platform === 'netbsd'); const _netbsd = (_platform === 'netbsd');
const _sunos = (_platform === 'sunos'); const _sunos = (_platform === 'sunos');
let _winDateFormat = { // let _winDateFormat = {
dateFormat: '', // dateFormat: '',
dateSeperator: '', // dateSeperator: '',
timeFormat: '', // timeFormat: '',
timeSeperator: '', // timeSeperator: '',
amDesignator: '', // amDesignator: '',
pmDesignator: '' // pmDesignator: ''
}; // };
// -------------------------- // --------------------------
// array of users online = sessions // array of users online = sessions
function getWinCulture() { // function getWinCulture() {
return new Promise((resolve) => { // return new Promise((resolve) => {
process.nextTick(() => { // process.nextTick(() => {
if (!_winDateFormat.dateFormat) { // if (!_winDateFormat.dateFormat) {
util.powerShell('(get-culture).DateTimeFormat') // util.powerShell('(get-culture).DateTimeFormat')
.then(data => { // .then(data => {
let lines = data.toString().split('\r\n'); // let lines = data.toString().split('\r\n');
_winDateFormat.dateFormat = util.getValue(lines, 'ShortDatePattern', ':'); // _winDateFormat.dateFormat = util.getValue(lines, 'ShortDatePattern', ':');
_winDateFormat.dateSeperator = util.getValue(lines, 'DateSeparator', ':'); // _winDateFormat.dateSeperator = util.getValue(lines, 'DateSeparator', ':');
_winDateFormat.timeFormat = util.getValue(lines, 'ShortTimePattern', ':'); // _winDateFormat.timeFormat = util.getValue(lines, 'ShortTimePattern', ':');
_winDateFormat.timeSeperator = util.getValue(lines, 'TimeSeparator', ':'); // _winDateFormat.timeSeperator = util.getValue(lines, 'TimeSeparator', ':');
_winDateFormat.amDesignator = util.getValue(lines, 'AMDesignator', ':'); // _winDateFormat.amDesignator = util.getValue(lines, 'AMDesignator', ':');
_winDateFormat.pmDesignator = util.getValue(lines, 'PMDesignator', ':'); // _winDateFormat.pmDesignator = util.getValue(lines, 'PMDesignator', ':');
resolve(_winDateFormat); // resolve(_winDateFormat);
}) // })
.catch(() => { // .catch(() => {
resolve(_winDateFormat); // resolve(_winDateFormat);
}); // });
} else { // } else {
resolve(_winDateFormat); // resolve(_winDateFormat);
} // }
}); // });
}); // });
} // }
function parseUsersLinux(lines, phase) { function parseUsersLinux(lines, phase) {
let result = []; let result = [];
@ -176,43 +176,43 @@ function parseUsersDarwin(lines) {
return result; return result;
} }
function parseUsersWin(lines, culture) { // function parseUsersWin(lines, culture) {
let result = []; // let result = [];
const header = lines[0]; // const header = lines[0];
const headerDelimiter = []; // const headerDelimiter = [];
if (header) { // if (header) {
const start = (header[0] === ' ') ? 1 : 0; // const start = (header[0] === ' ') ? 1 : 0;
headerDelimiter.push(start - 1); // headerDelimiter.push(start - 1);
let nextSpace = 0; // let nextSpace = 0;
for (let i = start + 1; i < header.length; i++) { // for (let i = start + 1; i < header.length; i++) {
if (header[i] === ' ' && ((header[i - 1] === ' ') || (header[i - 1] === '.'))) { // if (header[i] === ' ' && ((header[i - 1] === ' ') || (header[i - 1] === '.'))) {
nextSpace = i; // nextSpace = i;
} else { // } else {
if (nextSpace) { // if (nextSpace) {
headerDelimiter.push(nextSpace); // headerDelimiter.push(nextSpace);
nextSpace = 0; // nextSpace = 0;
} // }
} // }
} // }
for (let i = 1; i < lines.length; i++) { // for (let i = 1; i < lines.length; i++) {
if (lines[i].trim()) { // if (lines[i].trim()) {
const user = lines[i].substring(headerDelimiter[0] + 1, headerDelimiter[1]).trim() || ''; // const user = lines[i].substring(headerDelimiter[0] + 1, headerDelimiter[1]).trim() || '';
const tty = lines[i].substring(headerDelimiter[1] + 1, headerDelimiter[2] - 2).trim() || ''; // const tty = lines[i].substring(headerDelimiter[1] + 1, headerDelimiter[2] - 2).trim() || '';
const dateTime = util.parseDateTime(lines[i].substring(headerDelimiter[5] + 1, 2000).trim(), culture) || ''; // const dateTime = util.parseDateTime(lines[i].substring(headerDelimiter[5] + 1, 2000).trim(), culture) || '';
result.push({ // result.push({
user: user, // user: user,
tty: tty, // tty: tty,
date: dateTime.date, // date: dateTime.date,
time: dateTime.time, // time: dateTime.time,
ip: '', // ip: '',
command: '' // command: ''
}); // });
} // }
} // }
} // }
return result; // return result;
} // }
function users(callback) { function users(callback) {
@ -283,21 +283,62 @@ function users(callback) {
} }
if (_windows) { if (_windows) {
try { try {
util.powerShell('query user').then(stdout => { const workload = [];
if (stdout) { // workload.push(util.powerShell('Get-CimInstance -ClassName Win32_Account | fl *'));
// lines / split workload.push(util.powerShell('Get-WmiObject Win32_LogonSession | fl *'));
let lines = stdout.toString().split('\r\n'); workload.push(util.powerShell('Get-WmiObject Win32_LoggedOnUser | fl *'));
getWinCulture() workload.push(util.powerShell('Get-WmiObject Win32_Process -Filter "name=\'explorer.exe\'" | Select @{Name="domain";Expression={$_.GetOwner().Domain}}, @{Name="username";Expression={$_.GetOwner().User}} | fl'));
.then(culture => { Promise.all(
result = parseUsersWin(lines, culture); workload
if (callback) { callback(result); } ).then(data => {
resolve(result); // controller + vram
}); // let accounts = parseWinAccounts(data[0].split(/\n\s*\n/));
} else { let sessions = parseWinSessions(data[0].split(/\n\s*\n/));
if (callback) { callback(result); } let loggedons = parseWinLoggedOn(data[1].split(/\n\s*\n/));
resolve(result); let users = parseWinUsers(data[2].split(/\n\s*\n/));
for (let id in loggedons) {
if ({}.hasOwnProperty.call(loggedons, id)) {
loggedons[id].dateTime = {}.hasOwnProperty.call(sessions, id) ? sessions[id] : '';
}
} }
users.forEach(user => {
let dateTime = '';
for (let id in loggedons) {
if ({}.hasOwnProperty.call(loggedons, id)) {
if (loggedons[id].user === user.user && (!dateTime || dateTime < loggedons[id].dateTime)) {
dateTime = loggedons[id].dateTime;
}
}
}
result.push({
user: user.user,
tty: '',
date: `${dateTime.substr(0, 4)}-${dateTime.substr(4, 2)}-${dateTime.substr(6, 2)}`,
time: `${dateTime.substr(8, 2)}:${dateTime.substr(10, 2)}`,
ip: '',
command: ''
});
});
if (callback) { callback(result); }
resolve(result);
}); });
// util.powerShell('query user').then(stdout => {
// if (stdout) {
// // lines / split
// let lines = stdout.toString().split('\r\n');
// getWinCulture()
// .then(culture => {
// result = parseUsersWin(lines, culture);
// if (callback) { callback(result); }
// resolve(result);
// });
// } else {
// if (callback) { callback(result); }
// resolve(result);
// }
// });
} catch (e) { } catch (e) {
if (callback) { callback(result); } if (callback) { callback(result); }
resolve(result); resolve(result);
@ -308,4 +349,69 @@ function users(callback) {
}); });
} }
// function parseWinAccounts(accountParts) {
// const accounts = [];
// accountParts.forEach(account => {
// const lines = account.split('\r\n');
// const name = util.getValue(lines, 'name', ':', true);
// const domain = util.getValue(lines, 'domain', ':', true);
// accounts.push(`${domain}\${name}`);
// });
// return accounts;
// }
function parseWinSessions(sessionParts) {
const sessions = {};
sessionParts.forEach(session => {
const lines = session.split('\r\n');
const id = util.getValue(lines, 'LogonId');
const starttime = util.getValue(lines, 'starttime');
if (id) {
sessions[id] = starttime;
}
});
return sessions;
}
function parseWinUsers(userParts) {
const users = [];
userParts.forEach(user => {
const lines = user.split('\r\n');
const domain = util.getValue(lines, 'domain', ':', true);
const username = util.getValue(lines, 'username', ':', true);
if (username) {
users.push({
domain,
user: username
});
}
});
return users;
}
function parseWinLoggedOn(loggedonParts) {
const loggedons = {};
loggedonParts.forEach(loggedon => {
const lines = loggedon.split('\r\n');
const antecendent = util.getValue(lines, 'antecedent', ':', true);
let parts = antecendent.split(',');
const domainParts = parts.length > 1 ? parts[0].split('=') : [];
const nameParts = parts.length > 1 ? parts[1].split('=') : [];
const domain = domainParts.length > 1 ? domainParts[1].replace(/"/g, '') : '';
const name = nameParts.length > 1 ? nameParts[1].replace(/"/g, '') : '';
const dependent = util.getValue(lines, 'dependent', ':', true);
parts = dependent.split('=');
const id = parts.length > 1 ? parts[1].replace(/"/g, '') : '';
if (id) {
loggedons[id] = {
domain,
user: name
};
}
});
return loggedons;
}
exports.users = users; exports.users = users;