use std::io::stdin;
use tokio::io::AsyncWriteExt;
use tokio::task::spawn_blocking;
use att::packet as pkt;
use att::server::*;
use att::Uuid;
struct H;
impl Handler for H {
fn handle_find_information_request(
&mut self,
item: &pkt::FindInformationRequest,
) -> Result<pkt::FindInformationResponse, ErrorResponse> {
match (
item.starting_handle().clone().into(),
item.ending_handle().clone().into(),
) {
(0x000F, 0x000F) => {
Ok(vec![
(0x000F.into(), Uuid::new_uuid16(0x2902).into()), ]
.into_iter()
.collect())
}
(0x0026, 0x0027) => {
Ok(vec![
(0x0026.into(), Uuid::new_uuid16(0x2902).into()), ]
.into_iter()
.collect())
}
(0x0027, 0x0027) => {
Ok(vec![
(0x0027.into(), Uuid::new_uuid16(0x2904).into()), ]
.into_iter()
.collect())
}
(x, _) => Err(ErrorResponse::new(
x.clone().into(),
pkt::ErrorCode::AttributeNotFound,
)),
}
}
fn handle_read_by_type_request(
&mut self,
item: &pkt::ReadByTypeRequest,
) -> Result<pkt::ReadByTypeResponse, ErrorResponse> {
match (
item.starting_handle().clone().into(),
item.ending_handle().clone().into(),
item.attribute_type(),
) {
(0x0001, 0x000B, Uuid::Uuid16(uuid)) if u16::from(uuid.clone()) == 0x2803 => {
Ok(vec![
(0x0002.into(), vec![0x08, 0x04, 0x00, 0x00, 0x2A].into()), (0x0003.into(), vec![0x02, 0x05, 0x00, 0x01, 0x2A].into()), ]
.into_iter()
.collect())
}
(0x000C, 0x000F, Uuid::Uuid16(uuid)) if u16::from(uuid.clone()) == 0x2803 => {
Ok(vec![
(0x000D.into(), vec![0x20, 0x0E, 0x00, 0x05, 0x2A].into()), ]
.into_iter()
.collect())
}
(0x0010, 0x0022, Uuid::Uuid16(uuid)) if u16::from(uuid.clone()) == 0x2803 => {
Ok(vec![
(0x0011.into(), vec![0x02, 0x12, 0x00, 0x29, 0x2A].into()), (0x0013.into(), vec![0x02, 0x14, 0x00, 0x24, 0x2A].into()), (0x0015.into(), vec![0x02, 0x16, 0x00, 0x25, 0x2A].into()), ]
.into_iter()
.collect())
}
(0x0023, 0x0027, Uuid::Uuid16(uuid)) if u16::from(uuid.clone()) == 0x2803 => {
Ok(vec![
(0x0024.into(), vec![0x12, 0x25, 0x00, 0x19, 0x2A].into()), ]
.into_iter()
.collect())
}
(x, _, _) => Err(ErrorResponse::new(
x.clone().into(),
pkt::ErrorCode::AttributeNotFound,
)),
}
}
fn handle_read_request(
&mut self,
item: &pkt::ReadRequest,
) -> Result<pkt::ReadResponse, ErrorResponse> {
match item.attribute_handle().clone().into() {
0x0005 => Ok(pkt::ReadResponse::new(vec![0x00].into())),
_ => Ok(pkt::ReadResponse::new(vec![0x00].into())),
}
}
fn handle_read_by_group_type_request(
&mut self,
item: &pkt::ReadByGroupTypeRequest,
) -> Result<pkt::ReadByGroupTypeResponse, ErrorResponse> {
match (
item.starting_handle().clone().into(),
item.ending_handle().clone().into(),
) {
(0x0001, 0xFFFF) => {
Ok(vec![
(0x0001.into(), 0x000B.into(), vec![0x00, 0x18].into()), (0x000C.into(), 0x000F.into(), vec![0x01, 0x18].into()), (0x0010.into(), 0x0022.into(), vec![0x0A, 0x18].into()), ]
.into_iter()
.collect())
}
(0x0023, 0xFFFF) => {
Ok(vec![
(0x0023.into(), 0x0027.into(), vec![0x0F, 0x18].into()), ]
.into_iter()
.collect())
}
(x, _) => Err(ErrorResponse::new(
x.clone().into(),
pkt::ErrorCode::AttributeNotFound,
)),
}
}
fn handle_write_request(
&mut self,
_item: &pkt::WriteRequest,
) -> Result<pkt::WriteResponse, ErrorResponse> {
Ok(pkt::WriteResponse::default())
}
}
#[tokio::main(flavor = "current_thread")]
async fn main() -> anyhow::Result<()> {
pretty_env_logger::init();
let mut server = Server::new()?;
let (connection, addr) = server.accept().await?.unwrap();
println!("accept {:?}", addr);
let mut notification = connection.notification(0x0025.into());
let mut indication = connection.indication(0x000E.into());
let mut task = tokio::spawn(connection.run(H));
let mut n = 0;
loop {
tokio::select! {
result = std::pin::Pin::new(&mut task) => {
result??;
}
maybe_line = spawn_blocking(|| stdin().read_line(&mut String::new())) => {
maybe_line??;
notification.write_all(&[n]).await?;
indication.write_all(&[0x0C, 0x00, 0x0F, 0x00]).await?;
n += 1;
}
}
}
}