printobserver_sdk/contract.rs
1//! Generated by `contract-codegen` from the checked-in contract schemas.
2//!
3//! This file is the Rust client's request and response types.
4//!
5//! Do not edit by hand: change the contracts, regenerate with `just
6//! generate-clients`, and commit what that writes.
7
8use std::collections::BTreeMap;
9
10use serde::{Deserialize, Serialize};
11
12use crate::{Client, ClientError};
13
14/// The version of the server contract these types were generated from: the
15/// version of the workspace this crate is compiled from. A published crate
16/// reports the release version it was built at, and a crate compiled from a
17/// checkout reports that checkout's workspace version.
18pub const CONTRACT_VERSION: &str = env!("CARGO_PKG_VERSION");
19
20/// Every operation this client exposes a method for, which is every operation
21/// the server declares and no other.
22pub const OPERATION_NAMES: [&str; 17] = [
23 "prints",
24 "status",
25 "context",
26 "image",
27 "history",
28 "manifest_get",
29 "manifest_set",
30 "pause",
31 "resume",
32 "cancel",
33 "start_print",
34 "set_feedrate_factor",
35 "set_flowrate_factor",
36 "set_tool_target_c",
37 "set_bed_target_c",
38 "set_fan_percent",
39 "acknowledge_failure",
40];
41
42/// What an operator's acknowledgement of a failure event asks for next.
43#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)]
44pub enum AcknowledgementDisposition {
45 /// Carry on printing.
46 #[serde(rename = "continue")]
47 Continue,
48 /// Carry on printing, watched more closely.
49 #[serde(rename = "watch")]
50 Watch,
51 /// Stop the print.
52 #[serde(rename = "stop")]
53 Stop,
54}
55
56/// What one mutating request left behind it.
57#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
58pub struct ActionAnswer {
59 /// The bounded intervention it opened, when it opened one.
60 #[serde(default, skip_serializing_if = "Option::is_none")]
61 pub intervention: Option<Intervention>,
62 /// What the printer said, when the request reached it and it refused.
63 #[serde(default, skip_serializing_if = "Option::is_none")]
64 pub printer_refusal: Option<String>,
65 /// The record of the request and the decision taken on it. A rejected
66 /// request's rejection is here, carrying its reason, the value asked for
67 /// and the range allowed, so a caller can ask again inside the range.
68 pub record: ActionRecord,
69}
70
71/// An accepted action reached the printer.
72#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
73pub struct ActionExecutedPayload {
74 /// The action's identifier.
75 pub action_id: ActionId,
76 /// The bounded intervention it opened, when it opened one.
77 #[serde(default, skip_serializing_if = "Option::is_none")]
78 pub intervention_id: Option<InterventionId>,
79}
80
81/// A lowercase hyphenated version 7 UUID identifying one requested action.
82pub type ActionId = String;
83
84/// One action of the closed vocabulary, named without its payload.
85///
86/// This is what a safety envelope grants and what a policy rejection names;
87/// the
88/// payload lives on `PrintAction` itself.
89#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)]
90pub enum ActionKind {
91 /// Pause the print.
92 #[serde(rename = "pause")]
93 Pause,
94 /// Resume the print.
95 #[serde(rename = "resume")]
96 Resume,
97 /// Cancel the print.
98 #[serde(rename = "cancel")]
99 Cancel,
100 /// Start a print of a named file.
101 #[serde(rename = "start_print")]
102 StartPrint,
103 /// Set the feedrate factor.
104 #[serde(rename = "set_feedrate_factor")]
105 SetFeedrateFactor,
106 /// Set the flowrate factor.
107 #[serde(rename = "set_flowrate_factor")]
108 SetFlowrateFactor,
109 /// Set a tool's target temperature.
110 #[serde(rename = "set_tool_target_c")]
111 SetToolTargetC,
112 /// Set the bed's target temperature.
113 #[serde(rename = "set_bed_target_c")]
114 SetBedTargetC,
115 /// Set the fan percentage.
116 #[serde(rename = "set_fan_percent")]
117 SetFanPercent,
118 /// Acknowledge a failure event.
119 #[serde(rename = "acknowledge_failure")]
120 AcknowledgeFailure,
121}
122
123/// One request, the decision taken on it, and what became of it.
124///
125/// `executed_at` and `outcome` are both optional and are absent together: a
126/// record is written when the decision is taken, which is before — and, for a
127/// rejected request, instead of — anything reaching the printer.
128#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
129pub struct ActionRecord {
130 /// The decision policy took on it.
131 pub decision: PolicyDecision,
132 /// When it reached the printer, if it did.
133 #[serde(default, skip_serializing_if = "Option::is_none")]
134 pub executed_at: Option<Timestamp>,
135 /// This record's identifier, minted by the store.
136 pub id: ActionId,
137 /// What the printer made of it, if it reached the printer.
138 #[serde(default, skip_serializing_if = "Option::is_none")]
139 pub outcome: Option<ExecutionOutcome>,
140 /// The print this request was made against.
141 pub print_id: PrintId,
142 /// The request itself.
143 pub request: ActionRequest,
144}
145
146/// Policy refused an action.
147#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
148pub struct ActionRejectedPayload {
149 /// The action's identifier.
150 pub action_id: ActionId,
151 /// The whole decision, carrying which rejection it was.
152 pub decision: PolicyDecision,
153}
154
155/// One request an actor made, at the instant it made it.
156#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
157pub struct ActionRequest {
158 /// What was asked for.
159 pub action: PrintAction,
160 /// Who asked.
161 pub actor: Actor,
162 /// When they asked.
163 pub requested_at: Timestamp,
164}
165
166/// An actor asked for an action.
167#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
168pub struct ActionRequestedPayload {
169 /// What was asked for.
170 pub action: PrintAction,
171 /// The action's identifier.
172 pub action_id: ActionId,
173 /// Who asked.
174 pub actor: Actor,
175}
176
177/// Who asked for something.
178#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
179pub enum Actor {
180 /// The supervising agent, naming its session.
181 #[serde(rename = "agent")]
182 Agent {
183 /// The supervision session the agent is acting in.
184 session_name: String,
185 },
186 /// A person.
187 #[serde(rename = "operator")]
188 Operator,
189 /// The supervisor itself.
190 #[serde(rename = "system")]
191 System,
192}
193
194/// An actor class, which is what a safety envelope grants actions to.
195#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)]
196pub enum ActorClass {
197 /// The supervising agent.
198 #[serde(rename = "agent")]
199 Agent,
200 /// A person.
201 #[serde(rename = "operator")]
202 Operator,
203 /// The supervisor itself.
204 #[serde(rename = "system")]
205 System,
206}
207
208/// One thing an adjustment may change.
209pub type Adjustable = String;
210
211/// The agent's written record of one supervision turn.
212///
213/// This is deliberately not how the agent acts: acting is a
214/// `PrintAction` that policy rules on.
215#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
216pub struct AgentAssessment {
217 /// How sure the agent is.
218 pub confidence: Confidence,
219 /// What the agent did.
220 pub did: String,
221 /// Whether the agent is escalating to a person.
222 pub escalating: bool,
223 /// Whether the print should carry on.
224 pub should_continue: bool,
225 /// One line saying what is happening.
226 pub summary: String,
227 /// Why it did it.
228 pub why: String,
229}
230
231/// The agent wrote down what it made of a turn.
232#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
233pub struct AgentAssessmentPayload {
234 /// What the agent answered with.
235 pub assessment: AgentAssessment,
236 /// The session the turn ran in.
237 pub session_name: String,
238}
239
240/// How sure the agent is.
241///
242/// A closed vocabulary rather than a number, because a number invites a
243/// precision the agent does not have.
244#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)]
245pub enum Confidence {
246 /// Not sure.
247 #[serde(rename = "low")]
248 Low,
249 /// Fairly sure.
250 #[serde(rename = "medium")]
251 Medium,
252 /// Sure.
253 #[serde(rename = "high")]
254 High,
255}
256
257/// What a context read answers.
258///
259/// The latest image is **materialized** here rather than left as the handle
260/// `PrintContext` carries: the one thing a supervision turn does with an
261/// image is look at it, and a handle is not something anything can open. The
262/// path is absolute on this server's own filesystem, exactly as
263/// `ImageAnswer`'s is, and is absent when there is no image or when the
264/// record is intact and the file is not.
265#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
266pub struct ContextAnswer {
267 /// Everything a supervision turn is given about the print.
268 pub context: PrintContext,
269 /// Where the latest image's bytes are, absolute on this host.
270 #[serde(default, skip_serializing_if = "Option::is_none")]
271 pub image_path: Option<String>,
272}
273
274/// The envelope intersected with the print's manifest.
275///
276/// This is what context reports, so that the agent can see its own limits
277/// before it asks. Computing one is the supervision core's; this crate
278/// declares
279/// the shape and nothing that produces it.
280#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
281pub struct EffectiveBounds {
282 /// The range each adjustable may be set to, inclusive.
283 pub allowed: BTreeMap<String, Range>,
284}
285
286/// What this server answers when it will not do what it was asked.
287#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
288pub struct ErrorAnswer {
289 /// One line saying why, in the words of whatever refused it.
290 pub error: String,
291}
292
293/// A lowercase hyphenated version 7 UUID identifying one event.
294pub type EventId = String;
295
296/// The name one kind of event is written down under: lowercase `snake_case`,
297/// declared by the domain that owns the event.
298pub type EventKind = String;
299
300/// One event, as the store holds it and the server serves it.
301///
302/// `raw` holds the bytes exactly as received for an externally sourced event
303/// and is absent for an internally raised one — it is what makes the history
304/// auditable when a normalization turns out to be wrong. `print_id` is
305/// optional, because an externally sourced event may name no print this
306/// system
307/// knows.
308#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
309pub struct EventRecord {
310 /// This event's identifier, minted by the store.
311 pub id: EventId,
312 /// The image it arrived with, when it arrived with one.
313 #[serde(default, skip_serializing_if = "Option::is_none")]
314 pub image: Option<ImageRef>,
315 /// Which event this is.
316 pub kind: EventKind,
317 /// What it carries, in the form its kind declares.
318 pub payload: serde_json::Value,
319 /// The print it belongs to, when it belongs to one.
320 #[serde(default, skip_serializing_if = "Option::is_none")]
321 pub print_id: Option<PrintId>,
322 /// The bytes exactly as received, for an externally sourced event.
323 #[serde(default, skip_serializing_if = "Option::is_none")]
324 pub raw: Option<RawBytes>,
325 /// When it was received.
326 pub received_at: Timestamp,
327 /// Where it came from.
328 pub source: EventSource,
329}
330
331/// Where an event came from, as the bare string the domain that raised it
332/// declares for itself.
333pub type EventSource = String;
334
335/// What happened when an accepted action reached the printer.
336#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
337pub enum ExecutionOutcome {
338 /// The printer took it.
339 #[serde(rename = "succeeded")]
340 Succeeded,
341 /// The printer did not, for this reason.
342 #[serde(rename = "failed")]
343 Failed {
344 /// Why it failed.
345 reason: String,
346 },
347}
348
349/// A file name a printer's own file API can be asked for: no path separator,
350/// no NUL byte, no `.` or `..` segment, no drive prefix, and not empty.
351pub type FileName = String;
352
353/// One heater, as a source reported it.
354///
355/// Every field is optional, because a source that reports no heater at all
356/// reports none of these; each is a plausibility-ranged reported value in
357/// degrees Celsius.
358#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
359pub struct HeaterSnapshot {
360 /// The temperature the heater is at.
361 #[serde(default, skip_serializing_if = "Option::is_none")]
362 pub actual_c: Option<Reported>,
363 /// The offset applied to this heater's target.
364 #[serde(default, skip_serializing_if = "Option::is_none")]
365 pub offset_c: Option<Reported>,
366 /// The temperature the heater is driving towards.
367 #[serde(default, skip_serializing_if = "Option::is_none")]
368 pub target_c: Option<Reported>,
369}
370
371/// What a history read answers.
372#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
373pub struct HistoryAnswer {
374 /// The print's events, newest first.
375 pub events: Vec<EventRecord>,
376}
377
378/// What an image read answers.
379///
380/// The path is absolute on this server's own filesystem, and is the whole of
381/// the answer about the bytes: nothing here renders them, encodes them or
382/// serves them. It is absent when the record is intact and the file is not,
383/// which is a different answer from there being no such image.
384#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
385pub struct ImageAnswer {
386 /// Where its bytes are, absolute on this host.
387 #[serde(default, skip_serializing_if = "Option::is_none")]
388 pub path: Option<String>,
389 /// The record.
390 pub record: ImageRecord,
391}
392
393/// A lowercase hyphenated version 7 UUID identifying one image.
394pub type ImageId = String;
395
396/// One image, stored beside the event it arrived with.
397///
398/// `relative_path` is relative to the configured state directory, so that the
399/// store stays portable. Materializing an image resolves that to an absolute
400/// path; nothing in this system renders image bytes into JSON.
401#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
402pub struct ImageRecord {
403 /// How many bytes it is.
404 pub byte_len: i64,
405 /// The content type it was served as.
406 pub content_type: String,
407 /// The event it arrived with.
408 pub event_id: EventId,
409 /// When it was fetched.
410 pub fetched_at: Timestamp,
411 /// This image's identifier, minted by the store.
412 pub id: ImageId,
413 /// The print it belongs to.
414 pub print_id: PrintId,
415 /// Where it lives, relative to the configured state directory.
416 pub relative_path: String,
417 /// The SHA-256 of its bytes, lowercase hexadecimal.
418 pub sha256: String,
419 /// Where it was fetched from, when it was fetched from somewhere.
420 #[serde(default, skip_serializing_if = "Option::is_none")]
421 pub source_url: Option<String>,
422}
423
424/// The handle an image travels in context under.
425#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
426pub struct ImageRef {
427 /// The image's identifier.
428 pub id: ImageId,
429 /// The SHA-256 of its bytes, lowercase hexadecimal.
430 pub sha256: String,
431}
432
433/// One adjustment made for a bounded time.
434///
435/// `prior_value` is read from the printer snapshot taken before the change,
436/// and
437/// is absent when the printer reported none — in which case expiry restores
438/// nothing and the outcome says so rather than guessing a default.
439#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
440pub struct Intervention {
441 /// The action that asked for it.
442 pub action_id: ActionId,
443 /// What it changed.
444 pub adjustable: Adjustable,
445 /// When it was applied.
446 pub applied_at: Timestamp,
447 /// What it was changed to.
448 pub applied_value: f64,
449 /// When it stops standing.
450 pub expires_at: Timestamp,
451 /// This intervention's identifier, minted by the store.
452 pub id: InterventionId,
453 /// What became of it.
454 pub outcome: InterventionOutcome,
455 /// The print it was made against.
456 pub print_id: PrintId,
457 /// What the printer reported before the change, if it reported anything.
458 #[serde(default, skip_serializing_if = "Option::is_none")]
459 pub prior_value: Option<f64>,
460 /// When the prior value was put back, if it was.
461 #[serde(default, skip_serializing_if = "Option::is_none")]
462 pub restored_at: Option<Timestamp>,
463}
464
465/// A bounded intervention expired.
466#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
467pub struct InterventionExpiredPayload {
468 /// What it had changed.
469 pub adjustable: Adjustable,
470 /// The intervention's identifier.
471 pub intervention_id: InterventionId,
472 /// What became of it.
473 pub outcome: InterventionOutcome,
474}
475
476/// A lowercase hyphenated version 7 UUID identifying one bounded
477/// intervention.
478pub type InterventionId = String;
479
480/// What became of a bounded change.
481#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
482pub enum InterventionOutcome {
483 /// It is still in force.
484 #[serde(rename = "still_active")]
485 StillActive,
486 /// The prior value was put back.
487 #[serde(rename = "restored")]
488 Restored,
489 /// There was no prior value to put back.
490 #[serde(rename = "restore_unavailable")]
491 RestoreUnavailable,
492 /// Putting the prior value back failed.
493 #[serde(rename = "restore_failed")]
494 RestoreFailed {
495 /// Why it failed.
496 reason: String,
497 },
498 /// Another intervention replaced it before it expired.
499 #[serde(rename = "superseded")]
500 Superseded {
501 /// The intervention that replaced it.
502 by: InterventionId,
503 },
504}
505
506/// What a sliced job declares about itself and about what may be adjusted.
507///
508/// An adjustable the manifest does not name takes the envelope's own range; a
509/// manifest range wider than the envelope's is narrowed to the envelope's and
510/// the narrowing is recorded on the print. A manifest may only narrow.
511#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
512pub struct JobManifest {
513 /// The range each named adjustable may take, inclusive.
514 pub allowed: BTreeMap<String, Range>,
515 /// The file this manifest is about, as the slicer named it.
516 pub file_name: String,
517 /// The material the job is sliced for.
518 pub material: String,
519 /// Whatever else the slicer recorded.
520 pub metadata: BTreeMap<String, String>,
521 /// The nozzle the job is sliced for, in millimetres.
522 pub nozzle_diameter_mm: f64,
523 /// The slicer profile the job was sliced with.
524 pub slicer_profile: String,
525}
526
527/// The job a printer reports it is running.
528///
529/// Every field but `state` is optional: an absent one means the source did
530/// not
531/// report it.
532#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
533pub struct JobSnapshot {
534 /// How far through the print is, as a fraction from zero to one.
535 ///
536 /// Normalized to a fraction here regardless of how the source expresses
537 /// it.
538 #[serde(default, skip_serializing_if = "Option::is_none")]
539 pub completion: Option<Reported>,
540 /// The error the source reports, when it reports one.
541 #[serde(default, skip_serializing_if = "Option::is_none")]
542 pub error: Option<String>,
543 /// The whole print's estimated duration, in whole seconds.
544 #[serde(default, skip_serializing_if = "Option::is_none")]
545 pub estimated_print_time_s: Option<i64>,
546 /// The name of the file being printed, as the source reported it.
547 #[serde(default, skip_serializing_if = "Option::is_none")]
548 pub file_name: Option<String>,
549 /// Where the file lives, in the source's own vocabulary.
550 #[serde(default, skip_serializing_if = "Option::is_none")]
551 pub file_origin: Option<String>,
552 /// How long the print has left, in whole seconds.
553 #[serde(default, skip_serializing_if = "Option::is_none")]
554 pub print_time_left_s: Option<i64>,
555 /// How long the print has been running, in whole seconds.
556 #[serde(default, skip_serializing_if = "Option::is_none")]
557 pub print_time_s: Option<i64>,
558 /// The file's size in bytes.
559 #[serde(default, skip_serializing_if = "Option::is_none")]
560 pub size_bytes: Option<i64>,
561 /// The state the source reports the job to be in.
562 pub state: PrinterState,
563}
564
565/// An external body arrived that could not be read.
566///
567/// This kind always carries its `raw` bytes, and it exists so that an alert
568/// this system cannot read is written down rather than dropped.
569#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
570pub struct MalformedExternalEventPayload {
571 /// One line saying why the body could not be read.
572 pub detail: String,
573}
574
575/// What a manifest read or write answers.
576#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
577pub struct ManifestAnswer {
578 /// The manifest, when the print has one.
579 #[serde(default, skip_serializing_if = "Option::is_none")]
580 pub manifest: Option<JobManifest>,
581 /// Every range this manifest asked wider than the envelope allows,
582 /// narrowed
583 /// to the envelope's — recorded on the print, so nobody has to wonder
584 /// later
585 /// which bound applied.
586 pub narrowings: Vec<ManifestNarrowing>,
587}
588
589/// One adjustable whose manifest range was wider than the envelope's.
590#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
591pub struct ManifestNarrowing {
592 /// The adjustable that was narrowed.
593 pub adjustable: Adjustable,
594 /// The range that stands.
595 pub applied: Range,
596 /// The range the manifest asked for.
597 pub requested: Range,
598}
599
600/// Obico reported a print failure.
601///
602/// The two instants are optional because Obico's own field for each is a Unix
603/// timestamp number, an empty string, or absent, and the last two both mean
604/// the
605/// producer reported no instant. An absent field here is that, never an epoch
606/// date standing in for it.
607#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
608pub struct ObicoFailureAlertPayload {
609 /// When the print ended, when Obico reported an instant for it.
610 #[serde(default, skip_serializing_if = "Option::is_none")]
611 pub ended_at: Option<Timestamp>,
612 /// The file being printed, when Obico named one.
613 #[serde(default, skip_serializing_if = "Option::is_none")]
614 pub file_name: Option<String>,
615 /// Whether Obico called it a warning rather than a failure.
616 pub is_warning: bool,
617 /// Obico's own identifier for the print, when it named one.
618 #[serde(default, skip_serializing_if = "Option::is_none")]
619 pub obico_print_id: Option<i64>,
620 /// Whether Obico paused the print itself.
621 pub print_paused: bool,
622 /// When the print started, when Obico reported an instant for it.
623 #[serde(default, skip_serializing_if = "Option::is_none")]
624 pub started_at: Option<Timestamp>,
625}
626
627/// The kind of printer notification Obico sent, normalized.
628#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)]
629pub enum ObicoNotificationType {
630 /// A print started.
631 #[serde(rename = "started")]
632 Started,
633 /// A print finished.
634 #[serde(rename = "done")]
635 Done,
636 /// A print was cancelled.
637 #[serde(rename = "cancelled")]
638 Cancelled,
639 /// A print was paused.
640 #[serde(rename = "paused")]
641 Paused,
642 /// A print was resumed.
643 #[serde(rename = "resumed")]
644 Resumed,
645 /// The printer is waiting for a filament change.
646 #[serde(rename = "filament_change")]
647 FilamentChange,
648 /// A heater cooled down.
649 #[serde(rename = "heater_cooled")]
650 HeaterCooled,
651 /// A heater reached its target.
652 #[serde(rename = "heater_target")]
653 HeaterTarget,
654}
655
656/// Obico sent a printer notification.
657///
658/// The two instants are optional for the same reason
659/// `ObicoFailureAlertPayload`'s are, and are absent along with the rest of
660/// the print's fields when the notification is about no print at all.
661#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
662pub struct ObicoPrinterNotificationPayload {
663 /// When the print ended, when Obico reported an instant for it.
664 #[serde(default, skip_serializing_if = "Option::is_none")]
665 pub ended_at: Option<Timestamp>,
666 /// The file being printed, when the notification is about one.
667 #[serde(default, skip_serializing_if = "Option::is_none")]
668 pub file_name: Option<String>,
669 /// Which notification it is.
670 pub notification_type: ObicoNotificationType,
671 /// Obico's own identifier for the print, when the notification is about
672 /// one.
673 #[serde(default, skip_serializing_if = "Option::is_none")]
674 pub obico_print_id: Option<i64>,
675 /// When the print started, when Obico reported an instant for it.
676 #[serde(default, skip_serializing_if = "Option::is_none")]
677 pub started_at: Option<Timestamp>,
678}
679
680/// An operator acknowledged an event.
681#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
682pub struct OperatorAcknowledgementPayload {
683 /// The event being acknowledged.
684 pub acknowledged_event_id: EventId,
685 /// What the operator asked for next.
686 pub disposition: AcknowledgementDisposition,
687}
688
689/// The decision policy took on one request.
690#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
691pub enum PolicyDecision {
692 /// The request may proceed.
693 #[serde(rename = "accepted")]
694 Accepted,
695 /// The request may not, for this reason.
696 #[serde(rename = "rejected")]
697 Rejected(RejectionReason),
698}
699
700/// A port failed while one event was being handled.
701///
702/// The event is named rather than implied, so that a reader holding an
703/// event's
704/// identifier reaches every failure recorded while that event was being
705/// handled. A failure recorded here is one the handling survived: the event
706/// is
707/// already in the history by the time any of these sites is reached, and the
708/// loop goes on to handle the next event.
709#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
710pub struct PortFailurePayload {
711 /// What the port said about it, in the port's own words.
712 pub detail: String,
713 /// The event whose handling reached the failing call.
714 pub event_id: EventId,
715 /// Where it failed.
716 pub site: PortFailureSite,
717}
718
719/// Where a port failed while an event was being handled.
720///
721/// A closed set of exactly the sites at which a failure has nowhere else to
722/// be
723/// recorded. The printer's action methods record theirs on the
724/// `ActionRecord` the request minted, and a restoring
725/// call records its own on the `Intervention` it was
726/// expiring; those are not sites here, because a second record of them would
727/// be
728/// a second version of one fact.
729#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)]
730pub enum PortFailureSite {
731 /// Reading the printer's own state.
732 #[serde(rename = "printer_snapshot")]
733 PrinterSnapshot,
734 /// Reading the job the printer reports it is running.
735 #[serde(rename = "printer_job")]
736 PrinterJob,
737 /// Writing the image the event arrived with.
738 #[serde(rename = "image_write")]
739 ImageWrite,
740 /// Running the supervision turn the event prompted.
741 #[serde(rename = "supervision_turn")]
742 SupervisionTurn,
743}
744
745/// The whole vocabulary an actor may ask for, and there is no other.
746#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
747#[serde(tag = "action")]
748pub enum PrintAction {
749 /// Pause the print.
750 #[serde(rename = "pause")]
751 Pause {
752 /// Who is asking.
753 actor: Actor,
754 /// Why the actor is asking for this.
755 reason: String,
756 },
757 /// Resume the print.
758 #[serde(rename = "resume")]
759 Resume {
760 /// Who is asking.
761 actor: Actor,
762 /// Why the actor is asking for this.
763 reason: String,
764 },
765 /// Cancel the print.
766 #[serde(rename = "cancel")]
767 Cancel {
768 /// Who is asking.
769 actor: Actor,
770 /// Why the actor is asking for this.
771 reason: String,
772 },
773 /// Start a print of a named file, with a manifest.
774 #[serde(rename = "start_print")]
775 StartPrint {
776 /// Who is asking.
777 actor: Actor,
778 /// The file to print, validated as a name a file API can be asked
779 /// for.
780 file_name: FileName,
781 /// The manifest this print is bounded by.
782 manifest: JobManifest,
783 /// Why the actor is asking for this.
784 reason: String,
785 },
786 /// Set the feedrate factor, where one means one hundred percent.
787 #[serde(rename = "set_feedrate_factor")]
788 SetFeedrateFactor {
789 /// Who is asking.
790 actor: Actor,
791 /// How long the change stands for, in whole seconds.
792 #[serde(default, skip_serializing_if = "Option::is_none")]
793 duration_s: Option<i64>,
794 /// The multiplier asked for.
795 factor: f64,
796 /// Why the actor is asking for this.
797 reason: String,
798 },
799 /// Set the flowrate factor, where one means one hundred percent.
800 #[serde(rename = "set_flowrate_factor")]
801 SetFlowrateFactor {
802 /// Who is asking.
803 actor: Actor,
804 /// How long the change stands for, in whole seconds.
805 #[serde(default, skip_serializing_if = "Option::is_none")]
806 duration_s: Option<i64>,
807 /// The multiplier asked for.
808 factor: f64,
809 /// Why the actor is asking for this.
810 reason: String,
811 },
812 /// Set one tool's target temperature.
813 #[serde(rename = "set_tool_target_c")]
814 SetToolTargetC {
815 /// Who is asking.
816 actor: Actor,
817 /// How long the change stands for, in whole seconds.
818 #[serde(default, skip_serializing_if = "Option::is_none")]
819 duration_s: Option<i64>,
820 /// Why the actor is asking for this.
821 reason: String,
822 /// The target temperature asked for, in degrees Celsius.
823 target_c: f64,
824 /// The tool, in the printer's own numbering.
825 tool: i64,
826 },
827 /// Set the bed's target temperature.
828 #[serde(rename = "set_bed_target_c")]
829 SetBedTargetC {
830 /// Who is asking.
831 actor: Actor,
832 /// How long the change stands for, in whole seconds.
833 #[serde(default, skip_serializing_if = "Option::is_none")]
834 duration_s: Option<i64>,
835 /// Why the actor is asking for this.
836 reason: String,
837 /// The target temperature asked for, in degrees Celsius.
838 target_c: f64,
839 },
840 /// Set the part-cooling fan percentage.
841 #[serde(rename = "set_fan_percent")]
842 SetFanPercent {
843 /// Who is asking.
844 actor: Actor,
845 /// How long the change stands for, in whole seconds.
846 #[serde(default, skip_serializing_if = "Option::is_none")]
847 duration_s: Option<i64>,
848 /// The percentage asked for.
849 percent: f64,
850 /// Why the actor is asking for this.
851 reason: String,
852 },
853 /// Acknowledge a failure event, with a disposition.
854 #[serde(rename = "acknowledge_failure")]
855 AcknowledgeFailure {
856 /// Who is asking.
857 actor: Actor,
858 /// What to do next.
859 disposition: AcknowledgementDisposition,
860 /// The event being acknowledged.
861 event_id: EventId,
862 /// Why the actor is asking for this.
863 reason: String,
864 },
865}
866
867/// Everything a supervision turn is given about one print.
868#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
869pub struct PrintContext {
870 /// The limits in force, so that the agent can see them before it asks.
871 pub bounds: EffectiveBounds,
872 /// The interventions still active.
873 pub interventions: Vec<Intervention>,
874 /// The job, when a snapshot could be taken.
875 #[serde(default, skip_serializing_if = "Option::is_none")]
876 pub job: Option<JobSnapshot>,
877 /// The most recent image, when there is one.
878 #[serde(default, skip_serializing_if = "Option::is_none")]
879 pub latest_image: Option<ImageRef>,
880 /// The manifest, when the print has one.
881 #[serde(default, skip_serializing_if = "Option::is_none")]
882 pub manifest: Option<JobManifest>,
883 /// The print itself.
884 pub print: PrintRecord,
885 /// The printer, when a snapshot could be taken.
886 #[serde(default, skip_serializing_if = "Option::is_none")]
887 pub printer: Option<PrinterSnapshot>,
888 /// A bounded list of this print's events, newest first.
889 pub recent_events: Vec<EventRecord>,
890}
891
892/// A lowercase hyphenated version 7 UUID identifying one print.
893pub type PrintId = String;
894
895/// One print, and the record supervision keys from.
896///
897/// The provider's own print id is carried beside this record's identifier
898/// rather than as it, because a print may be observed before the provider
899/// that reports it has one.
900#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
901pub struct PrintRecord {
902 /// Why it ended, if it has.
903 #[serde(default, skip_serializing_if = "Option::is_none")]
904 pub end_reason: Option<String>,
905 /// When it ended, if it has.
906 #[serde(default, skip_serializing_if = "Option::is_none")]
907 pub ended_at: Option<Timestamp>,
908 /// The file being printed, as the source reported it.
909 #[serde(default, skip_serializing_if = "Option::is_none")]
910 pub file_name: Option<String>,
911 /// This print's identifier, minted by the store.
912 pub id: PrintId,
913 /// Every manifest range this print narrowed to the envelope's.
914 pub narrowings: Vec<ManifestNarrowing>,
915 /// When the print was opened.
916 pub opened_at: Timestamp,
917 /// The provider's own identifier for the print, whichever provider
918 /// reported it, when one has.
919 #[serde(default, skip_serializing_if = "Option::is_none")]
920 pub provider_print_id: Option<i64>,
921 /// The state the print is in.
922 pub state: PrinterState,
923}
924
925/// A printer, as a source reported it at one instant.
926#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
927pub struct PrinterSnapshot {
928 /// The bed heater, when the printer reports one.
929 #[serde(default, skip_serializing_if = "Option::is_none")]
930 pub bed: Option<HeaterSnapshot>,
931 /// The chamber heater, when the printer reports one.
932 #[serde(default, skip_serializing_if = "Option::is_none")]
933 pub chamber: Option<HeaterSnapshot>,
934 /// The state the printer is in.
935 pub connection: PrinterState,
936 /// The part-cooling fan, in percent.
937 #[serde(default, skip_serializing_if = "Option::is_none")]
938 pub fan_percent: Option<Reported>,
939 /// The feedrate multiplier, where one means one hundred percent.
940 #[serde(default, skip_serializing_if = "Option::is_none")]
941 pub feedrate_factor: Option<Reported>,
942 /// The flowrate multiplier, where one means one hundred percent.
943 #[serde(default, skip_serializing_if = "Option::is_none")]
944 pub flowrate_factor: Option<Reported>,
945 /// The instant this observation was taken.
946 pub observed_at: Timestamp,
947 /// The tool heaters, indexed by tool number.
948 pub tools: Vec<HeaterSnapshot>,
949}
950
951/// The state a source reports a printer or a print to be in.
952///
953/// The `unknown` arm exists so that a state nobody anticipated is recorded
954/// carrying the source's own word for it rather than lost.
955#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
956pub enum PrinterState {
957 /// Connected and idle.
958 #[serde(rename = "operational")]
959 Operational,
960 /// Printing, but paused.
961 #[serde(rename = "paused")]
962 Paused,
963 /// Printing.
964 #[serde(rename = "printing")]
965 Printing,
966 /// Cancelling a print.
967 #[serde(rename = "cancelling")]
968 Cancelling,
969 /// In an error state.
970 #[serde(rename = "error")]
971 Error,
972 /// Not reachable.
973 #[serde(rename = "offline")]
974 Offline,
975 /// A state this vocabulary does not name, in the source's own word for
976 /// it.
977 #[serde(rename = "unknown")]
978 Unknown(String),
979}
980
981/// What the prints read answers: every print, and the one the printer is
982/// running.
983///
984/// An open print's recorded `state` is the state it was opened in, which is
985/// `printing` whether or not the machine is paused now; what the machine is
986/// doing is the status read's answer.
987#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
988pub struct PrintsAnswer {
989 /// The print the printer's current job belongs to, present exactly when
990 /// the
991 /// printer reports a job it is printing or has paused. Absent when the
992 /// printer could not be read.
993 #[serde(default, skip_serializing_if = "Option::is_none")]
994 pub active: Option<PrintId>,
995 /// Every print this server holds, ended or not, most recently opened
996 /// first.
997 pub prints: Vec<PrintRecord>,
998}
999
1000/// An inclusive pair of 64-bit floats.
1001#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
1002pub struct Range {
1003 /// The highest value the range admits, inclusive.
1004 pub max: f64,
1005 /// The lowest value the range admits, inclusive.
1006 pub min: f64,
1007}
1008
1009/// Bytes exactly as received, base64-encoded.
1010pub type RawBytes = String;
1011
1012/// Why a request was refused.
1013///
1014/// Each rejection is a distinct variant, so a consumer distinguishes them by
1015/// matching rather than by reading a message.
1016#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
1017pub enum RejectionReason {
1018 /// The value asked for is outside the range allowed for that adjustable.
1019 #[serde(rename = "out_of_bounds")]
1020 OutOfBounds {
1021 /// The adjustable that was asked for.
1022 adjustable: Adjustable,
1023 /// The range that was allowed.
1024 allowed: Range,
1025 /// The value that was asked for.
1026 requested: f64,
1027 },
1028 /// This actor class may not request this action at all.
1029 #[serde(rename = "actor_may_not_request")]
1030 ActorMayNotRequest {
1031 /// The action they asked for.
1032 action: ActionKind,
1033 /// The class of the actor that asked.
1034 actor_class: ActorClass,
1035 },
1036 /// There is no active print to act on.
1037 #[serde(rename = "no_active_print")]
1038 NoActivePrint,
1039 /// The printer is not in a state this action is valid from.
1040 #[serde(rename = "invalid_from_state")]
1041 InvalidFromState {
1042 /// The state the printer is in.
1043 state: PrinterState,
1044 },
1045 /// The agent's minimum interval has not elapsed.
1046 #[serde(rename = "min_interval_not_elapsed")]
1047 MinIntervalNotElapsed {
1048 /// The minimum interval, in whole seconds.
1049 interval_s: i64,
1050 /// How long it has been since the last agent action, in whole
1051 /// seconds.
1052 since_last_s: i64,
1053 },
1054 /// The adjustable is not one this printer has.
1055 #[serde(rename = "unsupported_adjustable")]
1056 UnsupportedAdjustable {
1057 /// The adjustable this printer cannot express.
1058 adjustable: Adjustable,
1059 },
1060}
1061
1062/// A value as a source reported it, flagged when it is outside the
1063/// plausibility range this crate declares for its field.
1064#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
1065pub struct Reported {
1066 /// One shape of the contracts, which say nothing more about it.
1067 pub out_of_range: bool,
1068 /// One shape of the contracts, which say nothing more about it.
1069 pub value: f64,
1070}
1071
1072/// What one restart put back the way it found it.
1073///
1074/// A supervisor that has been restarted adopts whatever the store holds
1075/// rather
1076/// than starting empty, and each of these is one of those adoptions. They are
1077/// recorded rather than merely done, because a print that carried on across a
1078/// restart and one that was started again look identical afterwards unless
1079/// the
1080/// history says which happened.
1081#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
1082pub enum StartupOutcome {
1083 /// A print left open was adopted as the print this supervisor is
1084 /// watching.
1085 #[serde(rename = "print_adopted")]
1086 PrintAdopted,
1087 /// A session left open was resumed rather than replaced.
1088 #[serde(rename = "session_resumed")]
1089 SessionResumed {
1090 /// The session's own name in the harness.
1091 session_name: String,
1092 },
1093 /// An intervention already past its expiry was expired on start.
1094 #[serde(rename = "intervention_expired")]
1095 InterventionExpired {
1096 /// What it had changed.
1097 adjustable: Adjustable,
1098 /// The intervention that had outlived its bound.
1099 intervention_id: InterventionId,
1100 /// What became of putting the prior value back.
1101 outcome: InterventionOutcome,
1102 },
1103}
1104
1105/// A supervisor reconciled one thing the store held when it started.
1106#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
1107pub struct StartupReconciliationPayload {
1108 /// What was reconciled.
1109 pub outcome: StartupOutcome,
1110 /// The print it is about.
1111 pub print_id: PrintId,
1112}
1113
1114/// What a status read answers.
1115#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
1116pub struct StatusAnswer {
1117 /// The bounded interventions still in force.
1118 pub interventions: Vec<Intervention>,
1119 /// The job, when a snapshot could be taken.
1120 #[serde(default, skip_serializing_if = "Option::is_none")]
1121 pub job: Option<JobSnapshot>,
1122 /// The print.
1123 pub print: PrintRecord,
1124 /// The printer, when a snapshot could be taken.
1125 #[serde(default, skip_serializing_if = "Option::is_none")]
1126 pub printer: Option<PrinterSnapshot>,
1127 /// The supervision session watching it, when one is.
1128 #[serde(default, skip_serializing_if = "Option::is_none")]
1129 pub session: Option<SupervisionSession>,
1130}
1131
1132/// The supervision session keyed to one print.
1133#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
1134pub struct SupervisionSession {
1135 /// Why it was closed, if it was.
1136 #[serde(default, skip_serializing_if = "Option::is_none")]
1137 pub close_reason: Option<String>,
1138 /// When the session was closed, if it was.
1139 #[serde(default, skip_serializing_if = "Option::is_none")]
1140 pub closed_at: Option<Timestamp>,
1141 /// When the session was opened.
1142 pub created_at: Timestamp,
1143 /// The identity the harness ran the session under.
1144 pub harness_identity: String,
1145 /// When the last turn ran.
1146 pub last_turn_at: Timestamp,
1147 /// The print this session watches.
1148 pub print_id: PrintId,
1149 /// The session's own name in the harness.
1150 pub session_name: String,
1151}
1152
1153/// A supervision session was closed.
1154#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
1155pub struct SupervisionSessionClosedPayload {
1156 /// Why it was closed.
1157 pub close_reason: String,
1158 /// The session's own name in the harness.
1159 pub session_name: String,
1160}
1161
1162/// A supervision session was opened.
1163#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
1164pub struct SupervisionSessionOpenedPayload {
1165 /// The identity the harness ran it under.
1166 pub harness_identity: String,
1167 /// The session's own name in the harness.
1168 pub session_name: String,
1169}
1170
1171/// An instant in UTC, as an RFC 3339 string with a zero offset.
1172pub type Timestamp = String;
1173
1174/// One payload type declared under a kind name, by the domain that owns it.
1175///
1176/// The table from kind name to payload type, as the server declares it: every
1177/// kind below has exactly one implementation here, and a kind this client
1178/// does not know flows through `EventRecord` untouched.
1179pub trait EventPayloadKind: serde::de::DeserializeOwned {
1180 /// The name this payload's events are written down under.
1181 const KIND: &'static str;
1182}
1183
1184impl EventPayloadKind for ActionExecutedPayload {
1185 const KIND: &'static str = "action_executed";
1186}
1187
1188impl EventPayloadKind for ActionRejectedPayload {
1189 const KIND: &'static str = "action_rejected";
1190}
1191
1192impl EventPayloadKind for ActionRequestedPayload {
1193 const KIND: &'static str = "action_requested";
1194}
1195
1196impl EventPayloadKind for AgentAssessmentPayload {
1197 const KIND: &'static str = "agent_assessment";
1198}
1199
1200impl EventPayloadKind for InterventionExpiredPayload {
1201 const KIND: &'static str = "intervention_expired";
1202}
1203
1204impl EventPayloadKind for MalformedExternalEventPayload {
1205 const KIND: &'static str = "malformed_external_event";
1206}
1207
1208impl EventPayloadKind for ObicoFailureAlertPayload {
1209 const KIND: &'static str = "obico_failure_alert";
1210}
1211
1212impl EventPayloadKind for ObicoPrinterNotificationPayload {
1213 const KIND: &'static str = "obico_printer_notification";
1214}
1215
1216impl EventPayloadKind for OperatorAcknowledgementPayload {
1217 const KIND: &'static str = "operator_acknowledgement";
1218}
1219
1220impl EventPayloadKind for PortFailurePayload {
1221 const KIND: &'static str = "port_failure";
1222}
1223
1224impl EventPayloadKind for StartupReconciliationPayload {
1225 const KIND: &'static str = "startup_reconciliation";
1226}
1227
1228impl EventPayloadKind for SupervisionSessionClosedPayload {
1229 const KIND: &'static str = "supervision_session_closed";
1230}
1231
1232impl EventPayloadKind for SupervisionSessionOpenedPayload {
1233 const KIND: &'static str = "supervision_session_opened";
1234}
1235
1236/// Every kind the server declares a payload type for, in name order.
1237pub const EVENT_KINDS: [&str; 13] = [
1238 "action_executed",
1239 "action_rejected",
1240 "action_requested",
1241 "agent_assessment",
1242 "intervention_expired",
1243 "malformed_external_event",
1244 "obico_failure_alert",
1245 "obico_printer_notification",
1246 "operator_acknowledgement",
1247 "port_failure",
1248 "startup_reconciliation",
1249 "supervision_session_closed",
1250 "supervision_session_opened",
1251];
1252
1253impl EventRecord {
1254 /// The payload as `P`, when this event is under the kind `P` declares.
1255 ///
1256 /// Answers `None` for an event of any other kind — one this client knows
1257 /// or one it does not — and the parse failure for an event under the
1258 /// right kind whose payload is not of the type.
1259 #[must_use]
1260 pub fn payload_as<P: EventPayloadKind>(&self) -> Option<Result<P, serde_json::Error>> {
1261 (self.kind == P::KIND).then(|| serde_json::from_value(self.payload.clone()))
1262 }
1263}
1264
1265impl Client {
1266 /// Call `prints` on the configured supervisor.
1267 ///
1268 /// # Errors
1269 ///
1270 /// Returns `ClientError` when the supervisor could not be reached, when
1271 /// it answered something this client cannot read.
1272 // llmlint: ignore[names_match_behavior] See suppressions.toml.
1273 pub fn prints(&self) -> Result<PrintsAnswer, ClientError> {
1274 let target = String::from("/v1/prints");
1275 let asked: Vec<(String, String)> = Vec::new();
1276 let sending: Option<serde_json::Value> = None;
1277 self.call("GET", &target, &asked, sending.as_ref())
1278 }
1279
1280 /// Call `status` on the configured supervisor.
1281 ///
1282 /// # Errors
1283 ///
1284 /// Returns `ClientError` when the supervisor could not be reached, when
1285 /// it answered something this client cannot read.
1286 pub fn status(&self, print_id: &str) -> Result<StatusAnswer, ClientError> {
1287 let target = format!("/v1/prints/{print_id}/status");
1288 let asked: Vec<(String, String)> = Vec::new();
1289 let sending: Option<serde_json::Value> = None;
1290 self.call("GET", &target, &asked, sending.as_ref())
1291 }
1292
1293 /// Call `context` on the configured supervisor.
1294 ///
1295 /// # Errors
1296 ///
1297 /// Returns `ClientError` when the supervisor could not be reached, when
1298 /// it answered something this client cannot read.
1299 pub fn context(&self, print_id: &str) -> Result<ContextAnswer, ClientError> {
1300 let target = format!("/v1/prints/{print_id}/context");
1301 let asked: Vec<(String, String)> = Vec::new();
1302 let sending: Option<serde_json::Value> = None;
1303 self.call("GET", &target, &asked, sending.as_ref())
1304 }
1305
1306 /// Call `image` on the configured supervisor.
1307 ///
1308 /// # Errors
1309 ///
1310 /// Returns `ClientError` when the supervisor could not be reached, when
1311 /// it answered something this client cannot read.
1312 pub fn image(&self, image_id: &str) -> Result<ImageAnswer, ClientError> {
1313 let target = format!("/v1/images/{image_id}");
1314 let asked: Vec<(String, String)> = Vec::new();
1315 let sending: Option<serde_json::Value> = None;
1316 self.call("GET", &target, &asked, sending.as_ref())
1317 }
1318
1319 /// Call `history` on the configured supervisor.
1320 ///
1321 /// # Errors
1322 ///
1323 /// Returns `ClientError` when the supervisor could not be reached, when
1324 /// it answered something this client cannot read.
1325 pub fn history(
1326 &self,
1327 print_id: &str,
1328 limit: Option<i64>,
1329 ) -> Result<HistoryAnswer, ClientError> {
1330 let target = format!("/v1/prints/{print_id}/history");
1331 let mut asked: Vec<(String, String)> = Vec::new();
1332 if let Some(value) = limit {
1333 asked.push(("limit".to_owned(), value.to_string()));
1334 }
1335 let sending: Option<serde_json::Value> = None;
1336 self.call("GET", &target, &asked, sending.as_ref())
1337 }
1338
1339 /// Call `manifest_get` on the configured supervisor.
1340 ///
1341 /// # Errors
1342 ///
1343 /// Returns `ClientError` when the supervisor could not be reached, when
1344 /// it answered something this client cannot read.
1345 pub fn manifest_get(&self, print_id: &str) -> Result<ManifestAnswer, ClientError> {
1346 let target = format!("/v1/prints/{print_id}/manifest");
1347 let asked: Vec<(String, String)> = Vec::new();
1348 let sending: Option<serde_json::Value> = None;
1349 self.call("GET", &target, &asked, sending.as_ref())
1350 }
1351
1352 /// Call `manifest_set` on the configured supervisor.
1353 ///
1354 /// # Errors
1355 ///
1356 /// Returns `ClientError` when the supervisor could not be reached, when
1357 /// it answered something this client cannot read, when this client
1358 /// refuses the call before making it because the reason is empty, and
1359 /// when the policy refused the action — which arrives as
1360 /// `ClientError::Rejected`, carrying the reason, the value asked for and
1361 /// the range allowed.
1362 pub fn manifest_set(
1363 &self,
1364 print_id: &str,
1365 reason: &str,
1366 manifest: &JobManifest,
1367 ) -> Result<ManifestAnswer, ClientError> {
1368 crate::reason_given(reason)?;
1369 let target = format!("/v1/prints/{print_id}/manifest");
1370 let asked: Vec<(String, String)> = Vec::new();
1371 let mut sending = serde_json::Map::new();
1372 sending.insert("reason".to_owned(), crate::as_value(&reason)?);
1373 sending.insert("manifest".to_owned(), crate::as_value(&manifest)?);
1374 let sending = Some(serde_json::Value::Object(sending));
1375 self.call("PUT", &target, &asked, sending.as_ref())
1376 }
1377
1378 /// Call `pause` on the configured supervisor.
1379 ///
1380 /// # Errors
1381 ///
1382 /// Returns `ClientError` when the supervisor could not be reached, when
1383 /// it answered something this client cannot read, when this client
1384 /// refuses the call before making it because the reason is empty, and
1385 /// when the policy refused the action — which arrives as
1386 /// `ClientError::Rejected`, carrying the reason, the value asked for and
1387 /// the range allowed.
1388 pub fn pause(&self, print_id: &str, reason: &str) -> Result<ActionAnswer, ClientError> {
1389 crate::reason_given(reason)?;
1390 let target = format!("/v1/prints/{print_id}/actions/pause");
1391 let asked: Vec<(String, String)> = Vec::new();
1392 let mut sending = serde_json::Map::new();
1393 sending.insert("actor".to_owned(), crate::as_value(&self.actor())?);
1394 sending.insert("reason".to_owned(), crate::as_value(&reason)?);
1395 let sending = Some(serde_json::Value::Object(sending));
1396 self.call("POST", &target, &asked, sending.as_ref())
1397 }
1398
1399 /// Call `resume` on the configured supervisor.
1400 ///
1401 /// # Errors
1402 ///
1403 /// Returns `ClientError` when the supervisor could not be reached, when
1404 /// it answered something this client cannot read, when this client
1405 /// refuses the call before making it because the reason is empty, and
1406 /// when the policy refused the action — which arrives as
1407 /// `ClientError::Rejected`, carrying the reason, the value asked for and
1408 /// the range allowed.
1409 pub fn resume(&self, print_id: &str, reason: &str) -> Result<ActionAnswer, ClientError> {
1410 crate::reason_given(reason)?;
1411 let target = format!("/v1/prints/{print_id}/actions/resume");
1412 let asked: Vec<(String, String)> = Vec::new();
1413 let mut sending = serde_json::Map::new();
1414 sending.insert("actor".to_owned(), crate::as_value(&self.actor())?);
1415 sending.insert("reason".to_owned(), crate::as_value(&reason)?);
1416 let sending = Some(serde_json::Value::Object(sending));
1417 self.call("POST", &target, &asked, sending.as_ref())
1418 }
1419
1420 /// Call `cancel` on the configured supervisor.
1421 ///
1422 /// # Errors
1423 ///
1424 /// Returns `ClientError` when the supervisor could not be reached, when
1425 /// it answered something this client cannot read, when this client
1426 /// refuses the call before making it because the reason is empty, and
1427 /// when the policy refused the action — which arrives as
1428 /// `ClientError::Rejected`, carrying the reason, the value asked for and
1429 /// the range allowed.
1430 pub fn cancel(&self, print_id: &str, reason: &str) -> Result<ActionAnswer, ClientError> {
1431 crate::reason_given(reason)?;
1432 let target = format!("/v1/prints/{print_id}/actions/cancel");
1433 let asked: Vec<(String, String)> = Vec::new();
1434 let mut sending = serde_json::Map::new();
1435 sending.insert("actor".to_owned(), crate::as_value(&self.actor())?);
1436 sending.insert("reason".to_owned(), crate::as_value(&reason)?);
1437 let sending = Some(serde_json::Value::Object(sending));
1438 self.call("POST", &target, &asked, sending.as_ref())
1439 }
1440
1441 /// Call `start_print` on the configured supervisor.
1442 ///
1443 /// # Errors
1444 ///
1445 /// Returns `ClientError` when the supervisor could not be reached, when
1446 /// it answered something this client cannot read, when this client
1447 /// refuses the call before making it because the reason is empty, and
1448 /// when the policy refused the action — which arrives as
1449 /// `ClientError::Rejected`, carrying the reason, the value asked for and
1450 /// the range allowed.
1451 pub fn start_print(
1452 &self,
1453 print_id: &str,
1454 file_name: &FileName,
1455 manifest: &JobManifest,
1456 reason: &str,
1457 ) -> Result<ActionAnswer, ClientError> {
1458 crate::reason_given(reason)?;
1459 let target = format!("/v1/prints/{print_id}/actions/start_print");
1460 let asked: Vec<(String, String)> = Vec::new();
1461 let mut sending = serde_json::Map::new();
1462 sending.insert("actor".to_owned(), crate::as_value(&self.actor())?);
1463 sending.insert("file_name".to_owned(), crate::as_value(&file_name)?);
1464 sending.insert("manifest".to_owned(), crate::as_value(&manifest)?);
1465 sending.insert("reason".to_owned(), crate::as_value(&reason)?);
1466 let sending = Some(serde_json::Value::Object(sending));
1467 self.call("POST", &target, &asked, sending.as_ref())
1468 }
1469
1470 /// Call `set_feedrate_factor` on the configured supervisor.
1471 ///
1472 /// # Errors
1473 ///
1474 /// Returns `ClientError` when the supervisor could not be reached, when
1475 /// it answered something this client cannot read, when this client
1476 /// refuses the call before making it because the reason is empty, and
1477 /// when the policy refused the action — which arrives as
1478 /// `ClientError::Rejected`, carrying the reason, the value asked for and
1479 /// the range allowed.
1480 pub fn set_feedrate_factor(
1481 &self,
1482 print_id: &str,
1483 factor: f64,
1484 reason: &str,
1485 duration_s: Option<i64>,
1486 ) -> Result<ActionAnswer, ClientError> {
1487 crate::reason_given(reason)?;
1488 let target = format!("/v1/prints/{print_id}/actions/set_feedrate_factor");
1489 let asked: Vec<(String, String)> = Vec::new();
1490 let mut sending = serde_json::Map::new();
1491 sending.insert("actor".to_owned(), crate::as_value(&self.actor())?);
1492 if let Some(value) = duration_s {
1493 sending.insert("duration_s".to_owned(), crate::as_value(&value)?);
1494 }
1495 sending.insert("factor".to_owned(), crate::as_value(&factor)?);
1496 sending.insert("reason".to_owned(), crate::as_value(&reason)?);
1497 let sending = Some(serde_json::Value::Object(sending));
1498 self.call("POST", &target, &asked, sending.as_ref())
1499 }
1500
1501 /// Call `set_flowrate_factor` on the configured supervisor.
1502 ///
1503 /// # Errors
1504 ///
1505 /// Returns `ClientError` when the supervisor could not be reached, when
1506 /// it answered something this client cannot read, when this client
1507 /// refuses the call before making it because the reason is empty, and
1508 /// when the policy refused the action — which arrives as
1509 /// `ClientError::Rejected`, carrying the reason, the value asked for and
1510 /// the range allowed.
1511 pub fn set_flowrate_factor(
1512 &self,
1513 print_id: &str,
1514 factor: f64,
1515 reason: &str,
1516 duration_s: Option<i64>,
1517 ) -> Result<ActionAnswer, ClientError> {
1518 crate::reason_given(reason)?;
1519 let target = format!("/v1/prints/{print_id}/actions/set_flowrate_factor");
1520 let asked: Vec<(String, String)> = Vec::new();
1521 let mut sending = serde_json::Map::new();
1522 sending.insert("actor".to_owned(), crate::as_value(&self.actor())?);
1523 if let Some(value) = duration_s {
1524 sending.insert("duration_s".to_owned(), crate::as_value(&value)?);
1525 }
1526 sending.insert("factor".to_owned(), crate::as_value(&factor)?);
1527 sending.insert("reason".to_owned(), crate::as_value(&reason)?);
1528 let sending = Some(serde_json::Value::Object(sending));
1529 self.call("POST", &target, &asked, sending.as_ref())
1530 }
1531
1532 /// Call `set_tool_target_c` on the configured supervisor.
1533 ///
1534 /// # Errors
1535 ///
1536 /// Returns `ClientError` when the supervisor could not be reached, when
1537 /// it answered something this client cannot read, when this client
1538 /// refuses the call before making it because the reason is empty, and
1539 /// when the policy refused the action — which arrives as
1540 /// `ClientError::Rejected`, carrying the reason, the value asked for and
1541 /// the range allowed.
1542 pub fn set_tool_target_c(
1543 &self,
1544 print_id: &str,
1545 reason: &str,
1546 target_c: f64,
1547 tool: i64,
1548 duration_s: Option<i64>,
1549 ) -> Result<ActionAnswer, ClientError> {
1550 crate::reason_given(reason)?;
1551 let target = format!("/v1/prints/{print_id}/actions/set_tool_target_c");
1552 let asked: Vec<(String, String)> = Vec::new();
1553 let mut sending = serde_json::Map::new();
1554 sending.insert("actor".to_owned(), crate::as_value(&self.actor())?);
1555 if let Some(value) = duration_s {
1556 sending.insert("duration_s".to_owned(), crate::as_value(&value)?);
1557 }
1558 sending.insert("reason".to_owned(), crate::as_value(&reason)?);
1559 sending.insert("target_c".to_owned(), crate::as_value(&target_c)?);
1560 sending.insert("tool".to_owned(), crate::as_value(&tool)?);
1561 let sending = Some(serde_json::Value::Object(sending));
1562 self.call("POST", &target, &asked, sending.as_ref())
1563 }
1564
1565 /// Call `set_bed_target_c` on the configured supervisor.
1566 ///
1567 /// # Errors
1568 ///
1569 /// Returns `ClientError` when the supervisor could not be reached, when
1570 /// it answered something this client cannot read, when this client
1571 /// refuses the call before making it because the reason is empty, and
1572 /// when the policy refused the action — which arrives as
1573 /// `ClientError::Rejected`, carrying the reason, the value asked for and
1574 /// the range allowed.
1575 pub fn set_bed_target_c(
1576 &self,
1577 print_id: &str,
1578 reason: &str,
1579 target_c: f64,
1580 duration_s: Option<i64>,
1581 ) -> Result<ActionAnswer, ClientError> {
1582 crate::reason_given(reason)?;
1583 let target = format!("/v1/prints/{print_id}/actions/set_bed_target_c");
1584 let asked: Vec<(String, String)> = Vec::new();
1585 let mut sending = serde_json::Map::new();
1586 sending.insert("actor".to_owned(), crate::as_value(&self.actor())?);
1587 if let Some(value) = duration_s {
1588 sending.insert("duration_s".to_owned(), crate::as_value(&value)?);
1589 }
1590 sending.insert("reason".to_owned(), crate::as_value(&reason)?);
1591 sending.insert("target_c".to_owned(), crate::as_value(&target_c)?);
1592 let sending = Some(serde_json::Value::Object(sending));
1593 self.call("POST", &target, &asked, sending.as_ref())
1594 }
1595
1596 /// Call `set_fan_percent` on the configured supervisor.
1597 ///
1598 /// # Errors
1599 ///
1600 /// Returns `ClientError` when the supervisor could not be reached, when
1601 /// it answered something this client cannot read, when this client
1602 /// refuses the call before making it because the reason is empty, and
1603 /// when the policy refused the action — which arrives as
1604 /// `ClientError::Rejected`, carrying the reason, the value asked for and
1605 /// the range allowed.
1606 pub fn set_fan_percent(
1607 &self,
1608 print_id: &str,
1609 percent: f64,
1610 reason: &str,
1611 duration_s: Option<i64>,
1612 ) -> Result<ActionAnswer, ClientError> {
1613 crate::reason_given(reason)?;
1614 let target = format!("/v1/prints/{print_id}/actions/set_fan_percent");
1615 let asked: Vec<(String, String)> = Vec::new();
1616 let mut sending = serde_json::Map::new();
1617 sending.insert("actor".to_owned(), crate::as_value(&self.actor())?);
1618 if let Some(value) = duration_s {
1619 sending.insert("duration_s".to_owned(), crate::as_value(&value)?);
1620 }
1621 sending.insert("percent".to_owned(), crate::as_value(&percent)?);
1622 sending.insert("reason".to_owned(), crate::as_value(&reason)?);
1623 let sending = Some(serde_json::Value::Object(sending));
1624 self.call("POST", &target, &asked, sending.as_ref())
1625 }
1626
1627 /// Call `acknowledge_failure` on the configured supervisor.
1628 ///
1629 /// # Errors
1630 ///
1631 /// Returns `ClientError` when the supervisor could not be reached, when
1632 /// it answered something this client cannot read, when this client
1633 /// refuses the call before making it because the reason is empty, and
1634 /// when the policy refused the action — which arrives as
1635 /// `ClientError::Rejected`, carrying the reason, the value asked for and
1636 /// the range allowed.
1637 pub fn acknowledge_failure(
1638 &self,
1639 print_id: &str,
1640 disposition: &AcknowledgementDisposition,
1641 event_id: &EventId,
1642 reason: &str,
1643 ) -> Result<ActionAnswer, ClientError> {
1644 crate::reason_given(reason)?;
1645 let target = format!("/v1/prints/{print_id}/actions/acknowledge_failure");
1646 let asked: Vec<(String, String)> = Vec::new();
1647 let mut sending = serde_json::Map::new();
1648 sending.insert("actor".to_owned(), crate::as_value(&self.actor())?);
1649 sending.insert("disposition".to_owned(), crate::as_value(&disposition)?);
1650 sending.insert("event_id".to_owned(), crate::as_value(&event_id)?);
1651 sending.insert("reason".to_owned(), crate::as_value(&reason)?);
1652 let sending = Some(serde_json::Value::Object(sending));
1653 self.call("POST", &target, &asked, sending.as_ref())
1654 }
1655}