@ziztechnology/dial-library 0.0.12 → 0.0.14
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 +13 -11
- package/dist/index.d.mts +15 -9
- package/dist/index.mjs +391 -326
- package/package.json +1 -1
package/dist/index.mjs
CHANGED
|
@@ -43,8 +43,108 @@ const dialSdkDebugWarn = (moduleName, scope, phase, data) => {
|
|
|
43
43
|
} catch {}
|
|
44
44
|
};
|
|
45
45
|
//#endregion
|
|
46
|
-
//#region src/sensor/
|
|
47
|
-
const DEBUG_MODULE$5 = "
|
|
46
|
+
//#region src/sensor/unified_info.ts
|
|
47
|
+
const DEBUG_MODULE$5 = "unified_info.ts";
|
|
48
|
+
const unifiedSensorInfo = () => {
|
|
49
|
+
dialSdkDebugWarn(DEBUG_MODULE$5, "unifiedSensorInfo", "called");
|
|
50
|
+
try {
|
|
51
|
+
return window.unifiedSensorInfo().then((payload) => {
|
|
52
|
+
dialSdkDebugWarn(DEBUG_MODULE$5, "unifiedSensorInfo", "resolved", { payload });
|
|
53
|
+
return payload;
|
|
54
|
+
}, (error) => {
|
|
55
|
+
dialSdkDebugWarn(DEBUG_MODULE$5, "unifiedSensorInfo", "rejected", error);
|
|
56
|
+
throw error;
|
|
57
|
+
});
|
|
58
|
+
} catch (error) {
|
|
59
|
+
dialSdkDebugWarn(DEBUG_MODULE$5, "unifiedSensorInfo", "threw", error);
|
|
60
|
+
throw error;
|
|
61
|
+
}
|
|
62
|
+
};
|
|
63
|
+
//#endregion
|
|
64
|
+
//#region src/sensor/constants.ts
|
|
65
|
+
const BATTERY_HEALTH_LABELS = {
|
|
66
|
+
GOOD: "良好",
|
|
67
|
+
OVERHEAT: "过热",
|
|
68
|
+
DEAD: "失效",
|
|
69
|
+
OVER_VOLTAGE: "电压过高",
|
|
70
|
+
UNSPECIFIED_FAILURE: "异常",
|
|
71
|
+
COLD: "温度过低",
|
|
72
|
+
UNKNOWN: "未知"
|
|
73
|
+
};
|
|
74
|
+
//#endregion
|
|
75
|
+
//#region src/driving_expression/constants.ts
|
|
76
|
+
const CAR_RUNNING_LABELS = {
|
|
77
|
+
STOPPED: "静止",
|
|
78
|
+
STEADY_DRIVING: "匀速行驶",
|
|
79
|
+
SUDDEN_BRAKING: "急刹车",
|
|
80
|
+
BRAKING: "刹车",
|
|
81
|
+
LEFT_TURN: "左转",
|
|
82
|
+
RIGHT_TURN: "右转",
|
|
83
|
+
ACCELERATION: "加速",
|
|
84
|
+
RAPID_ACCELERATION: "急加速"
|
|
85
|
+
};
|
|
86
|
+
const CAR_RUNNING_STATUSES = [
|
|
87
|
+
"STOPPED",
|
|
88
|
+
"STEADY_DRIVING",
|
|
89
|
+
"ACCELERATION",
|
|
90
|
+
"RAPID_ACCELERATION",
|
|
91
|
+
"BRAKING",
|
|
92
|
+
"SUDDEN_BRAKING",
|
|
93
|
+
"LEFT_TURN",
|
|
94
|
+
"RIGHT_TURN"
|
|
95
|
+
];
|
|
96
|
+
const CAR_RUNNING_STATUS_PRIORITY = {
|
|
97
|
+
STOPPED: 0,
|
|
98
|
+
STEADY_DRIVING: 0,
|
|
99
|
+
ACCELERATION: 1,
|
|
100
|
+
BRAKING: 2,
|
|
101
|
+
LEFT_TURN: 3,
|
|
102
|
+
RIGHT_TURN: 3,
|
|
103
|
+
RAPID_ACCELERATION: 4,
|
|
104
|
+
SUDDEN_BRAKING: 5
|
|
105
|
+
};
|
|
106
|
+
//#endregion
|
|
107
|
+
//#region src/helper/sensor.ts
|
|
108
|
+
const extractFreshVector = (metric, capturedAtMs, maxSampleAgeMs) => {
|
|
109
|
+
if (!metric?.available || !Number.isFinite(capturedAtMs) || !Number.isFinite(metric.sampledAtMs)) return null;
|
|
110
|
+
const ageMs = capturedAtMs - metric.sampledAtMs;
|
|
111
|
+
if (ageMs < 0 || ageMs > maxSampleAgeMs) return null;
|
|
112
|
+
const { x, y, z } = metric.value;
|
|
113
|
+
return [
|
|
114
|
+
x,
|
|
115
|
+
y,
|
|
116
|
+
z
|
|
117
|
+
].every(Number.isFinite) ? {
|
|
118
|
+
sampledAtMs: metric.sampledAtMs,
|
|
119
|
+
value: metric.value
|
|
120
|
+
} : null;
|
|
121
|
+
};
|
|
122
|
+
//#endregion
|
|
123
|
+
//#region src/helper/validation.ts
|
|
124
|
+
const requirePositiveFinite = (name, value, debug) => {
|
|
125
|
+
dialSdkDebugWarn(debug.moduleName, debug.scope, "called", {
|
|
126
|
+
name,
|
|
127
|
+
value
|
|
128
|
+
});
|
|
129
|
+
if (!Number.isFinite(value) || value <= 0) {
|
|
130
|
+
const error = /* @__PURE__ */ new RangeError(`${name} must be a positive finite number`);
|
|
131
|
+
dialSdkDebugWarn(debug.moduleName, debug.scope, "threw", error);
|
|
132
|
+
throw error;
|
|
133
|
+
}
|
|
134
|
+
dialSdkDebugWarn(debug.moduleName, debug.scope, "returned", { result: value });
|
|
135
|
+
return value;
|
|
136
|
+
};
|
|
137
|
+
const isRecord = (value, debug) => {
|
|
138
|
+
const result = typeof value === "object" && value !== null && !Array.isArray(value);
|
|
139
|
+
if (debug) dialSdkDebugWarn(debug.moduleName, debug.scope, "returned", {
|
|
140
|
+
value,
|
|
141
|
+
result
|
|
142
|
+
});
|
|
143
|
+
return result;
|
|
144
|
+
};
|
|
145
|
+
//#endregion
|
|
146
|
+
//#region src/driving_expression/check_status.ts
|
|
147
|
+
const DEBUG_MODULE$4 = "check_status.ts";
|
|
48
148
|
const DEVICE_RIGHT = {
|
|
49
149
|
x: 1,
|
|
50
150
|
y: 0,
|
|
@@ -56,7 +156,7 @@ const ZERO_VECTOR$1 = {
|
|
|
56
156
|
z: 0
|
|
57
157
|
};
|
|
58
158
|
const DEFAULT_DRIVING_STATUS_TUNING = Object.freeze({
|
|
59
|
-
version: "driving-status-calibrated-2026-07",
|
|
159
|
+
version: "driving-status-calibrated-2026-07-17-r2",
|
|
60
160
|
maxSampleAgeMs: 1e3,
|
|
61
161
|
gravityFilterTimeConstantMs: 1e3,
|
|
62
162
|
biasFilterTimeConstantMs: 1e4,
|
|
@@ -69,7 +169,7 @@ const DEFAULT_DRIVING_STATUS_TUNING = Object.freeze({
|
|
|
69
169
|
stoppedRawGyroThreshold: .065,
|
|
70
170
|
drivingGyroThreshold: .04,
|
|
71
171
|
drivingRawGyroThreshold: .08,
|
|
72
|
-
stoppedConfirmationMs:
|
|
172
|
+
stoppedConfirmationMs: 1500,
|
|
73
173
|
drivingConfirmationMs: 600,
|
|
74
174
|
longitudinalWindowMs: 800,
|
|
75
175
|
longitudinalMinimumSamples: 5,
|
|
@@ -86,9 +186,9 @@ const DEFAULT_DRIVING_STATUS_TUNING = Object.freeze({
|
|
|
86
186
|
verticalBumpRatio: 1.25,
|
|
87
187
|
longitudinalReversalWindowMs: 400,
|
|
88
188
|
turnWindowMs: 1500,
|
|
89
|
-
turnMinimumSamples:
|
|
90
|
-
turnYawThreshold: .
|
|
91
|
-
turnConfirmationMs:
|
|
189
|
+
turnMinimumSamples: 3,
|
|
190
|
+
turnYawThreshold: .08,
|
|
191
|
+
turnConfirmationMs: 400,
|
|
92
192
|
turnIntegratedAngleThreshold: .12,
|
|
93
193
|
turnSignCoherence: .7,
|
|
94
194
|
turnYawDominanceThreshold: .6,
|
|
@@ -100,14 +200,14 @@ const DEFAULT_DRIVING_STATUS_TUNING = Object.freeze({
|
|
|
100
200
|
turnClosureWindowMs: 1500
|
|
101
201
|
});
|
|
102
202
|
const classifyDrivingSnapshot = (info, tuningOverrides) => {
|
|
103
|
-
dialSdkDebugWarn(DEBUG_MODULE$
|
|
203
|
+
dialSdkDebugWarn(DEBUG_MODULE$4, "classifyDrivingSnapshot", "called", {
|
|
104
204
|
info,
|
|
105
205
|
tuningOverrides
|
|
106
206
|
});
|
|
107
207
|
const tuning = resolveDrivingStatusTuning(tuningOverrides);
|
|
108
208
|
const metrics = extractDrivingSnapshotMetrics(info, tuning);
|
|
109
209
|
if (metrics === null) {
|
|
110
|
-
dialSdkDebugWarn(DEBUG_MODULE$
|
|
210
|
+
dialSdkDebugWarn(DEBUG_MODULE$4, "classifyDrivingSnapshot", "returned", { result: null });
|
|
111
211
|
return null;
|
|
112
212
|
}
|
|
113
213
|
const { candidateStatus, rejectionReason } = classifyInstantaneousEvidence(metrics, tuning);
|
|
@@ -121,11 +221,11 @@ const classifyDrivingSnapshot = (info, tuningOverrides) => {
|
|
|
121
221
|
maximumSampleAgeMs: Math.max(info.capturedAtMs - metrics.linearAccelerationSampledAtMs, info.capturedAtMs - metrics.gyroscopeSampledAtMs, info.capturedAtMs - metrics.gravitySampledAtMs)
|
|
122
222
|
}
|
|
123
223
|
};
|
|
124
|
-
dialSdkDebugWarn(DEBUG_MODULE$
|
|
224
|
+
dialSdkDebugWarn(DEBUG_MODULE$4, "classifyDrivingSnapshot", "returned", { result });
|
|
125
225
|
return result;
|
|
126
226
|
};
|
|
127
227
|
const resolveDrivingStatusTuning = (overrides = {}) => {
|
|
128
|
-
dialSdkDebugWarn(DEBUG_MODULE$
|
|
228
|
+
dialSdkDebugWarn(DEBUG_MODULE$4, "resolveDrivingStatusTuning", "called", { overrides });
|
|
129
229
|
const tuning = {
|
|
130
230
|
...DEFAULT_DRIVING_STATUS_TUNING,
|
|
131
231
|
...overrides
|
|
@@ -164,7 +264,10 @@ const resolveDrivingStatusTuning = (overrides = {}) => {
|
|
|
164
264
|
"turnExitYawThreshold",
|
|
165
265
|
"turnExitConfirmationMs",
|
|
166
266
|
"turnClosureWindowMs"
|
|
167
|
-
])
|
|
267
|
+
]) requirePositiveFinite(field, tuning[field], {
|
|
268
|
+
moduleName: DEBUG_MODULE$4,
|
|
269
|
+
scope: "assertPositiveFinite"
|
|
270
|
+
});
|
|
168
271
|
for (const field of [
|
|
169
272
|
"motionMinimumSamples",
|
|
170
273
|
"longitudinalMinimumSamples",
|
|
@@ -187,28 +290,28 @@ const resolveDrivingStatusTuning = (overrides = {}) => {
|
|
|
187
290
|
if (tuning.rapidLongitudinalMeanThreshold <= tuning.longitudinalThreshold) throwLoggedRangeError("resolveDrivingStatusTuning", "rapidLongitudinalMeanThreshold must be greater than longitudinalThreshold");
|
|
188
291
|
if (tuning.rapidLongitudinalPeakThreshold < tuning.rapidLongitudinalMeanThreshold) throwLoggedRangeError("resolveDrivingStatusTuning", "rapidLongitudinalPeakThreshold must be greater than or equal to rapidLongitudinalMeanThreshold");
|
|
189
292
|
if (tuning.turnYawThreshold <= tuning.turnExitYawThreshold) throwLoggedRangeError("resolveDrivingStatusTuning", "turnYawThreshold must be greater than turnExitYawThreshold");
|
|
190
|
-
dialSdkDebugWarn(DEBUG_MODULE$
|
|
293
|
+
dialSdkDebugWarn(DEBUG_MODULE$4, "resolveDrivingStatusTuning", "returned", { tuning });
|
|
191
294
|
return tuning;
|
|
192
295
|
};
|
|
193
296
|
const extractDrivingSnapshotMetrics = (info, tuning = DEFAULT_DRIVING_STATUS_TUNING, correction = {}) => {
|
|
194
|
-
dialSdkDebugWarn(DEBUG_MODULE$
|
|
297
|
+
dialSdkDebugWarn(DEBUG_MODULE$4, "extractDrivingSnapshotMetrics", "called", {
|
|
195
298
|
info,
|
|
196
299
|
tuning,
|
|
197
300
|
correction
|
|
198
301
|
});
|
|
199
302
|
if (!info || !Number.isFinite(info.capturedAtMs)) {
|
|
200
|
-
dialSdkDebugWarn(DEBUG_MODULE$
|
|
303
|
+
dialSdkDebugWarn(DEBUG_MODULE$4, "extractDrivingSnapshotMetrics", "returned invalid capture time", { info });
|
|
201
304
|
return null;
|
|
202
305
|
}
|
|
203
|
-
const linearAcceleration =
|
|
204
|
-
const gyroscope =
|
|
205
|
-
const gravityMetric =
|
|
306
|
+
const linearAcceleration = extractFreshVector(info.linearAcceleration, info.capturedAtMs, tuning.maxSampleAgeMs);
|
|
307
|
+
const gyroscope = extractFreshVector(info.gyroscope, info.capturedAtMs, tuning.maxSampleAgeMs);
|
|
308
|
+
const gravityMetric = extractFreshVector(info.gravity, info.capturedAtMs, tuning.maxSampleAgeMs);
|
|
206
309
|
const gravity = availableCorrectedGravity(correction, info.capturedAtMs, tuning.maxSampleAgeMs) ?? (correction.filteredGravity !== void 0 && gravityMetric !== null ? {
|
|
207
310
|
value: correction.filteredGravity,
|
|
208
311
|
sampledAtMs: gravityMetric.sampledAtMs
|
|
209
312
|
} : gravityMetric);
|
|
210
313
|
if (linearAcceleration === null || gyroscope === null || gravity === null) {
|
|
211
|
-
dialSdkDebugWarn(DEBUG_MODULE$
|
|
314
|
+
dialSdkDebugWarn(DEBUG_MODULE$4, "extractDrivingSnapshotMetrics", "returned unavailable vectors", {
|
|
212
315
|
linearAcceleration,
|
|
213
316
|
gyroscope,
|
|
214
317
|
gravity
|
|
@@ -217,7 +320,7 @@ const extractDrivingSnapshotMetrics = (info, tuning = DEFAULT_DRIVING_STATUS_TUN
|
|
|
217
320
|
}
|
|
218
321
|
const frame = buildVehicleFrame(gravity.value, tuning.vehicleRightMinimumNorm);
|
|
219
322
|
if (frame === null) {
|
|
220
|
-
dialSdkDebugWarn(DEBUG_MODULE$
|
|
323
|
+
dialSdkDebugWarn(DEBUG_MODULE$4, "extractDrivingSnapshotMetrics", "returned invalid vehicle frame", {
|
|
221
324
|
gravity: gravity.value,
|
|
222
325
|
vehicleRightMinimumNorm: tuning.vehicleRightMinimumNorm
|
|
223
326
|
});
|
|
@@ -240,28 +343,28 @@ const extractDrivingSnapshotMetrics = (info, tuning = DEFAULT_DRIVING_STATUS_TUN
|
|
|
240
343
|
rawGyroscope: gyroscope.value,
|
|
241
344
|
frame
|
|
242
345
|
};
|
|
243
|
-
dialSdkDebugWarn(DEBUG_MODULE$
|
|
346
|
+
dialSdkDebugWarn(DEBUG_MODULE$4, "extractDrivingSnapshotMetrics", "returned", { result });
|
|
244
347
|
return result;
|
|
245
348
|
};
|
|
246
349
|
const buildVehicleFrame = (gravity, rightMinimumNorm = DEFAULT_DRIVING_STATUS_TUNING.vehicleRightMinimumNorm) => {
|
|
247
|
-
dialSdkDebugWarn(DEBUG_MODULE$
|
|
350
|
+
dialSdkDebugWarn(DEBUG_MODULE$4, "buildVehicleFrame", "called", {
|
|
248
351
|
gravity,
|
|
249
352
|
rightMinimumNorm
|
|
250
353
|
});
|
|
251
354
|
const gravityDirection = normalize(gravity);
|
|
252
355
|
if (gravityDirection === null) {
|
|
253
|
-
dialSdkDebugWarn(DEBUG_MODULE$
|
|
356
|
+
dialSdkDebugWarn(DEBUG_MODULE$4, "buildVehicleFrame", "returned invalid gravity", { result: null });
|
|
254
357
|
return null;
|
|
255
358
|
}
|
|
256
359
|
const up = gravityDirection;
|
|
257
360
|
const projectedRight = subtract(DEVICE_RIGHT, scale(up, dot(DEVICE_RIGHT, up)));
|
|
258
361
|
if (magnitude(projectedRight) < rightMinimumNorm) {
|
|
259
|
-
dialSdkDebugWarn(DEBUG_MODULE$
|
|
362
|
+
dialSdkDebugWarn(DEBUG_MODULE$4, "buildVehicleFrame", "returned degenerate right axis", { result: null });
|
|
260
363
|
return null;
|
|
261
364
|
}
|
|
262
365
|
const right = normalize(projectedRight);
|
|
263
366
|
if (right === null) {
|
|
264
|
-
dialSdkDebugWarn(DEBUG_MODULE$
|
|
367
|
+
dialSdkDebugWarn(DEBUG_MODULE$4, "buildVehicleFrame", "returned invalid right axis", { result: null });
|
|
265
368
|
return null;
|
|
266
369
|
}
|
|
267
370
|
const forward = normalize(cross(right, up));
|
|
@@ -270,7 +373,7 @@ const buildVehicleFrame = (gravity, rightMinimumNorm = DEFAULT_DRIVING_STATUS_TU
|
|
|
270
373
|
right,
|
|
271
374
|
forward
|
|
272
375
|
};
|
|
273
|
-
dialSdkDebugWarn(DEBUG_MODULE$
|
|
376
|
+
dialSdkDebugWarn(DEBUG_MODULE$4, "buildVehicleFrame", "returned", { result });
|
|
274
377
|
return result;
|
|
275
378
|
};
|
|
276
379
|
const classifyInstantaneousEvidence = (metrics, tuning) => {
|
|
@@ -298,18 +401,6 @@ const classifyInstantaneousEvidence = (metrics, tuning) => {
|
|
|
298
401
|
rejectionReason: null
|
|
299
402
|
};
|
|
300
403
|
};
|
|
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
404
|
const availableCorrectedGravity = (correction, capturedAtMs, maxSampleAgeMs) => {
|
|
314
405
|
const { filteredGravity, filteredGravitySampledAtMs } = correction;
|
|
315
406
|
if (filteredGravity === void 0 || filteredGravitySampledAtMs === void 0 || !isFresh(filteredGravitySampledAtMs, capturedAtMs, maxSampleAgeMs)) return null;
|
|
@@ -349,80 +440,57 @@ const normalize = (value) => {
|
|
|
349
440
|
const length = magnitude(value);
|
|
350
441
|
return Number.isFinite(length) && length > Number.EPSILON ? scale(value, 1 / length) : null;
|
|
351
442
|
};
|
|
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
443
|
const throwLoggedRangeError = (scope, message) => {
|
|
360
444
|
const error = new RangeError(message);
|
|
361
|
-
dialSdkDebugWarn(DEBUG_MODULE$
|
|
445
|
+
dialSdkDebugWarn(DEBUG_MODULE$4, scope, "threw", error);
|
|
362
446
|
throw error;
|
|
363
447
|
};
|
|
364
448
|
//#endregion
|
|
365
|
-
//#region src/
|
|
366
|
-
const
|
|
367
|
-
|
|
368
|
-
|
|
449
|
+
//#region src/helper/async.ts
|
|
450
|
+
const createAbortError = (message, debug) => {
|
|
451
|
+
dialSdkDebugWarn(debug.moduleName, debug.scope, "called");
|
|
452
|
+
if (typeof DOMException === "function") {
|
|
453
|
+
const result = new DOMException(message, "AbortError");
|
|
454
|
+
dialSdkDebugWarn(debug.moduleName, debug.scope, "returned DOMException", { result });
|
|
455
|
+
return result;
|
|
456
|
+
}
|
|
457
|
+
const error = new Error(message);
|
|
458
|
+
error.name = "AbortError";
|
|
459
|
+
dialSdkDebugWarn(debug.moduleName, debug.scope, "returned Error", { result: error });
|
|
460
|
+
return error;
|
|
461
|
+
};
|
|
462
|
+
const isAbortError = (error, debug) => {
|
|
463
|
+
const result = error instanceof Error && error.name === "AbortError";
|
|
464
|
+
if (debug) dialSdkDebugWarn(debug.moduleName, debug.scope, "returned", {
|
|
465
|
+
error,
|
|
466
|
+
result
|
|
467
|
+
});
|
|
468
|
+
return result;
|
|
469
|
+
};
|
|
470
|
+
const invokeSafely = (callback, args, onError) => {
|
|
369
471
|
try {
|
|
370
|
-
|
|
371
|
-
|
|
372
|
-
return payload;
|
|
373
|
-
}, (error) => {
|
|
374
|
-
dialSdkDebugWarn(DEBUG_MODULE$4, "unifiedSensorInfo", "rejected", error);
|
|
375
|
-
throw error;
|
|
376
|
-
});
|
|
472
|
+
callback(...args);
|
|
473
|
+
return true;
|
|
377
474
|
} catch (error) {
|
|
378
|
-
|
|
379
|
-
|
|
475
|
+
onError(error);
|
|
476
|
+
return false;
|
|
380
477
|
}
|
|
381
478
|
};
|
|
382
479
|
//#endregion
|
|
383
|
-
//#region src/
|
|
384
|
-
const
|
|
385
|
-
|
|
386
|
-
|
|
387
|
-
|
|
388
|
-
OVER_VOLTAGE: "电压过高",
|
|
389
|
-
UNSPECIFIED_FAILURE: "异常",
|
|
390
|
-
COLD: "温度过低",
|
|
391
|
-
UNKNOWN: "未知"
|
|
480
|
+
//#region src/driving_expression/driving_expressions.ts
|
|
481
|
+
const DEBUG_MODULE$3 = "driving_expressions.ts";
|
|
482
|
+
const IS_RECORD_DEBUG$1 = {
|
|
483
|
+
moduleName: DEBUG_MODULE$3,
|
|
484
|
+
scope: "isRecord"
|
|
392
485
|
};
|
|
393
|
-
const
|
|
394
|
-
|
|
395
|
-
|
|
396
|
-
SUDDEN_BRAKING: "急刹车",
|
|
397
|
-
BRAKING: "刹车",
|
|
398
|
-
LEFT_TURN: "左转",
|
|
399
|
-
RIGHT_TURN: "右转",
|
|
400
|
-
ACCELERATION: "加速",
|
|
401
|
-
RAPID_ACCELERATION: "急加速"
|
|
486
|
+
const REQUIRE_POSITIVE_FINITE_DEBUG$1 = {
|
|
487
|
+
moduleName: DEBUG_MODULE$3,
|
|
488
|
+
scope: "requirePositiveFinite"
|
|
402
489
|
};
|
|
403
|
-
const
|
|
404
|
-
|
|
405
|
-
"
|
|
406
|
-
"ACCELERATION",
|
|
407
|
-
"RAPID_ACCELERATION",
|
|
408
|
-
"BRAKING",
|
|
409
|
-
"SUDDEN_BRAKING",
|
|
410
|
-
"LEFT_TURN",
|
|
411
|
-
"RIGHT_TURN"
|
|
412
|
-
];
|
|
413
|
-
const CAR_RUNNING_STATUS_PRIORITY = {
|
|
414
|
-
STOPPED: 0,
|
|
415
|
-
STEADY_DRIVING: 0,
|
|
416
|
-
ACCELERATION: 1,
|
|
417
|
-
BRAKING: 2,
|
|
418
|
-
LEFT_TURN: 3,
|
|
419
|
-
RIGHT_TURN: 3,
|
|
420
|
-
RAPID_ACCELERATION: 4,
|
|
421
|
-
SUDDEN_BRAKING: 5
|
|
490
|
+
const CREATE_ABORT_ERROR_DEBUG$1 = {
|
|
491
|
+
moduleName: DEBUG_MODULE$3,
|
|
492
|
+
scope: "createAbortError"
|
|
422
493
|
};
|
|
423
|
-
//#endregion
|
|
424
|
-
//#region src/sensor/driving_expressions.ts
|
|
425
|
-
const DEBUG_MODULE$3 = "driving_expressions.ts";
|
|
426
494
|
const OFFICIAL_DRIVING_EXPRESSION_FALLBACKS = Object.freeze({
|
|
427
495
|
STOPPED: Object.freeze({
|
|
428
496
|
kind: "emoji",
|
|
@@ -490,7 +558,7 @@ const parseDrivingExpressionsConfig = (raw, options = {}) => {
|
|
|
490
558
|
options
|
|
491
559
|
});
|
|
492
560
|
const parsed = parseJsonObject(raw);
|
|
493
|
-
if (parsed.schemaVersion !== 1 || !isRecord
|
|
561
|
+
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
562
|
const knownStatuses = new Set(CAR_RUNNING_STATUSES);
|
|
495
563
|
const stateKeys = Object.keys(parsed.states);
|
|
496
564
|
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,12 +584,16 @@ const tryParseDrivingExpressionsConfig = (raw, options) => {
|
|
|
516
584
|
dialSdkDebugWarn(DEBUG_MODULE$3, "tryParseDrivingExpressionsConfig", "returned", { result });
|
|
517
585
|
return result;
|
|
518
586
|
} catch (error) {
|
|
587
|
+
if (!(error instanceof DrivingExpressionsConfigError)) {
|
|
588
|
+
dialSdkDebugWarn(DEBUG_MODULE$3, "tryParseDrivingExpressionsConfig", "threw unexpected error", error);
|
|
589
|
+
throw error;
|
|
590
|
+
}
|
|
519
591
|
dialSdkDebugWarn(DEBUG_MODULE$3, "tryParseDrivingExpressionsConfig", "returned null after parse error", error);
|
|
520
592
|
return null;
|
|
521
593
|
}
|
|
522
594
|
};
|
|
523
595
|
/**
|
|
524
|
-
* Reads Runtime's typed
|
|
596
|
+
* Reads Runtime's typed driving-expressions injection.
|
|
525
597
|
* It never installs official fallbacks implicitly.
|
|
526
598
|
*/
|
|
527
599
|
const readDrivingExpressionsConfig = (raw, options) => {
|
|
@@ -544,7 +616,7 @@ const readDrivingExpressionsConfig = (raw, options) => {
|
|
|
544
616
|
const waitForDrivingExpressionsConfig = (options = {}) => {
|
|
545
617
|
dialSdkDebugWarn(DEBUG_MODULE$3, "waitForDrivingExpressionsConfig", "called", { options });
|
|
546
618
|
const timeoutMs = requireNonNegativeFinite("timeoutMs", options.timeoutMs ?? 3e3);
|
|
547
|
-
const pollIntervalMs = requirePositiveFinite
|
|
619
|
+
const pollIntervalMs = requirePositiveFinite("pollIntervalMs", options.pollIntervalMs ?? 100, REQUIRE_POSITIVE_FINITE_DEBUG$1);
|
|
548
620
|
const { signal } = options;
|
|
549
621
|
return new Promise((resolve, reject) => {
|
|
550
622
|
const deadlineMs = Date.now() + timeoutMs;
|
|
@@ -592,7 +664,7 @@ const waitForDrivingExpressionsConfig = (options = {}) => {
|
|
|
592
664
|
};
|
|
593
665
|
const handleAbort = () => {
|
|
594
666
|
dialSdkDebugWarn(DEBUG_MODULE$3, "waitForDrivingExpressionsConfig.handleAbort", "called");
|
|
595
|
-
fail(createAbortError$1
|
|
667
|
+
fail(createAbortError("The operation was aborted", CREATE_ABORT_ERROR_DEBUG$1));
|
|
596
668
|
};
|
|
597
669
|
const read = () => {
|
|
598
670
|
dialSdkDebugWarn(DEBUG_MODULE$3, "waitForDrivingExpressionsConfig.read", "called");
|
|
@@ -610,7 +682,13 @@ const waitForDrivingExpressionsConfig = (options = {}) => {
|
|
|
610
682
|
handleAbort();
|
|
611
683
|
return;
|
|
612
684
|
}
|
|
613
|
-
|
|
685
|
+
let config;
|
|
686
|
+
try {
|
|
687
|
+
config = read();
|
|
688
|
+
} catch (error) {
|
|
689
|
+
fail(error);
|
|
690
|
+
return;
|
|
691
|
+
}
|
|
614
692
|
if (config !== null) {
|
|
615
693
|
finish(config);
|
|
616
694
|
return;
|
|
@@ -905,7 +983,7 @@ const parseDrivingExpressionMedia = (raw, status, options) => {
|
|
|
905
983
|
dialSdkDebugWarn(DEBUG_MODULE$3, "parseDrivingExpressionMedia", "returned legacy image", { result });
|
|
906
984
|
return result;
|
|
907
985
|
}
|
|
908
|
-
if (!isRecord$1
|
|
986
|
+
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
987
|
const mediaAssetId = parseMediaAssetId(raw.mediaAssetId, status);
|
|
910
988
|
assertFieldsAbsent(raw, status, [
|
|
911
989
|
"items",
|
|
@@ -1011,7 +1089,7 @@ const parseJsonObject = (raw) => {
|
|
|
1011
1089
|
});
|
|
1012
1090
|
throw error;
|
|
1013
1091
|
}
|
|
1014
|
-
if (!isRecord$1
|
|
1092
|
+
if (!isRecord(value, IS_RECORD_DEBUG$1)) {
|
|
1015
1093
|
const error = new DrivingExpressionsConfigError("DRIVING_EXPRESSIONS_INVALID_SCHEMA", "drivingExpressions must be a JSON object or JSON object string");
|
|
1016
1094
|
dialSdkDebugWarn(DEBUG_MODULE$3, "parseJsonObject", "threw", error);
|
|
1017
1095
|
throw error;
|
|
@@ -1021,24 +1099,8 @@ const parseJsonObject = (raw) => {
|
|
|
1021
1099
|
};
|
|
1022
1100
|
const readRuntimeDrivingExpressionsValue = () => {
|
|
1023
1101
|
dialSdkDebugWarn(DEBUG_MODULE$3, "readRuntimeDrivingExpressionsValue", "called");
|
|
1024
|
-
const
|
|
1025
|
-
|
|
1026
|
-
const result = runtimeGlobal.__TOOOONY_DRIVING_EXPRESSIONS__;
|
|
1027
|
-
dialSdkDebugWarn(DEBUG_MODULE$3, "readRuntimeDrivingExpressionsValue", "returned typed injection", { result });
|
|
1028
|
-
return result;
|
|
1029
|
-
}
|
|
1030
|
-
const faceConfig = runtimeGlobal.__TOOOONY_FACE_CONFIG__;
|
|
1031
|
-
if (!isRecord$1(faceConfig)) {
|
|
1032
|
-
dialSdkDebugWarn(DEBUG_MODULE$3, "readRuntimeDrivingExpressionsValue", "returned", { result: void 0 });
|
|
1033
|
-
return;
|
|
1034
|
-
}
|
|
1035
|
-
if (faceConfig.drivingExpressions !== void 0) {
|
|
1036
|
-
const result = faceConfig.drivingExpressions;
|
|
1037
|
-
dialSdkDebugWarn(DEBUG_MODULE$3, "readRuntimeDrivingExpressionsValue", "returned face config", { result });
|
|
1038
|
-
return result;
|
|
1039
|
-
}
|
|
1040
|
-
const result = isRecord$1(faceConfig.values) ? faceConfig.values.drivingExpressions : void 0;
|
|
1041
|
-
dialSdkDebugWarn(DEBUG_MODULE$3, "readRuntimeDrivingExpressionsValue", "returned legacy face config", { result });
|
|
1102
|
+
const result = globalThis.__TOOOONY_DRIVING_EXPRESSIONS__;
|
|
1103
|
+
dialSdkDebugWarn(DEBUG_MODULE$3, "readRuntimeDrivingExpressionsValue", "returned typed injection", { result });
|
|
1042
1104
|
return result;
|
|
1043
1105
|
};
|
|
1044
1106
|
const parseMediaAssetId = (raw, status) => {
|
|
@@ -1159,14 +1221,6 @@ const compact = (value) => {
|
|
|
1159
1221
|
dialSdkDebugWarn(DEBUG_MODULE$3, "compact", "returned", { result: value });
|
|
1160
1222
|
return value;
|
|
1161
1223
|
};
|
|
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
1224
|
const requireNonNegativeFinite = (name, value) => {
|
|
1171
1225
|
dialSdkDebugWarn(DEBUG_MODULE$3, "requireNonNegativeFinite", "called", {
|
|
1172
1226
|
name,
|
|
@@ -1180,33 +1234,8 @@ const requireNonNegativeFinite = (name, value) => {
|
|
|
1180
1234
|
dialSdkDebugWarn(DEBUG_MODULE$3, "requireNonNegativeFinite", "returned", { result: value });
|
|
1181
1235
|
return value;
|
|
1182
1236
|
};
|
|
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
1237
|
//#endregion
|
|
1209
|
-
//#region src/
|
|
1238
|
+
//#region src/driving_expression/page_lifecycle.ts
|
|
1210
1239
|
const DEBUG_MODULE$2 = "page_lifecycle.ts";
|
|
1211
1240
|
const subscribers = /* @__PURE__ */ new Set();
|
|
1212
1241
|
let installedWindow = null;
|
|
@@ -1339,21 +1368,22 @@ const dispatchResume = () => {
|
|
|
1339
1368
|
};
|
|
1340
1369
|
const safeInvoke = (callback) => {
|
|
1341
1370
|
dialSdkDebugWarn(DEBUG_MODULE$2, "safeInvoke", "called");
|
|
1342
|
-
|
|
1343
|
-
callback();
|
|
1344
|
-
dialSdkDebugWarn(DEBUG_MODULE$2, "safeInvoke", "returned");
|
|
1345
|
-
} catch (error) {
|
|
1371
|
+
if (invokeSafely(callback, [], (error) => {
|
|
1346
1372
|
dialSdkDebugWarn(DEBUG_MODULE$2, "safeInvoke", "callback threw", error);
|
|
1347
|
-
}
|
|
1373
|
+
})) dialSdkDebugWarn(DEBUG_MODULE$2, "safeInvoke", "returned");
|
|
1348
1374
|
};
|
|
1349
1375
|
//#endregion
|
|
1350
|
-
//#region src/
|
|
1376
|
+
//#region src/driving_expression/driving_status_controller.ts
|
|
1351
1377
|
const DEBUG_MODULE$1 = "driving_status_controller.ts";
|
|
1352
1378
|
const ZERO_VECTOR = {
|
|
1353
1379
|
x: 0,
|
|
1354
1380
|
y: 0,
|
|
1355
1381
|
z: 0
|
|
1356
1382
|
};
|
|
1383
|
+
const REQUIRE_POSITIVE_FINITE_DEBUG = {
|
|
1384
|
+
moduleName: DEBUG_MODULE$1,
|
|
1385
|
+
scope: "requirePositiveFinite"
|
|
1386
|
+
};
|
|
1357
1387
|
const createDrivingStatusController = (options = {}) => {
|
|
1358
1388
|
dialSdkDebugWarn(DEBUG_MODULE$1, "createDrivingStatusController", "called", { options });
|
|
1359
1389
|
const result = new DefaultDrivingStatusController(options);
|
|
@@ -1437,9 +1467,9 @@ var DefaultDrivingStatusController = class {
|
|
|
1437
1467
|
dialSdkDebugWarn(DEBUG_MODULE$1, "DefaultDrivingStatusController.handleLifecycleResume", "returned");
|
|
1438
1468
|
};
|
|
1439
1469
|
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);
|
|
1470
|
+
this.sensorProvider = options.sensorProvider ?? unifiedSensorInfo;
|
|
1471
|
+
this.pollIntervalMs = requirePositiveFinite("pollIntervalMs", options.pollIntervalMs ?? 200, REQUIRE_POSITIVE_FINITE_DEBUG);
|
|
1472
|
+
this.unavailableFallbackMs = requirePositiveFinite("unavailableFallbackMs", options.unavailableFallbackMs ?? 3e3, REQUIRE_POSITIVE_FINITE_DEBUG);
|
|
1443
1473
|
this.tuning = resolveDrivingStatusTuning(options.tuning);
|
|
1444
1474
|
this.clock = options.clock ?? systemClock;
|
|
1445
1475
|
this.onDiagnostic = options.onDiagnostic;
|
|
@@ -1580,6 +1610,7 @@ var DefaultDrivingStatusController = class {
|
|
|
1580
1610
|
}, delayMs);
|
|
1581
1611
|
}
|
|
1582
1612
|
async poll(generation) {
|
|
1613
|
+
const pollStartedAtMs = this.clock.now();
|
|
1583
1614
|
dialSdkDebugWarn(DEBUG_MODULE$1, "DefaultDrivingStatusController.poll", "called", { generation });
|
|
1584
1615
|
if (!this.polling || generation !== this.generation || this.pendingRead !== null) {
|
|
1585
1616
|
dialSdkDebugWarn(DEBUG_MODULE$1, "DefaultDrivingStatusController.poll", "ignored", {
|
|
@@ -1610,7 +1641,7 @@ var DefaultDrivingStatusController = class {
|
|
|
1610
1641
|
linearAccelerationBias: this.linearAccelerationBias,
|
|
1611
1642
|
gyroscopeBias: this.gyroscopeBias
|
|
1612
1643
|
});
|
|
1613
|
-
const accelerometerSample =
|
|
1644
|
+
const accelerometerSample = extractFreshVector(payload.accelerometer, payload.capturedAtMs, this.tuning.maxSampleAgeMs);
|
|
1614
1645
|
if (gravity === null || metrics === null || accelerometerSample === null) {
|
|
1615
1646
|
dialSdkDebugWarn(DEBUG_MODULE$1, "DefaultDrivingStatusController.poll", "invalid or stale snapshot", {
|
|
1616
1647
|
metrics,
|
|
@@ -1622,7 +1653,7 @@ var DefaultDrivingStatusController = class {
|
|
|
1622
1653
|
dialSdkDebugWarn(DEBUG_MODULE$1, "DefaultDrivingStatusController.poll", "processed sample", { capturedAtMs: metrics.capturedAtMs });
|
|
1623
1654
|
}
|
|
1624
1655
|
} catch (error) {
|
|
1625
|
-
if (!this.polling || generation !== this.generation || pendingRead.signal.aborted || isAbortError
|
|
1656
|
+
if (!this.polling || generation !== this.generation || pendingRead.signal.aborted || isAbortError(error)) {
|
|
1626
1657
|
dialSdkDebugWarn(DEBUG_MODULE$1, "DefaultDrivingStatusController.poll", "ignored provider error", { error });
|
|
1627
1658
|
return;
|
|
1628
1659
|
}
|
|
@@ -1630,7 +1661,10 @@ var DefaultDrivingStatusController = class {
|
|
|
1630
1661
|
this.processUnavailable("provider_error");
|
|
1631
1662
|
} finally {
|
|
1632
1663
|
if (this.pendingRead === pendingRead) this.pendingRead = null;
|
|
1633
|
-
if (this.polling && generation === this.generation)
|
|
1664
|
+
if (this.polling && generation === this.generation) {
|
|
1665
|
+
const elapsedMs = Math.max(0, this.clock.now() - pollStartedAtMs);
|
|
1666
|
+
this.schedulePoll(Math.max(0, this.pollIntervalMs - elapsedMs), generation);
|
|
1667
|
+
}
|
|
1634
1668
|
dialSdkDebugWarn(DEBUG_MODULE$1, "DefaultDrivingStatusController.poll", "completed", {
|
|
1635
1669
|
generation,
|
|
1636
1670
|
polling: this.polling
|
|
@@ -1638,7 +1672,7 @@ var DefaultDrivingStatusController = class {
|
|
|
1638
1672
|
}
|
|
1639
1673
|
}
|
|
1640
1674
|
resolveGravityFrame(info) {
|
|
1641
|
-
const sample =
|
|
1675
|
+
const sample = extractFreshVector(info.gravity, info.capturedAtMs, this.tuning.maxSampleAgeMs);
|
|
1642
1676
|
if (sample === null) {
|
|
1643
1677
|
if (this.filteredGravity === null || this.lastGravitySampledAtMs === null) return null;
|
|
1644
1678
|
const ageMs = info.capturedAtMs - this.lastGravitySampledAtMs;
|
|
@@ -1691,19 +1725,23 @@ var DefaultDrivingStatusController = class {
|
|
|
1691
1725
|
frameAgeMs: metrics.capturedAtMs - gravity.sampledAtMs,
|
|
1692
1726
|
tuningVersion: this.tuning.version
|
|
1693
1727
|
});
|
|
1694
|
-
const
|
|
1695
|
-
const
|
|
1696
|
-
const
|
|
1728
|
+
const longitudinalRetentionMs = Math.max(recognitionRetentionMs(this.tuning.longitudinalWindowMs, this.tuning.longitudinalMinimumSamples), recognitionRetentionMs(this.tuning.rapidLongitudinalWindowMs, this.tuning.rapidLongitudinalMinimumSamples));
|
|
1729
|
+
const addedLongitudinal = pushUniqueMetric(this.longitudinalWindow, metrics, "linearAccelerationSampledAtMs", longitudinalRetentionMs);
|
|
1730
|
+
const yawRetentionMs = Math.max(this.tuning.turnWindowMs, this.tuning.turnClosureWindowMs, recognitionRetentionMs(this.tuning.turnConfirmationMs, this.tuning.turnMinimumSamples));
|
|
1731
|
+
const addedYaw = pushUniqueMetric(this.yawWindow, metrics, "gyroscopeSampledAtMs", yawRetentionMs);
|
|
1732
|
+
const addedMotion = pushUniqueVector(this.motionWindow, accelerometerSample, recognitionRetentionMs(this.tuning.motionWindowMs, this.tuning.motionMinimumSamples));
|
|
1697
1733
|
if (!addedLongitudinal && !addedYaw && !addedMotion) {
|
|
1698
1734
|
dialSdkDebugWarn(DEBUG_MODULE$1, "DefaultDrivingStatusController.processAvailable", "ignored duplicate sample");
|
|
1699
1735
|
return;
|
|
1700
1736
|
}
|
|
1701
|
-
const
|
|
1737
|
+
const motionCoverageWindow = selectCoverageWindow(this.motionWindow, this.tuning.motionMinimumSamples, this.tuning.motionWindowMs, (sample) => sample.sampledAtMs);
|
|
1738
|
+
const motionStatisticsWindow = motionCoverageWindow ?? recentVectors(this.motionWindow, this.tuning.motionWindowMs);
|
|
1739
|
+
const motionMad = motionCoverageWindow === null ? null : calculateCombinedAxisMad(motionCoverageWindow, minimumTemporalSamples(this.tuning.motionMinimumSamples));
|
|
1702
1740
|
const previousBaseStatus = this.baseStatus;
|
|
1703
1741
|
const previousUrgentStatus = this.urgentStatus;
|
|
1704
1742
|
const previousLongitudinalStatus = this.normalLongitudinalStatus;
|
|
1705
1743
|
const previousTurnStatus = this.turnStatus;
|
|
1706
|
-
const baseCondition = this.updateBaseDetector(motionMad, metrics, accelerometerSample.sampledAtMs, addedMotion);
|
|
1744
|
+
const baseCondition = this.updateBaseDetector(motionMad, metrics, accelerometerSample.sampledAtMs, addedMotion, motionCoverageWindow?.[0]?.sampledAtMs ?? accelerometerSample.sampledAtMs);
|
|
1707
1745
|
const longitudinalEvidence = detectLongitudinalEvidence(this.longitudinalWindow, this.tuning);
|
|
1708
1746
|
if (addedLongitudinal) this.updateLongitudinalDetector(longitudinalEvidence, metrics.linearAccelerationSampledAtMs);
|
|
1709
1747
|
const turnEvidence = detectTurnEvidence(this.yawWindow, this.tuning);
|
|
@@ -1716,8 +1754,8 @@ var DefaultDrivingStatusController = class {
|
|
|
1716
1754
|
if (this.stationaryConfirmed) this.updateBias(metrics);
|
|
1717
1755
|
const statistics = {
|
|
1718
1756
|
base: {
|
|
1719
|
-
sampleCount:
|
|
1720
|
-
durationMs: vectorWindowDuration(
|
|
1757
|
+
sampleCount: motionStatisticsWindow.length,
|
|
1758
|
+
durationMs: vectorWindowDuration(motionStatisticsWindow),
|
|
1721
1759
|
motionMad,
|
|
1722
1760
|
gyroMagnitude: metrics.gyroMagnitude,
|
|
1723
1761
|
rawGyroMagnitude: metrics.rawGyroMagnitude
|
|
@@ -1763,7 +1801,7 @@ var DefaultDrivingStatusController = class {
|
|
|
1763
1801
|
normalLongitudinalStatus: this.normalLongitudinalStatus
|
|
1764
1802
|
});
|
|
1765
1803
|
}
|
|
1766
|
-
updateBaseDetector(motionMad, metrics, sampledAtMs, isNewMotionSample) {
|
|
1804
|
+
updateBaseDetector(motionMad, metrics, sampledAtMs, isNewMotionSample, conditionStartedAtMs) {
|
|
1767
1805
|
if (motionMad === null || !isNewMotionSample) return "warming_up";
|
|
1768
1806
|
const gyroForStop = this.biasCalibrated ? metrics.gyroMagnitude : metrics.rawGyroMagnitude;
|
|
1769
1807
|
const stoppedGyroThreshold = this.biasCalibrated ? this.tuning.stoppedGyroThreshold : this.tuning.stoppedRawGyroThreshold;
|
|
@@ -1772,7 +1810,7 @@ var DefaultDrivingStatusController = class {
|
|
|
1772
1810
|
const moving = motionMad >= this.tuning.drivingMotionThreshold || gyroForStop >= drivingGyroThreshold;
|
|
1773
1811
|
if (stationary) {
|
|
1774
1812
|
this.drivingConditionSinceMs = null;
|
|
1775
|
-
if (this.stoppedConditionSinceMs === null) this.stoppedConditionSinceMs =
|
|
1813
|
+
if (this.stoppedConditionSinceMs === null) this.stoppedConditionSinceMs = conditionStartedAtMs;
|
|
1776
1814
|
if (sampledAtMs - this.stoppedConditionSinceMs >= this.tuning.stoppedConfirmationMs) {
|
|
1777
1815
|
this.baseStatus = "STOPPED";
|
|
1778
1816
|
this.stationaryConfirmed = true;
|
|
@@ -1782,7 +1820,7 @@ var DefaultDrivingStatusController = class {
|
|
|
1782
1820
|
this.stoppedConditionSinceMs = null;
|
|
1783
1821
|
this.stationaryConfirmed = false;
|
|
1784
1822
|
if (moving) {
|
|
1785
|
-
if (this.drivingConditionSinceMs === null) this.drivingConditionSinceMs =
|
|
1823
|
+
if (this.drivingConditionSinceMs === null) this.drivingConditionSinceMs = sampledAtMs;
|
|
1786
1824
|
if (sampledAtMs - this.drivingConditionSinceMs >= this.tuning.drivingConfirmationMs) this.baseStatus = "STEADY_DRIVING";
|
|
1787
1825
|
return "moving";
|
|
1788
1826
|
}
|
|
@@ -1882,7 +1920,15 @@ var DefaultDrivingStatusController = class {
|
|
|
1882
1920
|
});
|
|
1883
1921
|
}
|
|
1884
1922
|
commitSelectedStatus(now) {
|
|
1885
|
-
const selected =
|
|
1923
|
+
const selected = [
|
|
1924
|
+
this.baseStatus,
|
|
1925
|
+
this.normalLongitudinalStatus,
|
|
1926
|
+
this.turnStatus,
|
|
1927
|
+
this.urgentStatus
|
|
1928
|
+
].reduce((highest, candidate) => {
|
|
1929
|
+
if (candidate === null) return highest;
|
|
1930
|
+
return CAR_RUNNING_STATUS_PRIORITY[candidate] > CAR_RUNNING_STATUS_PRIORITY[highest] ? candidate : highest;
|
|
1931
|
+
}, this.baseStatus);
|
|
1886
1932
|
this.commit(selected, now, "candidate_confirmed");
|
|
1887
1933
|
}
|
|
1888
1934
|
processUnavailable(category) {
|
|
@@ -1890,7 +1936,6 @@ var DefaultDrivingStatusController = class {
|
|
|
1890
1936
|
const now = this.clock.now();
|
|
1891
1937
|
if (this.unavailableSinceMs === null) this.unavailableSinceMs = now;
|
|
1892
1938
|
const unavailableForMs = Math.max(0, now - this.unavailableSinceMs);
|
|
1893
|
-
this.clearRecognitionWindows();
|
|
1894
1939
|
this.setCandidate(null, now);
|
|
1895
1940
|
this.emitDiagnostic({
|
|
1896
1941
|
type: "sample_unavailable",
|
|
@@ -1908,6 +1953,7 @@ var DefaultDrivingStatusController = class {
|
|
|
1908
1953
|
return;
|
|
1909
1954
|
}
|
|
1910
1955
|
this.fallbackApplied = true;
|
|
1956
|
+
this.clearRecognitionWindows();
|
|
1911
1957
|
this.baseStatus = "STOPPED";
|
|
1912
1958
|
this.emitDiagnostic({
|
|
1913
1959
|
type: "fallback_to_stopped",
|
|
@@ -1940,7 +1986,12 @@ var DefaultDrivingStatusController = class {
|
|
|
1940
1986
|
reason,
|
|
1941
1987
|
atMs: now
|
|
1942
1988
|
};
|
|
1943
|
-
for (const listener of [...this.listeners])
|
|
1989
|
+
for (const listener of [...this.listeners]) invokeSafely(listener, [event], (error) => {
|
|
1990
|
+
dialSdkDebugWarn(DEBUG_MODULE$1, "safeCall", "callback threw", {
|
|
1991
|
+
error,
|
|
1992
|
+
value: event
|
|
1993
|
+
});
|
|
1994
|
+
});
|
|
1944
1995
|
this.emitDiagnostic({
|
|
1945
1996
|
type: "status_committed",
|
|
1946
1997
|
atMs: now,
|
|
@@ -2002,7 +2053,12 @@ var DefaultDrivingStatusController = class {
|
|
|
2002
2053
|
event,
|
|
2003
2054
|
hasListener: this.onDiagnostic !== void 0
|
|
2004
2055
|
});
|
|
2005
|
-
if (this.onDiagnostic)
|
|
2056
|
+
if (this.onDiagnostic) invokeSafely(this.onDiagnostic, [event], (error) => {
|
|
2057
|
+
dialSdkDebugWarn(DEBUG_MODULE$1, "safeCall", "callback threw", {
|
|
2058
|
+
error,
|
|
2059
|
+
value: event
|
|
2060
|
+
});
|
|
2061
|
+
});
|
|
2006
2062
|
}
|
|
2007
2063
|
attachLifecycleListeners() {
|
|
2008
2064
|
if (!this.managePageLifecycle || this.unsubscribePageLifecycle !== null) return;
|
|
@@ -2014,8 +2070,12 @@ var DefaultDrivingStatusController = class {
|
|
|
2014
2070
|
}
|
|
2015
2071
|
};
|
|
2016
2072
|
const detectLongitudinalEvidence = (window, tuning) => {
|
|
2017
|
-
const
|
|
2018
|
-
const
|
|
2073
|
+
const recentRapidWindow = recentMetrics(window, tuning.rapidLongitudinalWindowMs, "linearAccelerationSampledAtMs");
|
|
2074
|
+
const rapidCoverageWindow = selectCoverageWindow(window, tuning.rapidLongitudinalMinimumSamples, tuning.rapidLongitudinalWindowMs, (sample) => sample.linearAccelerationSampledAtMs);
|
|
2075
|
+
const rapidWindow = rapidCoverageWindow ?? recentRapidWindow;
|
|
2076
|
+
const recentNormalWindow = recentMetrics(window, tuning.longitudinalWindowMs, "linearAccelerationSampledAtMs");
|
|
2077
|
+
const normalCoverageWindow = selectCoverageWindow(window, tuning.longitudinalMinimumSamples, tuning.longitudinalWindowMs, (sample) => sample.linearAccelerationSampledAtMs);
|
|
2078
|
+
const normalWindow = normalCoverageWindow ?? recentNormalWindow;
|
|
2019
2079
|
let rapidCandidate = null;
|
|
2020
2080
|
let rejectionReason = null;
|
|
2021
2081
|
const rapidValues = rapidWindow.map((sample) => sample.longitudinal);
|
|
@@ -2037,7 +2097,7 @@ const detectLongitudinalEvidence = (window, tuning) => {
|
|
|
2037
2097
|
verticalRms,
|
|
2038
2098
|
hasReversal
|
|
2039
2099
|
};
|
|
2040
|
-
if (
|
|
2100
|
+
if (rapidCoverageWindow !== null) {
|
|
2041
2101
|
if (rapidPeak >= tuning.rapidLongitudinalPeakThreshold && Math.abs(rapidMean) >= tuning.rapidLongitudinalMeanThreshold) {
|
|
2042
2102
|
if (verticalRms > longitudinalRms * tuning.verticalBumpRatio) rejectionReason = "vertical_bump";
|
|
2043
2103
|
else if (hasReversal) rejectionReason = "longitudinal_reversal";
|
|
@@ -2059,8 +2119,9 @@ const detectLongitudinalEvidence = (window, tuning) => {
|
|
|
2059
2119
|
peak: maximumAbsolute(values),
|
|
2060
2120
|
coherence
|
|
2061
2121
|
};
|
|
2062
|
-
|
|
2063
|
-
|
|
2122
|
+
const retentionValues = recentNormalWindow.map((sample) => sample.longitudinal);
|
|
2123
|
+
retainedNormal = Math.abs(trimmedMean(retentionValues)) >= tuning.longitudinalExitThreshold;
|
|
2124
|
+
if (normalCoverageWindow !== null && Math.abs(mean) >= tuning.longitudinalThreshold && coherence >= tuning.longitudinalSignCoherence) normalCandidate = direction > 0 ? "ACCELERATION" : "BRAKING";
|
|
2064
2125
|
}
|
|
2065
2126
|
return {
|
|
2066
2127
|
rapidCandidate,
|
|
@@ -2072,7 +2133,8 @@ const detectLongitudinalEvidence = (window, tuning) => {
|
|
|
2072
2133
|
};
|
|
2073
2134
|
};
|
|
2074
2135
|
const detectTurnEvidence = (window, tuning) => {
|
|
2075
|
-
const
|
|
2136
|
+
const turnWindow = recentMetrics(window, tuning.turnWindowMs, "gyroscopeSampledAtMs");
|
|
2137
|
+
const latest = turnWindow[turnWindow.length - 1];
|
|
2076
2138
|
if (!latest) return {
|
|
2077
2139
|
candidate: null,
|
|
2078
2140
|
latestYaw: 0,
|
|
@@ -2080,20 +2142,22 @@ const detectTurnEvidence = (window, tuning) => {
|
|
|
2080
2142
|
rejectionReason: null,
|
|
2081
2143
|
statistics: null
|
|
2082
2144
|
};
|
|
2083
|
-
const
|
|
2145
|
+
const recentStrongWindow = recentMetrics(turnWindow, tuning.turnConfirmationMs, "gyroscopeSampledAtMs");
|
|
2146
|
+
const strongCoverageWindow = selectCoverageWindow(window, tuning.turnMinimumSamples, tuning.turnConfirmationMs, (sample) => sample.gyroscopeSampledAtMs);
|
|
2147
|
+
const strongWindow = strongCoverageWindow ?? recentStrongWindow;
|
|
2084
2148
|
const strongMean = trimmedMean(strongWindow.map((sample) => sample.yaw));
|
|
2085
2149
|
const strongDirection = Math.sign(strongMean);
|
|
2086
2150
|
const strongCoherence = signCoherence(strongWindow.map((sample) => sample.yaw), strongDirection, tuning.turnExitYawThreshold);
|
|
2087
|
-
const strong =
|
|
2088
|
-
const signedAngle = integrateYaw(
|
|
2151
|
+
const strong = strongCoverageWindow !== null && Math.abs(strongMean) >= tuning.turnYawThreshold && strongCoherence >= tuning.turnSignCoherence;
|
|
2152
|
+
const signedAngle = integrateYaw(turnWindow);
|
|
2089
2153
|
const gentleDirection = Math.sign(signedAngle);
|
|
2090
|
-
const gentleCoherence = signCoherence(
|
|
2091
|
-
const yawRms = rootMeanSquare(
|
|
2092
|
-
const rawGyroRms = rootMeanSquare(
|
|
2154
|
+
const gentleCoherence = signCoherence(turnWindow.map((sample) => sample.yaw), gentleDirection, tuning.turnExitYawThreshold);
|
|
2155
|
+
const yawRms = rootMeanSquare(turnWindow.map((sample) => sample.yaw));
|
|
2156
|
+
const rawGyroRms = rootMeanSquare(turnWindow.map((sample) => sample.rawGyroMagnitude));
|
|
2093
2157
|
const yawDominance = rawGyroRms <= Number.EPSILON ? 0 : Math.min(1, yawRms / rawGyroRms);
|
|
2094
|
-
const lateralRms = rootMeanSquare(
|
|
2095
|
-
const verticalRms = rootMeanSquare(
|
|
2096
|
-
const gentleShape =
|
|
2158
|
+
const lateralRms = rootMeanSquare(turnWindow.map((sample) => sample.lateral));
|
|
2159
|
+
const verticalRms = rootMeanSquare(turnWindow.map((sample) => sample.vertical));
|
|
2160
|
+
const gentleShape = turnWindow.length >= tuning.turnMinimumSamples && Math.abs(signedAngle) >= tuning.turnIntegratedAngleThreshold && gentleCoherence >= tuning.turnSignCoherence;
|
|
2097
2161
|
const verticalDominant = verticalRms > Math.max(lateralRms, tuning.turnVerticalNoiseFloor) * tuning.turnVerticalBumpRatio;
|
|
2098
2162
|
const yawDominant = yawDominance >= tuning.turnYawDominanceThreshold;
|
|
2099
2163
|
const laterallySupported = lateralRms >= tuning.turnLateralEvidenceThreshold;
|
|
@@ -2105,8 +2169,8 @@ const detectTurnEvidence = (window, tuning) => {
|
|
|
2105
2169
|
sampledAtMs: latest.gyroscopeSampledAtMs,
|
|
2106
2170
|
rejectionReason,
|
|
2107
2171
|
statistics: {
|
|
2108
|
-
sampleCount:
|
|
2109
|
-
durationMs: metricWindowDuration(
|
|
2172
|
+
sampleCount: turnWindow.length,
|
|
2173
|
+
durationMs: metricWindowDuration(turnWindow, "gyroscopeSampledAtMs"),
|
|
2110
2174
|
strongMean,
|
|
2111
2175
|
strongCoherence,
|
|
2112
2176
|
signedAngle,
|
|
@@ -2130,10 +2194,29 @@ const recentMetrics = (values, windowMs, timestampKey) => {
|
|
|
2130
2194
|
const latestAtMs = values[values.length - 1]?.[timestampKey] ?? 0;
|
|
2131
2195
|
return values.filter((value) => value[timestampKey] >= latestAtMs - windowMs);
|
|
2132
2196
|
};
|
|
2133
|
-
const
|
|
2134
|
-
|
|
2135
|
-
|
|
2136
|
-
|
|
2197
|
+
const MINIMUM_TEMPORAL_SAMPLES = 3;
|
|
2198
|
+
const MAXIMUM_RECOGNITION_GAP_MS = 1e3;
|
|
2199
|
+
const minimumTemporalSamples = (minimumSamples) => Math.min(minimumSamples, MINIMUM_TEMPORAL_SAMPLES);
|
|
2200
|
+
const maximumRecognitionGapMs = (minimumSamples, durationMs) => {
|
|
2201
|
+
const nominalSampleIntervalMs = durationMs / Math.max(1, minimumSamples - 1);
|
|
2202
|
+
return Math.max(MAXIMUM_RECOGNITION_GAP_MS, nominalSampleIntervalMs * 2.5);
|
|
2203
|
+
};
|
|
2204
|
+
const recognitionRetentionMs = (durationMs, minimumSamples) => Math.max(durationMs, maximumRecognitionGapMs(minimumSamples, durationMs) * Math.max(1, minimumTemporalSamples(minimumSamples) - 1));
|
|
2205
|
+
const selectCoverageWindow = (values, minimumSamples, durationMs, timestampOf) => {
|
|
2206
|
+
const requiredSamples = minimumTemporalSamples(minimumSamples);
|
|
2207
|
+
if (values.length < requiredSamples) return null;
|
|
2208
|
+
const lastAtMs = timestampOf(values[values.length - 1]);
|
|
2209
|
+
const maximumGapMs = maximumRecognitionGapMs(minimumSamples, durationMs);
|
|
2210
|
+
for (let startIndex = values.length - requiredSamples; startIndex >= 0; startIndex -= 1) {
|
|
2211
|
+
const coveredValues = values.slice(startIndex);
|
|
2212
|
+
if (lastAtMs - timestampOf(coveredValues[0]) < durationMs) continue;
|
|
2213
|
+
if (coveredValues.slice(1).every((value, index) => timestampOf(value) - timestampOf(coveredValues[index]) < maximumGapMs)) return coveredValues;
|
|
2214
|
+
}
|
|
2215
|
+
return null;
|
|
2216
|
+
};
|
|
2217
|
+
const recentVectors = (values, windowMs) => {
|
|
2218
|
+
const latestAtMs = values[values.length - 1]?.sampledAtMs ?? 0;
|
|
2219
|
+
return values.filter((value) => value.sampledAtMs >= latestAtMs - windowMs);
|
|
2137
2220
|
};
|
|
2138
2221
|
const integrateYaw = (values) => {
|
|
2139
2222
|
let angle = 0;
|
|
@@ -2187,7 +2270,6 @@ const median = (values) => {
|
|
|
2187
2270
|
const pushUniqueMetric = (window, metrics, timestampKey, windowMs) => {
|
|
2188
2271
|
const latest = window[window.length - 1];
|
|
2189
2272
|
if (latest && metrics[timestampKey] <= latest[timestampKey]) return false;
|
|
2190
|
-
if (window.some((value) => value[timestampKey] === metrics[timestampKey])) return false;
|
|
2191
2273
|
window.push(metrics);
|
|
2192
2274
|
const cutoffMs = metrics[timestampKey] - windowMs;
|
|
2193
2275
|
while (window[0] && window[0][timestampKey] < cutoffMs) window.shift();
|
|
@@ -2196,67 +2278,44 @@ const pushUniqueMetric = (window, metrics, timestampKey, windowMs) => {
|
|
|
2196
2278
|
const pushUniqueVector = (window, sample, windowMs) => {
|
|
2197
2279
|
const latest = window[window.length - 1];
|
|
2198
2280
|
if (latest && sample.sampledAtMs <= latest.sampledAtMs) return false;
|
|
2199
|
-
if (window.some((value) => value.sampledAtMs === sample.sampledAtMs)) return false;
|
|
2200
2281
|
window.push(sample);
|
|
2201
2282
|
const cutoffMs = sample.sampledAtMs - windowMs;
|
|
2202
2283
|
while (window[0] && window[0].sampledAtMs < cutoffMs) window.shift();
|
|
2203
2284
|
return true;
|
|
2204
2285
|
};
|
|
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
2286
|
const observationTime = (metrics) => Math.max(metrics.linearAccelerationSampledAtMs, metrics.gyroscopeSampledAtMs);
|
|
2220
2287
|
const lerpVector = (from, to, alpha) => ({
|
|
2221
2288
|
x: from.x + (to.x - from.x) * alpha,
|
|
2222
2289
|
y: from.y + (to.y - from.y) * alpha,
|
|
2223
2290
|
z: from.z + (to.z - from.z) * alpha
|
|
2224
2291
|
});
|
|
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
2292
|
const systemClock = {
|
|
2231
2293
|
now: () => Date.now(),
|
|
2232
2294
|
setTimeout: (callback, delayMs) => globalThis.setTimeout(callback, delayMs),
|
|
2233
2295
|
clearTimeout: (handle) => globalThis.clearTimeout(handle)
|
|
2234
2296
|
};
|
|
2235
2297
|
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
2298
|
const noop = () => void 0;
|
|
2256
2299
|
//#endregion
|
|
2257
|
-
//#region src/
|
|
2300
|
+
//#region src/driving_expression/driving_expression_player.ts
|
|
2258
2301
|
const DEBUG_MODULE = "driving_expression_player.ts";
|
|
2259
2302
|
const MAX_RETAINED_IMAGES = 3;
|
|
2303
|
+
const POSITIVE_FINITE_DEBUG = {
|
|
2304
|
+
moduleName: DEBUG_MODULE,
|
|
2305
|
+
scope: "positiveFinite"
|
|
2306
|
+
};
|
|
2307
|
+
const CREATE_ABORT_ERROR_DEBUG = {
|
|
2308
|
+
moduleName: DEBUG_MODULE,
|
|
2309
|
+
scope: "createAbortError"
|
|
2310
|
+
};
|
|
2311
|
+
const IS_ABORT_ERROR_DEBUG = {
|
|
2312
|
+
moduleName: DEBUG_MODULE,
|
|
2313
|
+
scope: "isAbortError"
|
|
2314
|
+
};
|
|
2315
|
+
const IS_RECORD_DEBUG = {
|
|
2316
|
+
moduleName: DEBUG_MODULE,
|
|
2317
|
+
scope: "isRecord"
|
|
2318
|
+
};
|
|
2260
2319
|
const createDrivingExpressionPlayer = (container, options) => {
|
|
2261
2320
|
dialSdkDebugWarn(DEBUG_MODULE, "createDrivingExpressionPlayer", "called", {
|
|
2262
2321
|
container,
|
|
@@ -2273,6 +2332,7 @@ var DefaultDrivingExpressionPlayer = class {
|
|
|
2273
2332
|
this.mediaKind = null;
|
|
2274
2333
|
this.errorCategory = null;
|
|
2275
2334
|
this.desiredMedia = null;
|
|
2335
|
+
this.desiredMediaRole = null;
|
|
2276
2336
|
this.userPaused = false;
|
|
2277
2337
|
this.lifecycleSuspended = false;
|
|
2278
2338
|
this.paused = false;
|
|
@@ -2321,15 +2381,15 @@ var DefaultDrivingExpressionPlayer = class {
|
|
|
2321
2381
|
this.document = container.ownerDocument;
|
|
2322
2382
|
this.config = options.config;
|
|
2323
2383
|
this.fallbacks = options.fallbacks;
|
|
2324
|
-
this.loadTimeoutMs =
|
|
2325
|
-
this.retryBackoffMs =
|
|
2384
|
+
this.loadTimeoutMs = requirePositiveFinite("loadTimeoutMs", options.loadTimeoutMs ?? 5e3, POSITIVE_FINITE_DEBUG);
|
|
2385
|
+
this.retryBackoffMs = requirePositiveFinite("retryBackoffMs", options.retryBackoffMs ?? 15e3, POSITIVE_FINITE_DEBUG);
|
|
2326
2386
|
this.fit = options.fit ?? "contain";
|
|
2327
2387
|
this.tgsRenderer = defaultTgsRenderer;
|
|
2328
2388
|
this.fetchImplementation = options.fetch ?? globalThis.fetch?.bind(globalThis);
|
|
2329
2389
|
this.onDiagnostic = options.onDiagnostic;
|
|
2330
|
-
this.maxTgsCompressedBytes =
|
|
2331
|
-
this.maxTgsJsonBytes =
|
|
2332
|
-
this.maxTgsLayers =
|
|
2390
|
+
this.maxTgsCompressedBytes = requirePositiveFinite("maxTgsCompressedBytes", options.maxTgsCompressedBytes ?? 2 * 1024 * 1024, POSITIVE_FINITE_DEBUG);
|
|
2391
|
+
this.maxTgsJsonBytes = requirePositiveFinite("maxTgsJsonBytes", options.maxTgsJsonBytes ?? 8 * 1024 * 1024, POSITIVE_FINITE_DEBUG);
|
|
2392
|
+
this.maxTgsLayers = requirePositiveFinite("maxTgsLayers", options.maxTgsLayers ?? 500, POSITIVE_FINITE_DEBUG);
|
|
2333
2393
|
if (options.managePageLifecycle ?? true) this.unsubscribePageLifecycle = subscribeDrivingPageLifecycle(this.handleLifecyclePause, this.handleLifecycleResume);
|
|
2334
2394
|
dialSdkDebugWarn(DEBUG_MODULE, "DefaultDrivingExpressionPlayer.constructor", "created", {
|
|
2335
2395
|
loadTimeoutMs: this.loadTimeoutMs,
|
|
@@ -2354,24 +2414,33 @@ var DefaultDrivingExpressionPlayer = class {
|
|
|
2354
2414
|
const operation = this.beginOperation();
|
|
2355
2415
|
const configured = this.config.states[status];
|
|
2356
2416
|
if (configured === void 0) {
|
|
2357
|
-
const fallback = this.
|
|
2358
|
-
if (fallback ===
|
|
2417
|
+
const fallback = this.resolveFallback(status);
|
|
2418
|
+
if (fallback.type === "missing") {
|
|
2419
|
+
this.desiredMedia = null;
|
|
2420
|
+
this.desiredMediaRole = null;
|
|
2359
2421
|
this.handleFailure(status, null, new DrivingExpressionResolutionError(status), "invalid_config", operation, false);
|
|
2360
2422
|
dialSdkDebugWarn(DEBUG_MODULE, "DefaultDrivingExpressionPlayer.show", "returned after missing config");
|
|
2361
2423
|
return;
|
|
2362
2424
|
}
|
|
2363
|
-
this.desiredMedia = fallback;
|
|
2425
|
+
this.desiredMedia = fallback.media;
|
|
2426
|
+
this.desiredMediaRole = "fallback";
|
|
2364
2427
|
if (this.paused) {
|
|
2365
2428
|
this.phase = "idle";
|
|
2366
2429
|
dialSdkDebugWarn(DEBUG_MODULE, "DefaultDrivingExpressionPlayer.show", "deferred fallback while paused");
|
|
2367
2430
|
return;
|
|
2368
2431
|
}
|
|
2369
|
-
|
|
2432
|
+
if (fallback.type === "unsupported") {
|
|
2433
|
+
this.handleFailure(status, fallback.media, unsupportedFallbackError(fallback.media), "invalid_config", operation, false, false);
|
|
2434
|
+
dialSdkDebugWarn(DEBUG_MODULE, "DefaultDrivingExpressionPlayer.show", "returned unsupported fallback");
|
|
2435
|
+
return;
|
|
2436
|
+
}
|
|
2437
|
+
this.renderFallback(status, fallback.media);
|
|
2370
2438
|
dialSdkDebugWarn(DEBUG_MODULE, "DefaultDrivingExpressionPlayer.show", "returned fallback", { snapshot: this.getSnapshot() });
|
|
2371
2439
|
return;
|
|
2372
2440
|
}
|
|
2373
2441
|
const media = normalizeMedia(configured);
|
|
2374
2442
|
this.desiredMedia = media;
|
|
2443
|
+
this.desiredMediaRole = "primary";
|
|
2375
2444
|
if (this.paused) {
|
|
2376
2445
|
this.phase = "idle";
|
|
2377
2446
|
dialSdkDebugWarn(DEBUG_MODULE, "DefaultDrivingExpressionPlayer.show", "deferred media while paused", { media });
|
|
@@ -2422,6 +2491,7 @@ var DefaultDrivingExpressionPlayer = class {
|
|
|
2422
2491
|
this.container.replaceChildren();
|
|
2423
2492
|
this.status = null;
|
|
2424
2493
|
this.desiredMedia = null;
|
|
2494
|
+
this.desiredMediaRole = null;
|
|
2425
2495
|
this.phase = "idle";
|
|
2426
2496
|
this.mediaKind = null;
|
|
2427
2497
|
this.errorCategory = null;
|
|
@@ -2490,7 +2560,12 @@ var DefaultDrivingExpressionPlayer = class {
|
|
|
2490
2560
|
}
|
|
2491
2561
|
if (this.status !== null && this.desiredMedia !== null) {
|
|
2492
2562
|
const operation = this.beginOperation();
|
|
2493
|
-
|
|
2563
|
+
if (this.desiredMediaRole === "fallback") {
|
|
2564
|
+
const status = this.status;
|
|
2565
|
+
const fallback = this.desiredMedia;
|
|
2566
|
+
if (isStaticFallback(fallback)) this.renderFallback(status, fallback);
|
|
2567
|
+
else this.handleFailure(status, fallback, unsupportedFallbackError(fallback), "invalid_config", operation, false, false);
|
|
2568
|
+
} else this.load(this.status, this.desiredMedia, operation);
|
|
2494
2569
|
}
|
|
2495
2570
|
dialSdkDebugWarn(DEBUG_MODULE, "DefaultDrivingExpressionPlayer.updatePauseState", "returned", this.getSnapshot());
|
|
2496
2571
|
}
|
|
@@ -2553,7 +2628,7 @@ var DefaultDrivingExpressionPlayer = class {
|
|
|
2553
2628
|
error,
|
|
2554
2629
|
operation
|
|
2555
2630
|
});
|
|
2556
|
-
if (!this.isCurrent(operation) || isAbortError(error)) {
|
|
2631
|
+
if (!this.isCurrent(operation) || isAbortError(error, IS_ABORT_ERROR_DEBUG)) {
|
|
2557
2632
|
dialSdkDebugWarn(DEBUG_MODULE, "DefaultDrivingExpressionPlayer.load", "ignored error");
|
|
2558
2633
|
return;
|
|
2559
2634
|
}
|
|
@@ -2774,19 +2849,37 @@ var DefaultDrivingExpressionPlayer = class {
|
|
|
2774
2849
|
status,
|
|
2775
2850
|
report
|
|
2776
2851
|
});
|
|
2777
|
-
const fallback = this.
|
|
2778
|
-
if (
|
|
2852
|
+
const fallback = this.resolveFallback(status);
|
|
2853
|
+
if (fallback.type !== "static") {
|
|
2779
2854
|
this.container.replaceChildren();
|
|
2780
|
-
dialSdkDebugWarn(DEBUG_MODULE, "DefaultDrivingExpressionPlayer.renderConfiguredFallback", "returned", {
|
|
2855
|
+
dialSdkDebugWarn(DEBUG_MODULE, "DefaultDrivingExpressionPlayer.renderConfiguredFallback", "returned", {
|
|
2856
|
+
result: false,
|
|
2857
|
+
fallbackType: fallback.type
|
|
2858
|
+
});
|
|
2781
2859
|
return false;
|
|
2782
2860
|
}
|
|
2783
|
-
this.renderFallback(status, fallback, report);
|
|
2861
|
+
this.renderFallback(status, fallback.media, report);
|
|
2784
2862
|
dialSdkDebugWarn(DEBUG_MODULE, "DefaultDrivingExpressionPlayer.renderConfiguredFallback", "returned", {
|
|
2785
2863
|
result: true,
|
|
2786
|
-
fallback
|
|
2864
|
+
fallback: fallback.media
|
|
2787
2865
|
});
|
|
2788
2866
|
return true;
|
|
2789
2867
|
}
|
|
2868
|
+
resolveFallback(status) {
|
|
2869
|
+
const fallback = this.fallbacks?.[status];
|
|
2870
|
+
const result = fallback === void 0 ? { type: "missing" } : isStaticFallback(fallback) ? {
|
|
2871
|
+
type: "static",
|
|
2872
|
+
media: fallback
|
|
2873
|
+
} : {
|
|
2874
|
+
type: "unsupported",
|
|
2875
|
+
media: fallback
|
|
2876
|
+
};
|
|
2877
|
+
dialSdkDebugWarn(DEBUG_MODULE, "DefaultDrivingExpressionPlayer.resolveFallback", "returned", {
|
|
2878
|
+
status,
|
|
2879
|
+
result
|
|
2880
|
+
});
|
|
2881
|
+
return result;
|
|
2882
|
+
}
|
|
2790
2883
|
renderFallback(status, fallback, report = true) {
|
|
2791
2884
|
dialSdkDebugWarn(DEBUG_MODULE, "DefaultDrivingExpressionPlayer.renderFallback", "called", {
|
|
2792
2885
|
status,
|
|
@@ -2799,11 +2892,11 @@ var DefaultDrivingExpressionPlayer = class {
|
|
|
2799
2892
|
this.errorCategory = null;
|
|
2800
2893
|
}
|
|
2801
2894
|
if (fallback.kind === "emoji") this.renderEmoji(fallback.text);
|
|
2802
|
-
else
|
|
2895
|
+
else {
|
|
2803
2896
|
const image = this.createImage();
|
|
2804
2897
|
image.src = fallback.url;
|
|
2805
2898
|
this.container.replaceChildren(image);
|
|
2806
|
-
}
|
|
2899
|
+
}
|
|
2807
2900
|
if (report) this.emitDiagnostic({
|
|
2808
2901
|
type: "media_fallback_applied",
|
|
2809
2902
|
status,
|
|
@@ -2852,14 +2945,15 @@ var DefaultDrivingExpressionPlayer = class {
|
|
|
2852
2945
|
});
|
|
2853
2946
|
dialSdkDebugWarn(DEBUG_MODULE, "DefaultDrivingExpressionPlayer.markReady", "returned", this.getSnapshot());
|
|
2854
2947
|
}
|
|
2855
|
-
handleFailure(status, media, error, category, operation, scheduleRetry = true) {
|
|
2948
|
+
handleFailure(status, media, error, category, operation, scheduleRetry = true, applyFallback = true) {
|
|
2856
2949
|
dialSdkDebugWarn(DEBUG_MODULE, "DefaultDrivingExpressionPlayer.handleFailure", "called", {
|
|
2857
2950
|
status,
|
|
2858
2951
|
media,
|
|
2859
2952
|
error,
|
|
2860
2953
|
category,
|
|
2861
2954
|
operation,
|
|
2862
|
-
scheduleRetry
|
|
2955
|
+
scheduleRetry,
|
|
2956
|
+
applyFallback
|
|
2863
2957
|
});
|
|
2864
2958
|
if (!this.isCurrent(operation) || this.failedOperation === operation) {
|
|
2865
2959
|
dialSdkDebugWarn(DEBUG_MODULE, "DefaultDrivingExpressionPlayer.handleFailure", "ignored");
|
|
@@ -2868,6 +2962,7 @@ var DefaultDrivingExpressionPlayer = class {
|
|
|
2868
2962
|
this.failedOperation = operation;
|
|
2869
2963
|
this.stopActiveVideo();
|
|
2870
2964
|
this.phase = "error";
|
|
2965
|
+
if (!applyFallback && media !== null) this.mediaKind = media.kind;
|
|
2871
2966
|
this.errorCategory = category;
|
|
2872
2967
|
this.emitDiagnostic({
|
|
2873
2968
|
type: "media_load_failed",
|
|
@@ -2876,8 +2971,24 @@ var DefaultDrivingExpressionPlayer = class {
|
|
|
2876
2971
|
category,
|
|
2877
2972
|
message: safeErrorMessage(error)
|
|
2878
2973
|
});
|
|
2879
|
-
|
|
2880
|
-
|
|
2974
|
+
let fallbackApplied = false;
|
|
2975
|
+
const fallback = applyFallback ? this.resolveFallback(status) : { type: "missing" };
|
|
2976
|
+
if (fallback.type === "static") {
|
|
2977
|
+
this.renderFallback(status, fallback.media);
|
|
2978
|
+
fallbackApplied = true;
|
|
2979
|
+
} else if (fallback.type === "unsupported") {
|
|
2980
|
+
this.container.replaceChildren();
|
|
2981
|
+
this.phase = "error";
|
|
2982
|
+
this.mediaKind = fallback.media.kind;
|
|
2983
|
+
this.errorCategory = "invalid_config";
|
|
2984
|
+
this.emitDiagnostic({
|
|
2985
|
+
type: "media_load_failed",
|
|
2986
|
+
status,
|
|
2987
|
+
kind: fallback.media.kind,
|
|
2988
|
+
category: "invalid_config",
|
|
2989
|
+
message: safeErrorMessage(unsupportedFallbackError(fallback.media))
|
|
2990
|
+
});
|
|
2991
|
+
} else {
|
|
2881
2992
|
this.phase = "error";
|
|
2882
2993
|
this.errorCategory = category;
|
|
2883
2994
|
}
|
|
@@ -3123,12 +3234,9 @@ var DefaultDrivingExpressionPlayer = class {
|
|
|
3123
3234
|
dialSdkDebugWarn(DEBUG_MODULE, "DefaultDrivingExpressionPlayer.emitDiagnostic", "returned no listener");
|
|
3124
3235
|
return;
|
|
3125
3236
|
}
|
|
3126
|
-
|
|
3127
|
-
this.onDiagnostic(event);
|
|
3128
|
-
dialSdkDebugWarn(DEBUG_MODULE, "DefaultDrivingExpressionPlayer.emitDiagnostic", "returned", { event });
|
|
3129
|
-
} catch (error) {
|
|
3237
|
+
if (invokeSafely(this.onDiagnostic, [event], (error) => {
|
|
3130
3238
|
dialSdkDebugWarn(DEBUG_MODULE, "DefaultDrivingExpressionPlayer.emitDiagnostic", "listener threw", error);
|
|
3131
|
-
}
|
|
3239
|
+
})) dialSdkDebugWarn(DEBUG_MODULE, "DefaultDrivingExpressionPlayer.emitDiagnostic", "returned", { event });
|
|
3132
3240
|
}
|
|
3133
3241
|
};
|
|
3134
3242
|
var MediaPlayerError = class extends Error {
|
|
@@ -3161,6 +3269,8 @@ const normalizeMedia = (media) => {
|
|
|
3161
3269
|
});
|
|
3162
3270
|
return result;
|
|
3163
3271
|
};
|
|
3272
|
+
const isStaticFallback = (media) => media.kind === "emoji" || media.kind === "image";
|
|
3273
|
+
const unsupportedFallbackError = (media) => new MediaPlayerError("invalid_config", `Fallback media kind ${media.kind} is unsupported; use emoji or image`);
|
|
3164
3274
|
const isRetainableImage = (media) => {
|
|
3165
3275
|
if (media.mimeType?.split(";", 1)[0]?.trim().toLowerCase() === "image/gif") return false;
|
|
3166
3276
|
try {
|
|
@@ -3246,7 +3356,7 @@ const waitForElementEvent = (element, successEvent, failureEvent, signal, timeou
|
|
|
3246
3356
|
const handleAbort = () => {
|
|
3247
3357
|
dialSdkDebugWarn(DEBUG_MODULE, "waitForElementEvent.handleAbort", "called");
|
|
3248
3358
|
cleanup();
|
|
3249
|
-
reject(createAbortError());
|
|
3359
|
+
reject(createAbortError("Aborted", CREATE_ABORT_ERROR_DEBUG));
|
|
3250
3360
|
};
|
|
3251
3361
|
element.addEventListener(successEvent, handleSuccess, { once: true });
|
|
3252
3362
|
element.addEventListener(failureEvent, handleFailure, { once: true });
|
|
@@ -3283,7 +3393,7 @@ const withTimeout = (promise, timeoutMs, signal) => {
|
|
|
3283
3393
|
const handleAbort = () => {
|
|
3284
3394
|
dialSdkDebugWarn(DEBUG_MODULE, "withTimeout.handleAbort", "called");
|
|
3285
3395
|
cleanup();
|
|
3286
|
-
reject(createAbortError());
|
|
3396
|
+
reject(createAbortError("Aborted", CREATE_ABORT_ERROR_DEBUG));
|
|
3287
3397
|
};
|
|
3288
3398
|
signal.addEventListener("abort", handleAbort, { once: true });
|
|
3289
3399
|
timer = globalThis.setTimeout(() => {
|
|
@@ -3310,9 +3420,9 @@ const defaultTgsRenderer = async (container, animationData, signal) => {
|
|
|
3310
3420
|
animationData,
|
|
3311
3421
|
signal
|
|
3312
3422
|
});
|
|
3313
|
-
if (signal.aborted) throw createAbortError();
|
|
3423
|
+
if (signal.aborted) throw createAbortError("Aborted", CREATE_ABORT_ERROR_DEBUG);
|
|
3314
3424
|
const module = await import("lottie-web/build/player/lottie_light.js");
|
|
3315
|
-
if (signal.aborted) throw createAbortError();
|
|
3425
|
+
if (signal.aborted) throw createAbortError("Aborted", CREATE_ABORT_ERROR_DEBUG);
|
|
3316
3426
|
const animation = module.default.loadAnimation({
|
|
3317
3427
|
animationData,
|
|
3318
3428
|
autoplay: true,
|
|
@@ -3336,7 +3446,7 @@ const defaultTgsRenderer = async (container, animationData, signal) => {
|
|
|
3336
3446
|
dialSdkDebugWarn(DEBUG_MODULE, "defaultTgsRenderer.aborted", "called");
|
|
3337
3447
|
cleanup();
|
|
3338
3448
|
animation.destroy();
|
|
3339
|
-
reject(createAbortError());
|
|
3449
|
+
reject(createAbortError("Aborted", CREATE_ABORT_ERROR_DEBUG));
|
|
3340
3450
|
};
|
|
3341
3451
|
const cleanup = () => {
|
|
3342
3452
|
dialSdkDebugWarn(DEBUG_MODULE, "defaultTgsRenderer.cleanup", "called");
|
|
@@ -3375,7 +3485,7 @@ function validateTgsAnimation(value, maxLayers) {
|
|
|
3375
3485
|
value,
|
|
3376
3486
|
maxLayers
|
|
3377
3487
|
});
|
|
3378
|
-
if (!isRecord(value) || !Array.isArray(value.layers)) throw new MediaPlayerError("decode", "TGS animation does not contain a layers array");
|
|
3488
|
+
if (!isRecord(value, IS_RECORD_DEBUG) || !Array.isArray(value.layers)) throw new MediaPlayerError("decode", "TGS animation does not contain a layers array");
|
|
3379
3489
|
if (value.layers.length > maxLayers) throw new MediaPlayerError("decode", "TGS animation has too many layers");
|
|
3380
3490
|
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
3491
|
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 +3540,7 @@ const resetVideo = (video) => {
|
|
|
3430
3540
|
video.pause();
|
|
3431
3541
|
video.removeAttribute("src");
|
|
3432
3542
|
video.removeAttribute("type");
|
|
3433
|
-
|
|
3434
|
-
video.load();
|
|
3435
|
-
} catch (error) {
|
|
3436
|
-
dialSdkDebugWarn(DEBUG_MODULE, "resetVideo", "load threw", error);
|
|
3437
|
-
}
|
|
3543
|
+
video.load();
|
|
3438
3544
|
dialSdkDebugWarn(DEBUG_MODULE, "resetVideo", "returned", { video });
|
|
3439
3545
|
};
|
|
3440
3546
|
const styleMediaElement = (element, fit) => {
|
|
@@ -3481,39 +3587,6 @@ const redactUrlQueries = (message) => {
|
|
|
3481
3587
|
dialSdkDebugWarn(DEBUG_MODULE, "redactUrlQueries", "returned", { result });
|
|
3482
3588
|
return result;
|
|
3483
3589
|
};
|
|
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
3590
|
const safeDestroy = (handle) => {
|
|
3518
3591
|
dialSdkDebugWarn(DEBUG_MODULE, "safeDestroy", "called", { handle });
|
|
3519
3592
|
try {
|
|
@@ -3523,13 +3596,5 @@ const safeDestroy = (handle) => {
|
|
|
3523
3596
|
dialSdkDebugWarn(DEBUG_MODULE, "safeDestroy", "destroy threw", error);
|
|
3524
3597
|
}
|
|
3525
3598
|
};
|
|
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
3599
|
//#endregion
|
|
3535
3600
|
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 };
|