elero-usb-transmitter-client 1.0.6 → 1.1.1
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/.github/workflows/nodejs.yml +27 -0
- package/README.md +58 -1
- package/dist/UsbTransmitterClient.d.ts +18 -0
- package/dist/UsbTransmitterClient.js +284 -0
- package/dist/cli.d.ts +2 -0
- package/dist/cli.js +277 -0
- package/dist/domain/constants.d.ts +32 -0
- package/dist/domain/constants.js +44 -0
- package/dist/domain/enums.d.ts +34 -0
- package/dist/domain/enums.js +40 -0
- package/dist/domain/types.d.ts +3 -0
- package/dist/domain/types.js +2 -0
- package/dist/index.d.ts +6 -0
- package/dist/index.js +18 -0
- package/dist/model/Response.d.ts +10 -0
- package/dist/model/Response.js +2 -0
- package/dist/src/cli.d.ts +2 -0
- package/dist/src/cli.js +277 -0
- package/jest.json +1 -1
- package/package.json +5 -2
- package/src/UsbTransmitterClient.ts +46 -39
- package/src/cli.ts +167 -0
- package/test/UsbTransmitterClient.test.ts +39 -0
- package/test/UsbTransmitterClientMock.test.ts +182 -0
- package/__test__/UsbTransmitterClient.test.ts +0 -31
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
name: Node.js CI
|
|
2
|
+
|
|
3
|
+
on:
|
|
4
|
+
push:
|
|
5
|
+
branches: [ main, develop ]
|
|
6
|
+
pull_request:
|
|
7
|
+
branches: [ main ]
|
|
8
|
+
|
|
9
|
+
jobs:
|
|
10
|
+
build:
|
|
11
|
+
|
|
12
|
+
runs-on: ubuntu-latest
|
|
13
|
+
|
|
14
|
+
strategy:
|
|
15
|
+
matrix:
|
|
16
|
+
node-version: [18.x, 20.x, 22.x]
|
|
17
|
+
|
|
18
|
+
steps:
|
|
19
|
+
- uses: actions/checkout@v3
|
|
20
|
+
- name: Use Node.js ${{ matrix.node-version }}
|
|
21
|
+
uses: actions/setup-node@v3
|
|
22
|
+
with:
|
|
23
|
+
node-version: ${{ matrix.node-version }}
|
|
24
|
+
cache: 'npm'
|
|
25
|
+
- run: npm ci
|
|
26
|
+
- run: npm run build
|
|
27
|
+
- run: npm test
|
package/README.md
CHANGED
|
@@ -1,7 +1,8 @@
|
|
|
1
1
|
# elero-usb-transmitter-client
|
|
2
2
|
|
|
3
3
|
[](https://www.npmjs.com/package/elero-usb-transmitter-client)
|
|
4
|
-
[](https://github.com/marc2016/elero-usb-transmitter-client/actions/workflows/nodejs.yml)
|
|
5
|
+
|
|
5
6
|
|
|
6
7
|
Elero USB Transmitter Client for node.js to send commands to Elero USB Stick and receive information. This libaray needs Elero Transmitter Stick (https://www.der-sonnenschutz-shop.de/elero-221250001-centero-transmitter-stick.html).
|
|
7
8
|
|
|
@@ -18,6 +19,30 @@ Using npm:
|
|
|
18
19
|
$ npm install elero-usb-transmitter-client
|
|
19
20
|
```
|
|
20
21
|
|
|
22
|
+
## CLI Usage
|
|
23
|
+
|
|
24
|
+
You can use the interactive CLI to control the transmitter directly.
|
|
25
|
+
|
|
26
|
+
### Installation
|
|
27
|
+
|
|
28
|
+
**Globally (if published to npm):**
|
|
29
|
+
```bash
|
|
30
|
+
npm install -g elero-usb-transmitter-client
|
|
31
|
+
elero-cli
|
|
32
|
+
```
|
|
33
|
+
|
|
34
|
+
**Via npx (if published to npm):**
|
|
35
|
+
```bash
|
|
36
|
+
npx elero-usb-transmitter-client
|
|
37
|
+
```
|
|
38
|
+
|
|
39
|
+
**From Source (Development):**
|
|
40
|
+
1. Clone the repository
|
|
41
|
+
2. Install dependencies: `npm install`
|
|
42
|
+
3. Build the project: `npm run build`
|
|
43
|
+
4. Link command: `npm link`
|
|
44
|
+
5. Run: `elero-cli`
|
|
45
|
+
|
|
21
46
|
## Example
|
|
22
47
|
|
|
23
48
|
### Initialize
|
|
@@ -57,6 +82,38 @@ console.log(response)
|
|
|
57
82
|
await client.close()
|
|
58
83
|
```
|
|
59
84
|
|
|
85
|
+
## Changelog
|
|
86
|
+
|
|
87
|
+
### 1.1.1
|
|
88
|
+
|
|
89
|
+
- Fixed `responseBytes are null` error by handling fragmented serial packets
|
|
90
|
+
- Added detailed unit tests with mocks
|
|
91
|
+
|
|
92
|
+
### 1.1.0
|
|
93
|
+
|
|
94
|
+
- Added interactive CLI (`elero-cli`)
|
|
95
|
+
- Added `inquirer` and `commander` dependencies
|
|
96
|
+
|
|
97
|
+
### 1.0.6
|
|
98
|
+
|
|
99
|
+
- Updated `serialport` dependency
|
|
100
|
+
- Fixed errors in response handling
|
|
101
|
+
|
|
102
|
+
### 1.0.5
|
|
103
|
+
|
|
104
|
+
- Improved mutex handling (release added)
|
|
105
|
+
|
|
106
|
+
### 1.0.4
|
|
107
|
+
|
|
108
|
+
- Fixed promise rejection logic
|
|
109
|
+
- Added null checks for response bytes
|
|
110
|
+
|
|
111
|
+
### 1.0.0
|
|
112
|
+
|
|
113
|
+
- Initial release with `getInfo`, `sendControlCommand`, and `checkChannels`
|
|
114
|
+
- Implemented `UsbTransmitterClient`
|
|
115
|
+
|
|
116
|
+
|
|
60
117
|
## License
|
|
61
118
|
|
|
62
119
|
[MIT](LICENSE)
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
import { SerialPort } from 'serialport';
|
|
2
|
+
import { Response } from './model/Response';
|
|
3
|
+
import { ControlCommand } from './domain/enums';
|
|
4
|
+
export declare class UsbTransmitterClient {
|
|
5
|
+
serialPort: SerialPort<any>;
|
|
6
|
+
constructor(devPath: string);
|
|
7
|
+
open(): Promise<void>;
|
|
8
|
+
close(): Promise<void>;
|
|
9
|
+
checkChannels(): Promise<number[]>;
|
|
10
|
+
getInfo(channel: number): Promise<Response>;
|
|
11
|
+
sendControlCommand(channel: number, controlCommand: ControlCommand): Promise<Response>;
|
|
12
|
+
private waitForResponse;
|
|
13
|
+
private sendCommand;
|
|
14
|
+
private readResponseBytes;
|
|
15
|
+
private calculateChecksum;
|
|
16
|
+
private getActiveChannels;
|
|
17
|
+
private parseResponse;
|
|
18
|
+
}
|
|
@@ -0,0 +1,284 @@
|
|
|
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
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
39
|
+
exports.UsbTransmitterClient = void 0;
|
|
40
|
+
var serialport_1 = require("serialport");
|
|
41
|
+
var _ = require("lodash");
|
|
42
|
+
var constants_1 = require("./domain/constants");
|
|
43
|
+
var enums_1 = require("./domain/enums");
|
|
44
|
+
var async_mutex_1 = require("async-mutex");
|
|
45
|
+
var DEFAULT_BAUDRATE = 38400;
|
|
46
|
+
var DEFAULT_BYTESIZE = 8;
|
|
47
|
+
var DEFAULT_PARITY = 'none';
|
|
48
|
+
var DEFAULT_STOPBITS = 1;
|
|
49
|
+
var mutex = new async_mutex_1.Mutex();
|
|
50
|
+
var UsbTransmitterClient = /** @class */ (function () {
|
|
51
|
+
function UsbTransmitterClient(devPath) {
|
|
52
|
+
this.serialPort = new serialport_1.SerialPort({
|
|
53
|
+
path: devPath,
|
|
54
|
+
baudRate: DEFAULT_BAUDRATE,
|
|
55
|
+
dataBits: DEFAULT_BYTESIZE,
|
|
56
|
+
parity: DEFAULT_PARITY,
|
|
57
|
+
stopBits: DEFAULT_STOPBITS,
|
|
58
|
+
autoOpen: false,
|
|
59
|
+
});
|
|
60
|
+
}
|
|
61
|
+
UsbTransmitterClient.prototype.open = function () {
|
|
62
|
+
var _this = this;
|
|
63
|
+
return new Promise(function (resolve, reject) {
|
|
64
|
+
if (!_this.serialPort.isOpen) {
|
|
65
|
+
_this.serialPort.open(function (error) {
|
|
66
|
+
if (error)
|
|
67
|
+
reject(error);
|
|
68
|
+
_this.serialPort.flush(function (error) {
|
|
69
|
+
if (error)
|
|
70
|
+
reject(error);
|
|
71
|
+
resolve();
|
|
72
|
+
});
|
|
73
|
+
});
|
|
74
|
+
}
|
|
75
|
+
});
|
|
76
|
+
};
|
|
77
|
+
UsbTransmitterClient.prototype.close = function () {
|
|
78
|
+
var _this = this;
|
|
79
|
+
return new Promise(function (resolve, reject) {
|
|
80
|
+
_this.serialPort.close(function (error) {
|
|
81
|
+
if (error)
|
|
82
|
+
reject(error);
|
|
83
|
+
resolve();
|
|
84
|
+
});
|
|
85
|
+
});
|
|
86
|
+
};
|
|
87
|
+
UsbTransmitterClient.prototype.checkChannels = function () {
|
|
88
|
+
return __awaiter(this, void 0, void 0, function () {
|
|
89
|
+
var data, release, responseBytes, response;
|
|
90
|
+
return __generator(this, function (_a) {
|
|
91
|
+
switch (_a.label) {
|
|
92
|
+
case 0:
|
|
93
|
+
data = [constants_1.BYTE_HEADER, constants_1.BYTE_LENGTH_2, enums_1.EasyCommand.EASY_CHECK];
|
|
94
|
+
return [4 /*yield*/, mutex.acquire()];
|
|
95
|
+
case 1:
|
|
96
|
+
release = _a.sent();
|
|
97
|
+
_a.label = 2;
|
|
98
|
+
case 2:
|
|
99
|
+
_a.trys.push([2, , 5, 6]);
|
|
100
|
+
return [4 /*yield*/, this.sendCommand(data)];
|
|
101
|
+
case 3:
|
|
102
|
+
_a.sent();
|
|
103
|
+
return [4 /*yield*/, this.waitForResponse(constants_1.RESPONSE_LENGTH_CHECK)];
|
|
104
|
+
case 4:
|
|
105
|
+
responseBytes = _a.sent();
|
|
106
|
+
response = this.parseResponse(responseBytes);
|
|
107
|
+
return [2 /*return*/, response.activeChannels];
|
|
108
|
+
case 5:
|
|
109
|
+
release();
|
|
110
|
+
return [7 /*endfinally*/];
|
|
111
|
+
case 6: return [2 /*return*/];
|
|
112
|
+
}
|
|
113
|
+
});
|
|
114
|
+
});
|
|
115
|
+
};
|
|
116
|
+
UsbTransmitterClient.prototype.getInfo = function (channel) {
|
|
117
|
+
return __awaiter(this, void 0, void 0, function () {
|
|
118
|
+
var lowChannels, highChannels, data, release, responseBytes, response;
|
|
119
|
+
return __generator(this, function (_a) {
|
|
120
|
+
switch (_a.label) {
|
|
121
|
+
case 0:
|
|
122
|
+
lowChannels = (1 << (channel - 1)) & 0xff;
|
|
123
|
+
highChannels = (1 << (channel - 1)) >> 8;
|
|
124
|
+
data = [
|
|
125
|
+
constants_1.BYTE_HEADER,
|
|
126
|
+
constants_1.BYTE_LENGTH_4,
|
|
127
|
+
enums_1.EasyCommand.EASY_INFO,
|
|
128
|
+
highChannels,
|
|
129
|
+
lowChannels,
|
|
130
|
+
];
|
|
131
|
+
return [4 /*yield*/, mutex.acquire()];
|
|
132
|
+
case 1:
|
|
133
|
+
release = _a.sent();
|
|
134
|
+
_a.label = 2;
|
|
135
|
+
case 2:
|
|
136
|
+
_a.trys.push([2, , 5, 6]);
|
|
137
|
+
return [4 /*yield*/, this.sendCommand(data)];
|
|
138
|
+
case 3:
|
|
139
|
+
_a.sent();
|
|
140
|
+
return [4 /*yield*/, this.waitForResponse(constants_1.RESPONSE_LENGTH_INFO)];
|
|
141
|
+
case 4:
|
|
142
|
+
responseBytes = _a.sent();
|
|
143
|
+
response = this.parseResponse(responseBytes);
|
|
144
|
+
return [2 /*return*/, response];
|
|
145
|
+
case 5:
|
|
146
|
+
release();
|
|
147
|
+
return [7 /*endfinally*/];
|
|
148
|
+
case 6: return [2 /*return*/];
|
|
149
|
+
}
|
|
150
|
+
});
|
|
151
|
+
});
|
|
152
|
+
};
|
|
153
|
+
UsbTransmitterClient.prototype.sendControlCommand = function (channel, controlCommand) {
|
|
154
|
+
return __awaiter(this, void 0, void 0, function () {
|
|
155
|
+
var lowChannels, highChannels, data, release, responseBytes, response;
|
|
156
|
+
return __generator(this, function (_a) {
|
|
157
|
+
switch (_a.label) {
|
|
158
|
+
case 0:
|
|
159
|
+
lowChannels = (1 << (channel - 1)) & 0xff;
|
|
160
|
+
highChannels = (1 << (channel - 1)) >> 8;
|
|
161
|
+
data = [
|
|
162
|
+
constants_1.BYTE_HEADER,
|
|
163
|
+
constants_1.BYTE_LENGTH_5,
|
|
164
|
+
enums_1.EasyCommand.EASY_SEND,
|
|
165
|
+
highChannels,
|
|
166
|
+
lowChannels,
|
|
167
|
+
controlCommand,
|
|
168
|
+
];
|
|
169
|
+
return [4 /*yield*/, mutex.acquire()];
|
|
170
|
+
case 1:
|
|
171
|
+
release = _a.sent();
|
|
172
|
+
_a.label = 2;
|
|
173
|
+
case 2:
|
|
174
|
+
_a.trys.push([2, , 5, 6]);
|
|
175
|
+
return [4 /*yield*/, this.sendCommand(data)];
|
|
176
|
+
case 3:
|
|
177
|
+
_a.sent();
|
|
178
|
+
return [4 /*yield*/, this.waitForResponse(constants_1.RESPONSE_LENGTH_INFO)];
|
|
179
|
+
case 4:
|
|
180
|
+
responseBytes = _a.sent();
|
|
181
|
+
response = this.parseResponse(responseBytes);
|
|
182
|
+
return [2 /*return*/, response];
|
|
183
|
+
case 5:
|
|
184
|
+
release();
|
|
185
|
+
return [7 /*endfinally*/];
|
|
186
|
+
case 6: return [2 /*return*/];
|
|
187
|
+
}
|
|
188
|
+
});
|
|
189
|
+
});
|
|
190
|
+
};
|
|
191
|
+
UsbTransmitterClient.prototype.waitForResponse = function (length) {
|
|
192
|
+
var _this = this;
|
|
193
|
+
return new Promise(function (resolve, reject) {
|
|
194
|
+
var timeout = setTimeout(function () {
|
|
195
|
+
cleanup();
|
|
196
|
+
reject(new Error('Timeout waiting for response'));
|
|
197
|
+
}, 2000);
|
|
198
|
+
var tryRead = function () {
|
|
199
|
+
var buffer = _this.serialPort.read(length);
|
|
200
|
+
if (buffer) {
|
|
201
|
+
cleanup();
|
|
202
|
+
resolve(buffer);
|
|
203
|
+
}
|
|
204
|
+
};
|
|
205
|
+
var cleanup = function () {
|
|
206
|
+
clearTimeout(timeout);
|
|
207
|
+
_this.serialPort.removeListener('readable', tryRead);
|
|
208
|
+
};
|
|
209
|
+
_this.serialPort.on('readable', tryRead);
|
|
210
|
+
tryRead();
|
|
211
|
+
});
|
|
212
|
+
};
|
|
213
|
+
UsbTransmitterClient.prototype.sendCommand = function (data) {
|
|
214
|
+
var _this = this;
|
|
215
|
+
var checksum = this.calculateChecksum(data);
|
|
216
|
+
data.push(checksum);
|
|
217
|
+
return new Promise(function (resolve, reject) {
|
|
218
|
+
_this.serialPort.flush(function (error) {
|
|
219
|
+
if (error)
|
|
220
|
+
reject(error);
|
|
221
|
+
_this.serialPort.write(data, function (error) {
|
|
222
|
+
if (error)
|
|
223
|
+
reject(error);
|
|
224
|
+
resolve(data.length);
|
|
225
|
+
});
|
|
226
|
+
});
|
|
227
|
+
});
|
|
228
|
+
};
|
|
229
|
+
UsbTransmitterClient.prototype.readResponseBytes = function (length) {
|
|
230
|
+
//Get the serial data from the serial port.
|
|
231
|
+
var response = this.serialPort.read(length);
|
|
232
|
+
return response;
|
|
233
|
+
};
|
|
234
|
+
UsbTransmitterClient.prototype.calculateChecksum = function (data) {
|
|
235
|
+
//Calculate checksum.
|
|
236
|
+
//All the sum of all bytes (Header to CS) must be 0x00.
|
|
237
|
+
var sum = _.sum(data);
|
|
238
|
+
var result = (256 - sum) % 256;
|
|
239
|
+
return result;
|
|
240
|
+
};
|
|
241
|
+
UsbTransmitterClient.prototype.getActiveChannels = function (byte, start) {
|
|
242
|
+
var channels = new Array();
|
|
243
|
+
for (var i = 0; i < 9; i++) {
|
|
244
|
+
if (((byte >> i) & 1) == 1) {
|
|
245
|
+
var channel = i + start;
|
|
246
|
+
channels.push(channel);
|
|
247
|
+
}
|
|
248
|
+
}
|
|
249
|
+
return channels;
|
|
250
|
+
};
|
|
251
|
+
UsbTransmitterClient.prototype.parseResponse = function (bytes) {
|
|
252
|
+
var activeHighChannels = this.getActiveChannels(bytes[3], 9);
|
|
253
|
+
var activeLowChannels = this.getActiveChannels(bytes[4], 1);
|
|
254
|
+
var activeChannels = _.concat(activeLowChannels, activeHighChannels);
|
|
255
|
+
var response = {
|
|
256
|
+
header: bytes[0],
|
|
257
|
+
length: bytes[1],
|
|
258
|
+
command: bytes[2],
|
|
259
|
+
activeChannels: activeChannels,
|
|
260
|
+
checksum: -1,
|
|
261
|
+
status: null,
|
|
262
|
+
statusCode: -1,
|
|
263
|
+
};
|
|
264
|
+
if (bytes.length == constants_1.RESPONSE_LENGTH_CHECK) {
|
|
265
|
+
response.checksum = bytes[5];
|
|
266
|
+
//Easy Ack (the answer on Easy Info)
|
|
267
|
+
}
|
|
268
|
+
else if (bytes.length == constants_1.RESPONSE_LENGTH_SEND) {
|
|
269
|
+
if (bytes[5] in enums_1.InfoData) {
|
|
270
|
+
response.status = bytes[5];
|
|
271
|
+
}
|
|
272
|
+
else {
|
|
273
|
+
response.status = enums_1.InfoData.INFO_UNKNOWN;
|
|
274
|
+
}
|
|
275
|
+
response.checksum = bytes[6];
|
|
276
|
+
}
|
|
277
|
+
else {
|
|
278
|
+
response.status = enums_1.InfoData.INFO_UNKNOWN;
|
|
279
|
+
}
|
|
280
|
+
return response;
|
|
281
|
+
};
|
|
282
|
+
return UsbTransmitterClient;
|
|
283
|
+
}());
|
|
284
|
+
exports.UsbTransmitterClient = UsbTransmitterClient;
|
package/dist/cli.d.ts
ADDED
package/dist/cli.js
ADDED
|
@@ -0,0 +1,277 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
"use strict";
|
|
3
|
+
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
|
|
4
|
+
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
|
|
5
|
+
return new (P || (P = Promise))(function (resolve, reject) {
|
|
6
|
+
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
|
|
7
|
+
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
|
|
8
|
+
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
|
|
9
|
+
step((generator = generator.apply(thisArg, _arguments || [])).next());
|
|
10
|
+
});
|
|
11
|
+
};
|
|
12
|
+
var __generator = (this && this.__generator) || function (thisArg, body) {
|
|
13
|
+
var _ = { label: 0, sent: function() { if (t[0] & 1) throw t[1]; return t[1]; }, trys: [], ops: [] }, f, y, t, g;
|
|
14
|
+
return g = { next: verb(0), "throw": verb(1), "return": verb(2) }, typeof Symbol === "function" && (g[Symbol.iterator] = function() { return this; }), g;
|
|
15
|
+
function verb(n) { return function (v) { return step([n, v]); }; }
|
|
16
|
+
function step(op) {
|
|
17
|
+
if (f) throw new TypeError("Generator is already executing.");
|
|
18
|
+
while (_) try {
|
|
19
|
+
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;
|
|
20
|
+
if (y = 0, t) op = [op[0] & 2, t.value];
|
|
21
|
+
switch (op[0]) {
|
|
22
|
+
case 0: case 1: t = op; break;
|
|
23
|
+
case 4: _.label++; return { value: op[1], done: false };
|
|
24
|
+
case 5: _.label++; y = op[1]; op = [0]; continue;
|
|
25
|
+
case 7: op = _.ops.pop(); _.trys.pop(); continue;
|
|
26
|
+
default:
|
|
27
|
+
if (!(t = _.trys, t = t.length > 0 && t[t.length - 1]) && (op[0] === 6 || op[0] === 2)) { _ = 0; continue; }
|
|
28
|
+
if (op[0] === 3 && (!t || (op[1] > t[0] && op[1] < t[3]))) { _.label = op[1]; break; }
|
|
29
|
+
if (op[0] === 6 && _.label < t[1]) { _.label = t[1]; t = op; break; }
|
|
30
|
+
if (t && _.label < t[2]) { _.label = t[2]; _.ops.push(op); break; }
|
|
31
|
+
if (t[2]) _.ops.pop();
|
|
32
|
+
_.trys.pop(); continue;
|
|
33
|
+
}
|
|
34
|
+
op = body.call(thisArg, _);
|
|
35
|
+
} catch (e) { op = [6, e]; y = 0; } finally { f = t = 0; }
|
|
36
|
+
if (op[0] & 5) throw op[1]; return { value: op[0] ? op[1] : void 0, done: true };
|
|
37
|
+
}
|
|
38
|
+
};
|
|
39
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
40
|
+
var commander_1 = require("commander");
|
|
41
|
+
var inquirer = require("inquirer");
|
|
42
|
+
var UsbTransmitterClient_1 = require("./UsbTransmitterClient");
|
|
43
|
+
var enums_1 = require("./domain/enums");
|
|
44
|
+
var serialport_1 = require("serialport");
|
|
45
|
+
var program = new commander_1.Command();
|
|
46
|
+
var client = null;
|
|
47
|
+
program
|
|
48
|
+
.version('1.0.0')
|
|
49
|
+
.option('-p, --port <path>', 'Path to serial port')
|
|
50
|
+
.parse(process.argv);
|
|
51
|
+
var options = program.opts();
|
|
52
|
+
function main() {
|
|
53
|
+
return __awaiter(this, void 0, void 0, function () {
|
|
54
|
+
var portPath, ports, portChoices, answer, error_1;
|
|
55
|
+
return __generator(this, function (_a) {
|
|
56
|
+
switch (_a.label) {
|
|
57
|
+
case 0:
|
|
58
|
+
portPath = options.port;
|
|
59
|
+
if (!!portPath) return [3 /*break*/, 3];
|
|
60
|
+
return [4 /*yield*/, serialport_1.SerialPort.list()];
|
|
61
|
+
case 1:
|
|
62
|
+
ports = _a.sent();
|
|
63
|
+
portChoices = ports.map(function (p) { return ({ name: p.path + " " + (p.manufacturer || ''), value: p.path }); });
|
|
64
|
+
if (portChoices.length === 0) {
|
|
65
|
+
console.error('No serial ports found. Please specify one with --port.');
|
|
66
|
+
process.exit(1);
|
|
67
|
+
}
|
|
68
|
+
return [4 /*yield*/, inquirer.prompt([
|
|
69
|
+
{
|
|
70
|
+
type: 'list',
|
|
71
|
+
name: 'port',
|
|
72
|
+
message: 'Select Serial Port',
|
|
73
|
+
choices: portChoices,
|
|
74
|
+
},
|
|
75
|
+
])];
|
|
76
|
+
case 2:
|
|
77
|
+
answer = _a.sent();
|
|
78
|
+
portPath = answer.port;
|
|
79
|
+
_a.label = 3;
|
|
80
|
+
case 3:
|
|
81
|
+
client = new UsbTransmitterClient_1.UsbTransmitterClient(portPath);
|
|
82
|
+
_a.label = 4;
|
|
83
|
+
case 4:
|
|
84
|
+
_a.trys.push([4, 7, , 8]);
|
|
85
|
+
return [4 /*yield*/, client.open()];
|
|
86
|
+
case 5:
|
|
87
|
+
_a.sent();
|
|
88
|
+
console.log("Connected to " + portPath);
|
|
89
|
+
return [4 /*yield*/, mainMenu()];
|
|
90
|
+
case 6:
|
|
91
|
+
_a.sent();
|
|
92
|
+
return [3 /*break*/, 8];
|
|
93
|
+
case 7:
|
|
94
|
+
error_1 = _a.sent();
|
|
95
|
+
console.error('Error connecting to device:', error_1);
|
|
96
|
+
process.exit(1);
|
|
97
|
+
return [3 /*break*/, 8];
|
|
98
|
+
case 8: return [2 /*return*/];
|
|
99
|
+
}
|
|
100
|
+
});
|
|
101
|
+
});
|
|
102
|
+
}
|
|
103
|
+
function mainMenu() {
|
|
104
|
+
return __awaiter(this, void 0, void 0, function () {
|
|
105
|
+
var answer, _a;
|
|
106
|
+
return __generator(this, function (_b) {
|
|
107
|
+
switch (_b.label) {
|
|
108
|
+
case 0: return [4 /*yield*/, inquirer.prompt([
|
|
109
|
+
{
|
|
110
|
+
type: 'list',
|
|
111
|
+
name: 'action',
|
|
112
|
+
message: 'Main Menu',
|
|
113
|
+
choices: [
|
|
114
|
+
{ name: 'Check Channels', value: 'check' },
|
|
115
|
+
{ name: 'Select Channel', value: 'select' },
|
|
116
|
+
new inquirer.Separator(),
|
|
117
|
+
{ name: 'Exit', value: 'exit' },
|
|
118
|
+
],
|
|
119
|
+
},
|
|
120
|
+
])];
|
|
121
|
+
case 1:
|
|
122
|
+
answer = _b.sent();
|
|
123
|
+
_a = answer.action;
|
|
124
|
+
switch (_a) {
|
|
125
|
+
case 'check': return [3 /*break*/, 2];
|
|
126
|
+
case 'select': return [3 /*break*/, 4];
|
|
127
|
+
case 'exit': return [3 /*break*/, 6];
|
|
128
|
+
}
|
|
129
|
+
return [3 /*break*/, 8];
|
|
130
|
+
case 2: return [4 /*yield*/, checkChannels()];
|
|
131
|
+
case 3:
|
|
132
|
+
_b.sent();
|
|
133
|
+
return [3 /*break*/, 8];
|
|
134
|
+
case 4: return [4 /*yield*/, selectChannel()];
|
|
135
|
+
case 5:
|
|
136
|
+
_b.sent();
|
|
137
|
+
return [3 /*break*/, 8];
|
|
138
|
+
case 6: return [4 /*yield*/, client.close()];
|
|
139
|
+
case 7:
|
|
140
|
+
_b.sent();
|
|
141
|
+
process.exit(0);
|
|
142
|
+
_b.label = 8;
|
|
143
|
+
case 8: return [2 /*return*/];
|
|
144
|
+
}
|
|
145
|
+
});
|
|
146
|
+
});
|
|
147
|
+
}
|
|
148
|
+
function checkChannels() {
|
|
149
|
+
return __awaiter(this, void 0, void 0, function () {
|
|
150
|
+
var channels, error_2;
|
|
151
|
+
return __generator(this, function (_a) {
|
|
152
|
+
switch (_a.label) {
|
|
153
|
+
case 0:
|
|
154
|
+
console.log('Checking channels...');
|
|
155
|
+
_a.label = 1;
|
|
156
|
+
case 1:
|
|
157
|
+
_a.trys.push([1, 3, , 4]);
|
|
158
|
+
return [4 /*yield*/, client.checkChannels()];
|
|
159
|
+
case 2:
|
|
160
|
+
channels = _a.sent();
|
|
161
|
+
console.log('Active Channels:', channels.join(', '));
|
|
162
|
+
return [3 /*break*/, 4];
|
|
163
|
+
case 3:
|
|
164
|
+
error_2 = _a.sent();
|
|
165
|
+
console.error('Error checking channels:', error_2);
|
|
166
|
+
return [3 /*break*/, 4];
|
|
167
|
+
case 4: return [4 /*yield*/, mainMenu()];
|
|
168
|
+
case 5:
|
|
169
|
+
_a.sent();
|
|
170
|
+
return [2 /*return*/];
|
|
171
|
+
}
|
|
172
|
+
});
|
|
173
|
+
});
|
|
174
|
+
}
|
|
175
|
+
function selectChannel() {
|
|
176
|
+
return __awaiter(this, void 0, void 0, function () {
|
|
177
|
+
var answer, channel;
|
|
178
|
+
return __generator(this, function (_a) {
|
|
179
|
+
switch (_a.label) {
|
|
180
|
+
case 0: return [4 /*yield*/, inquirer.prompt([
|
|
181
|
+
{
|
|
182
|
+
type: 'input',
|
|
183
|
+
name: 'channel',
|
|
184
|
+
message: 'Enter Channel Number (1-9):',
|
|
185
|
+
validate: function (input) {
|
|
186
|
+
var num = parseInt(input, 10);
|
|
187
|
+
if (isNaN(num) || num < 1 || num > 9) {
|
|
188
|
+
return 'Please enter a number between 1 and 9';
|
|
189
|
+
}
|
|
190
|
+
return true;
|
|
191
|
+
},
|
|
192
|
+
},
|
|
193
|
+
])];
|
|
194
|
+
case 1:
|
|
195
|
+
answer = _a.sent();
|
|
196
|
+
channel = parseInt(answer.channel, 10);
|
|
197
|
+
return [4 /*yield*/, channelMenu(channel)];
|
|
198
|
+
case 2:
|
|
199
|
+
_a.sent();
|
|
200
|
+
return [2 /*return*/];
|
|
201
|
+
}
|
|
202
|
+
});
|
|
203
|
+
});
|
|
204
|
+
}
|
|
205
|
+
function channelMenu(channel) {
|
|
206
|
+
return __awaiter(this, void 0, void 0, function () {
|
|
207
|
+
var answer, info, cmd, response, error_3;
|
|
208
|
+
return __generator(this, function (_a) {
|
|
209
|
+
switch (_a.label) {
|
|
210
|
+
case 0: return [4 /*yield*/, inquirer.prompt([
|
|
211
|
+
{
|
|
212
|
+
type: 'list',
|
|
213
|
+
name: 'action',
|
|
214
|
+
message: "Channel " + channel + " Actions",
|
|
215
|
+
choices: [
|
|
216
|
+
{ name: 'Get Info', value: 'info' },
|
|
217
|
+
{ name: 'Move Up', value: 'up' },
|
|
218
|
+
{ name: 'Move Down', value: 'down' },
|
|
219
|
+
{ name: 'Stop', value: 'stop' },
|
|
220
|
+
new inquirer.Separator(),
|
|
221
|
+
{ name: 'Back to Main Menu', value: 'back' },
|
|
222
|
+
],
|
|
223
|
+
},
|
|
224
|
+
])];
|
|
225
|
+
case 1:
|
|
226
|
+
answer = _a.sent();
|
|
227
|
+
if (!(answer.action === 'back')) return [3 /*break*/, 3];
|
|
228
|
+
return [4 /*yield*/, mainMenu()];
|
|
229
|
+
case 2:
|
|
230
|
+
_a.sent();
|
|
231
|
+
return [2 /*return*/];
|
|
232
|
+
case 3:
|
|
233
|
+
_a.trys.push([3, 8, , 9]);
|
|
234
|
+
if (!(answer.action === 'info')) return [3 /*break*/, 5];
|
|
235
|
+
return [4 /*yield*/, client.getInfo(channel)];
|
|
236
|
+
case 4:
|
|
237
|
+
info = _a.sent();
|
|
238
|
+
console.log('Channel Info:', info);
|
|
239
|
+
return [3 /*break*/, 7];
|
|
240
|
+
case 5:
|
|
241
|
+
cmd = void 0;
|
|
242
|
+
switch (answer.action) {
|
|
243
|
+
case 'up':
|
|
244
|
+
cmd = enums_1.ControlCommand.up;
|
|
245
|
+
break;
|
|
246
|
+
case 'down':
|
|
247
|
+
cmd = enums_1.ControlCommand.down;
|
|
248
|
+
break;
|
|
249
|
+
case 'stop':
|
|
250
|
+
cmd = enums_1.ControlCommand.stop;
|
|
251
|
+
break;
|
|
252
|
+
default:
|
|
253
|
+
throw new Error('Unknown command');
|
|
254
|
+
}
|
|
255
|
+
console.log("Sending " + answer.action + " command to channel " + channel + "...");
|
|
256
|
+
return [4 /*yield*/, client.sendControlCommand(channel, cmd)];
|
|
257
|
+
case 6:
|
|
258
|
+
response = _a.sent();
|
|
259
|
+
console.log('Response:', response);
|
|
260
|
+
_a.label = 7;
|
|
261
|
+
case 7: return [3 /*break*/, 9];
|
|
262
|
+
case 8:
|
|
263
|
+
error_3 = _a.sent();
|
|
264
|
+
console.error('Error executing command:', error_3);
|
|
265
|
+
return [3 /*break*/, 9];
|
|
266
|
+
case 9: return [4 /*yield*/, channelMenu(channel)];
|
|
267
|
+
case 10:
|
|
268
|
+
_a.sent();
|
|
269
|
+
return [2 /*return*/];
|
|
270
|
+
}
|
|
271
|
+
});
|
|
272
|
+
});
|
|
273
|
+
}
|
|
274
|
+
main().catch(function (err) {
|
|
275
|
+
console.error('Unexpected error:', err);
|
|
276
|
+
process.exit(1);
|
|
277
|
+
});
|