use crate::{
application_protocol::primitives::data_value::ApplicationDataValue,
common::{
error::Error,
helper::{
decode_unsigned, encode_context_bool, encode_context_object_id,
encode_context_unsigned, get_tagged_body_for_tag,
},
io::{Reader, Writer},
object_id::{ObjectId, ObjectType},
property_id::PropertyId,
tag::{Tag, TagNumber},
},
};
#[derive(Debug, Clone)]
#[cfg_attr(feature = "defmt", derive(defmt::Format))]
pub struct CovNotification<'a> {
pub process_id: u32,
pub device_id: ObjectId,
pub object_id: ObjectId,
pub time_remaining_seconds: u32,
reader: Reader,
buf: &'a [u8],
}
#[derive(Debug, Clone)]
#[cfg_attr(feature = "defmt", derive(defmt::Format))]
pub struct PropertyResult<'a> {
pub id: PropertyId,
pub value: ApplicationDataValue<'a>,
}
impl<'a> CovNotification<'a> {
const TAG_PROCESS_ID: u8 = 0;
const TAG_DEVICE_ID: u8 = 1;
const TAG_OBJECT_ID: u8 = 2;
const TAG_LIFETIME: u8 = 3;
const TAG_LIST_OF_VALUES: u8 = 4;
pub fn decode(reader: &mut Reader, buf: &'a [u8]) -> Result<Self, Error> {
let tag = Tag::decode_expected(
reader,
buf,
TagNumber::ContextSpecific(Self::TAG_PROCESS_ID),
"CovNotification process_id",
)?;
let process_id = decode_unsigned(tag.value, reader, buf)? as u32;
let tag = Tag::decode_expected(
reader,
buf,
TagNumber::ContextSpecific(Self::TAG_DEVICE_ID),
"CovNotification device_id tag",
)?;
let device_id = ObjectId::decode(tag.value, reader, buf)?;
if device_id.object_type != ObjectType::ObjectDevice {
return Err(Error::InvalidValue(
"expected device object type for CovNotification device_id field",
));
}
let tag = Tag::decode_expected(
reader,
buf,
TagNumber::ContextSpecific(Self::TAG_OBJECT_ID),
"CovNotification object_id",
)?;
let object_id = ObjectId::decode(tag.value, reader, buf)?;
let tag = Tag::decode_expected(
reader,
buf,
TagNumber::ContextSpecific(Self::TAG_LIFETIME),
"CovNotification lifetime",
)?;
let time_remaining_seconds = decode_unsigned(tag.value, reader, buf)? as u32;
let buf = get_tagged_body_for_tag(
reader,
buf,
Self::TAG_LIST_OF_VALUES,
"CovNotification decode list of values",
)?;
let reader = Reader {
index: 0,
end: buf.len(),
};
Ok(Self {
process_id,
device_id,
object_id,
time_remaining_seconds,
buf,
reader,
})
}
fn next_internal(&mut self) -> Result<PropertyResult<'a>, Error> {
let tag = Tag::decode_expected(
&mut self.reader,
self.buf,
TagNumber::ContextSpecific(0),
"CovNotification next property_id",
)?;
let property_id: PropertyId =
(decode_unsigned(tag.value, &mut self.reader, self.buf)? as u32).into();
Tag::decode_expected(
&mut self.reader,
self.buf,
TagNumber::ContextSpecificOpening(2),
"CovNotification next expected value opening tag",
)?;
let tag = Tag::decode(&mut self.reader, self.buf)?;
let value = ApplicationDataValue::decode(
&tag,
&self.object_id,
&property_id,
&mut self.reader,
self.buf,
)?;
Tag::decode_expected(
&mut self.reader,
self.buf,
TagNumber::ContextSpecificClosing(2),
"CovNotification next expected value closing tag",
)?;
Ok(PropertyResult {
id: property_id,
value,
})
}
}
impl<'a> Iterator for CovNotification<'a> {
type Item = Result<PropertyResult<'a>, Error>;
fn next(&mut self) -> Option<Self::Item> {
if self.reader.eof() {
return None;
}
let result = self.next_internal();
Some(result)
}
}
#[derive(Debug, Clone)]
#[cfg_attr(feature = "defmt", derive(defmt::Format))]
pub struct SubscribeCov {
process_id: u32,
object_id: ObjectId,
issue_confirmed_notifications: bool,
lifetime_seconds: u32, }
impl SubscribeCov {
const TAG_PROCESS_ID: u8 = 0;
const TAG_OBJECT_ID: u8 = 1;
const TAG_CONFIRMED: u8 = 2;
const TAG_LIFETIME: u8 = 3;
pub fn new(
process_id: u32,
object_id: ObjectId,
issue_confirmed_notifications: bool,
lifetime_seconds: u32,
) -> Self {
Self {
process_id,
object_id,
issue_confirmed_notifications,
lifetime_seconds,
}
}
pub fn encode(&self, writer: &mut Writer) {
encode_context_unsigned(writer, Self::TAG_PROCESS_ID, self.process_id);
encode_context_object_id(writer, Self::TAG_OBJECT_ID, &self.object_id);
encode_context_bool(
writer,
Self::TAG_CONFIRMED,
self.issue_confirmed_notifications,
);
encode_context_unsigned(writer, Self::TAG_LIFETIME, self.lifetime_seconds);
}
}