@@ -2,7 +2,7 @@ use crate::json_c8y::C8yAlarm;
22use mqtt_channel:: MqttError ;
33use mqtt_channel:: Topic ;
44use mqtt_channel:: TopicFilter ;
5- use tedge_api:: entity_store:: EntityMetadata ;
5+ use tedge_api:: entity_store:: EntityExternalId ;
66use tedge_api:: entity_store:: EntityType ;
77use tedge_config:: TopicPrefix ;
88
@@ -19,13 +19,14 @@ pub enum C8yTopic {
1919impl C8yTopic {
2020 /// Return the c8y SmartRest response topic for the given entity
2121 pub fn smartrest_response_topic (
22- entity : & EntityMetadata ,
22+ external_id : & EntityExternalId ,
23+ entity_type : & EntityType ,
2324 prefix : & TopicPrefix ,
2425 ) -> Option < Topic > {
25- match entity . r#type {
26+ match entity_type {
2627 EntityType :: MainDevice => Some ( C8yTopic :: upstream_topic ( prefix) ) ,
2728 EntityType :: ChildDevice | EntityType :: Service => {
28- Self :: ChildSmartRestResponse ( entity . external_id . clone ( ) . into ( ) )
29+ Self :: ChildSmartRestResponse ( external_id. clone ( ) . into ( ) )
2930 . to_topic ( prefix)
3031 . ok ( )
3132 }
@@ -77,28 +78,30 @@ impl From<&C8yAlarm> for C8yTopic {
7778 }
7879}
7980
80- /// Generates the SmartREST topic to publish to, for a given managed object
81- /// from the list of external IDs of itself and all its parents.
82- ///
83- /// The parents are appended in the reverse order,
84- /// starting from the main device at the end of the list.
85- /// The main device itself is represented by the root topic c8y/s/us,
86- /// with the rest of the children appended to it at each topic level.
81+ /// Generates the SmartREST topic to publish to, from the external ID of its parent.
82+ /// If the parent is the main device, the topic would be `<prefix>/s/us`.
83+ /// For all other parent devices, the target topic would be `<prefix>/s/us/<parent-xid>`.
84+ /// For the main device with no parent, and the topic would be `<prefix>/s/us` in that case as well.
8785///
8886/// # Examples
8987///
90- /// - `["main"]` -> `c8y/s/us`
91- /// - `["child1", "main"]` -> `c8y/s/us/child1`
92- /// - `["child2", "child1", "main"]` -> `c8y/s/us/child1/child2`
93- pub fn publish_topic_from_ancestors ( ancestors : & [ impl AsRef < str > ] , prefix : & TopicPrefix ) -> Topic {
94- let mut target_topic = format ! ( "{prefix}/{SMARTREST_PUBLISH_TOPIC}" ) ;
95- for ancestor in ancestors. iter ( ) . rev ( ) . skip ( 1 ) {
96- // Skipping the last ancestor as it is the main device represented by the root topic itself
97- target_topic. push ( '/' ) ;
98- target_topic. push_str ( ancestor. as_ref ( ) ) ;
88+ /// - `(Some("main"), "main", "c8y")` -> `c8y/s/us`
89+ /// - `[Some("child1"), "main", "c8y"]` -> `c8y/s/us/child1`
90+ /// - `[Some("service1"), "main", "c8y"]` -> `c8y/s/us/service1`
91+ /// - `(None, "main", "c8y")` -> `c8y/s/us`
92+ pub fn publish_topic_from_parent (
93+ parent_xid : Option < & str > ,
94+ main_device_xid : & str ,
95+ prefix : & TopicPrefix ,
96+ ) -> Topic {
97+ if let Some ( parent) = parent_xid {
98+ if parent != main_device_xid {
99+ return C8yTopic :: ChildSmartRestResponse ( parent. to_string ( ) )
100+ . to_topic ( prefix)
101+ . unwrap ( ) ;
102+ }
99103 }
100-
101- Topic :: new_unchecked ( & target_topic)
104+ C8yTopic :: upstream_topic ( prefix)
102105}
103106
104107#[ cfg( test) ]
@@ -135,13 +138,12 @@ mod tests {
135138 )
136139 }
137140
138- #[ test_case( & [ "main" ] , "c8y2/s/us" ) ]
139- #[ test_case( & [ "foo" ] , "c8y2/s/us" ) ]
140- #[ test_case( & [ "child1" , "main" ] , "c8y2/s/us/child1" ) ]
141- #[ test_case( & [ "child3" , "child2" , "child1" , "main" ] , "c8y2/s/us/child1/child2/child3" ) ]
142- fn topic_from_ancestors ( ancestors : & [ & str ] , topic : & str ) {
141+ #[ test_case( None , "main-device" , "c8y2/s/us" ) ]
142+ #[ test_case( Some ( "child01" ) , "main-device" , "c8y2/s/us/child01" ) ]
143+ #[ test_case( Some ( "main-device" ) , "main-device" , "c8y2/s/us" ) ]
144+ fn topic_from_parent ( parent_xid : Option < & str > , main_device_xid : & str , topic : & str ) {
143145 let nested_child_topic =
144- publish_topic_from_ancestors ( ancestors , & "c8y2" . try_into ( ) . unwrap ( ) ) ;
146+ publish_topic_from_parent ( parent_xid , main_device_xid , & "c8y2" . try_into ( ) . unwrap ( ) ) ;
145147 assert_eq ! ( nested_child_topic, Topic :: new_unchecked( topic) ) ;
146148 }
147149}
0 commit comments