use coap_message::{Code, MinimalWritableMessage};
use coap_message_utils::Error;
use coap_numbers::code;
pub struct Log {
data: scroll_ring::Buffer<1024>,
}
impl Log {
pub fn new() -> Self {
Self {
data: Default::default(),
}
}
pub fn init(&'static self) -> Result<(), log::SetLoggerError> {
log::set_logger(self)?;
log::set_max_level(log::LevelFilter::Info);
Ok(())
}
pub fn start_once() -> &'static Self {
use static_cell::StaticCell;
static S: StaticCell<Log> = StaticCell::new();
let s = S.init_with(|| Self::new());
s.init()
.expect("No other log must be set before calling start_once");
s
}
pub fn handler(&self) -> coap_scroll_ring_server::BufferHandler<'_, 1024> {
coap_scroll_ring_server::BufferHandler::new(&self.data)
}
}
impl log::Log for Log {
fn enabled(&self, metadata: &log::Metadata) -> bool {
metadata.level() <= log::Level::Info
}
fn log(&self, record: &log::Record) {
if self.enabled(record.metadata()) {
struct WriteWrapper<'a>(&'a scroll_ring::Buffer<1024>);
impl<'a> core::fmt::Write for WriteWrapper<'a> {
fn write_str(&mut self, s: &str) -> core::fmt::Result {
self.0.write(s.as_bytes());
Ok(())
}
}
use core::fmt::Write;
writeln!(
WriteWrapper(&self.data),
"{} {}",
record.level(),
record.args()
)
.unwrap();
}
}
fn flush(&self) {}
}
pub struct LogMessagePostHandler {
level: log::Level,
}
impl LogMessagePostHandler {
pub fn new_info() -> Self {
Self {
level: log::Level::Info,
}
}
pub fn new_warn() -> Self {
Self {
level: log::Level::Warn,
}
}
}
impl coap_handler::Handler for LogMessagePostHandler {
type ExtractRequestError = Error;
type BuildResponseError<M: MinimalWritableMessage> = M::UnionError;
type RequestData = ();
fn extract_request_data<M: coap_message::ReadableMessage>(
&mut self,
request: &M,
) -> Result<Self::RequestData, Error> {
use coap_message_utils::OptionsExt;
match request.code().into() {
code::POST => (),
_ => Err(Error::method_not_allowed())?,
}
request.options().ignore_elective_others()?;
let payload = core::str::from_utf8(request.payload())
.map_err(|e| Error::bad_request_with_rbep(e.valid_up_to()))?;
use log::log;
log!(self.level, "{}", payload);
Ok(())
}
fn estimate_length(&mut self, _: &Self::RequestData) -> usize {
8
}
fn build_response<M: coap_message::MutableWritableMessage>(
&mut self,
response: &mut M,
_request: (),
) -> Result<(), M::UnionError> {
response.set_code(M::Code::new(code::CHANGED)?);
Ok(())
}
}