1use crate::can::CanInterface;
2use crate::can::Frame;
3use crate::can::FrameData;
4use crate::error::mkerr;
5use crate::pgn;
6type Error = crate::error::Error;
7const FILE_CODE: u8 = 0xFC;
8
9const BROADCAST_ADDRESS: u8 = 0xFF; const NAME_TIMEOUT_RESOLUTION: u8 = 10;
11const NAME_TIMEOUT_RECALL: u8 = 1;
12const NAME_CLAIM_TIMEOUT: u8 = 250 / NAME_TIMEOUT_RESOLUTION;
13const CLAIM_PRIORITY: u8 = 5;
14use crate::name::name_table::NULL_ADDRESS;
15
16use crate::name::name_table::NameEntry;
17use crate::name::name_table::NameState;
18use crate::name::name_table::NameTable;
19
20#[derive(Debug, Copy, Clone, PartialEq, defmt::Format)]
21#[repr(u8)]
22enum NameManagerState {
23 Disabled,
24 Init,
25 WaitOtherNames,
26 Active,
28}
29
30impl NameManagerState {
31 fn running(&self) -> bool {
32 match self {
33 NameManagerState::Disabled => false,
34 NameManagerState::Init => false,
35 NameManagerState::WaitOtherNames => false,
36 NameManagerState::Active => true,
38 }
39 }
40}
41
42pub struct NameManager {
43 table: NameTable,
44 next_timeout: Option<u8>,
45 time_delta_remander: usize,
46 manager_state: NameManagerState,
47 manager_state_timeout: u8,
48}
49
50impl NameManager {
51 pub fn new() -> NameManager {
52 NameManager {
53 table: NameTable::new(),
54 next_timeout: Some(0),
55 time_delta_remander: 0,
56 manager_state: NameManagerState::Init,
57 manager_state_timeout: 0,
58 }
59 }
60
61 pub fn disable(&mut self) {
62 self.to_state(NameManagerState::Disabled);
63 self.next_timeout = None;
64 }
65
66 pub fn enable(&mut self) {
67 if self.manager_state != NameManagerState::Disabled {
68 return;
69 }
70 self.to_state(NameManagerState::Init);
71 }
72
73 fn to_state(&mut self, state: NameManagerState) {
74 defmt::println!("NameManager state={:?} -> {:?}", self.manager_state, state);
75 match state {
76 NameManagerState::Disabled => {}
77 NameManagerState::Init => {
78 self.table.reset_state(line!());
79 self.next_timeout = Some(250 / NAME_TIMEOUT_RESOLUTION);
80 }
81 NameManagerState::WaitOtherNames => {}
82 NameManagerState::Active => {}
83 }
84 self.manager_state = state;
85 }
86
87 fn expect_enabled(&self) -> Result<(), Error> {
88 if self.manager_state == NameManagerState::Disabled {
89 return Err(mkerr(
90 FILE_CODE,
91 crate::error::ErrorCode::NotEnabled,
92 line!(),
93 ));
94 }
95 Ok(())
96 }
97
98 pub fn find_spare_address(&self, pref: u8) -> Option<u8> {
99 let mut cur = pref;
100 loop {
101 match self.table.index_at_address(cur) {
102 None => {
103 return Some(cur);
104 }
105 Some(_) => {
106 if cur >= NULL_ADDRESS - 1 {
107 cur = 0
108 } else {
109 cur += 1
110 }
111 if cur == pref {
112 return None;
113 }
114 }
115 }
116 }
117 }
118 pub fn get_next_timeout_ms(&self) -> Option<u32> {
119 match self.next_timeout {
120 Some(x) => Some(x as u32 * NAME_TIMEOUT_RESOLUTION as u32),
121 None => None,
122 }
123 }
124
125 fn send_claim(
126 &mut self,
127 iface: &mut dyn CanInterface,
128 index: usize,
129 info: &NameEntry,
130 address: u8,
131 destination: u8,
132 ) -> Result<(), Error> {
133 let id = crate::can::new_id_unchecked(
134 pgn::ADDRESS_CLAIMED,
135 address,
136 destination,
137 CLAIM_PRIORITY,
138 );
139 if iface
148 .transmit(Frame::from_iter(
149 id.as_raw(),
150 self.table.name(index).bytes_iter(),
151 ))
152 .is_ok()
153 {
154 if info.address() == NULL_ADDRESS {
155 self.table.set_state(index, NameState::DEAD, line!())?;
157 self.clear_timeout(index)?;
158
159 } else if info.state() != NameState::ACTTIVE {
161 self.table.set_state(index, NameState::CLAIMING, line!())?;
163 self.set_name_timeout(index, NAME_CLAIM_TIMEOUT)?;
164 }
165 } else {
166 self.set_name_timeout(index, NAME_TIMEOUT_RECALL)?;
168 }
169 Ok(())
170 }
171 fn kill_claim(&mut self, iface: &mut dyn CanInterface, index: usize) -> Result<usize, Error> {
172 self.table.set_address(index, NULL_ADDRESS)?;
173
174 let info = self.table.info(index)?;
175 if info.local() {
176 self.send_claim(iface, index, &info, NULL_ADDRESS, BROADCAST_ADDRESS)?;
177 } else {
178 self.table.set_state(index, NameState::DEAD, line!())?;
179 self.table.clear_timeout(index)?;
180 }
181
182 Ok(index)
183 }
184
185 pub fn request_names(&mut self, iface: &mut dyn CanInterface, src: u8) -> Result<(), Error> {
186 self.expect_enabled()?;
187 let id = crate::can::new_id(pgn::REQUEST, src, 0xff, 5).unwrap();
188 #[cfg(feature = "defmt")]
189 defmt::println!("Request names");
190 match iface.transmit(crate::can::Frame::from_slice(
191 id.as_raw(),
192 &pgn::encode(pgn::ADDRESS_CLAIMED), )) {
194 Ok(_) => Ok(()),
195 Err(_) => Err(mkerr(FILE_CODE, crate::error::ErrorCode::NoSpace, line!())),
196 }
197 }
198
199 fn set_name_timeout(self: &mut Self, index: usize, timeout: u8) -> Result<usize, Error> {
200 self.next_timeout = match self.next_timeout {
201 None => Some(timeout),
202 Some(x) => Some(core::cmp::min(x, timeout)),
203 };
204 self.table.set_timeout(index, timeout)
205 }
206 fn set_manager_timeout(self: &mut Self, timeout: u8) {
207 self.next_timeout = match self.next_timeout {
208 None => Some(timeout),
209 Some(x) => Some(core::cmp::min(x, timeout)),
210 };
211 self.manager_state_timeout = timeout;
212 }
213 fn clear_timeout(self: &mut Self, index: usize) -> Result<usize, Error> {
214 self.table.clear_timeout(index)
215 }
216 fn accept_claim(
217 &mut self,
218 iface: &mut dyn CanInterface,
219 index: usize,
220 address: u8,
221 ) -> Result<usize, Error> {
222 self.table.set_address(index, address)?;
223 let info = self.table.info(index)?;
226 if info.local() {
227 match self.manager_state {
228 NameManagerState::Disabled => {
229 return Err(mkerr(
230 FILE_CODE,
231 crate::error::ErrorCode::NotEnabled,
232 line!(),
233 ));
234 }
235 NameManagerState::Init => {
236 self.table.set_state(index, NameState::INIT, line!())?;
237 }
239 NameManagerState::WaitOtherNames => {
240 self.table.set_state(index, NameState::INIT, line!())?;
241 }
243 NameManagerState::Active => {
244 self.send_claim(iface, index, &info, address, BROADCAST_ADDRESS)?;
245 }
246 }
247 } else {
248 self.table.set_state(index, NameState::CLAIMING, line!())?;
249 self.set_name_timeout(index, NAME_CLAIM_TIMEOUT)?;
250 }
251
252 Ok(index)
253 }
254
255 fn send_local_claims(
257 &mut self,
258 iface: &mut dyn CanInterface,
259 for_addr: u8,
260 ) -> Result<bool, Error> {
261 if for_addr == 255 {
262 for index in 0..self.table.size() {
263 let info = self.table.info(index).unwrap();
264 if !info.local() {
265 continue;
266 }
267 defmt::println!(
268 "Send local claim {} {} {:?}\n",
269 line!(),
270 index,
271 info.address()
272 );
273 self.send_claim(iface, index, &info, info.address(), BROADCAST_ADDRESS)?;
274 }
275 } else {
276 match self.table.index_at_address(for_addr) {
277 Some(index) => {
278 let info = self.table.info(index)?;
279 if info.local() {
280 self.send_claim(iface, index, &info, info.address(), BROADCAST_ADDRESS)?;
281 }
282 }
283 None => {}
284 }
285 }
286 return Ok(true);
287 }
288
289 pub fn advance_time(
290 &mut self,
291 iface: &mut dyn CanInterface,
292 mut time_delta_ms: usize,
293 ) -> Result<bool, Error> {
294 time_delta_ms += self.time_delta_remander;
295 if time_delta_ms > 255 {
296 time_delta_ms = 250;
297 }
298
299 let time_delta = (time_delta_ms / (NAME_TIMEOUT_RESOLUTION as usize)) as u8;
300 self.time_delta_remander = time_delta_ms % (NAME_TIMEOUT_RESOLUTION as usize);
301 let cur_timeout = self.next_timeout;
302 self.next_timeout = None;
303
304 if self.manager_state == NameManagerState::Disabled {
305 return Ok(false);
306 }
307
308 match self.manager_state {
309 NameManagerState::Disabled => {
310 return Ok(false);
311 }
312 NameManagerState::Init => {
313 self.to_state(NameManagerState::WaitOtherNames);
314 self.set_manager_timeout(NAME_CLAIM_TIMEOUT); self.request_names(iface, NULL_ADDRESS)?;
316 }
317 NameManagerState::WaitOtherNames => {
318 if self.manager_state_timeout <= time_delta {
319 self.manager_state_timeout = 0;
320 self.to_state(NameManagerState::Active);
321 self.send_local_claims(iface, BROADCAST_ADDRESS)?;
322 } else {
323 self.set_manager_timeout(self.manager_state_timeout - time_delta);
324 }
325 }
326 NameManagerState::Active => {
328 if cur_timeout.is_none() {
330 return Ok(true);
331 }
332 }
333 }
334
335 for index in 0..self.table.size() {
336 let info = self.table.info(index).unwrap();
337 if 0 == info.timeout() {
338 continue;
339 } if info.timeout() > time_delta {
341 self.set_name_timeout(index, info.timeout() - time_delta)?;
343 continue;
344 }
345
346 self.clear_timeout(index)?;
348
349 if info.state() == NameState::CLAIMING {
350 self.table.set_state(index, NameState::ACTTIVE, line!())?;
352 } else if info.local() {
354 if !self.manager_state.running() {
356 self.set_name_timeout(index, 10)?;
357 continue;
359 }
360 self.send_claim(iface, index, &info, info.address(), BROADCAST_ADDRESS)?;
361 }
362 }
363 return Ok(true);
364 }
365
366 fn process_claim(
367 &mut self,
368 iface: &mut dyn CanInterface,
369 source: u8,
370 name: &crate::name::Name,
371 local: bool,
372 ) -> Result<bool, Error> {
373 let index = self.table.entry(name)?;
374 if local {
375 self.table.set_local(index, local)?;
376 }
377 let info = self.table.info(index)?; if source == NULL_ADDRESS || source == BROADCAST_ADDRESS {
381 defmt::println!("Claim dead {} {}\n", line!(), source);
382 self.kill_claim(iface, index)?;
383 return Ok(true);
384 }
385
386 if info.state() == NameState::DEAD
387 || info.state() == NameState::INIT
388 || info.address() != source
389 {
390 let current_clam = self.table.index_at_address(source);
391 if current_clam.is_some() && current_clam.unwrap() != index {
392 let current_claim_index = current_clam.unwrap();
394 let current_claim_name = self.table.get_name(current_claim_index);
395 let current_claim_info = self.table.info(current_claim_index)?; let local_not_started =
397 current_claim_info.state() == NameState::INIT && current_claim_info.local();
398 if local_not_started
399 || (current_claim_name.is_ok() && current_claim_name.unwrap() < *name)
400 {
401 if current_claim_info.local() {
405 match self.find_spare_address(128) {
407 Some(new_add) => {
408 defmt::println!(
409 "Claim local move {} {}->{}\n",
410 line!(),
411 source,
412 new_add
413 );
414 self.accept_claim(iface, current_claim_index, new_add)?;
415 }
416 None => {
417 defmt::println!("Claim dead {} {}\n", line!(), source);
419 self.kill_claim(iface, current_claim_index)?;
420 }
421 }
422 } else {
423 defmt::println!("Claim dead {} {}\n", line!(), source);
424 self.kill_claim(iface, current_claim_index)?;
425 }
426 self.accept_claim(iface, index, source)?;
427 } else {
428 if local {
431 match self.find_spare_address(128) {
433 Some(new_add) => {
434 defmt::println!(
435 "Claim local move {} {}->{}\n",
436 line!(),
437 source,
438 new_add
439 );
440 self.accept_claim(iface, index, new_add)?;
441 }
442 None => {
443 defmt::println!("Claim dead {} {}\n", line!(), source);
445 self.kill_claim(iface, index)?;
446 }
447 }
448 } else {
449 defmt::println!("Claim dead {} {}->{}\n", line!(), info.address(), source);
450 self.kill_claim(iface, index)?;
451 }
452 }
453 } else {
454 self.accept_claim(iface, index, source)?;
456 }
457 }
458
459 Ok(true)
462 }
463
464 pub fn resolve(&self, name: &crate::name::Name) -> Result<crate::can::Address, Error> {
465 self.expect_enabled()?;
466 let info = self.table.info_from_name(name)?;
467 if info.state() != NameState::ACTTIVE {
468 return Err(mkerr(
469 FILE_CODE,
470 crate::error::ErrorCode::NotResolved,
471 line!(),
472 ));
473 }
474
475 Ok(info.address())
476 }
477
478 pub fn resolve_local(&self, name: &crate::name::Name) -> Result<crate::can::Address, Error> {
479 self.expect_enabled()?;
480 let info = self.table.info_from_name(name)?;
481 if !info.local() {
482 return Err(mkerr(FILE_CODE, crate::error::ErrorCode::NotLocal, line!()));
483 }
484 if info.state() != NameState::ACTTIVE {
485 return Err(crate::error::mkerr_u32(
486 FILE_CODE,
487 crate::error::ErrorCode::NotResolved,
488 line!(),
489 info.state() as u32,
490 ));
491 }
492
493 Ok(info.address())
494 }
495
496 pub fn resolve_local_else_null(&self, name: &crate::name::Name) -> u8 {
497 match self.resolve_local(name) {
498 Ok(addr) => addr,
499 Err(_) => 254,
500 }
501 }
502
503 pub fn register_local_name(
504 &mut self,
505 iface: &mut dyn CanInterface,
506 address: u8,
507 name: &crate::name::Name,
508 ) -> Result<bool, Error> {
509 defmt::println!("Register local name {} {}\n", line!(), address);
510 self.process_claim(iface, address, name, true)
511 }
512
513 pub fn on_can_frame(
514 &mut self,
515 iface: &mut dyn CanInterface,
516 id: crate::can::ApiId,
517 data: &FrameData,
518 ) -> Result<bool, Error> {
519 if self.manager_state == NameManagerState::Disabled {
520 return Ok(false);
521 }
522 #[cfg(feature = "defmt")]
524 defmt::println!(
525 "Name Got Frame pgn={}/{} len={}\n",
526 id.pgn(),
527 pgn::REQUEST,
528 data.len()
529 );
530 use crate::can::Id;
531 return match id.pgn() {
532 pgn::ADDRESS_CLAIMED => match crate::name::Name::from_bytes(&data) {
533 Ok(name) => {
534 defmt::println!("Remote claim {} {}\n", line!(), id.source());
535 self.process_claim(iface, id.source(), &name, false)
536 }
537 Err(e) => Err(e),
538 },
539 pgn::REQUEST if data.len() >= 3 && data[0..3] == pgn::encode(pgn::ADDRESS_CLAIMED) => {
540 #[cfg(feature = "defmt")]
541 defmt::println!("PR @{}", line!());
542
543 self.send_local_claims(iface, id.destination())?;
544 Ok(true)
545 }
546 _ => Ok(false),
547 };
548 }
549}
550
551#[cfg(test)]
574pub mod name_manager_tests {
575 use crate::can::CanInterface;
576 use crate::can::DummyCanInerface;
577 use crate::can::FrameData;
578 use crate::name::name_manager::NameManager;
579 use crate::name::Name;
580
581 #[test]
582 fn name_manager() {
583 let mut man = NameManager::new();
584 let mut can = DummyCanInerface::new();
585
586 assert_eq!(man.get_next_timeout_ms(), Some(0));
587 assert_eq!(0, can.tx_queue.len());
588 assert_eq!(Some(true), man.advance_time(&mut can, 0).ok());
589
590 assert_eq!(1, can.tx_queue.len());
592 let frame = can.tx_queue.dequeue().unwrap();
593 assert_eq!(frame.id().as_raw(), 0x14EAFFFE);
594 assert_eq!(frame.data().as_slice(), &[0u8, 0xEEu8, 0u8]);
595 assert_eq!(0, can.tx_queue.len());
596
597 assert_eq!(man.get_next_timeout_ms(), Some(250));
599 assert_eq!(Some(true), man.advance_time(&mut can, 250).ok());
600 assert_eq!(0, can.tx_queue.len());
601
602 print!(
603 "Name SC {:x}\n",
604 Name::create(true, 0, 0, 0, 0, 0, 0, 0, 0).raw()
605 );
606 let local_name = Name(0);
607
608 print!("Register local name on 130\n");
609 assert_eq!(
610 Some(true),
611 man.register_local_name(&mut can, 0x82, &local_name).ok()
612 );
613 assert_eq!(0xFE, man.resolve_local_else_null(&local_name)); assert_eq!(1, can.tx_queue.len());
617 let frame = can.tx_queue.dequeue().unwrap();
618 print!(
619 "FRAME: {:x} {:?}\n",
620 frame.id().as_raw(),
621 frame.data().as_slice()
622 );
623 assert_eq!(frame.id().as_raw(), 0x14EEFF82);
624 assert_eq!(frame.data().as_slice(), &[0, 0, 0, 0, 0, 0, 0, 0,]);
625 assert_eq!(0, can.tx_queue.len());
626
627 print!("Advance time by 200\n");
628 assert_eq!(Some(true), man.advance_time(&mut can, 200).ok());
629 assert_eq!(0xFE, man.resolve_local_else_null(&local_name)); print!("Advance time by 49\n");
631 assert_eq!(Some(true), man.advance_time(&mut can, 49).ok());
632 assert_eq!(0xFE, man.resolve_local_else_null(&local_name)); print!("Advance time by 1\n");
634 assert_eq!(Some(true), man.advance_time(&mut can, 1).ok());
635 assert_eq!(0x82, man.resolve_local_else_null(&local_name)); assert_eq!(
638 Some(true),
639 man.on_can_frame(
640 &mut can,
641 crate::can::new_id(crate::pgn::ADDRESS_CLAIMED, 28, 255, 3).unwrap(),
642 &FrameData::from_iter(Name::create(true, 0, 0, 0, 0, 0, 0, 0, 123).bytes_iter())
643 )
644 .ok()
645 );
646 print!("Advance time by 249\n");
647 assert_eq!(Some(true), man.advance_time(&mut can, 249).ok());
648 print!("Advance time by 1\n");
649 assert_eq!(Some(true), man.advance_time(&mut can, 1).ok());
650 assert_eq!(0, can.tx_queue.len());
651 }
652
653 #[test]
654 fn conflict() {
655 let our_name = Name::create(true, 0, 0, 0, 0, 0, 0, 0, 123);
656 let them_name = Name::create(true, 0, 0, 0, 0, 0, 0, 0, 124);
657 let mut man = NameManager::new();
658 let mut can = DummyCanInerface::new();
659 print!("US Name SC {:x}\n", our_name.raw());
660 print!("Then Name SC {:x}\n", them_name.raw());
661
662 assert_eq!(man.get_next_timeout_ms(), Some(0));
663 assert_eq!(0, can.tx_queue.len());
664 assert_eq!(Some(true), man.advance_time(&mut can, 0).ok());
665
666 assert_eq!(1, can.tx_queue.len());
668 let frame = can.tx_queue.dequeue().unwrap();
669 assert_eq!(frame.id().as_raw(), 0x14EAFFFE);
670 assert_eq!(frame.data().as_slice(), &[0u8, 0xEEu8, 0u8]);
671 assert_eq!(0, can.tx_queue.len());
672
673 assert_eq!(man.get_next_timeout_ms(), Some(250));
675 assert_eq!(Some(true), man.advance_time(&mut can, 250).ok());
676 assert_eq!(0, can.tx_queue.len());
677
678 assert_eq!(
679 Some(true),
680 man.register_local_name(&mut can, 130, &our_name).ok()
681 );
682
683 assert_eq!(1, can.tx_queue.len());
685 let frame = can.tx_queue.dequeue().unwrap();
686 print!(
687 "FRAME: {:x} {:?}\n",
688 frame.id().as_raw(),
689 frame.data().as_slice()
690 );
691 assert_eq!(frame.id().as_raw(), 0x14EEFF82);
692 assert_eq!(
693 frame.data().as_slice(),
694 &our_name.bytes_iter().collect::<Vec<u8>>()
695 );
696 assert_eq!(0, can.tx_queue.len());
697
698 print!(
699 "XXXXX Advance time by 200 {:?}\n",
700 man.get_next_timeout_ms()
701 );
702 assert_eq!(Some(true), man.advance_time(&mut can, 200).ok());
703 assert_eq!(0xFE, man.resolve_local_else_null(&our_name)); print!("Advance time by 49\n");
705 assert_eq!(Some(true), man.advance_time(&mut can, 49).ok());
706 assert_eq!(0xFE, man.resolve_local_else_null(&our_name)); print!("Advance time by 1\n");
708 assert_eq!(Some(true), man.advance_time(&mut can, 1).ok());
709 assert_eq!(0x82, man.resolve_local_else_null(&our_name)); assert_eq!(
712 Some(true),
713 man.on_can_frame(
714 &mut can,
715 crate::can::new_id(crate::pgn::ADDRESS_CLAIMED, 130, 255, 3).unwrap(),
716 &FrameData::from_iter(them_name.bytes_iter())
717 )
718 .ok()
719 );
720 print!("Advance time by 249\n");
721 assert_eq!(Some(true), man.advance_time(&mut can, 249).ok());
722 print!("Advance time by 1\n");
723 assert_eq!(Some(true), man.advance_time(&mut can, 1).ok());
724 assert_eq!(0x82, man.resolve_local_else_null(&our_name)); assert_eq!(0, can.tx_queue.len());
726 }
727
728 #[test]
729 fn name_manager_junk() {
730 use crate::can::Id;
731 let mut _man = NameManager::new();
732 let mut _can_dummy = DummyCanInerface::new();
733 let _can: &mut dyn CanInterface = &mut _can_dummy;
734 assert_eq!(
735 crate::pgn::ADDRESS_CLAIMED,
736 crate::can::new_id(crate::pgn::ADDRESS_CLAIMED, 1, 2, 3)
737 .unwrap()
738 .pgn()
739 );
740 }
766}