jmri-client 1.4.2 → 2.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -1,4 +1,7 @@
1
- jmri-client [![Build Status](https://travis-ci.org/yamanote1138/jmri-client.png?branch=master)](https://travis-ci.org/yamanote1138/jmri-client)
1
+ jmri-client
2
+ [![Build](https://github.com/yamanote1138/jmri-client/actions/workflows/build-and-test.yml/badge.svg?branch=main)](https://github.com/yamanote1138/jmri-client/actions/workflows/build-and-test.yml)
3
+ ![License](https://img.shields.io/npm/l/jmri-client)
4
+ ![NPM Version](https://img.shields.io/npm/v/jmri-client)
2
5
  =========
3
6
 
4
7
  node client to connect to a [JMRI](http://jmri.sourceforge.net/) xmlio webservice
@@ -8,73 +11,66 @@ this allows basic control of a model railroad layout via DCC
8
11
 
9
12
  ## Usage
10
13
 
11
- setup, configure and connect
14
+ ### setup and instantiate client
12
15
  ```javascript
13
- const JmriClient = require('jmri-client');
16
+ "use strict";
14
17
 
15
- let client = new JmriClient({
16
- host: 'http://domain.com',
17
- port: 1138
18
- });
18
+ import { JmriClient } from "jmri-client";
19
+
20
+ const client = new JmriClient('http', 'jmri.local', 12080);
19
21
  ```
20
22
 
23
+ ### getPower
21
24
  get status of layout power (on or off)
22
25
  ```javascript
23
- client.getPower(function(err, status){
24
- console.log('the power is ', status);
25
- // handle error and/or do stuff
26
+ await client.getPower().then((res) => {
27
+ console.log(res);
26
28
  });
27
29
  ```
28
30
 
29
- turn layout power on/off (2=on, 4=off)
30
- todo: change to accept 'on', 1, 'off' or 0
31
+ ### setPower
32
+ turn layout power on/off
31
33
  ```javascript
32
- client.setPower('1', function(err){
33
- // handle error and/or do stuff
34
+ await client.setPower(true).then((res) => {
35
+ console.log(res);
34
36
  });
35
37
  ```
36
38
 
39
+ ## future functionality
40
+
41
+ ### getThrottle
37
42
  get full status data for a given address or array of addresses (eg [11, 38])
38
43
  ```javascript
39
- client.getThrottle(addresses, function(err, data){
40
- // handle error and/or do stuff
41
- });
44
+ await client.getThrottle(addresses);
42
45
  ```
43
46
 
44
- set speed (0-1) for specified address
45
- todo: change this to accept value from 0-100
47
+ ### setThrottleSpeed
48
+ set speed for specified throttle address
46
49
  ```javascript
47
- client.setThrottleSpeed(address, speed, function(err){
48
- // handle error and/or do stuff
49
- });
50
+ await client.setThrottleSpeed(address, speed);
50
51
  ```
51
52
 
53
+ ### setThrottleDirection
52
54
  set direction for specified address
53
55
  use 'true' for forward, 'false' for backward
54
- todo: fix this to use clearer values
55
56
  ```javascript
56
- client.setThrottleDirection(address, function(err){
57
- // handle error and/or do stuff
58
- });
57
+ await client.setThrottleDirection(address, direction);
59
58
  ```
60
59
 
60
+ ### setThrottleFunction
61
61
  set function value specified address and function
62
62
  ```javascript
63
- client.setThrottleFunction(address, functionNumber, value, function(err){
64
- // handle error and/or do stuff
65
- });
63
+ await client.setThrottleFunction(address, functionNumber, value);
66
64
  ```
67
65
 
66
+ ### getTurnouts
68
67
  list all turnouts with current status
69
68
  ```javascript
70
- client.getTurnouts(function(err, data){
71
- // handle error and/or do stuff
72
- });
69
+ await client.getTurnouts();
73
70
  ```
74
71
 
72
+ ### setTurnout
75
73
  set status of specific turnout by address
76
74
  ```javascript
77
- client.setTurnout(address, value, function(err, data){
78
- // handle error and/or do stuff
79
- });
75
+ await client.setTurnout(address, value);
80
76
  ```
@@ -0,0 +1,15 @@
1
+ declare type Protocol = "http" | "https";
2
+ declare class JmriClient {
3
+ protected readonly _protocol: Protocol;
4
+ protected readonly _host: string;
5
+ protected readonly _port: number;
6
+ constructor(protocol: Protocol, host: string, port?: number);
7
+ protected _validate: () => void;
8
+ protected _getValue: (type: string) => Promise<unknown>;
9
+ protected _setValue: (type: string, data: object) => Promise<unknown>;
10
+ protected _send: (method: string, type: string, data?: object) => Promise<unknown>;
11
+ getPower: () => Promise<unknown>;
12
+ setPower: (isOn: boolean) => Promise<unknown>;
13
+ getRoster: () => Promise<unknown>;
14
+ }
15
+ export { JmriClient };
package/dist/index.js ADDED
@@ -0,0 +1,124 @@
1
+ "use strict";
2
+ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
3
+ function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
4
+ return new (P || (P = Promise))(function (resolve, reject) {
5
+ function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
6
+ function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
7
+ function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
8
+ step((generator = generator.apply(thisArg, _arguments || [])).next());
9
+ });
10
+ };
11
+ var __generator = (this && this.__generator) || function (thisArg, body) {
12
+ var _ = { label: 0, sent: function() { if (t[0] & 1) throw t[1]; return t[1]; }, trys: [], ops: [] }, f, y, t, g;
13
+ return g = { next: verb(0), "throw": verb(1), "return": verb(2) }, typeof Symbol === "function" && (g[Symbol.iterator] = function() { return this; }), g;
14
+ function verb(n) { return function (v) { return step([n, v]); }; }
15
+ function step(op) {
16
+ if (f) throw new TypeError("Generator is already executing.");
17
+ while (_) try {
18
+ if (f = 1, y && (t = op[0] & 2 ? y["return"] : op[0] ? y["throw"] || ((t = y["return"]) && t.call(y), 0) : y.next) && !(t = t.call(y, op[1])).done) return t;
19
+ if (y = 0, t) op = [op[0] & 2, t.value];
20
+ switch (op[0]) {
21
+ case 0: case 1: t = op; break;
22
+ case 4: _.label++; return { value: op[1], done: false };
23
+ case 5: _.label++; y = op[1]; op = [0]; continue;
24
+ case 7: op = _.ops.pop(); _.trys.pop(); continue;
25
+ default:
26
+ if (!(t = _.trys, t = t.length > 0 && t[t.length - 1]) && (op[0] === 6 || op[0] === 2)) { _ = 0; continue; }
27
+ if (op[0] === 3 && (!t || (op[1] > t[0] && op[1] < t[3]))) { _.label = op[1]; break; }
28
+ if (op[0] === 6 && _.label < t[1]) { _.label = t[1]; t = op; break; }
29
+ if (t && _.label < t[2]) { _.label = t[2]; _.ops.push(op); break; }
30
+ if (t[2]) _.ops.pop();
31
+ _.trys.pop(); continue;
32
+ }
33
+ op = body.call(thisArg, _);
34
+ } catch (e) { op = [6, e]; y = 0; } finally { f = t = 0; }
35
+ if (op[0] & 5) throw op[1]; return { value: op[0] ? op[1] : void 0, done: true };
36
+ }
37
+ };
38
+ import fetch from "node-fetch";
39
+ var JmriClient = /** @class */ (function () {
40
+ function JmriClient(protocol, host, port) {
41
+ var _this = this;
42
+ this._port = 80;
43
+ this._validate = function () {
44
+ if (!_this._protocol)
45
+ throw new Error("protocol is empty");
46
+ if (!_this._host)
47
+ throw new Error("host is empty");
48
+ if (_this._port < 0 || _this._port > 65535)
49
+ throw new Error("port is out of range");
50
+ };
51
+ this._getValue = function (type) { return __awaiter(_this, void 0, void 0, function () {
52
+ return __generator(this, function (_a) {
53
+ switch (_a.label) {
54
+ case 0: return [4 /*yield*/, this._send("GET", type)];
55
+ case 1: return [2 /*return*/, _a.sent()];
56
+ }
57
+ });
58
+ }); };
59
+ this._setValue = function (type, data) { return __awaiter(_this, void 0, void 0, function () {
60
+ return __generator(this, function (_a) {
61
+ switch (_a.label) {
62
+ case 0: return [4 /*yield*/, this._send("POST", type, data)];
63
+ case 1: return [2 /*return*/, _a.sent()];
64
+ }
65
+ });
66
+ }); };
67
+ this._send = function (method, type, data) { return __awaiter(_this, void 0, void 0, function () {
68
+ var uri, options, response;
69
+ return __generator(this, function (_a) {
70
+ switch (_a.label) {
71
+ case 0:
72
+ uri = "".concat(this._protocol, "://").concat(this._host, ":").concat(this._port, "/json/").concat(type);
73
+ options = {
74
+ method: method,
75
+ };
76
+ if (data !== undefined) {
77
+ (options.body = JSON.stringify(data)),
78
+ (options.headers = {
79
+ "Content-Type": "application/json; charset=utf-8",
80
+ });
81
+ }
82
+ return [4 /*yield*/, fetch(uri, options)];
83
+ case 1:
84
+ response = _a.sent();
85
+ return [4 /*yield*/, response.json()];
86
+ case 2: return [2 /*return*/, _a.sent()];
87
+ }
88
+ });
89
+ }); };
90
+ this.getPower = function () { return __awaiter(_this, void 0, void 0, function () {
91
+ return __generator(this, function (_a) {
92
+ switch (_a.label) {
93
+ case 0: return [4 /*yield*/, this._getValue("power")];
94
+ case 1: return [2 /*return*/, _a.sent()];
95
+ }
96
+ });
97
+ }); };
98
+ this.setPower = function (isOn) { return __awaiter(_this, void 0, void 0, function () {
99
+ return __generator(this, function (_a) {
100
+ switch (_a.label) {
101
+ case 0: return [4 /*yield*/, this._setValue("power", {
102
+ state: isOn ? 2 : 4,
103
+ })];
104
+ case 1: return [2 /*return*/, _a.sent()];
105
+ }
106
+ });
107
+ }); };
108
+ this.getRoster = function () { return __awaiter(_this, void 0, void 0, function () {
109
+ return __generator(this, function (_a) {
110
+ switch (_a.label) {
111
+ case 0: return [4 /*yield*/, this._getValue("roster")];
112
+ case 1: return [2 /*return*/, _a.sent()];
113
+ }
114
+ });
115
+ }); };
116
+ this._protocol = protocol;
117
+ this._host = host;
118
+ if (port !== undefined)
119
+ this._port = port;
120
+ this._validate();
121
+ }
122
+ return JmriClient;
123
+ }());
124
+ export { JmriClient };
package/package.json CHANGED
@@ -1,49 +1,54 @@
1
1
  {
2
+ "name": "jmri-client",
3
+ "version": "2.0.0",
4
+ "description": "node client to connect to a JMRI xmlio webservice",
5
+ "main": "dist/index.js",
6
+ "type": "module",
7
+ "types": "dist/index.d.ts",
8
+ "scripts": {
9
+ "prepublish": "npm run build",
10
+ "build": "tsc",
11
+ "test": "jest --no-cache --coverage"
12
+ },
13
+ "keywords": [
14
+ "jmri",
15
+ "xmlio",
16
+ "model railroad",
17
+ "train",
18
+ "node"
19
+ ],
2
20
  "author": {
3
21
  "email": "yamanote1138@gmail.com",
4
22
  "name": "Chad Francis",
5
23
  "url": "http://thechad.io"
6
24
  },
7
- "bugs": {
8
- "url": "https://github.com/yamanote1138/jmri-client/issues"
9
- },
10
- "name": "jmri-client",
11
- "description": "node client to connect to a JMRI xmlio webservice",
12
25
  "homepage": "https://github.com/yamanote1138/jmri-client",
13
- "version": "1.4.2",
14
26
  "private": false,
27
+ "readmeFilename": "README.md",
28
+ "license": "MIT",
15
29
  "repository": {
16
30
  "type": "git",
17
31
  "url": "git://github.com/yamanote1138/jmri-client.git"
18
32
  },
19
- "dependencies": {
20
- "request": "^2.88.2",
21
- "xml2json": "^0.12.0"
33
+ "bugs": {
34
+ "url": "https://github.com/yamanote1138/jmri-client/issues"
35
+ },
36
+ "engines": {
37
+ "node": ">=14"
22
38
  },
23
39
  "devDependencies": {
24
- "eslint": "^7.0.0",
25
- "eslint-config-strongloop": "^2.1.0",
26
- "eslint-plugin-mocha": "^6.3.0",
27
- "eslint-plugin-node": "^11.1.0",
28
- "eslint-utils": "^2.0.0",
29
- "mocha": "^7.1.2"
40
+ "@types/jest": "^29.0.0",
41
+ "@types/node": "^18.7.14",
42
+ "jest": "^28.1.3",
43
+ "ts-jest": "^28.0.8",
44
+ "typescript": "^4.8.2"
30
45
  },
31
- "engines": {
32
- "node": ">=10.15.1"
46
+ "dependencies": {
47
+ "node-fetch": "^3.2.10",
48
+ "xml2json": "^0.12.0"
33
49
  },
34
- "keywords": [
35
- "jmri",
36
- "xmlio",
37
- "api",
38
- "model railroad",
39
- "train",
40
- "node"
41
- ],
42
- "license": "MIT",
43
- "main": "index.js",
44
- "scripts": {
45
- "lint": "./node_modules/eslint/bin/eslint.js --ignore-path .gitignore .",
46
- "pretest": "eslint --ignore-path .gitignore .",
47
- "test": "./node_modules/.bin/mocha -R spec ./tests/unit.test.js"
48
- }
50
+ "files": [
51
+ "dist",
52
+ "index.js"
53
+ ]
49
54
  }
package/.editorconfig DELETED
@@ -1,9 +0,0 @@
1
- root = true
2
-
3
- [*]
4
- charset = utf-8
5
- end_of_line = lf
6
- indent_size = 2
7
- indent_style = space
8
- insert_final_newline = true
9
- trim_trailing_whitespace = true
package/.eslintrc.json DELETED
@@ -1,18 +0,0 @@
1
- {
2
- "env": {
3
- "mocha": true,
4
- "node": true
5
- },
6
- "extends": ["eslint:recommended", "plugin:node/recommended"],
7
- "plugins": [
8
- "mocha"
9
- ],
10
- "rules": {
11
- "node/exports-style": ["error", "module.exports"],
12
- "node/prefer-global/buffer": ["error", "always"],
13
- "node/prefer-global/console": ["error", "always"],
14
- "node/prefer-global/process": ["error", "always"],
15
- "node/prefer-global/url-search-params": ["error", "always"],
16
- "node/prefer-global/url": ["error", "always"]
17
- }
18
- }
package/.travis.yml DELETED
@@ -1,3 +0,0 @@
1
- language: node_js
2
- node_js:
3
- - "10.15.1"
package/lib/jmriClient.js DELETED
@@ -1,95 +0,0 @@
1
- 'use strict';
2
-
3
- const request = require('request');
4
- const xml2json = require('xml2json');
5
-
6
- function JmriClient(config) {
7
- this.config = {
8
- port:80,
9
- path:'/xmlio/'
10
- };
11
- Object.assign(this.config, config);
12
-
13
- if(!this.config.host) throw new Error('host not specified');
14
- if(typeof(this.config.host) != 'string') throw new Error('host is not a string');
15
-
16
- if(!this.config.port) throw new Error('port not specified');
17
- if(typeof(this.config.port) != 'number') throw new Error('port is not a number');
18
- if(this.config.port < 0 || this.config.port > 65535) throw new Error('port is out of range');
19
-
20
- if(!this.config.path) throw new Error('path not specified');
21
- if(typeof(this.config.path) != 'string') throw new Error('path is not a string');
22
- }
23
-
24
- JmriClient.prototype = {
25
-
26
- getPower: function(done){
27
- let xmldata = '<item><type>power</type><name>power</name></item>';
28
-
29
- _send(this, xmldata, function(err, data){
30
- if (!err && data) data = data.XMLIO.item.value;
31
- done(err, data);
32
- });
33
- },
34
-
35
- setPower: function(value, done){
36
- let xmldata = `<item><type>power</type><name>power</name><set>${value}</set></item>`;
37
- _send(this, xmldata, done);
38
- },
39
-
40
- getThrottle: function(addresses, done){
41
- if (!(addresses instanceof Array)) addresses = [addresses];
42
- let xmldata = '';
43
- addresses.forEach(function(address){
44
- xmldata += `<throttle><address>${address}</address></throttle>`;
45
- });
46
- _send(this, xmldata, done);
47
- },
48
-
49
- setThrottleSpeed: function(address, value, done){
50
- let xmldata = `<throttle><address>${address}</address><speed>${value}</speed></throttle>`;
51
- _send(this, xmldata, done);
52
- },
53
-
54
- setThrottleFunction: function(address, functionNumber, value, done){
55
- let xmldata = `<throttle><address>${address}</address><F${functionNumber}>${value}</F${functionNumber}></throttle>`;
56
- _send(this, xmldata, done);
57
- },
58
-
59
- setThrottleDirection: function(address, value, done){
60
- let xmldata = `<throttle><address>${address}</address><forward>${value}</forward></throttle>`;
61
- _send(this, xmldata, done);
62
- },
63
-
64
- setTurnout: function(address, value, done){
65
- let xmldata = `<turnout name="${address}" set="${value}" />`;
66
- _send(this, xmldata, done);
67
- },
68
-
69
- getTurnouts: function(done){
70
- let xmldata = '<list type="turnout" />';
71
- _send(this, xmldata, done);
72
- },
73
-
74
- };
75
-
76
- function _send(client, xmldata, done){
77
-
78
- // wrap request data
79
- xmldata = `<?xml version="1.0" encoding="UTF-8"?><XMLIO>${xmldata}</XMLIO>`;
80
-
81
- var options = {
82
- uri: client.host + client.path,
83
- body: xmldata,
84
- headers: {
85
- 'Content-Type': 'application/xml',
86
- },
87
- };
88
-
89
- request.post(options, function(error, response, body) {
90
- if (body) body = JSON.parse(xml2json.toJson(body));
91
- done(error, body);
92
- });
93
- }
94
-
95
- module.exports = JmriClient;
@@ -1,115 +0,0 @@
1
- const assert = require('assert');
2
- const JmriClient = require('../lib/jmriClient');
3
-
4
- describe('JmriClient', function(){
5
-
6
- describe('constructor', function(){
7
-
8
- describe('host validation', function(){
9
-
10
- it('should throw error when host is not provided', function(){
11
- assert.throws(
12
- function(){
13
- new JmriClient();
14
- },
15
- Error
16
- );
17
- });
18
-
19
- it('should throw error when host is not valid', function(){
20
- assert.throws(
21
- function(){
22
- new JmriClient({host:123});
23
- },
24
- Error
25
- );
26
- });
27
-
28
- it('should not throw error when host is valid', function(){
29
- assert.doesNotThrow(
30
- function(){
31
- new JmriClient({host:'localhost'});
32
- },
33
- Error
34
- );
35
- });
36
-
37
- });
38
-
39
- describe('port validation', function(){
40
-
41
- it('should default to port 80 if no value is specified', function(){
42
- let jc = new JmriClient({host:'localhost'});
43
- assert(jc.config.port === 80);
44
- });
45
-
46
- it('should throw error when specified port is not valid', function(){
47
- assert.throws(
48
- function(){
49
- new JmriClient({host:'localhost', port:null});
50
- },
51
- Error
52
- );
53
- assert.throws(
54
- function(){
55
- new JmriClient({host:'localhost', port:'foo'});
56
- },
57
- Error
58
- );
59
- assert.throws(
60
- function(){
61
- new JmriClient({host:'localhost', port:70000});
62
- },
63
- Error
64
- );
65
- });
66
-
67
- it('should not throw error when port is valid', function(){
68
- assert.doesNotThrow(
69
- function(){
70
- new JmriClient({host:'localhost', port:1138});
71
- },
72
- Error
73
- );
74
- });
75
-
76
- });
77
-
78
- describe('path validation', function(){
79
-
80
- it('should default to \'/xmlio/\' if no path is specified', function(){
81
- let jc = new JmriClient({host:'localhost'});
82
- assert(jc.config.path === '/xmlio/');
83
- });
84
-
85
- it('should throw error when specified path is invalid', function(){
86
- assert.throws(
87
- function(){
88
- new JmriClient({host:'localhost', path:null});
89
- }
90
- );
91
- assert.throws(
92
- function(){
93
- new JmriClient({host:'localhost', path:1});
94
- }
95
- );
96
- assert.throws(
97
- function(){
98
- new JmriClient({host:'localhost', path:''});
99
- }
100
- );
101
- });
102
-
103
- it('should not throw error when specified path is valid', function(){
104
- assert.doesNotThrow(
105
- function(){
106
- new JmriClient({host:'localhost', path:'/crap'});
107
- }
108
- );
109
- });
110
-
111
- });
112
-
113
- });
114
-
115
- });