use std::fmt::Formatter;
use std::ops::{Add, BitOr, BitOrAssign};
use crate::app::sequence::Sequence;
use crate::app::FunctionCode;
use crate::outstation::{ApplicationIin, RequestError};
use crate::util::bit::bits::*;
use crate::util::bit::{format_bitfield, Bitfield};
use scursor::*;
#[derive(Copy, Clone, Debug, PartialEq, Eq)]
pub struct ControlField {
pub fir: bool,
pub fin: bool,
pub con: bool,
pub uns: bool,
pub seq: Sequence,
}
impl std::fmt::Display for ControlField {
fn fmt(&self, f: &mut Formatter) -> std::fmt::Result {
write!(
f,
"[fir: {} fin: {} con: {} uns: {} seq: {}]",
self.fir,
self.fin,
self.con,
self.uns,
self.seq.value()
)
}
}
impl ControlField {
const FIR_MASK: u8 = 0b1000_0000;
const FIN_MASK: u8 = 0b0100_0000;
const CON_MASK: u8 = 0b0010_0000;
const UNS_MASK: u8 = 0b0001_0000;
pub(crate) fn response(seq: Sequence, fir: bool, fin: bool, con: bool) -> Self {
Self {
fir,
fin,
con,
uns: false,
seq,
}
}
pub(crate) fn single_response(seq: Sequence) -> Self {
Self {
fir: true,
fin: true,
con: false,
uns: false,
seq,
}
}
pub(crate) fn request(seq: Sequence) -> Self {
Self {
fir: true,
fin: true,
con: false,
uns: false,
seq,
}
}
pub(crate) fn unsolicited(seq: Sequence) -> Self {
Self {
fir: true,
fin: true,
con: false,
uns: true,
seq,
}
}
pub(crate) fn unsolicited_response(seq: Sequence) -> Self {
Self {
fir: true,
fin: true,
con: true,
uns: true,
seq,
}
}
pub(crate) fn from(x: u8) -> Self {
Self {
fir: x & Self::FIR_MASK != 0,
fin: x & Self::FIN_MASK != 0,
con: x & Self::CON_MASK != 0,
uns: x & Self::UNS_MASK != 0,
seq: Sequence::new(x),
}
}
pub(crate) fn is_fir_and_fin(self) -> bool {
self.fir && self.fin
}
pub(crate) fn to_u8(self) -> u8 {
let mut x: u8 = 0;
if self.fir {
x |= Self::FIR_MASK;
}
if self.fin {
x |= Self::FIN_MASK;
}
if self.con {
x |= Self::CON_MASK;
}
if self.uns {
x |= Self::UNS_MASK;
}
x |= self.seq.value();
x
}
pub(crate) fn parse(cursor: &mut ReadCursor) -> Result<Self, ReadError> {
Ok(Self::from(cursor.read_u8()?))
}
pub(crate) fn write(self, cursor: &mut WriteCursor) -> Result<(), WriteError> {
cursor.write_u8(self.to_u8())
}
}
#[derive(Copy, Clone, Debug, PartialEq, Eq)]
pub struct Iin1 {
pub value: u8,
}
#[derive(Copy, Clone, Debug, PartialEq, Eq)]
pub struct Iin2 {
pub value: u8,
}
#[derive(Copy, Clone, Debug, PartialEq, Eq)]
pub struct Iin {
pub iin1: Iin1,
pub iin2: Iin2,
}
impl Iin1 {
pub const BROADCAST: Iin1 = Iin1::new(BIT_0.value);
pub const CLASS_1_EVENTS: Iin1 = Iin1::new(BIT_1.value);
pub const CLASS_2_EVENTS: Iin1 = Iin1::new(BIT_2.value);
pub const CLASS_3_EVENTS: Iin1 = Iin1::new(BIT_3.value);
pub const NEED_TIME: Iin1 = Iin1::new(BIT_4.value);
pub const LOCAL_CONTROL: Iin1 = Iin1::new(BIT_5.value);
pub const DEVICE_TROUBLE: Iin1 = Iin1::new(BIT_6.value);
pub const RESTART: Iin1 = Iin1::new(BIT_7.value);
pub const fn new(value: u8) -> Self {
Self { value }
}
pub fn get_broadcast(&self) -> bool {
self.value.bit_0()
}
pub fn get_class_1_events(self) -> bool {
self.value.bit_1()
}
pub fn get_class_2_events(self) -> bool {
self.value.bit_2()
}
pub fn get_class_3_events(self) -> bool {
self.value.bit_3()
}
pub fn get_need_time(self) -> bool {
self.value.bit_4()
}
pub fn get_local_control(self) -> bool {
self.value.bit_5()
}
pub fn get_device_trouble(self) -> bool {
self.value.bit_6()
}
pub fn get_device_restart(self) -> bool {
self.value.bit_7()
}
}
impl Default for Iin1 {
fn default() -> Self {
Self::new(0)
}
}
impl BitOr for Iin1 {
type Output = Self;
fn bitor(self, rhs: Iin1) -> Self::Output {
Self::new(self.value | rhs.value)
}
}
impl BitOrAssign<Iin1> for Iin1 {
fn bitor_assign(&mut self, rhs: Iin1) {
*self = *self | rhs
}
}
impl Iin2 {
pub const NO_FUNC_CODE_SUPPORT: Iin2 = Iin2::new(BIT_0.value);
pub const OBJECT_UNKNOWN: Iin2 = Iin2::new(BIT_1.value);
pub const PARAMETER_ERROR: Iin2 = Iin2::new(BIT_2.value);
pub const EVENT_BUFFER_OVERFLOW: Iin2 = Iin2::new(BIT_3.value);
pub const ALREADY_EXECUTING: Iin2 = Iin2::new(BIT_4.value);
pub const CONFIG_CORRUPT: Iin2 = Iin2::new(BIT_5.value);
pub const fn new(value: u8) -> Self {
Self { value }
}
pub(crate) fn set(&mut self, iin2: Self) {
self.value |= iin2.value;
}
pub fn get_no_func_code_support(self) -> bool {
self.value.bit_0()
}
pub fn get_object_unknown(self) -> bool {
self.value.bit_1()
}
pub fn get_parameter_error(self) -> bool {
self.value.bit_2()
}
pub fn get_event_buffer_overflow(self) -> bool {
self.value.bit_3()
}
pub fn get_already_executing(self) -> bool {
self.value.bit_4()
}
pub fn get_config_corrupt(self) -> bool {
self.value.bit_5()
}
pub fn get_reserved_2(self) -> bool {
self.value.bit_6()
}
pub fn get_reserved_1(self) -> bool {
self.value.bit_7()
}
}
impl Default for Iin2 {
fn default() -> Self {
Self::new(0)
}
}
impl BitOr for Iin2 {
type Output = Self;
fn bitor(self, rhs: Iin2) -> Self::Output {
Self::new(self.value | rhs.value)
}
}
impl BitOrAssign<Iin2> for Iin2 {
fn bitor_assign(&mut self, rhs: Iin2) {
*self = *self | rhs
}
}
impl Default for Iin {
fn default() -> Self {
Iin::new(Iin1::default(), Iin2::default())
}
}
impl BitOr for Iin {
type Output = Iin;
fn bitor(self, rhs: Self) -> Self::Output {
Self {
iin1: self.iin1 | rhs.iin1,
iin2: self.iin2 | rhs.iin2,
}
}
}
impl BitOrAssign for Iin {
fn bitor_assign(&mut self, rhs: Iin) {
*self = *self | rhs
}
}
impl BitOr<Iin1> for Iin {
type Output = Self;
fn bitor(self, rhs: Iin1) -> Self::Output {
Self {
iin1: self.iin1 | rhs,
iin2: self.iin2,
}
}
}
impl BitOrAssign<Iin1> for Iin {
fn bitor_assign(&mut self, rhs: Iin1) {
*self = *self | rhs;
}
}
impl BitOr<Iin2> for Iin {
type Output = Self;
fn bitor(self, rhs: Iin2) -> Self::Output {
Self {
iin1: self.iin1,
iin2: self.iin2 | rhs,
}
}
}
impl BitOrAssign<Iin2> for Iin {
fn bitor_assign(&mut self, rhs: Iin2) {
*self = *self | rhs;
}
}
impl BitOr<ApplicationIin> for Iin {
type Output = Self;
fn bitor(mut self, rhs: ApplicationIin) -> Self::Output {
if rhs.need_time {
self |= Iin1::NEED_TIME;
}
if rhs.local_control {
self |= Iin1::LOCAL_CONTROL;
}
if rhs.device_trouble {
self |= Iin1::DEVICE_TROUBLE;
}
if rhs.config_corrupt {
self |= Iin2::CONFIG_CORRUPT;
}
self
}
}
impl BitOrAssign<ApplicationIin> for Iin {
fn bitor_assign(&mut self, rhs: ApplicationIin) {
*self = *self | rhs;
}
}
impl From<RequestError> for Iin2 {
fn from(from: RequestError) -> Self {
match from {
RequestError::ParameterError => Iin2::PARAMETER_ERROR,
RequestError::NotSupported => Iin2::NO_FUNC_CODE_SUPPORT,
}
}
}
impl Add<Iin2> for Iin1 {
type Output = Iin;
fn add(self, rhs: Iin2) -> Self::Output {
Iin::new(self, rhs)
}
}
impl std::fmt::Display for Iin1 {
fn fmt(&self, f: &mut Formatter) -> std::fmt::Result {
format_bitfield(
f,
self.value,
"iin1",
[
"BROADCAST",
"CLASS_1_EVENTS",
"CLASS_2_EVENTS",
"CLASS_3_EVENTS",
"NEED_TIME",
"LOCAL_CONTROL",
"DEVICE_TROUBLE",
"DEVICE_RESTART",
],
)
}
}
impl std::fmt::Display for Iin2 {
fn fmt(&self, f: &mut Formatter) -> std::fmt::Result {
format_bitfield(
f,
self.value,
"iin2",
[
"NO_FUNC_CODE_SUPPORT",
"OBJECT_UNKNOWN",
"PARAMETER_ERROR",
"EVENT_BUFFER_OVERFLOW",
"ALREADY_EXECUTING",
"CONFIG_CORRUPT",
"RESERVED_2",
"RESERVED_1",
],
)
}
}
impl Iin {
pub const fn new(iin1: Iin1, iin2: Iin2) -> Self {
Self { iin1, iin2 }
}
pub(crate) fn parse(cursor: &mut ReadCursor) -> Result<Self, ReadError> {
Ok(Self {
iin1: Iin1::new(cursor.read_u8()?),
iin2: Iin2::new(cursor.read_u8()?),
})
}
pub(crate) fn has_request_error(self) -> bool {
self.iin2.get_no_func_code_support()
|| self.iin2.get_object_unknown()
|| self.iin2.get_parameter_error()
}
pub(crate) fn write(self, cursor: &mut WriteCursor) -> Result<(), WriteError> {
cursor.write_u8(self.iin1.value)?;
cursor.write_u8(self.iin2.value)?;
Ok(())
}
}
#[derive(Copy, Clone, Debug, PartialEq, Eq)]
pub struct RequestHeader {
pub control: ControlField,
pub function: FunctionCode,
}
#[derive(Copy, Clone, Debug, PartialEq, Eq)]
pub enum ResponseFunction {
Response,
UnsolicitedResponse,
}
#[derive(Copy, Clone, Debug, PartialEq, Eq)]
pub struct ResponseHeader {
pub control: ControlField,
pub function: ResponseFunction,
pub iin: Iin,
}
impl ResponseFunction {
pub fn is_unsolicited(self) -> bool {
match self {
ResponseFunction::Response => false,
ResponseFunction::UnsolicitedResponse => true,
}
}
pub(crate) fn function(&self) -> FunctionCode {
match self {
ResponseFunction::Response => FunctionCode::Response,
ResponseFunction::UnsolicitedResponse => FunctionCode::UnsolicitedResponse,
}
}
}
impl From<ResponseFunction> for FunctionCode {
fn from(from: ResponseFunction) -> Self {
match from {
ResponseFunction::Response => FunctionCode::Response,
ResponseFunction::UnsolicitedResponse => FunctionCode::UnsolicitedResponse,
}
}
}
impl RequestHeader {
pub(crate) fn new(control: ControlField, function: FunctionCode) -> Self {
Self { control, function }
}
pub(crate) fn write(self, cursor: &mut WriteCursor) -> Result<(), WriteError> {
self.control.write(cursor)?;
self.function.write(cursor)?;
Ok(())
}
}
impl ResponseHeader {
pub(crate) const LENGTH: usize = 4;
pub(crate) fn new(control: ControlField, function: ResponseFunction, iin: Iin) -> Self {
Self {
control,
function,
iin,
}
}
pub(crate) fn write(self, cursor: &mut WriteCursor) -> Result<(), WriteError> {
self.control.write(cursor)?;
self.function.function().write(cursor)?;
self.iin.write(cursor)?;
Ok(())
}
}