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.
@@ -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
  [![npm version](https://img.shields.io/npm/v/elero-usb-transmitter-client.svg?style=flat-square)](https://www.npmjs.com/package/elero-usb-transmitter-client)
4
- [![build status](https://img.shields.io/travis/marc2016/elero-usb-transmitter-client/master.svg?style=flat-square)](https://travis-ci.org/github/marc2016/elero-usb-transmitter-client)
4
+ [![Node.js CI](https://github.com/marc2016/elero-usb-transmitter-client/actions/workflows/nodejs.yml/badge.svg)](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
@@ -0,0 +1,2 @@
1
+ #!/usr/bin/env node
2
+ export {};
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
+ });