use std::collections::BTreeMap;
use serde::{Deserialize, Serialize};
use crate::{Client, ClientError};
pub const CONTRACT_VERSION: &str = env!("CARGO_PKG_VERSION");
pub const OPERATION_NAMES: [&str; 27] = [
"prints",
"status",
"context",
"image",
"history",
"manifest_get",
"look",
"manifest_set",
"spools",
"spool",
"printer_history",
"preflight",
"pause",
"resume",
"cancel",
"start_print",
"set_feedrate_factor",
"set_flowrate_factor",
"set_tool_target_c",
"set_bed_target_c",
"set_fan_percent",
"acknowledge_failure",
"register_spool",
"load_spool",
"unload_spool",
"adjust_spool",
"retire_spool",
];
#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)]
pub enum AcknowledgementDisposition {
#[serde(rename = "continue")]
Continue,
#[serde(rename = "watch")]
Watch,
#[serde(rename = "stop")]
Stop,
}
#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
pub struct ActionAnswer {
#[serde(default, skip_serializing_if = "Option::is_none")]
pub intervention: Option<Intervention>,
#[serde(default, skip_serializing_if = "Option::is_none")]
pub printer_refusal: Option<String>,
pub record: ActionRecord,
}
#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
pub struct ActionExecutedPayload {
pub action_id: ActionId,
#[serde(default, skip_serializing_if = "Option::is_none")]
pub intervention_id: Option<InterventionId>,
}
pub type ActionId = String;
#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)]
pub enum ActionKind {
#[serde(rename = "pause")]
Pause,
#[serde(rename = "resume")]
Resume,
#[serde(rename = "cancel")]
Cancel,
#[serde(rename = "start_print")]
StartPrint,
#[serde(rename = "set_feedrate_factor")]
SetFeedrateFactor,
#[serde(rename = "set_flowrate_factor")]
SetFlowrateFactor,
#[serde(rename = "set_tool_target_c")]
SetToolTargetC,
#[serde(rename = "set_bed_target_c")]
SetBedTargetC,
#[serde(rename = "set_fan_percent")]
SetFanPercent,
#[serde(rename = "acknowledge_failure")]
AcknowledgeFailure,
#[serde(rename = "register_spool")]
RegisterSpool,
#[serde(rename = "load_spool")]
LoadSpool,
#[serde(rename = "unload_spool")]
UnloadSpool,
#[serde(rename = "adjust_spool")]
AdjustSpool,
#[serde(rename = "retire_spool")]
RetireSpool,
}
#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
pub struct ActionRecord {
pub decision: PolicyDecision,
#[serde(default, skip_serializing_if = "Option::is_none")]
pub executed_at: Option<Timestamp>,
pub id: ActionId,
#[serde(default, skip_serializing_if = "Option::is_none")]
pub outcome: Option<ExecutionOutcome>,
pub print_id: PrintId,
pub request: ActionRequest,
}
#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
pub struct ActionRejectedPayload {
pub action_id: ActionId,
pub decision: PolicyDecision,
}
#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
pub struct ActionRequest {
pub action: PrintAction,
pub actor: Actor,
pub requested_at: Timestamp,
}
#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
pub struct ActionRequestedPayload {
pub action: PrintAction,
pub action_id: ActionId,
pub actor: Actor,
}
#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
pub enum Actor {
#[serde(rename = "agent")]
Agent {
session_name: String,
},
#[serde(rename = "operator")]
Operator,
#[serde(rename = "system")]
System,
}
#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)]
pub enum ActorClass {
#[serde(rename = "agent")]
Agent,
#[serde(rename = "operator")]
Operator,
#[serde(rename = "system")]
System,
}
pub type Adjustable = String;
#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
pub struct AgentAssessment {
pub confidence: Confidence,
pub did: String,
pub escalating: bool,
pub should_continue: bool,
pub summary: String,
pub why: String,
}
#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
pub struct AgentAssessmentPayload {
pub assessment: AgentAssessment,
pub session_name: String,
}
#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
pub struct CameraLookPayload {
#[serde(default, skip_serializing_if = "Option::is_none")]
pub delivered: Option<Vec<EventId>>,
pub waited_s: i64,
}
#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
#[serde(tag = "key")]
pub enum ChargeKey {
#[serde(rename = "print")]
Print {
print_id: PrintId,
segment: i64,
tool: i64,
},
#[serde(rename = "unobserved")]
Unobserved {
file_name: String,
generation: i64,
origin: String,
print_number: i64,
tool: i64,
},
}
#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)]
pub enum ChargeMethod {
#[serde(rename = "slicer_estimate")]
SlicerEstimate,
#[serde(rename = "gcode_extrusion")]
GcodeExtrusion,
#[serde(rename = "file_fraction")]
FileFraction,
#[serde(rename = "unobserved_estimate")]
UnobservedEstimate,
}
#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
pub struct ChargePendedPayload {
pub pending: PendingCharge,
}
#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
pub struct ClearedMark {
pub reason: UnverifiedReason,
pub spool_id: SpoolId,
}
#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)]
pub enum Confidence {
#[serde(rename = "low")]
Low,
#[serde(rename = "medium")]
Medium,
#[serde(rename = "high")]
High,
}
#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
pub struct ContextAnswer {
pub context: PrintContext,
#[serde(default, skip_serializing_if = "Option::is_none")]
pub image_path: Option<String>,
}
#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
pub struct EffectiveBounds {
pub allowed: BTreeMap<String, Range>,
}
#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
pub struct ErrorAnswer {
pub error: String,
}
pub type EventId = String;
pub type EventKind = String;
#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
pub struct EventRecord {
pub id: EventId,
#[serde(default, skip_serializing_if = "Option::is_none")]
pub image: Option<ImageRef>,
pub kind: EventKind,
pub payload: serde_json::Value,
#[serde(default, skip_serializing_if = "Option::is_none")]
pub print_id: Option<PrintId>,
#[serde(default, skip_serializing_if = "Option::is_none")]
pub raw: Option<RawBytes>,
pub received_at: Timestamp,
pub source: EventSource,
}
pub type EventSource = String;
#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
pub enum ExecutionOutcome {
#[serde(rename = "succeeded")]
Succeeded,
#[serde(rename = "failed")]
Failed {
reason: String,
},
}
#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
pub struct FilamentChangeSignalledPayload {
#[serde(default, skip_serializing_if = "Option::is_none")]
pub position: Option<FilePosition>,
pub position_read_at_signal: bool,
pub source_kind: EventKind,
#[serde(default, skip_serializing_if = "Option::is_none")]
pub spool_id: Option<SpoolId>,
#[serde(default, skip_serializing_if = "Option::is_none")]
pub tool: Option<i64>,
}
#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
pub struct FilamentConsumedPayload {
#[serde(default, skip_serializing_if = "Option::is_none")]
pub analysed_length_mm: Option<f64>,
pub charge_key: ChargeKey,
#[serde(default, skip_serializing_if = "Option::is_none")]
pub density_g_cm3: Option<f64>,
#[serde(default, skip_serializing_if = "Option::is_none")]
pub diameter_mm: Option<f64>,
#[serde(default, skip_serializing_if = "Option::is_none")]
pub grams: Option<f64>,
pub length_mm: f64,
pub method: ChargeMethod,
#[serde(default, skip_serializing_if = "Option::is_none")]
pub note: Option<String>,
#[serde(default, skip_serializing_if = "Option::is_none")]
pub position: Option<FilePosition>,
#[serde(default, skip_serializing_if = "Option::is_none")]
pub remaining_after_g: Option<f64>,
#[serde(default, skip_serializing_if = "Option::is_none")]
pub remaining_before_g: Option<f64>,
#[serde(default, skip_serializing_if = "Option::is_none")]
pub spool_id: Option<SpoolId>,
pub tool: i64,
}
pub type FileName = String;
#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
pub struct FilePosition {
pub bytes: i64,
pub observed_at: Timestamp,
#[serde(default, skip_serializing_if = "Option::is_none")]
pub size_bytes: Option<i64>,
}
#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
pub struct FileTallyRebaselinedPayload {
pub disposition: RebaselineDisposition,
pub file_name: String,
pub new_failures: i64,
pub new_generation: i64,
pub new_successes: i64,
pub old_failures: i64,
pub old_generation: i64,
pub old_successes: i64,
pub origin: String,
}
#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
pub struct HeaterSnapshot {
#[serde(default, skip_serializing_if = "Option::is_none")]
pub actual_c: Option<Reported>,
#[serde(default, skip_serializing_if = "Option::is_none")]
pub offset_c: Option<Reported>,
#[serde(default, skip_serializing_if = "Option::is_none")]
pub target_c: Option<Reported>,
}
#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
pub struct HistoryAnswer {
pub events: Vec<EventRecord>,
}
#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
pub struct ImageAnswer {
#[serde(default, skip_serializing_if = "Option::is_none")]
pub path: Option<String>,
pub record: ImageRecord,
}
pub type ImageId = String;
#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
pub struct ImageRecord {
pub byte_len: i64,
pub content_type: String,
pub event_id: EventId,
pub fetched_at: Timestamp,
pub id: ImageId,
pub print_id: PrintId,
pub relative_path: String,
pub sha256: String,
#[serde(default, skip_serializing_if = "Option::is_none")]
pub source_url: Option<String>,
}
#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
pub struct ImageRef {
pub id: ImageId,
pub sha256: String,
}
#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
pub struct Intervention {
pub action_id: ActionId,
pub adjustable: Adjustable,
pub applied_at: Timestamp,
pub applied_value: f64,
pub expires_at: Timestamp,
pub id: InterventionId,
pub outcome: InterventionOutcome,
pub print_id: PrintId,
#[serde(default, skip_serializing_if = "Option::is_none")]
pub prior_value: Option<f64>,
#[serde(default, skip_serializing_if = "Option::is_none")]
pub restored_at: Option<Timestamp>,
}
#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
pub struct InterventionExpiredPayload {
pub adjustable: Adjustable,
pub intervention_id: InterventionId,
pub outcome: InterventionOutcome,
}
pub type InterventionId = String;
#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
pub enum InterventionOutcome {
#[serde(rename = "still_active")]
StillActive,
#[serde(rename = "restored")]
Restored,
#[serde(rename = "restore_unavailable")]
RestoreUnavailable,
#[serde(rename = "restore_failed")]
RestoreFailed {
reason: String,
},
#[serde(rename = "superseded")]
Superseded {
by: InterventionId,
},
}
#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
pub struct JobManifest {
pub allowed: BTreeMap<String, Range>,
pub file_name: String,
pub material: String,
pub metadata: BTreeMap<String, String>,
pub nozzle_diameter_mm: f64,
pub slicer_profile: String,
}
#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
pub struct JobSnapshot {
#[serde(default, skip_serializing_if = "Option::is_none")]
pub completion: Option<Reported>,
#[serde(default, skip_serializing_if = "Option::is_none")]
pub error: Option<String>,
#[serde(default, skip_serializing_if = "Option::is_none")]
pub estimated_print_time_s: Option<i64>,
#[serde(default, skip_serializing_if = "Option::is_none")]
pub filament: Option<Vec<ToolFilament>>,
#[serde(default, skip_serializing_if = "Option::is_none")]
pub file_name: Option<String>,
#[serde(default, skip_serializing_if = "Option::is_none")]
pub file_origin: Option<String>,
#[serde(default, skip_serializing_if = "Option::is_none")]
pub file_position_bytes: Option<i64>,
#[serde(default, skip_serializing_if = "Option::is_none")]
pub print_time_left_s: Option<i64>,
#[serde(default, skip_serializing_if = "Option::is_none")]
pub print_time_s: Option<i64>,
#[serde(default, skip_serializing_if = "Option::is_none")]
pub size_bytes: Option<i64>,
pub state: PrinterState,
}
#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
pub struct LoadedSpool {
pub spool_id: SpoolId,
pub tool: i64,
}
#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
pub struct Look {
#[serde(default, skip_serializing_if = "Option::is_none")]
pub arrived: Option<Vec<EventRecord>>,
pub detector_paused: bool,
pub event: EventRecord,
#[serde(default, skip_serializing_if = "Option::is_none")]
pub frame: Option<ImageRef>,
#[serde(default, skip_serializing_if = "Option::is_none")]
pub image_path: Option<String>,
#[serde(default, skip_serializing_if = "Option::is_none")]
pub job: Option<JobSnapshot>,
#[serde(default, skip_serializing_if = "Option::is_none")]
pub printer: Option<PrinterSnapshot>,
}
#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
pub struct MalformedExternalEventPayload {
pub detail: String,
}
#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
pub struct ManifestAnswer {
#[serde(default, skip_serializing_if = "Option::is_none")]
pub manifest: Option<JobManifest>,
pub narrowings: Vec<ManifestNarrowing>,
}
#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
pub struct ManifestNarrowing {
pub adjustable: Adjustable,
pub applied: Range,
pub requested: Range,
}
#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
pub struct ObicoFailureAlertPayload {
#[serde(default, skip_serializing_if = "Option::is_none")]
pub ended_at: Option<Timestamp>,
#[serde(default, skip_serializing_if = "Option::is_none")]
pub file_name: Option<String>,
pub is_warning: bool,
#[serde(default, skip_serializing_if = "Option::is_none")]
pub obico_print_id: Option<i64>,
pub print_paused: bool,
#[serde(default, skip_serializing_if = "Option::is_none")]
pub started_at: Option<Timestamp>,
}
#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)]
pub enum ObicoNotificationType {
#[serde(rename = "started")]
Started,
#[serde(rename = "done")]
Done,
#[serde(rename = "cancelled")]
Cancelled,
#[serde(rename = "paused")]
Paused,
#[serde(rename = "resumed")]
Resumed,
#[serde(rename = "filament_change")]
FilamentChange,
#[serde(rename = "heater_cooled")]
HeaterCooled,
#[serde(rename = "heater_target")]
HeaterTarget,
}
#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
pub struct ObicoPrinterNotificationPayload {
#[serde(default, skip_serializing_if = "Option::is_none")]
pub ended_at: Option<Timestamp>,
#[serde(default, skip_serializing_if = "Option::is_none")]
pub file_name: Option<String>,
pub notification_type: ObicoNotificationType,
#[serde(default, skip_serializing_if = "Option::is_none")]
pub obico_print_id: Option<i64>,
#[serde(default, skip_serializing_if = "Option::is_none")]
pub started_at: Option<Timestamp>,
}
#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
pub struct OperatorAcknowledgementPayload {
pub acknowledged_event_id: EventId,
pub disposition: AcknowledgementDisposition,
}
#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
pub struct PendingCharge {
#[serde(default, skip_serializing_if = "Option::is_none")]
pub analysed_length_mm: Option<f64>,
pub charge_key: ChargeKey,
pub length_mm: f64,
pub method: ChargeMethod,
#[serde(default, skip_serializing_if = "Option::is_none")]
pub note: Option<String>,
pub pended_at: Timestamp,
#[serde(default, skip_serializing_if = "Option::is_none")]
pub position: Option<FilePosition>,
pub print_id: PrintId,
pub tool: i64,
}
#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
pub struct PendingTaken {
pub charge_key: ChargeKey,
pub print_id: PrintId,
}
#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
pub struct PeriodicObservationPayload {
pub interval_s: i64,
#[serde(default, skip_serializing_if = "Option::is_none")]
pub job: Option<JobSnapshot>,
#[serde(default, skip_serializing_if = "Option::is_none")]
pub printer: Option<PrinterSnapshot>,
}
#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
pub enum PolicyDecision {
#[serde(rename = "accepted")]
Accepted,
#[serde(rename = "rejected")]
Rejected(RejectionReason),
}
#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
pub struct PortFailurePayload {
pub detail: String,
pub event_id: EventId,
pub site: PortFailureSite,
}
#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)]
pub enum PortFailureSite {
#[serde(rename = "printer_snapshot")]
PrinterSnapshot,
#[serde(rename = "printer_job")]
PrinterJob,
#[serde(rename = "image_write")]
ImageWrite,
#[serde(rename = "supervision_turn")]
SupervisionTurn,
#[serde(rename = "camera_look")]
CameraLook,
#[serde(rename = "detector_acknowledgement")]
DetectorAcknowledgement,
}
#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
pub struct Preflight {
pub checked_at: Timestamp,
pub file_name: String,
pub tools: Vec<PreflightTool>,
pub verdict: PreflightVerdict,
}
#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
pub struct PreflightAnswer {
pub preflight: Preflight,
}
#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
pub struct PreflightCheckedPayload {
#[serde(default, skip_serializing_if = "Option::is_none")]
pub action_id: Option<ActionId>,
pub preflight: Preflight,
}
#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
pub struct PreflightTool {
#[serde(default, skip_serializing_if = "Option::is_none")]
pub buffer_g: Option<f64>,
#[serde(default, skip_serializing_if = "Option::is_none")]
pub marks: Option<Vec<UnverifiedMark>>,
#[serde(default, skip_serializing_if = "Option::is_none")]
pub remaining_g: Option<f64>,
#[serde(default, skip_serializing_if = "Option::is_none")]
pub required_g: Option<f64>,
#[serde(default, skip_serializing_if = "Option::is_none")]
pub spool_id: Option<SpoolId>,
#[serde(default, skip_serializing_if = "Option::is_none")]
pub spool_name: Option<String>,
pub tool: i64,
pub verdict: PreflightVerdict,
}
#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)]
pub enum PreflightVerdict {
#[serde(rename = "passed")]
Passed,
#[serde(rename = "unchecked")]
Unchecked,
#[serde(rename = "insufficient")]
Insufficient,
#[serde(rename = "unverified_spool")]
UnverifiedSpool,
#[serde(rename = "no_analysis")]
NoAnalysis,
#[serde(rename = "overridden")]
Overridden,
#[serde(rename = "warned")]
Warned,
}
#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
#[serde(tag = "action")]
pub enum PrintAction {
#[serde(rename = "pause")]
Pause {
actor: Actor,
reason: String,
},
#[serde(rename = "resume")]
Resume {
actor: Actor,
reason: String,
},
#[serde(rename = "cancel")]
Cancel {
actor: Actor,
reason: String,
},
#[serde(rename = "start_print")]
StartPrint {
actor: Actor,
file_name: FileName,
manifest: JobManifest,
#[serde(default, skip_serializing_if = "Option::is_none")]
override_filament_check: Option<bool>,
reason: String,
},
#[serde(rename = "set_feedrate_factor")]
SetFeedrateFactor {
actor: Actor,
#[serde(default, skip_serializing_if = "Option::is_none")]
duration_s: Option<i64>,
factor: f64,
reason: String,
},
#[serde(rename = "set_flowrate_factor")]
SetFlowrateFactor {
actor: Actor,
#[serde(default, skip_serializing_if = "Option::is_none")]
duration_s: Option<i64>,
factor: f64,
reason: String,
},
#[serde(rename = "set_tool_target_c")]
SetToolTargetC {
actor: Actor,
#[serde(default, skip_serializing_if = "Option::is_none")]
duration_s: Option<i64>,
reason: String,
target_c: f64,
tool: i64,
},
#[serde(rename = "set_bed_target_c")]
SetBedTargetC {
actor: Actor,
#[serde(default, skip_serializing_if = "Option::is_none")]
duration_s: Option<i64>,
reason: String,
target_c: f64,
},
#[serde(rename = "set_fan_percent")]
SetFanPercent {
actor: Actor,
#[serde(default, skip_serializing_if = "Option::is_none")]
duration_s: Option<i64>,
percent: f64,
reason: String,
},
#[serde(rename = "acknowledge_failure")]
AcknowledgeFailure {
actor: Actor,
disposition: AcknowledgementDisposition,
event_id: EventId,
reason: String,
},
}
#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
pub struct PrintContext {
pub bounds: EffectiveBounds,
pub interventions: Vec<Intervention>,
#[serde(default, skip_serializing_if = "Option::is_none")]
pub job: Option<JobSnapshot>,
#[serde(default, skip_serializing_if = "Option::is_none")]
pub latest_image: Option<ImageRef>,
#[serde(default, skip_serializing_if = "Option::is_none")]
pub manifest: Option<JobManifest>,
pub print: PrintRecord,
#[serde(default, skip_serializing_if = "Option::is_none")]
pub printer: Option<PrinterSnapshot>,
pub recent_events: Vec<EventRecord>,
}
#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
pub struct PrintEndedPayload {
#[serde(default, skip_serializing_if = "Option::is_none")]
pub last_position: Option<FilePosition>,
pub outcome: PrintOutcome,
pub reason: String,
pub state: PrinterState,
}
pub type PrintId = String;
#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)]
pub enum PrintOutcome {
#[serde(rename = "completed")]
Completed,
#[serde(rename = "cancelled")]
Cancelled,
#[serde(rename = "failed")]
Failed,
}
#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
pub struct PrintRecord {
#[serde(default, skip_serializing_if = "Option::is_none")]
pub end_reason: Option<String>,
#[serde(default, skip_serializing_if = "Option::is_none")]
pub ended_at: Option<Timestamp>,
#[serde(default, skip_serializing_if = "Option::is_none")]
pub file_name: Option<String>,
pub id: PrintId,
#[serde(default, skip_serializing_if = "Option::is_none")]
pub job_print_time_s: Option<i64>,
#[serde(default, skip_serializing_if = "Option::is_none")]
pub job_started_at: Option<Timestamp>,
pub narrowings: Vec<ManifestNarrowing>,
pub opened_at: Timestamp,
#[serde(default, skip_serializing_if = "Option::is_none")]
pub provider_print_id: Option<i64>,
pub state: PrinterState,
}
#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
pub struct PrintStartedPayload {
#[serde(default, skip_serializing_if = "Option::is_none")]
pub file_name: Option<String>,
pub loaded: Vec<LoadedSpool>,
#[serde(default, skip_serializing_if = "Option::is_none")]
pub preflight: Option<Preflight>,
#[serde(default, skip_serializing_if = "Option::is_none")]
pub started_by: Option<ActionId>,
}
#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
pub struct PrintUntrackedPayload {
pub reason: String,
}
#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
pub struct PrinterSnapshot {
#[serde(default, skip_serializing_if = "Option::is_none")]
pub bed: Option<HeaterSnapshot>,
#[serde(default, skip_serializing_if = "Option::is_none")]
pub chamber: Option<HeaterSnapshot>,
pub connection: PrinterState,
#[serde(default, skip_serializing_if = "Option::is_none")]
pub fan_percent: Option<Reported>,
#[serde(default, skip_serializing_if = "Option::is_none")]
pub feedrate_factor: Option<Reported>,
#[serde(default, skip_serializing_if = "Option::is_none")]
pub flowrate_factor: Option<Reported>,
pub observed_at: Timestamp,
pub tools: Vec<HeaterSnapshot>,
}
#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
pub enum PrinterState {
#[serde(rename = "operational")]
Operational,
#[serde(rename = "paused")]
Paused,
#[serde(rename = "printing")]
Printing,
#[serde(rename = "cancelling")]
Cancelling,
#[serde(rename = "error")]
Error,
#[serde(rename = "offline")]
Offline,
#[serde(rename = "unknown")]
Unknown(String),
}
#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
pub struct PrintsAnswer {
#[serde(default, skip_serializing_if = "Option::is_none")]
pub active: Option<PrintId>,
pub prints: Vec<PrintRecord>,
}
#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
pub struct Range {
pub max: f64,
pub min: f64,
}
pub type RawBytes = String;
#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)]
pub enum RebaselineDisposition {
#[serde(rename = "accounted")]
Accounted,
#[serde(rename = "unverified")]
Unverified,
}
#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
pub enum RejectionReason {
#[serde(rename = "out_of_bounds")]
OutOfBounds {
adjustable: Adjustable,
allowed: Range,
requested: f64,
},
#[serde(rename = "actor_may_not_request")]
ActorMayNotRequest {
action: ActionKind,
actor_class: ActorClass,
},
#[serde(rename = "no_active_print")]
NoActivePrint,
#[serde(rename = "invalid_from_state")]
InvalidFromState {
state: PrinterState,
},
#[serde(rename = "min_interval_not_elapsed")]
MinIntervalNotElapsed {
interval_s: i64,
since_last_s: i64,
},
#[serde(rename = "unsupported_adjustable")]
UnsupportedAdjustable {
adjustable: Adjustable,
},
#[serde(rename = "insufficient_filament")]
InsufficientFilament {
buffer_g: f64,
remaining_g: f64,
required_g: f64,
spool_id: SpoolId,
spool_name: String,
tool: i64,
#[serde(default, skip_serializing_if = "Option::is_none")]
unverified: Option<UnverifiedReason>,
},
#[serde(rename = "unverified_spool")]
UnverifiedSpool {
reason: UnverifiedReason,
spool_id: SpoolId,
spool_name: String,
tool: i64,
},
#[serde(rename = "analysis_unavailable")]
AnalysisUnavailable {
file_name: String,
waited_s: i64,
},
#[serde(rename = "spool_refused")]
SpoolRefused {
detail: String,
},
}
#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
pub struct Reported {
pub out_of_range: bool,
pub value: f64,
}
#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
pub struct SpoolAdjustedPayload {
pub actor: Actor,
#[serde(default, skip_serializing_if = "Option::is_none")]
pub cleared_marks: Option<Vec<ClearedMark>>,
#[serde(default, skip_serializing_if = "Option::is_none")]
pub gross_g: Option<f64>,
pub reason: String,
pub remaining_after_g: f64,
pub remaining_before_g: f64,
pub spool_id: SpoolId,
#[serde(default, skip_serializing_if = "Option::is_none")]
pub took_pending: Option<Vec<PendingTaken>>,
}
#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
pub struct SpoolAnswer {
pub recent: Vec<EventRecord>,
pub spool: SpoolRecord,
}
#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
#[serde(tag = "command")]
pub enum SpoolCommand {
#[serde(rename = "register_spool")]
RegisterSpool {
actor: Actor,
#[serde(default, skip_serializing_if = "Option::is_none")]
color: Option<String>,
#[serde(default, skip_serializing_if = "Option::is_none")]
density_g_cm3: Option<f64>,
#[serde(default, skip_serializing_if = "Option::is_none")]
diameter_mm: Option<f64>,
initial_g: f64,
material: String,
name: String,
reason: String,
#[serde(default, skip_serializing_if = "Option::is_none")]
remaining_g: Option<f64>,
#[serde(default, skip_serializing_if = "Option::is_none")]
tare_g: Option<f64>,
},
#[serde(rename = "load_spool")]
LoadSpool {
actor: Actor,
reason: String,
spool_id: SpoolId,
tool: i64,
},
#[serde(rename = "unload_spool")]
UnloadSpool {
actor: Actor,
reason: String,
spool_id: SpoolId,
},
#[serde(rename = "adjust_spool")]
AdjustSpool {
actor: Actor,
#[serde(default, skip_serializing_if = "Option::is_none")]
gross_g: Option<f64>,
reason: String,
#[serde(default, skip_serializing_if = "Option::is_none")]
remaining_g: Option<f64>,
spool_id: SpoolId,
},
#[serde(rename = "retire_spool")]
RetireSpool {
actor: Actor,
reason: String,
spool_id: SpoolId,
},
}
#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
pub struct SpoolCommandAnswer {
pub decision: PolicyDecision,
pub events: Vec<EventRecord>,
#[serde(default, skip_serializing_if = "Option::is_none")]
pub spool: Option<SpoolRecord>,
}
#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
pub struct SpoolCommandRejectedPayload {
pub command: SpoolCommand,
pub decision: PolicyDecision,
}
pub type SpoolId = String;
#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
pub struct SpoolLoadedPayload {
pub actor: Actor,
#[serde(default, skip_serializing_if = "Option::is_none")]
pub cleared_marks: Option<Vec<ClearedMark>>,
pub reason: String,
#[serde(default, skip_serializing_if = "Option::is_none")]
pub replaced: Option<SpoolId>,
pub spool_id: SpoolId,
#[serde(default, skip_serializing_if = "Option::is_none")]
pub took_pending: Option<Vec<PendingTaken>>,
pub tool: i64,
}
#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
pub struct SpoolRecord {
#[serde(default, skip_serializing_if = "Option::is_none")]
pub color: Option<String>,
pub density_g_cm3: f64,
pub diameter_mm: f64,
pub id: SpoolId,
pub initial_g: f64,
#[serde(default, skip_serializing_if = "Option::is_none")]
pub loaded_on_tool: Option<i64>,
pub material: String,
pub name: String,
pub registered_at: Timestamp,
pub remaining_g: f64,
#[serde(default, skip_serializing_if = "Option::is_none")]
pub retired_at: Option<Timestamp>,
#[serde(default, skip_serializing_if = "Option::is_none")]
pub tare_g: Option<f64>,
pub trust: SpoolTrust,
pub updated_at: Timestamp,
}
#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
pub struct SpoolRegisteredPayload {
pub actor: Actor,
pub reason: String,
pub spool: SpoolRecord,
}
#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
pub struct SpoolRetiredPayload {
pub actor: Actor,
pub reason: String,
pub remaining_g: f64,
pub spool_id: SpoolId,
}
#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
#[serde(tag = "state")]
pub enum SpoolTrust {
#[serde(rename = "verified")]
Verified,
#[serde(rename = "unverified")]
Unverified {
marks: Vec<UnverifiedMark>,
},
}
#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
pub struct SpoolUnloadedPayload {
pub actor: Actor,
pub reason: String,
pub spool_id: SpoolId,
pub tool: i64,
}
#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
pub struct SpoolUnverifiedPayload {
pub reason: UnverifiedReason,
pub spool_id: SpoolId,
}
#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
pub struct SpoolsAnswer {
pub at_a_glance: Vec<String>,
pub pending: Vec<PendingCharge>,
pub spools: Vec<SpoolRecord>,
}
#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
pub enum StartupOutcome {
#[serde(rename = "print_adopted")]
PrintAdopted,
#[serde(rename = "session_resumed")]
SessionResumed {
session_name: String,
},
#[serde(rename = "intervention_expired")]
InterventionExpired {
adjustable: Adjustable,
intervention_id: InterventionId,
outcome: InterventionOutcome,
},
}
#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
pub struct StartupReconciliationPayload {
pub outcome: StartupOutcome,
pub print_id: PrintId,
}
#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
pub struct StatusAnswer {
pub interventions: Vec<Intervention>,
#[serde(default, skip_serializing_if = "Option::is_none")]
pub job: Option<JobSnapshot>,
pub print: PrintRecord,
#[serde(default, skip_serializing_if = "Option::is_none")]
pub printer: Option<PrinterSnapshot>,
#[serde(default, skip_serializing_if = "Option::is_none")]
pub session: Option<SupervisionSession>,
}
#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
pub struct SupervisionSession {
#[serde(default, skip_serializing_if = "Option::is_none")]
pub close_reason: Option<String>,
#[serde(default, skip_serializing_if = "Option::is_none")]
pub closed_at: Option<Timestamp>,
pub created_at: Timestamp,
pub harness_identity: String,
pub last_turn_at: Timestamp,
pub print_id: PrintId,
pub session_name: String,
}
#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
pub struct SupervisionSessionClosedPayload {
pub close_reason: String,
pub session_name: String,
}
#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
pub struct SupervisionSessionOpenedPayload {
pub harness_identity: String,
pub session_name: String,
}
#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
pub struct TimelineAnswer {
pub events: Vec<EventRecord>,
#[serde(default, skip_serializing_if = "Option::is_none")]
pub next: Option<EventId>,
}
pub type Timestamp = String;
#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
pub struct ToolFilament {
pub length_mm: f64,
pub tool: i64,
#[serde(default, skip_serializing_if = "Option::is_none")]
pub volume_cm3: Option<f64>,
}
#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
pub struct UnaccountedPrintPayload {
pub charged: bool,
pub file_name: String,
#[serde(default, skip_serializing_if = "Option::is_none")]
pub printed_at: Option<Timestamp>,
pub success: bool,
}
#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
pub struct UnverifiedMark {
pub reason: UnverifiedReason,
pub since: Timestamp,
}
#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
#[serde(tag = "reason")]
pub enum UnverifiedReason {
#[serde(rename = "uncharged_print")]
UnchargedPrint {
print_id: PrintId,
},
#[serde(rename = "unaccounted_print")]
UnaccountedPrint {
file_name: String,
printed_at: Timestamp,
},
#[serde(rename = "filament_change_unconfirmed")]
FilamentChangeUnconfirmed {
print_id: PrintId,
},
#[serde(rename = "filament_change_unconfirmed_position")]
FilamentChangeUnconfirmedPosition {
print_id: PrintId,
},
#[serde(rename = "tally_reset")]
TallyReset {
file_name: String,
origin: String,
},
}
pub trait EventPayloadKind: serde::de::DeserializeOwned {
const KIND: &'static str;
}
impl EventPayloadKind for ActionExecutedPayload {
const KIND: &'static str = "action_executed";
}
impl EventPayloadKind for ActionRejectedPayload {
const KIND: &'static str = "action_rejected";
}
impl EventPayloadKind for ActionRequestedPayload {
const KIND: &'static str = "action_requested";
}
impl EventPayloadKind for AgentAssessmentPayload {
const KIND: &'static str = "agent_assessment";
}
impl EventPayloadKind for CameraLookPayload {
const KIND: &'static str = "camera_look";
}
impl EventPayloadKind for ChargePendedPayload {
const KIND: &'static str = "charge_pended";
}
impl EventPayloadKind for FilamentChangeSignalledPayload {
const KIND: &'static str = "filament_change_signalled";
}
impl EventPayloadKind for FilamentConsumedPayload {
const KIND: &'static str = "filament_consumed";
}
impl EventPayloadKind for FileTallyRebaselinedPayload {
const KIND: &'static str = "file_tally_rebaselined";
}
impl EventPayloadKind for InterventionExpiredPayload {
const KIND: &'static str = "intervention_expired";
}
impl EventPayloadKind for MalformedExternalEventPayload {
const KIND: &'static str = "malformed_external_event";
}
impl EventPayloadKind for ObicoFailureAlertPayload {
const KIND: &'static str = "obico_failure_alert";
}
impl EventPayloadKind for ObicoPrinterNotificationPayload {
const KIND: &'static str = "obico_printer_notification";
}
impl EventPayloadKind for OperatorAcknowledgementPayload {
const KIND: &'static str = "operator_acknowledgement";
}
impl EventPayloadKind for PeriodicObservationPayload {
const KIND: &'static str = "periodic_observation";
}
impl EventPayloadKind for PortFailurePayload {
const KIND: &'static str = "port_failure";
}
impl EventPayloadKind for PreflightCheckedPayload {
const KIND: &'static str = "preflight_checked";
}
impl EventPayloadKind for PrintEndedPayload {
const KIND: &'static str = "print_ended";
}
impl EventPayloadKind for PrintStartedPayload {
const KIND: &'static str = "print_started";
}
impl EventPayloadKind for PrintUntrackedPayload {
const KIND: &'static str = "print_untracked";
}
impl EventPayloadKind for SpoolAdjustedPayload {
const KIND: &'static str = "spool_adjusted";
}
impl EventPayloadKind for SpoolCommandRejectedPayload {
const KIND: &'static str = "spool_command_rejected";
}
impl EventPayloadKind for SpoolLoadedPayload {
const KIND: &'static str = "spool_loaded";
}
impl EventPayloadKind for SpoolRegisteredPayload {
const KIND: &'static str = "spool_registered";
}
impl EventPayloadKind for SpoolRetiredPayload {
const KIND: &'static str = "spool_retired";
}
impl EventPayloadKind for SpoolUnloadedPayload {
const KIND: &'static str = "spool_unloaded";
}
impl EventPayloadKind for SpoolUnverifiedPayload {
const KIND: &'static str = "spool_unverified";
}
impl EventPayloadKind for StartupReconciliationPayload {
const KIND: &'static str = "startup_reconciliation";
}
impl EventPayloadKind for SupervisionSessionClosedPayload {
const KIND: &'static str = "supervision_session_closed";
}
impl EventPayloadKind for SupervisionSessionOpenedPayload {
const KIND: &'static str = "supervision_session_opened";
}
impl EventPayloadKind for UnaccountedPrintPayload {
const KIND: &'static str = "unaccounted_print";
}
pub const EVENT_KINDS: [&str; 31] = [
"action_executed",
"action_rejected",
"action_requested",
"agent_assessment",
"camera_look",
"charge_pended",
"filament_change_signalled",
"filament_consumed",
"file_tally_rebaselined",
"intervention_expired",
"malformed_external_event",
"obico_failure_alert",
"obico_printer_notification",
"operator_acknowledgement",
"periodic_observation",
"port_failure",
"preflight_checked",
"print_ended",
"print_started",
"print_untracked",
"spool_adjusted",
"spool_command_rejected",
"spool_loaded",
"spool_registered",
"spool_retired",
"spool_unloaded",
"spool_unverified",
"startup_reconciliation",
"supervision_session_closed",
"supervision_session_opened",
"unaccounted_print",
];
impl EventRecord {
#[must_use]
pub fn payload_as<P: EventPayloadKind>(&self) -> Option<Result<P, serde_json::Error>> {
(self.kind == P::KIND).then(|| serde_json::from_value(self.payload.clone()))
}
}
impl Client {
pub fn prints(&self) -> Result<PrintsAnswer, ClientError> {
let target = String::from("/v1/prints");
let asked: Vec<(String, String)> = Vec::new();
let sending: Option<serde_json::Value> = None;
self.call("GET", &target, &asked, sending.as_ref())
}
pub fn status(&self, print_id: &str) -> Result<StatusAnswer, ClientError> {
let target = format!("/v1/prints/{print_id}/status");
let asked: Vec<(String, String)> = Vec::new();
let sending: Option<serde_json::Value> = None;
self.call("GET", &target, &asked, sending.as_ref())
}
pub fn context(&self, print_id: &str) -> Result<ContextAnswer, ClientError> {
let target = format!("/v1/prints/{print_id}/context");
let asked: Vec<(String, String)> = Vec::new();
let sending: Option<serde_json::Value> = None;
self.call("GET", &target, &asked, sending.as_ref())
}
pub fn image(&self, image_id: &str) -> Result<ImageAnswer, ClientError> {
let target = format!("/v1/images/{image_id}");
let asked: Vec<(String, String)> = Vec::new();
let sending: Option<serde_json::Value> = None;
self.call("GET", &target, &asked, sending.as_ref())
}
pub fn history(
&self,
print_id: &str,
limit: Option<i64>,
) -> Result<HistoryAnswer, ClientError> {
let target = format!("/v1/prints/{print_id}/history");
let mut asked: Vec<(String, String)> = Vec::new();
if let Some(value) = limit {
asked.push(("limit".to_owned(), value.to_string()));
}
let sending: Option<serde_json::Value> = None;
self.call("GET", &target, &asked, sending.as_ref())
}
pub fn manifest_get(&self, print_id: &str) -> Result<ManifestAnswer, ClientError> {
let target = format!("/v1/prints/{print_id}/manifest");
let asked: Vec<(String, String)> = Vec::new();
let sending: Option<serde_json::Value> = None;
self.call("GET", &target, &asked, sending.as_ref())
}
pub fn look(&self, print_id: &str, wait_s: Option<i64>) -> Result<Look, ClientError> {
let target = format!("/v1/prints/{print_id}/look");
let mut asked: Vec<(String, String)> = Vec::new();
if let Some(value) = wait_s {
asked.push(("wait_s".to_owned(), value.to_string()));
}
let sending: Option<serde_json::Value> = None;
self.call("GET", &target, &asked, sending.as_ref())
}
pub fn manifest_set(
&self,
print_id: &str,
reason: &str,
manifest: &JobManifest,
) -> Result<ManifestAnswer, ClientError> {
crate::reason_given(reason)?;
let target = format!("/v1/prints/{print_id}/manifest");
let asked: Vec<(String, String)> = Vec::new();
let mut sending = serde_json::Map::new();
sending.insert("reason".to_owned(), crate::as_value(&reason)?);
sending.insert("manifest".to_owned(), crate::as_value(&manifest)?);
let sending = Some(serde_json::Value::Object(sending));
self.call("PUT", &target, &asked, sending.as_ref())
}
pub fn spools(&self, include_retired: Option<bool>) -> Result<SpoolsAnswer, ClientError> {
let target = String::from("/v1/spools");
let mut asked: Vec<(String, String)> = Vec::new();
if let Some(value) = include_retired {
asked.push(("include_retired".to_owned(), value.to_string()));
}
let sending: Option<serde_json::Value> = None;
self.call("GET", &target, &asked, sending.as_ref())
}
pub fn spool(&self, spool_id: &str) -> Result<SpoolAnswer, ClientError> {
let target = format!("/v1/spools/{spool_id}");
let asked: Vec<(String, String)> = Vec::new();
let sending: Option<serde_json::Value> = None;
self.call("GET", &target, &asked, sending.as_ref())
}
pub fn printer_history(
&self,
kinds: Option<Vec<String>>,
since: Option<String>,
until: Option<String>,
spool_id: Option<String>,
before: Option<String>,
limit: Option<i64>,
) -> Result<TimelineAnswer, ClientError> {
let target = String::from("/v1/history");
let mut asked: Vec<(String, String)> = Vec::new();
for value in kinds.into_iter().flatten() {
asked.push(("kinds".to_owned(), value));
}
if let Some(value) = since {
asked.push(("since".to_owned(), value));
}
if let Some(value) = until {
asked.push(("until".to_owned(), value));
}
if let Some(value) = spool_id {
asked.push(("spool_id".to_owned(), value));
}
if let Some(value) = before {
asked.push(("before".to_owned(), value));
}
if let Some(value) = limit {
asked.push(("limit".to_owned(), value.to_string()));
}
let sending: Option<serde_json::Value> = None;
self.call("GET", &target, &asked, sending.as_ref())
}
pub fn preflight(&self, file_name: &str) -> Result<PreflightAnswer, ClientError> {
let target = String::from("/v1/preflight");
let asked: Vec<(String, String)> = vec![("file_name".to_owned(), file_name.to_owned())];
let sending: Option<serde_json::Value> = None;
self.call("GET", &target, &asked, sending.as_ref())
}
pub fn pause(&self, print_id: &str, reason: &str) -> Result<ActionAnswer, ClientError> {
crate::reason_given(reason)?;
let target = format!("/v1/prints/{print_id}/actions/pause");
let asked: Vec<(String, String)> = Vec::new();
let mut sending = serde_json::Map::new();
sending.insert("actor".to_owned(), crate::as_value(&self.actor())?);
sending.insert("reason".to_owned(), crate::as_value(&reason)?);
let sending = Some(serde_json::Value::Object(sending));
self.call("POST", &target, &asked, sending.as_ref())
}
pub fn resume(&self, print_id: &str, reason: &str) -> Result<ActionAnswer, ClientError> {
crate::reason_given(reason)?;
let target = format!("/v1/prints/{print_id}/actions/resume");
let asked: Vec<(String, String)> = Vec::new();
let mut sending = serde_json::Map::new();
sending.insert("actor".to_owned(), crate::as_value(&self.actor())?);
sending.insert("reason".to_owned(), crate::as_value(&reason)?);
let sending = Some(serde_json::Value::Object(sending));
self.call("POST", &target, &asked, sending.as_ref())
}
pub fn cancel(&self, print_id: &str, reason: &str) -> Result<ActionAnswer, ClientError> {
crate::reason_given(reason)?;
let target = format!("/v1/prints/{print_id}/actions/cancel");
let asked: Vec<(String, String)> = Vec::new();
let mut sending = serde_json::Map::new();
sending.insert("actor".to_owned(), crate::as_value(&self.actor())?);
sending.insert("reason".to_owned(), crate::as_value(&reason)?);
let sending = Some(serde_json::Value::Object(sending));
self.call("POST", &target, &asked, sending.as_ref())
}
pub fn start_print(
&self,
print_id: &str,
file_name: &FileName,
manifest: &JobManifest,
reason: &str,
override_filament_check: Option<bool>,
) -> Result<ActionAnswer, ClientError> {
crate::reason_given(reason)?;
let target = format!("/v1/prints/{print_id}/actions/start_print");
let asked: Vec<(String, String)> = Vec::new();
let mut sending = serde_json::Map::new();
sending.insert("actor".to_owned(), crate::as_value(&self.actor())?);
sending.insert("file_name".to_owned(), crate::as_value(&file_name)?);
sending.insert("manifest".to_owned(), crate::as_value(&manifest)?);
if let Some(value) = override_filament_check {
sending.insert(
"override_filament_check".to_owned(),
crate::as_value(&value)?,
);
}
sending.insert("reason".to_owned(), crate::as_value(&reason)?);
let sending = Some(serde_json::Value::Object(sending));
self.call("POST", &target, &asked, sending.as_ref())
}
pub fn set_feedrate_factor(
&self,
print_id: &str,
factor: f64,
reason: &str,
duration_s: Option<i64>,
) -> Result<ActionAnswer, ClientError> {
crate::reason_given(reason)?;
let target = format!("/v1/prints/{print_id}/actions/set_feedrate_factor");
let asked: Vec<(String, String)> = Vec::new();
let mut sending = serde_json::Map::new();
sending.insert("actor".to_owned(), crate::as_value(&self.actor())?);
if let Some(value) = duration_s {
sending.insert("duration_s".to_owned(), crate::as_value(&value)?);
}
sending.insert("factor".to_owned(), crate::as_value(&factor)?);
sending.insert("reason".to_owned(), crate::as_value(&reason)?);
let sending = Some(serde_json::Value::Object(sending));
self.call("POST", &target, &asked, sending.as_ref())
}
pub fn set_flowrate_factor(
&self,
print_id: &str,
factor: f64,
reason: &str,
duration_s: Option<i64>,
) -> Result<ActionAnswer, ClientError> {
crate::reason_given(reason)?;
let target = format!("/v1/prints/{print_id}/actions/set_flowrate_factor");
let asked: Vec<(String, String)> = Vec::new();
let mut sending = serde_json::Map::new();
sending.insert("actor".to_owned(), crate::as_value(&self.actor())?);
if let Some(value) = duration_s {
sending.insert("duration_s".to_owned(), crate::as_value(&value)?);
}
sending.insert("factor".to_owned(), crate::as_value(&factor)?);
sending.insert("reason".to_owned(), crate::as_value(&reason)?);
let sending = Some(serde_json::Value::Object(sending));
self.call("POST", &target, &asked, sending.as_ref())
}
pub fn set_tool_target_c(
&self,
print_id: &str,
reason: &str,
target_c: f64,
tool: i64,
duration_s: Option<i64>,
) -> Result<ActionAnswer, ClientError> {
crate::reason_given(reason)?;
let target = format!("/v1/prints/{print_id}/actions/set_tool_target_c");
let asked: Vec<(String, String)> = Vec::new();
let mut sending = serde_json::Map::new();
sending.insert("actor".to_owned(), crate::as_value(&self.actor())?);
if let Some(value) = duration_s {
sending.insert("duration_s".to_owned(), crate::as_value(&value)?);
}
sending.insert("reason".to_owned(), crate::as_value(&reason)?);
sending.insert("target_c".to_owned(), crate::as_value(&target_c)?);
sending.insert("tool".to_owned(), crate::as_value(&tool)?);
let sending = Some(serde_json::Value::Object(sending));
self.call("POST", &target, &asked, sending.as_ref())
}
pub fn set_bed_target_c(
&self,
print_id: &str,
reason: &str,
target_c: f64,
duration_s: Option<i64>,
) -> Result<ActionAnswer, ClientError> {
crate::reason_given(reason)?;
let target = format!("/v1/prints/{print_id}/actions/set_bed_target_c");
let asked: Vec<(String, String)> = Vec::new();
let mut sending = serde_json::Map::new();
sending.insert("actor".to_owned(), crate::as_value(&self.actor())?);
if let Some(value) = duration_s {
sending.insert("duration_s".to_owned(), crate::as_value(&value)?);
}
sending.insert("reason".to_owned(), crate::as_value(&reason)?);
sending.insert("target_c".to_owned(), crate::as_value(&target_c)?);
let sending = Some(serde_json::Value::Object(sending));
self.call("POST", &target, &asked, sending.as_ref())
}
pub fn set_fan_percent(
&self,
print_id: &str,
percent: f64,
reason: &str,
duration_s: Option<i64>,
) -> Result<ActionAnswer, ClientError> {
crate::reason_given(reason)?;
let target = format!("/v1/prints/{print_id}/actions/set_fan_percent");
let asked: Vec<(String, String)> = Vec::new();
let mut sending = serde_json::Map::new();
sending.insert("actor".to_owned(), crate::as_value(&self.actor())?);
if let Some(value) = duration_s {
sending.insert("duration_s".to_owned(), crate::as_value(&value)?);
}
sending.insert("percent".to_owned(), crate::as_value(&percent)?);
sending.insert("reason".to_owned(), crate::as_value(&reason)?);
let sending = Some(serde_json::Value::Object(sending));
self.call("POST", &target, &asked, sending.as_ref())
}
pub fn acknowledge_failure(
&self,
print_id: &str,
disposition: &AcknowledgementDisposition,
event_id: &EventId,
reason: &str,
) -> Result<ActionAnswer, ClientError> {
crate::reason_given(reason)?;
let target = format!("/v1/prints/{print_id}/actions/acknowledge_failure");
let asked: Vec<(String, String)> = Vec::new();
let mut sending = serde_json::Map::new();
sending.insert("actor".to_owned(), crate::as_value(&self.actor())?);
sending.insert("disposition".to_owned(), crate::as_value(&disposition)?);
sending.insert("event_id".to_owned(), crate::as_value(&event_id)?);
sending.insert("reason".to_owned(), crate::as_value(&reason)?);
let sending = Some(serde_json::Value::Object(sending));
self.call("POST", &target, &asked, sending.as_ref())
}
#[expect(clippy::too_many_arguments)]
pub fn register_spool(
&self,
initial_g: f64,
material: &str,
name: &str,
reason: &str,
color: Option<String>,
density_g_cm3: Option<f64>,
diameter_mm: Option<f64>,
remaining_g: Option<f64>,
tare_g: Option<f64>,
) -> Result<SpoolCommandAnswer, ClientError> {
crate::reason_given(reason)?;
let target = String::from("/v1/spools/actions/register_spool");
let asked: Vec<(String, String)> = Vec::new();
let mut sending = serde_json::Map::new();
sending.insert("actor".to_owned(), crate::as_value(&self.actor())?);
if let Some(value) = color {
sending.insert("color".to_owned(), crate::as_value(&value)?);
}
if let Some(value) = density_g_cm3 {
sending.insert("density_g_cm3".to_owned(), crate::as_value(&value)?);
}
if let Some(value) = diameter_mm {
sending.insert("diameter_mm".to_owned(), crate::as_value(&value)?);
}
sending.insert("initial_g".to_owned(), crate::as_value(&initial_g)?);
sending.insert("material".to_owned(), crate::as_value(&material)?);
sending.insert("name".to_owned(), crate::as_value(&name)?);
sending.insert("reason".to_owned(), crate::as_value(&reason)?);
if let Some(value) = remaining_g {
sending.insert("remaining_g".to_owned(), crate::as_value(&value)?);
}
if let Some(value) = tare_g {
sending.insert("tare_g".to_owned(), crate::as_value(&value)?);
}
let sending = Some(serde_json::Value::Object(sending));
self.call("POST", &target, &asked, sending.as_ref())
}
pub fn load_spool(
&self,
spool_id: &str,
reason: &str,
tool: i64,
) -> Result<SpoolCommandAnswer, ClientError> {
crate::reason_given(reason)?;
let target = format!("/v1/spools/{spool_id}/actions/load_spool");
let asked: Vec<(String, String)> = Vec::new();
let mut sending = serde_json::Map::new();
sending.insert("actor".to_owned(), crate::as_value(&self.actor())?);
sending.insert("reason".to_owned(), crate::as_value(&reason)?);
sending.insert("tool".to_owned(), crate::as_value(&tool)?);
let sending = Some(serde_json::Value::Object(sending));
self.call("POST", &target, &asked, sending.as_ref())
}
pub fn unload_spool(
&self,
spool_id: &str,
reason: &str,
) -> Result<SpoolCommandAnswer, ClientError> {
crate::reason_given(reason)?;
let target = format!("/v1/spools/{spool_id}/actions/unload_spool");
let asked: Vec<(String, String)> = Vec::new();
let mut sending = serde_json::Map::new();
sending.insert("actor".to_owned(), crate::as_value(&self.actor())?);
sending.insert("reason".to_owned(), crate::as_value(&reason)?);
let sending = Some(serde_json::Value::Object(sending));
self.call("POST", &target, &asked, sending.as_ref())
}
pub fn adjust_spool(
&self,
spool_id: &str,
reason: &str,
gross_g: Option<f64>,
remaining_g: Option<f64>,
) -> Result<SpoolCommandAnswer, ClientError> {
crate::reason_given(reason)?;
let target = format!("/v1/spools/{spool_id}/actions/adjust_spool");
let asked: Vec<(String, String)> = Vec::new();
let mut sending = serde_json::Map::new();
sending.insert("actor".to_owned(), crate::as_value(&self.actor())?);
if let Some(value) = gross_g {
sending.insert("gross_g".to_owned(), crate::as_value(&value)?);
}
sending.insert("reason".to_owned(), crate::as_value(&reason)?);
if let Some(value) = remaining_g {
sending.insert("remaining_g".to_owned(), crate::as_value(&value)?);
}
let sending = Some(serde_json::Value::Object(sending));
self.call("POST", &target, &asked, sending.as_ref())
}
pub fn retire_spool(
&self,
spool_id: &str,
reason: &str,
) -> Result<SpoolCommandAnswer, ClientError> {
crate::reason_given(reason)?;
let target = format!("/v1/spools/{spool_id}/actions/retire_spool");
let asked: Vec<(String, String)> = Vec::new();
let mut sending = serde_json::Map::new();
sending.insert("actor".to_owned(), crate::as_value(&self.actor())?);
sending.insert("reason".to_owned(), crate::as_value(&reason)?);
let sending = Some(serde_json::Value::Object(sending));
self.call("POST", &target, &asked, sending.as_ref())
}
}