fgdb - khalilbendhief/KHALIL GitHub Wiki

6.2 new.rs — Hardware Initialization

new.rs implements MachineNewTrait and handles EtherCAT device discovery, module initialization, and channel binding. It runs once at startup.

Step 1 — Validate the device group

validate_same_machine_identification_unique(&device_identification)?;
validate_no_role_duplicates(&device_identification)?;

Ensures all devices assigned in the dashboard share the same serial number and have no duplicate roles. Fails early with a clear error if the assignment is invalid.

Step 2 — Acquire the 750-354 coupler

let _wago_750_354 = get_ethercat_device::<Wago750_354>(
    hardware, params, 0, [WAGO_750_354_IDENTITY_A].to_vec(),
).await?;

Fetches the coupler handle from the EtherCAT bus by identity. The 0 is the expected position on the bus.

Step 3 — Discover and register slot modules

let modules = Wago750_354::initialize_modules(_wago_750_354.1).await?;
let mut coupler = _wago_750_354.0.write().await;
for module in modules { coupler.set_module(module); }
coupler.init_slot_modules(_wago_750_354.1);

The coupler scans its physical slots left-to-right and registers whatever modules it finds. After this, coupler.slot_devices is populated by slot index.

Step 4 — Downcast slot devices to concrete types

// Slot 0 → 750-530 (Digital Output)
let dev = coupler.slot_devices.get(0).unwrap().clone().unwrap();
let wago750_530: Arc<RwLock<Wago750_530>> =
    downcast_device::<Wago750_530>(dev).await?;
 
// Slot 1 → 750-430 (Digital Input)
let dev = coupler.slot_devices.get(1).unwrap().clone().unwrap();
let wago750_430: Arc<RwLock<Wago750_430>> =
    downcast_device::<Wago750_430>(dev).await?;

downcast_device casts the generic Arc<dyn EthercatDevice> to the concrete module type. If the physical module in a slot doesn't match the expected type, this returns an error at runtime.

⚠️ Physical slot order matters: slot 0 = 750-530 (DO), slot 1 = 750-430 (DI). Mount the modules in this exact order on the DIN rail.

Step 5 — Create per-channel I/O handles

let di1 = DigitalInput::new(wago750_430.clone(), Wago750_430Port::Port1);
// ... di2 through di8
 
let do1 = DigitalOutput::new(wago750_530.clone(), Wago750_530Port::Port1);
// ... do2 through do8

Each DigitalInput / DigitalOutput holds a shared reference (Arc<RwLock<T>>) to its parent module and a port identifier. Multiple channel handles share the same module lock safely.

Step 6 — Construct the machine and emit initial state

let mut machine = Self {
    digital_input:  [di1, di2, di3, di4, di5, di6, di7, di8],
    digital_output: [do1, do2, do3, do4, do5, do6, do7, do8],
    inputs: [false; 8],
    led_on: [false; 8],
    // ...
};
machine.emit_state();
Ok(machine)

All channels are bundled into fixed-size arrays. emit_state() is called immediately so any connected frontend receives the initial state without waiting for the first 30 Hz tick.


⚠️ **GitHub.com Fallback** ⚠️