1+ from pymavlink import mavutil
2+
3+ class Callback ():
4+ def __init__ (
5+ self ,
6+ name : str ,
7+ trigger_message_type : str ,
8+ trigger_condition : function = (lambda curr_msg , prev_msg : True ),
9+ payload : function = (lambda msg , conn , state : print (msg )),
10+ only_once : bool = True
11+ ):
12+ """
13+ A callback instance. Callbacks are composed of two components - the trigger, which controls
14+ when and how the callback fires, and the payload, which contains the code to run.
15+
16+ Parameters:
17+ `name`: A name to help disambiguate the callback.
18+ `trigger_message_type`: mavlink message type that triggers the callback,
19+ e.g. `'GLOBAL_POSITION_INT'`
20+ `trigger_condition`: a function that should take in mavlink messages of the designated
21+ trigger type and return a boolean that indicates whether or not the callback should
22+ fire on that message.
23+ Also has access to the previous message of that time seen by the callback system. An
24+ example of how this can be used is triggering specifically on the transition between
25+ waypoints 2 -> 3.
26+ Functions must be able to handle cases where prev_msg is `None`.
27+ If unspecified, a function that will always return `True` will be used - i.e., the
28+ callback will fire on every message of the correct type.
29+ `payload`: a function that contains the desired logic to run when the callback fires.
30+ Has access to the message it was triggered on, the `mavlink_connection` object, and
31+ a state dictionary owned by the MPS server instance itself (for passing information
32+ back to the wider server context.)
33+ If unspecified, a default function will be used that simply prints the message.
34+ `only_once`: indicates that the callback should only execute once, i.e. it will be removed
35+ after being triggered for the first and only time.
36+ """
37+
38+ self .name = name
39+ self .trigger_message_type = trigger_message_type
40+ self .trigger_condition = trigger_condition
41+ self .payload = payload
42+ self .only_once = only_once
43+
44+ class CallbackSystem ():
45+ def __init__ (self , mav_connection : mavutil .mavfile , state : dict ):
46+ self .conn = mav_connection
47+ self .state = state
48+
49+ self .callbacks : dict [str , list [Callback ]] = {}
50+ self .prev_messages : dict [str , object ] = {}
51+
52+ def update_and_check (self , latest_messages : dict ):
53+ # traverse through all callbacks and check each of their triggers
54+ for callback_type , callback_list in self .callbacks .items ():
55+ prev_msg = self .prev_messages .get (callback_type , None )
56+ curr_msg = latest_messages .get (callback_type , None )
57+
58+ if curr_msg == None :
59+ # no point testing
60+ continue
61+
62+ for callback in callback_list :
63+ if callback .trigger_condition (curr_msg , prev_msg ):
64+
65+ if callback .only_once :
66+ # remove callback before firing it
67+ self .callbacks [callback_type ].remove (callback )
68+
69+ # fire callback
70+ callback .payload (curr_msg , self .conn , self .state )
71+
72+ print (f"DEBUG: Fired Callback { callback .name } " )
73+
74+ # update prev_messages
75+ self .prev_messages .update (latest_messages )
76+
77+ def register_callback (self , callback : Callback ):
78+ self .callbacks [callback .trigger_message_type ].append (callback )
79+
80+ # def unregister_callback(self, name: str, trigger_message_type: int):
81+ # pass
0 commit comments