use embedded_hal::digital::v2::{InputPin, OutputPin};
use coap_message::{Code, ReadableMessage, MinimalWritableMessage, MutableWritableMessage, OptionNumber};
use crate::common::ErrorDetail;
struct OutputWrapper<P: OutputPin>(P);
struct InputWrapper<P: InputPin>(P);
impl<P: InputPin> coap_handler::Handler for InputWrapper<P> {
type RequestData = ();
type ExtractRequestError = core::convert::Infallible;
type BuildResponseError<M: MinimalWritableMessage> = M::UnionError;
fn extract_request_data<M: ReadableMessage>(&mut self, _request: &M) -> Result<Self::RequestData, Self::ExtractRequestError> {
Ok(())
}
fn estimate_length(&mut self, _request: &Self::RequestData) -> usize {
3
}
fn build_response<M: MutableWritableMessage>(&mut self, response: &mut M, _request: Self::RequestData) -> Result<(), M::UnionError> {
if let Ok(high) = self.0.is_high() {
response.set_code(Code::new(coap_numbers::code::CONTENT)?);
response.add_option_uint(OptionNumber::new(coap_numbers::option::CONTENT_FORMAT)?,
60u8 )?;
response.set_payload(if high { b"\xf5" } else { b"\xf4" })?;
} else {
response.set_code(Code::new(coap_numbers::code::INTERNAL_SERVER_ERROR)?);
response.set_payload(b"GPIO read error")?;
}
Ok(())
}
}
impl<P: OutputPin> coap_handler::Handler for OutputWrapper<P> {
type RequestData = ();
type ExtractRequestError = ErrorDetail;
type BuildResponseError<M: MinimalWritableMessage> = M::UnionError;
fn extract_request_data<M: ReadableMessage>(&mut self, request: &M) -> Result<(), ErrorDetail> {
match request.payload() {
b"\xf5" => self.0.set_high().map_err(|_| ErrorDetail("Failure setting pin")),
b"\xf4" => self.0.set_low().map_err(|_| ErrorDetail("Failure setting pin")),
_ => Err(ErrorDetail("PUT value must be CBOR true or false")),
}
}
fn estimate_length(&mut self, _request: &Self::RequestData) -> usize {
4
}
fn build_response<M: MutableWritableMessage>(&mut self, response: &mut M, _request: Self::RequestData) -> Result<(), M::UnionError> {
response.set_code(Code::new(coap_numbers::code::CHANGED)?);
Ok(())
}
}
pub fn handler_for_input<P: InputPin>(pin: P) -> impl coap_handler::Handler {
InputWrapper(pin)
}
pub fn handler_for_output<P: OutputPin>(pin: P) -> impl coap_handler::Handler {
OutputWrapper(pin)
}