@@ -179,6 +179,8 @@ impl MqttSchema {
179179 ChannelFilter :: Command ( operation) => format ! ( "/cmd/{operation}/+" ) ,
180180 ChannelFilter :: AnyCommandMetadata => "/cmd/+" . to_string ( ) ,
181181 ChannelFilter :: CommandMetadata ( operation) => format ! ( "/cmd/{operation}" ) ,
182+ ChannelFilter :: AnySignal => "/signal/+" . to_string ( ) ,
183+ ChannelFilter :: Signal ( signal_type) => format ! ( "/signal/{signal_type}" ) ,
182184 ChannelFilter :: Health => "/status/health" . to_string ( ) ,
183185 } ;
184186
@@ -608,6 +610,9 @@ pub enum Channel {
608610 operation : OperationType ,
609611 cmd_id : String ,
610612 } ,
613+ Signal {
614+ signal_type : SignalType ,
615+ } ,
611616 MeasurementMetadata {
612617 measurement_type : String ,
613618 } ,
@@ -660,6 +665,9 @@ impl FromStr for Channel {
660665 operation : operation. parse ( ) . unwrap ( ) , // Infallible
661666 cmd_id : cmd_id. to_string ( ) ,
662667 } ) ,
668+ [ "signal" , signal_type] => Ok ( Channel :: Signal {
669+ signal_type : signal_type. into ( ) ,
670+ } ) ,
663671 [ "status" , "health" ] => Ok ( Channel :: Health ) ,
664672
665673 _ => Err ( ChannelError :: InvalidCategory ( channel. to_string ( ) ) ) ,
@@ -687,6 +695,7 @@ impl Display for Channel {
687695 Channel :: Command { operation, cmd_id } => write ! ( f, "cmd/{operation}/{cmd_id}" ) ,
688696 Channel :: CommandMetadata { operation } => write ! ( f, "cmd/{operation}" ) ,
689697 Channel :: Health => write ! ( f, "status/health" ) ,
698+ Channel :: Signal { signal_type } => write ! ( f, "signal/{signal_type}" ) ,
690699 }
691700 }
692701}
@@ -786,6 +795,64 @@ impl OperationType {
786795 }
787796}
788797
798+ #[ derive( Debug , Clone , PartialEq , Eq , Hash ) ]
799+ pub enum SignalType {
800+ SyncOperations ,
801+ Custom ( String ) ,
802+ }
803+
804+ // Using a custom Serialize/Deserialize implementations to read "foo" as Custom("foo")
805+ impl < ' de > Deserialize < ' de > for SignalType {
806+ fn deserialize < D > ( deserializer : D ) -> Result < Self , D :: Error >
807+ where
808+ D : Deserializer < ' de > ,
809+ {
810+ let str = String :: deserialize ( deserializer) ?;
811+ Ok ( str. as_str ( ) . into ( ) )
812+ }
813+ }
814+
815+ impl Serialize for SignalType {
816+ fn serialize < S > ( & self , serializer : S ) -> Result < S :: Ok , S :: Error >
817+ where
818+ S : Serializer ,
819+ {
820+ self . to_string ( ) . serialize ( serializer)
821+ }
822+ }
823+
824+ impl FromStr for SignalType {
825+ type Err = Infallible ;
826+
827+ fn from_str ( s : & str ) -> Result < Self , Self :: Err > {
828+ Ok ( s. into ( ) )
829+ }
830+ }
831+
832+ impl < ' a > From < & ' a str > for SignalType {
833+ fn from ( s : & ' a str ) -> SignalType {
834+ match s {
835+ "sync_operations" => SignalType :: SyncOperations ,
836+ custom => SignalType :: Custom ( custom. to_string ( ) ) ,
837+ }
838+ }
839+ }
840+
841+ impl Display for SignalType {
842+ fn fmt ( & self , f : & mut Formatter < ' _ > ) -> std:: fmt:: Result {
843+ match self {
844+ SignalType :: SyncOperations => write ! ( f, "sync_operations" ) ,
845+ SignalType :: Custom ( custom) => write ! ( f, "{custom}" ) ,
846+ }
847+ }
848+ }
849+
850+ impl SignalType {
851+ pub fn name ( & self ) -> String {
852+ format ! ( "{self}" )
853+ }
854+ }
855+
789856#[ derive( Debug , thiserror:: Error , PartialEq , Eq , Clone ) ]
790857pub enum ChannelError {
791858 #[ error( "Channel needs to have at least 2 segments" ) ]
@@ -809,6 +876,8 @@ pub enum ChannelFilter {
809876 Alarm ,
810877 AnyCommand ,
811878 Command ( OperationType ) ,
879+ AnySignal ,
880+ Signal ( SignalType ) ,
812881 MeasurementMetadata ,
813882 EventMetadata ,
814883 AlarmMetadata ,
@@ -831,6 +900,7 @@ impl From<&Channel> for ChannelFilter {
831900 operation,
832901 cmd_id : _,
833902 } => ChannelFilter :: Command ( operation. clone ( ) ) ,
903+ Channel :: Signal { signal_type } => ChannelFilter :: Signal ( signal_type. clone ( ) ) ,
834904 Channel :: MeasurementMetadata {
835905 measurement_type : _,
836906 } => ChannelFilter :: MeasurementMetadata ,
@@ -1090,6 +1160,15 @@ mod tests {
10901160 ) ,
10911161 mqtt_channel:: Topic :: new_unchecked( "te/device/main///cmd/log_upload" )
10921162 ) ;
1163+ assert_eq ! (
1164+ mqtt_schema. topic_for(
1165+ & device,
1166+ & Channel :: Signal {
1167+ signal_type: SignalType :: SyncOperations ,
1168+ }
1169+ ) ,
1170+ mqtt_channel:: Topic :: new_unchecked( "te/device/main///signal/sync_operations" )
1171+ ) ;
10931172 assert_eq ! (
10941173 mqtt_schema. topic_for( & device, & Channel :: Health ) ,
10951174 mqtt_channel:: Topic :: new_unchecked( "te/device/main///status/health" )
0 commit comments