1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
//! [embedded_graphics] targets made available via CoAP
//!
//! TBD:
//!
//! * There is nothing RIOT specific about this; maybe there should be embedded-coap-demos?
//! * Anything but primitive ASCII uploads

use coap_message::{MinimalWritableMessage, MutableWritableMessage, ReadableMessage, Code};
use coap_message_utils::Error;

use embedded_graphics::pixelcolor::BinaryColor;
use embedded_graphics::prelude::*;

struct TargetWrapper<T: DrawTarget<BinaryColor>> {
    target: T,
    // if we could make this generic over color types (currenlty can't b/c how do we get from input
    // to concrete values otherwise?), this'd need
    // _phantom: core::marker::PhantomData<C>,
}

impl<T: DrawTarget<BinaryColor>> coap_handler::Handler for TargetWrapper<T> {
    type RequestData = ();

    type ExtractRequestError = Error;
    type BuildResponseError<M: MinimalWritableMessage> = M::UnionError;

    fn extract_request_data<M: ReadableMessage>(
        &mut self,
        request: &M,
    ) -> Result<Self::RequestData, Self::ExtractRequestError> {
        // FIXME check code; error handling

        let p = request.payload();
        if p.len() == 25 {
            for (line, linedata) in p.chunks_exact(5).enumerate() {
                for (row, c) in linedata.iter().enumerate() {
                    Pixel(
                        Point::new(row as _, line as _),
                        match c {
                            0x20 => BinaryColor::Off,
                            _ => BinaryColor::On,
                        },
                    )
                    .draw(&mut self.target)
                    // FIXME do we get anythign better?
                    .map_err(|_| Error::internal_server_error())?;
                }
            }
            Ok(())
        } else {
            // FIXME: Express "Not exactly 25 characters found" using problem details or diagnostic
            // payload
            Err(Error::internal_server_error())
        }
    }
    fn estimate_length(&mut self, _request: &Self::RequestData) -> usize {
        100 // worst case
    }
    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<T: DrawTarget<BinaryColor>>(target: T) -> impl coap_handler::Handler {
    TargetWrapper { target }
}