Skip to main content

bacnet_types/enums/
units.rs

1// ===========================================================================
2// EngineeringUnits (Clause 21) — large enum, grouped by category
3// ===========================================================================
4
5#[cfg(all(feature = "serde", not(feature = "std")))]
6use alloc::string::String;
7
8#[cfg(feature = "serde")]
9use serde::Deserialize;
10
11bacnet_enum! {
12    /// BACnet engineering units (Clause 21).
13    ///
14    /// ASHRAE owns 0-255 and 47808-49999. Vendor units go in 256-47807 or
15    /// 50000-65535, following the extension rules of Clause 23.
16    pub struct EngineeringUnits(u32);
17
18    // Acceleration
19    const METERS_PER_SECOND_PER_SECOND = 166;
20    // Area
21    const SQUARE_METERS = 0;
22    const SQUARE_CENTIMETERS = 116;
23    const SQUARE_FEET = 1;
24    const SQUARE_INCHES = 115;
25    // Currency
26    const CURRENCY1 = 105;
27    const CURRENCY2 = 106;
28    const CURRENCY3 = 107;
29    const CURRENCY4 = 108;
30    const CURRENCY5 = 109;
31    const CURRENCY6 = 110;
32    const CURRENCY7 = 111;
33    const CURRENCY8 = 112;
34    const CURRENCY9 = 113;
35    const CURRENCY10 = 114;
36    // Electrical
37    const MILLIAMPERES = 2;
38    const AMPERES = 3;
39    const AMPERES_PER_METER = 167;
40    const AMPERES_PER_SQUARE_METER = 168;
41    const AMPERE_SQUARE_METERS = 169;
42    const DECIBELS = 199;
43    const DECIBELS_MILLIVOLT = 200;
44    const DECIBELS_VOLT = 201;
45    const FARADS = 170;
46    const HENRYS = 171;
47    const OHMS = 4;
48    const OHM_METER_SQUARED_PER_METER = 237;
49    const OHM_METERS = 172;
50    const MILLIOHMS = 145;
51    const KILOHMS = 122;
52    const MEGOHMS = 123;
53    const MICROSIEMENS = 190;
54    const MILLISIEMENS = 202;
55    const SIEMENS = 173;
56    const SIEMENS_PER_METER = 174;
57    const TESLAS = 175;
58    const VOLTS = 5;
59    const MILLIVOLTS = 124;
60    const KILOVOLTS = 6;
61    const MEGAVOLTS = 7;
62    const VOLT_AMPERES = 8;
63    const KILOVOLT_AMPERES = 9;
64    const MEGAVOLT_AMPERES = 10;
65    const VOLT_AMPERES_REACTIVE = 11;
66    const KILOVOLT_AMPERES_REACTIVE = 12;
67    const MEGAVOLT_AMPERES_REACTIVE = 13;
68    const VOLTS_PER_DEGREE_KELVIN = 176;
69    const VOLTS_PER_METER = 177;
70    const DEGREES_PHASE = 14;
71    const POWER_FACTOR = 15;
72    const WEBERS = 178;
73    // Energy
74    const AMPERE_SECONDS = 238;
75    const VOLT_AMPERE_HOURS = 239;
76    const KILOVOLT_AMPERE_HOURS = 240;
77    const MEGAVOLT_AMPERE_HOURS = 241;
78    const VOLT_AMPERE_HOURS_REACTIVE = 242;
79    const KILOVOLT_AMPERE_HOURS_REACTIVE = 243;
80    const MEGAVOLT_AMPERE_HOURS_REACTIVE = 244;
81    const VOLT_SQUARE_HOURS = 245;
82    const AMPERE_SQUARE_HOURS = 246;
83    const JOULES = 16;
84    const KILOJOULES = 17;
85    const KILOJOULES_PER_KILOGRAM = 125;
86    const MEGAJOULES = 126;
87    const WATT_HOURS = 18;
88    const KILOWATT_HOURS = 19;
89    const MEGAWATT_HOURS = 146;
90    const WATT_HOURS_REACTIVE = 203;
91    const KILOWATT_HOURS_REACTIVE = 204;
92    const MEGAWATT_HOURS_REACTIVE = 205;
93    const BTUS = 20;
94    const KILO_BTUS = 147;
95    const MEGA_BTUS = 148;
96    const THERMS = 21;
97    const TON_HOURS = 22;
98    // Enthalpy
99    const JOULES_PER_KILOGRAM_DRY_AIR = 23;
100    const KILOJOULES_PER_KILOGRAM_DRY_AIR = 149;
101    const MEGAJOULES_PER_KILOGRAM_DRY_AIR = 150;
102    const BTUS_PER_POUND_DRY_AIR = 24;
103    const BTUS_PER_POUND = 117;
104    // Entropy
105    const JOULES_PER_DEGREE_KELVIN = 127;
106    const KILOJOULES_PER_DEGREE_KELVIN = 151;
107    const MEGAJOULES_PER_DEGREE_KELVIN = 152;
108    const JOULES_PER_KILOGRAM_DEGREE_KELVIN = 128;
109    // Force
110    const NEWTON = 153;
111    // Frequency
112    const CYCLES_PER_HOUR = 25;
113    const CYCLES_PER_MINUTE = 26;
114    const HERTZ = 27;
115    const KILOHERTZ = 129;
116    const MEGAHERTZ = 130;
117    const PER_HOUR = 131;
118    // Humidity
119    const GRAMS_OF_WATER_PER_KILOGRAM_DRY_AIR = 28;
120    const PERCENT_RELATIVE_HUMIDITY = 29;
121    // Length
122    const MICROMETERS = 194;
123    const MILLIMETERS = 30;
124    const CENTIMETERS = 118;
125    const KILOMETERS = 193;
126    const METERS = 31;
127    const INCHES = 32;
128    const FEET = 33;
129    // Light
130    const CANDELAS = 179;
131    const CANDELAS_PER_SQUARE_METER = 180;
132    const WATTS_PER_SQUARE_FOOT = 34;
133    const WATTS_PER_SQUARE_METER = 35;
134    const LUMENS = 36;
135    const LUXES = 37;
136    const FOOT_CANDLES = 38;
137    // Mass
138    const MILLIGRAMS = 196;
139    const GRAMS = 195;
140    const KILOGRAMS = 39;
141    const POUNDS_MASS = 40;
142    const TONS = 41;
143    // Mass flow
144    const GRAMS_PER_SECOND = 154;
145    const GRAMS_PER_MINUTE = 155;
146    const KILOGRAMS_PER_SECOND = 42;
147    const KILOGRAMS_PER_MINUTE = 43;
148    const KILOGRAMS_PER_HOUR = 44;
149    const POUNDS_MASS_PER_SECOND = 119;
150    const POUNDS_MASS_PER_MINUTE = 45;
151    const POUNDS_MASS_PER_HOUR = 46;
152    const TONS_PER_HOUR = 156;
153    // Power
154    const MILLIWATTS = 132;
155    const WATTS = 47;
156    const KILOWATTS = 48;
157    const MEGAWATTS = 49;
158    const BTUS_PER_HOUR = 50;
159    const KILO_BTUS_PER_HOUR = 157;
160    const JOULE_PER_HOURS = 247;
161    const HORSEPOWER = 51;
162    const TONS_REFRIGERATION = 52;
163    // Pressure
164    const PASCALS = 53;
165    const HECTOPASCALS = 133;
166    const KILOPASCALS = 54;
167    const MILLIBARS = 134;
168    const BARS = 55;
169    const POUNDS_FORCE_PER_SQUARE_INCH = 56;
170    const MILLIMETERS_OF_WATER = 206;
171    const CENTIMETERS_OF_WATER = 57;
172    const INCHES_OF_WATER = 58;
173    const MILLIMETERS_OF_MERCURY = 59;
174    const CENTIMETERS_OF_MERCURY = 60;
175    const INCHES_OF_MERCURY = 61;
176    // Temperature
177    const DEGREES_CELSIUS = 62;
178    const DEGREES_KELVIN = 63;
179    const DEGREES_KELVIN_PER_HOUR = 181;
180    const DEGREES_KELVIN_PER_MINUTE = 182;
181    const DEGREES_FAHRENHEIT = 64;
182    const DEGREE_DAYS_CELSIUS = 65;
183    const DEGREE_DAYS_FAHRENHEIT = 66;
184    const DELTA_DEGREES_FAHRENHEIT = 120;
185    const DELTA_DEGREES_KELVIN = 121;
186    // Time
187    const YEARS = 67;
188    const MONTHS = 68;
189    const WEEKS = 69;
190    const DAYS = 70;
191    const HOURS = 71;
192    const MINUTES = 72;
193    const SECONDS = 73;
194    const HUNDREDTHS_SECONDS = 158;
195    const MILLISECONDS = 159;
196    // Torque
197    const NEWTON_METERS = 160;
198    // Velocity
199    const MILLIMETERS_PER_SECOND = 161;
200    const MILLIMETERS_PER_MINUTE = 162;
201    const METERS_PER_SECOND = 74;
202    const METERS_PER_MINUTE = 163;
203    const METERS_PER_HOUR = 164;
204    const KILOMETERS_PER_HOUR = 75;
205    const FEET_PER_SECOND = 76;
206    const FEET_PER_MINUTE = 77;
207    const MILES_PER_HOUR = 78;
208    // Volume
209    const CUBIC_FEET = 79;
210    const CUBIC_METERS = 80;
211    const IMPERIAL_GALLONS = 81;
212    const MILLILITERS = 197;
213    const LITERS = 82;
214    const US_GALLONS = 83;
215    // Volumetric flow
216    const CUBIC_FEET_PER_SECOND = 142;
217    const CUBIC_FEET_PER_MINUTE = 84;
218    const MILLION_STANDARD_CUBIC_FEET_PER_MINUTE = 254;
219    const CUBIC_FEET_PER_HOUR = 191;
220    const CUBIC_FEET_PER_DAY = 248;
221    const STANDARD_CUBIC_FEET_PER_DAY = 47808;
222    const MILLION_STANDARD_CUBIC_FEET_PER_DAY = 47809;
223    const THOUSAND_CUBIC_FEET_PER_DAY = 47810;
224    const THOUSAND_STANDARD_CUBIC_FEET_PER_DAY = 47811;
225    const POUNDS_MASS_PER_DAY = 47812;
226    const CUBIC_METERS_PER_SECOND = 85;
227    const CUBIC_METERS_PER_MINUTE = 165;
228    const CUBIC_METERS_PER_HOUR = 135;
229    const CUBIC_METERS_PER_DAY = 249;
230    const IMPERIAL_GALLONS_PER_MINUTE = 86;
231    const MILLILITERS_PER_SECOND = 198;
232    const LITERS_PER_SECOND = 87;
233    const LITERS_PER_MINUTE = 88;
234    const LITERS_PER_HOUR = 136;
235    const US_GALLONS_PER_MINUTE = 89;
236    const US_GALLONS_PER_HOUR = 192;
237    // Other
238    const DEGREES_ANGULAR = 90;
239    const DEGREES_CELSIUS_PER_HOUR = 91;
240    const DEGREES_CELSIUS_PER_MINUTE = 92;
241    const DEGREES_FAHRENHEIT_PER_HOUR = 93;
242    const DEGREES_FAHRENHEIT_PER_MINUTE = 94;
243    const JOULE_SECONDS = 183;
244    const KILOGRAMS_PER_CUBIC_METER = 186;
245    const KILOWATT_HOURS_PER_SQUARE_METER = 137;
246    const KILOWATT_HOURS_PER_SQUARE_FOOT = 138;
247    const WATT_HOURS_PER_CUBIC_METER = 250;
248    const JOULES_PER_CUBIC_METER = 251;
249    const MEGAJOULES_PER_SQUARE_METER = 139;
250    const MEGAJOULES_PER_SQUARE_FOOT = 140;
251    const MOLE_PERCENT = 252;
252    const NO_UNITS = 95;
253    const NEWTON_SECONDS = 187;
254    const NEWTONS_PER_METER = 188;
255    const PARTS_PER_MILLION = 96;
256    const PARTS_PER_BILLION = 97;
257    const PASCAL_SECONDS = 253;
258    const PERCENT = 98;
259    const PERCENT_OBSCURATION_PER_FOOT = 143;
260    const PERCENT_OBSCURATION_PER_METER = 144;
261    const PERCENT_PER_SECOND = 99;
262    const PER_MINUTE = 100;
263    const PER_SECOND = 101;
264    const PSI_PER_DEGREE_FAHRENHEIT = 102;
265    const RADIANS = 103;
266    const RADIANS_PER_SECOND = 184;
267    const REVOLUTIONS_PER_MINUTE = 104;
268    const SQUARE_METERS_PER_NEWTON = 185;
269    const WATTS_PER_METER_PER_DEGREE_KELVIN = 189;
270    const WATTS_PER_SQUARE_METER_DEGREE_KELVIN = 141;
271    const PER_MILLE = 207;
272    const GRAMS_PER_GRAM = 208;
273    const KILOGRAMS_PER_KILOGRAM = 209;
274    const GRAMS_PER_KILOGRAM = 210;
275    const MILLIGRAMS_PER_GRAM = 211;
276    const MILLIGRAMS_PER_KILOGRAM = 212;
277    const GRAMS_PER_MILLILITER = 213;
278    const GRAMS_PER_LITER = 214;
279    const MILLIGRAMS_PER_LITER = 215;
280    const MICROGRAMS_PER_LITER = 216;
281    const GRAMS_PER_CUBIC_METER = 217;
282    const MILLIGRAMS_PER_CUBIC_METER = 218;
283    const MICROGRAMS_PER_CUBIC_METER = 219;
284    const NANOGRAMS_PER_CUBIC_METER = 220;
285    const GRAMS_PER_CUBIC_CENTIMETER = 221;
286    const BECQUERELS = 222;
287    const KILOBECQUERELS = 223;
288    const MEGABECQUERELS = 224;
289    const GRAY = 225;
290    const MILLIGRAY = 226;
291    const MICROGRAY = 227;
292    const SIEVERTS = 228;
293    const MILLISIEVERTS = 229;
294    const MICROSIEVERTS = 230;
295    const MICROSIEVERTS_PER_HOUR = 231;
296    const MILLIREMS = 47814;
297    const MILLIREMS_PER_HOUR = 47815;
298    const DECIBELS_A = 232;
299    const NEPHELOMETRIC_TURBIDITY_UNIT = 233;
300    const PH = 234;
301    const GRAMS_PER_SQUARE_METER = 235;
302    const MINUTES_PER_DEGREE_KELVIN = 236;
303    const DEGREES_LOVIBOND = 47816;
304    const ALCOHOL_BY_VOLUME = 47817;
305    const INTERNATIONAL_BITTERING_UNITS = 47818;
306    const EUROPEAN_BITTERNESS_UNITS = 47819;
307    const DEGREES_PLATO = 47820;
308    const SPECIFIC_GRAVITY = 47821;
309    const EUROPEAN_BREWING_CONVENTION = 47822;
310}
311
312#[cfg(feature = "serde")]
313impl<'de> Deserialize<'de> for EngineeringUnits {
314    fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
315    where
316        D: serde::Deserializer<'de>,
317    {
318        let string: String = Deserialize::deserialize(deserializer)?;
319        string.parse().map_err(serde::de::Error::custom)
320    }
321}
322
323#[cfg(all(test, feature = "serde"))]
324mod serde_tests {
325    use super::EngineeringUnits;
326
327    fn parse(input: &str) -> EngineeringUnits {
328        serde_json::from_str(&format!("\"{input}\"")).expect("deserializes")
329    }
330
331    #[test]
332    fn accepts_every_supported_case_style() {
333        for input in [
334            "degreescelsius",
335            "DEGREESCELSIUS",
336            "DegreesCelsius",
337            "degreesCelsius",
338            "degrees_celsius",
339            "DEGREES_CELSIUS",
340            "degrees-celsius",
341            "DEGREES-CELSIUS",
342        ] {
343            assert_eq!(
344                parse(input),
345                EngineeringUnits::DEGREES_CELSIUS,
346                "input: {input}"
347            );
348        }
349    }
350
351    #[test]
352    fn covers_the_full_standard_range() {
353        assert_eq!(parse("square_meters"), EngineeringUnits::SQUARE_METERS);
354        assert_eq!(
355            parse("european-brewing-convention"),
356            EngineeringUnits::EUROPEAN_BREWING_CONVENTION
357        );
358    }
359
360    #[test]
361    fn rejects_unknown_names() {
362        assert!(serde_json::from_str::<EngineeringUnits>("\"not-a-unit\"").is_err());
363    }
364
365    #[test]
366    fn rejects_non_string_input() {
367        assert!(serde_json::from_str::<EngineeringUnits>("126").is_err());
368    }
369}