fix: wire distinct M3 simulator identities

Merge PR #159 after Code Queue rebase and validation. Runner verified M3 cardinality, hardware-loop smoke, patch-panel runtime smoke, m3 readonly contract, and git diff check. This is source/config blocker removal only; it does not claim DEV-LIVE M3 pass.
This commit is contained in:
Lyon
2026-05-23 00:09:29 +08:00
committed by GitHub
parent 792262c5d1
commit 7a0648088c
20 changed files with 791 additions and 53 deletions
+7
View File
@@ -13,8 +13,15 @@ const gatewaySessionId = selectInstanceValue(
process.env.HWLAB_GATEWAY_SESSION_ID,
"gws_mvp_simu"
);
const resourceId = selectInstanceValue(process.env.HWLAB_BOX_RESOURCE_ID, "");
const port = parsePort(process.env.PORT, 7201);
const state = createBoxState({ boxId, gatewaySessionId });
if (resourceId) {
state.resource.resourceId = resourceId;
for (const capability of state.capabilities ?? []) {
capability.resourceId = resourceId;
}
}
const routes = new Map();
+17 -6
View File
@@ -16,7 +16,8 @@ const boxUrls = parseBoxUrls(process.env.HWLAB_BOX_URLS);
const boxes = parseBoxes({
resources: process.env.HWLAB_BOX_RESOURCES,
ids: process.env.HWLAB_BOX_IDS,
urls: boxUrls
urls: boxUrls,
instanceScoped: parseList(process.env.HWLAB_GATEWAY_ID).length > 1
});
const state = createGatewayState({
gatewayId,
@@ -115,10 +116,11 @@ function parseList(value) {
.filter(Boolean);
}
function parseBoxes({ resources, ids, urls }) {
const explicitResources = parseList(resources);
const explicitIds = parseList(ids);
const count = Math.max(explicitResources.length, explicitIds.length, urls.length, 1);
function parseBoxes({ resources, ids, urls, instanceScoped = false }) {
const explicitResources = instanceScoped ? selectScopedList(resources) : parseList(resources);
const explicitIds = instanceScoped ? selectScopedList(ids) : parseList(ids);
const explicitUrls = instanceScoped ? selectScopedList(urls.join(",")) : urls;
const count = Math.max(explicitResources.length, explicitIds.length, explicitUrls.length, 1);
const parsed = [];
for (let index = 0; index < count; index += 1) {
@@ -130,7 +132,7 @@ function parseBoxes({ resources, ids, urls }) {
parsed.push({
boxId,
resourceId,
url: urls[index] ?? null,
url: explicitUrls[index] ?? null,
state: "registered"
});
}
@@ -138,6 +140,15 @@ function parseBoxes({ resources, ids, urls }) {
return parsed;
}
function selectScopedList(value) {
const items = parseList(value);
if (items.length <= 1) {
return items;
}
const selected = selectInstanceValue(items.join(","), "");
return selected ? [selected] : [];
}
function normalizeBoxRegistration(body) {
const boxId = body.boxId ?? body.identity?.boxId;
const resourceId = body.resourceId ?? body.resource?.resourceId ?? (boxId ? resourceIdForBox(boxId) : null);
+16 -3
View File
@@ -1,5 +1,5 @@
#!/usr/bin/env node
import { createMvpTopology } from "../../internal/patchpanel/fixture.mjs";
import { createM3Topology } from "../../internal/patchpanel/fixture.mjs";
import {
createPatchPanelRuntime,
createPatchPanelRuntimeFromFile
@@ -9,12 +9,16 @@ import { createJsonServer, listen, parsePort, readJson } from "../../internal/si
const port = parsePort(process.env.PORT, 7301);
const wiringConfigPath = process.env.HWLAB_WIRING_CONFIG_PATH;
const topology = createMvpTopology();
const topology = createM3Topology();
const endpointMap = parseEndpointMap(process.env.HWLAB_PATCH_PANEL_ENDPOINT_MAP) ?? {
res_boxsimu_2: "http://hwlab-box-simu-2.hwlab-dev.svc.cluster.local:7201"
};
const runtime = wiringConfigPath
? await createPatchPanelRuntimeFromFile({ path: wiringConfigPath })
: createPatchPanelRuntime({
wiringConfig: topology.wiringConfig,
configSource: "internal:mvp-topology"
endpointMap,
configSource: "internal:m3-topology"
});
const routes = new Map();
@@ -38,3 +42,12 @@ routes.set("POST /signals/route", async ({ req }) => runtime.routeSignal(await r
routes.set("POST /sync/tick", async ({ req }) => runtime.tick(await readJson(req)));
listen(createJsonServer({ routes }), port);
function parseEndpointMap(value) {
const source = String(value ?? "").trim();
if (!source) {
return null;
}
return JSON.parse(source);
}