@ziztechnology/dial-library 0.0.12 → 0.0.13
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 +6 -4
- package/dist/index.d.mts +4 -0
- package/dist/index.mjs +246 -202
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -225,9 +225,9 @@ controller.destroy();
|
|
|
225
225
|
|
|
226
226
|
控制器默认每 200ms 读取一次,并保证上一次读取结束后才开始下一次。所有确认都使用传感器时间而不是轮询次数;相同 `sampledAtMs` 的重复数据不会推进窗口。
|
|
227
227
|
|
|
228
|
-
静止和匀速使用 accelerometer 的 1 秒三轴 MAD 稳健波动窗口,至少需要 5 个唯一样本。运动量不高于 `0.12 m/s²` 且陀螺仪足够稳定,连续
|
|
228
|
+
静止和匀速使用 accelerometer 的 1 秒三轴 MAD 稳健波动窗口,至少需要 5 个唯一样本。运动量不高于 `0.12 m/s²` 且陀螺仪足够稳定,连续 3 秒才进入 `STOPPED`;运动量达到 `0.18 m/s²` 或陀螺仪出现持续运动,连续 0.6 秒进入 `STEADY_DRIVING`。中间区间保持原基础状态。
|
|
229
229
|
|
|
230
|
-
普通加速和刹车要求 0.8 秒内至少 4/5 的样本方向一致;急加速和急刹要求峰值、0.6
|
|
230
|
+
普通加速和刹车要求 0.8 秒内至少 4/5 的样本方向一致;急加速和急刹要求峰值、0.6 秒持续均值及方向一致性同时成立,并拒绝垂直能量占主导或短时间反号的颠簸。车辆刚出现方向稳定的物理偏航后,强转向路径要求 0.4 秒内至少 3 个唯一样本,窗口均值达到 `0.08 rad/s`;在默认轮询频率下通常会在 0.4–0.6 秒内触发。转向也可以由累计转角触发,并锁存到回正结束。算法不会预测车辆尚未产生转动时的驾驶意图。最终优先级为:急加减速、已锁存转向、普通加减速、基础状态。
|
|
231
231
|
|
|
232
232
|
缓慢转向还要求偏航旋转占陀螺仪能量的主要部分,或存在足够的横向加速度;垂直颠簸占主导且缺少偏航佐证时不会创建转向事件。重力样本短时缺失时,控制器会在 `maxSampleAgeMs` 内复用最后一个滤波后的车辆坐标系;缓存到期后按传感器不可用处理。单独调用 `classifyDrivingSnapshot()` 不会使用控制器缓存。
|
|
233
233
|
|
|
@@ -254,12 +254,14 @@ console.log(snapshot.tuningVersion);
|
|
|
254
254
|
```ts
|
|
255
255
|
const controller = createDrivingStatusController({
|
|
256
256
|
tuning: {
|
|
257
|
-
turnYawThreshold: 0.
|
|
257
|
+
turnYawThreshold: 0.08,
|
|
258
|
+
turnConfirmationMs: 400,
|
|
259
|
+
turnMinimumSamples: 3,
|
|
258
260
|
motionWindowMs: 1_200,
|
|
259
261
|
motionMinimumSamples: 6,
|
|
260
262
|
drivingMotionThreshold: 0.2,
|
|
261
263
|
stoppedMotionThreshold: 0.11,
|
|
262
|
-
stoppedConfirmationMs:
|
|
264
|
+
stoppedConfirmationMs: 3_000,
|
|
263
265
|
longitudinalThreshold: 0.75,
|
|
264
266
|
turnYawDominanceThreshold: 0.65,
|
|
265
267
|
turnLateralEvidenceThreshold: 0.3,
|
package/dist/index.d.mts
CHANGED
|
@@ -413,6 +413,10 @@ interface DrivingExpressionPlayerSnapshot {
|
|
|
413
413
|
}
|
|
414
414
|
interface DrivingExpressionPlayerOptions {
|
|
415
415
|
config: DrivingExpressionsConfigInput;
|
|
416
|
+
/**
|
|
417
|
+
* Emoji and image entries are renderable fallbacks. Other structured kinds
|
|
418
|
+
* remain accepted for source compatibility but are reported as invalid_config.
|
|
419
|
+
*/
|
|
416
420
|
fallbacks?: Partial<Readonly<Record<CarRunningStatus, StructuredDrivingExpressionMedia>>>;
|
|
417
421
|
loadTimeoutMs?: number;
|
|
418
422
|
retryBackoffMs?: number;
|
package/dist/index.mjs
CHANGED
|
@@ -43,6 +43,45 @@ const dialSdkDebugWarn = (moduleName, scope, phase, data) => {
|
|
|
43
43
|
} catch {}
|
|
44
44
|
};
|
|
45
45
|
//#endregion
|
|
46
|
+
//#region src/helper/sensor.ts
|
|
47
|
+
const extractFreshVector = (metric, capturedAtMs, maxSampleAgeMs) => {
|
|
48
|
+
if (!metric?.available || !Number.isFinite(capturedAtMs) || !Number.isFinite(metric.sampledAtMs)) return null;
|
|
49
|
+
const ageMs = capturedAtMs - metric.sampledAtMs;
|
|
50
|
+
if (ageMs < 0 || ageMs > maxSampleAgeMs) return null;
|
|
51
|
+
const { x, y, z } = metric.value;
|
|
52
|
+
return [
|
|
53
|
+
x,
|
|
54
|
+
y,
|
|
55
|
+
z
|
|
56
|
+
].every(Number.isFinite) ? {
|
|
57
|
+
sampledAtMs: metric.sampledAtMs,
|
|
58
|
+
value: metric.value
|
|
59
|
+
} : null;
|
|
60
|
+
};
|
|
61
|
+
//#endregion
|
|
62
|
+
//#region src/helper/validation.ts
|
|
63
|
+
const requirePositiveFinite = (name, value, debug) => {
|
|
64
|
+
dialSdkDebugWarn(debug.moduleName, debug.scope, "called", {
|
|
65
|
+
name,
|
|
66
|
+
value
|
|
67
|
+
});
|
|
68
|
+
if (!Number.isFinite(value) || value <= 0) {
|
|
69
|
+
const error = /* @__PURE__ */ new RangeError(`${name} must be a positive finite number`);
|
|
70
|
+
dialSdkDebugWarn(debug.moduleName, debug.scope, "threw", error);
|
|
71
|
+
throw error;
|
|
72
|
+
}
|
|
73
|
+
dialSdkDebugWarn(debug.moduleName, debug.scope, "returned", { result: value });
|
|
74
|
+
return value;
|
|
75
|
+
};
|
|
76
|
+
const isRecord = (value, debug) => {
|
|
77
|
+
const result = typeof value === "object" && value !== null && !Array.isArray(value);
|
|
78
|
+
if (debug) dialSdkDebugWarn(debug.moduleName, debug.scope, "returned", {
|
|
79
|
+
value,
|
|
80
|
+
result
|
|
81
|
+
});
|
|
82
|
+
return result;
|
|
83
|
+
};
|
|
84
|
+
//#endregion
|
|
46
85
|
//#region src/sensor/check_status.ts
|
|
47
86
|
const DEBUG_MODULE$5 = "check_status.ts";
|
|
48
87
|
const DEVICE_RIGHT = {
|
|
@@ -56,7 +95,7 @@ const ZERO_VECTOR$1 = {
|
|
|
56
95
|
z: 0
|
|
57
96
|
};
|
|
58
97
|
const DEFAULT_DRIVING_STATUS_TUNING = Object.freeze({
|
|
59
|
-
version: "driving-status-calibrated-2026-07",
|
|
98
|
+
version: "driving-status-calibrated-2026-07-17",
|
|
60
99
|
maxSampleAgeMs: 1e3,
|
|
61
100
|
gravityFilterTimeConstantMs: 1e3,
|
|
62
101
|
biasFilterTimeConstantMs: 1e4,
|
|
@@ -69,7 +108,7 @@ const DEFAULT_DRIVING_STATUS_TUNING = Object.freeze({
|
|
|
69
108
|
stoppedRawGyroThreshold: .065,
|
|
70
109
|
drivingGyroThreshold: .04,
|
|
71
110
|
drivingRawGyroThreshold: .08,
|
|
72
|
-
stoppedConfirmationMs:
|
|
111
|
+
stoppedConfirmationMs: 3e3,
|
|
73
112
|
drivingConfirmationMs: 600,
|
|
74
113
|
longitudinalWindowMs: 800,
|
|
75
114
|
longitudinalMinimumSamples: 5,
|
|
@@ -86,9 +125,9 @@ const DEFAULT_DRIVING_STATUS_TUNING = Object.freeze({
|
|
|
86
125
|
verticalBumpRatio: 1.25,
|
|
87
126
|
longitudinalReversalWindowMs: 400,
|
|
88
127
|
turnWindowMs: 1500,
|
|
89
|
-
turnMinimumSamples:
|
|
90
|
-
turnYawThreshold: .
|
|
91
|
-
turnConfirmationMs:
|
|
128
|
+
turnMinimumSamples: 3,
|
|
129
|
+
turnYawThreshold: .08,
|
|
130
|
+
turnConfirmationMs: 400,
|
|
92
131
|
turnIntegratedAngleThreshold: .12,
|
|
93
132
|
turnSignCoherence: .7,
|
|
94
133
|
turnYawDominanceThreshold: .6,
|
|
@@ -164,7 +203,10 @@ const resolveDrivingStatusTuning = (overrides = {}) => {
|
|
|
164
203
|
"turnExitYawThreshold",
|
|
165
204
|
"turnExitConfirmationMs",
|
|
166
205
|
"turnClosureWindowMs"
|
|
167
|
-
])
|
|
206
|
+
]) requirePositiveFinite(field, tuning[field], {
|
|
207
|
+
moduleName: DEBUG_MODULE$5,
|
|
208
|
+
scope: "assertPositiveFinite"
|
|
209
|
+
});
|
|
168
210
|
for (const field of [
|
|
169
211
|
"motionMinimumSamples",
|
|
170
212
|
"longitudinalMinimumSamples",
|
|
@@ -200,9 +242,9 @@ const extractDrivingSnapshotMetrics = (info, tuning = DEFAULT_DRIVING_STATUS_TUN
|
|
|
200
242
|
dialSdkDebugWarn(DEBUG_MODULE$5, "extractDrivingSnapshotMetrics", "returned invalid capture time", { info });
|
|
201
243
|
return null;
|
|
202
244
|
}
|
|
203
|
-
const linearAcceleration =
|
|
204
|
-
const gyroscope =
|
|
205
|
-
const gravityMetric =
|
|
245
|
+
const linearAcceleration = extractFreshVector(info.linearAcceleration, info.capturedAtMs, tuning.maxSampleAgeMs);
|
|
246
|
+
const gyroscope = extractFreshVector(info.gyroscope, info.capturedAtMs, tuning.maxSampleAgeMs);
|
|
247
|
+
const gravityMetric = extractFreshVector(info.gravity, info.capturedAtMs, tuning.maxSampleAgeMs);
|
|
206
248
|
const gravity = availableCorrectedGravity(correction, info.capturedAtMs, tuning.maxSampleAgeMs) ?? (correction.filteredGravity !== void 0 && gravityMetric !== null ? {
|
|
207
249
|
value: correction.filteredGravity,
|
|
208
250
|
sampledAtMs: gravityMetric.sampledAtMs
|
|
@@ -298,18 +340,6 @@ const classifyInstantaneousEvidence = (metrics, tuning) => {
|
|
|
298
340
|
rejectionReason: null
|
|
299
341
|
};
|
|
300
342
|
};
|
|
301
|
-
const availableFreshVector = (metric, capturedAtMs, maxSampleAgeMs) => {
|
|
302
|
-
if (!metric?.available || !isFresh(metric.sampledAtMs, capturedAtMs, maxSampleAgeMs)) return null;
|
|
303
|
-
const { x, y, z } = metric.value;
|
|
304
|
-
return [
|
|
305
|
-
x,
|
|
306
|
-
y,
|
|
307
|
-
z
|
|
308
|
-
].every(Number.isFinite) ? {
|
|
309
|
-
value: metric.value,
|
|
310
|
-
sampledAtMs: metric.sampledAtMs
|
|
311
|
-
} : null;
|
|
312
|
-
};
|
|
313
343
|
const availableCorrectedGravity = (correction, capturedAtMs, maxSampleAgeMs) => {
|
|
314
344
|
const { filteredGravity, filteredGravitySampledAtMs } = correction;
|
|
315
345
|
if (filteredGravity === void 0 || filteredGravitySampledAtMs === void 0 || !isFresh(filteredGravitySampledAtMs, capturedAtMs, maxSampleAgeMs)) return null;
|
|
@@ -349,13 +379,6 @@ const normalize = (value) => {
|
|
|
349
379
|
const length = magnitude(value);
|
|
350
380
|
return Number.isFinite(length) && length > Number.EPSILON ? scale(value, 1 / length) : null;
|
|
351
381
|
};
|
|
352
|
-
const assertPositiveFinite = (name, value) => {
|
|
353
|
-
if (!Number.isFinite(value) || value <= 0) {
|
|
354
|
-
const error = /* @__PURE__ */ new RangeError(`${name} must be a positive finite number`);
|
|
355
|
-
dialSdkDebugWarn(DEBUG_MODULE$5, "assertPositiveFinite", "threw", error);
|
|
356
|
-
throw error;
|
|
357
|
-
}
|
|
358
|
-
};
|
|
359
382
|
const throwLoggedRangeError = (scope, message) => {
|
|
360
383
|
const error = new RangeError(message);
|
|
361
384
|
dialSdkDebugWarn(DEBUG_MODULE$5, scope, "threw", error);
|
|
@@ -421,8 +444,51 @@ const CAR_RUNNING_STATUS_PRIORITY = {
|
|
|
421
444
|
SUDDEN_BRAKING: 5
|
|
422
445
|
};
|
|
423
446
|
//#endregion
|
|
447
|
+
//#region src/helper/async.ts
|
|
448
|
+
const createAbortError = (message, debug) => {
|
|
449
|
+
dialSdkDebugWarn(debug.moduleName, debug.scope, "called");
|
|
450
|
+
if (typeof DOMException === "function") {
|
|
451
|
+
const result = new DOMException(message, "AbortError");
|
|
452
|
+
dialSdkDebugWarn(debug.moduleName, debug.scope, "returned DOMException", { result });
|
|
453
|
+
return result;
|
|
454
|
+
}
|
|
455
|
+
const error = new Error(message);
|
|
456
|
+
error.name = "AbortError";
|
|
457
|
+
dialSdkDebugWarn(debug.moduleName, debug.scope, "returned Error", { result: error });
|
|
458
|
+
return error;
|
|
459
|
+
};
|
|
460
|
+
const isAbortError = (error, debug) => {
|
|
461
|
+
const result = error instanceof Error && error.name === "AbortError";
|
|
462
|
+
if (debug) dialSdkDebugWarn(debug.moduleName, debug.scope, "returned", {
|
|
463
|
+
error,
|
|
464
|
+
result
|
|
465
|
+
});
|
|
466
|
+
return result;
|
|
467
|
+
};
|
|
468
|
+
const invokeSafely = (callback, args, onError) => {
|
|
469
|
+
try {
|
|
470
|
+
callback(...args);
|
|
471
|
+
return true;
|
|
472
|
+
} catch (error) {
|
|
473
|
+
onError(error);
|
|
474
|
+
return false;
|
|
475
|
+
}
|
|
476
|
+
};
|
|
477
|
+
//#endregion
|
|
424
478
|
//#region src/sensor/driving_expressions.ts
|
|
425
479
|
const DEBUG_MODULE$3 = "driving_expressions.ts";
|
|
480
|
+
const IS_RECORD_DEBUG$1 = {
|
|
481
|
+
moduleName: DEBUG_MODULE$3,
|
|
482
|
+
scope: "isRecord"
|
|
483
|
+
};
|
|
484
|
+
const REQUIRE_POSITIVE_FINITE_DEBUG$1 = {
|
|
485
|
+
moduleName: DEBUG_MODULE$3,
|
|
486
|
+
scope: "requirePositiveFinite"
|
|
487
|
+
};
|
|
488
|
+
const CREATE_ABORT_ERROR_DEBUG$1 = {
|
|
489
|
+
moduleName: DEBUG_MODULE$3,
|
|
490
|
+
scope: "createAbortError"
|
|
491
|
+
};
|
|
426
492
|
const OFFICIAL_DRIVING_EXPRESSION_FALLBACKS = Object.freeze({
|
|
427
493
|
STOPPED: Object.freeze({
|
|
428
494
|
kind: "emoji",
|
|
@@ -490,7 +556,7 @@ const parseDrivingExpressionsConfig = (raw, options = {}) => {
|
|
|
490
556
|
options
|
|
491
557
|
});
|
|
492
558
|
const parsed = parseJsonObject(raw);
|
|
493
|
-
if (parsed.schemaVersion !== 1 || !isRecord
|
|
559
|
+
if (parsed.schemaVersion !== 1 || !isRecord(parsed.states, IS_RECORD_DEBUG$1)) throw new DrivingExpressionsConfigError("DRIVING_EXPRESSIONS_INVALID_SCHEMA", "drivingExpressions must use schemaVersion 1 and contain a states object");
|
|
494
560
|
const knownStatuses = new Set(CAR_RUNNING_STATUSES);
|
|
495
561
|
const stateKeys = Object.keys(parsed.states);
|
|
496
562
|
if (stateKeys.length !== CAR_RUNNING_STATUSES.length || stateKeys.some((key) => !knownStatuses.has(key))) throw new DrivingExpressionsConfigError("DRIVING_EXPRESSIONS_INCOMPLETE", "drivingExpressions.states must contain exactly the eight supported statuses");
|
|
@@ -516,6 +582,10 @@ const tryParseDrivingExpressionsConfig = (raw, options) => {
|
|
|
516
582
|
dialSdkDebugWarn(DEBUG_MODULE$3, "tryParseDrivingExpressionsConfig", "returned", { result });
|
|
517
583
|
return result;
|
|
518
584
|
} catch (error) {
|
|
585
|
+
if (!(error instanceof DrivingExpressionsConfigError)) {
|
|
586
|
+
dialSdkDebugWarn(DEBUG_MODULE$3, "tryParseDrivingExpressionsConfig", "threw unexpected error", error);
|
|
587
|
+
throw error;
|
|
588
|
+
}
|
|
519
589
|
dialSdkDebugWarn(DEBUG_MODULE$3, "tryParseDrivingExpressionsConfig", "returned null after parse error", error);
|
|
520
590
|
return null;
|
|
521
591
|
}
|
|
@@ -544,7 +614,7 @@ const readDrivingExpressionsConfig = (raw, options) => {
|
|
|
544
614
|
const waitForDrivingExpressionsConfig = (options = {}) => {
|
|
545
615
|
dialSdkDebugWarn(DEBUG_MODULE$3, "waitForDrivingExpressionsConfig", "called", { options });
|
|
546
616
|
const timeoutMs = requireNonNegativeFinite("timeoutMs", options.timeoutMs ?? 3e3);
|
|
547
|
-
const pollIntervalMs = requirePositiveFinite
|
|
617
|
+
const pollIntervalMs = requirePositiveFinite("pollIntervalMs", options.pollIntervalMs ?? 100, REQUIRE_POSITIVE_FINITE_DEBUG$1);
|
|
548
618
|
const { signal } = options;
|
|
549
619
|
return new Promise((resolve, reject) => {
|
|
550
620
|
const deadlineMs = Date.now() + timeoutMs;
|
|
@@ -592,7 +662,7 @@ const waitForDrivingExpressionsConfig = (options = {}) => {
|
|
|
592
662
|
};
|
|
593
663
|
const handleAbort = () => {
|
|
594
664
|
dialSdkDebugWarn(DEBUG_MODULE$3, "waitForDrivingExpressionsConfig.handleAbort", "called");
|
|
595
|
-
fail(createAbortError$1
|
|
665
|
+
fail(createAbortError("The operation was aborted", CREATE_ABORT_ERROR_DEBUG$1));
|
|
596
666
|
};
|
|
597
667
|
const read = () => {
|
|
598
668
|
dialSdkDebugWarn(DEBUG_MODULE$3, "waitForDrivingExpressionsConfig.read", "called");
|
|
@@ -610,7 +680,13 @@ const waitForDrivingExpressionsConfig = (options = {}) => {
|
|
|
610
680
|
handleAbort();
|
|
611
681
|
return;
|
|
612
682
|
}
|
|
613
|
-
|
|
683
|
+
let config;
|
|
684
|
+
try {
|
|
685
|
+
config = read();
|
|
686
|
+
} catch (error) {
|
|
687
|
+
fail(error);
|
|
688
|
+
return;
|
|
689
|
+
}
|
|
614
690
|
if (config !== null) {
|
|
615
691
|
finish(config);
|
|
616
692
|
return;
|
|
@@ -905,7 +981,7 @@ const parseDrivingExpressionMedia = (raw, status, options) => {
|
|
|
905
981
|
dialSdkDebugWarn(DEBUG_MODULE$3, "parseDrivingExpressionMedia", "returned legacy image", { result });
|
|
906
982
|
return result;
|
|
907
983
|
}
|
|
908
|
-
if (!isRecord$1
|
|
984
|
+
if (!isRecord(raw, IS_RECORD_DEBUG$1) || typeof raw.kind !== "string") throw invalidMedia(status, "media must be a structured object with a supported kind");
|
|
909
985
|
const mediaAssetId = parseMediaAssetId(raw.mediaAssetId, status);
|
|
910
986
|
assertFieldsAbsent(raw, status, [
|
|
911
987
|
"items",
|
|
@@ -1011,7 +1087,7 @@ const parseJsonObject = (raw) => {
|
|
|
1011
1087
|
});
|
|
1012
1088
|
throw error;
|
|
1013
1089
|
}
|
|
1014
|
-
if (!isRecord$1
|
|
1090
|
+
if (!isRecord(value, IS_RECORD_DEBUG$1)) {
|
|
1015
1091
|
const error = new DrivingExpressionsConfigError("DRIVING_EXPRESSIONS_INVALID_SCHEMA", "drivingExpressions must be a JSON object or JSON object string");
|
|
1016
1092
|
dialSdkDebugWarn(DEBUG_MODULE$3, "parseJsonObject", "threw", error);
|
|
1017
1093
|
throw error;
|
|
@@ -1028,7 +1104,7 @@ const readRuntimeDrivingExpressionsValue = () => {
|
|
|
1028
1104
|
return result;
|
|
1029
1105
|
}
|
|
1030
1106
|
const faceConfig = runtimeGlobal.__TOOOONY_FACE_CONFIG__;
|
|
1031
|
-
if (!isRecord$1
|
|
1107
|
+
if (!isRecord(faceConfig, IS_RECORD_DEBUG$1)) {
|
|
1032
1108
|
dialSdkDebugWarn(DEBUG_MODULE$3, "readRuntimeDrivingExpressionsValue", "returned", { result: void 0 });
|
|
1033
1109
|
return;
|
|
1034
1110
|
}
|
|
@@ -1037,7 +1113,7 @@ const readRuntimeDrivingExpressionsValue = () => {
|
|
|
1037
1113
|
dialSdkDebugWarn(DEBUG_MODULE$3, "readRuntimeDrivingExpressionsValue", "returned face config", { result });
|
|
1038
1114
|
return result;
|
|
1039
1115
|
}
|
|
1040
|
-
const result = isRecord
|
|
1116
|
+
const result = isRecord(faceConfig.values, IS_RECORD_DEBUG$1) ? faceConfig.values.drivingExpressions : void 0;
|
|
1041
1117
|
dialSdkDebugWarn(DEBUG_MODULE$3, "readRuntimeDrivingExpressionsValue", "returned legacy face config", { result });
|
|
1042
1118
|
return result;
|
|
1043
1119
|
};
|
|
@@ -1159,14 +1235,6 @@ const compact = (value) => {
|
|
|
1159
1235
|
dialSdkDebugWarn(DEBUG_MODULE$3, "compact", "returned", { result: value });
|
|
1160
1236
|
return value;
|
|
1161
1237
|
};
|
|
1162
|
-
const isRecord$1 = (value) => {
|
|
1163
|
-
const result = typeof value === "object" && value !== null && !Array.isArray(value);
|
|
1164
|
-
dialSdkDebugWarn(DEBUG_MODULE$3, "isRecord", "returned", {
|
|
1165
|
-
value,
|
|
1166
|
-
result
|
|
1167
|
-
});
|
|
1168
|
-
return result;
|
|
1169
|
-
};
|
|
1170
1238
|
const requireNonNegativeFinite = (name, value) => {
|
|
1171
1239
|
dialSdkDebugWarn(DEBUG_MODULE$3, "requireNonNegativeFinite", "called", {
|
|
1172
1240
|
name,
|
|
@@ -1180,31 +1248,6 @@ const requireNonNegativeFinite = (name, value) => {
|
|
|
1180
1248
|
dialSdkDebugWarn(DEBUG_MODULE$3, "requireNonNegativeFinite", "returned", { result: value });
|
|
1181
1249
|
return value;
|
|
1182
1250
|
};
|
|
1183
|
-
const requirePositiveFinite$1 = (name, value) => {
|
|
1184
|
-
dialSdkDebugWarn(DEBUG_MODULE$3, "requirePositiveFinite", "called", {
|
|
1185
|
-
name,
|
|
1186
|
-
value
|
|
1187
|
-
});
|
|
1188
|
-
if (!Number.isFinite(value) || value <= 0) {
|
|
1189
|
-
const error = /* @__PURE__ */ new RangeError(`${name} must be a positive finite number`);
|
|
1190
|
-
dialSdkDebugWarn(DEBUG_MODULE$3, "requirePositiveFinite", "threw", error);
|
|
1191
|
-
throw error;
|
|
1192
|
-
}
|
|
1193
|
-
dialSdkDebugWarn(DEBUG_MODULE$3, "requirePositiveFinite", "returned", { result: value });
|
|
1194
|
-
return value;
|
|
1195
|
-
};
|
|
1196
|
-
const createAbortError$1 = () => {
|
|
1197
|
-
dialSdkDebugWarn(DEBUG_MODULE$3, "createAbortError", "called");
|
|
1198
|
-
if (typeof DOMException === "function") {
|
|
1199
|
-
const result = new DOMException("The operation was aborted", "AbortError");
|
|
1200
|
-
dialSdkDebugWarn(DEBUG_MODULE$3, "createAbortError", "returned DOMException", { result });
|
|
1201
|
-
return result;
|
|
1202
|
-
}
|
|
1203
|
-
const error = /* @__PURE__ */ new Error("The operation was aborted");
|
|
1204
|
-
error.name = "AbortError";
|
|
1205
|
-
dialSdkDebugWarn(DEBUG_MODULE$3, "createAbortError", "returned Error", { result: error });
|
|
1206
|
-
return error;
|
|
1207
|
-
};
|
|
1208
1251
|
//#endregion
|
|
1209
1252
|
//#region src/sensor/page_lifecycle.ts
|
|
1210
1253
|
const DEBUG_MODULE$2 = "page_lifecycle.ts";
|
|
@@ -1339,12 +1382,9 @@ const dispatchResume = () => {
|
|
|
1339
1382
|
};
|
|
1340
1383
|
const safeInvoke = (callback) => {
|
|
1341
1384
|
dialSdkDebugWarn(DEBUG_MODULE$2, "safeInvoke", "called");
|
|
1342
|
-
|
|
1343
|
-
callback();
|
|
1344
|
-
dialSdkDebugWarn(DEBUG_MODULE$2, "safeInvoke", "returned");
|
|
1345
|
-
} catch (error) {
|
|
1385
|
+
if (invokeSafely(callback, [], (error) => {
|
|
1346
1386
|
dialSdkDebugWarn(DEBUG_MODULE$2, "safeInvoke", "callback threw", error);
|
|
1347
|
-
}
|
|
1387
|
+
})) dialSdkDebugWarn(DEBUG_MODULE$2, "safeInvoke", "returned");
|
|
1348
1388
|
};
|
|
1349
1389
|
//#endregion
|
|
1350
1390
|
//#region src/sensor/driving_status_controller.ts
|
|
@@ -1354,6 +1394,10 @@ const ZERO_VECTOR = {
|
|
|
1354
1394
|
y: 0,
|
|
1355
1395
|
z: 0
|
|
1356
1396
|
};
|
|
1397
|
+
const REQUIRE_POSITIVE_FINITE_DEBUG = {
|
|
1398
|
+
moduleName: DEBUG_MODULE$1,
|
|
1399
|
+
scope: "requirePositiveFinite"
|
|
1400
|
+
};
|
|
1357
1401
|
const createDrivingStatusController = (options = {}) => {
|
|
1358
1402
|
dialSdkDebugWarn(DEBUG_MODULE$1, "createDrivingStatusController", "called", { options });
|
|
1359
1403
|
const result = new DefaultDrivingStatusController(options);
|
|
@@ -1437,9 +1481,9 @@ var DefaultDrivingStatusController = class {
|
|
|
1437
1481
|
dialSdkDebugWarn(DEBUG_MODULE$1, "DefaultDrivingStatusController.handleLifecycleResume", "returned");
|
|
1438
1482
|
};
|
|
1439
1483
|
dialSdkDebugWarn(DEBUG_MODULE$1, "DefaultDrivingStatusController.constructor", "called", { options });
|
|
1440
|
-
this.sensorProvider = options.sensorProvider ??
|
|
1441
|
-
this.pollIntervalMs = requirePositiveFinite("pollIntervalMs", options.pollIntervalMs ?? 200);
|
|
1442
|
-
this.unavailableFallbackMs = requirePositiveFinite("unavailableFallbackMs", options.unavailableFallbackMs ?? 3e3);
|
|
1484
|
+
this.sensorProvider = options.sensorProvider ?? unifiedSensorInfo;
|
|
1485
|
+
this.pollIntervalMs = requirePositiveFinite("pollIntervalMs", options.pollIntervalMs ?? 200, REQUIRE_POSITIVE_FINITE_DEBUG);
|
|
1486
|
+
this.unavailableFallbackMs = requirePositiveFinite("unavailableFallbackMs", options.unavailableFallbackMs ?? 3e3, REQUIRE_POSITIVE_FINITE_DEBUG);
|
|
1443
1487
|
this.tuning = resolveDrivingStatusTuning(options.tuning);
|
|
1444
1488
|
this.clock = options.clock ?? systemClock;
|
|
1445
1489
|
this.onDiagnostic = options.onDiagnostic;
|
|
@@ -1610,7 +1654,7 @@ var DefaultDrivingStatusController = class {
|
|
|
1610
1654
|
linearAccelerationBias: this.linearAccelerationBias,
|
|
1611
1655
|
gyroscopeBias: this.gyroscopeBias
|
|
1612
1656
|
});
|
|
1613
|
-
const accelerometerSample =
|
|
1657
|
+
const accelerometerSample = extractFreshVector(payload.accelerometer, payload.capturedAtMs, this.tuning.maxSampleAgeMs);
|
|
1614
1658
|
if (gravity === null || metrics === null || accelerometerSample === null) {
|
|
1615
1659
|
dialSdkDebugWarn(DEBUG_MODULE$1, "DefaultDrivingStatusController.poll", "invalid or stale snapshot", {
|
|
1616
1660
|
metrics,
|
|
@@ -1622,7 +1666,7 @@ var DefaultDrivingStatusController = class {
|
|
|
1622
1666
|
dialSdkDebugWarn(DEBUG_MODULE$1, "DefaultDrivingStatusController.poll", "processed sample", { capturedAtMs: metrics.capturedAtMs });
|
|
1623
1667
|
}
|
|
1624
1668
|
} catch (error) {
|
|
1625
|
-
if (!this.polling || generation !== this.generation || pendingRead.signal.aborted || isAbortError
|
|
1669
|
+
if (!this.polling || generation !== this.generation || pendingRead.signal.aborted || isAbortError(error)) {
|
|
1626
1670
|
dialSdkDebugWarn(DEBUG_MODULE$1, "DefaultDrivingStatusController.poll", "ignored provider error", { error });
|
|
1627
1671
|
return;
|
|
1628
1672
|
}
|
|
@@ -1638,7 +1682,7 @@ var DefaultDrivingStatusController = class {
|
|
|
1638
1682
|
}
|
|
1639
1683
|
}
|
|
1640
1684
|
resolveGravityFrame(info) {
|
|
1641
|
-
const sample =
|
|
1685
|
+
const sample = extractFreshVector(info.gravity, info.capturedAtMs, this.tuning.maxSampleAgeMs);
|
|
1642
1686
|
if (sample === null) {
|
|
1643
1687
|
if (this.filteredGravity === null || this.lastGravitySampledAtMs === null) return null;
|
|
1644
1688
|
const ageMs = info.capturedAtMs - this.lastGravitySampledAtMs;
|
|
@@ -1882,7 +1926,15 @@ var DefaultDrivingStatusController = class {
|
|
|
1882
1926
|
});
|
|
1883
1927
|
}
|
|
1884
1928
|
commitSelectedStatus(now) {
|
|
1885
|
-
const selected =
|
|
1929
|
+
const selected = [
|
|
1930
|
+
this.baseStatus,
|
|
1931
|
+
this.normalLongitudinalStatus,
|
|
1932
|
+
this.turnStatus,
|
|
1933
|
+
this.urgentStatus
|
|
1934
|
+
].reduce((highest, candidate) => {
|
|
1935
|
+
if (candidate === null) return highest;
|
|
1936
|
+
return CAR_RUNNING_STATUS_PRIORITY[candidate] > CAR_RUNNING_STATUS_PRIORITY[highest] ? candidate : highest;
|
|
1937
|
+
}, this.baseStatus);
|
|
1886
1938
|
this.commit(selected, now, "candidate_confirmed");
|
|
1887
1939
|
}
|
|
1888
1940
|
processUnavailable(category) {
|
|
@@ -1940,7 +1992,12 @@ var DefaultDrivingStatusController = class {
|
|
|
1940
1992
|
reason,
|
|
1941
1993
|
atMs: now
|
|
1942
1994
|
};
|
|
1943
|
-
for (const listener of [...this.listeners])
|
|
1995
|
+
for (const listener of [...this.listeners]) invokeSafely(listener, [event], (error) => {
|
|
1996
|
+
dialSdkDebugWarn(DEBUG_MODULE$1, "safeCall", "callback threw", {
|
|
1997
|
+
error,
|
|
1998
|
+
value: event
|
|
1999
|
+
});
|
|
2000
|
+
});
|
|
1944
2001
|
this.emitDiagnostic({
|
|
1945
2002
|
type: "status_committed",
|
|
1946
2003
|
atMs: now,
|
|
@@ -2002,7 +2059,12 @@ var DefaultDrivingStatusController = class {
|
|
|
2002
2059
|
event,
|
|
2003
2060
|
hasListener: this.onDiagnostic !== void 0
|
|
2004
2061
|
});
|
|
2005
|
-
if (this.onDiagnostic)
|
|
2062
|
+
if (this.onDiagnostic) invokeSafely(this.onDiagnostic, [event], (error) => {
|
|
2063
|
+
dialSdkDebugWarn(DEBUG_MODULE$1, "safeCall", "callback threw", {
|
|
2064
|
+
error,
|
|
2065
|
+
value: event
|
|
2066
|
+
});
|
|
2067
|
+
});
|
|
2006
2068
|
}
|
|
2007
2069
|
attachLifecycleListeners() {
|
|
2008
2070
|
if (!this.managePageLifecycle || this.unsubscribePageLifecycle !== null) return;
|
|
@@ -2187,7 +2249,6 @@ const median = (values) => {
|
|
|
2187
2249
|
const pushUniqueMetric = (window, metrics, timestampKey, windowMs) => {
|
|
2188
2250
|
const latest = window[window.length - 1];
|
|
2189
2251
|
if (latest && metrics[timestampKey] <= latest[timestampKey]) return false;
|
|
2190
|
-
if (window.some((value) => value[timestampKey] === metrics[timestampKey])) return false;
|
|
2191
2252
|
window.push(metrics);
|
|
2192
2253
|
const cutoffMs = metrics[timestampKey] - windowMs;
|
|
2193
2254
|
while (window[0] && window[0][timestampKey] < cutoffMs) window.shift();
|
|
@@ -2196,67 +2257,44 @@ const pushUniqueMetric = (window, metrics, timestampKey, windowMs) => {
|
|
|
2196
2257
|
const pushUniqueVector = (window, sample, windowMs) => {
|
|
2197
2258
|
const latest = window[window.length - 1];
|
|
2198
2259
|
if (latest && sample.sampledAtMs <= latest.sampledAtMs) return false;
|
|
2199
|
-
if (window.some((value) => value.sampledAtMs === sample.sampledAtMs)) return false;
|
|
2200
2260
|
window.push(sample);
|
|
2201
2261
|
const cutoffMs = sample.sampledAtMs - windowMs;
|
|
2202
2262
|
while (window[0] && window[0].sampledAtMs < cutoffMs) window.shift();
|
|
2203
2263
|
return true;
|
|
2204
2264
|
};
|
|
2205
|
-
const extractFreshVectorMetric = (metric, capturedAtMs, maxSampleAgeMs) => {
|
|
2206
|
-
if (!metric?.available || !Number.isFinite(capturedAtMs) || !Number.isFinite(metric.sampledAtMs)) return null;
|
|
2207
|
-
const ageMs = capturedAtMs - metric.sampledAtMs;
|
|
2208
|
-
if (ageMs < 0 || ageMs > maxSampleAgeMs) return null;
|
|
2209
|
-
const { x, y, z } = metric.value;
|
|
2210
|
-
return [
|
|
2211
|
-
x,
|
|
2212
|
-
y,
|
|
2213
|
-
z
|
|
2214
|
-
].every(Number.isFinite) ? {
|
|
2215
|
-
sampledAtMs: metric.sampledAtMs,
|
|
2216
|
-
value: metric.value
|
|
2217
|
-
} : null;
|
|
2218
|
-
};
|
|
2219
2265
|
const observationTime = (metrics) => Math.max(metrics.linearAccelerationSampledAtMs, metrics.gyroscopeSampledAtMs);
|
|
2220
2266
|
const lerpVector = (from, to, alpha) => ({
|
|
2221
2267
|
x: from.x + (to.x - from.x) * alpha,
|
|
2222
2268
|
y: from.y + (to.y - from.y) * alpha,
|
|
2223
2269
|
z: from.z + (to.z - from.z) * alpha
|
|
2224
2270
|
});
|
|
2225
|
-
const defaultSensorProvider = () => {
|
|
2226
|
-
const runtimeGlobal = globalThis;
|
|
2227
|
-
if (typeof runtimeGlobal.unifiedSensorInfo !== "function") return Promise.reject(/* @__PURE__ */ new Error("window.unifiedSensorInfo is unavailable"));
|
|
2228
|
-
return runtimeGlobal.unifiedSensorInfo();
|
|
2229
|
-
};
|
|
2230
2271
|
const systemClock = {
|
|
2231
2272
|
now: () => Date.now(),
|
|
2232
2273
|
setTimeout: (callback, delayMs) => globalThis.setTimeout(callback, delayMs),
|
|
2233
2274
|
clearTimeout: (handle) => globalThis.clearTimeout(handle)
|
|
2234
2275
|
};
|
|
2235
2276
|
const isBaseStatus = (status) => status === "STOPPED" || status === "STEADY_DRIVING";
|
|
2236
|
-
const isAbortError$1 = (error) => error instanceof Error && error.name === "AbortError";
|
|
2237
|
-
const requirePositiveFinite = (name, value) => {
|
|
2238
|
-
if (!Number.isFinite(value) || value <= 0) {
|
|
2239
|
-
const error = /* @__PURE__ */ new RangeError(`${name} must be a positive finite number`);
|
|
2240
|
-
dialSdkDebugWarn(DEBUG_MODULE$1, "requirePositiveFinite", "threw", error);
|
|
2241
|
-
throw error;
|
|
2242
|
-
}
|
|
2243
|
-
return value;
|
|
2244
|
-
};
|
|
2245
|
-
const safeCall = (callback, value) => {
|
|
2246
|
-
try {
|
|
2247
|
-
callback(value);
|
|
2248
|
-
} catch (error) {
|
|
2249
|
-
dialSdkDebugWarn(DEBUG_MODULE$1, "safeCall", "callback threw", {
|
|
2250
|
-
error,
|
|
2251
|
-
value
|
|
2252
|
-
});
|
|
2253
|
-
}
|
|
2254
|
-
};
|
|
2255
2277
|
const noop = () => void 0;
|
|
2256
2278
|
//#endregion
|
|
2257
2279
|
//#region src/sensor/driving_expression_player.ts
|
|
2258
2280
|
const DEBUG_MODULE = "driving_expression_player.ts";
|
|
2259
2281
|
const MAX_RETAINED_IMAGES = 3;
|
|
2282
|
+
const POSITIVE_FINITE_DEBUG = {
|
|
2283
|
+
moduleName: DEBUG_MODULE,
|
|
2284
|
+
scope: "positiveFinite"
|
|
2285
|
+
};
|
|
2286
|
+
const CREATE_ABORT_ERROR_DEBUG = {
|
|
2287
|
+
moduleName: DEBUG_MODULE,
|
|
2288
|
+
scope: "createAbortError"
|
|
2289
|
+
};
|
|
2290
|
+
const IS_ABORT_ERROR_DEBUG = {
|
|
2291
|
+
moduleName: DEBUG_MODULE,
|
|
2292
|
+
scope: "isAbortError"
|
|
2293
|
+
};
|
|
2294
|
+
const IS_RECORD_DEBUG = {
|
|
2295
|
+
moduleName: DEBUG_MODULE,
|
|
2296
|
+
scope: "isRecord"
|
|
2297
|
+
};
|
|
2260
2298
|
const createDrivingExpressionPlayer = (container, options) => {
|
|
2261
2299
|
dialSdkDebugWarn(DEBUG_MODULE, "createDrivingExpressionPlayer", "called", {
|
|
2262
2300
|
container,
|
|
@@ -2273,6 +2311,7 @@ var DefaultDrivingExpressionPlayer = class {
|
|
|
2273
2311
|
this.mediaKind = null;
|
|
2274
2312
|
this.errorCategory = null;
|
|
2275
2313
|
this.desiredMedia = null;
|
|
2314
|
+
this.desiredMediaRole = null;
|
|
2276
2315
|
this.userPaused = false;
|
|
2277
2316
|
this.lifecycleSuspended = false;
|
|
2278
2317
|
this.paused = false;
|
|
@@ -2321,15 +2360,15 @@ var DefaultDrivingExpressionPlayer = class {
|
|
|
2321
2360
|
this.document = container.ownerDocument;
|
|
2322
2361
|
this.config = options.config;
|
|
2323
2362
|
this.fallbacks = options.fallbacks;
|
|
2324
|
-
this.loadTimeoutMs =
|
|
2325
|
-
this.retryBackoffMs =
|
|
2363
|
+
this.loadTimeoutMs = requirePositiveFinite("loadTimeoutMs", options.loadTimeoutMs ?? 5e3, POSITIVE_FINITE_DEBUG);
|
|
2364
|
+
this.retryBackoffMs = requirePositiveFinite("retryBackoffMs", options.retryBackoffMs ?? 15e3, POSITIVE_FINITE_DEBUG);
|
|
2326
2365
|
this.fit = options.fit ?? "contain";
|
|
2327
2366
|
this.tgsRenderer = defaultTgsRenderer;
|
|
2328
2367
|
this.fetchImplementation = options.fetch ?? globalThis.fetch?.bind(globalThis);
|
|
2329
2368
|
this.onDiagnostic = options.onDiagnostic;
|
|
2330
|
-
this.maxTgsCompressedBytes =
|
|
2331
|
-
this.maxTgsJsonBytes =
|
|
2332
|
-
this.maxTgsLayers =
|
|
2369
|
+
this.maxTgsCompressedBytes = requirePositiveFinite("maxTgsCompressedBytes", options.maxTgsCompressedBytes ?? 2 * 1024 * 1024, POSITIVE_FINITE_DEBUG);
|
|
2370
|
+
this.maxTgsJsonBytes = requirePositiveFinite("maxTgsJsonBytes", options.maxTgsJsonBytes ?? 8 * 1024 * 1024, POSITIVE_FINITE_DEBUG);
|
|
2371
|
+
this.maxTgsLayers = requirePositiveFinite("maxTgsLayers", options.maxTgsLayers ?? 500, POSITIVE_FINITE_DEBUG);
|
|
2333
2372
|
if (options.managePageLifecycle ?? true) this.unsubscribePageLifecycle = subscribeDrivingPageLifecycle(this.handleLifecyclePause, this.handleLifecycleResume);
|
|
2334
2373
|
dialSdkDebugWarn(DEBUG_MODULE, "DefaultDrivingExpressionPlayer.constructor", "created", {
|
|
2335
2374
|
loadTimeoutMs: this.loadTimeoutMs,
|
|
@@ -2354,24 +2393,33 @@ var DefaultDrivingExpressionPlayer = class {
|
|
|
2354
2393
|
const operation = this.beginOperation();
|
|
2355
2394
|
const configured = this.config.states[status];
|
|
2356
2395
|
if (configured === void 0) {
|
|
2357
|
-
const fallback = this.
|
|
2358
|
-
if (fallback ===
|
|
2396
|
+
const fallback = this.resolveFallback(status);
|
|
2397
|
+
if (fallback.type === "missing") {
|
|
2398
|
+
this.desiredMedia = null;
|
|
2399
|
+
this.desiredMediaRole = null;
|
|
2359
2400
|
this.handleFailure(status, null, new DrivingExpressionResolutionError(status), "invalid_config", operation, false);
|
|
2360
2401
|
dialSdkDebugWarn(DEBUG_MODULE, "DefaultDrivingExpressionPlayer.show", "returned after missing config");
|
|
2361
2402
|
return;
|
|
2362
2403
|
}
|
|
2363
|
-
this.desiredMedia = fallback;
|
|
2404
|
+
this.desiredMedia = fallback.media;
|
|
2405
|
+
this.desiredMediaRole = "fallback";
|
|
2364
2406
|
if (this.paused) {
|
|
2365
2407
|
this.phase = "idle";
|
|
2366
2408
|
dialSdkDebugWarn(DEBUG_MODULE, "DefaultDrivingExpressionPlayer.show", "deferred fallback while paused");
|
|
2367
2409
|
return;
|
|
2368
2410
|
}
|
|
2369
|
-
|
|
2411
|
+
if (fallback.type === "unsupported") {
|
|
2412
|
+
this.handleFailure(status, fallback.media, unsupportedFallbackError(fallback.media), "invalid_config", operation, false, false);
|
|
2413
|
+
dialSdkDebugWarn(DEBUG_MODULE, "DefaultDrivingExpressionPlayer.show", "returned unsupported fallback");
|
|
2414
|
+
return;
|
|
2415
|
+
}
|
|
2416
|
+
this.renderFallback(status, fallback.media);
|
|
2370
2417
|
dialSdkDebugWarn(DEBUG_MODULE, "DefaultDrivingExpressionPlayer.show", "returned fallback", { snapshot: this.getSnapshot() });
|
|
2371
2418
|
return;
|
|
2372
2419
|
}
|
|
2373
2420
|
const media = normalizeMedia(configured);
|
|
2374
2421
|
this.desiredMedia = media;
|
|
2422
|
+
this.desiredMediaRole = "primary";
|
|
2375
2423
|
if (this.paused) {
|
|
2376
2424
|
this.phase = "idle";
|
|
2377
2425
|
dialSdkDebugWarn(DEBUG_MODULE, "DefaultDrivingExpressionPlayer.show", "deferred media while paused", { media });
|
|
@@ -2422,6 +2470,7 @@ var DefaultDrivingExpressionPlayer = class {
|
|
|
2422
2470
|
this.container.replaceChildren();
|
|
2423
2471
|
this.status = null;
|
|
2424
2472
|
this.desiredMedia = null;
|
|
2473
|
+
this.desiredMediaRole = null;
|
|
2425
2474
|
this.phase = "idle";
|
|
2426
2475
|
this.mediaKind = null;
|
|
2427
2476
|
this.errorCategory = null;
|
|
@@ -2490,7 +2539,12 @@ var DefaultDrivingExpressionPlayer = class {
|
|
|
2490
2539
|
}
|
|
2491
2540
|
if (this.status !== null && this.desiredMedia !== null) {
|
|
2492
2541
|
const operation = this.beginOperation();
|
|
2493
|
-
|
|
2542
|
+
if (this.desiredMediaRole === "fallback") {
|
|
2543
|
+
const status = this.status;
|
|
2544
|
+
const fallback = this.desiredMedia;
|
|
2545
|
+
if (isStaticFallback(fallback)) this.renderFallback(status, fallback);
|
|
2546
|
+
else this.handleFailure(status, fallback, unsupportedFallbackError(fallback), "invalid_config", operation, false, false);
|
|
2547
|
+
} else this.load(this.status, this.desiredMedia, operation);
|
|
2494
2548
|
}
|
|
2495
2549
|
dialSdkDebugWarn(DEBUG_MODULE, "DefaultDrivingExpressionPlayer.updatePauseState", "returned", this.getSnapshot());
|
|
2496
2550
|
}
|
|
@@ -2553,7 +2607,7 @@ var DefaultDrivingExpressionPlayer = class {
|
|
|
2553
2607
|
error,
|
|
2554
2608
|
operation
|
|
2555
2609
|
});
|
|
2556
|
-
if (!this.isCurrent(operation) || isAbortError(error)) {
|
|
2610
|
+
if (!this.isCurrent(operation) || isAbortError(error, IS_ABORT_ERROR_DEBUG)) {
|
|
2557
2611
|
dialSdkDebugWarn(DEBUG_MODULE, "DefaultDrivingExpressionPlayer.load", "ignored error");
|
|
2558
2612
|
return;
|
|
2559
2613
|
}
|
|
@@ -2774,19 +2828,37 @@ var DefaultDrivingExpressionPlayer = class {
|
|
|
2774
2828
|
status,
|
|
2775
2829
|
report
|
|
2776
2830
|
});
|
|
2777
|
-
const fallback = this.
|
|
2778
|
-
if (
|
|
2831
|
+
const fallback = this.resolveFallback(status);
|
|
2832
|
+
if (fallback.type !== "static") {
|
|
2779
2833
|
this.container.replaceChildren();
|
|
2780
|
-
dialSdkDebugWarn(DEBUG_MODULE, "DefaultDrivingExpressionPlayer.renderConfiguredFallback", "returned", {
|
|
2834
|
+
dialSdkDebugWarn(DEBUG_MODULE, "DefaultDrivingExpressionPlayer.renderConfiguredFallback", "returned", {
|
|
2835
|
+
result: false,
|
|
2836
|
+
fallbackType: fallback.type
|
|
2837
|
+
});
|
|
2781
2838
|
return false;
|
|
2782
2839
|
}
|
|
2783
|
-
this.renderFallback(status, fallback, report);
|
|
2840
|
+
this.renderFallback(status, fallback.media, report);
|
|
2784
2841
|
dialSdkDebugWarn(DEBUG_MODULE, "DefaultDrivingExpressionPlayer.renderConfiguredFallback", "returned", {
|
|
2785
2842
|
result: true,
|
|
2786
|
-
fallback
|
|
2843
|
+
fallback: fallback.media
|
|
2787
2844
|
});
|
|
2788
2845
|
return true;
|
|
2789
2846
|
}
|
|
2847
|
+
resolveFallback(status) {
|
|
2848
|
+
const fallback = this.fallbacks?.[status];
|
|
2849
|
+
const result = fallback === void 0 ? { type: "missing" } : isStaticFallback(fallback) ? {
|
|
2850
|
+
type: "static",
|
|
2851
|
+
media: fallback
|
|
2852
|
+
} : {
|
|
2853
|
+
type: "unsupported",
|
|
2854
|
+
media: fallback
|
|
2855
|
+
};
|
|
2856
|
+
dialSdkDebugWarn(DEBUG_MODULE, "DefaultDrivingExpressionPlayer.resolveFallback", "returned", {
|
|
2857
|
+
status,
|
|
2858
|
+
result
|
|
2859
|
+
});
|
|
2860
|
+
return result;
|
|
2861
|
+
}
|
|
2790
2862
|
renderFallback(status, fallback, report = true) {
|
|
2791
2863
|
dialSdkDebugWarn(DEBUG_MODULE, "DefaultDrivingExpressionPlayer.renderFallback", "called", {
|
|
2792
2864
|
status,
|
|
@@ -2799,11 +2871,11 @@ var DefaultDrivingExpressionPlayer = class {
|
|
|
2799
2871
|
this.errorCategory = null;
|
|
2800
2872
|
}
|
|
2801
2873
|
if (fallback.kind === "emoji") this.renderEmoji(fallback.text);
|
|
2802
|
-
else
|
|
2874
|
+
else {
|
|
2803
2875
|
const image = this.createImage();
|
|
2804
2876
|
image.src = fallback.url;
|
|
2805
2877
|
this.container.replaceChildren(image);
|
|
2806
|
-
}
|
|
2878
|
+
}
|
|
2807
2879
|
if (report) this.emitDiagnostic({
|
|
2808
2880
|
type: "media_fallback_applied",
|
|
2809
2881
|
status,
|
|
@@ -2852,14 +2924,15 @@ var DefaultDrivingExpressionPlayer = class {
|
|
|
2852
2924
|
});
|
|
2853
2925
|
dialSdkDebugWarn(DEBUG_MODULE, "DefaultDrivingExpressionPlayer.markReady", "returned", this.getSnapshot());
|
|
2854
2926
|
}
|
|
2855
|
-
handleFailure(status, media, error, category, operation, scheduleRetry = true) {
|
|
2927
|
+
handleFailure(status, media, error, category, operation, scheduleRetry = true, applyFallback = true) {
|
|
2856
2928
|
dialSdkDebugWarn(DEBUG_MODULE, "DefaultDrivingExpressionPlayer.handleFailure", "called", {
|
|
2857
2929
|
status,
|
|
2858
2930
|
media,
|
|
2859
2931
|
error,
|
|
2860
2932
|
category,
|
|
2861
2933
|
operation,
|
|
2862
|
-
scheduleRetry
|
|
2934
|
+
scheduleRetry,
|
|
2935
|
+
applyFallback
|
|
2863
2936
|
});
|
|
2864
2937
|
if (!this.isCurrent(operation) || this.failedOperation === operation) {
|
|
2865
2938
|
dialSdkDebugWarn(DEBUG_MODULE, "DefaultDrivingExpressionPlayer.handleFailure", "ignored");
|
|
@@ -2868,6 +2941,7 @@ var DefaultDrivingExpressionPlayer = class {
|
|
|
2868
2941
|
this.failedOperation = operation;
|
|
2869
2942
|
this.stopActiveVideo();
|
|
2870
2943
|
this.phase = "error";
|
|
2944
|
+
if (!applyFallback && media !== null) this.mediaKind = media.kind;
|
|
2871
2945
|
this.errorCategory = category;
|
|
2872
2946
|
this.emitDiagnostic({
|
|
2873
2947
|
type: "media_load_failed",
|
|
@@ -2876,8 +2950,24 @@ var DefaultDrivingExpressionPlayer = class {
|
|
|
2876
2950
|
category,
|
|
2877
2951
|
message: safeErrorMessage(error)
|
|
2878
2952
|
});
|
|
2879
|
-
|
|
2880
|
-
|
|
2953
|
+
let fallbackApplied = false;
|
|
2954
|
+
const fallback = applyFallback ? this.resolveFallback(status) : { type: "missing" };
|
|
2955
|
+
if (fallback.type === "static") {
|
|
2956
|
+
this.renderFallback(status, fallback.media);
|
|
2957
|
+
fallbackApplied = true;
|
|
2958
|
+
} else if (fallback.type === "unsupported") {
|
|
2959
|
+
this.container.replaceChildren();
|
|
2960
|
+
this.phase = "error";
|
|
2961
|
+
this.mediaKind = fallback.media.kind;
|
|
2962
|
+
this.errorCategory = "invalid_config";
|
|
2963
|
+
this.emitDiagnostic({
|
|
2964
|
+
type: "media_load_failed",
|
|
2965
|
+
status,
|
|
2966
|
+
kind: fallback.media.kind,
|
|
2967
|
+
category: "invalid_config",
|
|
2968
|
+
message: safeErrorMessage(unsupportedFallbackError(fallback.media))
|
|
2969
|
+
});
|
|
2970
|
+
} else {
|
|
2881
2971
|
this.phase = "error";
|
|
2882
2972
|
this.errorCategory = category;
|
|
2883
2973
|
}
|
|
@@ -3123,12 +3213,9 @@ var DefaultDrivingExpressionPlayer = class {
|
|
|
3123
3213
|
dialSdkDebugWarn(DEBUG_MODULE, "DefaultDrivingExpressionPlayer.emitDiagnostic", "returned no listener");
|
|
3124
3214
|
return;
|
|
3125
3215
|
}
|
|
3126
|
-
|
|
3127
|
-
this.onDiagnostic(event);
|
|
3128
|
-
dialSdkDebugWarn(DEBUG_MODULE, "DefaultDrivingExpressionPlayer.emitDiagnostic", "returned", { event });
|
|
3129
|
-
} catch (error) {
|
|
3216
|
+
if (invokeSafely(this.onDiagnostic, [event], (error) => {
|
|
3130
3217
|
dialSdkDebugWarn(DEBUG_MODULE, "DefaultDrivingExpressionPlayer.emitDiagnostic", "listener threw", error);
|
|
3131
|
-
}
|
|
3218
|
+
})) dialSdkDebugWarn(DEBUG_MODULE, "DefaultDrivingExpressionPlayer.emitDiagnostic", "returned", { event });
|
|
3132
3219
|
}
|
|
3133
3220
|
};
|
|
3134
3221
|
var MediaPlayerError = class extends Error {
|
|
@@ -3161,6 +3248,8 @@ const normalizeMedia = (media) => {
|
|
|
3161
3248
|
});
|
|
3162
3249
|
return result;
|
|
3163
3250
|
};
|
|
3251
|
+
const isStaticFallback = (media) => media.kind === "emoji" || media.kind === "image";
|
|
3252
|
+
const unsupportedFallbackError = (media) => new MediaPlayerError("invalid_config", `Fallback media kind ${media.kind} is unsupported; use emoji or image`);
|
|
3164
3253
|
const isRetainableImage = (media) => {
|
|
3165
3254
|
if (media.mimeType?.split(";", 1)[0]?.trim().toLowerCase() === "image/gif") return false;
|
|
3166
3255
|
try {
|
|
@@ -3246,7 +3335,7 @@ const waitForElementEvent = (element, successEvent, failureEvent, signal, timeou
|
|
|
3246
3335
|
const handleAbort = () => {
|
|
3247
3336
|
dialSdkDebugWarn(DEBUG_MODULE, "waitForElementEvent.handleAbort", "called");
|
|
3248
3337
|
cleanup();
|
|
3249
|
-
reject(createAbortError());
|
|
3338
|
+
reject(createAbortError("Aborted", CREATE_ABORT_ERROR_DEBUG));
|
|
3250
3339
|
};
|
|
3251
3340
|
element.addEventListener(successEvent, handleSuccess, { once: true });
|
|
3252
3341
|
element.addEventListener(failureEvent, handleFailure, { once: true });
|
|
@@ -3283,7 +3372,7 @@ const withTimeout = (promise, timeoutMs, signal) => {
|
|
|
3283
3372
|
const handleAbort = () => {
|
|
3284
3373
|
dialSdkDebugWarn(DEBUG_MODULE, "withTimeout.handleAbort", "called");
|
|
3285
3374
|
cleanup();
|
|
3286
|
-
reject(createAbortError());
|
|
3375
|
+
reject(createAbortError("Aborted", CREATE_ABORT_ERROR_DEBUG));
|
|
3287
3376
|
};
|
|
3288
3377
|
signal.addEventListener("abort", handleAbort, { once: true });
|
|
3289
3378
|
timer = globalThis.setTimeout(() => {
|
|
@@ -3310,9 +3399,9 @@ const defaultTgsRenderer = async (container, animationData, signal) => {
|
|
|
3310
3399
|
animationData,
|
|
3311
3400
|
signal
|
|
3312
3401
|
});
|
|
3313
|
-
if (signal.aborted) throw createAbortError();
|
|
3402
|
+
if (signal.aborted) throw createAbortError("Aborted", CREATE_ABORT_ERROR_DEBUG);
|
|
3314
3403
|
const module = await import("lottie-web/build/player/lottie_light.js");
|
|
3315
|
-
if (signal.aborted) throw createAbortError();
|
|
3404
|
+
if (signal.aborted) throw createAbortError("Aborted", CREATE_ABORT_ERROR_DEBUG);
|
|
3316
3405
|
const animation = module.default.loadAnimation({
|
|
3317
3406
|
animationData,
|
|
3318
3407
|
autoplay: true,
|
|
@@ -3336,7 +3425,7 @@ const defaultTgsRenderer = async (container, animationData, signal) => {
|
|
|
3336
3425
|
dialSdkDebugWarn(DEBUG_MODULE, "defaultTgsRenderer.aborted", "called");
|
|
3337
3426
|
cleanup();
|
|
3338
3427
|
animation.destroy();
|
|
3339
|
-
reject(createAbortError());
|
|
3428
|
+
reject(createAbortError("Aborted", CREATE_ABORT_ERROR_DEBUG));
|
|
3340
3429
|
};
|
|
3341
3430
|
const cleanup = () => {
|
|
3342
3431
|
dialSdkDebugWarn(DEBUG_MODULE, "defaultTgsRenderer.cleanup", "called");
|
|
@@ -3375,7 +3464,7 @@ function validateTgsAnimation(value, maxLayers) {
|
|
|
3375
3464
|
value,
|
|
3376
3465
|
maxLayers
|
|
3377
3466
|
});
|
|
3378
|
-
if (!isRecord(value) || !Array.isArray(value.layers)) throw new MediaPlayerError("decode", "TGS animation does not contain a layers array");
|
|
3467
|
+
if (!isRecord(value, IS_RECORD_DEBUG) || !Array.isArray(value.layers)) throw new MediaPlayerError("decode", "TGS animation does not contain a layers array");
|
|
3379
3468
|
if (value.layers.length > maxLayers) throw new MediaPlayerError("decode", "TGS animation has too many layers");
|
|
3380
3469
|
if (typeof value.fr === "number" && (!Number.isFinite(value.fr) || value.fr <= 0 || value.fr > 120)) throw new MediaPlayerError("decode", "TGS animation frame rate is outside the supported range");
|
|
3381
3470
|
if (typeof value.ip === "number" && typeof value.op === "number" && (value.op <= value.ip || value.op - value.ip > 3e4)) throw new MediaPlayerError("decode", "TGS animation duration is outside the supported range");
|
|
@@ -3430,11 +3519,7 @@ const resetVideo = (video) => {
|
|
|
3430
3519
|
video.pause();
|
|
3431
3520
|
video.removeAttribute("src");
|
|
3432
3521
|
video.removeAttribute("type");
|
|
3433
|
-
|
|
3434
|
-
video.load();
|
|
3435
|
-
} catch (error) {
|
|
3436
|
-
dialSdkDebugWarn(DEBUG_MODULE, "resetVideo", "load threw", error);
|
|
3437
|
-
}
|
|
3522
|
+
video.load();
|
|
3438
3523
|
dialSdkDebugWarn(DEBUG_MODULE, "resetVideo", "returned", { video });
|
|
3439
3524
|
};
|
|
3440
3525
|
const styleMediaElement = (element, fit) => {
|
|
@@ -3481,39 +3566,6 @@ const redactUrlQueries = (message) => {
|
|
|
3481
3566
|
dialSdkDebugWarn(DEBUG_MODULE, "redactUrlQueries", "returned", { result });
|
|
3482
3567
|
return result;
|
|
3483
3568
|
};
|
|
3484
|
-
const createAbortError = () => {
|
|
3485
|
-
dialSdkDebugWarn(DEBUG_MODULE, "createAbortError", "called");
|
|
3486
|
-
if (typeof DOMException !== "undefined") {
|
|
3487
|
-
const result = new DOMException("Aborted", "AbortError");
|
|
3488
|
-
dialSdkDebugWarn(DEBUG_MODULE, "createAbortError", "returned DOMException", { result });
|
|
3489
|
-
return result;
|
|
3490
|
-
}
|
|
3491
|
-
const error = /* @__PURE__ */ new Error("Aborted");
|
|
3492
|
-
error.name = "AbortError";
|
|
3493
|
-
dialSdkDebugWarn(DEBUG_MODULE, "createAbortError", "returned Error", { result: error });
|
|
3494
|
-
return error;
|
|
3495
|
-
};
|
|
3496
|
-
const isAbortError = (error) => {
|
|
3497
|
-
const result = error instanceof Error && error.name === "AbortError";
|
|
3498
|
-
dialSdkDebugWarn(DEBUG_MODULE, "isAbortError", "returned", {
|
|
3499
|
-
error,
|
|
3500
|
-
result
|
|
3501
|
-
});
|
|
3502
|
-
return result;
|
|
3503
|
-
};
|
|
3504
|
-
const positiveFinite = (name, value) => {
|
|
3505
|
-
dialSdkDebugWarn(DEBUG_MODULE, "positiveFinite", "called", {
|
|
3506
|
-
name,
|
|
3507
|
-
value
|
|
3508
|
-
});
|
|
3509
|
-
if (!Number.isFinite(value) || value <= 0) {
|
|
3510
|
-
const error = /* @__PURE__ */ new RangeError(`${name} must be a positive finite number`);
|
|
3511
|
-
dialSdkDebugWarn(DEBUG_MODULE, "positiveFinite", "threw", error);
|
|
3512
|
-
throw error;
|
|
3513
|
-
}
|
|
3514
|
-
dialSdkDebugWarn(DEBUG_MODULE, "positiveFinite", "returned", { result: value });
|
|
3515
|
-
return value;
|
|
3516
|
-
};
|
|
3517
3569
|
const safeDestroy = (handle) => {
|
|
3518
3570
|
dialSdkDebugWarn(DEBUG_MODULE, "safeDestroy", "called", { handle });
|
|
3519
3571
|
try {
|
|
@@ -3523,13 +3575,5 @@ const safeDestroy = (handle) => {
|
|
|
3523
3575
|
dialSdkDebugWarn(DEBUG_MODULE, "safeDestroy", "destroy threw", error);
|
|
3524
3576
|
}
|
|
3525
3577
|
};
|
|
3526
|
-
const isRecord = (value) => {
|
|
3527
|
-
const result = typeof value === "object" && value !== null && !Array.isArray(value);
|
|
3528
|
-
dialSdkDebugWarn(DEBUG_MODULE, "isRecord", "returned", {
|
|
3529
|
-
value,
|
|
3530
|
-
result
|
|
3531
|
-
});
|
|
3532
|
-
return result;
|
|
3533
|
-
};
|
|
3534
3578
|
//#endregion
|
|
3535
3579
|
export { BATTERY_HEALTH_LABELS, CAR_RUNNING_LABELS, CAR_RUNNING_STATUSES, CAR_RUNNING_STATUS_PRIORITY, DEFAULT_DRIVING_STATUS_TUNING, DrivingExpressionResolutionError, DrivingExpressionsConfigError, OFFICIAL_DRIVING_EXPRESSIONS_CONFIG, OFFICIAL_DRIVING_EXPRESSION_FALLBACKS, buildVehicleFrame, classifyDrivingSnapshot, createDrivingExpressionPlayer, createDrivingStatusController, extractDrivingSnapshotMetrics, isPublicDrivingMediaUrl, parseDrivingExpressionsConfig, readDrivingExpressionsConfig, resolveDrivingExpression, resolveDrivingExpressionStrict, resolveDrivingStatusTuning, tryParseDrivingExpressionsConfig, unifiedSensorInfo, waitForDrivingExpressionsConfig };
|