1- from enum import Enum
21import json
3- from ovos_utils .json_helper import merge_dict
2+ from enum import Enum
3+
44from ovos_bus_client import Message
5+ from ovos_utils .json_helper import merge_dict
6+ from typing import Union , List , Optional
57
68
79class HiveMessageType (str , Enum ):
810 HANDSHAKE = "shake" # negotiate initial connection
911 BUS = "bus" # request meant for internal mycroft-bus in master
1012 SHARED_BUS = "shared_bus" # passive sharing of message
11- # from mycroft-bus in slave
13+ # from mycroft-bus in slave
14+
15+ INTERCOM = "intercom" # from satellite to satellite
16+
1217 BROADCAST = "broadcast" # forward message to all slaves
1318 PROPAGATE = "propagate" # forward message to all slaves and masters
1419 ESCALATE = "escalate" # forward message up the authority chain to all
15- # masters
20+ # masters
1621 HELLO = "hello" # like escalate, used to announce the device
1722 QUERY = "query" # like escalate, but stops once one of the nodes can
18- # send a response
23+ # send a response
1924 CASCADE = "cascade" # like propagate, but expects a response back from
20- # all nodes in the hive (responses optional)
25+ # all nodes in the hive (responses optional)
2126 PING = "ping" # like cascade, but used to map the network
2227 RENDEZVOUS = "rendezvous" # reserved for rendezvous-nodes
2328 THIRDPRTY = "3rdparty" # user land message, do whatever you want
2429 BINARY = "bin" # binary data container, payload for something else
2530
2631
2732class HiveMessage :
28- def __init__ (self , msg_type , payload = None , node = None , source_peer = None ,
29- route = None , target_peers = None , meta = None , target_site_id = None ):
33+ def __init__ (self , msg_type : Union [HiveMessageType , str ],
34+ payload : Optional [Union [Message , 'HiveMessage' , str , dict ]] = None ,
35+ node : Optional [str ]= None ,
36+ source_peer : Optional [str ]= None ,
37+ route : Optional [List [str ]]= None ,
38+ target_peers : Optional [List [str ]]= None ,
39+ target_site_id : Optional [str ] = None ,
40+ target_pubkey : Optional [str ] = None ):
3041 # except for the hivemind node classes receiving the message and
3142 # creating the object nothing should be able to change these values
3243 # node classes might change them a runtime by the private attribute
3344 # but end-users should consider them read_only
45+
46+
3447 if msg_type not in [m .value for m in HiveMessageType ]:
3548 raise ValueError ("Unknown HiveMessage.msg_type" )
36-
3749 self ._msg_type = msg_type
50+
3851 # the payload is more or less a free for all
3952 # the msg_type determines what happens to the message, but the
4053 # payload can simply be ignored by the receiving module
41-
42- # some msg_types might return HiveMessage, others (mycroft) Message
43- # we should support the dict/json format, json is used at the
44- # transport layer before converting into any of these formats
54+ # we store things in dict/json format, json is always used at the
55+ # transport layer before converting into any of the other formats
4556 if isinstance (payload , Message ):
4657 payload = {"type" : payload .msg_type ,
4758 "data" : payload .data ,
@@ -51,40 +62,44 @@ def __init__(self, msg_type, payload=None, node=None, source_peer=None,
5162 self ._payload = payload or {}
5263
5364 self ._site_id = target_site_id
65+ self ._target_pubkey = target_pubkey
5466 self ._node = node # node semi-unique identifier
5567 self ._source_peer = source_peer # peer_id
5668 self ._route = route or [] # where did this message come from
5769 self ._targets = target_peers or [] # where will it be sent
58- self ._meta = meta or {}
5970
6071 @property
61- def target_site_id (self ):
72+ def target_site_id (self ) -> str :
6273 return self ._site_id
6374
6475 @property
65- def msg_type (self ):
76+ def target_public_key (self ) -> str :
77+ return self ._target_pubkey
78+
79+ @property
80+ def msg_type (self ) -> str :
6681 return self ._msg_type
6782
6883 @property
69- def node_id (self ):
84+ def node_id (self ) -> str :
7085 return self ._node
7186
7287 @property
73- def source_peer (self ):
88+ def source_peer (self ) -> str :
7489 return self ._source_peer
7590
7691 @property
77- def target_peers (self ):
92+ def target_peers (self ) -> List [ str ] :
7893 if self .source_peer :
7994 return self ._targets or [self ._source_peer ]
8095 return self ._targets
8196
8297 @property
83- def route (self ):
98+ def route (self ) -> List [ str ] :
8499 return [r for r in self ._route if r .get ("targets" ) and r .get ("source" )]
85100
86101 @property
87- def payload (self ):
102+ def payload (self ) -> Union [ 'HiveMessage' , Message , dict ] :
88103 if self .msg_type in [HiveMessageType .BUS , HiveMessageType .SHARED_BUS ]:
89104 return Message (self ._payload ["type" ],
90105 data = self ._payload .get ("data" ),
@@ -97,37 +112,42 @@ def payload(self):
97112 return self ._payload
98113
99114 @property
100- def as_dict (self ):
115+ def as_dict (self ) -> dict :
101116 pload = self ._payload
102117 if isinstance (pload , HiveMessage ):
103- pload = pload .as_json
118+ pload = pload .as_dict
104119 elif isinstance (pload , Message ):
105120 pload = pload .serialize ()
106121 if isinstance (pload , str ):
107122 pload = json .loads (pload )
123+
124+ assert isinstance (pload , dict )
125+
108126 return {"msg_type" : self .msg_type ,
109127 "payload" : pload ,
110128 "route" : self .route ,
111129 "node" : self .node_id ,
112130 "target_site_id" : self .target_site_id ,
131+ "target_pubkey" : self .target_public_key ,
113132 "source_peer" : self .source_peer }
114133
115134 @property
116- def as_json (self ):
135+ def as_json (self ) -> str :
117136 return json .dumps (self .as_dict )
118137
119- def serialize (self ):
138+ def serialize (self ) -> str :
120139 return self .as_json
121140
122141 @staticmethod
123- def deserialize (payload ) :
142+ def deserialize (payload : Union [ str , dict ]) -> 'HiveMessage' :
124143 if isinstance (payload , str ):
125144 payload = json .loads (payload )
126145
127146 if "msg_type" in payload :
128147 try :
129148 return HiveMessage (payload ["msg_type" ], payload ["payload" ],
130- target_site_id = payload .get ("target_site_id" ))
149+ target_site_id = payload .get ("target_site_id" ),
150+ target_pubkey = payload .get ("target_pubkey" ))
131151 except :
132152 pass # not a hivemind message
133153
@@ -136,12 +156,14 @@ def deserialize(payload):
136156 # NOTE: technically could also be SHARED_BUS or THIRDPRTY
137157 return HiveMessage (HiveMessageType .BUS ,
138158 Message .deserialize (payload ),
139- target_site_id = payload .get ("target_site_id" ))
159+ target_site_id = payload .get ("target_site_id" ),
160+ target_pubkey = payload .get ("target_pubkey" ))
140161 except :
141162 pass # not a mycroft message
142163
143164 return HiveMessage (HiveMessageType .THIRDPRTY , payload ,
144- target_site_id = payload .get ("target_site_id" ))
165+ target_site_id = payload .get ("target_site_id" ),
166+ target_pubkey = payload .get ("target_pubkey" ))
145167
146168 def __getitem__ (self , item ):
147169 return self ._payload .get (item )
0 commit comments