2222//! Link context for scanning and discovering Crazyflies
2323
2424use pyo3:: prelude:: * ;
25- use pyo3:: exceptions:: PyRuntimeError ;
25+ use pyo3:: exceptions:: { PyRuntimeError , PyValueError } ;
2626use pyo3_stub_gen_derive:: * ;
2727use std:: sync:: Arc ;
2828
@@ -65,7 +65,7 @@ impl LinkContext {
6565 // Default to E7E7E7E7E7 if no address provided
6666 let addr = if let Some ( addr_vec) = address {
6767 if addr_vec. len ( ) != 5 {
68- return Err ( PyRuntimeError :: new_err (
68+ return Err ( PyValueError :: new_err (
6969 "Address must be exactly 5 bytes"
7070 ) ) ;
7171 }
@@ -83,4 +83,34 @@ impl LinkContext {
8383 Ok ( uris. into_iter ( ) . map ( |uri| uri. to_string ( ) ) . collect :: < Vec < _ > > ( ) )
8484 } )
8585 }
86+
87+ /// Send a radio broadcast packet (no acknowledgement) on a specific radio and channel
88+ ///
89+ /// This sends a raw packet without expecting an ack, useful for P2P communication.
90+ ///
91+ /// # Arguments
92+ /// * `radio_nth` - Radio dongle index (usually 0)
93+ /// * `channel` - Radio channel number (0-125)
94+ /// * `address` - 5-byte destination address
95+ /// * `data` - Packet payload bytes
96+ #[ gen_stub( override_return_type( type_repr = "collections.abc.Coroutine[typing.Any, typing.Any, None]" ) ) ]
97+ fn send_radio_broadcast < ' py > ( & self , py : Python < ' py > , radio_nth : usize , channel : u8 , address : Vec < u8 > , data : Vec < u8 > ) -> PyResult < Bound < ' py , PyAny > > {
98+ if address. len ( ) != 5 {
99+ return Err ( PyValueError :: new_err ( "Address must be exactly 5 bytes" ) ) ;
100+ }
101+ let mut addr_array = [ 0u8 ; 5 ] ;
102+ addr_array. copy_from_slice ( & address) ;
103+
104+ let ch = crazyradio:: Channel :: from_number ( channel)
105+ . map_err ( |_| PyValueError :: new_err ( format ! ( "Invalid channel {}: must be 0-125" , channel) ) ) ?;
106+
107+ let inner = self . inner . clone ( ) ;
108+ pyo3_async_runtimes:: tokio:: future_into_py ( py, async move {
109+ let mut radio = inner. get_radio ( radio_nth) . await
110+ . map_err ( |e| PyRuntimeError :: new_err ( format ! ( "Failed to get radio: {:?}" , e) ) ) ?;
111+ radio. send_packet_no_ack_async ( ch, addr_array, data) . await
112+ . map_err ( |e| PyRuntimeError :: new_err ( format ! ( "Broadcast failed: {:?}" , e) ) ) ?;
113+ Ok ( ( ) )
114+ } )
115+ }
86116}
0 commit comments