1+
12#[ derive( Debug ) ]
23pub struct NmeaSentence {
34 pub sentence_type : char ,
@@ -28,12 +29,24 @@ pub struct SeatalkMessage {
2829 pub checksum : String ,
2930}
3031
32+ #[ derive( Debug ) ]
33+ pub struct DscMessage {
34+ pub format_specifier : String ,
35+ pub address : String ,
36+ pub category : String ,
37+ pub self_id : String ,
38+ pub subsequent_communications : String ,
39+ pub data_fields : Vec < String > ,
40+ pub checksum : Option < String > ,
41+ }
42+
3143#[ derive( Debug ) ]
3244pub enum MessageType {
3345 Nmea ( NmeaSentence ) ,
3446 Ais ( NmeaSentence ) ,
3547 Inmarsat ( InmarsatMessage ) ,
3648 Seatalk ( SeatalkMessage ) ,
49+ Dsc ( DscMessage ) ,
3750}
3851
3952pub fn parse_inmarsat_header ( header : & str ) -> Result < InmarsatHeader , & ' static str > {
@@ -119,6 +132,64 @@ pub fn parse_nmea_sentence(sentence: &str) -> Result<NmeaSentence, &'static str>
119132 } )
120133}
121134
135+ pub fn parse_dsc_message ( message : & str ) -> Result < DscMessage , & ' static str > {
136+ // DSC messages start with $ and have DSC as talker ID
137+ if !message. starts_with ( '$' ) {
138+ return Err ( "DSC message must start with '$'" ) ;
139+ }
140+
141+ let content = & message[ 1 ..] ; // Remove the leading '$'
142+
143+ // Split into data part and checksum part
144+ let ( data_part, checksum_part) = match content. split_once ( '*' ) {
145+ Some ( ( data, checksum) ) => ( data, Some ( checksum) ) ,
146+ None => ( content, None ) ,
147+ } ;
148+
149+ // Split data part into fields
150+ let fields: Vec < & str > = data_part. split ( ',' ) . collect ( ) ;
151+ if fields. len ( ) < 6 {
152+ return Err ( "DSC message must have at least 6 fields" ) ;
153+ }
154+
155+ // Verify talker ID is DSC
156+ if fields[ 0 ] != "DSC" {
157+ return Err ( "DSC message must have 'DSC' as talker ID" ) ;
158+ }
159+
160+ // Extract required DSC fields
161+ let format_specifier = fields[ 1 ] . to_string ( ) ;
162+ let address = fields[ 2 ] . to_string ( ) ;
163+ let category = fields[ 3 ] . to_string ( ) ;
164+ let self_id = fields[ 4 ] . to_string ( ) ;
165+ let subsequent_communications = fields[ 5 ] . to_string ( ) ;
166+
167+ // Process remaining data fields
168+ let data_fields = fields[ 6 ..]
169+ . iter ( )
170+ . map ( |field| field. to_string ( ) )
171+ . collect ( ) ;
172+
173+ // Process checksum if present
174+ let checksum = checksum_part. and_then ( |cs| {
175+ if cs. len ( ) >= 2 {
176+ Some ( cs[ 0 ..2 ] . to_string ( ) )
177+ } else {
178+ None
179+ }
180+ } ) ;
181+
182+ Ok ( DscMessage {
183+ format_specifier,
184+ address,
185+ category,
186+ self_id,
187+ subsequent_communications,
188+ data_fields,
189+ checksum,
190+ } )
191+ }
192+
122193pub fn parse_inmarsat_message ( message : & str ) -> Result < InmarsatMessage , & ' static str > {
123194 // Split the message into header and payload
124195 let ( header_part, payload_part) = match message. split_once ( '/' ) {
@@ -173,6 +244,10 @@ pub fn detect_and_parse_message(message: &str) -> Result<MessageType, &'static s
173244 // SeaTalk message
174245 let seatalk_message = parse_seatalk_message ( message) ?;
175246 Ok ( MessageType :: Seatalk ( seatalk_message) )
247+ } else if message. starts_with ( "$DSC" ) {
248+ // DSC message
249+ let dsc_message = parse_dsc_message ( message) ?;
250+ Ok ( MessageType :: Dsc ( dsc_message) )
176251 } else {
177252 // NMEA message
178253 let nmea_sentence = parse_nmea_sentence ( message) ?;
@@ -202,6 +277,8 @@ fn main() {
202277 "/g:1-9-1234,s:egcterm1,n:213,c:1333636200*hh/$CSSM3,123456,005213,798,0,3,14,00,2012,04,05,14,30,3400,N,076,W,300*hh" ,
203278 // SeaTalk example
204279 "$STALK,84,56,e,0,0,0,0,0,8*0F" ,
280+ // DSC example
281+ "$DSC,12,3380405810,00,1234567890,72,1234567890,00,00,00,00,00,00,00*3B" ,
205282 ] ;
206283
207284 for example in examples {
@@ -212,6 +289,7 @@ fn main() {
212289 MessageType :: Ais ( ais) => println ! ( "AIS Sentence: {:?}" , ais) ,
213290 MessageType :: Inmarsat ( inmarsat) => println ! ( "Inmarsat Message: {:?}" , inmarsat) ,
214291 MessageType :: Seatalk ( seatalk) => println ! ( "SeaTalk Message: {:?}" , seatalk) ,
292+ MessageType :: Dsc ( dsc) => println ! ( "DSC Message: {:?}" , dsc) ,
215293 } ,
216294 Err ( e) => eprintln ! ( "Error parsing message: {}" , e) ,
217295 }
0 commit comments