use tokio::sync::oneshot;
use mbus_core::errors::MbusError;
use mbus_core::transport::UnitIdOrSlaveAddr;
#[cfg(feature = "diagnostics")]
use mbus_core::function_codes::public::{DiagnosticSubFunction, EncapsulatedInterfaceType};
#[cfg(feature = "coils")]
use mbus_core::models::coil::Coils;
#[cfg(feature = "diagnostics")]
use mbus_core::models::diagnostic::{ObjectId, ReadDeviceIdCode};
#[cfg(feature = "file-record")]
use mbus_core::models::file_record::SubRequest;
use crate::client::response::ClientResponse;
pub(crate) type ResponseSender = oneshot::Sender<Result<ClientResponse, MbusError>>;
#[allow(clippy::large_enum_variant)]
#[derive(Debug)]
pub(crate) enum ClientRequest {
#[cfg(feature = "coils")]
ReadMultipleCoils {
unit: UnitIdOrSlaveAddr,
address: u16,
quantity: u16,
},
#[cfg(feature = "coils")]
WriteSingleCoil {
unit: UnitIdOrSlaveAddr,
address: u16,
value: bool,
},
#[cfg(feature = "coils")]
WriteMultipleCoils {
unit: UnitIdOrSlaveAddr,
address: u16,
coils: Coils,
},
#[cfg(feature = "holding-registers")]
ReadHoldingRegisters {
unit: UnitIdOrSlaveAddr,
address: u16,
quantity: u16,
},
#[cfg(feature = "input-registers")]
ReadInputRegisters {
unit: UnitIdOrSlaveAddr,
address: u16,
quantity: u16,
},
#[cfg(feature = "holding-registers")]
WriteSingleRegister {
unit: UnitIdOrSlaveAddr,
address: u16,
value: u16,
},
#[cfg(feature = "holding-registers")]
WriteMultipleRegisters {
unit: UnitIdOrSlaveAddr,
address: u16,
values: heapless::Vec<u16, { mbus_core::data_unit::common::MAX_PDU_DATA_LEN }>,
},
#[cfg(feature = "holding-registers")]
ReadWriteMultipleRegisters {
unit: UnitIdOrSlaveAddr,
read_address: u16,
read_quantity: u16,
write_address: u16,
write_values: heapless::Vec<u16, { mbus_core::data_unit::common::MAX_PDU_DATA_LEN }>,
},
#[cfg(feature = "holding-registers")]
MaskWriteRegister {
unit: UnitIdOrSlaveAddr,
address: u16,
and_mask: u16,
or_mask: u16,
},
#[cfg(feature = "discrete-inputs")]
ReadDiscreteInputs {
unit: UnitIdOrSlaveAddr,
address: u16,
quantity: u16,
},
#[cfg(feature = "fifo")]
ReadFifoQueue {
unit: UnitIdOrSlaveAddr,
address: u16,
},
#[cfg(feature = "file-record")]
ReadFileRecord {
unit: UnitIdOrSlaveAddr,
sub_request: SubRequest,
},
#[cfg(feature = "file-record")]
WriteFileRecord {
unit: UnitIdOrSlaveAddr,
sub_request: SubRequest,
},
#[cfg(feature = "diagnostics")]
ReadDeviceIdentification {
unit: UnitIdOrSlaveAddr,
read_device_id_code: ReadDeviceIdCode,
object_id: ObjectId,
},
#[cfg(feature = "diagnostics")]
EncapsulatedInterfaceTransport {
unit: UnitIdOrSlaveAddr,
mei_type: EncapsulatedInterfaceType,
data: heapless::Vec<u8, { mbus_core::data_unit::common::MAX_PDU_DATA_LEN }>,
},
#[cfg(feature = "diagnostics")]
ReadExceptionStatus { unit: UnitIdOrSlaveAddr },
#[cfg(feature = "diagnostics")]
Diagnostics {
unit: UnitIdOrSlaveAddr,
sub_function: DiagnosticSubFunction,
data: heapless::Vec<u16, { mbus_core::data_unit::common::MAX_PDU_DATA_LEN }>,
},
#[cfg(feature = "diagnostics")]
GetCommEventCounter { unit: UnitIdOrSlaveAddr },
#[cfg(feature = "diagnostics")]
GetCommEventLog { unit: UnitIdOrSlaveAddr },
#[cfg(feature = "diagnostics")]
ReportServerId { unit: UnitIdOrSlaveAddr },
}
impl ClientRequest {
#[allow(dead_code)]
pub(crate) fn unit(&self) -> UnitIdOrSlaveAddr {
match self {
#[cfg(feature = "coils")]
Self::ReadMultipleCoils { unit, .. }
| Self::WriteSingleCoil { unit, .. }
| Self::WriteMultipleCoils { unit, .. } => *unit,
#[cfg(feature = "holding-registers")]
Self::ReadHoldingRegisters { unit, .. }
| Self::WriteSingleRegister { unit, .. }
| Self::WriteMultipleRegisters { unit, .. }
| Self::ReadWriteMultipleRegisters { unit, .. }
| Self::MaskWriteRegister { unit, .. } => *unit,
#[cfg(feature = "input-registers")]
Self::ReadInputRegisters { unit, .. } => *unit,
#[cfg(feature = "discrete-inputs")]
Self::ReadDiscreteInputs { unit, .. } => *unit,
#[cfg(feature = "fifo")]
Self::ReadFifoQueue { unit, .. } => *unit,
#[cfg(feature = "file-record")]
Self::ReadFileRecord { unit, .. } | Self::WriteFileRecord { unit, .. } => *unit,
#[cfg(feature = "diagnostics")]
Self::ReadDeviceIdentification { unit, .. }
| Self::EncapsulatedInterfaceTransport { unit, .. }
| Self::ReadExceptionStatus { unit, .. }
| Self::Diagnostics { unit, .. }
| Self::GetCommEventCounter { unit, .. }
| Self::GetCommEventLog { unit, .. }
| Self::ReportServerId { unit, .. } => *unit,
#[allow(unreachable_patterns)]
_ => unreachable!(),
}
}
}
#[allow(clippy::large_enum_variant)]
pub(crate) enum TaskCommand {
Connect {
resp_tx: oneshot::Sender<Result<(), MbusError>>,
},
Request {
params: ClientRequest,
resp_tx: ResponseSender,
},
Disconnect,
}