fix: render live V2X vehicles in Cesium preview

This commit is contained in:
2026-08-25 12:57:35 +08:00
parent bc845444bb
commit 25cf82e7c7
23 changed files with 198 additions and 58 deletions

View File

@@ -11,6 +11,8 @@ const source = fs.readFileSync(path.join(__dirname, "lib", "v2x-cesium-overlay.j
const context = {
window: { location: new URL("https://preview.example.test/areas/fengshu/") },
URL,
Blob,
TextDecoder,
console,
};
vm.runInNewContext(source, context, { filename: "v2x-cesium-overlay.js" });
@@ -69,6 +71,9 @@ assert.equal(lampColorName(999), "other");
// --- AC7: loose payload parsing --------------------------------------------
assert.deepEqual(parseLoosePayload('{"a":1}'), { a: 1 });
assert.deepEqual(parseLoosePayload("{a:1,b:'x',}"), { a: 1, b: "x" });
assert.deepEqual(parseLoosePayload('{data:{1519:[{id:"53122",longitude:114.12871535072304,latitude:30.46061866463221}]}}'), {
data: { 1519: [{ id: "53122", longitude: 114.12871535072304, latitude: 30.46061866463221 }] },
}, "targetPosition uses unquoted numeric device-id keys");
assert.deepEqual(parseLoosePayload('{"a":NaN}'), { a: null });
assert.equal(parseLoosePayload("{bad"), null);
assert.equal(parseLoosePayload(null), null);
@@ -161,6 +166,10 @@ assert.equal(obuPush.vehicle.id, "obu-c1");
assert.deepEqual(normalizeTargetVehicles(JSON.stringify({ data: { 8: [{ id: 9, longitude: 114.12866, latitude: 30.4605, type: 1, subType: 2, angle: 180, speed: 5 }] } })), [{
id: "8-9-12", label: "8-9", kind: "target", longitude: 114.12866, latitude: 30.4605, angle: 180, speed: 5, type: 1, subType: 2,
}]);
assert.equal(normalizeTargetPush(JSON.stringify({ data: { 1519: [{ id: "50089", longitude: 114.12876415699589, latitude: 30.46060781353787, type: 1, subType: 1 }] }, interval: 1000 })).vehicles.length, 1,
"the live targetPosition payload uses numeric object keys and string target ids");
assert.equal(normalizeTargetPush('{data:{1519:[{id:"53122",longitude:114.12871535072304,latitude:30.46061866463221,type:1,subType:1}]},interval:1000}').vehicles.length, 1,
"unquoted numeric device-id keys are accepted from the live targetPosition stream");
const targetPush = normalizeTargetPush(JSON.stringify({ interval: 0, data: { 8: [{ id: 9, longitude: 114.1, latitude: 30.4, type: 1 }] } }));
assert.equal(targetPush.vehicles[0].subType, 1, "type 1 without subType defaults to subType 1");
assert.equal(resolvePushInterval(targetPush.interval), 500, "interval 0 falls back to 500");
@@ -168,7 +177,7 @@ assert.equal(resolvePushInterval(undefined), 500);
assert.equal(resolvePushInterval(900), 900);
// --- AC8: model naming matches the dashboard --------------------------------
assert.equal(modelNameFor({ kind: "obu" }), "car_obu.glb");
assert.equal(modelNameFor({ kind: "obu" }), "11.glb");
assert.equal(modelNameFor({ kind: "target", type: 1, subType: 2 }), "12.glb");
assert.equal(modelNameFor({ kind: "target" }), "11.glb");
@@ -178,10 +187,12 @@ const registry = createVehicleRegistry({ now: () => clock });
registry.ingest([{ id: "v1", kind: "target", type: 1, subType: 1 }], 1000);
assert.equal(registry.list().length, 1);
assert.equal(registry.list()[0].visible, true);
assert.equal(registry.visibleSize, 1);
assert.equal(registry.list()[0].duration, 1000);
assert.deepEqual(registry.sweep(clock + 1499), [], "still fresh below interval * 1.5");
assert.deepEqual(registry.sweep(clock + 1500), ["v1"], "hidden at interval * 1.5");
assert.equal(registry.list()[0].visible, false);
assert.equal(registry.visibleSize, 0);
assert.equal(registry.list().length, 1, "hidden vehicles are kept as reusable slots, not removed");
clock = 5000;