2222from enum import IntEnum
2323import xml .etree .ElementTree as et
2424from cssrlib .gnss import gpst2time , time2gst
25+ import copy
2526
2627
2728class uOSNMA (IntEnum ):
@@ -145,14 +146,17 @@ class osnma():
145146 tag = bytearray (42 )
146147 mack_p = bytearray (60 * GALMAX ) # previous MACK
147148 mack_c = bytearray (60 * GALMAX ) # current MACK
148- subfrm = bytearray (16 * 10 * GALMAX )
149149 tag_list = []
150150
151151 vcnt_min = 2
152152 iodnav = np .zeros (GALMAX + 1 , dtype = int )
153153 vcnt = np .zeros (GALMAX + 1 , dtype = int )
154154 vstatus = np .zeros (GALMAX + 1 , dtype = bool )
155155
156+ subfrm_n = None
157+ subfrm_p = None
158+ subfrm = None
159+
156160 # Public Key in PEM received from GSC OSNMA server
157161 # note : EC_PARAMETER section should be removed.
158162 # pubk_path = '../data/OSNMA_PublicKey_20210920133026_s.pem'
@@ -162,6 +166,8 @@ class osnma():
162166 mt_path = '../data/pubkey/osnma/OSNMA_MerkleTree_20240115100000_newPKID_1.xml'
163167 pk_list = []
164168
169+ flg_slowmac = False
170+
165171 def raw2der (self , ds ):
166172 """ convert digital signature from raw format to der format """
167173 lds = len (ds )
@@ -234,6 +240,14 @@ def __init__(self):
234240 self .pk_list .append (pubkey (k ))
235241 self .load_mt (self .mt_path )
236242
243+ self .flg_dsm = {}
244+
245+ self .subfrm_n = bytearray (16 * 10 * self .GALMAX )
246+ self .subfrm_p = bytearray (16 * 10 * self .GALMAX )
247+ self .subfrm = bytearray (16 * 10 * self .GALMAX )
248+
249+ self .prn_ref = - 1
250+
237251 def process_hash (self , msg ):
238252 """ calculate hash """
239253 digest = hashes .Hash (self .hash_table [self .hf ]())
@@ -394,7 +408,7 @@ def decode_dsm_pkr(self, did):
394408 self .status |= uOSNMA .PKR_UPDATED # PKR updated
395409 return result
396410
397- def decode_hk (self , hk ):
411+ def decode_hk (self , hk , prn ):
398412 """ decode HKROOT message """
399413 self .nma_header = hk [0 ]
400414 nmas , cid , cpks , _ = bs .unpack_from ('u2u2u3u1' , hk , 0 )
@@ -424,6 +438,9 @@ def decode_hk(self, hk):
424438 self .nb [did ] = nb_ + 6 # number of blocks
425439
426440 result = False
441+ if self .monlevel > 1 :
442+ print (f"flg_dsm[did={ did } ]={ self .flg_dsm [did ]:2x} "
443+ f"nb={ self .nb [did ]:2d} bid={ bid } prn={ prn } " )
427444 if did in self .nb .keys () and \
428445 self .flg_dsm [did ] == (1 << self .nb [did ])- 1 :
429446 if did <= 11 : # DSM-KROOT
@@ -532,9 +549,10 @@ def decode_mack(self, prn):
532549 lk = self .klen_t [self .ks ]
533550 self .nt = (480 - lk )// (lt + 16 ) # number of tags
534551 ltag_b = (lt + 16 )// 8
535- i0 = 60 * (prn - 1 )
536- mack_p = self .mack_p [i0 :i0 + 60 ] # previous MACK
537- mack_c = self .mack_c [i0 :i0 + 60 ] # current MACK
552+ lm_b = 60
553+ i0 = (prn - 1 )* lm_b
554+ mack_p = self .mack_p [i0 :i0 + lm_b ] # previous MACK
555+ mack_c = self .mack_c [i0 :i0 + lm_b ] # current MACK
538556 i0 = ltag_b * self .nt
539557 self .tag = mack_p [0 :i0 ]
540558 self .key_p = mack_p [i0 :i0 + lk // 8 ]
@@ -590,12 +608,33 @@ def load_inav(self, msg):
590608
591609 return nav , nma_b
592610
593- def load_nav (self , nav , prn ):
611+ def load_nav (self , nav , prn , tow ):
594612 """ load navigation message into subframe buffer """
595613 mt = bs .unpack_from ('u6' , nav , 0 )[0 ]
614+ j0 = (prn - 1 )* 160
615+
616+ if tow % 30 == 1 :
617+ self .subfrm [j0 :j0 + 160 ] = self .subfrm_p [j0 :j0 + 160 ]
618+ self .subfrm_p [j0 :j0 + 160 ] = self .subfrm_n [j0 :j0 + 160 ]
619+ # self.subfrm_n[j0:j0+160] = [0]*160
620+
596621 if mt > 0 and mt <= 10 :
597- j = (prn - 1 )* 160 + (mt - 1 )* 16
598- self .subfrm [j :j + 16 ] = nav
622+ j = j0 + (mt - 1 )* 16
623+ self .subfrm_n [j :j + 16 ] = nav
624+
625+ if self .monlevel > 0 and prn == self .prn_ref :
626+ if mt >= 1 and mt <= 4 :
627+ iodnav = bs .unpack_from ('u10' , nav , 6 )[0 ]
628+ print (f"tow={ tow } prn={ prn :2d} mt={ mt :2d} iodnav={ iodnav } " )
629+ elif mt == 5 :
630+ tow_ = bs .unpack_from ('u20' , nav , 85 )[0 ]
631+ print (f"tow={ tow } prn={ prn :2d} mt={ mt :2d} tow={ tow_ } " )
632+ elif mt == 6 :
633+ tow_ = bs .unpack_from ('u20' , nav , 105 )[0 ]
634+ print (f"tow={ tow } prn={ prn :2d} mt={ mt :2d} tow={ tow_ } " )
635+ else :
636+ print (f"tow={ tow } prn={ prn :2d} mt={ mt :2d} " )
637+
599638 return True
600639
601640 def gen_navmsg (self , prn ):
@@ -656,7 +695,6 @@ def gen_utcmsg(self):
656695 return None
657696 if self .monlevel > 0 :
658697 tow = bs .unpack_from ('u20' , mt6 , 105 )[0 ]
659- # bs.pack_into('u20', mt6, 105, tow+self.tofst) # <- tow-=60
660698 print (" utc gst_tow=%6d" % (tow ))
661699
662700 # 141b MT6 99b, MT10 42b
@@ -667,20 +705,16 @@ def gen_utcmsg(self):
667705 bs .pack_into ('u8' , msg , j , b )
668706 j += 8
669707 j = 99
670- for k in range (5 ):
671- b = bs .unpack_from ('u8' , mt10 , k * 8 + 86 )[0 ]
672- bs .pack_into ('u8' , msg , j , b )
673- j += 8
674708
675- b = bs .unpack_from ('u2' , mt10 , 40 + 86 )[0 ]
676- bs .pack_into ('u2' , msg , j , b )
677- j += 2
709+ a0g , a1g , t0g , wn0g = bs .unpack_from ('s16s12u8u6' , mt10 , 86 )
710+ bs .pack_into ('s16s12u8u6' , msg , j , a0g , a1g , t0g , wn0g )
678711
679712 return msg
680713
681714 def gen_msg (self , adkd , prn_d , gst_sf , ctr , msg ):
682715 """ generate message for verification of NMA """
683716 mlen = 141 if adkd == 4 else 549
717+ rem_ = mlen - mlen // 8 * 8 # number of remaining bit
684718 j = 0
685719 if adkd == 0 and self .prn_a == prn_d :
686720 mlen += 8 + 42
@@ -700,13 +734,9 @@ def gen_msg(self, adkd, prn_d, gst_sf, ctr, msg):
700734 j += 42
701735 for k in range (len (msg )):
702736 b = msg [k ]
703- if k == len (msg )- 1 :
704- if adkd == 4 :
705- bs .pack_into ('u3' , m , j , b >> 5 )
706- j += 3
707- else :
708- bs .pack_into ('u5' , m , j , b >> 3 )
709- j += 5
737+ if rem_ != 0 and k == len (msg )- 1 :
738+ bs .pack_into ('u' + str (rem_ ), m , j , b >> (8 - rem_ ))
739+ j += rem_
710740 else :
711741 bs .pack_into ('u8' , m , j , b )
712742 j += 8
@@ -765,26 +795,26 @@ def decode(self, nma_b, wn, tow, prn):
765795 PRN number
766796 """
767797 status = False
768- k = (tow % 30 )// 2
769- if k == 0 : # reset counter
798+ ki = (tow % 30 )// 2
799+ if ki == 0 : # reset counter
770800 self .cnt [prn - 1 ] = 0
771801 self .hk [prn - 1 ] = bytearray (15 )
772802 self .mack [prn - 1 ][0 ] = 0
773- elif k < 0 :
803+ elif ki < 0 :
774804 return
775805
776806 # convert GPS time to Galileo standard time (GST)
777807 gst_wn , gst_tow = time2gst (gpst2time (wn , tow ))
778808
779809 self .gst_tow = (gst_tow // 30 )* 30 # current subframe-time
780810 # store sub-frame for NMA
781- self .hk [prn - 1 ][k ] = nma_b [0 ] # HK-ROOT message
782- self .mack [prn - 1 ][k * 4 :k * 4 + 4 ] = nma_b [1 :5 ] # MACK message
783- self .cnt [prn - 1 ] |= (1 << k )
811+ self .hk [prn - 1 ][ki ] = nma_b [0 ] # HK-ROOT message
812+ self .mack [prn - 1 ][ki * 4 :ki * 4 + 4 ] = nma_b [1 :5 ] # MACK message
813+ self .cnt [prn - 1 ] |= (1 << ki )
784814 if self .cnt [prn - 1 ] == 0x7fff : # all(0-14) message loaded
785815 self .save_mack (self .mack [prn - 1 ], prn ) # store MACK
786816 # decode HK-ROOT messages
787- result = self .decode_hk (self .hk [prn - 1 ])
817+ result = self .decode_hk (self .hk [prn - 1 ], prn )
788818 if self .monlevel > 0 :
789819 s = "wn=%4d tow=%d gst_tow=%6d prn=%d did=%d" % \
790820 (wn , tow , self .gst_tow , prn , self .did0 )
@@ -865,20 +895,29 @@ def decode(self, nma_b, wn, tow, prn):
865895 tag , macseq , cop = self .decode_tags_info (0 )
866896 else :
867897 tag , prn_d , adkd , cop = self .decode_tags_info (k )
868- if adkd == 12 : # delayed tag loading
898+ if adkd == 12 and self .flg_slowmac :
899+ # delayed tag loading
869900 navmsg = self .gen_navmsg (prn_d )
870- tag_ = taginfo (self .gst_sf , prn_d , adkd , cop ,
901+ tag_ = taginfo (self .gst_sf_p , prn_d , adkd , cop ,
871902 tag , ctr , navmsg )
872903 self .tag_list .append (tag_ )
873904
874905 if adkd == 12 :
906+ print (f"{ ctr } prn_d={ prn_d } adkd={ adkd } slow-MAC "
907+ "is skipped" )
875908 continue
876909 elif adkd == 0 :
877910 navmsg = self .gen_navmsg (prn_d )
878911 elif adkd == 4 :
879912 navmsg = self .gen_utcmsg ()
880913 else :
881914 navmsg = None
915+
916+ if navmsg is None :
917+ print (f"{ ctr } prn_d={ prn_d } adkd={ adkd } navmsg is "
918+ "not available." )
919+ continue
920+
882921 tag_ = taginfo (self .gst_sf_p , prn_d ,
883922 adkd , cop , tag , ctr , navmsg )
884923 result = self .verify_navmsg (tag_ )
@@ -893,15 +932,16 @@ def decode(self, nma_b, wn, tow, prn):
893932 print (f"{ ctr } prn_d={ prn_d } adkd={
894933 adkd } tag not verified" )
895934 # slow MAC
896- for tag_ in self .tag_list :
897- dt = self .difftime (self .gst_sf , tag_ .gst_sf )
898- if dt == 300 :
899- result = self .verify_navmsg (tag_ )
900- if self .monlevel > 0 and result :
901- print ("SLOW-MAC# %d prn_d=%2d adkd=%2d tag verified"
902- % (tag_ .cnt , tag_ .prn , tag_ .adkd ))
903- elif dt > 300 :
904- tag_ = None
935+ if self .flg_slowmac :
936+ for tag_ in self .tag_list :
937+ dt = self .difftime (self .gst_sf , tag_ .gst_sf )
938+ if dt == 300 :
939+ result = self .verify_navmsg (tag_ )
940+ if self .monlevel > 0 and result :
941+ print ("SLOW-MAC# %d prn_d=%2d adkd=%2d tag verified"
942+ % (tag_ .cnt , tag_ .prn , tag_ .adkd ))
943+ elif dt > 300 :
944+ tag_ = None
905945
906946 self .cnt [prn - 1 ] = 0
907947 return status
0 commit comments