import { AVRSimulator } from '../AVRSimulator'; import { RP2040Simulator } from '../RP2040Simulator'; /** Any simulator that components can interact with (AVR, RP2040, or ESP32 bridge shim). */ export type AnySimulator = | { setPinState(pin: number, state: boolean): void; isRunning(): boolean; pinManager: import('../PinManager').PinManager; // eslint-disable-next-line @typescript-eslint/no-explicit-any [key: string]: any; } | AVRSimulator | RP2040Simulator; /** * Interface for simulation logic mapped to a specific wokwi-element */ export interface PartSimulationLogic { /** * Called when a digital pin connected to this part changes state. * Useful for output components (LEDs, buzzers, etc). * * @param pinName The name of the pin on the component that changed * @param state The new digital state (true = HIGH, false = LOW) * @param element The DOM element of the wokwi component */ onPinStateChange?: (pinName: string, state: boolean, element: HTMLElement) => void; /** * Called when the simulation starts to attach events or setup periodic tasks. * Useful for input components (buttons, potentiometers) or complex components (servos). * * @param element The DOM element of the wokwi component * @param avrSimulator The running simulator instance * @param getArduinoPinHelper Function to find what Arduino pin is connected to a specific component pin * @param componentId The unique ID of this component instance (used by SensorUpdateRegistry) * @returns A cleanup function to remove event listeners when simulation stops */ attachEvents?: ( element: HTMLElement, simulator: AnySimulator, getArduinoPinHelper: (componentPinName: string) => number | null, componentId: string, ) => () => void; } class PartRegistry { private parts: Map = new Map(); register(metadataId: string, logic: PartSimulationLogic) { this.parts.set(metadataId, logic); } get(metadataId: string): PartSimulationLogic | undefined { return this.parts.get(metadataId); } } export const PartSimulationRegistry = new PartRegistry(); // Import store explicitly inside a function to avoid circular dependencies if any, // but since we just need it at runtime, we can import it at the top or dynamically. import { useSimulatorStore } from '../../store/useSimulatorStore'; PartSimulationRegistry.register('raspberry-pi-3', { onPinStateChange: (pinName: string, state: boolean, _element: HTMLElement) => { // When Arduino changes a pin connected to Raspberry Pi, forward to backend useSimulatorStore.getState().sendRemotePinEvent(pinName, state ? 1 : 0); }, });