Fix weird machine api behavior/add status (#4186)

* YOYO NEW API SPEC!

* fies

Signed-off-by: Jess Frazelle <github@jessfraz.com>

* add status

Signed-off-by: Jess Frazelle <github@jessfraz.com>

* pass disabled

Signed-off-by: Jess Frazelle <github@jessfraz.com>

* disabled

Signed-off-by: Jess Frazelle <github@jessfraz.com>

* add nozzle diameter

Signed-off-by: Jess Frazelle <github@jessfraz.com>

* ypdates

Signed-off-by: Jess Frazelle <github@jessfraz.com>

* update types

Signed-off-by: Jess Frazelle <github@jessfraz.com>

* update types

Signed-off-by: Jess Frazelle <github@jessfraz.com>

* update types

Signed-off-by: Jess Frazelle <github@jessfraz.com>

---------

Signed-off-by: Jess Frazelle <github@jessfraz.com>
Co-authored-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com>
Co-authored-by: Paul Tagliamonte <paul@zoo.dev>
This commit is contained in:
Jess Frazelle
2024-10-17 15:30:46 -07:00
committed by GitHub
parent b6dd6e7dd0
commit 7218efc489
9 changed files with 727 additions and 88 deletions

View File

@ -11,6 +11,8 @@ export const NetworkMachineIndicator = ({
}) => {
const machineCount = machineManager.machineCount()
const reason = machineManager.noMachinesReason()
const machines = machineManager.machines
console.log('react machines', machines)
return isDesktop() ? (
<Popover className="relative">
@ -46,20 +48,29 @@ export const NetworkMachineIndicator = ({
</div>
{machineCount > 0 && (
<ul className="divide-y divide-chalkboard-20 dark:divide-chalkboard-80">
{Object.entries(machineManager.machines).map(
([hostname, machine]) => (
<li key={hostname} className={'px-2 py-4 gap-1 last:mb-0 '}>
<p className="">
{machine.make_model.model ||
machine.make_model.manufacturer ||
'Unknown Machine'}
{machines.map((machine) => {
return (
<li key={machine.id} className={'px-2 py-4 gap-1 last:mb-0 '}>
<p className="">{machine.id.toUpperCase()}</p>
<p className="text-chalkboard-60 dark:text-chalkboard-50 text-xs">
{machine.make_model.model}
</p>
<p className="text-chalkboard-60 dark:text-chalkboard-50 text-xs">
Hostname {hostname}
{machine.state.state.toUpperCase()}
{machine.state.state === 'failed' && machine.state.message
? ': ' + machine.state.message
: ''}
</p>
{machine.extra &&
machine.extra.type === 'bambu' &&
machine.extra.nozzle_diameter && (
<p className="text-chalkboard-60 dark:text-chalkboard-50 text-xs">
Nozzle Diameter: {machine.extra.nozzle_diameter}
</p>
)}
</li>
)
)}
})}
</ul>
)}
</Popover.Panel>

View File

@ -190,10 +190,17 @@ export const modelingMachineCommandConfig: StateMachineCommandSetConfig<
options: () => {
return Object.entries(machineManager.machines).map(
([_, machine]) => ({
name: `${machine.id} (${
machine.make_model.model || machine.make_model.manufacturer
}) via ${machineManager.machineApiIp || 'the local network'}`,
name:
`${machine.id} (${
machine.make_model.model || machine.make_model.manufacturer
}) (${machine.state.state})` +
(machine.extra &&
machine.extra.type === 'bambu' &&
machine.extra.nozzle_diameter
? ` - Nozzle Diameter: ${machine.extra.nozzle_diameter}`
: ''),
isCurrent: false,
disabled: machine.state.state !== 'idle',
value: machine as components['schemas']['MachineInfoResponse'],
})
)

View File

@ -119,18 +119,54 @@ export interface components {
/** @description Extra machine-specific information regarding a connected machine. */
ExtraMachineInfoResponse:
| {
Moonraker: Record<string, never>
/** @enum {string} */
type: 'moonraker'
}
| {
Usb: Record<string, never>
/** @enum {string} */
type: 'usb'
}
| {
Bambu: Record<string, never>
/** @description The current stage of the machine as defined by Bambu which can include errors, etc. */
current_stage?: components['schemas']['Stage'] | null
/** @description The nozzle diameter of the machine. */
nozzle_diameter: components['schemas']['NozzleDiameter']
/** @enum {string} */
type: 'bambu'
}
/** @description Configuration for a FDM-based printer. */
FdmHardwareConfiguration: {
/** @description type of material being extruded */
filament_material: components['schemas']['FilamentMaterial']
/**
* Format: double
* @description Diameter of the extrusion nozzle, in mm.
*/
nozzle_diameter: number
}
/** @description The material that the filament is made of. */
FilamentMaterial:
| 'Pla'
| 'Abs'
| 'Petg'
| 'Nylon'
| 'Tpu'
| 'Pva'
| 'Hips'
| 'Composite'
| 'Other'
/** @description The hardware configuration of a machine. */
HardwareConfiguration:
| 'None'
| {
Fdm: components['schemas']['FdmHardwareConfiguration']
}
/** @description Information regarding a connected machine. */
MachineInfoResponse: {
/** @description Additional, per-machine information which is specific to the underlying machine type. */
extra?: components['schemas']['ExtraMachineInfoResponse'] | null
/** @description Information about how the Machine is currently configured. */
hardware_configuration: components['schemas']['HardwareConfiguration']
/** @description Machine Identifier (ID) for the specific Machine. */
id: string
/** @description Information regarding the method of manufacture. */
@ -157,17 +193,40 @@ export interface components {
}
/** @description Current state of the machine -- be it printing, idle or offline. This can be used to determine if a printer is in the correct state to take a new job. */
MachineState:
| 'Unknown'
| 'Idle'
| 'Running'
| 'Offline'
| 'Paused'
| 'Complete'
| {
Failed: string | null
/** @enum {string} */
state: 'unknown'
}
| {
/** @enum {string} */
state: 'idle'
}
| {
/** @enum {string} */
state: 'running'
}
| {
/** @enum {string} */
state: 'offline'
}
| {
/** @enum {string} */
state: 'paused'
}
| {
/** @enum {string} */
state: 'complete'
}
| {
/** @description A human-readable message describing the failure. */
message?: string | null
/** @enum {string} */
state: 'failed'
}
/** @description Specific technique by which this Machine takes a design, and produces a real-world 3D object. */
MachineType: 'Stereolithography' | 'FusedDeposition' | 'Cnc'
/** @description A nozzle diameter. */
NozzleDiameter: '0.2' | '0.4' | '0.6' | '0.8'
/** @description The response from the `/ping` endpoint. */
Pong: {
/** @description The pong response. */
@ -186,7 +245,50 @@ export interface components {
job_name: string
/** @description The machine id to print to. */
machine_id: string
/** @description Requested design-specific slicer configurations. */
slicer_configuration?: components['schemas']['SlicerConfiguration'] | null
}
/** @description The slicer configuration is a set of parameters that are passed to the slicer to control how the gcode is generated. */
SlicerConfiguration: Record<string, never>
/** @description The print stage. These come from: https://github.com/SoftFever/OrcaSlicer/blob/431978baf17961df90f0d01871b0ad1d839d7f5d/src/slic3r/GUI/DeviceManager.cpp#L78 */
Stage:
| 'nothing'
| 'empty'
| 'auto_bed_leveling'
| 'heatbed_preheating'
| 'sweeping_xy_mech_mode'
| 'changing_filament'
| 'm400_pause'
| 'paused_due_to_filament_runout'
| 'heating_hotend'
| 'calibrating_extrusion'
| 'scanning_bed_surface'
| 'inspecting_first_layer'
| 'identifying_build_plate_type'
| 'calibrating_micro_lidar'
| 'homing_toolhead'
| 'cleaning_nozzle_tip'
| 'checking_extruder_temperature'
| 'printing_was_paused_by_the_user'
| 'pause_of_front_cover_falling'
| 'calibrating_micro_lidar2'
| 'calibrating_extrusion_flow'
| 'paused_due_to_nozzle_temperature_malfunction'
| 'paused_due_to_heat_bed_temperature_malfunction'
| 'filament_unloading'
| 'skip_step_pause'
| 'filament_loading'
| 'motor_noise_calibration'
| 'paused_due_to_ams_lost'
| 'paused_due_to_low_speed_of_the_heat_break_fan'
| 'paused_due_to_chamber_temperature_control_error'
| 'cooling_chamber'
| 'paused_by_the_gcode_inserted_by_the_user'
| 'motor_noise_showoff'
| 'nozzle_filament_covered_detected_pause'
| 'cutter_error_pause'
| 'first_layer_error_pause'
| 'nozzle_clog_pause'
/** @description Set of three values to represent the extent of a 3-D Volume. This contains the width, depth, and height values, generally used to represent some maximum or minimum.
*
* All measurements are in millimeters. */

View File

@ -85,7 +85,11 @@ export class MachineManager {
return
}
this._machines = await window.electron.listMachines()
if (this._machineApiIp === null) {
return
}
this._machines = await window.electron.listMachines(this._machineApiIp)
}
private async updateMachineApiIp(): Promise<void> {

View File

@ -238,6 +238,7 @@ ipcMain.handle('find_machine_api', () => {
const ip = service.addresses[0]
const port = service.port
// We want to return the ip address of the machine API.
console.log(`Machine API found at ${ip}:${port}`)
resolve(`${ip}:${port}`)
}
)

View File

@ -77,11 +77,12 @@ const kittycad = (access: string, args: any) =>
// We could probably do this from the renderer side, but I fear CORS will
// bite our butts.
const listMachines = async (): Promise<MachinesListing> => {
const machineApi = await ipcRenderer.invoke('find_machine_api')
if (!machineApi) return []
return fetch(`http://${machineApi}/machines`).then((resp) => resp.json())
const listMachines = async (
machineApiAddr: string
): Promise<MachinesListing> => {
return fetch(`http://${machineApiAddr}/machines`).then((resp) => {
return resp.json()
})
}
const getMachineApiIp = async (): Promise<String | null> =>