iobroker.assistant 1.4.8 → 1.4.9
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 -0
- package/build/lib/piAgent.js +2 -0
- package/build/lib/piAgent.js.map +1 -1
- package/build/lib/timers.js +7 -0
- package/build/lib/timers.js.map +1 -1
- package/build/lib/voice/esphome.js +44 -24
- package/build/lib/voice/esphome.js.map +1 -1
- package/build/main.js +76 -16
- package/build/main.js.map +1 -1
- package/io-package.json +14 -14
- package/package.json +1 -1
package/build/main.js
CHANGED
|
@@ -996,6 +996,11 @@ class Assistant extends adapter_core_1.Adapter {
|
|
|
996
996
|
const roomName = (room || '').replace(/^(enum\.rooms\.|system\.rooms\.)/, '');
|
|
997
997
|
return (roomName || device).replace(/[^\w-]/g, '_') || 'unknown';
|
|
998
998
|
}
|
|
999
|
+
/** The id under `satellites.*` of the satellite a request came from, or '' when it has no states there (Wyoming). */
|
|
1000
|
+
knownSatelliteId(device, room) {
|
|
1001
|
+
const id = this.satelliteStateId(device, room);
|
|
1002
|
+
return this.satStatesEnsured.has(id) ? id : '';
|
|
1003
|
+
}
|
|
999
1004
|
/** Reflect a satellite's status into `satellites.<room>.*` states (created on first sight). */
|
|
1000
1005
|
async updateSatelliteState(device, room, state) {
|
|
1001
1006
|
const id = await this.ensureSatelliteObjects(device, room);
|
|
@@ -2480,18 +2485,38 @@ class Assistant extends adapter_core_1.Adapter {
|
|
|
2480
2485
|
}
|
|
2481
2486
|
return;
|
|
2482
2487
|
}
|
|
2483
|
-
// Scripts: start a countdown timer. message = { duration: seconds | "5 min", label?, room
|
|
2488
|
+
// Scripts: start a countdown timer. message = { duration | seconds: seconds | "5 min", label | name?, room?,
|
|
2489
|
+
// satellite?, announce? }. With `satellite` (its id under satellites.*, or the device name) the timer is that
|
|
2490
|
+
// satellite's like one set there by voice: an ESPHome satellite shows and rings it, and the announcement plays
|
|
2491
|
+
// there. `announce` = what to say when it fires, word for word (default: "Timer finished: <name>.").
|
|
2484
2492
|
if (obj.command === 'setTimer') {
|
|
2485
2493
|
const m = (obj.message || {});
|
|
2486
|
-
|
|
2487
|
-
|
|
2488
|
-
|
|
2494
|
+
// `seconds` are seconds also as a string; a bare number in a `duration` string stays minutes as before
|
|
2495
|
+
const duration = m.seconds !== undefined
|
|
2496
|
+
? Math.round(Number(m.seconds) || 0) ||
|
|
2497
|
+
(typeof m.seconds === 'string' ? (0, nlu_1.parseDurationSeconds)(m.seconds, false) || 0 : 0)
|
|
2498
|
+
: typeof m.duration === 'string'
|
|
2499
|
+
? (0, nlu_1.parseDurationSeconds)(m.duration, true) || 0
|
|
2500
|
+
: Math.round(Number(m.duration) || 0);
|
|
2501
|
+
const satellite = this.timerSatellite(m.satellite);
|
|
2489
2502
|
let result;
|
|
2490
|
-
if (!this.timers
|
|
2491
|
-
result = { ok: false, error:
|
|
2503
|
+
if (!this.timers) {
|
|
2504
|
+
result = { ok: false, error: 'timers not ready' };
|
|
2505
|
+
}
|
|
2506
|
+
else if (duration <= 0) {
|
|
2507
|
+
result = { ok: false, error: 'duration must be > 0 seconds' };
|
|
2508
|
+
}
|
|
2509
|
+
else if (satellite === null) {
|
|
2510
|
+
result = { ok: false, error: `unknown satellite "${String(m.satellite)}"` };
|
|
2492
2511
|
}
|
|
2493
2512
|
else {
|
|
2494
|
-
const info = this.timers.add({
|
|
2513
|
+
const info = this.timers.add({
|
|
2514
|
+
label: String(m.name ?? m.label ?? ''),
|
|
2515
|
+
room: m.room || '',
|
|
2516
|
+
source: satellite,
|
|
2517
|
+
duration,
|
|
2518
|
+
announce: typeof m.announce === 'string' ? m.announce : '',
|
|
2519
|
+
});
|
|
2495
2520
|
result = { ok: true, id: info.id, fireAt: info.fireAt };
|
|
2496
2521
|
}
|
|
2497
2522
|
if (obj.callback) {
|
|
@@ -2499,19 +2524,37 @@ class Assistant extends adapter_core_1.Adapter {
|
|
|
2499
2524
|
}
|
|
2500
2525
|
return;
|
|
2501
2526
|
}
|
|
2502
|
-
// Scripts: cancel a timer by id, or all when no id is given. message = { id? }
|
|
2527
|
+
// Scripts: cancel a timer by id, or all when no id is given. message = { id?, satellite? } — with `satellite`
|
|
2528
|
+
// only that satellite's timers.
|
|
2503
2529
|
if (obj.command === 'cancelTimer') {
|
|
2504
2530
|
const m = (obj.message || {});
|
|
2505
|
-
const
|
|
2531
|
+
const satellite = this.timerSatellite(m.satellite);
|
|
2532
|
+
let result;
|
|
2533
|
+
if (satellite === null) {
|
|
2534
|
+
result = { ok: false, cancelled: 0, error: `unknown satellite "${String(m.satellite)}"` };
|
|
2535
|
+
}
|
|
2536
|
+
else {
|
|
2537
|
+
const mine = (this.timers?.list() || []).filter(t => !satellite || t.source === satellite);
|
|
2538
|
+
const ids = m.id ? mine.filter(t => t.id === m.id).map(t => t.id) : mine.map(t => t.id);
|
|
2539
|
+
const cancelled = satellite || m.id
|
|
2540
|
+
? ids.filter(id => this.timers?.cancel(id)).length
|
|
2541
|
+
: (this.timers?.cancelAll() ?? 0);
|
|
2542
|
+
result = { ok: true, cancelled };
|
|
2543
|
+
}
|
|
2506
2544
|
if (obj.callback) {
|
|
2507
|
-
this.sendTo(obj.from, obj.command,
|
|
2545
|
+
this.sendTo(obj.from, obj.command, result, obj.callback);
|
|
2508
2546
|
}
|
|
2509
2547
|
return;
|
|
2510
2548
|
}
|
|
2511
|
-
// Scripts: list the running timers.
|
|
2549
|
+
// Scripts: list the running timers. message = { satellite? } — with it only that satellite's.
|
|
2512
2550
|
if (obj.command === 'listTimers') {
|
|
2551
|
+
const m = (obj.message || {});
|
|
2552
|
+
const satellite = this.timerSatellite(m.satellite);
|
|
2553
|
+
const result = satellite === null
|
|
2554
|
+
? { timers: [], error: `unknown satellite "${String(m.satellite)}"` }
|
|
2555
|
+
: { timers: (this.timers?.list() || []).filter(t => !satellite || t.source === satellite) };
|
|
2513
2556
|
if (obj.callback) {
|
|
2514
|
-
this.sendTo(obj.from, obj.command,
|
|
2557
|
+
this.sendTo(obj.from, obj.command, result, obj.callback);
|
|
2515
2558
|
}
|
|
2516
2559
|
return;
|
|
2517
2560
|
}
|
|
@@ -3150,9 +3193,10 @@ class Assistant extends adapter_core_1.Adapter {
|
|
|
3150
3193
|
return Promise.resolve('');
|
|
3151
3194
|
}
|
|
3152
3195
|
const voice = VOICE_TRANSPORTS.has(origin.transport || '');
|
|
3196
|
+
const satellite = voice ? this.knownSatelliteId(origin.satellite || source, origin.room || '') : '';
|
|
3153
3197
|
// The journal shows "[picture] What is in this picture?", like the conversation history
|
|
3154
3198
|
const shown = (0, media_1.historyText)(question, attachments.images.length, !!attachments.video);
|
|
3155
|
-
return this.requestOrigin.run({ source, room: origin.room || '', voice, attachments }, () => this.journal
|
|
3199
|
+
return this.requestOrigin.run({ source, room: origin.room || '', voice, satellite, attachments }, () => this.journal
|
|
3156
3200
|
? this.journal.run(shown, source, origin, () => {
|
|
3157
3201
|
this.traceSpeechInput(question, origin);
|
|
3158
3202
|
this.traceAttachments(attachments);
|
|
@@ -3677,7 +3721,11 @@ class Assistant extends adapter_core_1.Adapter {
|
|
|
3677
3721
|
// pi-agent asks its questions to confirm a write ("… Say yes or no.") in this language, not in the system
|
|
3678
3722
|
// language: a satellite listening in Russian does not hear a German "Ja"
|
|
3679
3723
|
const language = String(this.config.voiceLanguage || this.language || '');
|
|
3680
|
-
|
|
3724
|
+
// From a satellite: where pi-agent can speak later on its own (a reminder, the end of a background
|
|
3725
|
+
// task) — its `tts` state says it there.
|
|
3726
|
+
const satellite = this.requestOrigin.getStore()?.satellite || '';
|
|
3727
|
+
const tts = satellite ? `${this.namespace}.satellites.${satellite}.tts` : '';
|
|
3728
|
+
return await harness.ask({ text, conversation: source, instructions, language, images, satellite, tts });
|
|
3681
3729
|
}
|
|
3682
3730
|
catch (e) {
|
|
3683
3731
|
if (localFallback) {
|
|
@@ -5033,13 +5081,25 @@ class Assistant extends adapter_core_1.Adapter {
|
|
|
5033
5081
|
await this.setStateAsync(`${base}.duration`, { val: t.duration, ack: true });
|
|
5034
5082
|
await this.setStateAsync(`${base}.fireAt`, { val: t.fireAt, ack: true });
|
|
5035
5083
|
}
|
|
5084
|
+
/**
|
|
5085
|
+
* The `source` a timer of a satellite gets (the device name, like a timer set there by voice), from the satellite
|
|
5086
|
+
* a script named: '' when it named none, null when the name is unknown.
|
|
5087
|
+
*/
|
|
5088
|
+
timerSatellite(name) {
|
|
5089
|
+
if (typeof name !== 'string' || !name.trim()) {
|
|
5090
|
+
return '';
|
|
5091
|
+
}
|
|
5092
|
+
const id = this.resolveSatelliteId(name);
|
|
5093
|
+
return id ? this.satDeviceById.get(id) || id : null;
|
|
5094
|
+
}
|
|
5036
5095
|
/** A timer expired: record it, play the jingle (if any) and speak the announcement on the origin satellite. */
|
|
5037
5096
|
onTimerFired(t) {
|
|
5038
5097
|
this.log.info(`Timer fired: "${t.label || '(no label)'}"${t.room ? ` (${t.room})` : ''}`);
|
|
5039
5098
|
this.setStateAsync('timers.lastFired', { val: t.label || t.id, ack: true }).catch(() => { });
|
|
5040
|
-
|
|
5099
|
+
// A text a script gave for this timer (a reminder) is said even when timer announcements are off
|
|
5100
|
+
const announce = !!t.announce || this.config.timerAnnounce !== false;
|
|
5041
5101
|
const target = this.announceTargetForSource(t.source);
|
|
5042
|
-
this.fireEffects(this.config.timerSound || '', announce, this.timerAnnounceMessage(t), target);
|
|
5102
|
+
this.fireEffects(this.config.timerSound || '', announce, t.announce || this.timerAnnounceMessage(t), target);
|
|
5043
5103
|
}
|
|
5044
5104
|
/** Build the spoken expiry message ("Timer abgelaufen: die Nudeln.") in the interaction language. */
|
|
5045
5105
|
timerAnnounceMessage(t) {
|