├── index.js ├── package.json ├── .gitignore ├── test └── unit │ ├── system.temperature.test.js │ ├── system.voltage.test.js │ ├── perf.test.js │ ├── wifi.test.js │ └── system.configuration.test.js ├── lib ├── perf.js ├── system.js └── wifi.js ├── README.md └── documentation.md /index.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | wifi: require('./lib/wifi'), 3 | system: require('./lib/system'), 4 | perf: require('./lib/perf'), 5 | rpio: require('rpio'), 6 | }; -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "pi-utils", 3 | "version": "0.1.7", 4 | "description": "Raspberry Pi Utility Functions / WiFi Management", 5 | "main": "index.js", 6 | "scripts": { 7 | "test": "mocha test --recursive" 8 | }, 9 | "author": "grojo, inc.", 10 | "repository": { 11 | "type": "git", 12 | "url": "git://github.com/hellogrojo/pi-utils.git" 13 | }, 14 | "keywords": [ 15 | "pi", 16 | "raspberry pi", 17 | "rpi", 18 | "gpio", 19 | "i2c", 20 | "spi", 21 | "wifi", 22 | "wireless", 23 | "wlan" 24 | ], 25 | "license": "ISC", 26 | "dependencies": { 27 | "is-online": "^6.0.1", 28 | "promise-retry": "^1.1.1", 29 | "rpio": "^0.9.14" 30 | }, 31 | "devDependencies": { 32 | "chai": "^3.5.0", 33 | "mocha": "^3.2.0", 34 | "sinon": "^1.17.7" 35 | } 36 | } 37 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # Logs 2 | logs 3 | *.log 4 | npm-debug.log* 5 | 6 | # Runtime data 7 | pids 8 | *.pid 9 | *.seed 10 | *.pid.lock 11 | 12 | # Directory for instrumented libs generated by jscoverage/JSCover 13 | lib-cov 14 | 15 | # Coverage directory used by tools like istanbul 16 | coverage 17 | 18 | # nyc test coverage 19 | .nyc_output 20 | 21 | # Grunt intermediate storage (http://gruntjs.com/creating-plugins#storing-task-files) 22 | .grunt 23 | 24 | # node-waf configuration 25 | .lock-wscript 26 | 27 | # Compiled binary addons (http://nodejs.org/api/addons.html) 28 | build/Release 29 | 30 | # Dependency directories 31 | node_modules 32 | jspm_packages 33 | 34 | # Optional npm cache directory 35 | .npm 36 | 37 | # Optional eslint cache 38 | .eslintcache 39 | 40 | # Optional REPL history 41 | .node_repl_history 42 | 43 | # Output of 'npm pack' 44 | *.tgz 45 | 46 | # Yarn Integrity file 47 | .yarn-integrity 48 | 49 | -------------------------------------------------------------------------------- /test/unit/system.temperature.test.js: -------------------------------------------------------------------------------- 1 | var chai = require('chai'); 2 | var expect = chai.expect; 3 | 4 | var util = require('../../index'); 5 | 6 | describe('Temperature', function() { 7 | 8 | describe('#cpuTemp', function() { 9 | 10 | it('CPU Temperature probe should return numeric value.', function() { 11 | expect(util.system.cpuTemp()).to.be.a('number'); 12 | }); 13 | 14 | it('CPU Temperature probe should return a positive number.', function() { 15 | expect(util.system.cpuTemp()).to.be.above(0); 16 | }); 17 | 18 | }); 19 | 20 | 21 | describe('#gpuTemp', function() { 22 | 23 | it('GPU Temperature probe should return numeric value.', function() { 24 | expect(util.system.cpuTemp()).to.be.a('number'); 25 | }); 26 | 27 | it('GPU Temperature probe should return a positive number.', function() { 28 | expect(util.system.gpuTemp()).to.be.above(0); 29 | }); 30 | 31 | }); 32 | 33 | }); 34 | 35 | -------------------------------------------------------------------------------- /test/unit/system.voltage.test.js: -------------------------------------------------------------------------------- 1 | var chai = require('chai'); 2 | var expect = chai.expect; 3 | 4 | var util = require('../../index'); 5 | 6 | describe('Voltage', function() { 7 | 8 | it('VCC readings should return all expected keys', function() { 9 | expect(util.system.vcc()).to.have.all.keys('core', 'sdram_c', 'sdram_i', 'sdram_p'); 10 | }); 11 | 12 | 13 | it('VCC readings should return all numeric values', function() { 14 | var vccVals = Object.values(util.system.vcc()); 15 | 16 | expect(vccVals).to.satisfy(function(vals) { 17 | return vals.every(function(val) { 18 | return (typeof(val) == 'number'); 19 | }); 20 | }); 21 | }); 22 | 23 | 24 | it('VCC readings should all be positive values', function() { 25 | var vccVals = Object.values(util.system.vcc()); 26 | 27 | expect(vccVals).to.satisfy(function(vals) { 28 | return vals.every(function(val) { 29 | return (val > 0); 30 | }); 31 | }); 32 | }); 33 | 34 | 35 | }); -------------------------------------------------------------------------------- /lib/perf.js: -------------------------------------------------------------------------------- 1 | var os = require('os'); 2 | var exec = require('child_process').exec; 3 | var execSync = require('child_process').execSync; 4 | 5 | var commands = { 6 | loadAvg: "cat /proc/loadavg | cut -d ' ' -f 1 | tr -d '\n'", 7 | diskStats: "/bin/df -k", 8 | } 9 | 10 | 11 | var perf = { 12 | 13 | /** 14 | * Get CPU load average 15 | * 16 | * @return {float} 17 | */ 18 | loadAverage: function() { 19 | return parseFloat(execSync(commands.loadAvg).toString()); 20 | }, 21 | 22 | /** 23 | * Get total memory available to OS 24 | * 25 | * @return {float} 26 | */ 27 | totalMemory: function() { 28 | return Math.round(os.totalmem() / 1024 / 1024); 29 | }, 30 | 31 | /** 32 | * Get free memory 33 | * 34 | * @return {float} 35 | */ 36 | freeMemory: function() { 37 | return Math.round(os.freemem() / 1024 / 1024); 38 | }, 39 | 40 | 41 | /** 42 | * Get total/free space on root mount 43 | * 44 | * @return {object} of float, values in MB 45 | * 46 | */ 47 | diskStats: function() { 48 | 49 | var df_stats = execSync(commands.diskStats).toString().split('\n'); 50 | var root_disk = df_stats[1].replace( /[\s\n\r]+/g,' ').split(' '); 51 | 52 | return { 53 | total: Math.round(root_disk[1] / 1024), 54 | used: Math.round(root_disk[2] / 1024), 55 | free: Math.round(root_disk[3] / 1024) 56 | } 57 | 58 | } 59 | 60 | } 61 | 62 | module.exports = perf; 63 | -------------------------------------------------------------------------------- /test/unit/perf.test.js: -------------------------------------------------------------------------------- 1 | var chai = require('chai'); 2 | var expect = chai.expect; 3 | 4 | var util = require('../../index'); 5 | 6 | describe('Perf Metrics', function() { 7 | 8 | describe('#loadAverage', function() { 9 | 10 | it('Load Average (1-min) should be >= 0.00', function() { 11 | expect(util.perf.loadAverage()).to.be.at.least(0); 12 | }); 13 | 14 | it('Load Average (1-min) should be a number', function() { 15 | expect(util.perf.loadAverage()).to.be.a('number'); 16 | }); 17 | 18 | }); 19 | 20 | describe('#totalMemory', function() { 21 | 22 | it('Total Memory should be a positive number', function() { 23 | expect(util.perf.totalMemory()).to.be.above(0); 24 | }); 25 | 26 | }); 27 | 28 | describe('#freeMemory', function() { 29 | 30 | it('Free Memory should be >= 0', function() { 31 | expect(util.perf.freeMemory()).to.be.at.least(0); 32 | }); 33 | 34 | }); 35 | 36 | describe('#diskStats', function() { 37 | 38 | it('Disk stats object should contain values for total/free/used', function() { 39 | expect(util.perf.diskStats()).to.have.all.keys('total', 'free', 'used'); 40 | }); 41 | 42 | it('Disk stats values should all be >= 0', function() { 43 | 44 | var diskVals = Object.values(util.perf.diskStats()); 45 | 46 | expect(diskVals).to.satisfy(function(vals) { 47 | return vals.every(function(val) { 48 | return (val >= 0); 49 | }); 50 | }); 51 | 52 | }); 53 | 54 | }); 55 | 56 | }); -------------------------------------------------------------------------------- /test/unit/wifi.test.js: -------------------------------------------------------------------------------- 1 | var chai = require('chai'); 2 | var expect = chai.expect; 3 | 4 | var util = require('../../index'); 5 | 6 | /* 7 | * These tests are non-invasive and don't require adapter to be connected. 8 | * We could perform other tests but would basically involve stubbing out 9 | * the majority of the functionality. 10 | */ 11 | 12 | describe('WiFi', function() { 13 | 14 | describe('#parseIwlist', function() { 15 | 16 | it('Should parse iwlist scan output and return object', function() { 17 | 18 | var sampleSSID = 'my-network'; 19 | var fakeNetwork = ` 20 | wlan0 Scan completed : 21 | Cell 01 - Address: 00:00:00:00:00:00 22 | Channel:1 23 | Frequency:2.412 GHz (Channel 1) 24 | Quality=53/70 Signal level=-85 dBm 25 | Encryption key:on 26 | ESSID:"my-network" 27 | IE: IEEE 802.11i/WPA2 Version 1 28 | Group Cipher : CCMP 29 | Pairwise Ciphers (1) : CCMP 30 | Authentication Suites (1) : PSK`; 31 | 32 | var networks = util.wifi.parseIwlist(fakeNetwork, sampleSSID); 33 | expect( networks ).to.be.a('object'); 34 | expect( networks[sampleSSID] ).to.have.property('current'); 35 | 36 | }); 37 | 38 | }); 39 | 40 | describe('#getMacAddress', function() { 41 | 42 | it('Should return valid MAC address from wlan0 adapter', function() { 43 | var mac = util.wifi.getMacAddress(); 44 | expect( mac ).to.match(/^([0-9A-F]{2}[:-]){5}([0-9A-F]{2})$/i); 45 | }) 46 | }) 47 | 48 | }); 49 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 |

2 | Grojo logo 3 |

4 | 5 | [![Twitter Follow](https://img.shields.io/twitter/follow/hellogrojo.svg?style=social&maxAge=3600)](https://twitter.com/hellogrojo) 6 | 7 | 8 | # pi-utils 9 | 10 | A collection of utilities for developing on the Raspberry Pi, including various system/os utilities, gpio functions, and WiFi management. Tested primarily on RPi3. 11 | 12 | ## Documentation   13 | [github](https://github.com/hellogrojo/pi-utils/blob/master/documentation.md) 14 | 15 | 16 | ## Installation   17 | **With [node](http://nodejs.org) [installed](http://nodejs.org/en/download):** 18 | ```sh 19 | # Get the latest release of pi-utils 20 | npm install --save pi-utils 21 | ``` 22 | 23 | This library depends on and provides a wrapper to the excellent [rpio](https://github.com/jperkin/node-rpio) library as well, which requires elevated permissions to access gpio functions. In order to run scripts without sudo, try the following: 24 | 25 | ```sh 26 | # Add user to gpio group 27 | sudo usermod -a -G gpio 28 | 29 | # configure udev rules 30 | sudo sh -c 'cat >/etc/udev/rules.d/20-gpiomem.rules < 40 | ## Support / Issues / Feedback 41 | 42 | Need help, have feedback, or need a question answered? We'd love to hear from you. Please [email us](mailto:hello@hellogrojo.com). 43 | 44 |
45 | ## Links 46 | - [Website](http://hellogrojo.com/) 47 | - [Twitter](https://twitter.com/hellogrojo) 48 | - [Facebook](https://www.facebook.com/hellogrojo) 49 | 50 |
51 | ## Team 52 | [Grojo](http://hellogrojo.com) is a small team of engineers and geek gardeners in Maine that are building a community around open source gardening. Our core team consists of: 53 | 54 | 55 | Aaron Hastings | Jared Pinkham | Brandon Bergman 56 | :---:|:---:|:---: 57 | Aaron Hastings | Jared Pinkham | Brandon Bergman 58 | 59 |
60 | ## License 61 | ISC License Copyright © 2016-2017 grojo, inc. 62 | 63 | Permission to use, copy, modify, and/or distribute this software for any purpose with or without fee is hereby granted, provided that the above copyright notice and this permission notice appear in all copies. 64 | 65 | THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 66 | 67 | Source: http://opensource.org/licenses/ISC -------------------------------------------------------------------------------- /test/unit/system.configuration.test.js: -------------------------------------------------------------------------------- 1 | var chai = require('chai'); 2 | var expect = chai.expect; 3 | 4 | var util = require('../../index'); 5 | 6 | describe('System Configuration', function() { 7 | 8 | describe('#uptime', function() { 9 | 10 | it('System uptime should return positive integer value', function() { 11 | expect(util.system.uptime()).to.be.above(0); 12 | }); 13 | 14 | }) 15 | 16 | describe('#serial', function() { 17 | 18 | it('System Serial Number should return valid 16-char hex string', function() { 19 | 20 | expect(util.system.serial()).to.match(/^([A-Fa-f0-9]{2}){8}$/); 21 | 22 | }); 23 | 24 | }); 25 | 26 | describe('#hardwareRevision', function() { 27 | 28 | it('Board revision code should be present in pre-defined list.', function() { 29 | 30 | revision_codes = Object.keys(util.system.board_revisions); 31 | expect( revision_codes ).to.contain.members([ util.system.hardwareRevision().code ]); 32 | 33 | }); 34 | 35 | }); 36 | 37 | describe('#cameraInfo', function() { 38 | 39 | it('Camera config object should be returned with supported/detected config keys present.', function() { 40 | 41 | expect(util.system.cameraInfo()).to.have.all.keys('supported', 'detected'); 42 | 43 | }); 44 | 45 | }); 46 | 47 | describe('#memoryConfig', function() { 48 | 49 | it('Memory config split object should be returned with arm/gpu config keys present.', function() { 50 | 51 | expect(util.system.memoryConfig()).to.have.all.keys('arm', 'gpu'); 52 | 53 | }); 54 | 55 | }); 56 | 57 | 58 | describe('#configData', function() { 59 | 60 | it('System configuration readings should return all numeric values', function() { 61 | var configVals = Object.values(util.system.configData()); 62 | 63 | expect(configVals).to.satisfy(function(vals) { 64 | return vals.every(function(val) { 65 | return (typeof(val) == 'number'); 66 | }); 67 | }); 68 | }); 69 | 70 | }); 71 | 72 | describe('#kernel', function() { 73 | 74 | it('Kernel should return valid string starting containing \'Linux\'', function() { 75 | expect(util.system.kernel()).to.have.string('Linux'); 76 | 77 | }); 78 | 79 | }); 80 | 81 | describe('#firmware', function() { 82 | 83 | it('Firmware version should return a valid 40-char hex string', function() { 84 | expect(util.system.firmware()).to.match(/^([A-Fa-f0-9]{2}){20}$/); 85 | 86 | }); 87 | 88 | }); 89 | 90 | describe('#clockSpeed', function() { 91 | 92 | it('Clock speed object should return three expected keys: arm, core, uart', function() { 93 | expect(util.system.clockSpeed()).to.have.all.keys('arm', 'core', 'uart'); 94 | }); 95 | 96 | 97 | it('Clock speed object should return numeric values for all keys', function() { 98 | var clockVals = Object.values(util.system.clockSpeed()); 99 | 100 | expect(clockVals).to.satisfy(function(vals) { 101 | return vals.every(function(val) { 102 | return (typeof(val) == 'number'); 103 | }); 104 | }); 105 | }); 106 | 107 | }); 108 | 109 | describe('#machineId', function() { 110 | 111 | it('Machine id should return a valid 32-char hex string', function() { 112 | expect(util.system.machineId()).to.match(/^([A-Fa-f0-9]{2}){16}$/); 113 | }); 114 | 115 | }); 116 | 117 | describe('#hostname', function() { 118 | 119 | it('Hostname should return valid string', function() { 120 | expect(util.system.hostname()).to.be.a('string'); 121 | }); 122 | 123 | it('Hostname should be at least 1 char long', function() { 124 | expect(util.system.hostname()).to.have.length.above(1); 125 | }) 126 | 127 | }); 128 | 129 | }); -------------------------------------------------------------------------------- /lib/system.js: -------------------------------------------------------------------------------- 1 | var os = require('os'); 2 | var exec = require('child_process').exec; 3 | var execSync = require('child_process').execSync; 4 | 5 | var commands = { 6 | cpuTemp: 'cat /sys/class/thermal/thermal_zone0/temp', 7 | gpuTemp: '/opt/vc/bin/vcgencmd measure_temp', 8 | vcc: '/opt/vc/bin/vcgencmd measure_volts ', 9 | getCamera: '/opt/vc/bin/vcgencmd get_camera', 10 | getSerial: "cat /proc/cpuinfo | grep Serial | cut -d ' ' -f 2 | tr -d '\n'", 11 | getRevision: "cat /proc/cpuinfo | grep Revision | cut -d ' ' -f 2 | tr -d '\n'", 12 | getMemory: '/opt/vc/bin/vcgencmd get_mem ', 13 | configInfo: '/opt/vc/bin/vcgencmd get_config int', 14 | kernel: '/bin/uname -a', 15 | firmware: "/opt/vc/bin/vcgencmd version | grep version | cut -d ' ' -f 2 | tr -d '\n'", 16 | machineId: "/usr/bin/hostnamectl | grep 'Machine ID:' | cut -d ':' -f 2 | tr -d ' \n'", 17 | hostname: "/bin/hostname | tr -d '\n'", 18 | clockSpeed: '/opt/vc/bin/vcgencmd measure_clock ', 19 | displayState: 'export DISPLAY=:0;/usr/bin/xset dpms force ', 20 | } 21 | 22 | 23 | var system = { 24 | 25 | /** 26 | * List of RPi revision codes and friendly names 27 | */ 28 | board_revisions: { 29 | '0002': 'Model B Rev. 1.0', 30 | '0003': 'Model B Rev. 1.0 + Fuses mod and D14 removed', 31 | '0004': 'Model B Rev. 2.0 256MB (Sony)', 32 | '0005': 'Model B Rev. 2.0 256MB (Qisda)', 33 | '0006': 'Model B Rev. 2.0 256MB (Egoman)', 34 | '0007': 'Model A Rev. 2.0 256MB (Egoman)', 35 | '0008': 'Model A Rev. 2.0 256MB (Sony)', 36 | '0009': 'Model A Rev. 2.0 256MB (Qisda)', 37 | '000d': 'Model B Rev. 2.0 512MB (Egoman)', 38 | '000e': 'Model B Rev. 2.0 512MB (Sony)', 39 | '000f': 'Model B Rev. 2.0 512MB (Qisda)', 40 | '0010': "Model B+ Rev. 1.0 512MB (Sony)", 41 | '0011': 'Compute Module Rev. 1.0 512MB (Sony)', 42 | '0012': 'Model A+ Rev. 1.1 256MB (Sony)', 43 | '0013': 'Model B+ Rev. 1.2 512MB', 44 | '0014': 'Compute Module Rev. 1.0 512MB (Embest)', 45 | '0015': 'Model A+ Rev. 1.1 256MB/512MB (Embest)', 46 | 'a01040': 'Pi 2 Model B Rev. 1.0 1GB', 47 | 'a01041': 'Pi 2 Model B Rev. 1.1 1GB (Sony)', 48 | 'a21041': 'Pi 2 Model B Rev. 1.1 1GB (Embest)', 49 | 'a22042': 'Pi 2 Model B Rev. 1.2 w/ BCM2837 1GB (Embest)', 50 | '900021': 'Model A+ Rev. 1.1 512MB', 51 | '900092': 'Pi Zero Rev. 1.2 512MB (Sony)', 52 | '900093': 'Pi Zero Rev. 1.3 512MB (Sony)', 53 | '920093': 'Pi Zero Rev. 1.3 512MB (Sony)', 54 | 'a02082': 'Pi 3 Model B Rev. 1.2 1GB (Sony)', 55 | 'a22082': 'Pi 3 Model B Rev. 1.2 1GB (Embest)' 56 | }, 57 | 58 | /** 59 | * Get CPU temp 60 | * 61 | * @param {boolean} fahrenheit - return in Fahrenheit 62 | * @return {float} 63 | */ 64 | cpuTemp: function(fahrenheit) { 65 | var cpuTempC = parseInt( execSync(commands.cpuTemp).toString() ) / 1000; 66 | 67 | if(fahrenheit) return (cpuTempC * 1.8) + 32.0; 68 | return cpuTempC; 69 | }, 70 | 71 | /** 72 | * Get GPU temp 73 | * 74 | * @param {boolean} fahrenheit - return in Fahrenheit 75 | * @return {float} 76 | */ 77 | gpuTemp: function(fahrenheit) { 78 | var gpuTemp = execSync(commands.gpuTemp).toString(); 79 | var gpuTempC = parseFloat( gpuTemp.substring(gpuTemp.lastIndexOf("=")+1, gpuTemp.lastIndexOf("'")) ); 80 | 81 | if(fahrenheit) return (gpuTempC * 1.8) + 32.0; 82 | return gpuTempC; 83 | }, 84 | 85 | /** 86 | * Get System Voltages 87 | * 88 | * @return {object} 89 | */ 90 | vcc: function () { 91 | var vcc = ['core', 'sdram_c', 'sdram_i', 'sdram_p']; 92 | var response = {}; 93 | 94 | for (var i = 0; i < vcc.length; i++) { 95 | response[vcc[i]] = parseFloat(execSync(commands.vcc + vcc[i]).toString().split('=')[1].trim().slice(0, -1)); 96 | } 97 | return response; 98 | }, 99 | 100 | /** 101 | * Get System Uptime 102 | * 103 | * @return {integer} 104 | */ 105 | uptime: function () { 106 | return os.uptime(); 107 | }, 108 | 109 | 110 | /** 111 | * Get Serial Number 112 | * 113 | * @return {string} 114 | */ 115 | serial: function () { 116 | return execSync(commands.getSerial).toString(); 117 | }, 118 | 119 | 120 | /** 121 | * Get Machine Id 122 | * 123 | * @return {string} 124 | */ 125 | machineId: function () { 126 | return execSync(commands.machineId).toString(); 127 | }, 128 | 129 | 130 | /** 131 | * Get hostname 132 | * 133 | * @return {string} 134 | */ 135 | hostname: function () { 136 | return execSync(commands.hostname).toString(); 137 | }, 138 | 139 | 140 | /** 141 | * Get Hardware Revision 142 | * 143 | * @return {string} 144 | */ 145 | hardwareRevision: function() { 146 | 147 | var revision = execSync(commands.getRevision).toString(); 148 | 149 | if(system.board_revisions[revision] === undefined) { 150 | return null; 151 | } 152 | 153 | return {'code': revision, 'name': system.board_revisions[revision]}; 154 | 155 | }, 156 | 157 | 158 | /** 159 | * Get Camera information (supported and detected) 160 | * 161 | * @return {object} 162 | */ 163 | cameraInfo: function() { 164 | 165 | var result = execSync(commands.getCamera).toString().trim().split(' '); 166 | var response = {}; 167 | 168 | for(var i = 0; i < result.length; i++) { 169 | var data = result[i].split('='); 170 | response[data[0]] = (data[1] === '1'); 171 | } 172 | 173 | return response; 174 | 175 | }, 176 | 177 | 178 | /** 179 | * Get configured memory split info (between ARM and GPU) 180 | * 181 | * @return {object} 182 | */ 183 | memoryConfig: function() { 184 | var types = ['arm', 'gpu']; 185 | var response = {}; 186 | 187 | for(var i = 0; i < types.length; i++) { 188 | response[types[i]] = execSync(commands.getMemory + types[i]).toString().trim().split('=')[1]; 189 | } 190 | 191 | return response; 192 | }, 193 | 194 | 195 | /** 196 | * Get various config settings from vcgencmd 197 | * 198 | * @return {object} 199 | */ 200 | configData: function() { 201 | 202 | var result = execSync(commands.configInfo).toString().trim().split('\n'); 203 | var response = {}; 204 | 205 | for(var i = 0; i < result.length; i++) { 206 | var data = result[i].split('='); 207 | response[data[0]] = parseInt(data[1]); 208 | } 209 | 210 | return response; 211 | 212 | }, 213 | 214 | /** 215 | * Get kernel version 216 | * 217 | * @return {string} 218 | */ 219 | kernel: function() { 220 | return execSync(commands.kernel).toString().trim(); 221 | }, 222 | 223 | /** 224 | * Get GPU firmware version 225 | * 226 | * @return {string} 227 | */ 228 | firmware: function() { 229 | return execSync(commands.firmware).toString().trim(); 230 | }, 231 | 232 | /** 233 | * Get ARM, Core, UART clock speeds 234 | * 235 | * @return {object} 236 | */ 237 | clockSpeed: function () { 238 | var clocks = ['core', 'arm', 'uart']; 239 | var response = {}; 240 | 241 | for (var i = 0; i < clocks.length; i++) { 242 | response[clocks[i]] = parseFloat(execSync(commands.clockSpeed + clocks[i]).toString().split('=')[1].trim().slice(0, -1)); 243 | } 244 | return response; 245 | }, 246 | 247 | /** 248 | * Turn on/off official LCD (may work for other displays, not tested 249 | * 250 | * @param {boolean} enable - turn on (true), or off (false) 251 | */ 252 | displayState: function(enable) { 253 | var state = (enable) ? 'on' : 'off'; 254 | execSync(commands.displayState + state).toString(); 255 | } 256 | 257 | } 258 | 259 | module.exports = system; 260 | -------------------------------------------------------------------------------- /lib/wifi.js: -------------------------------------------------------------------------------- 1 | const exec = require('child_process').exec; 2 | const execSync = require('child_process').execSync; 3 | const promiseRetry = require('promise-retry'); 4 | 5 | const WLAN = 'wlan0'; 6 | const NET_ID = 0; 7 | const MAX_CONNECT_RETRIES = 1; 8 | 9 | const ERR_CONNECT = 'Could not connect to network.'; 10 | const ERR_START = 'Could not start wifi adapter.'; 11 | const ERR_STOP = 'Could not stop wifi adapter.'; 12 | const ERR_DHCP = 'Could not renew DHCP lease.'; 13 | const ERR_MAX_RETRIES = 'Could not start wifi adapter - Max retries exceeded.'; 14 | const ERR_HANDSHAKE = 'Could not get an IP address from the network. Please check credentials.'; 15 | 16 | var commands = { 17 | startInterface: 'sudo /sbin/ifup ' + WLAN, 18 | stopInterface: 'sudo /sbin/ifdown ' + WLAN, 19 | dhcpRenew: 'sudo /sbin/dhclient -v ' + WLAN, 20 | scanUtil: 'sudo /sbin/iwlist ' + WLAN + ' scan', 21 | iwGetId: "/sbin/iwgetid -r | tr -d '\n'", 22 | getLocalIP: "sudo /sbin/ifconfig " + WLAN + " | grep 'inet addr' | cut -d: -f2 | awk '{print $1}'", 23 | getExternalIP: '/usr/bin/wget http://icanhazip.com -qO-', 24 | getMacAddress: 'cat /sys/class/net/' + WLAN + '/address', 25 | signalQuality: "/sbin/iwconfig wlan0 | grep -i --color quality | cut -d '=' -f 2 | cut -d '/' -f 1 | tr -d '\n'", 26 | wpaCli: 'sudo /sbin/wpa_cli', 27 | } 28 | 29 | var wifi = { 30 | 31 | /** 32 | * Scan for available wifi networks 33 | * 34 | * @return {Promise.} A promise that returns an array of network if resolved, 35 | * or an Error if rejected. 36 | */ 37 | scanNetworks: function() { 38 | 39 | return new Promise((resolve, reject) => { 40 | 41 | wifi.getCurrentNetwork() 42 | .then(function(currentNetwork) { 43 | exec(commands.scanUtil, function(err, stdout, stderr) { 44 | (err) ? reject(stderr) : resolve(wifi.parseIwlist(stdout, currentNetwork)); 45 | }); 46 | 47 | }) 48 | .catch(err => { 49 | reject(err); 50 | }) 51 | 52 | }); 53 | 54 | }, 55 | 56 | 57 | /** 58 | * Set credentials for wifi network 59 | * 60 | * @param {string} ssid - SSID of the network to connect to 61 | * @param {string} psk - PSK/passphrase of the network 62 | * 63 | * @return {boolean} returns true if no errors 64 | */ 65 | setCreds: function(ssid, psk, key_mgmt) { 66 | 67 | return new Promise((resolve, reject) => { 68 | 69 | // make sure interface is up, this will throw exceptions if wlan0 is down 70 | wifi.startInterface() 71 | .then(started => { 72 | if(started) { 73 | 74 | // remove existing network 0 75 | execSync(`${commands.wpaCli} remove_network ${NET_ID}`).toString().split('\n')[1]; 76 | 77 | // add network via wpa_cli 78 | execSync(`${commands.wpaCli} add_network`).toString().split('\n')[1]; 79 | 80 | // set the SSID 81 | execSync(`${commands.wpaCli} set_network ${NET_ID} ssid '"${ssid}"'`); 82 | 83 | // set passphrase if required 84 | if(psk) { 85 | execSync(`${commands.wpaCli} set_network ${NET_ID} psk '"${psk}"'`); 86 | } 87 | 88 | // set key management 89 | if(key_mgmt) { 90 | execSync(`${commands.wpaCli} set_network ${NET_ID} key_mgmt ${key_mgmt}`); 91 | } 92 | 93 | // enable directed probe scan in case this is a hidden network 94 | execSync(`${commands.wpaCli} set_network ${NET_ID} scan_ssid 1`); 95 | 96 | // enable the network 97 | execSync(`${commands.wpaCli} enable_network ${NET_ID}`); 98 | 99 | // save config to wpa_supplicant file 100 | execSync(`${commands.wpaCli} save_config`); 101 | 102 | resolve(true); 103 | 104 | } 105 | }) 106 | .catch(err => { 107 | reject(err); 108 | }) 109 | 110 | }); 111 | 112 | }, 113 | 114 | 115 | /** 116 | * Stop wlan adapter 117 | * 118 | * @return {Promise.} A promise that returns true if resolved, 119 | * or an Error if rejected. 120 | */ 121 | stopInterface: function() { 122 | 123 | return new Promise((resolve, reject) => { 124 | 125 | exec(commands.stopInterface, function(err, stdout) { 126 | 127 | if(stdout.indexOf('Killed') == -1) { 128 | resolve(true); 129 | } else { 130 | reject(ERR_STOP); 131 | } 132 | 133 | }); 134 | 135 | }); 136 | 137 | }, 138 | 139 | /** 140 | * Start wlan adapter 141 | * 142 | * @return {Promise.} A promise that returns true if resolved, 143 | * or an Error if rejected. 144 | */ 145 | startInterface: function() { 146 | 147 | return new Promise((resolve, reject) => { 148 | 149 | exec(commands.startInterface, function(err, stdout, stderr) { 150 | if(stdout.indexOf('Failed') == -1 || stdout.indexOf('already configured') > -1) { 151 | resolve(true); 152 | } else { 153 | console.log(stdout); 154 | reject(ERR_START); 155 | } 156 | 157 | }); 158 | 159 | }); 160 | 161 | }, 162 | 163 | /** 164 | * Renew the dhcp lease 165 | * 166 | * @return {Promise.} A promise that returns true if resolved, 167 | * or an Error if rejected. 168 | */ 169 | dhcpRenew: function() { 170 | 171 | return new Promise((resolve, reject) => { 172 | 173 | exec(commands.dhcpRenew, function(err, stdout, stderr) { 174 | // verbose mode in command sends to stderr 175 | if(stderr.indexOf('bound to') > -1) { 176 | resolve(true); 177 | } 178 | 179 | reject(ERR_DHCP); 180 | }); 181 | 182 | }); 183 | 184 | }, 185 | 186 | /** 187 | * Connect to the network. Attempts to: 188 | * 189 | * 1) Set WiFi credentials 190 | * 2) Stop Interface 191 | * 3) Start Interface (with retries) 192 | * 4) Renew DHCP Lease 193 | * 194 | * @param {string} ssid - Network SSID 195 | * @param {string} psk - Network PSK/Passphrase 196 | * 197 | * @return {Promise.} A promise that returns true if resolved, 198 | * or an Error if rejected. 199 | */ 200 | connect: function(ssid, psk, key_mgmt) { 201 | 202 | key_mgmt = key_mgmt || null; 203 | 204 | return new Promise((resolve, reject) => { 205 | 206 | wifi.setCreds(ssid, psk, key_mgmt) 207 | .then(wifi.stopInterface) 208 | .then(function() { 209 | 210 | promiseRetry(function(retry, number) { 211 | 212 | return wifi.startInterface() 213 | .catch(function(err) { 214 | if(err == ERR_START && number > MAX_RETRIES) { 215 | throw(ERR_MAX_RETRIES); 216 | } 217 | 218 | retry(err); 219 | }); 220 | 221 | }) 222 | 223 | }) 224 | .then(wifi.dhcpRenew) 225 | .then(wifi.getLocalIP) 226 | .then(function() { 227 | resolve(true); 228 | }) 229 | .catch(function(err) { 230 | reject(err); 231 | }); 232 | 233 | }); 234 | 235 | }, 236 | 237 | /** 238 | * Get SSID of current connected network (if available) 239 | * 240 | * @param {Function} callback - called after exec 241 | * 242 | * @return {Promise.} A promise that returns true if resolved, 243 | * or an Error if rejected. 244 | */ 245 | getCurrentNetwork: function() { 246 | 247 | return new Promise((resolve, reject) => { 248 | exec(commands.iwGetId, function(err, stdout, stderr) { 249 | if(err) { 250 | resolve(null); 251 | } 252 | 253 | resolve(stdout); 254 | }); 255 | 256 | }); 257 | 258 | }, 259 | 260 | /** 261 | * Parses the output of the iwlist scan 262 | * 263 | * @param {string} output - Raw results from iwlist 264 | * @param {string} currentNetwork - SSID of currently connected network 265 | * 266 | * @return {array} of parsed network data objects from scan 267 | */ 268 | parseIwlist: function(output, currentNetwork) { 269 | 270 | var networks = {}; 271 | 272 | var out = output.replace(/^\s+/mg, '').split('\n') 273 | var cells = []; 274 | var line; 275 | var info = {}; 276 | var fields = { 277 | 'mac' : /^Cell \d+ - Address: (.*)/, 278 | 'ssid' : /^ESSID:"(.*)"/, 279 | 'channel': /^Channel:(.*)/, 280 | 'quality' : /Quality(?:=|\:)([^\s]+)/, 281 | 'encryption_key' : /Encryption key:(.*)/, 282 | 'wpa': /IE: (WPA Version .*)/, 283 | 'wpa2': /IE:.*(WPA2 Version .*)/, 284 | }; 285 | 286 | for (var i=0,l=out.length; i} A promise that returns external IP if resolved, 356 | * or an Error if rejected. 357 | */ 358 | getExternalIP: function() { 359 | 360 | return new Promise((resolve, reject) => { 361 | 362 | exec(commands.getExternalIP, function(err, stdout, stderr) { 363 | (err) ? reject(stderr) : resolve(stdout); 364 | }) 365 | 366 | }); 367 | 368 | }, 369 | 370 | /** 371 | * Get MAC address of wireless adapter 372 | * 373 | * @return {string} mac address 374 | */ 375 | getMacAddress: function() { 376 | return execSync(commands.getMacAddress).toString().trim(); 377 | }, 378 | 379 | /** 380 | * Get local IP to determine if we are connected to router 381 | * 382 | * @return {boolean} 383 | */ 384 | isConnected: function() { 385 | return (wifi.getLocalIP().length >= 7); 386 | }, 387 | 388 | /** 389 | * Use 'is-online' lib to determine if we have Internet connectivity 390 | * 391 | * @return {Promise.} A promise that returns true if resolved, 392 | * or an Error if rejected. 393 | */ 394 | isOnline: function() { 395 | 396 | var online = require('is-online'); 397 | 398 | return new Promise((resolve, reject) => { 399 | online().then(status => { 400 | resolve(status); 401 | }) 402 | .catch(err => { 403 | reject(err); 404 | }); 405 | 406 | }); 407 | 408 | }, 409 | 410 | /** 411 | * Get signal quality of current wireless connection as a percentage 412 | * 413 | * @return {float} quality 414 | */ 415 | getSignalQuality: function() { 416 | return Math.round(parseFloat(execSync(commands.signalQuality).toString()) / 70.0 * 1000) / 10; 417 | }, 418 | 419 | } 420 | 421 | module.exports = wifi; 422 | -------------------------------------------------------------------------------- /documentation.md: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | ## Installation   5 | **With [node](http://nodejs.org) [installed](http://nodejs.org/en/download):** 6 | ```sh 7 | # Get the latest stable release of pi-utils 8 | $ npm install --save pi-utils 9 | ``` 10 | 11 | ## Examples 12 | ```sh 13 | var utils = require('pi-utils'); 14 | 15 | # Connect to a wifi network 16 | > utils.wifi.connect('grojo', 'IndoorGardening123!').then(result => { 17 | > if(result) console.log('Connected!'); 18 | > }); 19 | Promise { } 20 | > Connected! 21 | 22 | # Get wlan IP address 23 | > utils.wifi.getLocalIP(); 24 | '192.168.1.248' 25 | ``` 26 | 27 | ```sh 28 | > var utils = require('pi-utils'); 29 | 30 | # Get Raspberry Pi Board Info 31 | > utils.system.hardwareRevision(); 32 | { code: 'a22082', name: 'Pi 3 Model B Rev. 1.2 1GB (Embest)' } 33 | 34 | # Turn off attached LCD display 35 | > utils.system.displayState(false); 36 | 37 | # Get CPU Temp (celsius) 38 | > utils.system.cpuTemp(); 39 | 41.856 40 | ``` 41 | 42 | ```sh 43 | > var utils = require('pi-utils'); 44 | 45 | # Get Disk Stats 46 | > utils.perf.diskStats(); 47 | { total: 7364, used: 1999, free: 5037 } 48 | 49 | ``` 50 | 51 | ```sh 52 | > var utils = require('pi-utils'); 53 | 54 | # Get GPIO status using rpio 55 | > utils.rpio.open(11, utils.rpio.INPUT); 56 | > console.log('Pin 11 is currently set ' + (utils.rpio.read(11) ? 'high' : 'low')); 57 | Pin 11 is currently set low 58 | ``` 59 | 60 | ### Table of Contents 61 | 62 | #WiFi Utilities (utils.wifi) 63 | 64 | - [scanNetworks](#scannetworks) 65 | - [setCreds](#setcreds) 66 | - [stopInterface](#stopinterface) 67 | - [startInterface](#startinterface) 68 | - [dhcpRenew](#dhcprenew) 69 | - [connect](#connect) 70 | - [getCurrentNetwork](#getcurrentnetwork) 71 | - [parseIwlist](#parseiwlist) 72 | - [getLocalIP](#getlocalip) 73 | - [getExternalIP](#getexternalip) 74 | - [getMacAddress](#getmacaddress) 75 | - [isConnected](#isconnected) 76 | - [isOnline](#isonline) 77 | 78 | #System / Board Utilities (utils.system) 79 | 80 | - [cpuTemp](#cputemp) 81 | - [gpuTemp](#gputemp) 82 | - [vcc](#vcc) 83 | - [uptime](#uptime) 84 | - [serial](#serial) 85 | - [machineId](#machineid) 86 | - [hostname](#hostname) 87 | - [hardwareRevision](#hardwarerevision) 88 | - [cameraInfo](#camerainfo) 89 | - [memoryConfig](#memoryconfig) 90 | - [configData](#configdata) 91 | - [kernel](#kernel) 92 | - [firmware](#firmware) 93 | - [clockSpeed](#clockspeed) 94 | - [displayState](#displaystate) 95 | 96 | #Performance Data (utils.perf) 97 | 98 | - [loadAverage](#loadaverage) 99 | - [totalMemory](#totalmemory) 100 | - [freeMemory](#freememory) 101 | - [diskStats](#diskstats) 102 | 103 | 104 | ## scanNetworks 105 | 106 | Scan for available wifi networks 107 | 108 | Returns **[Promise](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Promise)<[array](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array), [Error](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Error)>** A promise that returns an array of network if resolved, 109 | or an Error if rejected. 110 | 111 | ## setCreds 112 | 113 | Set credentials for wifi network 114 | 115 | **Parameters** 116 | 117 | - `ssid` **[string](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String)** SSID of the network to connect to 118 | - `psk` **[string](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String)** PSK/passphrase of the network 119 | 120 | Returns **[boolean](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Boolean)** returns true if no errors 121 | 122 | ## stopInterface 123 | 124 | Stop wlan adapter 125 | 126 | Returns **[Promise](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Promise)<[boolean](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Boolean), [Error](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Error)>** A promise that returns true if resolved, 127 | or an Error if rejected. 128 | 129 | ## startInterface 130 | 131 | Start wlan adapter 132 | 133 | Returns **[Promise](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Promise)<[boolean](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Boolean), [Error](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Error)>** A promise that returns true if resolved, 134 | or an Error if rejected. 135 | 136 | ## dhcpRenew 137 | 138 | Renew the dhcp lease 139 | 140 | Returns **[Promise](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Promise)<[boolean](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Boolean), [Error](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Error)>** A promise that returns true if resolved, 141 | or an Error if rejected. 142 | 143 | ## connect 144 | 145 | Connect to the network. Attempts to: 146 | 147 | 1) Set WiFi credentials 148 | 2) Stop Interface 149 | 3) Start Interface (with retries) 150 | 4) Renew DHCP Lease 151 | 152 | **Parameters** 153 | 154 | - `ssid` **[string](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String)** Network SSID 155 | - `psk` **[string](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String)** Network PSK/Passphrase 156 | 157 | Returns **[Promise](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Promise)<[boolean](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Boolean), [Error](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Error)>** A promise that returns true if resolved, 158 | or an Error if rejected. 159 | 160 | ## getCurrentNetwork 161 | 162 | Get SSID of current connected network (if available) 163 | 164 | **Parameters** 165 | 166 | - `callback` **[Function](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/function)** called after exec 167 | 168 | Returns **[Promise](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Promise)<[boolean](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Boolean), [Error](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Error)>** A promise that returns true if resolved, 169 | or an Error if rejected. 170 | 171 | ## parseIwlist 172 | 173 | Parses the output of the iwlist scan 174 | 175 | **Parameters** 176 | 177 | - `output` **[string](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String)** Raw results from iwlist 178 | - `currentNetwork` **[string](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String)** SSID of currently connected network 179 | 180 | Returns **[array](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array)** of parsed network data objects from scan 181 | 182 | ## getLocalIP 183 | 184 | Get IP address of wireless adapter 185 | 186 | Returns **[string](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String)** ip address or empty 187 | 188 | ## getExternalIP 189 | 190 | Get External IP address of this network 191 | 192 | Returns **[Promise](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Promise)<[string](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String), [Error](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Error)>** A promise that returns external IP if resolved, 193 | or an Error if rejected. 194 | 195 | ## getMacAddress 196 | 197 | Get MAC address of wireless adapter 198 | 199 | Returns **[string](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String)** mac address 200 | 201 | ## isConnected 202 | 203 | Get local IP to determine if we are connected to router 204 | 205 | Returns **[boolean](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Boolean)** 206 | 207 | ## isOnline 208 | 209 | Use 'is-online' lib to determine if we have Internet connectivity 210 | 211 | Returns **[Promise](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Promise)<[boolean](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Boolean), [Error](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Error)>** A promise that returns true if resolved, 212 | or an Error if rejected. 213 | 214 | ## cpuTemp 215 | 216 | Get CPU temp 217 | 218 | **Parameters** 219 | 220 | - `fahrenheit` **[boolean](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Boolean)** return in Fahrenheit 221 | 222 | Returns **float** 223 | 224 | ## gpuTemp 225 | 226 | Get GPU temp 227 | 228 | **Parameters** 229 | 230 | - `fahrenheit` **[boolean](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Boolean)** return in Fahrenheit 231 | 232 | Returns **float** 233 | 234 | ## vcc 235 | 236 | Get System Voltages 237 | 238 | Returns **[object](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object)** 239 | 240 | ## uptime 241 | 242 | Get System Uptime 243 | 244 | Returns **integer** 245 | 246 | ## serial 247 | 248 | Get Serial Number 249 | 250 | Returns **[string](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String)** 251 | 252 | ## machineId 253 | 254 | Get Machine Id 255 | 256 | Returns **[string](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String)** 257 | 258 | ## hostname 259 | 260 | Get hostname 261 | 262 | Returns **[string](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String)** 263 | 264 | ## hardwareRevision 265 | 266 | Get Hardware Revision 267 | 268 | Returns **[string](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String)** 269 | 270 | ## cameraInfo 271 | 272 | Get Camera information (supported and detected) 273 | 274 | Returns **[object](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object)** 275 | 276 | ## memoryConfig 277 | 278 | Get configured memory split info (between ARM and GPU) 279 | 280 | Returns **[object](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object)** 281 | 282 | ## configData 283 | 284 | Get various config settings from vcgencmd 285 | 286 | Returns **[object](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object)** 287 | 288 | ## kernel 289 | 290 | Get kernel version 291 | 292 | Returns **[string](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String)** 293 | 294 | ## firmware 295 | 296 | Get GPU firmware version 297 | 298 | Returns **[string](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String)** 299 | 300 | ## clockSpeed 301 | 302 | Get ARM, Core, UART clock speeds 303 | 304 | Returns **[object](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object)** 305 | 306 | ## displayState 307 | 308 | Turn on/off official LCD (may work for other displays, not tested 309 | 310 | **Parameters** 311 | 312 | - `enable` **[boolean](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Boolean)** turn on (true), or off (false) 313 | 314 | 315 | ## loadAverage 316 | 317 | Get CPU load average 318 | 319 | Returns **float** 320 | 321 | ## totalMemory 322 | 323 | Get total memory available to OS 324 | 325 | Returns **float** 326 | 327 | ## freeMemory 328 | 329 | Get free memory 330 | 331 | Returns **float** 332 | 333 | ## diskStats 334 | 335 | Get total/free space on root mount 336 | 337 | Returns **[object](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object)** of float, values in MB 338 | 339 | --------------------------------------------------------------------------------