Skip to main content

printobserver_types/
printer.rs

1//! Normalized observations of a printer and of the job it is running.
2
3use serde::{Deserialize, Serialize};
4
5use schemars::JsonSchema;
6
7use crate::reported::Reported;
8use crate::timestamp::Timestamp;
9
10/// The state a source reports a printer or a print to be in.
11///
12/// The `unknown` arm exists so that a state nobody anticipated is recorded
13/// carrying the source's own word for it rather than lost.
14#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize, JsonSchema)]
15#[serde(rename_all = "snake_case", deny_unknown_fields)]
16pub enum PrinterState {
17    /// Connected and idle.
18    Operational,
19    /// Printing, but paused.
20    Paused,
21    /// Printing.
22    Printing,
23    /// Cancelling a print.
24    Cancelling,
25    /// In an error state.
26    Error,
27    /// Not reachable.
28    Offline,
29    /// A state this vocabulary does not name, in the source's own word for it.
30    Unknown(String),
31}
32
33/// One heater, as a source reported it.
34///
35/// Every field is optional, because a source that reports no heater at all
36/// reports none of these; each is a plausibility-ranged reported value in
37/// degrees Celsius.
38#[derive(Debug, Clone, PartialEq, Serialize, Deserialize, JsonSchema, Default)]
39#[serde(deny_unknown_fields)]
40pub struct HeaterSnapshot {
41    /// The temperature the heater is at.
42    #[serde(
43        default,
44        skip_serializing_if = "Option::is_none",
45        deserialize_with = "crate::reported::de_heater_actual_c"
46    )]
47    pub actual_c: Option<Reported<f64>>,
48    /// The temperature the heater is driving towards.
49    #[serde(
50        default,
51        skip_serializing_if = "Option::is_none",
52        deserialize_with = "crate::reported::de_heater_target_c"
53    )]
54    pub target_c: Option<Reported<f64>>,
55    /// The offset applied to this heater's target.
56    #[serde(
57        default,
58        skip_serializing_if = "Option::is_none",
59        deserialize_with = "crate::reported::de_heater_offset_c"
60    )]
61    pub offset_c: Option<Reported<f64>>,
62}
63
64/// A printer, as a source reported it at one instant.
65#[derive(Debug, Clone, PartialEq, Serialize, Deserialize, JsonSchema)]
66#[serde(deny_unknown_fields)]
67pub struct PrinterSnapshot {
68    /// The state the printer is in.
69    pub connection: PrinterState,
70    /// The tool heaters, indexed by tool number.
71    pub tools: Vec<HeaterSnapshot>,
72    /// The bed heater, when the printer reports one.
73    #[serde(default, skip_serializing_if = "Option::is_none")]
74    pub bed: Option<HeaterSnapshot>,
75    /// The chamber heater, when the printer reports one.
76    #[serde(default, skip_serializing_if = "Option::is_none")]
77    pub chamber: Option<HeaterSnapshot>,
78    /// The feedrate multiplier, where one means one hundred percent.
79    #[serde(
80        default,
81        skip_serializing_if = "Option::is_none",
82        deserialize_with = "crate::reported::de_feedrate_factor"
83    )]
84    pub feedrate_factor: Option<Reported<f64>>,
85    /// The flowrate multiplier, where one means one hundred percent.
86    #[serde(
87        default,
88        skip_serializing_if = "Option::is_none",
89        deserialize_with = "crate::reported::de_flowrate_factor"
90    )]
91    pub flowrate_factor: Option<Reported<f64>>,
92    /// The part-cooling fan, in percent.
93    #[serde(
94        default,
95        skip_serializing_if = "Option::is_none",
96        deserialize_with = "crate::reported::de_fan_percent"
97    )]
98    pub fan_percent: Option<Reported<f64>>,
99    /// The instant this observation was taken.
100    pub observed_at: Timestamp,
101}
102
103/// The job a printer reports it is running.
104///
105/// Every field but `state` is optional: an absent one means the source did not
106/// report it.
107#[derive(Debug, Clone, PartialEq, Serialize, Deserialize, JsonSchema)]
108#[serde(deny_unknown_fields)]
109pub struct JobSnapshot {
110    /// The name of the file being printed, as the source reported it.
111    #[serde(default, skip_serializing_if = "Option::is_none")]
112    pub file_name: Option<String>,
113    /// Where the file lives, in the source's own vocabulary.
114    #[serde(default, skip_serializing_if = "Option::is_none")]
115    pub file_origin: Option<String>,
116    /// The file's size in bytes.
117    #[serde(default, skip_serializing_if = "Option::is_none")]
118    pub size_bytes: Option<i64>,
119    /// The whole print's estimated duration, in whole seconds.
120    #[serde(default, skip_serializing_if = "Option::is_none")]
121    pub estimated_print_time_s: Option<i64>,
122    /// How far through the print is, as a fraction from zero to one.
123    ///
124    /// Normalized to a fraction here regardless of how the source expresses it.
125    #[serde(
126        default,
127        skip_serializing_if = "Option::is_none",
128        deserialize_with = "crate::reported::de_completion"
129    )]
130    pub completion: Option<Reported<f64>>,
131    /// How long the print has been running, in whole seconds.
132    #[serde(default, skip_serializing_if = "Option::is_none")]
133    pub print_time_s: Option<i64>,
134    /// How long the print has left, in whole seconds.
135    #[serde(default, skip_serializing_if = "Option::is_none")]
136    pub print_time_left_s: Option<i64>,
137    /// The state the source reports the job to be in.
138    pub state: PrinterState,
139    /// The error the source reports, when it reports one.
140    #[serde(default, skip_serializing_if = "Option::is_none")]
141    pub error: Option<String>,
142}