diff --git a/README.md b/README.md index 50df6c1..b32b974 100644 --- a/README.md +++ b/README.md @@ -26,8 +26,7 @@ npm install node index.js ``` -The first command will install all the prerequisites and the second starts *ambient2pwsweather*. You will need to keep this window and process running in order to allow it to continue to retrieve data from AmbientWeather.net. There are tools available (like [forever](https://www.npmjs.com/package/forever)) to ensure the process runs in the background. - +The first command will install all the prerequisites and the second starts *ambient2pwsweather*. You will need to keep this window and process running in order to allow it to continue to retrieve data from AmbientWeather.net. Configuration --------------- @@ -54,6 +53,31 @@ Alternatively, the following environment variables can be used to override confi - PWD_PASSWORD - (From your PWS Weather account. NOTE: Your password cannot have any punctuation or special characters) - LOG_LEVEL - (debug, info, warn, error) +Install as Service +--------------- +To install as a service, you must first install a service tool for your platform. + +```js +// for macOS +npm install node-mac + +// for Windows +npm install node-windows + +// for Linux +npm install node-linux +``` + +Then install as a service: +```js +npm run service install +``` + +You can view logs through the standard/system logging for your platform. + +For more details, visit the respective module npm page: [macOS](https://www.npmjs.com/package/node-mac), [Windows](https://www.npmjs.com/package/node-windows), [Linux](https://www.npmjs.com/package/node-linux) + + Author --------------- Dan Wilson ([@killroyboy](https://twitter.com/killroyboy) / [Web](https://www.codeality.com)) @@ -64,4 +88,4 @@ MIT Contributing --------------- -Code contributions are greatly appreciated, please submit a new [pull request](https://github.com/killroyboy/ambient2pwsweather/pull/new/master)! \ No newline at end of file +Code contributions are greatly appreciated, please submit a new [pull request](https://github.com/killroyboy/ambient2pwsweather/pull/new/master)! diff --git a/index.js b/index.js index 82ceb63..c40017f 100644 --- a/index.js +++ b/index.js @@ -6,6 +6,8 @@ * * Currently only supports 1 device from AmbientWeather */ +process.env['NODE_CONFIG_DIR'] = __dirname + '/config/'; + const got = require('got'), pkg = require('./package.json'), config = require('config'), diff --git a/package-lock.json b/package-lock.json index e6e116f..6dd0f69 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,6 +1,6 @@ { "name": "ambient2pwsweather", - "version": "0.0.5", + "version": "1.0.0", "lockfileVersion": 1, "requires": true, "dependencies": { @@ -586,7 +586,6 @@ "version": "5.1.0", "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-5.1.0.tgz", "integrity": "sha1-6L0O/uWPz/b4+UUQoKVUu/ojVEk=", - "dev": true, "requires": { "lru-cache": "^4.0.1", "shebang-command": "^1.2.0", @@ -1806,6 +1805,30 @@ } } }, + "is-admin": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/is-admin/-/is-admin-2.1.1.tgz", + "integrity": "sha1-eYaQMOwC0sv4+Ky1cFR1wiY5T7o=", + "requires": { + "execa": "^0.6.1" + }, + "dependencies": { + "execa": { + "version": "0.6.3", + "resolved": "https://registry.npmjs.org/execa/-/execa-0.6.3.tgz", + "integrity": "sha1-V7aaWU8IF1nGnlNw8NF7nLEWWP4=", + "requires": { + "cross-spawn": "^5.0.1", + "get-stream": "^3.0.0", + "is-stream": "^1.1.0", + "npm-run-path": "^2.0.0", + "p-finally": "^1.0.0", + "signal-exit": "^3.0.0", + "strip-eof": "^1.0.0" + } + } + } + }, "is-binary-path": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/is-binary-path/-/is-binary-path-1.0.1.tgz", @@ -1869,6 +1892,15 @@ } } }, + "is-elevated": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/is-elevated/-/is-elevated-2.0.1.tgz", + "integrity": "sha1-CisKArXdvlYOM5kqzUtURUdJmZg=", + "requires": { + "is-admin": "^2.1.0", + "is-root": "^1.0.0" + } + }, "is-extendable": { "version": "0.1.1", "resolved": "https://registry.npmjs.org/is-extendable/-/is-extendable-0.1.1.tgz", @@ -1994,11 +2026,15 @@ "resolved": "https://registry.npmjs.org/is-retry-allowed/-/is-retry-allowed-1.1.0.tgz", "integrity": "sha1-EaBgVotnM5REAz0BJaYaINVk+zQ=" }, + "is-root": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-root/-/is-root-1.0.0.tgz", + "integrity": "sha1-B7bCM7w5TNnQK6FclmvWZg1jQtU=" + }, "is-stream": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/is-stream/-/is-stream-1.1.0.tgz", - "integrity": "sha1-EtSj3U5o4Lec6428hBc66A2RykQ=", - "dev": true + "integrity": "sha1-EtSj3U5o4Lec6428hBc66A2RykQ=" }, "is-typedarray": { "version": "1.0.0", @@ -2019,8 +2055,7 @@ "isexe": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz", - "integrity": "sha1-6PvzdNxVb/iUehDcsFctYz8s+hA=", - "dev": true + "integrity": "sha1-6PvzdNxVb/iUehDcsFctYz8s+hA=" }, "isobject": { "version": "3.0.1", @@ -2121,7 +2156,6 @@ "version": "4.1.3", "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-4.1.3.tgz", "integrity": "sha512-fFEhvcgzuIoJVUF8fYr5KR0YqxD238zgObTps31YdADwPPAp82a4M8TrckkWyx7ekNlf9aBcVn81cFwwXngrJA==", - "dev": true, "requires": { "pseudomap": "^1.0.2", "yallist": "^2.1.2" @@ -2330,7 +2364,6 @@ "version": "2.0.2", "resolved": "https://registry.npmjs.org/npm-run-path/-/npm-run-path-2.0.2.tgz", "integrity": "sha1-NakjLfo11wZ7TLLd8jV7GHFTbF8=", - "dev": true, "requires": { "path-key": "^2.0.0" } @@ -2523,8 +2556,7 @@ "path-key": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/path-key/-/path-key-2.0.1.tgz", - "integrity": "sha1-QRyttXTFoUDTpLGRDUDYDMn0C0A=", - "dev": true + "integrity": "sha1-QRyttXTFoUDTpLGRDUDYDMn0C0A=" }, "pause-stream": { "version": "0.0.11", @@ -2573,8 +2605,7 @@ "pseudomap": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/pseudomap/-/pseudomap-1.0.2.tgz", - "integrity": "sha1-8FKijacOYYkX7wqKw0wa5aaChrM=", - "dev": true + "integrity": "sha1-8FKijacOYYkX7wqKw0wa5aaChrM=" }, "pstree.remy": { "version": "1.1.0", @@ -2831,7 +2862,6 @@ "version": "1.2.0", "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-1.2.0.tgz", "integrity": "sha1-RKrGW2lbAzmJaMOfNj/uXer98eo=", - "dev": true, "requires": { "shebang-regex": "^1.0.0" } @@ -2839,14 +2869,12 @@ "shebang-regex": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-1.0.0.tgz", - "integrity": "sha1-2kL0l0DAtC2yypcoVxyxkMmO/qM=", - "dev": true + "integrity": "sha1-2kL0l0DAtC2yypcoVxyxkMmO/qM=" }, "signal-exit": { "version": "3.0.2", "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.2.tgz", - "integrity": "sha1-tf3AjxKH6hF4Yo5BXiUTK3NkbG0=", - "dev": true + "integrity": "sha1-tf3AjxKH6hF4Yo5BXiUTK3NkbG0=" }, "snapdragon": { "version": "0.8.2", @@ -3155,8 +3183,7 @@ "strip-eof": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/strip-eof/-/strip-eof-1.0.0.tgz", - "integrity": "sha1-u0P/VZim6wXYm1n80SnJgzE2Br8=", - "dev": true + "integrity": "sha1-u0P/VZim6wXYm1n80SnJgzE2Br8=" }, "strip-json-comments": { "version": "2.0.1", @@ -3504,7 +3531,6 @@ "version": "1.3.0", "resolved": "https://registry.npmjs.org/which/-/which-1.3.0.tgz", "integrity": "sha512-xcJpopdamTuY5duC/KnTTNBraPK54YwpenP4lzxU8H91GudWpFv38u0CKjclE1Wi2EH2EDz5LRcHcKbCIzqGyg==", - "dev": true, "requires": { "isexe": "^2.0.0" } @@ -3553,8 +3579,7 @@ "yallist": { "version": "2.1.2", "resolved": "https://registry.npmjs.org/yallist/-/yallist-2.1.2.tgz", - "integrity": "sha1-HBH5IY8HYImkfdUS+TxmmaaoHVI=", - "dev": true + "integrity": "sha1-HBH5IY8HYImkfdUS+TxmmaaoHVI=" }, "yeast": { "version": "0.1.2", diff --git a/package.json b/package.json index 30f9e62..58a0178 100644 --- a/package.json +++ b/package.json @@ -1,11 +1,12 @@ { "name": "ambient2pwsweather", - "version": "0.0.6", + "version": "1.0.0", "description": "Pull weather data from AmbientWeather.net and push to PWSWeather", "main": "index.js", "scripts": { "test": "echo \"Error: no test specified\" && exit 1", "start": "node index.js", + "service": "sudo node service.js", "start dev": "nodemon index.js", "build": "mkdir -p build && zip -x 'node_modules/*' -x 'build/*' -x '.git/*' -x '.idea/*' -x 'config/development.json' -r build/ambient2pwsweather-$(npm run version --silent).zip *", "version": "echo $npm_package_version" @@ -30,6 +31,7 @@ "config": "^1.30.0", "eazy-logger": "^3.0.2", "got": "^8.3.1", + "is-elevated": "^2.0.1", "lodash": "^4.17.10", "moment": "^2.22.1" }, diff --git a/service.js b/service.js new file mode 100644 index 0000000..103c7d3 --- /dev/null +++ b/service.js @@ -0,0 +1,109 @@ +/** + * ambient2pwsweather installation + * * Manager ambient2pwsweather as a service on macOS, Windows or Linux + * * You must manually install the platform service yourself: node-mac, node-windows, node-linux + */ + +// determine which service helper we should require +var service_mod = ''; +switch (process.platform) { + case 'darwin': + service_mod = 'node-mac'; + break; + case 'win32': + service_mod = 'node-windows'; + break; + case 'linux': + service_mod = 'node-linux'; + break; +} + +if (!service_mod) { + console.log('ERROR: Undetected platform. Running as a service is only available on macOS, Windows and Linux.'); + process.exit(); +} + +const isElevated = require('is-elevated'); + +isElevated().then(elevated => { + if (!elevated) { + console.log('ERROR: Must be run as root/Administrator.') + process.exit(); + } else { + const Service = require(service_mod).Service; + + // Create a new service object + var svc = new Service({ + name:'ambient2pwsweather', + description: 'Pull weather data from an AmbientWeather.net Station and push to a PWSweather.com Station', + script: require('path').join(__dirname, 'index.js') + }); + + svc.on('start', function () { + setTimeout(function () { + // console.log('Service running:', svc.exists); + }, 300); + }); + + svc.on('stop', function () { + setTimeout(function () { + // console.log('Service running:', svc.exists); + }, 300); + }); + + svc.on('error', function (e) { + console.log('Error occurred:', e); + }); + + svc.on('alreadyinstalled', function () { + console.log('Service already installed.'); + console.log('Service installed:', svc.exists); + }); + + svc.on('install', function() { + svc.start(); + }); + + svc.on('uninstall', function() { + console.log('Uninstall complete.'); + console.log('Service installed:', svc.exists); + }); + + var command = process.argv[2]; + + var usage = function () { + console.log('Usage: service [install|uninstall|status|start|stop|restart]'); + process.exit(0); + }; + + if (!command) { + usage(); + } + + switch (command) { + case 'install': + // Install the service + svc.install(); + break; + case 'uninstall': + // Uninstall the service. + svc.uninstall(); + break; + case 'status': + console.log('Service installed:', svc.exists); + // console.log('Service running:', svc.exists); + break; + case 'start': + svc.start(); + break; + case 'stop': + svc.stop(); + break; + case 'restart': + svc.restart(); + break; + default: + usage(); + } + } +}); \ No newline at end of file