#![allow(clippy::manual_range_patterns)]
use crate::profile::typedef::{self, FitBaseType};
use crate::proto::*;
use alloc::vec::Vec;
#[cfg(feature = "serde")]
use serde::{Deserialize, Serialize, Serializer, ser::SerializeStruct};
fn is_expanded(state: &[u8], num: u8) -> bool {
match num {
5 | 28 => (state[num as usize >> 3] >> (num & 7)) & 1 == 1,
_ => false,
}
}
#[cfg_attr(feature = "serde", derive(Deserialize), serde(from = "De"))]
#[derive(Debug, Clone)]
pub struct Monitoring {
pub timestamp: typedef::DateTime,
pub device_index: typedef::DeviceIndex,
pub calories: u16,
pub distance: u32,
pub cycles: u32,
pub active_time: u32,
pub activity_type: typedef::ActivityType,
pub activity_subtype: typedef::ActivitySubtype,
pub activity_level: typedef::ActivityLevel,
pub distance_16: u16,
pub cycles_16: u16,
pub active_time_16: u16,
pub local_timestamp: typedef::LocalDateTime,
pub temperature: i16,
pub temperature_min: i16,
pub temperature_max: i16,
pub activity_time: [u16; 8],
pub active_calories: u16,
pub current_activity_type_intensity: u8,
pub timestamp_min_8: u8,
pub timestamp_16: u16,
pub heart_rate: u8,
pub intensity: u8,
pub duration_min: u16,
pub duration: u32,
pub ascent: u32,
pub descent: u32,
pub moderate_activity_minutes: u16,
pub vigorous_activity_minutes: u16,
state: [u8; 4], pub unknown_fields: Vec<Field>,
pub developer_fields: Vec<DeveloperField>,
}
impl Monitoring {
pub const TIMESTAMP: u8 = 253;
pub const DEVICE_INDEX: u8 = 0;
pub const CALORIES: u8 = 1;
pub const DISTANCE: u8 = 2;
pub const CYCLES: u8 = 3;
pub const ACTIVE_TIME: u8 = 4;
pub const ACTIVITY_TYPE: u8 = 5;
pub const ACTIVITY_SUBTYPE: u8 = 6;
pub const ACTIVITY_LEVEL: u8 = 7;
pub const DISTANCE_16: u8 = 8;
pub const CYCLES_16: u8 = 9;
pub const ACTIVE_TIME_16: u8 = 10;
pub const LOCAL_TIMESTAMP: u8 = 11;
pub const TEMPERATURE: u8 = 12;
pub const TEMPERATURE_MIN: u8 = 14;
pub const TEMPERATURE_MAX: u8 = 15;
pub const ACTIVITY_TIME: u8 = 16;
pub const ACTIVE_CALORIES: u8 = 19;
pub const CURRENT_ACTIVITY_TYPE_INTENSITY: u8 = 24;
pub const TIMESTAMP_MIN_8: u8 = 25;
pub const TIMESTAMP_16: u8 = 26;
pub const HEART_RATE: u8 = 27;
pub const INTENSITY: u8 = 28;
pub const DURATION_MIN: u8 = 29;
pub const DURATION: u8 = 30;
pub const ASCENT: u8 = 31;
pub const DESCENT: u8 = 32;
pub const MODERATE_ACTIVITY_MINUTES: u8 = 33;
pub const VIGOROUS_ACTIVITY_MINUTES: u8 = 34;
pub const fn new() -> Self {
Self {
timestamp: typedef::DateTime(u32::MAX),
device_index: typedef::DeviceIndex(u8::MAX),
calories: u16::MAX,
distance: u32::MAX,
cycles: u32::MAX,
active_time: u32::MAX,
activity_type: typedef::ActivityType(u8::MAX),
activity_subtype: typedef::ActivitySubtype(u8::MAX),
activity_level: typedef::ActivityLevel(u8::MAX),
distance_16: u16::MAX,
cycles_16: u16::MAX,
active_time_16: u16::MAX,
local_timestamp: typedef::LocalDateTime(u32::MAX),
temperature: i16::MAX,
temperature_min: i16::MAX,
temperature_max: i16::MAX,
activity_time: [u16::MAX; 8],
active_calories: u16::MAX,
current_activity_type_intensity: u8::MAX,
timestamp_min_8: u8::MAX,
timestamp_16: u16::MAX,
heart_rate: u8::MAX,
intensity: u8::MAX,
duration_min: u16::MAX,
duration: u32::MAX,
ascent: u32::MAX,
descent: u32::MAX,
moderate_activity_minutes: u16::MAX,
vigorous_activity_minutes: u16::MAX,
state: [0u8; 4],
unknown_fields: Vec::new(),
developer_fields: Vec::new(),
}
}
pub fn distance_scaled(&self) -> Option<f64> {
if self.distance == u32::MAX {
return None;
}
Some(self.distance as f64 / 100.0 - 0.0)
}
pub fn set_distance_scaled(&mut self, v: f64) -> &mut Self {
let unscaled = (v + 0.0) * 100.0;
if unscaled.is_nan() || unscaled.is_infinite() || unscaled > u32::MAX as f64 {
self.distance = u32::MAX;
return self;
}
self.distance = unscaled as u32;
self
}
pub fn cycles_scaled(&self) -> Option<f64> {
if self.cycles == u32::MAX {
return None;
}
Some(self.cycles as f64 / 2.0 - 0.0)
}
pub fn set_cycles_scaled(&mut self, v: f64) -> &mut Self {
let unscaled = (v + 0.0) * 2.0;
if unscaled.is_nan() || unscaled.is_infinite() || unscaled > u32::MAX as f64 {
self.cycles = u32::MAX;
return self;
}
self.cycles = unscaled as u32;
self
}
pub fn active_time_scaled(&self) -> Option<f64> {
if self.active_time == u32::MAX {
return None;
}
Some(self.active_time as f64 / 1000.0 - 0.0)
}
pub fn set_active_time_scaled(&mut self, v: f64) -> &mut Self {
let unscaled = (v + 0.0) * 1000.0;
if unscaled.is_nan() || unscaled.is_infinite() || unscaled > u32::MAX as f64 {
self.active_time = u32::MAX;
return self;
}
self.active_time = unscaled as u32;
self
}
pub fn temperature_scaled(&self) -> Option<f64> {
if self.temperature == i16::MAX {
return None;
}
Some(self.temperature as f64 / 100.0 - 0.0)
}
pub fn set_temperature_scaled(&mut self, v: f64) -> &mut Self {
let unscaled = (v + 0.0) * 100.0;
if unscaled.is_nan() || unscaled.is_infinite() || unscaled > i16::MAX as f64 {
self.temperature = i16::MAX;
return self;
}
self.temperature = unscaled as i16;
self
}
pub fn temperature_min_scaled(&self) -> Option<f64> {
if self.temperature_min == i16::MAX {
return None;
}
Some(self.temperature_min as f64 / 100.0 - 0.0)
}
pub fn set_temperature_min_scaled(&mut self, v: f64) -> &mut Self {
let unscaled = (v + 0.0) * 100.0;
if unscaled.is_nan() || unscaled.is_infinite() || unscaled > i16::MAX as f64 {
self.temperature_min = i16::MAX;
return self;
}
self.temperature_min = unscaled as i16;
self
}
pub fn temperature_max_scaled(&self) -> Option<f64> {
if self.temperature_max == i16::MAX {
return None;
}
Some(self.temperature_max as f64 / 100.0 - 0.0)
}
pub fn set_temperature_max_scaled(&mut self, v: f64) -> &mut Self {
let unscaled = (v + 0.0) * 100.0;
if unscaled.is_nan() || unscaled.is_infinite() || unscaled > i16::MAX as f64 {
self.temperature_max = i16::MAX;
return self;
}
self.temperature_max = unscaled as i16;
self
}
pub fn intensity_scaled(&self) -> Option<f64> {
if self.intensity == u8::MAX {
return None;
}
Some(self.intensity as f64 / 10.0 - 0.0)
}
pub fn set_intensity_scaled(&mut self, v: f64) -> &mut Self {
let unscaled = (v + 0.0) * 10.0;
if unscaled.is_nan() || unscaled.is_infinite() || unscaled > u8::MAX as f64 {
self.intensity = u8::MAX;
return self;
}
self.intensity = unscaled as u8;
self
}
pub fn ascent_scaled(&self) -> Option<f64> {
if self.ascent == u32::MAX {
return None;
}
Some(self.ascent as f64 / 1000.0 - 0.0)
}
pub fn set_ascent_scaled(&mut self, v: f64) -> &mut Self {
let unscaled = (v + 0.0) * 1000.0;
if unscaled.is_nan() || unscaled.is_infinite() || unscaled > u32::MAX as f64 {
self.ascent = u32::MAX;
return self;
}
self.ascent = unscaled as u32;
self
}
pub fn descent_scaled(&self) -> Option<f64> {
if self.descent == u32::MAX {
return None;
}
Some(self.descent as f64 / 1000.0 - 0.0)
}
pub fn set_descent_scaled(&mut self, v: f64) -> &mut Self {
let unscaled = (v + 0.0) * 1000.0;
if unscaled.is_nan() || unscaled.is_infinite() || unscaled > u32::MAX as f64 {
self.descent = u32::MAX;
return self;
}
self.descent = unscaled as u32;
self
}
pub fn mark_as_expanded(&mut self, num: u8, flag: bool) -> bool {
match num {
5 | 28 => {
if flag {
self.state[num as usize >> 3] |= 1 << (num & 7)
} else {
self.state[num as usize >> 3] &= !(1 << (num & 7))
}
true
}
_ => false,
}
}
pub fn is_expanded(&self, num: u8) -> bool {
is_expanded(&self.state, num)
}
fn count_valid_fields(&self) -> usize {
(self.timestamp.0 != u32::MAX) as usize
+ (self.device_index.0 != u8::MAX) as usize
+ (self.calories != u16::MAX) as usize
+ (self.distance != u32::MAX) as usize
+ (self.cycles != u32::MAX) as usize
+ (self.active_time != u32::MAX) as usize
+ (self.activity_type.0 != u8::MAX) as usize
+ (self.activity_subtype.0 != u8::MAX) as usize
+ (self.activity_level.0 != u8::MAX) as usize
+ (self.distance_16 != u16::MAX) as usize
+ (self.cycles_16 != u16::MAX) as usize
+ (self.active_time_16 != u16::MAX) as usize
+ (self.local_timestamp.0 != u32::MAX) as usize
+ (self.temperature != i16::MAX) as usize
+ (self.temperature_min != i16::MAX) as usize
+ (self.temperature_max != i16::MAX) as usize
+ (self.activity_time != [u16::MAX; 8]) as usize
+ (self.active_calories != u16::MAX) as usize
+ (self.current_activity_type_intensity != u8::MAX) as usize
+ (self.timestamp_min_8 != u8::MAX) as usize
+ (self.timestamp_16 != u16::MAX) as usize
+ (self.heart_rate != u8::MAX) as usize
+ (self.intensity != u8::MAX) as usize
+ (self.duration_min != u16::MAX) as usize
+ (self.duration != u32::MAX) as usize
+ (self.ascent != u32::MAX) as usize
+ (self.descent != u32::MAX) as usize
+ (self.moderate_activity_minutes != u16::MAX) as usize
+ (self.vigorous_activity_minutes != u16::MAX) as usize
}
}
impl Default for Monitoring {
fn default() -> Self {
Self::new()
}
}
impl From<&Message> for Monitoring {
fn from(mesg: &Message) -> Self {
const KNOWN_NUMS: [u64; 4] = [34343608319, 0, 0, 2305843009213693952];
let mut n = 0u64;
for field in &mesg.fields {
n += (KNOWN_NUMS[field.num as usize >> 6] >> (field.num & 63)) & 1 ^ 1
}
let mut v = Self::new();
v.unknown_fields = Vec::<Field>::with_capacity(n as usize);
v.developer_fields = mesg.developer_fields.clone();
for field in &mesg.fields {
match field.num {
253 => v.timestamp = typedef::DateTime(field.value.as_u32()),
0 => v.device_index = typedef::DeviceIndex(field.value.as_u8()),
1 => v.calories = field.value.as_u16(),
2 => v.distance = field.value.as_u32(),
3 => v.cycles = field.value.as_u32(),
4 => v.active_time = field.value.as_u32(),
5 => v.activity_type = typedef::ActivityType(field.value.as_u8()),
6 => v.activity_subtype = typedef::ActivitySubtype(field.value.as_u8()),
7 => v.activity_level = typedef::ActivityLevel(field.value.as_u8()),
8 => v.distance_16 = field.value.as_u16(),
9 => v.cycles_16 = field.value.as_u16(),
10 => v.active_time_16 = field.value.as_u16(),
11 => v.local_timestamp = typedef::LocalDateTime(field.value.as_u32()),
12 => v.temperature = field.value.as_i16(),
14 => v.temperature_min = field.value.as_i16(),
15 => v.temperature_max = field.value.as_i16(),
16 => {
v.activity_time = match &field.value {
Value::VecUint16(v) => {
let mut arr = [u16::MAX; 8];
for (i, x) in v.iter().take(8).enumerate() {
arr[i] = *x;
}
arr
}
_ => [u16::MAX; 8],
}
}
19 => v.active_calories = field.value.as_u16(),
24 => v.current_activity_type_intensity = field.value.as_u8(),
25 => v.timestamp_min_8 = field.value.as_u8(),
26 => v.timestamp_16 = field.value.as_u16(),
27 => v.heart_rate = field.value.as_u8(),
28 => v.intensity = field.value.as_u8(),
29 => v.duration_min = field.value.as_u16(),
30 => v.duration = field.value.as_u32(),
31 => v.ascent = field.value.as_u32(),
32 => v.descent = field.value.as_u32(),
33 => v.moderate_activity_minutes = field.value.as_u16(),
34 => v.vigorous_activity_minutes = field.value.as_u16(),
_ => {
v.unknown_fields.push(field.clone());
continue;
}
};
if field.is_expanded && field.num < 29 {
v.state[field.num as usize >> 3] |= 1 << (field.num & 7)
}
}
v
}
}
impl From<Monitoring> for Message {
fn from(m: Monitoring) -> Self {
let mut fields =
Vec::<Field>::with_capacity(m.count_valid_fields() + m.unknown_fields.len());
if m.timestamp.0 != u32::MAX {
fields.push(Field {
num: 253,
base_type: FitBaseType::UINT32,
value: Value::Uint32(m.timestamp.0),
is_expanded: false,
});
};
if m.device_index.0 != u8::MAX {
fields.push(Field {
num: 0,
base_type: FitBaseType::UINT8,
value: Value::Uint8(m.device_index.0),
is_expanded: false,
});
};
if m.calories != u16::MAX {
fields.push(Field {
num: 1,
base_type: FitBaseType::UINT16,
value: Value::Uint16(m.calories),
is_expanded: false,
});
};
if m.distance != u32::MAX {
fields.push(Field {
num: 2,
base_type: FitBaseType::UINT32,
value: Value::Uint32(m.distance),
is_expanded: false,
});
};
if m.cycles != u32::MAX {
fields.push(Field {
num: 3,
base_type: FitBaseType::UINT32,
value: Value::Uint32(m.cycles),
is_expanded: false,
});
};
if m.active_time != u32::MAX {
fields.push(Field {
num: 4,
base_type: FitBaseType::UINT32,
value: Value::Uint32(m.active_time),
is_expanded: false,
});
};
if m.activity_type.0 != u8::MAX {
fields.push(Field {
num: 5,
base_type: FitBaseType::ENUM,
value: Value::Uint8(m.activity_type.0),
is_expanded: is_expanded(&m.state, 5),
});
};
if m.activity_subtype.0 != u8::MAX {
fields.push(Field {
num: 6,
base_type: FitBaseType::ENUM,
value: Value::Uint8(m.activity_subtype.0),
is_expanded: false,
});
};
if m.activity_level.0 != u8::MAX {
fields.push(Field {
num: 7,
base_type: FitBaseType::ENUM,
value: Value::Uint8(m.activity_level.0),
is_expanded: false,
});
};
if m.distance_16 != u16::MAX {
fields.push(Field {
num: 8,
base_type: FitBaseType::UINT16,
value: Value::Uint16(m.distance_16),
is_expanded: false,
});
};
if m.cycles_16 != u16::MAX {
fields.push(Field {
num: 9,
base_type: FitBaseType::UINT16,
value: Value::Uint16(m.cycles_16),
is_expanded: false,
});
};
if m.active_time_16 != u16::MAX {
fields.push(Field {
num: 10,
base_type: FitBaseType::UINT16,
value: Value::Uint16(m.active_time_16),
is_expanded: false,
});
};
if m.local_timestamp.0 != u32::MAX {
fields.push(Field {
num: 11,
base_type: FitBaseType::UINT32,
value: Value::Uint32(m.local_timestamp.0),
is_expanded: false,
});
};
if m.temperature != i16::MAX {
fields.push(Field {
num: 12,
base_type: FitBaseType::SINT16,
value: Value::Int16(m.temperature),
is_expanded: false,
});
};
if m.temperature_min != i16::MAX {
fields.push(Field {
num: 14,
base_type: FitBaseType::SINT16,
value: Value::Int16(m.temperature_min),
is_expanded: false,
});
};
if m.temperature_max != i16::MAX {
fields.push(Field {
num: 15,
base_type: FitBaseType::SINT16,
value: Value::Int16(m.temperature_max),
is_expanded: false,
});
};
if m.activity_time != [u16::MAX; 8] {
fields.push(Field {
num: 16,
base_type: FitBaseType::UINT16,
value: Value::VecUint16(Vec::from(&m.activity_time)),
is_expanded: false,
});
};
if m.active_calories != u16::MAX {
fields.push(Field {
num: 19,
base_type: FitBaseType::UINT16,
value: Value::Uint16(m.active_calories),
is_expanded: false,
});
};
if m.current_activity_type_intensity != u8::MAX {
fields.push(Field {
num: 24,
base_type: FitBaseType::BYTE,
value: Value::Uint8(m.current_activity_type_intensity),
is_expanded: false,
});
};
if m.timestamp_min_8 != u8::MAX {
fields.push(Field {
num: 25,
base_type: FitBaseType::UINT8,
value: Value::Uint8(m.timestamp_min_8),
is_expanded: false,
});
};
if m.timestamp_16 != u16::MAX {
fields.push(Field {
num: 26,
base_type: FitBaseType::UINT16,
value: Value::Uint16(m.timestamp_16),
is_expanded: false,
});
};
if m.heart_rate != u8::MAX {
fields.push(Field {
num: 27,
base_type: FitBaseType::UINT8,
value: Value::Uint8(m.heart_rate),
is_expanded: false,
});
};
if m.intensity != u8::MAX {
fields.push(Field {
num: 28,
base_type: FitBaseType::UINT8,
value: Value::Uint8(m.intensity),
is_expanded: is_expanded(&m.state, 28),
});
};
if m.duration_min != u16::MAX {
fields.push(Field {
num: 29,
base_type: FitBaseType::UINT16,
value: Value::Uint16(m.duration_min),
is_expanded: false,
});
};
if m.duration != u32::MAX {
fields.push(Field {
num: 30,
base_type: FitBaseType::UINT32,
value: Value::Uint32(m.duration),
is_expanded: false,
});
};
if m.ascent != u32::MAX {
fields.push(Field {
num: 31,
base_type: FitBaseType::UINT32,
value: Value::Uint32(m.ascent),
is_expanded: false,
});
};
if m.descent != u32::MAX {
fields.push(Field {
num: 32,
base_type: FitBaseType::UINT32,
value: Value::Uint32(m.descent),
is_expanded: false,
});
};
if m.moderate_activity_minutes != u16::MAX {
fields.push(Field {
num: 33,
base_type: FitBaseType::UINT16,
value: Value::Uint16(m.moderate_activity_minutes),
is_expanded: false,
});
};
if m.vigorous_activity_minutes != u16::MAX {
fields.push(Field {
num: 34,
base_type: FitBaseType::UINT16,
value: Value::Uint16(m.vigorous_activity_minutes),
is_expanded: false,
});
};
fields.extend_from_slice(&m.unknown_fields);
Self {
header: 0,
num: typedef::MesgNum::MONITORING,
fields,
developer_fields: m.developer_fields,
}
}
}
#[cfg(feature = "serde")]
impl Serialize for Monitoring {
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
where
S: Serializer,
{
let n = self.count_valid_fields() + 2;
let mut state = serializer.serialize_struct("Monitoring", n)?;
if let Some(v) = self.timestamp.unix_timestamp() {
state.serialize_field("timestamp", &v)?;
}
if self.device_index.0 != u8::MAX {
state.serialize_field("device_index", &self.device_index)?;
}
if self.calories != u16::MAX {
state.serialize_field("calories", &self.calories)?;
}
if let Some(v) = self.distance_scaled() {
state.serialize_field("distance", &v)?;
}
if let Some(v) = self.cycles_scaled() {
state.serialize_field("cycles", &v)?;
}
if let Some(v) = self.active_time_scaled() {
state.serialize_field("active_time", &v)?;
}
if self.activity_type.0 != u8::MAX {
state.serialize_field("activity_type", &self.activity_type)?;
}
if self.activity_subtype.0 != u8::MAX {
state.serialize_field("activity_subtype", &self.activity_subtype)?;
}
if self.activity_level.0 != u8::MAX {
state.serialize_field("activity_level", &self.activity_level)?;
}
if self.distance_16 != u16::MAX {
state.serialize_field("distance_16", &self.distance_16)?;
}
if self.cycles_16 != u16::MAX {
state.serialize_field("cycles_16", &self.cycles_16)?;
}
if self.active_time_16 != u16::MAX {
state.serialize_field("active_time_16", &self.active_time_16)?;
}
if let Some(v) = self.local_timestamp.unix_timestamp() {
state.serialize_field("local_timestamp", &v)?;
}
if let Some(v) = self.temperature_scaled() {
state.serialize_field("temperature", &v)?;
}
if let Some(v) = self.temperature_min_scaled() {
state.serialize_field("temperature_min", &v)?;
}
if let Some(v) = self.temperature_max_scaled() {
state.serialize_field("temperature_max", &v)?;
}
if self.activity_time != [u16::MAX; 8] {
state.serialize_field("activity_time", &self.activity_time)?;
}
if self.active_calories != u16::MAX {
state.serialize_field("active_calories", &self.active_calories)?;
}
if self.current_activity_type_intensity != u8::MAX {
state.serialize_field(
"current_activity_type_intensity",
&self.current_activity_type_intensity,
)?;
}
if self.timestamp_min_8 != u8::MAX {
state.serialize_field("timestamp_min_8", &self.timestamp_min_8)?;
}
if self.timestamp_16 != u16::MAX {
state.serialize_field("timestamp_16", &self.timestamp_16)?;
}
if self.heart_rate != u8::MAX {
state.serialize_field("heart_rate", &self.heart_rate)?;
}
if let Some(v) = self.intensity_scaled() {
state.serialize_field("intensity", &v)?;
}
if self.duration_min != u16::MAX {
state.serialize_field("duration_min", &self.duration_min)?;
}
if self.duration != u32::MAX {
state.serialize_field("duration", &self.duration)?;
}
if let Some(v) = self.ascent_scaled() {
state.serialize_field("ascent", &v)?;
}
if let Some(v) = self.descent_scaled() {
state.serialize_field("descent", &v)?;
}
if self.moderate_activity_minutes != u16::MAX {
state.serialize_field("moderate_activity_minutes", &self.moderate_activity_minutes)?;
}
if self.vigorous_activity_minutes != u16::MAX {
state.serialize_field("vigorous_activity_minutes", &self.vigorous_activity_minutes)?;
}
if !self.unknown_fields.is_empty() {
state.serialize_field("unknown_fields", &self.unknown_fields)?;
}
if !self.developer_fields.is_empty() {
state.serialize_field("developer_fields", &self.developer_fields)?;
}
state.end()
}
}
#[cfg(feature = "serde")]
#[cfg_attr(feature = "serde", derive(Deserialize), serde(default))]
struct De {
timestamp: Option<i64>,
device_index: typedef::DeviceIndex,
calories: u16,
distance: f64,
cycles: f64,
active_time: f64,
activity_type: typedef::ActivityType,
activity_subtype: typedef::ActivitySubtype,
activity_level: typedef::ActivityLevel,
distance_16: u16,
cycles_16: u16,
active_time_16: u16,
local_timestamp: Option<i64>,
temperature: f64,
temperature_min: f64,
temperature_max: f64,
activity_time: [u16; 8],
active_calories: u16,
current_activity_type_intensity: u8,
timestamp_min_8: u8,
timestamp_16: u16,
heart_rate: u8,
intensity: f64,
duration_min: u16,
duration: u32,
ascent: f64,
descent: f64,
moderate_activity_minutes: u16,
vigorous_activity_minutes: u16,
unknown_fields: Vec<Field>,
developer_fields: Vec<DeveloperField>,
}
#[cfg(feature = "serde")]
impl From<De> for Monitoring {
fn from(m: De) -> Self {
Self {
timestamp: m.timestamp.map_or_else(
|| typedef::DateTime(u32::MAX),
typedef::DateTime::from_unix_timestamp,
),
device_index: m.device_index,
calories: m.calories,
distance: {
let unscaled = (m.distance + 0.0) * 100.0;
if unscaled.is_nan() || unscaled.is_infinite() || unscaled > u32::MAX as f64 {
u32::MAX
} else {
unscaled as u32
}
},
cycles: {
let unscaled = (m.cycles + 0.0) * 2.0;
if unscaled.is_nan() || unscaled.is_infinite() || unscaled > u32::MAX as f64 {
u32::MAX
} else {
unscaled as u32
}
},
active_time: {
let unscaled = (m.active_time + 0.0) * 1000.0;
if unscaled.is_nan() || unscaled.is_infinite() || unscaled > u32::MAX as f64 {
u32::MAX
} else {
unscaled as u32
}
},
activity_type: m.activity_type,
activity_subtype: m.activity_subtype,
activity_level: m.activity_level,
distance_16: m.distance_16,
cycles_16: m.cycles_16,
active_time_16: m.active_time_16,
local_timestamp: m.local_timestamp.map_or_else(
|| typedef::LocalDateTime(u32::MAX),
typedef::LocalDateTime::from_unix_timestamp,
),
temperature: {
let unscaled = (m.temperature + 0.0) * 100.0;
if unscaled.is_nan() || unscaled.is_infinite() || unscaled > i16::MAX as f64 {
i16::MAX
} else {
unscaled as i16
}
},
temperature_min: {
let unscaled = (m.temperature_min + 0.0) * 100.0;
if unscaled.is_nan() || unscaled.is_infinite() || unscaled > i16::MAX as f64 {
i16::MAX
} else {
unscaled as i16
}
},
temperature_max: {
let unscaled = (m.temperature_max + 0.0) * 100.0;
if unscaled.is_nan() || unscaled.is_infinite() || unscaled > i16::MAX as f64 {
i16::MAX
} else {
unscaled as i16
}
},
activity_time: m.activity_time,
active_calories: m.active_calories,
current_activity_type_intensity: m.current_activity_type_intensity,
timestamp_min_8: m.timestamp_min_8,
timestamp_16: m.timestamp_16,
heart_rate: m.heart_rate,
intensity: {
let unscaled = (m.intensity + 0.0) * 10.0;
if unscaled.is_nan() || unscaled.is_infinite() || unscaled > u8::MAX as f64 {
u8::MAX
} else {
unscaled as u8
}
},
duration_min: m.duration_min,
duration: m.duration,
ascent: {
let unscaled = (m.ascent + 0.0) * 1000.0;
if unscaled.is_nan() || unscaled.is_infinite() || unscaled > u32::MAX as f64 {
u32::MAX
} else {
unscaled as u32
}
},
descent: {
let unscaled = (m.descent + 0.0) * 1000.0;
if unscaled.is_nan() || unscaled.is_infinite() || unscaled > u32::MAX as f64 {
u32::MAX
} else {
unscaled as u32
}
},
moderate_activity_minutes: m.moderate_activity_minutes,
vigorous_activity_minutes: m.vigorous_activity_minutes,
state: [0u8; 4],
unknown_fields: m.unknown_fields,
developer_fields: m.developer_fields,
}
}
}
#[cfg(feature = "serde")]
impl Default for De {
fn default() -> Self {
Self {
timestamp: None,
device_index: typedef::DeviceIndex(u8::MAX),
calories: u16::MAX,
distance: f64::from_bits(u64::MAX),
cycles: f64::from_bits(u64::MAX),
active_time: f64::from_bits(u64::MAX),
activity_type: typedef::ActivityType(u8::MAX),
activity_subtype: typedef::ActivitySubtype(u8::MAX),
activity_level: typedef::ActivityLevel(u8::MAX),
distance_16: u16::MAX,
cycles_16: u16::MAX,
active_time_16: u16::MAX,
local_timestamp: None,
temperature: f64::from_bits(u64::MAX),
temperature_min: f64::from_bits(u64::MAX),
temperature_max: f64::from_bits(u64::MAX),
activity_time: [u16::MAX; 8],
active_calories: u16::MAX,
current_activity_type_intensity: u8::MAX,
timestamp_min_8: u8::MAX,
timestamp_16: u16::MAX,
heart_rate: u8::MAX,
intensity: f64::from_bits(u64::MAX),
duration_min: u16::MAX,
duration: u32::MAX,
ascent: f64::from_bits(u64::MAX),
descent: f64::from_bits(u64::MAX),
moderate_activity_minutes: u16::MAX,
vigorous_activity_minutes: u16::MAX,
unknown_fields: Vec::new(),
developer_fields: Vec::new(),
}
}
}