diff --git a/electron/src/machines/extruder/extruder2/Extruder2ControlPage.tsx b/electron/src/machines/extruder/extruder2/Extruder2ControlPage.tsx index 86918eda..5399e52a 100644 --- a/electron/src/machines/extruder/extruder2/Extruder2ControlPage.tsx +++ b/electron/src/machines/extruder/extruder2/Extruder2ControlPage.tsx @@ -16,38 +16,29 @@ import { StatusBadge } from "@/control/StatusBadge"; export function Extruder2ControlPage() { const { - mode, - nozzleHeatingState, + state, nozzleTemperature, nozzlePower, - - frontHeatingState, frontTemperature, frontPower, - - backHeatingState, backTemperature, backPower, - - middleHeatingState, middleTemperature, middlePower, + screwRpm, + pressure, - extruderSetMode, - heatingSetBackTemp, - heatingSetFrontTemp, - heatingSetMiddleTemp, - heatingSetNozzleTemp, - screwSetRegulation, - screwSetTargetPressure, - screwSetTargetRpm, + setExtruderMode, + setBackHeatingTemperature, + setFrontHeatingTemperature, + setMiddleHeatingTemperature, + setNozzleHeatingTemperature, + setInverterRegulation, + setInverterTargetPressure, + setInverterTargetRpm, - uses_rpm, - bar, - rpm, - targetBar, - targetRpm, - inverterState, + isLoading, + isDisabled, } = useExtruder2(); return ( @@ -55,86 +46,88 @@ export function Extruder2ControlPage() { - {inverterState?.fault_occurence == true && ( + {state?.inverter_status_state.fault_occurence == true && ( Inverter encountered an error!! Press the restart button in Config )} - {inverterState?.running == true && - inverterState.fault_occurence == false && ( + {state?.inverter_status_state.running == true && + state.inverter_status_state.fault_occurence == false && ( Running )} - {inverterState?.running == false && - inverterState.fault_occurence == false && ( + {state?.inverter_status_state.running == false && + state.inverter_status_state.fault_occurence == false && ( Healthy )}
@@ -143,21 +136,21 @@ export function Extruder2ControlPage() { label="Rpm" unit="rpm" renderValue={(value) => roundToDecimals(value, 0)} - timeseries={rpm} + timeseries={screwRpm} /> roundToDecimals(value, 0)} - timeseries={bar} + timeseries={pressure} />
- value={mode} + value={state?.mode_state.mode} orientation="vertical" className="grid h-full grid-cols-2 gap-2" options={{ @@ -180,7 +173,9 @@ export function Extruder2ControlPage() { className: "h-full", }, }} - onChange={extruderSetMode} + onChange={setExtruderMode} + disabled={isDisabled} + loading={isLoading} />
diff --git a/electron/src/machines/extruder/extruder2/Extruder2Graph.tsx b/electron/src/machines/extruder/extruder2/Extruder2Graph.tsx index 38de1cd3..6b81758c 100644 --- a/electron/src/machines/extruder/extruder2/Extruder2Graph.tsx +++ b/electron/src/machines/extruder/extruder2/Extruder2Graph.tsx @@ -10,26 +10,17 @@ import { useExtruder2 } from "./useExtruder"; export function Extruder2GraphsPage() { const { - nozzleHeatingState, + state, nozzleTemperature, nozzlePower, - - frontHeatingState, frontTemperature, frontPower, - - backHeatingState, backTemperature, backPower, - - middleHeatingState, middleTemperature, middlePower, - - bar, - rpm, - targetBar, - targetRpm, + pressure, + screwRpm, } = useExtruder2(); const syncHook = useGraphSync(30 * 60 * 1000, "extruder-graphs"); @@ -49,11 +40,11 @@ export function Extruder2GraphsPage() { newData: nozzleTemperature, color: "#ef4444", lines: - nozzleHeatingState?.target_temperature !== undefined + state?.heating_states.nozzle?.target_temperature !== undefined ? [ { type: "target" as const, - value: nozzleHeatingState.target_temperature, + value: state.heating_states.nozzle.target_temperature, color: "#ef4444", show: true, }, @@ -68,11 +59,11 @@ export function Extruder2GraphsPage() { newData: frontTemperature, color: "#f59e0b", lines: - frontHeatingState?.target_temperature !== undefined + state?.heating_states.front?.target_temperature !== undefined ? [ { type: "target" as const, - value: frontHeatingState.target_temperature, + value: state.heating_states.front.target_temperature, color: "#f59e0b", show: true, }, @@ -87,11 +78,11 @@ export function Extruder2GraphsPage() { newData: middleTemperature, color: "#8b5cf6", lines: - middleHeatingState?.target_temperature !== undefined + state?.heating_states.middle?.target_temperature !== undefined ? [ { type: "target" as const, - value: middleHeatingState.target_temperature, + value: state.heating_states.middle.target_temperature, color: "#8b5cf6", show: true, }, @@ -106,11 +97,11 @@ export function Extruder2GraphsPage() { newData: backTemperature, color: "#3b82f6", lines: - backHeatingState?.target_temperature !== undefined + state?.heating_states.back?.target_temperature !== undefined ? [ { type: "target" as const, - value: backHeatingState.target_temperature, + value: state.heating_states.back.target_temperature, color: "#3b82f6", show: true, }, @@ -217,14 +208,14 @@ export function Extruder2GraphsPage() { (null); - - useEffect(() => { - if (!pid2 && pressurePidSettings) { - setPid2(pressurePidSettings); - } - }, [pressurePidSettings, pid2]); - - if (!pid2) { - return
Loading PID settings...
; - } - return ( )} diff --git a/electron/src/machines/extruder/extruder2/extruder2Namespace.ts b/electron/src/machines/extruder/extruder2/extruder2Namespace.ts index 86a96942..15c15a47 100644 --- a/electron/src/machines/extruder/extruder2/extruder2Namespace.ts +++ b/electron/src/machines/extruder/extruder2/extruder2Namespace.ts @@ -8,41 +8,175 @@ import { NamespaceId, createNamespaceHookImplementation, ThrottledStoreUpdater, + handleUnhandledEventError, } from "../../../client/socketioStore"; import { MachineIdentificationUnique } from "@/machines/types"; -import { - createTimeSeries, - TimeSeries, - TimeSeriesValue, -} from "@/lib/timeseries"; +import { createTimeSeries, TimeSeries } from "@/lib/timeseries"; +import { useMemo } from "react"; + +// ========== Event Schema Definitions ========== + +/** + * Machine operation mode enum + */ +export const modeSchema = z.enum(["Standby", "Heat", "Extrude"]); +export type Mode = z.infer; + +/** + * Consolidated live values event schema (60FPS data) + */ +export const liveValuesEventDataSchema = z.object({ + screw_rpm: z.number(), + pressure: z.number(), + nozzle_temperature: z.number(), + front_temperature: z.number(), + back_temperature: z.number(), + middle_temperature: z.number(), + nozzle_power: z.number(), + front_power: z.number(), + back_power: z.number(), + middle_power: z.number(), +}); + +/** + * Rotation state schema + */ +export const rotationStateSchema = z.object({ + forward: z.boolean(), +}); + +/** + * Mode state schema + */ +export const modeStateSchema = z.object({ + mode: modeSchema, +}); + +/** + * Regulation state schema + */ +export const regulationStateSchema = z.object({ + uses_rpm: z.boolean(), +}); + +/** + * Pressure state schema + */ +export const pressureStateSchema = z.object({ + bar: z.number(), + target_bar: z.number(), +}); + +/** + * Screw state schema + */ +export const screwStateSchema = z.object({ + rpm: z.number(), + target_rpm: z.number(), +}); + +/** + * Heating state schema + */ +export const heatingStateSchema = z.object({ + temperature: z.number(), + target_temperature: z.number(), + wiring_error: z.boolean(), +}); + +/** + * Heating states schema + */ +export const heatingStatesSchema = z.object({ + nozzle: heatingStateSchema, + front: heatingStateSchema, + back: heatingStateSchema, + middle: heatingStateSchema, +}); + +/** + * Extruder settings state schema + */ +export const extruderSettingsStateSchema = z.object({ + pressure_limit: z.number(), + pressure_limit_enabled: z.boolean(), +}); + +/** + * Inverter status state schema + */ +export const inverterStatusStateSchema = z.object({ + running: z.boolean(), + forward_running: z.boolean(), + reverse_running: z.boolean(), + up_to_frequency: z.boolean(), + overload_warning: z.boolean(), + no_function: z.boolean(), + output_frequency_detection: z.boolean(), + abc_fault: z.boolean(), + fault_occurence: z.boolean(), +}); + +/** + * PID settings schema + */ +export const pidSettingsSchema = z.object({ + temperature: z.object({ + ki: z.number(), + kp: z.number(), + kd: z.number(), + }), + pressure: z.object({ + ki: z.number(), + kp: z.number(), + kd: z.number(), + }), +}); + +/** + * Consolidated state event schema (state changes only) + */ +export const stateEventDataSchema = z.object({ + rotation_state: rotationStateSchema, + mode_state: modeStateSchema, + regulation_state: regulationStateSchema, + pressure_state: pressureStateSchema, + screw_state: screwStateSchema, + heating_states: heatingStatesSchema, + extruder_settings_state: extruderSettingsStateSchema, + inverter_status_state: inverterStatusStateSchema, + pid_settings: pidSettingsSchema, +}); + +// ========== Event Schemas with Wrappers ========== + +export const liveValuesEventSchema = eventSchema(liveValuesEventDataSchema); +export const stateEventSchema = eventSchema(stateEventDataSchema); + +// ========== Type Inferences ========== + +export type StateEvent = z.infer; + +// Additional exports for backward compatibility +export const SetRegulationSchema = z.object({ + uses_rpm: z.boolean(), +}); + +export const mode = z.object({ + mode: modeSchema, +}); export type Extruder2NamespaceStore = { - modeState: ModeStateEvent | null; - inverterState: InverterStatusEvent | null; - rotationState: InverterRotationEvent | null; - - heatingNozzleState: HeatingStateEvent | null; - heatingFrontState: HeatingStateEvent | null; - heatingBackState: HeatingStateEvent | null; - heatingMiddleState: HeatingStateEvent | null; - - motorRpmState: MotorScrewStateEvent | null; - motorBarState: MotorPressureStateEvent | null; - motorRegulationState: MotorRegulationStateEvent | null; - - extruderSettingsState: ExtruderSettingsStateEvent | null; - - pressurePidSettings: PidSettingsEvent | null; - temperaturePidSettings: PidSettingsEvent | null; - // Metric Events (cached for 1 hour ) - rpm: TimeSeries; - bar: TimeSeries; + // Single state event from server + state: StateEvent | null; + // Time series data for live values + screwRpm: TimeSeries; + pressure: TimeSeries; nozzleTemperature: TimeSeries; frontTemperature: TimeSeries; backTemperature: TimeSeries; middleTemperature: TimeSeries; - nozzlePower: TimeSeries; frontPower: TimeSeries; middlePower: TimeSeries; @@ -55,6 +189,20 @@ const ONE_SECOND = 1000; const FIVE_SECOND = 5 * ONE_SECOND; const ONE_HOUR = 60 * 60 * ONE_SECOND; +const { initialTimeSeries: screwRpm, insert: addScrewRpm } = createTimeSeries( + TWENTY_MILLISECOND, + ONE_SECOND, + FIVE_SECOND, + ONE_HOUR, +); + +const { initialTimeSeries: pressure, insert: addPressure } = createTimeSeries( + TWENTY_MILLISECOND, + ONE_SECOND, + FIVE_SECOND, + ONE_HOUR, +); + const { initialTimeSeries: backTemperature, insert: addBackTemperature } = createTimeSeries(TWENTY_MILLISECOND, ONE_SECOND, FIVE_SECOND, ONE_HOUR); @@ -83,20 +231,6 @@ const { initialTimeSeries: backPower, insert: addBackPower } = createTimeSeries( ONE_HOUR, ); -const { initialTimeSeries: rpm, insert: addRpm } = createTimeSeries( - TWENTY_MILLISECOND, - ONE_SECOND, - FIVE_SECOND, - ONE_HOUR, -); - -const { initialTimeSeries: bar, insert: addBar } = createTimeSeries( - TWENTY_MILLISECOND, - ONE_SECOND, - FIVE_SECOND, - ONE_HOUR, -); - export function extruder2MessageHandler( store: StoreApi, throttledUpdater: ThrottledStoreUpdater, @@ -112,169 +246,65 @@ export function extruder2MessageHandler( }; try { - if (eventName == "PressurePidSettingsEvent") { - updateStore((state) => ({ - ...state, - pressurePidSettings: pidSettingsEventSchema.parse(event), - })); - } - - if (eventName == "ExtruderSettingsStateEvent") { - updateStore((state) => ({ - ...state, - extruderSettingsState: extruderSettingsStateEventSchema.parse(event), - })); - } - - if (eventName == "InverterStatusEvent") { - console.log(eventName); - updateStore((state) => ({ - ...state, - inverterState: event as InverterStatusEvent, - })); - } else if (eventName == "RotationStateEvent") { - updateStore((state) => ({ - ...state, - rotationState: event as InverterRotationEvent, - })); - } else if (eventName == "ModeStateEvent") { - updateStore((state) => ({ - ...state, - modeState: event as ModeStateEvent, - })); - } else if (eventName == "FrontHeatingStateEvent") { - const heatingEvent = event as HeatingStateEvent; - const timeseriesValue: TimeSeriesValue = { - value: heatingEvent.data.temperature, - timestamp: event.ts, - }; + if (eventName === "StateEvent") { + const stateEvent = stateEventSchema.parse(event); + console.log("StateEvent", stateEvent); updateStore((state) => ({ ...state, - heatingFrontState: heatingEvent, - frontTemperature: addFrontTemperature( - state.frontTemperature, - timeseriesValue, - ), + state: stateEvent, })); - } else if (eventName == "NozzleHeatingStateEvent") { - const heatingEvent = event as HeatingStateEvent; - const timeseriesValue: TimeSeriesValue = { - value: heatingEvent.data.temperature, - timestamp: event.ts, - }; + } else if (eventName === "LiveValuesEvent") { + const liveValuesEvent = liveValuesEventSchema.parse(event); + console.log("LiveValuesEvent", liveValuesEvent); + + const timestamp = event.ts; updateStore((state) => ({ ...state, - heatingNozzleState: heatingEvent, - nozzleTemperature: addNozzleTemperature( - state.nozzleTemperature, - timeseriesValue, - ), - })); - } else if (eventName == "BackHeatingStateEvent") { - const heatingEvent = event as HeatingStateEvent; - const timeseriesValue: TimeSeriesValue = { - value: heatingEvent.data.temperature, - timestamp: event.ts, - }; - - updateStore((state) => ({ - ...state, - heatingBackState: heatingEvent, - backTemperature: addBackTemperature( - state.backTemperature, - timeseriesValue, - ), - })); - } else if (eventName == "MiddleHeatingStateEvent") { - const heatingEvent = event as HeatingStateEvent; - const timeseriesValue: TimeSeriesValue = { - value: heatingEvent.data.temperature, - timestamp: event.ts, - }; - - updateStore((state) => ({ - ...state, - heatingMiddleState: heatingEvent, - middleTemperature: addMiddleTemperature( - state.middleTemperature, - timeseriesValue, - ), - })); - } else if (eventName == "NozzleHeatingPowerEvent") { - const parsed = heatingPowerEventSchema.parse(event); - const timeseriesValue: TimeSeriesValue = { - value: parsed.data.wattage, - timestamp: event.ts, - }; - - updateStore((state) => ({ - ...state, - nozzlePower: addNozzlePower(state.nozzlePower, timeseriesValue), - })); - } else if (eventName == "FrontHeatingPowerEvent") { - const parsed = heatingPowerEventSchema.parse(event); - const timeseriesValue: TimeSeriesValue = { - value: parsed.data.wattage, - timestamp: event.ts, - }; - - updateStore((state) => ({ - ...state, - frontPower: addFrontPower(state.frontPower, timeseriesValue), - })); - } else if (eventName == "MiddleHeatingPowerEvent") { - const parsed = heatingPowerEventSchema.parse(event); - const timeseriesValue: TimeSeriesValue = { - value: parsed.data.wattage, - timestamp: event.ts, - }; - - updateStore((state) => ({ - ...state, - middlePower: addMiddlePower(state.middlePower, timeseriesValue), - })); - } else if (eventName == "BackHeatingPowerEvent") { - const parsed = heatingPowerEventSchema.parse(event); - const timeseriesValue: TimeSeriesValue = { - value: parsed.data.wattage, - timestamp: event.ts, - }; - - updateStore((state) => ({ - ...state, - backPower: addBackPower(state.backPower, timeseriesValue), - })); - } else if (eventName == "RegulationStateEvent") { - updateStore((state) => ({ - ...state, - motorRegulationState: event as MotorRegulationStateEvent, - })); - } else if (eventName == "PressureStateEvent") { - const pressureEvent = event as MotorPressureStateEvent; - const timeseriesValue: TimeSeriesValue = { - value: pressureEvent.data.bar, - timestamp: event.ts, - }; - - updateStore((state) => ({ - ...state, - motorBarState: pressureEvent, - bar: addBar(state.bar, timeseriesValue), - })); - } else if (eventName == "ScrewStateEvent") { - const screwEvent = event as MotorScrewStateEvent; - const timeseriesValue: TimeSeriesValue = { - value: screwEvent.data.rpm, - timestamp: event.ts, - }; - - updateStore((state) => ({ - ...state, - motorRpmState: screwEvent, - rpm: addRpm(state.rpm, timeseriesValue), + screwRpm: addScrewRpm(state.screwRpm, { + value: liveValuesEvent.data.screw_rpm, + timestamp, + }), + pressure: addPressure(state.pressure, { + value: liveValuesEvent.data.pressure, + timestamp, + }), + nozzleTemperature: addNozzleTemperature(state.nozzleTemperature, { + value: liveValuesEvent.data.nozzle_temperature, + timestamp, + }), + frontTemperature: addFrontTemperature(state.frontTemperature, { + value: liveValuesEvent.data.front_temperature, + timestamp, + }), + backTemperature: addBackTemperature(state.backTemperature, { + value: liveValuesEvent.data.back_temperature, + timestamp, + }), + middleTemperature: addMiddleTemperature(state.middleTemperature, { + value: liveValuesEvent.data.middle_temperature, + timestamp, + }), + nozzlePower: addNozzlePower(state.nozzlePower, { + value: liveValuesEvent.data.nozzle_power, + timestamp, + }), + frontPower: addFrontPower(state.frontPower, { + value: liveValuesEvent.data.front_power, + timestamp, + }), + middlePower: addMiddlePower(state.middlePower, { + value: liveValuesEvent.data.middle_power, + timestamp, + }), + backPower: addBackPower(state.backPower, { + value: liveValuesEvent.data.back_power, + timestamp, + }), })); + } else { + handleUnhandledEventError(eventName); } } catch (error) { console.error(`Unexpected error processing ${eventName} event:`, error); @@ -287,26 +317,9 @@ export const createExtruder2NamespaceStore = (): StoreApi => create(() => { return { - modeState: null, - inverterState: null, - rotationState: null, - - heatingNozzleState: null, - heatingFrontState: null, - heatingBackState: null, - heatingMiddleState: null, - - motorRpmState: null, - motorRegulationState: null, - motorBarState: null, - extruderSettingsState: null, - - pressurePidSettings: null, - temperaturePidSettings: null, - - rpm, - bar, - + state: null, + screwRpm, + pressure, nozzleTemperature, frontTemperature, backTemperature, @@ -328,164 +341,14 @@ export function useExtruder2Namespace( machine_identification_unique: MachineIdentificationUnique, ): Extruder2NamespaceStore { // Generate namespace ID from validated machine ID - const namespaceId: NamespaceId = { - type: "machine", - machine_identification_unique, - }; + const namespaceId = useMemo( + () => ({ + type: "machine", + machine_identification_unique, + }), + [machine_identification_unique], + ); // Use the implementation with validated namespace ID return useExtruder2NamespaceImplementation(namespaceId); } - -export const modeSchema = z.enum(["Standby", "Heat", "Extrude"]); -export const mode = z.object({ - mode: modeSchema, -}); -export const heatingTypeSchema = z.enum(["front", "back", "middle"]); - -export const SetRegulationSchema = z.object({ - uses_rpm: z.boolean(), -}); - -// Data Schemas - -export const inverterStatusEventDataSchema = z.object({ - // RUN (Inverter running) - running: z.boolean(), - // Forward running motor spins forward - forward_running: z.boolean(), - // Reverse running motor spins backwards - reverse_running: z.boolean(), - // Up to frequency, SU not completely sure what its for - up_to_frequency: z.boolean(), - // overload warning OL - overload_warning: z.boolean(), - // No function, its described that way in the datasheet - no_function: z.boolean(), - // FU Output Frequency Detection - output_frequency_detection: z.boolean(), - // ABC (Fault) - abc_fault: z.boolean(), - // is True when a fault occured - fault_occurence: z.boolean(), -}); - -export const modeStateEventDataSchema = z.object({ - mode: modeSchema, -}); - -export const inverterRotationEventDataSchema = z.object({ - forward: z.boolean(), -}); - -export const heatingStateDataSchema = z.object({ - temperature: z.number(), - target_temperature: z.number(), - wiring_error: z.boolean(), -}); - -export const heatingTargetTemperatureDataSchema = z.object({ - target_temperature: z.number(), -}); - -export const motorScrewStateEventDataSchema = z.object({ - rpm: z.number(), - target_rpm: z.number(), -}); - -export const motorBarStateEventDataSchema = z.object({ - bar: z.number(), - target_bar: z.number(), -}); - -export const motorRegulationEventDataSchema = z.object({ - uses_rpm: z.boolean(), -}); - -export const extruderPressureLimitDataSchema = z.object({ - pressure_limit: z.number(), -}); - -export const extruderPressureLimitEnabledDataSchema = z.object({ - pressure_limit_enabled: z.boolean(), -}); - -export const extruderSettingsStateEventDataSchema = z.object({ - pressure_limit: z.number(), - pressure_limit_enabled: z.boolean(), -}); - -export const pidSettingsEventDataSchema = z.object({ - ki: z.number(), - kd: z.number(), - kp: z.number(), -}); - -// Event Schemas -export const heatingTargetEventSchema = eventSchema( - heatingTargetTemperatureDataSchema, -); - -export const motorScrewStateEventSchema = eventSchema( - motorScrewStateEventDataSchema, -); - -export const motorPressureStateEventSchema = eventSchema( - motorBarStateEventDataSchema, -); - -export const inverterRotationEventSchema = eventSchema( - inverterRotationEventDataSchema, -); - -export const motorRegulationEventSchema = eventSchema( - motorRegulationEventDataSchema, -); -export const heatingStateEventSchema = eventSchema(heatingStateDataSchema); -export const modeStateEventSchema = eventSchema(modeStateEventDataSchema); - -export const extruderSettingsStateEventSchema = eventSchema( - extruderSettingsStateEventDataSchema, -); - -export const pidSettingsEventSchema = eventSchema(pidSettingsEventDataSchema); - -export const heatingPowerEventDataSchema = z.object({ - wattage: z.number(), -}); - -export const heatingPowerEventSchema = eventSchema(heatingPowerEventDataSchema); - -export const inverterStatusEventSchema = eventSchema( - inverterStatusEventDataSchema, -); - -// type defs -export type MotorScrewStateEvent = z.infer; -export type MotorPressureStateEvent = z.infer< - typeof motorPressureStateEventSchema ->; -export type InverterStatusEvent = z.infer; -export type InverterRotationEvent = z.infer; - -export type MotorRegulationStateEvent = z.infer< - typeof motorRegulationEventSchema ->; -export type ModeStateEvent = z.infer; -export type HeatingPowerEvent = z.infer; -export type HeatingStateEvent = z.infer; - -export type HeatingType = z.infer; -export type Heating = z.infer; - -export type MotorPressure = z.infer; -export type MotorRpm = z.infer; -export type Mode = z.infer; -export type InverterStatus = z.infer; - -export type PidSettings = z.infer; -export type PidSettingsEvent = z.infer; - -export type ExtruderSettingsStateEvent = z.infer< - typeof extruderSettingsStateEventSchema ->; diff --git a/electron/src/machines/extruder/extruder2/useExtruder.ts b/electron/src/machines/extruder/extruder2/useExtruder.ts index 3890c078..3c3f82d4 100644 --- a/electron/src/machines/extruder/extruder2/useExtruder.ts +++ b/electron/src/machines/extruder/extruder2/useExtruder.ts @@ -5,22 +5,16 @@ import { MachineIdentificationUnique } from "@/machines/types"; import { extruder2 } from "@/machines/properties"; import { extruder2Route } from "@/routes/routes"; import { z } from "zod"; -import { - Heating, - InverterStatus, - Mode, - useExtruder2Namespace, - PidSettings, -} from "./extruder2Namespace"; +import { StateEvent, Mode, useExtruder2Namespace } from "./extruder2Namespace"; import { useEffect, useMemo } from "react"; -import { TimeSeries } from "@/lib/timeseries"; +import { produce } from "immer"; export function useExtruder2() { const { serial: serialString } = extruder2Route.useParams(); // Memoize the machine identification to keep it stable between renders const machineIdentification: MachineIdentificationUnique = useMemo(() => { - const serial = parseInt(serialString); // Use 0 as fallback if NaN + const serial = parseInt(serialString); if (isNaN(serial)) { toastError( @@ -41,529 +35,360 @@ export function useExtruder2() { machine_identification: extruder2.machine_identification, serial, }; - }, [serialString]); // Only recreate when serialString changes + }, [serialString]); - const inverter = useInverter(machineIdentification); - const mode = useMode(machineIdentification); - const motor = useMotor(machineIdentification); - const heating = useHeatingTemperature(machineIdentification); - const heatingPower = useHeatingPower(machineIdentification); - const settings = useSettings(machineIdentification); - const pidSettings = usePidSettings(machineIdentification); - - return { - ...inverter, - ...mode, - ...motor, - ...heating, - ...settings, - ...heatingPower, - ...pidSettings, - }; -} - -export function useHeatingPower( - machine_identification_unique: MachineIdentificationUnique, -): { - nozzlePower: TimeSeries; - frontPower: TimeSeries; - middlePower: TimeSeries; - backPower: TimeSeries; -} { - const { nozzlePower, frontPower, middlePower, backPower } = - useExtruder2Namespace(machine_identification_unique); - - return { nozzlePower, frontPower, middlePower, backPower }; -} - -export function useSettings( - machine_identification_unique: MachineIdentificationUnique, -): { - extruderSetPressureLimit: (pressure_limit: number) => void; - extruderSetPressureLimitIsEnabled: ( - pressure_limit_is_enabled: boolean, - ) => void; - pressureLimitState: number | undefined; - pressureLimitEnabledState: boolean | undefined; -} { - const pressureLimitState = useStateOptimistic(); - const pressureLimitEnabledState = useStateOptimistic(); - // Define schemas - const pressureLimitSchema = z.object({ - ExtruderSetPressureLimit: z.number(), - }); - const pressureLimitEnabledSchema = z.object({ - ExtruderSetPressureLimitIsEnabled: z.boolean(), - }); - - // Create mutation hooks - const { request: pressureLimit } = useMachineMutation(pressureLimitSchema); - const { request: pressureLimitIsEnabled } = useMachineMutation( - pressureLimitEnabledSchema, - ); - - const { extruderSettingsState } = useExtruder2Namespace( - machine_identification_unique, - ); - - // Set pressure limit value - const extruderSetPressureLimit = async (pressure: number) => { - pressureLimitState.setOptimistic(pressure); - pressureLimit({ - machine_identification_unique, - data: { ExtruderSetPressureLimit: pressure }, - }); - }; - - // Enable/disable pressure limit - const extruderSetPressureLimitIsEnabled = (enabled: boolean) => { - pressureLimitEnabledState.setOptimistic(enabled); - pressureLimitIsEnabled({ - machine_identification_unique, - data: { ExtruderSetPressureLimitIsEnabled: enabled }, - }); - }; - - useEffect(() => { - if (extruderSettingsState?.data) { - pressureLimitState.setReal(extruderSettingsState.data.pressure_limit); - pressureLimitEnabledState.setReal( - extruderSettingsState.data.pressure_limit, - ); - } - }, [ - extruderSettingsState?.data.pressure_limit, - extruderSettingsState?.data.pressure_limit_enabled, - ]); - - return { - extruderSetPressureLimit, - extruderSetPressureLimitIsEnabled, - pressureLimitState: extruderSettingsState?.data.pressure_limit, - pressureLimitEnabledState: - extruderSettingsState?.data.pressure_limit_enabled, - }; -} - -export function useInverter( - machine_identification_unique: MachineIdentificationUnique, -): { - inverterSetRotation: (forward: boolean) => void; - rotationState: boolean | undefined; - inverterReset: () => void; - inverterState: InverterStatus | undefined; -} { - const state = useStateOptimistic(); - - const schema = z.object({ InverterRotationSetDirection: z.boolean() }); - const { request: requestRotation } = useMachineMutation(schema); - const inverterSetRotation = async (forward: boolean) => { - state.setOptimistic(forward); - requestRotation({ - machine_identification_unique, - data: { InverterRotationSetDirection: forward }, - }); - }; - - const inverterSchema = z.object({ - InverterReset: z.boolean(), // this represents a zero-argument tuple variant - }); - - const { request: requestReset } = useMachineMutation(inverterSchema); - const inverterReset = async () => { - requestReset({ - machine_identification_unique, - data: { InverterReset: true }, // key is the enum variant, value is empty tuple - }); - }; - - const { rotationState, inverterState } = useExtruder2Namespace( - machine_identification_unique, - ); - - useEffect(() => { - if (rotationState?.data) { - state.setReal(rotationState.data.forward); - } - }, [rotationState?.data.forward]); - - return { - inverterSetRotation, - rotationState: rotationState?.data.forward, - inverterReset, - inverterState: inverterState?.data, - }; -} - -export function useMode( - machine_identification_unique: MachineIdentificationUnique, -): { - mode: Mode | undefined; - extruderSetMode: (value: Mode) => void; - modeIsLoading: boolean; - modeIsDisabled: boolean; -} { - const state = useStateOptimistic(); - - // Write path - const schema = z.object({ - ExtruderSetMode: z.enum(["Heat", "Extrude", "Standby"]), - }); - - const { request } = useMachineMutation(schema); - - const extruderSetMode = async (value: Mode) => { - state.setOptimistic(value); - request({ - machine_identification_unique, - data: { ExtruderSetMode: value }, - }) - .then((response) => { - if (!response.success) state.resetToReal(); - }) - .catch(() => state.resetToReal()); - }; - - // Read path - const { modeState } = useExtruder2Namespace(machine_identification_unique); - useEffect(() => { - if (modeState?.data) { - state.setReal(modeState.data.mode); - } - }, [modeState?.data.mode]); - - return { - mode: state.value, - extruderSetMode, - modeIsLoading: state.isOptimistic || !state.isInitialized, - modeIsDisabled: state.isOptimistic || !state.isInitialized, - }; -} - -export function useMotor( - machine_identification_unique: MachineIdentificationUnique, -): { - uses_rpm: boolean | undefined; - rpm: TimeSeries; - targetRpm: number | undefined; - bar: TimeSeries; - targetBar: number | undefined; - screwSetTargetRpm: (rpm: number) => void; - screwSetRegulation: (usesRpm: boolean) => void; - screwSetTargetPressure: (bar: number) => void; -} { - const SetTargetRpmSchema = z.object({ - InverterSetTargetRpm: z.number(), - }); - - const SetRegulationSchema = z.object({ - InverterSetRegulation: z.boolean(), - }); - - const SetTargetPressureSchema = z.object({ - InverterSetTargetPressure: z.number(), - }); - - const { motorRpmState, motorBarState, motorRegulationState, rpm, bar } = - useExtruder2Namespace(machine_identification_unique); - - const rpmState = useStateOptimistic(); - const rpmTargetState = useStateOptimistic(); - - const regulationState = useStateOptimistic(); - const { request: regulationRequest } = - useMachineMutation(SetRegulationSchema); - - const screwSetRegulation = async (value: boolean) => { - regulationState.setOptimistic(value); - regulationRequest({ - machine_identification_unique, - data: { InverterSetRegulation: value }, - }) - .then((response) => { - if (!response.success) regulationState.resetToReal(); - }) - .catch(() => regulationState.resetToReal()); - }; - - const { request: reqestTargetRpm } = useMachineMutation(SetTargetRpmSchema); - const screwSetTargetRpm = async (value: number) => { - rpmTargetState.setOptimistic(value); - reqestTargetRpm({ - machine_identification_unique, - data: { InverterSetTargetRpm: value }, - }) - .then((response) => { - if (!response.success) rpmTargetState.resetToReal(); - }) - .catch(() => rpmTargetState.resetToReal()); - }; - - const pressureState = useStateOptimistic(); - const targetPressureState = useStateOptimistic(); - - const { request: targetPressureRequest } = useMachineMutation( - SetTargetPressureSchema, - ); - - const screwSetTargetPressure = async (value: number) => { - targetPressureState.setOptimistic(value); - targetPressureRequest({ - machine_identification_unique, - data: { InverterSetTargetPressure: value }, - }) - .then((response) => { - if (!response.success) targetPressureState.resetToReal(); - }) - .catch(() => targetPressureState.resetToReal()); - }; - - useEffect(() => { - if (motorRpmState?.data) { - rpmState.setReal(motorRpmState.data.rpm); - rpmTargetState.setReal(motorRpmState.data.target_rpm); - } - - if (motorBarState?.data) { - pressureState.setReal(motorBarState.data.bar); - targetPressureState.setReal(motorBarState.data.target_bar); - } - - if (motorRegulationState?.data) { - regulationState.setReal(motorRegulationState.data.uses_rpm); - } - }, [ - motorRpmState?.data.rpm, - motorRpmState?.data.target_rpm, - motorBarState?.data.bar, - motorBarState?.data.target_bar, - motorRegulationState?.data.uses_rpm, - ]); - - return { - rpm: rpm, - uses_rpm: regulationState.value, - targetRpm: rpmTargetState.value, - targetBar: targetPressureState.value, - bar: bar, - - screwSetTargetRpm, - screwSetTargetPressure, - screwSetRegulation, - }; -} - -export function usePidSettings( - machine_identification_unique: MachineIdentificationUnique, -): { - pressurePidSettings: PidSettings | undefined; - setPressurePid: (settings: PidSettings) => void; -} { - const { pressurePidSettings } = useExtruder2Namespace( - machine_identification_unique, - ); - - const pressurePidSettingsState = useStateOptimistic(); - - const SetPressurePidSchema = z.object({ - SetPressurePidSettings: z.object({ - ki: z.number(), - kp: z.number(), - kd: z.number(), - }), - }); - - const { request: PressurePidSettingsRequest } = - useMachineMutation(SetPressurePidSchema); - - const setPressurePid = async (value: PidSettings) => { - pressurePidSettingsState.setOptimistic(value); - PressurePidSettingsRequest({ - machine_identification_unique, - data: { SetPressurePidSettings: value }, - }) - .then((response) => { - if (!response.success) pressurePidSettingsState.resetToReal(); - }) - .catch(() => pressurePidSettingsState.resetToReal()); - }; - - useEffect(() => { - if (pressurePidSettings?.data) { - pressurePidSettingsState.setReal(pressurePidSettings?.data); - } - }); - - return { - pressurePidSettings: pressurePidSettingsState.value, - setPressurePid, - }; -} - -export function useHeatingTemperature( - machine_identification_unique: MachineIdentificationUnique, -): { - heatingSetNozzleTemp: (value: number) => void; - heatingSetFrontTemp: (value: number) => void; - heatingSetBackTemp: (value: number) => void; - heatingSetMiddleTemp: (value: number) => void; - - nozzleHeatingTarget: number | undefined; - frontHeatingTarget: number | undefined; - backHeatingTarget: number | undefined; - middleHeatingTarget: number | undefined; - - nozzleHeatingState: Heating | undefined; - frontHeatingState: Heating | undefined; - backHeatingState: Heating | undefined; - middleHeatingState: Heating | undefined; - - nozzleTemperature: TimeSeries; - frontTemperature: TimeSeries; - backTemperature: TimeSeries; - middleTemperature: TimeSeries; -} { - const nozzleHeatingTargetState = useStateOptimistic(); - const frontHeatingTargetState = useStateOptimistic(); - const backHeatingTargetState = useStateOptimistic(); - const middleHeatingTargetState = useStateOptimistic(); - - const SetNozzleHeatingSchema = z.object({ - NozzleSetHeatingTemperature: z.number(), - }); - - const SetFrontHeatingSchema = z.object({ - FrontHeatingSetTargetTemperature: z.number(), - }); - - const SetBackHeatingSchema = z.object({ - BackHeatingSetTargetTemperature: z.number(), - }); - - const SetMiddleHeatingSchema = z.object({ - MiddleSetHeatingTemperature: z.number(), - }); - - const { request: HeatingNozzleRequest } = useMachineMutation( - SetNozzleHeatingSchema, - ); - - const heatingSetNozzleTemp = async (value: number) => { - frontHeatingTargetState.setOptimistic(value); - HeatingNozzleRequest({ - machine_identification_unique, - data: { NozzleSetHeatingTemperature: value }, - }) - .then((response) => { - if (!response.success) nozzleHeatingTargetState.resetToReal(); - }) - .catch(() => nozzleHeatingTargetState.resetToReal()); - }; - - const { request: HeatiingFrontRequest } = useMachineMutation( - SetFrontHeatingSchema, - ); - - const heatingSetFrontTemp = async (value: number) => { - frontHeatingTargetState.setOptimistic(value); - HeatiingFrontRequest({ - machine_identification_unique, - data: { FrontHeatingSetTargetTemperature: value }, - }) - .then((response) => { - if (!response.success) frontHeatingTargetState.resetToReal(); - }) - .catch(() => frontHeatingTargetState.resetToReal()); - }; - - const { request: HeatingBackRequest } = - useMachineMutation(SetBackHeatingSchema); - - const heatingSetBackTemp = async (value: number) => { - backHeatingTargetState.setOptimistic(value); - HeatingBackRequest({ - machine_identification_unique, - data: { BackHeatingSetTargetTemperature: value }, - }) - .then((response) => { - if (!response.success) backHeatingTargetState.resetToReal(); - }) - .catch(() => backHeatingTargetState.resetToReal()); - }; - - const { request: HeatingMiddleRequest } = useMachineMutation( - SetMiddleHeatingSchema, - ); - - const heatingSetMiddleTemp = async (value: number) => { - middleHeatingTargetState.setOptimistic(value); - HeatingMiddleRequest({ - machine_identification_unique, - data: { MiddleSetHeatingTemperature: value }, - }) - .then((response) => { - if (!response.success) middleHeatingTargetState.resetToReal(); - }) - .catch(() => middleHeatingTargetState.resetToReal()); - }; - - // Read path + // Get consolidated state and live values from namespace const { - heatingFrontState, - heatingBackState, - heatingMiddleState, - heatingNozzleState, + state, + screwRpm, + pressure, + nozzleTemperature, frontTemperature, backTemperature, middleTemperature, - nozzleTemperature, - } = useExtruder2Namespace(machine_identification_unique); + nozzlePower, + frontPower, + middlePower, + backPower, + } = useExtruder2Namespace(machineIdentification); + // Single optimistic state for all state management + const stateOptimistic = useStateOptimistic(); + + // Update optimistic state when real state changes useEffect(() => { - if (heatingFrontState?.data) { - frontHeatingTargetState.setReal( - heatingFrontState.data.target_temperature, - ); + if (state) { + stateOptimistic.setReal(state); } - if (heatingBackState?.data) { - backHeatingTargetState.setReal(heatingBackState.data.target_temperature); + }, [state, stateOptimistic]); + + // Helper function for optimistic updates using produce + const updateStateOptimistically = ( + producer: (current: StateEvent) => void, + serverRequest: () => void, + ) => { + const currentState = stateOptimistic.value; + if (currentState) { + stateOptimistic.setOptimistic(produce(currentState, producer)); } - if (heatingMiddleState?.data) { - middleHeatingTargetState.setReal( - heatingMiddleState.data.target_temperature, - ); - } - if (heatingNozzleState?.data) { - nozzleHeatingTargetState.setReal( - heatingNozzleState.data.target_temperature, - ); - } - }, [ - frontHeatingTargetState, - backHeatingTargetState, - middleHeatingTargetState, - nozzleHeatingTargetState, - ]); + serverRequest(); + }; + + // Action functions with verb-first names + const setInverterRotationDirection = (forward: boolean) => { + updateStateOptimistically( + (current) => { + current.data.rotation_state.forward = forward; + }, + () => + requestInverterRotationDirection({ + machine_identification_unique: machineIdentification, + data: { SetInverterRotationDirection: forward }, + }), + ); + }; + + const setExtruderMode = (mode: Mode) => { + updateStateOptimistically( + (current) => { + current.data.mode_state.mode = mode; + }, + () => + requestExtruderMode({ + machine_identification_unique: machineIdentification, + data: { SetExtruderMode: mode }, + }), + ); + }; + + const setInverterRegulation = (usesRpm: boolean) => { + updateStateOptimistically( + (current) => { + current.data.regulation_state.uses_rpm = usesRpm; + }, + () => + requestInverterRegulation({ + machine_identification_unique: machineIdentification, + data: { SetInverterRegulation: usesRpm }, + }), + ); + }; + + const setInverterTargetRpm = (rpm: number) => { + updateStateOptimistically( + (current) => { + current.data.screw_state.target_rpm = rpm; + }, + () => + requestInverterTargetRpm({ + machine_identification_unique: machineIdentification, + data: { SetInverterTargetRpm: rpm }, + }), + ); + }; + + const setInverterTargetPressure = (pressure: number) => { + updateStateOptimistically( + (current) => { + current.data.pressure_state.target_bar = pressure; + }, + () => + requestInverterTargetPressure({ + machine_identification_unique: machineIdentification, + data: { SetInverterTargetPressure: pressure }, + }), + ); + }; + + const setNozzleHeatingTemperature = (temperature: number) => { + updateStateOptimistically( + (current) => { + current.data.heating_states.nozzle.target_temperature = temperature; + }, + () => + requestNozzleHeatingTemperature({ + machine_identification_unique: machineIdentification, + data: { SetNozzleHeatingTemperature: temperature }, + }), + ); + }; + + const setFrontHeatingTemperature = (temperature: number) => { + updateStateOptimistically( + (current) => { + current.data.heating_states.front.target_temperature = temperature; + }, + () => + requestFrontHeatingTemperature({ + machine_identification_unique: machineIdentification, + data: { SetFrontHeatingTargetTemperature: temperature }, + }), + ); + }; + + const setBackHeatingTemperature = (temperature: number) => { + updateStateOptimistically( + (current) => { + current.data.heating_states.back.target_temperature = temperature; + }, + () => + requestBackHeatingTemperature({ + machine_identification_unique: machineIdentification, + data: { SetBackHeatingTargetTemperature: temperature }, + }), + ); + }; + + const setMiddleHeatingTemperature = (temperature: number) => { + updateStateOptimistically( + (current) => { + current.data.heating_states.middle.target_temperature = temperature; + }, + () => + requestMiddleHeatingTemperature({ + machine_identification_unique: machineIdentification, + data: { SetMiddleHeatingTemperature: temperature }, + }), + ); + }; + + const setExtruderPressureLimit = (pressureLimit: number) => { + updateStateOptimistically( + (current) => { + current.data.extruder_settings_state.pressure_limit = pressureLimit; + }, + () => + requestExtruderPressureLimit({ + machine_identification_unique: machineIdentification, + data: { SetExtruderPressureLimit: pressureLimit }, + }), + ); + }; + + const setExtruderPressureLimitEnabled = (enabled: boolean) => { + updateStateOptimistically( + (current) => { + current.data.extruder_settings_state.pressure_limit_enabled = enabled; + }, + () => + requestExtruderPressureLimitEnabled({ + machine_identification_unique: machineIdentification, + data: { SetExtruderPressureLimitIsEnabled: enabled }, + }), + ); + }; + + const setPressurePidKp = (kp: number) => { + updateStateOptimistically( + (current) => { + current.data.pid_settings.pressure.kp = kp; + }, + () => { + const currentState = stateOptimistic.value; + if (currentState) { + const settings = produce( + currentState.data.pid_settings.pressure, + (draft) => { + draft.kp = kp; + }, + ); + requestPressurePidSettings({ + machine_identification_unique: machineIdentification, + data: { SetPressurePidSettings: settings }, + }); + } + }, + ); + }; + + const setPressurePidKi = (ki: number) => { + updateStateOptimistically( + (current) => { + current.data.pid_settings.pressure.ki = ki; + }, + () => { + const currentState = stateOptimistic.value; + if (currentState) { + const settings = produce( + currentState.data.pid_settings.pressure, + (draft) => { + draft.ki = ki; + }, + ); + requestPressurePidSettings({ + machine_identification_unique: machineIdentification, + data: { SetPressurePidSettings: settings }, + }); + } + }, + ); + }; + + const setPressurePidKd = (kd: number) => { + updateStateOptimistically( + (current) => { + current.data.pid_settings.pressure.kd = kd; + }, + () => { + const currentState = stateOptimistic.value; + if (currentState) { + const settings = produce( + currentState.data.pid_settings.pressure, + (draft) => { + draft.kd = kd; + }, + ); + requestPressurePidSettings({ + machine_identification_unique: machineIdentification, + data: { SetPressurePidSettings: settings }, + }); + } + }, + ); + }; + + const resetInverter = () => { + // No optimistic update needed for reset + requestResetInverter({ + machine_identification_unique: machineIdentification, + data: { ResetInverter: true }, + }); + }; + + // Mutation hooks + const { request: requestInverterRotationDirection } = useMachineMutation( + z.object({ SetInverterRotationDirection: z.boolean() }), + ); + + const { request: requestExtruderMode } = useMachineMutation( + z.object({ SetExtruderMode: z.enum(["Heat", "Extrude", "Standby"]) }), + ); + + const { request: requestInverterRegulation } = useMachineMutation( + z.object({ SetInverterRegulation: z.boolean() }), + ); + + const { request: requestInverterTargetRpm } = useMachineMutation( + z.object({ SetInverterTargetRpm: z.number() }), + ); + + const { request: requestInverterTargetPressure } = useMachineMutation( + z.object({ SetInverterTargetPressure: z.number() }), + ); + + const { request: requestNozzleHeatingTemperature } = useMachineMutation( + z.object({ SetNozzleHeatingTemperature: z.number() }), + ); + + const { request: requestFrontHeatingTemperature } = useMachineMutation( + z.object({ SetFrontHeatingTargetTemperature: z.number() }), + ); + + const { request: requestBackHeatingTemperature } = useMachineMutation( + z.object({ SetBackHeatingTargetTemperature: z.number() }), + ); + + const { request: requestMiddleHeatingTemperature } = useMachineMutation( + z.object({ SetMiddleHeatingTemperature: z.number() }), + ); + + const { request: requestExtruderPressureLimit } = useMachineMutation( + z.object({ SetExtruderPressureLimit: z.number() }), + ); + + const { request: requestExtruderPressureLimitEnabled } = useMachineMutation( + z.object({ SetExtruderPressureLimitIsEnabled: z.boolean() }), + ); + + const { request: requestPressurePidSettings } = useMachineMutation( + z.object({ + SetPressurePidSettings: z.object({ + ki: z.number(), + kp: z.number(), + kd: z.number(), + }), + }), + ); + + const { request: requestResetInverter } = useMachineMutation( + z.object({ ResetInverter: z.boolean() }), + ); return { - heatingSetNozzleTemp, - heatingSetFrontTemp, - heatingSetBackTemp, - heatingSetMiddleTemp, - - nozzleHeatingTarget: nozzleHeatingTargetState.value, - frontHeatingTarget: frontHeatingTargetState.value, - backHeatingTarget: backHeatingTargetState.value, - middleHeatingTarget: middleHeatingTargetState.value, - - nozzleHeatingState: heatingNozzleState?.data, - frontHeatingState: heatingFrontState?.data, - backHeatingState: heatingBackState?.data, - middleHeatingState: heatingMiddleState?.data, + // Consolidated state + state: stateOptimistic.value?.data, + // Individual live values (TimeSeries) + screwRpm, + pressure, nozzleTemperature, frontTemperature, backTemperature, middleTemperature, + nozzlePower, + frontPower, + middlePower, + backPower, + + // Loading states + isLoading: stateOptimistic.isOptimistic, + isDisabled: !stateOptimistic.isInitialized, + + // Action functions (verb-first) + setInverterRotationDirection, + setExtruderMode, + setInverterRegulation, + setInverterTargetRpm, + setInverterTargetPressure, + setNozzleHeatingTemperature, + setFrontHeatingTemperature, + setBackHeatingTemperature, + setMiddleHeatingTemperature, + setExtruderPressureLimit, + setExtruderPressureLimitEnabled, + setPressurePidKp, + setPressurePidKi, + setPressurePidKd, + resetInverter, }; } diff --git a/server/src/machines/extruder1/act.rs b/server/src/machines/extruder1/act.rs index d9ab52c9..4b272654 100644 --- a/server/src/machines/extruder1/act.rs +++ b/server/src/machines/extruder1/act.rs @@ -33,40 +33,9 @@ impl Actor for ExtruderV2 { if now.duration_since(self.last_measurement_emit) > Duration::from_secs_f64(1.0 / 60.0) { - // channel 1 - self.emit_heating( - self.temperature_controller_back.heating.clone(), - super::HeatingType::Back, - ); - self.emit_heating( - self.temperature_controller_front.heating.clone(), - super::HeatingType::Front, - ); - self.emit_heating( - self.temperature_controller_middle.heating.clone(), - super::HeatingType::Middle, - ); - self.emit_heating( - self.temperature_controller_nozzle.heating.clone(), - super::HeatingType::Nozzle, - ); - - self.emit_heating_element_power(super::HeatingType::Nozzle); - self.emit_heating_element_power(super::HeatingType::Front); - self.emit_heating_element_power(super::HeatingType::Middle); - self.emit_heating_element_power(super::HeatingType::Back); - - self.emit_regulation(); - self.emit_mode_state(); - self.emit_rotation_state(); - self.emit_inverter_status(); - - self.emit_pressure_pid_settings(); - - self.emit_bar(); - self.emit_rpm(); - self.emit_extruder_settings(); - + // Emit live values at 60 FPS + self.emit_live_values(); + self.last_measurement_emit = now; } }) diff --git a/server/src/machines/extruder1/api.rs b/server/src/machines/extruder1/api.rs index e94f1b57..400bca3d 100644 --- a/server/src/machines/extruder1/api.rs +++ b/server/src/machines/extruder1/api.rs @@ -17,81 +17,114 @@ use smol::channel::Sender; use socketioxide::extract::SocketRef; use tracing::instrument; -#[derive(Serialize, Debug, Clone)] -pub struct FrequencyEvent { - frequency: f64, - // is this the Frequency in the eeprom or the one in memory(running) - is_ram: bool, +#[derive(Serialize, Debug, Clone, Default)] +pub struct LiveValuesEvent { + /// screw rpm + pub screw_rpm: f64, + /// pressure in bar + pub pressure: f64, + /// nozzle temperature in celsius + pub nozzle_temperature: f64, + /// front temperature in celsius + pub front_temperature: f64, + /// back temperature in celsius + pub back_temperature: f64, + /// middle temperature in celsius + pub middle_temperature: f64, + /// nozzle heating power in watts + pub nozzle_power: f64, + /// front heating power in watts + pub front_power: f64, + /// back heating power in watts + pub back_power: f64, + /// middle heating power in watts + pub middle_power: f64, +} + +impl LiveValuesEvent { + pub fn build(&self) -> Event { + Event::new("LiveValuesEvent", self.clone()) + } } #[derive(Serialize, Debug, Clone)] -pub struct MotorStateEvent { - start: bool, - forward_rotation: bool, +pub struct StateEvent { + /// rotation state + pub rotation_state: RotationState, + /// mode state + pub mode_state: ModeState, + /// regulation state + pub regulation_state: RegulationState, + /// pressure state + pub pressure_state: PressureState, + /// screw state + pub screw_state: ScrewState, + /// heating states + pub heating_states: HeatingStates, + /// extruder settings state + pub extruder_settings_state: ExtruderSettingsState, + /// inverter status state + pub inverter_status_state: InverterStatusState, + /// pid settings + pub pid_settings: PidSettingsStates, +} + +impl StateEvent { + pub fn build(&self) -> Event { + Event::new("StateEvent", self.clone()) + } } #[derive(Serialize, Debug, Clone)] -pub struct HeatingStateEvent { +pub struct RotationState { + pub forward: bool, +} + +#[derive(Serialize, Debug, Clone)] +pub struct ModeState { + pub mode: ExtruderV2Mode, +} + +#[derive(Serialize, Debug, Clone)] +pub struct RegulationState { + pub uses_rpm: bool, +} + +#[derive(Serialize, Debug, Clone)] +pub struct PressureState { + pub bar: f64, + pub target_bar: f64, +} + +#[derive(Serialize, Debug, Clone)] +pub struct ScrewState { + pub rpm: f64, + pub target_rpm: f64, +} + +#[derive(Serialize, Debug, Clone)] +pub struct HeatingStates { + pub nozzle: HeatingState, + pub front: HeatingState, + pub back: HeatingState, + pub middle: HeatingState, +} + +#[derive(Serialize, Debug, Clone)] +pub struct HeatingState { pub temperature: f64, pub target_temperature: f64, pub wiring_error: bool, } -impl HeatingStateEvent { - pub fn build(&self, heating_type: HeatingType) -> Event { - let event = match heating_type { - HeatingType::Nozzle => Event::new("NozzleHeatingStateEvent", self.clone()), - HeatingType::Front => Event::new("FrontHeatingStateEvent", self.clone()), - HeatingType::Back => Event::new("BackHeatingStateEvent", self.clone()), - HeatingType::Middle => Event::new("MiddleHeatingStateEvent", self.clone()), - }; - return event; - } +#[derive(Serialize, Debug, Clone)] +pub struct ExtruderSettingsState { + pub pressure_limit: f64, + pub pressure_limit_enabled: bool, } #[derive(Serialize, Debug, Clone)] -pub struct RotationStateEvent { - pub forward: bool, -} - -impl RotationStateEvent { - pub fn build(&self) -> Event { - Event::new("RotationStateEvent", self.clone()) - } -} - -#[derive(Serialize, Debug, Clone)] -pub struct OperationModeEvent { - operation_mode: u8, - mode_name: String, -} - -#[derive(Serialize, Debug, Clone)] -pub struct ModeEvent { - pub mode: ExtruderV2Mode, -} - -impl ModeEvent { - pub fn build(&self) -> Event { - Event::new("ModeStateEvent", self.clone()) - } -} - -#[derive(Serialize, Debug, Clone)] -pub struct RegulationStateEvent { - pub uses_rpm: bool, -} - -impl RegulationStateEvent { - pub fn build(&self) -> Event { - Event::new("RegulationStateEvent", self.clone()) - } -} - -/// Inverter status Register 40009 -// bit 8-14 is unused -#[derive(Serialize, Debug, Clone)] -pub struct InverterStatusEvent { +pub struct InverterStatusState { /// RUN (Inverter running) pub running: bool, /// Forward running motor spins forward @@ -112,67 +145,6 @@ pub struct InverterStatusEvent { pub fault_occurence: bool, } -impl InverterStatusEvent { - pub fn build(&self) -> Event { - Event::new("InverterStatusEvent", self.clone()) - } -} - -/// This is used when we just need a simple confirmation, that what we did, didnt cause errors -#[derive(Serialize, Debug, Clone)] -pub struct InverterSuccessEvent { - success: bool, -} - -#[derive(Serialize, Debug, Clone)] -pub struct ErrorEvent { - message: String, - fault_code: u16, -} -#[derive(Serialize, Debug, Clone)] - -pub struct PressureStateEvent { - pub bar: f64, - pub target_bar: f64, -} - -impl PressureStateEvent { - pub fn build(&self) -> Event { - Event::new("PressureStateEvent", self.clone()) - } -} - -#[derive(Serialize, Debug, Clone)] - -pub struct ScrewStateEvent { - pub rpm: f64, - pub target_rpm: f64, -} - -impl ScrewStateEvent { - pub fn build(&self) -> Event { - Event::new("ScrewStateEvent", self.clone()) - } -} - -#[derive(Serialize, Debug, Clone)] - -pub struct ExtruderSettingsStateEvent { - pub pressure_limit: f64, - pub pressure_limit_enabled: bool, -} - -impl ExtruderSettingsStateEvent { - pub fn build(&self) -> Event { - Event::new("ExtruderSettingsStateEvent", self.clone()) - } -} - -pub enum PidType { - Temperature, - Pressure, -} - #[derive(Deserialize, Serialize, Debug, Clone)] pub struct PidSettings { pub ki: f64, @@ -181,48 +153,14 @@ pub struct PidSettings { } #[derive(Serialize, Debug, Clone)] -pub struct PidSettingsEvent { - pub ki: f64, - pub kp: f64, - pub kd: f64, -} - -impl PidSettingsEvent { - pub fn build(&self, pid_type: PidType) -> Event { - match pid_type { - PidType::Temperature => Event::new("TemperaturePidSettingsEvent", self.clone()), - PidType::Pressure => Event::new("PressurePidSettingsEvent", self.clone()), - } - } -} - -#[derive(Serialize, Debug, Clone)] -pub struct HeatingPowerEvent { - pub wattage: f64, -} - -impl HeatingPowerEvent { - pub fn build(&self, heating_type: HeatingType) -> Event { - match heating_type { - HeatingType::Nozzle => Event::new("NozzleHeatingPowerEvent", self.clone()), - HeatingType::Front => Event::new("FrontHeatingPowerEvent", self.clone()), - HeatingType::Back => Event::new("BackHeatingPowerEvent", self.clone()), - HeatingType::Middle => Event::new("MiddleHeatingPowerEvent", self.clone()), - } - } +pub struct PidSettingsStates { + pub temperature: PidSettings, + pub pressure: PidSettings, } pub enum ExtruderV2Events { - RotationStateEvent(Event), - ModeEvent(Event), - RegulationStateEvent(Event), - PressureStateEvent(Event), - ScrewStateEvent(Event), - HeatingStateEvent(Event), - ExtruderSettingsStateEvent(Event), - HeatingPowerEvent(Event), - InverterStatusEvent(Event), - PidSettingsEvent(Event), + LiveValues(Event), + State(Event), } #[derive(Deserialize, Serialize)] @@ -230,27 +168,27 @@ enum Mutation { /// INVERTER /// Frequency Control // Set Rotation also starts the motor - InverterRotationSetDirection(bool), - InverterSetTargetPressure(f64), - InverterSetTargetRpm(f64), - InverterSetRegulation(bool), + SetInverterRotationDirection(bool), + SetInverterTargetPressure(f64), + SetInverterTargetRpm(f64), + SetInverterRegulation(bool), //Mode - ExtruderSetMode(ExtruderV2Mode), - FrontHeatingSetTargetTemperature(f64), - BackHeatingSetTargetTemperature(f64), - MiddleSetHeatingTemperature(f64), - NozzleSetHeatingTemperature(f64), + SetExtruderMode(ExtruderV2Mode), + SetFrontHeatingTargetTemperature(f64), + SetBackHeatingTargetTemperature(f64), + SetMiddleHeatingTemperature(f64), + SetNozzleHeatingTemperature(f64), // SetPressure - ExtruderSetPressureLimit(f64), - ExtruderSetPressureLimitIsEnabled(bool), + SetExtruderPressureLimit(f64), + SetExtruderPressureLimitIsEnabled(bool), // Pid Configure SetPressurePidSettings(PidSettings), // Reset - InverterReset(bool), + ResetInverter(bool), } #[derive(Debug)] @@ -278,16 +216,8 @@ impl ExtruderV2Namespace { impl CacheableEvents for ExtruderV2Events { fn event_value(&self) -> GenericEvent { match self { - ExtruderV2Events::RotationStateEvent(event) => event.into(), - ExtruderV2Events::ModeEvent(event) => event.into(), - ExtruderV2Events::RegulationStateEvent(event) => event.into(), - ExtruderV2Events::PressureStateEvent(event) => event.into(), - ExtruderV2Events::ScrewStateEvent(event) => event.into(), - ExtruderV2Events::HeatingStateEvent(event) => event.into(), - ExtruderV2Events::ExtruderSettingsStateEvent(event) => event.into(), - ExtruderV2Events::HeatingPowerEvent(event) => event.into(), - ExtruderV2Events::InverterStatusEvent(event) => event.into(), - ExtruderV2Events::PidSettingsEvent(event) => event.into(), + ExtruderV2Events::LiveValues(event) => event.into(), + ExtruderV2Events::State(event) => event.into(), } } @@ -296,16 +226,8 @@ impl CacheableEvents for ExtruderV2Events { let cache_one = cache_one_event(); match self { - ExtruderV2Events::RotationStateEvent(_) => cache_one, - ExtruderV2Events::ModeEvent(_) => cache_one, - ExtruderV2Events::RegulationStateEvent(_) => cache_one, - ExtruderV2Events::ExtruderSettingsStateEvent(_) => cache_one, - ExtruderV2Events::HeatingStateEvent(_) => cache_one, - ExtruderV2Events::PressureStateEvent(_) => cache_one_hour, - ExtruderV2Events::ScrewStateEvent(_) => cache_one_hour, - ExtruderV2Events::HeatingPowerEvent(_) => cache_one_hour, - ExtruderV2Events::InverterStatusEvent(_) => cache_one, - ExtruderV2Events::PidSettingsEvent(_) => cache_one, + ExtruderV2Events::LiveValues(_) => cache_one_hour, + ExtruderV2Events::State(_) => cache_one, } } } @@ -315,29 +237,29 @@ impl MachineApi for ExtruderV2 { // there are multiple Modbus Frames that are "prebuilt" let control: Mutation = serde_json::from_value(request_body)?; match control { - Mutation::ExtruderSetMode(mode) => self.set_mode_state(mode), - Mutation::InverterRotationSetDirection(forward) => self.set_rotation_state(forward), - Mutation::InverterSetRegulation(uses_rpm) => self.set_regulation(uses_rpm), - Mutation::InverterSetTargetPressure(bar) => self.set_target_pressure(bar), - Mutation::InverterSetTargetRpm(rpm) => self.set_target_rpm(rpm), - Mutation::InverterReset(_) => self.reset_inverter(), + Mutation::SetExtruderMode(mode) => self.set_mode_state(mode), + Mutation::SetInverterRotationDirection(forward) => self.set_rotation_state(forward), + Mutation::SetInverterRegulation(uses_rpm) => self.set_regulation(uses_rpm), + Mutation::SetInverterTargetPressure(bar) => self.set_target_pressure(bar), + Mutation::SetInverterTargetRpm(rpm) => self.set_target_rpm(rpm), + Mutation::ResetInverter(_) => self.reset_inverter(), - Mutation::FrontHeatingSetTargetTemperature(temp) => { + Mutation::SetFrontHeatingTargetTemperature(temp) => { self.set_target_temperature(temp, HeatingType::Front) } - Mutation::MiddleSetHeatingTemperature(temp) => { + Mutation::SetMiddleHeatingTemperature(temp) => { self.set_target_temperature(temp, HeatingType::Middle) } - Mutation::BackHeatingSetTargetTemperature(temp) => { + Mutation::SetBackHeatingTargetTemperature(temp) => { self.set_target_temperature(temp, HeatingType::Back) } - Mutation::NozzleSetHeatingTemperature(temp) => { + Mutation::SetNozzleHeatingTemperature(temp) => { self.set_target_temperature(temp, HeatingType::Nozzle) } - Mutation::ExtruderSetPressureLimit(pressure_limit) => { + Mutation::SetExtruderPressureLimit(pressure_limit) => { self.set_nozzle_pressure_limit(pressure_limit); } - Mutation::ExtruderSetPressureLimitIsEnabled(enabled) => { + Mutation::SetExtruderPressureLimitIsEnabled(enabled) => { self.set_nozzle_pressure_limit_is_enabled(enabled); } diff --git a/server/src/machines/extruder1/mod.rs b/server/src/machines/extruder1/mod.rs index 6bb2b3f8..cf7f93fa 100644 --- a/server/src/machines/extruder1/mod.rs +++ b/server/src/machines/extruder1/mod.rs @@ -1,5 +1,7 @@ use api::{ - ExtruderSettingsStateEvent, ExtruderV2Events, ExtruderV2Namespace, PidSettings, PidType, + ExtruderV2Events, ExtruderV2Namespace, PidSettings, LiveValuesEvent, StateEvent, + RotationState, ModeState, RegulationState, PressureState, ScrewState, HeatingStates, HeatingState, + ExtruderSettingsState, InverterStatusState, PidSettingsStates, }; use control_core::{ actors::mitsubishi_inverter_rs485::MitsubishiControlRequests, machines::Machine, @@ -76,10 +78,103 @@ impl std::fmt::Display for ExtruderV2 { impl Machine for ExtruderV2 {} impl ExtruderV2 { + pub fn emit_live_values(&mut self) { + let live_values = LiveValuesEvent { + screw_rpm: self.screw_speed_controller.get_screw_rpm().get::(), + pressure: self.screw_speed_controller.get_pressure().get::(), + nozzle_temperature: self.temperature_controller_nozzle.heating.temperature.get::(), + front_temperature: self.temperature_controller_front.heating.temperature.get::(), + back_temperature: self.temperature_controller_back.heating.temperature.get::(), + middle_temperature: self.temperature_controller_middle.heating.temperature.get::(), + nozzle_power: self.temperature_controller_nozzle.get_heating_element_wattage(), + front_power: self.temperature_controller_front.get_heating_element_wattage(), + back_power: self.temperature_controller_back.get_heating_element_wattage(), + middle_power: self.temperature_controller_middle.get_heating_element_wattage(), + }; + + let event = live_values.build(); + self.namespace.emit(ExtruderV2Events::LiveValues(event)); + } + + pub fn emit_state(&mut self) { + let state = StateEvent { + rotation_state: RotationState { + forward: self.screw_speed_controller.get_rotation_direction(), + }, + mode_state: ModeState { + mode: self.mode.clone(), + }, + regulation_state: RegulationState { + uses_rpm: self.screw_speed_controller.get_uses_rpm(), + }, + pressure_state: PressureState { + bar: self.screw_speed_controller.get_pressure().get::(), + target_bar: self.screw_speed_controller.get_target_pressure().get::(), + }, + screw_state: ScrewState { + rpm: self.screw_speed_controller.get_screw_rpm().get::(), + target_rpm: self.screw_speed_controller.get_target_rpm().get::(), + }, + heating_states: HeatingStates { + nozzle: HeatingState { + temperature: self.temperature_controller_nozzle.heating.temperature.get::(), + target_temperature: self.temperature_controller_nozzle.heating.target_temperature.get::(), + wiring_error: self.temperature_controller_nozzle.heating.wiring_error, + }, + front: HeatingState { + temperature: self.temperature_controller_front.heating.temperature.get::(), + target_temperature: self.temperature_controller_front.heating.target_temperature.get::(), + wiring_error: self.temperature_controller_front.heating.wiring_error, + }, + back: HeatingState { + temperature: self.temperature_controller_back.heating.temperature.get::(), + target_temperature: self.temperature_controller_back.heating.target_temperature.get::(), + wiring_error: self.temperature_controller_back.heating.wiring_error, + }, + middle: HeatingState { + temperature: self.temperature_controller_middle.heating.temperature.get::(), + target_temperature: self.temperature_controller_middle.heating.target_temperature.get::(), + wiring_error: self.temperature_controller_middle.heating.wiring_error, + }, + }, + extruder_settings_state: ExtruderSettingsState { + pressure_limit: self.screw_speed_controller.get_nozzle_pressure_limit().get::(), + pressure_limit_enabled: self.screw_speed_controller.get_nozzle_pressure_limit_enabled(), + }, + inverter_status_state: InverterStatusState { + running: self.screw_speed_controller.inverter.inverter_status.running, + forward_running: self.screw_speed_controller.inverter.inverter_status.forward_running, + reverse_running: self.screw_speed_controller.inverter.inverter_status.reverse_running, + up_to_frequency: self.screw_speed_controller.inverter.inverter_status.su, + overload_warning: self.screw_speed_controller.inverter.inverter_status.ol, + no_function: self.screw_speed_controller.inverter.inverter_status.no_function, + output_frequency_detection: self.screw_speed_controller.inverter.inverter_status.fu, + abc_fault: self.screw_speed_controller.inverter.inverter_status.abc_, + fault_occurence: self.screw_speed_controller.inverter.inverter_status.fault_occurence, + }, + pid_settings: PidSettingsStates { + temperature: PidSettings { + ki: 0.0, // TODO: Add temperature PID settings when available + kp: 0.0, + kd: 0.0, + }, + pressure: PidSettings { + ki: self.screw_speed_controller.pid.get_ki(), + kp: self.screw_speed_controller.pid.get_kp(), + kd: self.screw_speed_controller.pid.get_kd(), + }, + }, + }; + + let event = state.build(); + self.namespace.emit(ExtruderV2Events::State(event)); + } + // Extruder Settings Api Impl fn set_nozzle_pressure_limit_is_enabled(&mut self, enabled: bool) { self.screw_speed_controller .set_nozzle_pressure_limit_is_enabled(enabled); + self.emit_state(); } /// pressure is represented as bar @@ -87,6 +182,7 @@ impl ExtruderV2 { let nozzle_pressure_limit = Pressure::new::(pressure); self.screw_speed_controller .set_nozzle_pressure_limit(nozzle_pressure_limit); + self.emit_state(); } fn get_nozzle_pressure_limit(&mut self) -> f64 { @@ -99,20 +195,6 @@ impl ExtruderV2 { .screw_speed_controller .get_nozzle_pressure_limit_enabled(); } - - fn emit_extruder_settings(&mut self) { - let pressure: f64 = self.get_nozzle_pressure_limit(); - let enabled = self.get_nozzle_pressure_limit_enabled(); - - let event = ExtruderSettingsStateEvent { - pressure_limit: pressure, - pressure_limit_enabled: enabled, - } - .build(); - - self.namespace - .emit(ExtruderV2Events::ExtruderSettingsStateEvent(event)); - } } impl ExtruderV2 { @@ -197,35 +279,10 @@ impl ExtruderV2 { impl ExtruderV2 { fn set_rotation_state(&mut self, forward: bool) { self.screw_speed_controller.set_rotation_direction(forward); - self.emit_rotation_state(); + self.emit_state(); } - fn emit_rotation_state(&mut self) { - let event = api::RotationStateEvent { - forward: self.screw_speed_controller.get_rotation_direction(), - } - .build(); - self.namespace - .emit(ExtruderV2Events::RotationStateEvent(event)) - } - fn emit_inverter_status(&mut self) { - let status = &self.screw_speed_controller.inverter.inverter_status; - let event = api::InverterStatusEvent { - running: status.running, - forward_running: status.forward_running, - reverse_running: status.reverse_running, - up_to_frequency: status.su, - overload_warning: status.ol, - no_function: status.no_function, - output_frequency_detection: status.fu, - abc_fault: status.abc_, - fault_occurence: status.fault_occurence, - } - .build(); - self.namespace - .emit(ExtruderV2Events::InverterStatusEvent(event)); - } fn reset_inverter(&mut self) { self.screw_speed_controller @@ -235,16 +292,7 @@ impl ExtruderV2 { fn set_mode_state(&mut self, mode: ExtruderV2Mode) { self.switch_mode(mode); - - self.emit_mode_state(); - } - - fn emit_mode_state(&mut self) { - let event = api::ModeEvent { - mode: self.mode.clone(), - } - .build(); - self.namespace.emit(ExtruderV2Events::ModeEvent(event)); + self.emit_state(); } } @@ -256,66 +304,25 @@ impl ExtruderV2 { .set_target_screw_rpm(self.screw_speed_controller.target_rpm); } self.screw_speed_controller.set_uses_rpm(uses_rpm); - - self.emit_regulation(); - } - - fn emit_regulation(&mut self) { - let event = api::RegulationStateEvent { - uses_rpm: self.screw_speed_controller.get_uses_rpm(), - } - .build(); - self.namespace - .emit(ExtruderV2Events::RegulationStateEvent(event)); + self.emit_state(); } fn set_target_pressure(&mut self, pressure: f64) { let pressure = Pressure::new::(pressure); self.screw_speed_controller.set_target_pressure(pressure); + self.emit_state(); } fn set_target_rpm(&mut self, rpm: f64) { let revolution_per_minutes = AngularVelocity::new::(rpm); self.screw_speed_controller .set_target_screw_rpm(revolution_per_minutes); + self.emit_state(); } } // Heating impl ExtruderV2 { - fn emit_heating(&mut self, heating: Heating, heating_type: HeatingType) { - let event = api::HeatingStateEvent { - temperature: heating.temperature.get::(), - target_temperature: heating.target_temperature.get::(), - wiring_error: heating.wiring_error, - } - .build(heating_type); - - self.namespace - .emit(ExtruderV2Events::HeatingStateEvent(event)); - } - - fn emit_heating_element_power(&mut self, heating_type: HeatingType) { - let wattage = match heating_type { - HeatingType::Nozzle => self - .temperature_controller_nozzle - .get_heating_element_wattage(), - HeatingType::Front => self - .temperature_controller_front - .get_heating_element_wattage(), - HeatingType::Back => self - .temperature_controller_back - .get_heating_element_wattage(), - HeatingType::Middle => self - .temperature_controller_middle - .get_heating_element_wattage(), - }; - - let event = api::HeatingPowerEvent { wattage }.build(heating_type); - self.namespace - .emit(ExtruderV2Events::HeatingPowerEvent(event)); - } - fn set_target_temperature(&mut self, target_temperature: f64, heating_type: HeatingType) { let target_temp = ThermodynamicTemperature::new::(target_temperature); @@ -337,69 +344,15 @@ impl ExtruderV2 { .set_target_temperature(target_temp), } - match heating_type { - HeatingType::Nozzle => self.emit_heating( - self.temperature_controller_nozzle.heating.clone(), - heating_type, - ), - HeatingType::Front => self.emit_heating( - self.temperature_controller_front.heating.clone(), - heating_type, - ), - HeatingType::Back => self.emit_heating( - self.temperature_controller_back.heating.clone(), - heating_type, - ), - HeatingType::Middle => self.emit_heating( - self.temperature_controller_middle.heating.clone(), - heating_type, - ), - } + self.emit_state(); } } impl ExtruderV2 { - fn emit_rpm(&mut self) { - let rpm = self.screw_speed_controller.get_screw_rpm(); - let target_rpm = self.screw_speed_controller.get_target_rpm(); - - let event = api::ScrewStateEvent { - // use uom here - rpm: rpm.get::(), - target_rpm: target_rpm.get::(), - } - .build(); - self.namespace - .emit(ExtruderV2Events::ScrewStateEvent(event)); - } - - fn emit_bar(&mut self) { - let pressure = self.screw_speed_controller.get_pressure(); - let target_pressure = self.screw_speed_controller.get_target_pressure(); - let event = api::PressureStateEvent { - bar: pressure.get::(), - target_bar: target_pressure.get::(), - } - .build(); - self.namespace - .emit(ExtruderV2Events::PressureStateEvent(event)); - } -} - -impl ExtruderV2 { - fn emit_pressure_pid_settings(&mut self) { - let kd = self.screw_speed_controller.pid.get_kd(); - let kp = self.screw_speed_controller.pid.get_kp(); - let ki = self.screw_speed_controller.pid.get_ki(); - - let event = api::PidSettingsEvent { ki, kp, kd }.build(PidType::Pressure); - self.namespace - .emit(ExtruderV2Events::PidSettingsEvent(event)); - } - fn configure_pressure_pid(&mut self, settings: PidSettings) { self.screw_speed_controller .pid .configure(settings.ki, settings.kp, settings.kd); + self.emit_state(); } }