feat(sensors): runtime seam for overlay-registered sensor controls
registerSensorControls() lets a private build add SensorControlDef entries for sensors it ships outside the OSS tree (e.g. the DFRobot Gravity analog family) so they get the live slider panel; every SENSOR_CONTROLS lookup now goes through getSensorControl(id) which falls back to the registered map. Dead code in a pure OSS build, same contract as proBoardRegistry / registerComponentDoc.
This commit is contained in:
parent
69819ee614
commit
116afcab98
|
|
@ -9,7 +9,7 @@
|
||||||
import React, { useEffect, useState } from 'react';
|
import React, { useEffect, useState } from 'react';
|
||||||
import { useTranslation } from 'react-i18next';
|
import { useTranslation } from 'react-i18next';
|
||||||
import {
|
import {
|
||||||
SENSOR_CONTROLS,
|
getSensorControl,
|
||||||
type SensorControl,
|
type SensorControl,
|
||||||
type SliderControl,
|
type SliderControl,
|
||||||
} from '../../simulation/sensorControlConfig';
|
} from '../../simulation/sensorControlConfig';
|
||||||
|
|
@ -49,7 +49,7 @@ export const SensorControlPanel: React.FC<SensorControlPanelProps> = ({
|
||||||
onClose,
|
onClose,
|
||||||
}) => {
|
}) => {
|
||||||
const { t } = useTranslation();
|
const { t } = useTranslation();
|
||||||
const def = SENSOR_CONTROLS[metadataId];
|
const def = getSensorControl(metadataId);
|
||||||
|
|
||||||
// Local slider/button state — hydrated from the registry's last-known
|
// Local slider/button state — hydrated from the registry's last-known
|
||||||
// values for this componentId (so reopening a sensor or switching between
|
// values for this componentId (so reopening a sensor or switching between
|
||||||
|
|
|
||||||
|
|
@ -11,7 +11,7 @@ import { ComponentPickerModal } from '../ComponentPickerModal';
|
||||||
import { ComponentPropertyDialog } from './ComponentPropertyDialog';
|
import { ComponentPropertyDialog } from './ComponentPropertyDialog';
|
||||||
import { CustomChipDialog } from '../customChips/CustomChipDialog';
|
import { CustomChipDialog } from '../customChips/CustomChipDialog';
|
||||||
import { SensorControlPanel } from './SensorControlPanel';
|
import { SensorControlPanel } from './SensorControlPanel';
|
||||||
import { SENSOR_CONTROLS } from '../../simulation/sensorControlConfig';
|
import { SENSOR_CONTROLS, getSensorControl } from '../../simulation/sensorControlConfig';
|
||||||
import { DynamicComponent, createComponentFromMetadata } from '../DynamicComponent';
|
import { DynamicComponent, createComponentFromMetadata } from '../DynamicComponent';
|
||||||
import { InstrumentComponent } from '../components-instruments/InstrumentComponent';
|
import { InstrumentComponent } from '../components-instruments/InstrumentComponent';
|
||||||
import { ComponentRegistry } from '../../services/ComponentRegistry';
|
import { ComponentRegistry } from '../../services/ComponentRegistry';
|
||||||
|
|
@ -996,7 +996,7 @@ export const SimulatorCanvas = ({ headerSlot }: SimulatorCanvasProps = {}) => {
|
||||||
const component = componentsRef.current.find((c) => c.id === touchId);
|
const component = componentsRef.current.find((c) => c.id === touchId);
|
||||||
if (component) {
|
if (component) {
|
||||||
if (interactionRunningRef.current) {
|
if (interactionRunningRef.current) {
|
||||||
if (SENSOR_CONTROLS[component.metadataId] !== undefined) {
|
if (getSensorControl(component.metadataId) !== undefined) {
|
||||||
setSensorControlComponentId(touchId);
|
setSensorControlComponentId(touchId);
|
||||||
setSensorControlMetadataId(component.metadataId);
|
setSensorControlMetadataId(component.metadataId);
|
||||||
}
|
}
|
||||||
|
|
@ -1417,7 +1417,7 @@ export const SimulatorCanvas = ({ headerSlot }: SimulatorCanvasProps = {}) => {
|
||||||
// panel). Mirrors the touch tap flow above.
|
// panel). Mirrors the touch tap flow above.
|
||||||
if (interactionRunning) {
|
if (interactionRunning) {
|
||||||
const component = components.find((c) => c.id === componentId);
|
const component = components.find((c) => c.id === componentId);
|
||||||
const isSensor = !!component && SENSOR_CONTROLS[component.metadataId] !== undefined;
|
const isSensor = !!component && getSensorControl(component.metadataId) !== undefined;
|
||||||
if (!isSensor) return;
|
if (!isSensor) return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -1710,7 +1710,7 @@ export const SimulatorCanvas = ({ headerSlot }: SimulatorCanvasProps = {}) => {
|
||||||
// handle its own clicks, so we suppress the property
|
// handle its own clicks, so we suppress the property
|
||||||
// dialog entirely. This is the path that also unblocks
|
// dialog entirely. This is the path that also unblocks
|
||||||
// wokwi-slide-switch toggling in the digital examples.
|
// wokwi-slide-switch toggling in the digital examples.
|
||||||
if (SENSOR_CONTROLS[component.metadataId] !== undefined) {
|
if (getSensorControl(component.metadataId) !== undefined) {
|
||||||
setSensorControlComponentId(draggedComponentId);
|
setSensorControlComponentId(draggedComponentId);
|
||||||
setSensorControlMetadataId(component.metadataId);
|
setSensorControlMetadataId(component.metadataId);
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -377,3 +377,20 @@ export const SENSOR_CONTROLS: Record<string, SensorControlDef> = {
|
||||||
defaultValues: { xAxis: 0, yAxis: 0 },
|
defaultValues: { xAxis: 0, yAxis: 0 },
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// ── Overlay seam ─────────────────────────────────────────────────────────────
|
||||||
|
// A private build (velxio.com) registers sensor-control definitions for the
|
||||||
|
// sensors it ships outside the OSS tree (e.g. the DFRobot Gravity analog
|
||||||
|
// family). Same contract as proBoardRegistry / registerComponentDoc: dead code
|
||||||
|
// in a pure OSS build. Read every SENSOR_CONTROLS lookup through
|
||||||
|
// getSensorControl() so overlay-registered sensors surface their slider panel.
|
||||||
|
const proSensorControls: Record<string, SensorControlDef> = {};
|
||||||
|
|
||||||
|
export function registerSensorControls(defs: Record<string, SensorControlDef>): void {
|
||||||
|
Object.assign(proSensorControls, defs);
|
||||||
|
}
|
||||||
|
|
||||||
|
export function getSensorControl(id: string | null | undefined): SensorControlDef | undefined {
|
||||||
|
if (!id) return undefined;
|
||||||
|
return SENSOR_CONTROLS[id] ?? proSensorControls[id];
|
||||||
|
}
|
||||||
|
|
|
||||||
|
|
@ -53,7 +53,7 @@ import {
|
||||||
updateWires as icUpdateWires,
|
updateWires as icUpdateWires,
|
||||||
setInterconnectRuntime,
|
setInterconnectRuntime,
|
||||||
} from '../simulation/Interconnect';
|
} from '../simulation/Interconnect';
|
||||||
import { SENSOR_CONTROLS } from '../simulation/sensorControlConfig';
|
import { SENSOR_CONTROLS, getSensorControl } from '../simulation/sensorControlConfig';
|
||||||
import { dispatchSensorUpdate } from '../simulation/SensorUpdateRegistry';
|
import { dispatchSensorUpdate } from '../simulation/SensorUpdateRegistry';
|
||||||
|
|
||||||
// ── Sensor pre-registration ──────────────────────────────────────────────────
|
// ── Sensor pre-registration ──────────────────────────────────────────────────
|
||||||
|
|
@ -2150,18 +2150,18 @@ export const useSimulatorStore = create<SimulatorState>((set, get) => {
|
||||||
// 2.5V) and refreshes the panel's cached value; bumping sensorResetNonce
|
// 2.5V) and refreshes the panel's cached value; bumping sensorResetNonce
|
||||||
// remounts the open SensorControlPanel so its slider snaps back too.
|
// remounts the open SensorControlPanel so its slider snaps back too.
|
||||||
const sensorComps = get().components.filter(
|
const sensorComps = get().components.filter(
|
||||||
(c) => c.metadataId && SENSOR_CONTROLS[c.metadataId],
|
(c) => c.metadataId && getSensorControl(c.metadataId),
|
||||||
);
|
);
|
||||||
if (sensorComps.length > 0) {
|
if (sensorComps.length > 0) {
|
||||||
set((s) => ({
|
set((s) => ({
|
||||||
components: s.components.map((c) => {
|
components: s.components.map((c) => {
|
||||||
const def = c.metadataId ? SENSOR_CONTROLS[c.metadataId] : undefined;
|
const def = getSensorControl(c.metadataId);
|
||||||
return def ? { ...c, properties: { ...c.properties, ...def.defaultValues } } : c;
|
return def ? { ...c, properties: { ...c.properties, ...def.defaultValues } } : c;
|
||||||
}),
|
}),
|
||||||
sensorResetNonce: s.sensorResetNonce + 1,
|
sensorResetNonce: s.sensorResetNonce + 1,
|
||||||
}));
|
}));
|
||||||
for (const c of sensorComps) {
|
for (const c of sensorComps) {
|
||||||
dispatchSensorUpdate(c.id, SENSOR_CONTROLS[c.metadataId].defaultValues);
|
dispatchSensorUpdate(c.id, getSensorControl(c.metadataId)!.defaultValues);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue