@putdotio/taizn 1.10.0 → 1.12.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 +5 -1
- package/dist/taizn.mjs +52 -7
- package/docs/TV_REMOTE.md +5 -1
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -58,8 +58,10 @@ taizn package
|
|
|
58
58
|
taizn install
|
|
59
59
|
taizn run
|
|
60
60
|
taizn tv info
|
|
61
|
+
taizn tv info --json
|
|
61
62
|
taizn tv pair
|
|
62
63
|
taizn tv press KEY_ENTER
|
|
64
|
+
taizn tv press --json KEY_ENTER
|
|
63
65
|
taizn tv press --delay-ms 250 KEY_HOME KEY_DOWN KEY_ENTER
|
|
64
66
|
taizn --version
|
|
65
67
|
```
|
|
@@ -78,7 +80,9 @@ proof output. `profile` imports
|
|
|
78
80
|
`package` builds and signs a `.wgt`. `install` packages and sideloads it.
|
|
79
81
|
`run` launches the configured variant application on the target. `tv` commands use
|
|
80
82
|
Samsung's websocket remote-control API to inspect a TV,
|
|
81
|
-
pair for a remote token, and send remote-control key presses.
|
|
83
|
+
pair for a remote token, and send remote-control key presses. Add `--json` to
|
|
84
|
+
`tv info` for a structured TV capability snapshot, or to `tv press` for a
|
|
85
|
+
structured key-sequence receipt. See
|
|
82
86
|
[Samsung TV Remote](./docs/TV_REMOTE.md) for pairing, environment, and limits.
|
|
83
87
|
`tv press` accepts one key or a sequence of keys.
|
|
84
88
|
|
package/dist/taizn.mjs
CHANGED
|
@@ -461,20 +461,56 @@ Effect.fn("sendSamsungTvKey")(function* (env, key) {
|
|
|
461
461
|
});
|
|
462
462
|
const sendSamsungTvKeys = Effect.fn("sendSamsungTvKeys")(function* (env, keys, pressOptions) {
|
|
463
463
|
const remoteOptions = yield* resolveRemoteOptions(env, { requireToken: true });
|
|
464
|
-
|
|
464
|
+
const token = remoteOptions.token;
|
|
465
|
+
const delayMs = Math.max(0, pressOptions?.delayMs ?? 250);
|
|
466
|
+
if (!token) return yield* MissingTvRemoteToken.make({});
|
|
465
467
|
yield* connectRemote(remoteOptions, {
|
|
466
|
-
delayMs
|
|
468
|
+
delayMs,
|
|
467
469
|
keys
|
|
468
470
|
});
|
|
471
|
+
if (pressOptions?.json) {
|
|
472
|
+
yield* Console.log(JSON.stringify({
|
|
473
|
+
delayMs,
|
|
474
|
+
keys,
|
|
475
|
+
keyCount: keys.length,
|
|
476
|
+
target: {
|
|
477
|
+
host: remoteOptions.host,
|
|
478
|
+
port: remoteOptions.port,
|
|
479
|
+
protocol: remoteOptions.protocol,
|
|
480
|
+
url: remoteTarget(remoteOptions)
|
|
481
|
+
}
|
|
482
|
+
}));
|
|
483
|
+
return;
|
|
484
|
+
}
|
|
469
485
|
yield* Console.log(keys.length === 1 ? `Sent Samsung TV remote key: ${keys[0]}` : `Sent Samsung TV remote keys: ${keys.join(", ")}`);
|
|
470
486
|
});
|
|
471
|
-
const showSamsungTvInfo = Effect.fn("showSamsungTvInfo")(function* (env) {
|
|
487
|
+
const showSamsungTvInfo = Effect.fn("showSamsungTvInfo")(function* (env, infoOptions = {}) {
|
|
472
488
|
const options = yield* resolveRemoteOptions(env);
|
|
473
489
|
const info = yield* fetchSamsungTvInfo(options.host, {
|
|
474
490
|
port: env.tvInfoPort,
|
|
475
491
|
timeoutMs: options.timeoutMs
|
|
476
492
|
});
|
|
477
493
|
const support = info.isSupport ? parseSupport(info.isSupport) : void 0;
|
|
494
|
+
if (infoOptions.json) {
|
|
495
|
+
yield* Console.log(JSON.stringify({
|
|
496
|
+
developer: {
|
|
497
|
+
enabled: stringFlag(info.device.developerMode),
|
|
498
|
+
ip: info.device.developerIP,
|
|
499
|
+
mode: info.device.developerMode
|
|
500
|
+
},
|
|
501
|
+
host: options.host,
|
|
502
|
+
infoPort: env.tvInfoPort ?? TV_INFO_PORT,
|
|
503
|
+
ip: info.device.ip ?? options.host,
|
|
504
|
+
model: info.device.modelName,
|
|
505
|
+
name: decodeHtml(info.name),
|
|
506
|
+
remote: info.remote,
|
|
507
|
+
remoteAvailable: stringFlag(support?.remote_available),
|
|
508
|
+
tokenAuth: stringFlag(info.device.TokenAuthSupport),
|
|
509
|
+
type: info.type,
|
|
510
|
+
uri: info.uri
|
|
511
|
+
}));
|
|
512
|
+
return;
|
|
513
|
+
}
|
|
478
514
|
yield* Console.log(`Samsung TV: ${decodeHtml(info.name)}`);
|
|
479
515
|
yield* Console.log(`model: ${info.device.modelName ?? "unknown"}`);
|
|
480
516
|
yield* Console.log(`ip: ${info.device.ip ?? options.host}`);
|
|
@@ -696,6 +732,11 @@ const hostFromTarget = (target) => {
|
|
|
696
732
|
};
|
|
697
733
|
const causeToMessage = (cause) => cause instanceof Error ? cause.message : String(cause);
|
|
698
734
|
const decodeHtml = (value) => value.replaceAll(""", "\"").replaceAll("&", "&");
|
|
735
|
+
const stringFlag = (value) => {
|
|
736
|
+
const normalized = value?.trim().toLowerCase();
|
|
737
|
+
if (normalized === "true" || normalized === "1") return true;
|
|
738
|
+
if (normalized === "false" || normalized === "0") return false;
|
|
739
|
+
};
|
|
699
740
|
//#endregion
|
|
700
741
|
//#region src/xml.ts
|
|
701
742
|
const escapeXml = (value) => value.replaceAll("&", "&").replaceAll("\"", """).replaceAll("<", "<").replaceAll(">", ">");
|
|
@@ -1223,12 +1264,16 @@ const tvPair = Command.make("pair", {}, () => Effect.gen(function* () {
|
|
|
1223
1264
|
}));
|
|
1224
1265
|
const tvPress = Command.make("press", {
|
|
1225
1266
|
delayMs: Flag.integer("delay-ms").pipe(Flag.withDefault(250)),
|
|
1267
|
+
json: Flag.boolean("json"),
|
|
1226
1268
|
keys: Argument.string("key").pipe(Argument.variadic({ min: 1 }))
|
|
1227
|
-
}, ({ delayMs, keys }) => Effect.gen(function* () {
|
|
1228
|
-
yield* sendSamsungTvKeys(yield* loadEnv(), keys, {
|
|
1269
|
+
}, ({ delayMs, json, keys }) => Effect.gen(function* () {
|
|
1270
|
+
yield* sendSamsungTvKeys(yield* loadEnv(), keys, {
|
|
1271
|
+
delayMs,
|
|
1272
|
+
json
|
|
1273
|
+
});
|
|
1229
1274
|
}));
|
|
1230
|
-
const tvInfo = Command.make("info", {}, () => Effect.gen(function* () {
|
|
1231
|
-
yield* showSamsungTvInfo(yield* loadEnv());
|
|
1275
|
+
const tvInfo = Command.make("info", { json: Flag.boolean("json") }, ({ json }) => Effect.gen(function* () {
|
|
1276
|
+
yield* showSamsungTvInfo(yield* loadEnv(), { json });
|
|
1232
1277
|
}));
|
|
1233
1278
|
const tv = Command.make("tv", {}).pipe(Command.withSubcommands([
|
|
1234
1279
|
tvPair,
|
package/docs/TV_REMOTE.md
CHANGED
|
@@ -7,19 +7,23 @@ and smoke checks against a physical TV or monitor.
|
|
|
7
7
|
|
|
8
8
|
```bash
|
|
9
9
|
taizn tv info
|
|
10
|
+
taizn tv info --json
|
|
10
11
|
taizn tv pair
|
|
11
12
|
taizn tv press KEY_ENTER
|
|
13
|
+
taizn tv press --json KEY_ENTER
|
|
12
14
|
taizn tv press --delay-ms 250 KEY_HOME KEY_DOWN KEY_ENTER
|
|
13
15
|
```
|
|
14
16
|
|
|
15
17
|
- `info` reads the TV's local `/api/v2/` metadata and reports remote-control
|
|
16
|
-
support.
|
|
18
|
+
support. Add `--json` to emit a structured TV capability snapshot for agents
|
|
19
|
+
and scripts.
|
|
17
20
|
- `pair` opens a Samsung remote websocket and waits for the TV to approve the
|
|
18
21
|
client. When pairing succeeds, it stores the token in `.taizn/remote.json`.
|
|
19
22
|
- `press` reconnects with the paired token and sends a Samsung remote key such
|
|
20
23
|
as `KEY_HOME`, `KEY_BACK`, `KEY_UP`, `KEY_DOWN`, `KEY_LEFT`, `KEY_RIGHT`, or
|
|
21
24
|
`KEY_ENTER`. Pass multiple keys to send a navigation sequence on one
|
|
22
25
|
websocket connection. `--delay-ms` controls the delay between sequence keys.
|
|
26
|
+
Add `--json` to emit a redacted receipt with the target, delay, and keys sent.
|
|
23
27
|
|
|
24
28
|
## Environment
|
|
25
29
|
|