@sebbo2002/node-pyatv 6.0.0-develop.2 → 6.0.0-develop.3
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/dist/bin/check.cjs +10 -0
- package/dist/bin/check.cjs.map +1 -0
- package/dist/bin/check.d.ts +2 -1
- package/dist/bin/check.js +4 -45
- package/dist/bin/check.js.map +1 -1
- package/dist/chunk-TZSWUAOB.js +7 -0
- package/dist/chunk-TZSWUAOB.js.map +1 -0
- package/dist/lib/index.cjs +7 -0
- package/dist/lib/index.cjs.map +1 -0
- package/dist/lib/{device.d.ts → index.d.cts} +340 -4
- package/dist/lib/index.d.ts +806 -6
- package/dist/lib/index.js +1 -7
- package/dist/lib/index.js.map +1 -1
- package/package.json +18 -9
- package/.editorconfig +0 -12
- package/.eslintignore +0 -4
- package/.eslintrc +0 -60
- package/.mocharc.yml +0 -7
- package/.nycrc +0 -32
- package/CHANGELOG.md +0 -295
- package/check.sh +0 -5
- package/dist/examples/push.d.ts +0 -1
- package/dist/examples/push.js +0 -51
- package/dist/examples/push.js.map +0 -1
- package/dist/lib/device-event.d.ts +0 -44
- package/dist/lib/device-event.js +0 -47
- package/dist/lib/device-event.js.map +0 -1
- package/dist/lib/device-events.d.ts +0 -30
- package/dist/lib/device-events.js +0 -237
- package/dist/lib/device-events.js.map +0 -1
- package/dist/lib/device.js +0 -793
- package/dist/lib/device.js.map +0 -1
- package/dist/lib/fake-spawn.d.ts +0 -43
- package/dist/lib/fake-spawn.js +0 -85
- package/dist/lib/fake-spawn.js.map +0 -1
- package/dist/lib/instance.d.ts +0 -97
- package/dist/lib/instance.js +0 -208
- package/dist/lib/instance.js.map +0 -1
- package/dist/lib/tools.d.ts +0 -12
- package/dist/lib/tools.js +0 -319
- package/dist/lib/tools.js.map +0 -1
- package/dist/lib/types.d.ts +0 -204
- package/dist/lib/types.js +0 -108
- package/dist/lib/types.js.map +0 -1
- package/docs/coverage/base.css +0 -224
- package/docs/coverage/block-navigation.js +0 -87
- package/docs/coverage/cobertura-coverage.xml +0 -2889
- package/docs/coverage/device-event.ts.html +0 -256
- package/docs/coverage/device-events.ts.html +0 -970
- package/docs/coverage/device.ts.html +0 -2518
- package/docs/coverage/fake-spawn.ts.html +0 -448
- package/docs/coverage/favicon.png +0 -0
- package/docs/coverage/index.html +0 -221
- package/docs/coverage/index.ts.html +0 -172
- package/docs/coverage/instance.ts.html +0 -718
- package/docs/coverage/prettify.css +0 -1
- package/docs/coverage/prettify.js +0 -2
- package/docs/coverage/sort-arrow-sprite.png +0 -0
- package/docs/coverage/sorter.js +0 -196
- package/docs/coverage/tools.ts.html +0 -1222
- package/docs/coverage/types.ts.html +0 -775
- package/docs/reference/.nojekyll +0 -1
- package/docs/reference/assets/highlight.css +0 -99
- package/docs/reference/assets/main.js +0 -58
- package/docs/reference/assets/search.js +0 -1
- package/docs/reference/assets/style.css +0 -1280
- package/docs/reference/classes/NodePyATVDevice.html +0 -1266
- package/docs/reference/classes/NodePyATVDeviceEvent.html +0 -123
- package/docs/reference/classes/NodePyATVInstance.html +0 -240
- package/docs/reference/enums/NodePyATVDeviceState.html +0 -97
- package/docs/reference/enums/NodePyATVExecutableType.html +0 -69
- package/docs/reference/enums/NodePyATVKeys.html +0 -216
- package/docs/reference/enums/NodePyATVListenerState.html +0 -83
- package/docs/reference/enums/NodePyATVMediaType.html +0 -83
- package/docs/reference/enums/NodePyATVPowerState.html +0 -69
- package/docs/reference/enums/NodePyATVProtocol.html +0 -83
- package/docs/reference/enums/NodePyATVRepeatState.html +0 -76
- package/docs/reference/enums/NodePyATVShuffleState.html +0 -76
- package/docs/reference/index.html +0 -139
- package/docs/reference/interfaces/NodePyATVDeviceOptions.html +0 -232
- package/docs/reference/interfaces/NodePyATVFindAndInstanceOptions.html +0 -193
- package/docs/reference/interfaces/NodePyATVFindOptions.html +0 -124
- package/docs/reference/interfaces/NodePyATVGetStateOptions.html +0 -66
- package/docs/reference/interfaces/NodePyATVInstanceOptions.html +0 -113
- package/docs/reference/interfaces/NodePyATVService.html +0 -73
- package/docs/reference/interfaces/NodePyATVState.html +0 -164
- package/docs/reference/interfaces/NodePyATVVersionResponse.html +0 -73
- package/docs/reference/modules.html +0 -106
- package/docs/reference/types/NodePyATVEventValueType.html +0 -66
- package/docs/tests/assets/MaterialIcons-Regular.woff +0 -0
- package/docs/tests/assets/MaterialIcons-Regular.woff2 +0 -0
- package/docs/tests/assets/app.css +0 -14
- package/docs/tests/assets/app.js +0 -2
- package/docs/tests/assets/app.js.LICENSE.txt +0 -55
- package/docs/tests/assets/roboto-light-webfont.woff +0 -0
- package/docs/tests/assets/roboto-light-webfont.woff2 +0 -0
- package/docs/tests/assets/roboto-medium-webfont.woff +0 -0
- package/docs/tests/assets/roboto-medium-webfont.woff2 +0 -0
- package/docs/tests/assets/roboto-regular-webfont.woff +0 -0
- package/docs/tests/assets/roboto-regular-webfont.woff2 +0 -0
- package/docs/tests/index.html +0 -2
- package/docs/tests/mochawesome.json +0 -4823
- package/release.config.cjs +0 -51
- package/src/bin/check.ts +0 -41
- package/src/examples/push.ts +0 -46
- package/src/lib/device-event.ts +0 -57
- package/src/lib/device-events.ts +0 -295
- package/src/lib/device.ts +0 -811
- package/src/lib/fake-spawn.ts +0 -121
- package/src/lib/index.ts +0 -29
- package/src/lib/instance.ts +0 -211
- package/src/lib/tools.ts +0 -379
- package/src/lib/types.ts +0 -230
- package/test/device-event.ts +0 -88
- package/test/device-events.ts +0 -502
- package/test/device.ts +0 -826
- package/test/instance.ts +0 -428
- package/test/tools.ts +0 -301
- package/tsconfig.json +0 -19
- package/typedoc.json +0 -15
package/src/lib/device.ts
DELETED
|
@@ -1,811 +0,0 @@
|
|
|
1
|
-
'use strict';
|
|
2
|
-
|
|
3
|
-
import {
|
|
4
|
-
NodePyATVApp,
|
|
5
|
-
NodePyATVDeviceOptions,
|
|
6
|
-
NodePyATVDeviceState,
|
|
7
|
-
NodePyATVExecutableType,
|
|
8
|
-
NodePyATVGetStateOptions,
|
|
9
|
-
NodePyATVInternalKeys,
|
|
10
|
-
NodePyATVKeys,
|
|
11
|
-
NodePyATVMediaType,
|
|
12
|
-
NodePyATVProtocol,
|
|
13
|
-
NodePyATVRepeatState,
|
|
14
|
-
NodePyATVService,
|
|
15
|
-
NodePyATVShuffleState,
|
|
16
|
-
NodePyATVState
|
|
17
|
-
} from './types.js';
|
|
18
|
-
|
|
19
|
-
import { addRequestId, getParamters, parseState, removeRequestId, request } from './tools.js';
|
|
20
|
-
import { NodePyATVDeviceEvent, NodePyATVDeviceEvents } from '../lib/index.js';
|
|
21
|
-
import { EventEmitter } from 'events';
|
|
22
|
-
|
|
23
|
-
/**
|
|
24
|
-
* Represents an Apple TV. Use [[getState]] to query the current state (e.g. media
|
|
25
|
-
* type and title). You can also use the attribute methods (e.g. [[getTitle]] to get
|
|
26
|
-
* the state. If you want realtime updates, subscribe to it's events with an
|
|
27
|
-
* `EventEmitter` like API, so for example by using [[on]], [[once]] or [[addListener]].
|
|
28
|
-
* It's also possible to send key commands by using [[pressKey]] or methods like [[pause]].
|
|
29
|
-
*/
|
|
30
|
-
export default class NodePyATVDevice implements EventEmitter{
|
|
31
|
-
private readonly options: NodePyATVDeviceOptions;
|
|
32
|
-
private readonly state: NodePyATVState;
|
|
33
|
-
private readonly events: NodePyATVDeviceEvents;
|
|
34
|
-
|
|
35
|
-
constructor(options: NodePyATVDeviceOptions) {
|
|
36
|
-
this.options = Object.assign({}, options);
|
|
37
|
-
this.state = parseState({}, '', {});
|
|
38
|
-
this.events = new NodePyATVDeviceEvents(this.state, this, this.options);
|
|
39
|
-
|
|
40
|
-
// @todo basic validation
|
|
41
|
-
}
|
|
42
|
-
|
|
43
|
-
/**
|
|
44
|
-
* Get the name of the Apple TV.
|
|
45
|
-
*
|
|
46
|
-
* ```typescript
|
|
47
|
-
* import pyatv from '@sebbo2002/node-pyatv';
|
|
48
|
-
* const devices = await pyatv.find();
|
|
49
|
-
* devices.forEach(device =>
|
|
50
|
-
* console.log(device.name)
|
|
51
|
-
* );
|
|
52
|
-
* ```
|
|
53
|
-
*/
|
|
54
|
-
get name(): string {
|
|
55
|
-
return this.options.name;
|
|
56
|
-
}
|
|
57
|
-
|
|
58
|
-
/**
|
|
59
|
-
* Get the IP address of the Apple TV.
|
|
60
|
-
*/
|
|
61
|
-
get host(): string {
|
|
62
|
-
return this.options.host;
|
|
63
|
-
}
|
|
64
|
-
|
|
65
|
-
/**
|
|
66
|
-
* Get the ID of the Apple TV.
|
|
67
|
-
*/
|
|
68
|
-
get id(): string | undefined {
|
|
69
|
-
return this.options.id;
|
|
70
|
-
}
|
|
71
|
-
|
|
72
|
-
/**
|
|
73
|
-
* Get the used protocol to connect to the Apple TV.
|
|
74
|
-
*/
|
|
75
|
-
get protocol(): NodePyATVProtocol | undefined {
|
|
76
|
-
return this.options.protocol;
|
|
77
|
-
}
|
|
78
|
-
|
|
79
|
-
/**
|
|
80
|
-
* Get the model identifier of the device. Only set, if the
|
|
81
|
-
* device was found using [[find()]]. Requires pyatv ≧ 0.10.3.
|
|
82
|
-
*
|
|
83
|
-
* @example device.model → "Gen4K"
|
|
84
|
-
*/
|
|
85
|
-
get model(): string | undefined {
|
|
86
|
-
return this.options.model;
|
|
87
|
-
}
|
|
88
|
-
|
|
89
|
-
/**
|
|
90
|
-
* Get the model name of the device. Only set, if the device
|
|
91
|
-
* was found with [[find()]]. Requires pyatv ≧ 0.10.3.
|
|
92
|
-
*
|
|
93
|
-
* @example device.modelName → "Apple TV 4K"
|
|
94
|
-
*/
|
|
95
|
-
get modelName(): string | undefined {
|
|
96
|
-
return this.options.modelName;
|
|
97
|
-
}
|
|
98
|
-
|
|
99
|
-
/**
|
|
100
|
-
* Get the operating system of the device. Only set, if the
|
|
101
|
-
* device was found with [[find()]]. Requires pyatv ≧ 0.10.3.
|
|
102
|
-
*
|
|
103
|
-
* @example device.os → "TvOS"
|
|
104
|
-
*/
|
|
105
|
-
get os(): string | undefined {
|
|
106
|
-
return this.options.os;
|
|
107
|
-
}
|
|
108
|
-
|
|
109
|
-
/**
|
|
110
|
-
* Get the device version. Only set, if the device was found
|
|
111
|
-
* during a scan using [[find()]]. Requires pyatv ≧ 0.10.3.
|
|
112
|
-
*
|
|
113
|
-
* @example device.version → "15.5.1"
|
|
114
|
-
*/
|
|
115
|
-
get version(): string | undefined {
|
|
116
|
-
return this.options.version;
|
|
117
|
-
}
|
|
118
|
-
|
|
119
|
-
/**
|
|
120
|
-
* Returns a list of services supported by the device. Ony set, if
|
|
121
|
-
* the device was found during a scan using [[find()]]. Requires
|
|
122
|
-
* pyatv ≧ 0.10.3.
|
|
123
|
-
*
|
|
124
|
-
* @example device.services → [
|
|
125
|
-
* {
|
|
126
|
-
* "protocol": "airplay",
|
|
127
|
-
* "port": 7000
|
|
128
|
-
* },
|
|
129
|
-
* {
|
|
130
|
-
* "protocol": "dmap",
|
|
131
|
-
* "port": 3689
|
|
132
|
-
* }
|
|
133
|
-
* ]
|
|
134
|
-
*/
|
|
135
|
-
get services(): NodePyATVService[] | undefined {
|
|
136
|
-
return this.options.services;
|
|
137
|
-
}
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
/**
|
|
141
|
-
* Returns true, if debugging is enabled. Returns the custom
|
|
142
|
-
* logging method, if one was specified. Otherwise, if debug
|
|
143
|
-
* log is disabled, returns undefined.
|
|
144
|
-
*/
|
|
145
|
-
get debug(): true | ((msg: string) => void) | undefined {
|
|
146
|
-
return this.options.debug;
|
|
147
|
-
}
|
|
148
|
-
|
|
149
|
-
/**
|
|
150
|
-
* Enable or disable debugging or set a custom
|
|
151
|
-
* debugging method to use.
|
|
152
|
-
*
|
|
153
|
-
* @param debug
|
|
154
|
-
*/
|
|
155
|
-
set debug(debug: true | ((msg: string) => void) | undefined) {
|
|
156
|
-
if (typeof debug === 'function') {
|
|
157
|
-
this.options.debug = debug;
|
|
158
|
-
}
|
|
159
|
-
else {
|
|
160
|
-
this.options.debug = Boolean(debug) || undefined;
|
|
161
|
-
}
|
|
162
|
-
}
|
|
163
|
-
|
|
164
|
-
/**
|
|
165
|
-
* Returns an object with `name`, `host`, `id` and `protocol`.
|
|
166
|
-
* Can be used to initiate a new device instance.
|
|
167
|
-
*
|
|
168
|
-
* @category Basic
|
|
169
|
-
*/
|
|
170
|
-
toJSON(): { name: string; host: string; id: string | undefined; protocol: NodePyATVProtocol | undefined } {
|
|
171
|
-
return {
|
|
172
|
-
name: this.name,
|
|
173
|
-
host: this.host,
|
|
174
|
-
id: this.id,
|
|
175
|
-
protocol: this.protocol
|
|
176
|
-
};
|
|
177
|
-
}
|
|
178
|
-
|
|
179
|
-
/**
|
|
180
|
-
* Returns a string. Just for debugging, etc.
|
|
181
|
-
*
|
|
182
|
-
* @category Basic
|
|
183
|
-
*/
|
|
184
|
-
toString(): string {
|
|
185
|
-
return `NodePyATVDevice(${this.name}, ${this.host})`;
|
|
186
|
-
}
|
|
187
|
-
|
|
188
|
-
/**
|
|
189
|
-
* Returns an [[NodePyATVState]] object representing the current state
|
|
190
|
-
* of the device. Has an internal cache, which has a default TTL of 5s.
|
|
191
|
-
* You can change this default value by passing the `maxAge` option.
|
|
192
|
-
*
|
|
193
|
-
* ```typescript
|
|
194
|
-
* await device.getState({maxAge: 10000}); // cache TTL: 10s
|
|
195
|
-
* ```
|
|
196
|
-
*
|
|
197
|
-
* @param options
|
|
198
|
-
* @category State
|
|
199
|
-
*/
|
|
200
|
-
async getState(options: NodePyATVGetStateOptions = {}): Promise<NodePyATVState> {
|
|
201
|
-
if (this.state?.dateTime && new Date().getTime() - this.state.dateTime.getTime() < (options.maxAge || 5000)) {
|
|
202
|
-
let position = null;
|
|
203
|
-
if (this.state.position && this.state.dateTime) {
|
|
204
|
-
position = Math.round(
|
|
205
|
-
this.state.position +
|
|
206
|
-
((new Date().getTime() - this.state.dateTime.getTime()) / 1000)
|
|
207
|
-
);
|
|
208
|
-
}
|
|
209
|
-
|
|
210
|
-
return Object.assign({}, this.state, {position});
|
|
211
|
-
}
|
|
212
|
-
|
|
213
|
-
const id = addRequestId();
|
|
214
|
-
|
|
215
|
-
try {
|
|
216
|
-
const parameters = getParamters(this.options);
|
|
217
|
-
|
|
218
|
-
const result = await request(id, NodePyATVExecutableType.atvscript, [...parameters, 'playing'], this.options);
|
|
219
|
-
const newState = parseState(result, id, this.options);
|
|
220
|
-
|
|
221
|
-
this.applyState(newState);
|
|
222
|
-
return newState;
|
|
223
|
-
}
|
|
224
|
-
finally {
|
|
225
|
-
removeRequestId(id);
|
|
226
|
-
}
|
|
227
|
-
}
|
|
228
|
-
|
|
229
|
-
/**
|
|
230
|
-
* Removes the state node-pyatv cached for this device.
|
|
231
|
-
*
|
|
232
|
-
* @category State
|
|
233
|
-
*/
|
|
234
|
-
clearState(): void {
|
|
235
|
-
this.applyState(parseState({}, '', {}));
|
|
236
|
-
}
|
|
237
|
-
|
|
238
|
-
private applyState(newState: NodePyATVState): void {
|
|
239
|
-
this.events.applyStateAndEmitEvents(newState);
|
|
240
|
-
}
|
|
241
|
-
|
|
242
|
-
/**
|
|
243
|
-
* Get the date and time when the state was last updated.
|
|
244
|
-
* @param options
|
|
245
|
-
* @category State
|
|
246
|
-
*/
|
|
247
|
-
async getDateTime(options: NodePyATVGetStateOptions = {}): Promise<Date | null> {
|
|
248
|
-
const state = await this.getState(options);
|
|
249
|
-
return state.dateTime;
|
|
250
|
-
}
|
|
251
|
-
|
|
252
|
-
/**
|
|
253
|
-
* Get the hash of the current media
|
|
254
|
-
* @param options
|
|
255
|
-
* @category State
|
|
256
|
-
*/
|
|
257
|
-
async getHash(options: NodePyATVGetStateOptions = {}): Promise<string | null> {
|
|
258
|
-
const state = await this.getState(options);
|
|
259
|
-
return state.hash;
|
|
260
|
-
}
|
|
261
|
-
|
|
262
|
-
/**
|
|
263
|
-
* Get the media type of the current media
|
|
264
|
-
* @param options
|
|
265
|
-
* @category State
|
|
266
|
-
*/
|
|
267
|
-
async getMediaType(options: NodePyATVGetStateOptions = {}): Promise<NodePyATVMediaType | null> {
|
|
268
|
-
const state = await this.getState(options);
|
|
269
|
-
return state.mediaType;
|
|
270
|
-
}
|
|
271
|
-
|
|
272
|
-
/**
|
|
273
|
-
* Get the state of this device (e.g. playing, etc.)
|
|
274
|
-
* @param options
|
|
275
|
-
* @category State
|
|
276
|
-
*/
|
|
277
|
-
async getDeviceState(options: NodePyATVGetStateOptions = {}): Promise<NodePyATVDeviceState | null> {
|
|
278
|
-
const state = await this.getState(options);
|
|
279
|
-
return state.deviceState;
|
|
280
|
-
}
|
|
281
|
-
|
|
282
|
-
/**
|
|
283
|
-
* Returns the title of the current playing media
|
|
284
|
-
* @param options
|
|
285
|
-
* @category State
|
|
286
|
-
*/
|
|
287
|
-
async getTitle(options: NodePyATVGetStateOptions = {}): Promise<string | null> {
|
|
288
|
-
const state = await this.getState(options);
|
|
289
|
-
return state.title;
|
|
290
|
-
}
|
|
291
|
-
|
|
292
|
-
/**
|
|
293
|
-
* Returns the artist of the current playing media
|
|
294
|
-
* @param options
|
|
295
|
-
* @category State
|
|
296
|
-
*/
|
|
297
|
-
async getArtist(options: NodePyATVGetStateOptions = {}): Promise<string | null> {
|
|
298
|
-
const state = await this.getState(options);
|
|
299
|
-
return state.artist;
|
|
300
|
-
}
|
|
301
|
-
|
|
302
|
-
/**
|
|
303
|
-
* Returns the album of the current playing media
|
|
304
|
-
* @param options
|
|
305
|
-
* @category State
|
|
306
|
-
*/
|
|
307
|
-
async getAlbum(options: NodePyATVGetStateOptions = {}): Promise<string | null> {
|
|
308
|
-
const state = await this.getState(options);
|
|
309
|
-
return state.album;
|
|
310
|
-
}
|
|
311
|
-
|
|
312
|
-
/**
|
|
313
|
-
* Returns the genre of the current playing media
|
|
314
|
-
* @param options
|
|
315
|
-
* @category State
|
|
316
|
-
*/
|
|
317
|
-
async getGenre(options: NodePyATVGetStateOptions = {}): Promise<string | null> {
|
|
318
|
-
const state = await this.getState(options);
|
|
319
|
-
return state.genre;
|
|
320
|
-
}
|
|
321
|
-
|
|
322
|
-
/**
|
|
323
|
-
* Returns the media length of the current playing media
|
|
324
|
-
* @param options
|
|
325
|
-
* @category State
|
|
326
|
-
*/
|
|
327
|
-
async getTotalTime(options: NodePyATVGetStateOptions = {}): Promise<number | null> {
|
|
328
|
-
const state = await this.getState(options);
|
|
329
|
-
return state.totalTime;
|
|
330
|
-
}
|
|
331
|
-
|
|
332
|
-
/**
|
|
333
|
-
* Returns the title of the current playing media
|
|
334
|
-
* @param options
|
|
335
|
-
* @category State
|
|
336
|
-
*/
|
|
337
|
-
async getPosition(options: NodePyATVGetStateOptions = {}): Promise<number | null> {
|
|
338
|
-
const state = await this.getState(options);
|
|
339
|
-
return state.position;
|
|
340
|
-
}
|
|
341
|
-
|
|
342
|
-
/**
|
|
343
|
-
* Returns the shuffle state
|
|
344
|
-
* @param options
|
|
345
|
-
* @category State
|
|
346
|
-
*/
|
|
347
|
-
async getShuffle(options: NodePyATVGetStateOptions = {}): Promise<NodePyATVShuffleState | null> {
|
|
348
|
-
const state = await this.getState(options);
|
|
349
|
-
return state.shuffle;
|
|
350
|
-
}
|
|
351
|
-
|
|
352
|
-
/**
|
|
353
|
-
* Returns the repeat state
|
|
354
|
-
* @param options
|
|
355
|
-
* @category State
|
|
356
|
-
*/
|
|
357
|
-
async getRepeat(options: NodePyATVGetStateOptions = {}): Promise<NodePyATVRepeatState | null> {
|
|
358
|
-
const state = await this.getState(options);
|
|
359
|
-
return state.repeat;
|
|
360
|
-
}
|
|
361
|
-
|
|
362
|
-
/**
|
|
363
|
-
* Returns the currently used app
|
|
364
|
-
* @param options
|
|
365
|
-
* @category State
|
|
366
|
-
*/
|
|
367
|
-
async getApp(options: NodePyATVGetStateOptions = {}): Promise<string | null> {
|
|
368
|
-
const state = await this.getState(options);
|
|
369
|
-
return state.app;
|
|
370
|
-
}
|
|
371
|
-
|
|
372
|
-
/**
|
|
373
|
-
* Returns the id of the currently used app
|
|
374
|
-
* @param options
|
|
375
|
-
* @category State
|
|
376
|
-
*/
|
|
377
|
-
async getAppId(options: NodePyATVGetStateOptions = {}): Promise<string | null> {
|
|
378
|
-
const state = await this.getState(options);
|
|
379
|
-
return state.appId;
|
|
380
|
-
}
|
|
381
|
-
|
|
382
|
-
/**
|
|
383
|
-
* Returns the list of installed apps on the Apple TV. Probably requires `companionCredentials`,
|
|
384
|
-
* see https://pyatv.dev/documentation/atvremote/#apps for more details.
|
|
385
|
-
*/
|
|
386
|
-
async listApps(): Promise<NodePyATVApp[]> {
|
|
387
|
-
const id = addRequestId();
|
|
388
|
-
const parameters = getParamters(this.options);
|
|
389
|
-
|
|
390
|
-
const result = await request(id, NodePyATVExecutableType.atvremote, [...parameters, 'app_list'], this.options);
|
|
391
|
-
if(typeof result !== 'string' || !result.startsWith('App: ')) {
|
|
392
|
-
throw new Error('Unexpected atvremote response: ' + result);
|
|
393
|
-
}
|
|
394
|
-
|
|
395
|
-
removeRequestId(id);
|
|
396
|
-
const regex = /(.+) \(([^\)]+)\)$/i;
|
|
397
|
-
const items = result.substring(5, ).split(', App: ').map(i => {
|
|
398
|
-
const m = i.match(regex);
|
|
399
|
-
if (m !== null) {
|
|
400
|
-
return {
|
|
401
|
-
id: m[2],
|
|
402
|
-
name: m[1],
|
|
403
|
-
launch: () => this.launchApp(m[2])
|
|
404
|
-
};
|
|
405
|
-
}
|
|
406
|
-
}) as Array<NodePyATVApp | undefined>;
|
|
407
|
-
|
|
408
|
-
return items.filter(Boolean) as NodePyATVApp[];
|
|
409
|
-
}
|
|
410
|
-
|
|
411
|
-
private async _pressKey(key: NodePyATVInternalKeys | string, executableType: NodePyATVExecutableType) {
|
|
412
|
-
const id = addRequestId();
|
|
413
|
-
const parameters = getParamters(this.options);
|
|
414
|
-
|
|
415
|
-
const result = await request(id, executableType, [...parameters, key], this.options);
|
|
416
|
-
if (
|
|
417
|
-
executableType === NodePyATVExecutableType.atvscript &&
|
|
418
|
-
(typeof result !== 'object' || result.result !== 'success')
|
|
419
|
-
) {
|
|
420
|
-
throw new Error(`Unable to parse pyatv response: ${JSON.stringify(result, null, ' ')}`);
|
|
421
|
-
}
|
|
422
|
-
|
|
423
|
-
removeRequestId(id);
|
|
424
|
-
}
|
|
425
|
-
|
|
426
|
-
/**
|
|
427
|
-
* Send a key press to the Apple TV
|
|
428
|
-
*
|
|
429
|
-
* ```typescript
|
|
430
|
-
* await device.pressKey(NodePyATVKeys.home);
|
|
431
|
-
* ```
|
|
432
|
-
*
|
|
433
|
-
* <br />
|
|
434
|
-
*
|
|
435
|
-
* ```javascript
|
|
436
|
-
* await device.pressKey('home');
|
|
437
|
-
* ```
|
|
438
|
-
*
|
|
439
|
-
* @param key
|
|
440
|
-
* @category Control
|
|
441
|
-
*/
|
|
442
|
-
async pressKey(key: NodePyATVKeys): Promise<void> {
|
|
443
|
-
const internalKeyEntry = Object.entries(NodePyATVInternalKeys)
|
|
444
|
-
.find(([k]) => key === k);
|
|
445
|
-
|
|
446
|
-
if(!internalKeyEntry) {
|
|
447
|
-
throw new Error(`Unsupported key value ${key}!`);
|
|
448
|
-
}
|
|
449
|
-
|
|
450
|
-
const internalKey = internalKeyEntry[1];
|
|
451
|
-
const executableType = [NodePyATVKeys.turnOn, NodePyATVKeys.turnOff].includes(key) ?
|
|
452
|
-
NodePyATVExecutableType.atvremote :
|
|
453
|
-
NodePyATVExecutableType.atvscript;
|
|
454
|
-
|
|
455
|
-
await this._pressKey(internalKey, executableType);
|
|
456
|
-
}
|
|
457
|
-
|
|
458
|
-
/**
|
|
459
|
-
* Send the "down" command
|
|
460
|
-
* @category Control
|
|
461
|
-
*/
|
|
462
|
-
async down(): Promise<void> {
|
|
463
|
-
await this._pressKey(NodePyATVInternalKeys.down, NodePyATVExecutableType.atvscript);
|
|
464
|
-
}
|
|
465
|
-
|
|
466
|
-
/**
|
|
467
|
-
* Send the "home" command
|
|
468
|
-
* @category Control
|
|
469
|
-
*/
|
|
470
|
-
async home(): Promise<void> {
|
|
471
|
-
await this._pressKey(NodePyATVInternalKeys.home, NodePyATVExecutableType.atvscript);
|
|
472
|
-
}
|
|
473
|
-
|
|
474
|
-
/**
|
|
475
|
-
* Send the "homeHold" command
|
|
476
|
-
* @category Control
|
|
477
|
-
*/
|
|
478
|
-
async homeHold(): Promise<void> {
|
|
479
|
-
await this._pressKey(NodePyATVInternalKeys.homeHold, NodePyATVExecutableType.atvscript);
|
|
480
|
-
}
|
|
481
|
-
|
|
482
|
-
/**
|
|
483
|
-
* Send the "left" command
|
|
484
|
-
* @category Control
|
|
485
|
-
*/
|
|
486
|
-
async left(): Promise<void> {
|
|
487
|
-
await this._pressKey(NodePyATVInternalKeys.left, NodePyATVExecutableType.atvscript);
|
|
488
|
-
}
|
|
489
|
-
|
|
490
|
-
/**
|
|
491
|
-
* Send the "menu" command
|
|
492
|
-
* @category Control
|
|
493
|
-
*/
|
|
494
|
-
async menu(): Promise<void> {
|
|
495
|
-
await this._pressKey(NodePyATVInternalKeys.menu, NodePyATVExecutableType.atvscript);
|
|
496
|
-
}
|
|
497
|
-
|
|
498
|
-
/**
|
|
499
|
-
* Send the "next" command
|
|
500
|
-
* @category Control
|
|
501
|
-
*/
|
|
502
|
-
async next(): Promise<void> {
|
|
503
|
-
await this._pressKey(NodePyATVInternalKeys.next, NodePyATVExecutableType.atvscript);
|
|
504
|
-
}
|
|
505
|
-
|
|
506
|
-
/**
|
|
507
|
-
* Send the "pause" command
|
|
508
|
-
* @category Control
|
|
509
|
-
*/
|
|
510
|
-
async pause(): Promise<void> {
|
|
511
|
-
await this._pressKey(NodePyATVInternalKeys.pause, NodePyATVExecutableType.atvscript);
|
|
512
|
-
}
|
|
513
|
-
|
|
514
|
-
/**
|
|
515
|
-
* Send the "play" command
|
|
516
|
-
* @category Control
|
|
517
|
-
*/
|
|
518
|
-
async play(): Promise<void> {
|
|
519
|
-
await this._pressKey(NodePyATVInternalKeys.play, NodePyATVExecutableType.atvscript);
|
|
520
|
-
}
|
|
521
|
-
|
|
522
|
-
/**
|
|
523
|
-
* Send the "playPause" command
|
|
524
|
-
* @category Control
|
|
525
|
-
*/
|
|
526
|
-
async playPause(): Promise<void> {
|
|
527
|
-
await this._pressKey(NodePyATVInternalKeys.playPause, NodePyATVExecutableType.atvscript);
|
|
528
|
-
}
|
|
529
|
-
|
|
530
|
-
/**
|
|
531
|
-
* Send the "previous" command
|
|
532
|
-
* @category Control
|
|
533
|
-
*/
|
|
534
|
-
async previous(): Promise<void> {
|
|
535
|
-
await this._pressKey(NodePyATVInternalKeys.previous, NodePyATVExecutableType.atvscript);
|
|
536
|
-
}
|
|
537
|
-
|
|
538
|
-
/**
|
|
539
|
-
* Send the "right" command
|
|
540
|
-
* @category Control
|
|
541
|
-
*/
|
|
542
|
-
async right(): Promise<void> {
|
|
543
|
-
await this._pressKey(NodePyATVInternalKeys.right, NodePyATVExecutableType.atvscript);
|
|
544
|
-
}
|
|
545
|
-
|
|
546
|
-
/**
|
|
547
|
-
* Send the "select" command
|
|
548
|
-
* @category Control
|
|
549
|
-
*/
|
|
550
|
-
async select(): Promise<void> {
|
|
551
|
-
await this._pressKey(NodePyATVInternalKeys.select, NodePyATVExecutableType.atvscript);
|
|
552
|
-
}
|
|
553
|
-
|
|
554
|
-
/**
|
|
555
|
-
* Send the "skipBackward" command
|
|
556
|
-
* @category Control
|
|
557
|
-
*/
|
|
558
|
-
async skipBackward(): Promise<void> {
|
|
559
|
-
await this._pressKey(NodePyATVInternalKeys.skipBackward, NodePyATVExecutableType.atvscript);
|
|
560
|
-
}
|
|
561
|
-
|
|
562
|
-
/**
|
|
563
|
-
* Send the "skipForward" command
|
|
564
|
-
* @category Control
|
|
565
|
-
*/
|
|
566
|
-
async skipForward(): Promise<void> {
|
|
567
|
-
await this._pressKey(NodePyATVInternalKeys.skipForward, NodePyATVExecutableType.atvscript);
|
|
568
|
-
}
|
|
569
|
-
|
|
570
|
-
/**
|
|
571
|
-
* Send the "stop" command
|
|
572
|
-
* @category Control
|
|
573
|
-
*/
|
|
574
|
-
async stop(): Promise<void> {
|
|
575
|
-
await this._pressKey(NodePyATVInternalKeys.stop, NodePyATVExecutableType.atvscript);
|
|
576
|
-
}
|
|
577
|
-
|
|
578
|
-
/**
|
|
579
|
-
* Send the "suspend" command
|
|
580
|
-
* @category Control
|
|
581
|
-
* @deprecated
|
|
582
|
-
*/
|
|
583
|
-
async suspend(): Promise<void> {
|
|
584
|
-
await this._pressKey(NodePyATVInternalKeys.suspend, NodePyATVExecutableType.atvscript);
|
|
585
|
-
}
|
|
586
|
-
|
|
587
|
-
/**
|
|
588
|
-
* Send the "topMenu" command
|
|
589
|
-
* @category Control
|
|
590
|
-
*/
|
|
591
|
-
async topMenu(): Promise<void> {
|
|
592
|
-
await this._pressKey(NodePyATVInternalKeys.topMenu, NodePyATVExecutableType.atvscript);
|
|
593
|
-
}
|
|
594
|
-
|
|
595
|
-
/**
|
|
596
|
-
* Send the "up" command
|
|
597
|
-
* @category Control
|
|
598
|
-
*/
|
|
599
|
-
async up(): Promise<void> {
|
|
600
|
-
await this._pressKey(NodePyATVInternalKeys.up, NodePyATVExecutableType.atvscript);
|
|
601
|
-
}
|
|
602
|
-
|
|
603
|
-
/**
|
|
604
|
-
* Send the "volumeDown" command
|
|
605
|
-
* @category Control
|
|
606
|
-
*/
|
|
607
|
-
async volumeDown(): Promise<void> {
|
|
608
|
-
await this._pressKey(NodePyATVInternalKeys.volumeDown, NodePyATVExecutableType.atvscript);
|
|
609
|
-
}
|
|
610
|
-
|
|
611
|
-
/**
|
|
612
|
-
* Send the "volumeUp" command
|
|
613
|
-
* @category Control
|
|
614
|
-
*/
|
|
615
|
-
async volumeUp(): Promise<void> {
|
|
616
|
-
await this._pressKey(NodePyATVInternalKeys.volumeUp, NodePyATVExecutableType.atvscript);
|
|
617
|
-
}
|
|
618
|
-
|
|
619
|
-
/**
|
|
620
|
-
* Send the "wakeup" command
|
|
621
|
-
* @category Control
|
|
622
|
-
* @deprecated
|
|
623
|
-
*/
|
|
624
|
-
async wakeup(): Promise<void> {
|
|
625
|
-
await this._pressKey(NodePyATVInternalKeys.wakeup, NodePyATVExecutableType.atvscript);
|
|
626
|
-
}
|
|
627
|
-
|
|
628
|
-
/**
|
|
629
|
-
* Send the "turn_off" command
|
|
630
|
-
* @category Control
|
|
631
|
-
*/
|
|
632
|
-
async turnOff(): Promise<void> {
|
|
633
|
-
await this._pressKey(NodePyATVInternalKeys.turnOff, NodePyATVExecutableType.atvremote);
|
|
634
|
-
}
|
|
635
|
-
|
|
636
|
-
/**
|
|
637
|
-
* Send the "turn_on" command
|
|
638
|
-
* @category Control
|
|
639
|
-
*/
|
|
640
|
-
async turnOn(): Promise<void> {
|
|
641
|
-
await this._pressKey(NodePyATVInternalKeys.turnOn, NodePyATVExecutableType.atvremote);
|
|
642
|
-
}
|
|
643
|
-
|
|
644
|
-
/**
|
|
645
|
-
* Launch an application. Probably requires `companionCredentials`, see
|
|
646
|
-
* https://pyatv.dev/documentation/atvremote/#apps for more details.
|
|
647
|
-
* @param id App identifier, e.g. `com.netflix.Netflix`
|
|
648
|
-
*/
|
|
649
|
-
async launchApp(id: string): Promise<void> {
|
|
650
|
-
await this._pressKey('launch_app=' + id, NodePyATVExecutableType.atvremote);
|
|
651
|
-
}
|
|
652
|
-
|
|
653
|
-
/**
|
|
654
|
-
* Add an event listener. Will start the event subscription with the
|
|
655
|
-
* Apple TV as long as there are listeners for any event registered.
|
|
656
|
-
* @param event
|
|
657
|
-
* @param listener
|
|
658
|
-
* @category Event
|
|
659
|
-
*/
|
|
660
|
-
addListener(event: string | symbol, listener: (event: NodePyATVDeviceEvent) => void): this {
|
|
661
|
-
this.events.addListener(event, listener);
|
|
662
|
-
return this;
|
|
663
|
-
}
|
|
664
|
-
|
|
665
|
-
/**
|
|
666
|
-
* Emit an event.
|
|
667
|
-
* @param event
|
|
668
|
-
* @param payload
|
|
669
|
-
* @category Event
|
|
670
|
-
*/
|
|
671
|
-
emit(event: string | symbol, payload: NodePyATVDeviceEvent): boolean {
|
|
672
|
-
return this.events.emit(event, payload);
|
|
673
|
-
}
|
|
674
|
-
|
|
675
|
-
/**
|
|
676
|
-
* Get all event names which are currently known.
|
|
677
|
-
* @category Event
|
|
678
|
-
*/
|
|
679
|
-
eventNames(): Array<string | symbol> {
|
|
680
|
-
return this.events.eventNames();
|
|
681
|
-
}
|
|
682
|
-
|
|
683
|
-
/**
|
|
684
|
-
* Get max number of listeners allowed
|
|
685
|
-
* @category Event
|
|
686
|
-
*/
|
|
687
|
-
getMaxListeners(): number {
|
|
688
|
-
return this.events.getMaxListeners();
|
|
689
|
-
}
|
|
690
|
-
|
|
691
|
-
/**
|
|
692
|
-
* Get number of listeners for event
|
|
693
|
-
* @param event
|
|
694
|
-
* @category Event
|
|
695
|
-
*/
|
|
696
|
-
listenerCount(event: string | symbol): number {
|
|
697
|
-
return this.events.listenerCount(event);
|
|
698
|
-
}
|
|
699
|
-
|
|
700
|
-
/**
|
|
701
|
-
* Get listeners for event. Will also return
|
|
702
|
-
* node-pyatv wrappers (e.g. once)
|
|
703
|
-
*
|
|
704
|
-
* @param event
|
|
705
|
-
* @category Event
|
|
706
|
-
*/
|
|
707
|
-
// eslint-disable-next-line @typescript-eslint/ban-types
|
|
708
|
-
listeners(event: string | symbol): Function[] {
|
|
709
|
-
return this.events.listeners(event);
|
|
710
|
-
}
|
|
711
|
-
|
|
712
|
-
/**
|
|
713
|
-
* Remove an event listener. Will stop the event subscription with the
|
|
714
|
-
* Apple TV if this was the last event listener.
|
|
715
|
-
* @param event
|
|
716
|
-
* @param listener
|
|
717
|
-
* @category Event
|
|
718
|
-
*/
|
|
719
|
-
off(event: string | symbol, listener: (event: NodePyATVDeviceEvent | Error) => void): this {
|
|
720
|
-
this.events.off(event, listener);
|
|
721
|
-
return this;
|
|
722
|
-
}
|
|
723
|
-
|
|
724
|
-
/**
|
|
725
|
-
* Add an event listener. Will start the event subscription with the
|
|
726
|
-
* Apple TV as long as there are listeners for any event registered.
|
|
727
|
-
* @param event
|
|
728
|
-
* @param listener
|
|
729
|
-
* @category Event
|
|
730
|
-
*/
|
|
731
|
-
on(event: string | symbol, listener: (event: NodePyATVDeviceEvent | Error) => void): this {
|
|
732
|
-
this.events.on(event, listener);
|
|
733
|
-
return this;
|
|
734
|
-
}
|
|
735
|
-
|
|
736
|
-
/**
|
|
737
|
-
* Add an event listener. Will start the event subscription with the
|
|
738
|
-
* Apple TV as long as there are listeners for any event registered.
|
|
739
|
-
* Removes the listener automatically after the first occurrence.
|
|
740
|
-
* @param event
|
|
741
|
-
* @param listener
|
|
742
|
-
* @category Event
|
|
743
|
-
*/
|
|
744
|
-
once(event: string | symbol, listener: (event: NodePyATVDeviceEvent | Error) => void): this {
|
|
745
|
-
this.events.once(event, listener);
|
|
746
|
-
return this;
|
|
747
|
-
}
|
|
748
|
-
|
|
749
|
-
/**
|
|
750
|
-
* @param event
|
|
751
|
-
* @param listener
|
|
752
|
-
* @category Event
|
|
753
|
-
*/
|
|
754
|
-
prependListener(event: string | symbol, listener: (event: NodePyATVDeviceEvent | Error) => void): this {
|
|
755
|
-
this.events.prependListener(event, listener);
|
|
756
|
-
return this;
|
|
757
|
-
}
|
|
758
|
-
|
|
759
|
-
/**
|
|
760
|
-
* @param event
|
|
761
|
-
* @param listener
|
|
762
|
-
* @category Event
|
|
763
|
-
*/
|
|
764
|
-
prependOnceListener(event: string | symbol, listener: (event: NodePyATVDeviceEvent | Error) => void): this {
|
|
765
|
-
this.events.prependOnceListener(event, listener);
|
|
766
|
-
return this;
|
|
767
|
-
}
|
|
768
|
-
|
|
769
|
-
/**
|
|
770
|
-
* @param event
|
|
771
|
-
* @category Event
|
|
772
|
-
*/
|
|
773
|
-
// eslint-disable-next-line @typescript-eslint/ban-types
|
|
774
|
-
rawListeners(event: string | symbol): Function[] {
|
|
775
|
-
return this.events.rawListeners(event);
|
|
776
|
-
}
|
|
777
|
-
|
|
778
|
-
/**
|
|
779
|
-
* Removes all listeners, either for the given event or
|
|
780
|
-
* for every event. Will stop the event subscription with
|
|
781
|
-
* the Apple TV if this was the last event listener.
|
|
782
|
-
*
|
|
783
|
-
* @param event
|
|
784
|
-
* @category Event
|
|
785
|
-
*/
|
|
786
|
-
removeAllListeners(event?: string | symbol): this {
|
|
787
|
-
this.events.removeAllListeners(event);
|
|
788
|
-
return this;
|
|
789
|
-
}
|
|
790
|
-
|
|
791
|
-
/**
|
|
792
|
-
* Remove an event listener. Will stop the event subscription with the
|
|
793
|
-
* Apple TV if this was the last event listener.
|
|
794
|
-
* @param event
|
|
795
|
-
* @param listener
|
|
796
|
-
* @category Event
|
|
797
|
-
*/
|
|
798
|
-
removeListener(event: string | symbol, listener: (event: NodePyATVDeviceEvent) => void): this {
|
|
799
|
-
this.events.removeListener(event, listener);
|
|
800
|
-
return this;
|
|
801
|
-
}
|
|
802
|
-
|
|
803
|
-
/**
|
|
804
|
-
* @param n
|
|
805
|
-
* @category Event
|
|
806
|
-
*/
|
|
807
|
-
setMaxListeners(n: number): this {
|
|
808
|
-
this.events.setMaxListeners(n);
|
|
809
|
-
return this;
|
|
810
|
-
}
|
|
811
|
-
}
|