Files
pikasTech-HWLAB/internal/patchpanel/fixture.mjs
T
Lyon 7a0648088c 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.
2026-05-23 00:09:29 +08:00

194 lines
4.8 KiB
JavaScript

import { createBoxState, createGatewayState } from "../sim/model.mjs";
import { createPatchPanelState, createWiringConfig } from "./model.mjs";
export const MVP_BOX_IDS = Object.freeze(["boxsim_alpha", "boxsim_beta"]);
export const MVP_GATEWAY_IDS = Object.freeze(["gwsimu_east", "gwsimu_west"]);
export const M3_BOX_IDS = Object.freeze(["boxsimu_1", "boxsimu_2"]);
export const M3_GATEWAY_IDS = Object.freeze(["gwsimu_1", "gwsimu_2"]);
export const M3_BOX_RESOURCES = Object.freeze(["res_boxsimu_1", "res_boxsimu_2"]);
function createGatewaySessionIds(gatewayIds) {
return gatewayIds.map((gatewayId) => `gws_${gatewayId}`);
}
export function createMvpTopology({ now = "2026-01-01T00:00:00.000Z" } = {}) {
const gatewaySessionIds = createGatewaySessionIds(MVP_GATEWAY_IDS);
const boxes = MVP_BOX_IDS.map((boxId, index) =>
createBoxState({
boxId,
gatewaySessionId: gatewaySessionIds[index],
ports: ["uart0", "eth0", "gpio0"],
includePortDefinitions: false,
now
})
);
const gateways = MVP_GATEWAY_IDS.map((gatewayId, index) =>
createGatewayState({
gatewayId,
endpoint: `http://127.0.0.1:${7101 + index}`,
boxes: [boxes[index].resource.resourceId],
now
})
);
const wiringConfig = createWiringConfig({
gatewaySessionId: gatewaySessionIds[0],
connections: [
{
from: {
resourceId: boxes[0].resource.resourceId,
port: "uart0"
},
to: {
resourceId: boxes[1].resource.resourceId,
port: "uart0"
},
mode: "exclusive"
},
{
from: {
resourceId: boxes[0].resource.resourceId,
port: "gpio0"
},
to: {
resourceId: boxes[1].resource.resourceId,
port: "gpio0"
},
mode: "monitor"
}
],
now
});
const patchPanel = createPatchPanelState({
gatewaySessionId: gatewaySessionIds[0],
wiringConfig,
now
});
return {
topologyId: "top_mvp_l2_l3_sim_patch",
projectId: "prj_mvp_topology",
environment: "dev",
services: {
boxes,
gateways,
patchPanel
},
wiringConfig,
constraints: {
patchPanelIsOnlyCrossDeviceChannel: true,
boxSimuLocalLoopbackForCrossDeviceSync: false
},
dryRunHints: {
cliTarget: "fixtures/mvp-topology/topology.json",
expectedServices: ["hwlab-box-simu", "hwlab-gateway-simu", "hwlab-patch-panel"]
}
};
}
export function createM3Topology({ now = "2026-05-21T00:00:00.000Z" } = {}) {
const projectId = "prj_m3_hardware_loop";
const gatewaySessionIds = createGatewaySessionIds(M3_GATEWAY_IDS);
const boxes = M3_BOX_IDS.map((boxId, index) =>
withProjectId(createBoxState({
boxId,
gatewaySessionId: gatewaySessionIds[index],
ports: ["DO1", "DI1"],
now
}), projectId)
);
const gateways = M3_GATEWAY_IDS.map((gatewayId, index) =>
withProjectId(createGatewayState({
gatewayId,
endpoint: `http://127.0.0.1:${7101 + index}`,
boxes: [M3_BOX_RESOURCES[index]],
now
}), projectId)
);
const wiringConfig = createWiringConfig({
wiringConfigId: "wir_m3_do1_di1",
projectId,
gatewaySessionId: gatewaySessionIds[0],
name: "M3 simulated DO1 to DI1 patch wiring",
connections: [
{
from: {
resourceId: M3_BOX_RESOURCES[0],
port: "DO1"
},
to: {
resourceId: M3_BOX_RESOURCES[1],
port: "DI1"
},
mode: "exclusive"
}
],
now
});
const patchPanel = createPatchPanelState({
patchPanelStatusId: "pps_m3_hardware_loop",
gatewaySessionId: gatewaySessionIds[0],
wiringConfig,
metadata: {
signal: "res_boxsimu_1:DO1 -> hwlab-patch-panel -> res_boxsimu_2:DI1"
},
now
});
return {
topologyId: "top_m3_hardware_loop",
projectId,
environment: "dev",
services: {
boxes,
gateways,
patchPanel
},
wiringConfig,
constraints: {
patchPanelIsOnlyCrossDeviceChannel: true,
boxSimuLocalLoopbackForCrossDeviceSync: false
},
dryRunHints: {
cliTarget: "fixtures/mvp/m3-hardware-loop/topology.json",
expectedServices: ["hwlab-box-simu", "hwlab-gateway-simu", "hwlab-patch-panel"]
}
};
}
function withProjectId(record, projectId) {
return {
...record,
projectId,
...(record.resource
? {
resource: {
...record.resource,
projectId
}
}
: {}),
...(record.capabilities
? {
capabilities: record.capabilities.map((capability) => ({
...capability,
projectId
}))
}
: {}),
...(record.session
? {
session: {
...record.session,
projectId
}
}
: {})
};
}