88
99import attr
1010
11+ from pyais .bit_vector import bit_vector
1112from pyais .constants import TalkerID , NavigationStatus , ManeuverIndicator , EpfdType , ShipType , NavAid , StationType , \
1213 TransmitMode , StationIntervals , TurnRate , InlandLoadedType
1314from pyais .exceptions import InvalidNMEAMessageException , TagBlockNotInitializedException , UnknownMessageException , UnknownPartNoException , \
1415 InvalidDataTypeException , MissingPayloadException
15- from pyais .util import SIX_BIT_ENCODING , SixBitNibleDecoder , SixBitNibleEncoder , checksum , compute_checksum , decode_bytes_as_ascii6 , extract_bits , get_bytes , get_itdma_comm_state , get_num , get_sotdma_comm_state , chk_to_int , coerce_val , b64encode_str , is_auxiliary_craft
16+ from pyais .util import SIX_BIT_ENCODING , SixBitNibleEncoder , checksum , compute_checksum , get_itdma_comm_state , get_sotdma_comm_state , chk_to_int , coerce_val , b64encode_str , is_auxiliary_craft
1617
1718NMEA_VALUE = typing .Union [str , float , int , bool , bytes ]
1819
@@ -535,9 +536,8 @@ class AISSentence(NMEASentence):
535536 'frag_num' ,
536537 'seq_id' ,
537538 'payload' ,
538- 'data ' ,
539+ 'bv ' ,
539540 'ais_id' ,
540- 'total_bits' ,
541541 'channel' ,
542542 )
543543
@@ -575,8 +575,8 @@ def __init__(self, raw: bytes) -> None:
575575 raise InvalidNMEAMessageException ("Too many fragments" )
576576
577577 # Finally decode bytes into bits
578- self .data , self . total_bits = SixBitNibleDecoder (). decode (self .payload , self .fill_bits )
579- self .ais_id = extract_bits ( self .data , 0 , 6 , self . total_bits )
578+ self .bv = bit_vector (self .payload , self .fill_bits )
579+ self .ais_id = self .bv . get ( 0 , 6 )
580580
581581 def asdict (self ) -> Dict [str , Any ]:
582582 """
@@ -641,9 +641,7 @@ def assemble_from_iterable(cls, messages: Sequence["AISSentence"]) -> "AISSenten
641641
642642 messages [0 ].raw = raw
643643 messages [0 ].payload = payload
644- data , total_bits = SixBitNibleDecoder ().decode (payload , fill_bits = messages [- 1 ].fill_bits )
645- messages [0 ].data = data
646- messages [0 ].total_bits = total_bits
644+ messages [0 ].bv = bit_vector (payload , messages [- 1 ].fill_bits )
647645 messages [0 ].is_valid = is_valid
648646 return messages [0 ]
649647
@@ -670,7 +668,7 @@ def decode(self) -> "ANY_MESSAGE":
670668 if not self .payload :
671669 raise MissingPayloadException (self .raw .decode ())
672670 try :
673- return MSG_CLASS [self .ais_id ].from_bytes (self .data , self . total_bits )
671+ return MSG_CLASS [self .ais_id ].from_bytes (self .bv )
674672 except KeyError as e :
675673 raise UnknownMessageException (f"The message { self } is not supported!" ) from e
676674
@@ -818,16 +816,13 @@ def create(cls, **kwargs: NMEA_VALUE) -> "ANY_MESSAGE":
818816 return cls (** args ) # type:ignore
819817
820818 @classmethod
821- def from_bytes (cls , data : bytes , total_bits : int ) -> "ANY_MESSAGE" :
819+ def from_bytes (cls , bv : bit_vector ) -> "ANY_MESSAGE" :
822820 cur : int = 0
823821 kwargs : typing .Dict [str , typing .Any ] = {}
824822
825- large_number = int .from_bytes (data , byteorder = 'big' )
826- large_number = large_number >> (8 - (total_bits % 8 )) % 8
827-
828823 # Iterate over fields and data
829824 for field in cls .fields ():
830- if cur >= total_bits :
825+ if cur >= len ( bv ) :
831826 # All fields that did not fit into the bit array are None
832827 kwargs [field .name ] = None
833828 continue
@@ -839,17 +834,17 @@ def from_bytes(cls, data: bytes, total_bits: int) -> "ANY_MESSAGE":
839834 val : typing .Any
840835 # Get the correct data type and decoding function
841836 if d_type == int or d_type == bool or d_type == float :
842- val = get_num (large_number , cur , width , total_bits , signed = field .metadata ['signed' ])
837+ val = bv . get_num (cur , width , field .metadata ['signed' ])
843838
844839 if d_type == float :
845840 val = float (val )
846841 elif d_type == bool :
847842 val = bool (val )
848843
849844 elif d_type == str :
850- val = decode_bytes_as_ascii6 ( data , cur , width )
845+ val = bv . get_str ( cur , width )
851846 elif d_type == bytes :
852- val = get_bytes (data , cur , width )
847+ val = bv . get_bytes (cur , width )
853848 else :
854849 raise InvalidDataTypeException (d_type )
855850
@@ -1170,13 +1165,13 @@ def create(cls, **kwargs: typing.Union[str, float, int, bool, bytes]) -> "ANY_ME
11701165 return MessageType8Default .create (** kwargs )
11711166
11721167 @classmethod
1173- def from_bytes (cls , data : bytes , total_bits : int ) -> "ANY_MESSAGE" :
1174- dac : int = extract_bits ( data , 40 , 10 )
1175- fid : int = extract_bits ( data , 50 , 6 )
1168+ def from_bytes (cls , bv : bit_vector ) -> "ANY_MESSAGE" :
1169+ dac : int = bv . get ( 40 , 10 )
1170+ fid : int = bv . get ( 50 , 6 )
11761171 if dac == 200 and fid == 10 :
1177- return MessageType8Dac200Fid10 .from_bytes (data , total_bits )
1172+ return MessageType8Dac200Fid10 .from_bytes (bv )
11781173 else :
1179- return MessageType8Default .from_bytes (data , total_bits )
1174+ return MessageType8Default .from_bytes (bv )
11801175
11811176
11821177@attr .s (slots = True )
@@ -1407,10 +1402,10 @@ def create(cls, **kwargs: typing.Union[str, float, int, bool, bytes]) -> "ANY_ME
14071402 return MessageType16DestinationA .create (** kwargs )
14081403
14091404 @classmethod
1410- def from_bytes (cls , data : bytes , total_bits : int ) -> "ANY_MESSAGE" :
1411- if total_bits > 96 :
1412- return MessageType16DestinationAB .from_bytes (data , total_bits )
1413- return MessageType16DestinationA .from_bytes (data , total_bits )
1405+ def from_bytes (cls , bv : bit_vector ) -> "ANY_MESSAGE" :
1406+ if len ( bv ) > 96 :
1407+ return MessageType16DestinationAB .from_bytes (bv )
1408+ return MessageType16DestinationA .from_bytes (bv )
14141409
14151410
14161411@attr .s (slots = True )
@@ -1651,11 +1646,11 @@ def create(cls, **kwargs: typing.Union[str, float, int, bool, bytes]) -> "ANY_ME
16511646 return MessageType22Broadcast .create (** kwargs )
16521647
16531648 @classmethod
1654- def from_bytes (cls , data : bytes , total_bits : int ) -> "ANY_MESSAGE" :
1655- if extract_bits ( data , 139 , 1 ):
1656- return MessageType22Addressed .from_bytes (data , total_bits )
1649+ def from_bytes (cls , bv : bit_vector ) -> "ANY_MESSAGE" :
1650+ if bv . get ( 139 , 1 ):
1651+ return MessageType22Addressed .from_bytes (bv )
16571652 else :
1658- return MessageType22Broadcast .from_bytes (data , total_bits )
1653+ return MessageType22Broadcast .from_bytes (bv )
16591654
16601655
16611656@attr .s (slots = True )
@@ -1767,15 +1762,15 @@ def create(cls, **kwargs: typing.Union[str, float, int, bool, bytes]) -> "ANY_ME
17671762 raise UnknownPartNoException (f"Partno { partno } is not allowed!" )
17681763
17691764 @classmethod
1770- def from_bytes (cls , data : bytes , total_bits : int ) -> "ANY_MESSAGE" :
1771- mmsi : int = extract_bits ( data , 8 , 30 )
1772- partno : int = extract_bits ( data , 38 , 2 )
1765+ def from_bytes (cls , bv : bit_vector ) -> "ANY_MESSAGE" :
1766+ mmsi : int = bv . get ( 8 , 30 )
1767+ partno : int = bv . get ( 38 , 2 )
17731768 if partno == 0 :
1774- return MessageType24PartA .from_bytes (data , total_bits )
1769+ return MessageType24PartA .from_bytes (bv )
17751770 elif partno == 1 :
17761771 if is_auxiliary_craft (mmsi ):
1777- return MessageType24PartBAuxiliaryCraft .from_bytes (data , total_bits )
1778- return MessageType24PartB .from_bytes (data , total_bits )
1772+ return MessageType24PartBAuxiliaryCraft .from_bytes (bv )
1773+ return MessageType24PartB .from_bytes (bv )
17791774 else :
17801775 raise UnknownPartNoException (f"Partno { partno } is not allowed!" )
17811776
@@ -1859,20 +1854,20 @@ def create(cls, **kwargs: typing.Union[str, float, int, bool, bytes]) -> "ANY_ME
18591854 return MessageType25BroadcastUnstructured .create (** kwargs )
18601855
18611856 @classmethod
1862- def from_bytes (cls , data : bytes , total_bits : int ) -> "ANY_MESSAGE" :
1863- addressed : int = extract_bits ( data , 38 , 1 )
1864- structured : int = extract_bits ( data , 39 , 1 )
1857+ def from_bytes (cls , bv : bit_vector ) -> "ANY_MESSAGE" :
1858+ addressed : int = bv . get ( 38 , 1 )
1859+ structured : int = bv . get ( 39 , 1 )
18651860
18661861 if addressed :
18671862 if structured :
1868- return MessageType25AddressedStructured .from_bytes (data , total_bits )
1863+ return MessageType25AddressedStructured .from_bytes (bv )
18691864 else :
1870- return MessageType25AddressedUnstructured .from_bytes (data , total_bits )
1865+ return MessageType25AddressedUnstructured .from_bytes (bv )
18711866 else :
18721867 if structured :
1873- return MessageType25BroadcastStructured .from_bytes (data , total_bits )
1868+ return MessageType25BroadcastStructured .from_bytes (bv )
18741869 else :
1875- return MessageType25BroadcastUnstructured .from_bytes (data , total_bits )
1870+ return MessageType25BroadcastUnstructured .from_bytes (bv )
18761871
18771872
18781873@attr .s (slots = True )
@@ -1959,20 +1954,20 @@ def create(cls, **kwargs: typing.Union[str, float, int, bool, bytes]) -> "ANY_ME
19591954 return MessageType26BroadcastUnstructured .create (** kwargs )
19601955
19611956 @classmethod
1962- def from_bytes (cls , data : bytes , total_bits : int ) -> "ANY_MESSAGE" :
1963- addressed : int = extract_bits ( data , 38 , 1 )
1964- structured : int = extract_bits ( data , 39 , 1 )
1957+ def from_bytes (cls , bv : bit_vector ) -> "ANY_MESSAGE" :
1958+ addressed : int = bv . get ( 38 , 1 )
1959+ structured : int = bv . get ( 39 , 1 )
19651960
19661961 if addressed :
19671962 if structured :
1968- return MessageType26AddressedStructured .from_bytes (data , total_bits )
1963+ return MessageType26AddressedStructured .from_bytes (bv )
19691964 else :
1970- return MessageType26AddressedUnstructured .from_bytes (data , total_bits )
1965+ return MessageType26AddressedUnstructured .from_bytes (bv )
19711966 else :
19721967 if structured :
1973- return MessageType26BroadcastStructured .from_bytes (data , total_bits )
1968+ return MessageType26BroadcastStructured .from_bytes (bv )
19741969 else :
1975- return MessageType26BroadcastUnstructured .from_bytes (data , total_bits )
1970+ return MessageType26BroadcastUnstructured .from_bytes (bv )
19761971
19771972
19781973@attr .s (slots = True )
0 commit comments