def decode(bv, validate=False): '''Unpack a sls_wind message. Fields in params: - time_month(uint): Time tag of measurement month 1..12 - time_day(uint): Time tag of measurement day of the month 1..31 - time_hour(uint): Time tag of measurement UTC hours 0..23 - time_min(uint): Time tag of measurement minutes - stationid(aisstr6): Character identifier of the station - pos_longitude(decimal): Location of measurement East West location - pos_latitude(decimal): Location of measurement North South location - flow(uint): Water flow - reserved(uint): Reserved bits for future use (field automatically set to "0") @type bv: BitVector @param bv: Bits defining a message @param validate: Set to true to cause checking to occur. Runs slower. FIX: not implemented. @rtype: dict @return: params ''' #Would be nice to check the bit count here.. #if validate: # assert (len(bv)==FIX: SOME NUMBER) r = {} r['time_month']=int(bv[0:4]) r['time_day']=int(bv[4:9]) r['time_hour']=int(bv[9:14]) r['time_min']=int(bv[14:20]) r['stationid']=aisstring.decode(bv[20:62]) r['pos_longitude']=Decimal(binary.signedIntFromBV(bv[62:87]))/Decimal('60000') r['pos_latitude']=Decimal(binary.signedIntFromBV(bv[87:111]))/Decimal('60000') r['flow']=int(bv[111:121]) r['reserved']=0 return r
def decode(bv, validate=False): '''Unpack a gnss_correction message. Fields in params: - MessageID(uint): AIS message number. Must be 17 (field automatically set to "17") - RepeatIndicator(uint): Indicated how many times a message has been repeated - UserID(uint): Base station identification number (MMSI) - Spare(uint): Reserved for definition by a regional authority. (field automatically set to "0") - x(decimal): East West location - y(decimal): North South location - Spare2(uint): Reserved for definition by a regional authority. (field automatically set to "0") - BinaryData(binary): GNSS Differential correction data @type bv: BitVector @param bv: Bits defining a message @param validate: Set to true to cause checking to occur. Runs slower. FIX: not implemented. @rtype: dict @return: params ''' #Would be nice to check the bit count here.. #if validate: # assert (len(bv)==FIX: SOME NUMBER) r = {} r['MessageID'] = 17 r['RepeatIndicator'] = int(bv[6:8]) r['UserID'] = int(bv[8:38]) r['Spare'] = 0 r['x'] = Decimal(binary.signedIntFromBV(bv[40:58])) / Decimal('600') r['y'] = Decimal(binary.signedIntFromBV(bv[58:75])) / Decimal('600') r['Spare2'] = 0 r['BinaryData'] = bv[80:] return r
def decode(bv, validate=False): '''Unpack a gnss_correction message. Fields in params: - MessageID(uint): AIS message number. Must be 17 (field automatically set to "17") - RepeatIndicator(uint): Indicated how many times a message has been repeated - UserID(uint): Base station identification number (MMSI) - Spare(uint): Reserved for definition by a regional authority. (field automatically set to "0") - x(decimal): East West location - y(decimal): North South location - Spare2(uint): Reserved for definition by a regional authority. (field automatically set to "0") - BinaryData(binary): GNSS Differential correction data @type bv: BitVector @param bv: Bits defining a message @param validate: Set to true to cause checking to occur. Runs slower. FIX: not implemented. @rtype: dict @return: params ''' #Would be nice to check the bit count here.. #if validate: # assert (len(bv)==FIX: SOME NUMBER) r = {} r['MessageID']=17 r['RepeatIndicator']=int(bv[6:8]) r['UserID']=int(bv[8:38]) r['Spare']=0 r['x']=Decimal(binary.signedIntFromBV(bv[40:58]))/Decimal('600') r['y']=Decimal(binary.signedIntFromBV(bv[58:75]))/Decimal('600') r['Spare2']=0 r['BinaryData']=bv[80:] return r
def decode(bv, validate=False): '''Unpack a sls_weatherreport message. Fields in params: - time_month(uint): Time tag of measurement month 1..12 - time_day(uint): Time tag of measurement day of the month 1..31 - time_hour(uint): Time tag of measurement UTC hours 0..23 - time_min(uint): Time tag of measurement minutes - stationid(aisstr6): Character identifier of the station - pos_longitude(decimal): Location of measurement East West location - pos_latitude(decimal): Location of measurement North South location - speed(udecimal): Average wind speed - gust(udecimal): Wind gust - direction(uint): Wind direction - atmpressure(udecimal): Atmospheric pressure - airtemp(decimal): Air temperature - dewpoint(decimal): Dew Point - visibility(udecimal): Visibility - watertemp(decimal): Water Temperature - reserved(uint): Reserved bits for future use (field automatically set to "0") @type bv: BitVector @param bv: Bits defining a message @param validate: Set to true to cause checking to occur. Runs slower. FIX: not implemented. @rtype: dict @return: params ''' #Would be nice to check the bit count here.. #if validate: # assert (len(bv)==FIX: SOME NUMBER) r = {} r['time_month'] = int(bv[0:4]) r['time_day'] = int(bv[4:9]) r['time_hour'] = int(bv[9:14]) r['time_min'] = int(bv[14:20]) r['stationid'] = aisstring.decode(bv[20:62]) r['pos_longitude'] = Decimal(binary.signedIntFromBV( bv[62:87])) / Decimal('60000') r['pos_latitude'] = Decimal(binary.signedIntFromBV( bv[87:111])) / Decimal('60000') r['speed'] = Decimal(int(bv[111:121])) / Decimal('10') r['gust'] = Decimal(int(bv[121:131])) / Decimal('10') r['direction'] = int(bv[131:140]) r['atmpressure'] = Decimal(int(bv[140:154])) / Decimal('10') r['airtemp'] = Decimal(binary.signedIntFromBV(bv[154:164])) / Decimal('10') r['dewpoint'] = Decimal(binary.signedIntFromBV( bv[164:174])) / Decimal('10') r['visibility'] = Decimal(int(bv[174:182])) / Decimal('10') r['watertemp'] = Decimal(binary.signedIntFromBV( bv[182:192])) / Decimal('10') r['reserved'] = 0 return r
def decode(bv, validate=False): '''Unpack a bsreport message. Fields in params: - MessageID(uint): AIS message number. Must be 4 (field automatically set to "11") - RepeatIndicator(uint): Indicated how many times a message has been repeated - UserID(uint): Unique ship identification number (MMSI) - Time_year(uint): Current time stamp year 1-9999 - Time_month(uint): Current time stamp month 1..12 - Time_day(uint): Current time stamp day of the month 1..31 - Time_hour(uint): Current time stamp UTC hours 0..23 - Time_min(uint): Current time stamp minutes - Time_sec(uint): Current time stamp seconds - PositionAccuracy(uint): Accuracy of positioning fixes - Position_longitude(decimal): Location of base station East West location - Position_latitude(decimal): Location of base station North South location - fixtype(uint): Method used for positioning - Spare(uint): Not used. Should be set to zero. (field automatically set to "0") - RAIM(bool): Receiver autonomous integrity monitoring flag - state_syncstate(uint): Communications State - SOTDMA Sycronization state - state_slottimeout(uint): Communications State - SOTDMA Frames remaining until a new slot is selected - state_slotoffset(uint): Communications State - SOTDMA In what slot will the next transmission occur. BROKEN @type bv: BitVector @param bv: Bits defining a message @param validate: Set to true to cause checking to occur. Runs slower. FIX: not implemented. @rtype: dict @return: params ''' #Would be nice to check the bit count here.. #if validate: # assert (len(bv)==FIX: SOME NUMBER) r = {} r['MessageID']=11 r['RepeatIndicator']=int(bv[6:8]) r['UserID']=int(bv[8:38]) r['Time_year']=int(bv[38:52]) r['Time_month']=int(bv[52:56]) r['Time_day']=int(bv[56:61]) r['Time_hour']=int(bv[61:66]) r['Time_min']=int(bv[66:72]) r['Time_sec']=int(bv[72:78]) r['PositionAccuracy']=int(bv[78:79]) r['Position_longitude']=Decimal(binary.signedIntFromBV(bv[79:107]))/Decimal('600000') r['Position_latitude']=Decimal(binary.signedIntFromBV(bv[107:134]))/Decimal('600000') r['fixtype']=int(bv[134:138]) r['Spare']=0 r['RAIM']=bool(int(bv[148:149])) r['state_syncstate']=int(bv[149:151]) r['state_slottimeout']=int(bv[151:154]) r['state_slotoffset']=int(bv[154:168]) return r
def decode(bv, validate=False): '''Unpack a whalenotice message. Fields in params: - MessageID(uint): AIS message number. Must be 8 (field automatically set to "8") - RepeatIndicator(uint): Indicated how many times a message has been repeated - UserID(uint): Unique ship identification number (MMSI) - Spare(uint): Reserved for definition by a regional authority. (field automatically set to "0") - dac(uint): Designated Area Code - 366 for the United States (field automatically set to "366") - fid(uint): Functional IDentifier - 63 for the Whale Notice (field automatically set to "63") - efid(uint): Extended Functional IDentifier. 1 for the Whale Notice (dac+fid+efid defines the exact message type) (field automatically set to "1") - month(uint): Time of most recent whale detection. UTC month 1..12 - day(uint): Time of most recent whale detection. UTC day of the month 1..31 - hour(uint): Time of most recent whale detection. UTC hours 0..23 - min(uint): Time of most recent whale detection. UTC minutes - sec(uint): Time of most recent whale detection. UTC seconds - stationid(aisstr6): Identifier of the station that detected the whale. (e.g. which buoy) - longitude(decimal): Center of the detection zone. East West location - latitude(decimal): Center of the detection zone. North South location - timetoexpire(uint): Seconds from the detection time until the notice expires - radius(uint): Distance from center of detection zone (lat/lon above) @type bv: BitVector @param bv: Bits defining a message @param validate: Set to true to cause checking to occur. Runs slower. FIX: not implemented. @rtype: dict @return: params ''' #Would be nice to check the bit count here.. #if validate: # assert (len(bv)==FIX: SOME NUMBER) r = {} r['MessageID'] = 8 r['RepeatIndicator'] = int(bv[6:8]) r['UserID'] = int(bv[8:38]) r['Spare'] = 0 r['dac'] = 366 r['fid'] = 63 r['efid'] = 1 r['month'] = int(bv[68:72]) r['day'] = int(bv[72:77]) r['hour'] = int(bv[77:82]) r['min'] = int(bv[82:88]) r['sec'] = int(bv[88:94]) r['stationid'] = aisstring.decode(bv[94:136]) r['longitude'] = Decimal(binary.signedIntFromBV( bv[136:164])) / Decimal('600000') r['latitude'] = Decimal(binary.signedIntFromBV( bv[164:191])) / Decimal('600000') r['timetoexpire'] = int(bv[191:207]) r['radius'] = int(bv[207:223]) return r
def filter_file(infile, outfile, polygonWKT, verbose=False): ''' For messages 1,2, and 3, see if the message is within the bounding box and send it to outfile if it is. Polygon should look something like this... 'POLYGON ((-1.0 50.5, -0.5 51.2, 0.3 50.9, -1 50.5))' param polygon: bounding region for the query type polygon: WKT polygon string ''' poly = Geometry.fromWKT(polygonWKT) bbox = poly.envelope() minx = bbox.minx # for speed, throw out points as soon as possible maxx = bbox.maxx miny = bbox.miny maxy = bbox.maxy if verbose: print 'minLon maxLon minLat maxLat filename' print minx, maxx, miny, maxy count = 0 linenum = 0 for line in infile: linenum += 1 if linenum % 1000 == 0: sys.stderr.write('line ' + str(linenum) + ' -- count=' + str(count) + '\n') # Trick: Only handle the first 19 characters since that contains the lon/lat txt = line.split(',')[5][:25] #print txt bv = binary.ais6tobitvec(txt) #line[5][:19] # Try to throw out points as soon as possible. Use float rather than decimal. faster?? Maybe not #lon = ais_msg_1.decodelongitude(bv) lon = binary.signedIntFromBV(bv[61:89]) / 600000.0 if lon < minx or lon > maxx: continue #print 'close1:',lon #lat = ais_msg_1.decodelatitude(bv) lat = binary.signedIntFromBV(bv[89:116]) / 600000.0 if lat < miny or lat > maxy: continue #print 'close2: POINT ('+str(lon)+' '+str(lat)+')' point = Geometry.fromWKT('POINT (' + str(lon) + ' ' + str(lat) + ')') inside = point.within(poly) if 1 == inside: outfile.write(line) count += 1 return count
def decode(bv, validate=False): '''Unpack a ChanMngmt message. Fields in params: - MessageID(uint): AIS message number. Must be 22 (field automatically set to "22") - RepeatIndicator(uint): Indicated how many times a message has been repeated - UserID(uint): Unique ship identification number (MMSI) - Spare(uint): Not used. Should be set to zero. (field automatically set to "0") - ChanA(uint): Channel number from ITU-R M.1084 Annex 4 - ChanB(uint): Channel number from ITU-R M.1084 Annex 4 - TxRxMode(uint): FIX: find the description - power(uint): FIX: put in a description - corner1_lon(decimal): north-east corner of area for assignment longitude of corner - corner1_lat(decimal): north-east corner of area for assignment latitude of corner - corner2_lon(decimal): south-west corner of area for assignment longitude of corner - corner2_lat(decimal): south-west corner of area for assignment latitude of corner - IndicatorType(uint): FIX: put in a description - ChanABandwidth(uint): FIX: put in a description - ChanBBandwidth(uint): FIX: put in a description - TransZoneSize(uint): FIX: put in a description - Spare2(uint): Not used. Should be set to zero. (field automatically set to "0") @type bv: BitVector @param bv: Bits defining a message @param validate: Set to true to cause checking to occur. Runs slower. FIX: not implemented. @rtype: dict @return: params ''' #Would be nice to check the bit count here.. #if validate: # assert (len(bv)==FIX: SOME NUMBER) r = {} r['MessageID']=22 r['RepeatIndicator']=int(bv[6:8]) r['UserID']=int(bv[8:38]) r['Spare']=0 r['ChanA']=int(bv[40:52]) r['ChanB']=int(bv[52:64]) r['TxRxMode']=int(bv[64:68]) r['power']=int(bv[68:69]) r['corner1_lon']=Decimal(binary.signedIntFromBV(bv[69:87]))/Decimal('600') r['corner1_lat']=Decimal(binary.signedIntFromBV(bv[87:104]))/Decimal('600') r['corner2_lon']=Decimal(binary.signedIntFromBV(bv[104:122]))/Decimal('600') r['corner2_lat']=Decimal(binary.signedIntFromBV(bv[122:139]))/Decimal('600') r['IndicatorType']=int(bv[139:140]) r['ChanABandwidth']=int(bv[140:141]) r['ChanBBandwidth']=int(bv[141:142]) r['TransZoneSize']=int(bv[142:145]) r['Spare2']=0 return r
def decode(bv, validate=False): '''Unpack a whalenotice message. Fields in params: - MessageID(uint): AIS message number. Must be 8 (field automatically set to "8") - RepeatIndicator(uint): Indicated how many times a message has been repeated - UserID(uint): Unique ship identification number (MMSI) - Spare(uint): Reserved for definition by a regional authority. (field automatically set to "0") - dac(uint): Designated Area Code - 366 for the United States (field automatically set to "366") - fid(uint): Functional IDentifier - 63 for the Whale Notice (field automatically set to "63") - efid(uint): Extended Functional IDentifier. 1 for the Whale Notice (dac+fid+efid defines the exact message type) (field automatically set to "1") - month(uint): Time of most recent whale detection. UTC month 1..12 - day(uint): Time of most recent whale detection. UTC day of the month 1..31 - hour(uint): Time of most recent whale detection. UTC hours 0..23 - min(uint): Time of most recent whale detection. UTC minutes - sec(uint): Time of most recent whale detection. UTC seconds - stationid(aisstr6): Identifier of the station that detected the whale. (e.g. which buoy) - longitude(decimal): Center of the detection zone. East West location - latitude(decimal): Center of the detection zone. North South location - timetoexpire(uint): Seconds from the detection time until the notice expires - radius(uint): Distance from center of detection zone (lat/lon above) @type bv: BitVector @param bv: Bits defining a message @param validate: Set to true to cause checking to occur. Runs slower. FIX: not implemented. @rtype: dict @return: params ''' #Would be nice to check the bit count here.. #if validate: # assert (len(bv)==FIX: SOME NUMBER) r = {} r['MessageID']=8 r['RepeatIndicator']=int(bv[6:8]) r['UserID']=int(bv[8:38]) r['Spare']=0 r['dac']=366 r['fid']=63 r['efid']=1 r['month']=int(bv[68:72]) r['day']=int(bv[72:77]) r['hour']=int(bv[77:82]) r['min']=int(bv[82:88]) r['sec']=int(bv[88:94]) r['stationid']=aisstring.decode(bv[94:136]) r['longitude']=Decimal(binary.signedIntFromBV(bv[136:164]))/Decimal('600000') r['latitude']=Decimal(binary.signedIntFromBV(bv[164:191]))/Decimal('600000') r['timetoexpire']=int(bv[191:207]) r['radius']=int(bv[207:223]) return r
def decode(bv, validate=False): """Unpack a bsreport message. Fields in params: - MessageID(uint): AIS message number. Must be 4 (field automatically set to "4") - RepeatIndicator(uint): Indicated how many times a message has been repeated - UserID(uint): Unique ship identification number (MMSI) - Time_year(uint): Current time stamp year 1-9999 - Time_month(uint): Current time stamp month 1..12 - Time_day(uint): Current time stamp day of the month 1..31 - Time_hour(uint): Current time stamp UTC hours 0..23 - Time_min(uint): Current time stamp minutes - Time_sec(uint): Current time stamp seconds - PositionAccuracy(uint): Accuracy of positioning fixes - Position_longitude(decimal): Location of base station East West location - Position_latitude(decimal): Location of base station North South location - fixtype(uint): Method used for positioning - Spare(uint): Not used. Should be set to zero. (field automatically set to "0") - RAIM(bool): Receiver autonomous integrity monitoring flag - state_syncstate(uint): Communications State - SOTDMA Sycronization state - state_slottimeout(uint): Communications State - SOTDMA Frames remaining until a new slot is selected - state_slotoffset(uint): Communications State - SOTDMA In what slot will the next transmission occur. BROKEN @type bv: BitVector @param bv: Bits defining a message @param validate: Set to true to cause checking to occur. Runs slower. FIX: not implemented. @rtype: dict @return: params """ r = {} r['MessageID'] = 4 r['RepeatIndicator'] = int(bv[6:8]) r['UserID'] = int(bv[8:38]) r['Time_year'] = int(bv[38:52]) r['Time_month'] = int(bv[52:56]) r['Time_day'] = int(bv[56:61]) r['Time_hour'] = int(bv[61:66]) r['Time_min'] = int(bv[66:72]) r['Time_sec'] = int(bv[72:78]) r['PositionAccuracy'] = int(bv[78:79]) r['Position_longitude'] = Decimal(binary.signedIntFromBV( bv[79:107])) / Decimal('600000') r['Position_latitude'] = Decimal(binary.signedIntFromBV( bv[107:134])) / Decimal('600000') r['fixtype'] = int(bv[134:138]) r['Spare'] = 0 r['RAIM'] = bool(int(bv[148:149])) r.update(commstate.sotdma_parse_bits(bv[-19:])) return r
def decode(bv, validate=False): '''Unpack a sls_weatherreport message. Fields in params: - time_month(uint): Time tag of measurement month 1..12 - time_day(uint): Time tag of measurement day of the month 1..31 - time_hour(uint): Time tag of measurement UTC hours 0..23 - time_min(uint): Time tag of measurement minutes - stationid(aisstr6): Character identifier of the station - pos_longitude(decimal): Location of measurement East West location - pos_latitude(decimal): Location of measurement North South location - speed(udecimal): Average wind speed - gust(udecimal): Wind gust - direction(uint): Wind direction - atmpressure(udecimal): Atmospheric pressure - airtemp(decimal): Air temperature - dewpoint(decimal): Dew Point - visibility(udecimal): Visibility - watertemp(decimal): Water Temperature - reserved(uint): Reserved bits for future use (field automatically set to "0") @type bv: BitVector @param bv: Bits defining a message @param validate: Set to true to cause checking to occur. Runs slower. FIX: not implemented. @rtype: dict @return: params ''' #Would be nice to check the bit count here.. #if validate: # assert (len(bv)==FIX: SOME NUMBER) r = {} r['time_month']=int(bv[0:4]) r['time_day']=int(bv[4:9]) r['time_hour']=int(bv[9:14]) r['time_min']=int(bv[14:20]) r['stationid']=aisstring.decode(bv[20:62]) r['pos_longitude']=Decimal(binary.signedIntFromBV(bv[62:87]))/Decimal('60000') r['pos_latitude']=Decimal(binary.signedIntFromBV(bv[87:111]))/Decimal('60000') r['speed']=Decimal(int(bv[111:121]))/Decimal('10') r['gust']=Decimal(int(bv[121:131]))/Decimal('10') r['direction']=int(bv[131:140]) r['atmpressure']=Decimal(int(bv[140:154]))/Decimal('10') r['airtemp']=Decimal(binary.signedIntFromBV(bv[154:164]))/Decimal('10') r['dewpoint']=Decimal(binary.signedIntFromBV(bv[164:174]))/Decimal('10') r['visibility']=Decimal(int(bv[174:182]))/Decimal('10') r['watertemp']=Decimal(binary.signedIntFromBV(bv[182:192]))/Decimal('10') r['reserved']=0 return r
def decode(bv, validate=False): '''Unpack a whalenotice message. Fields in params: - MessageID(uint): AIS message number. Must be 8 (field automatically set to "8") - RepeatIndicator(uint): Indicated how many times a message has been repeated - UserID(uint): Unique ship identification number (MMSI) - Spare(uint): Reserved for definition by a regional authority. (field automatically set to "0") - dac(uint): Designated Area Code - 366 for the United States (field automatically set to "366") - fid(uint): Functional IDentifier - 63 for the Whale Notice (field automatically set to "63") - day(uint): Time of most recent whale detection. UTC day of the month 1..31 - hour(uint): Time of most recent whale detection. UTC hours 0..23 - min(uint): Time of most recent whale detection. UTC minutes - stationid(uint): Identifier of the station that recorded the whale. Usually a number. - longitude(decimal): Center of the detection zone. East West location - latitude(decimal): Center of the detection zone. North South location - timetoexpire(uint): Minutes from the detection time until the notice expires - radius(uint): Distance from center of detection zone (lat/lon above) @type bv: BitVector @param bv: Bits defining a message @param validate: Set to true to cause checking to occur. Runs slower. FIX: not implemented. @rtype: dict @return: params ''' #Would be nice to check the bit count here.. #if validate: # assert (len(bv)==FIX: SOME NUMBER) r = {} r['MessageID'] = 8 r['RepeatIndicator'] = int(bv[6:8]) r['UserID'] = int(bv[8:38]) r['Spare'] = 0 r['dac'] = 366 r['fid'] = 63 r['day'] = int(bv[56:61]) r['hour'] = int(bv[61:66]) r['min'] = int(bv[66:72]) r['stationid'] = int(bv[72:80]) r['longitude'] = Decimal(binary.signedIntFromBV( bv[80:108])) / Decimal('600000') r['latitude'] = Decimal(binary.signedIntFromBV( bv[108:135])) / Decimal('600000') r['timetoexpire'] = int(bv[135:151]) r['radius'] = int(bv[151:167]) return r
def decode(bv, validate=False): '''Unpack a timed_circular_notice message. Fields in params: - MessageID(uint): AIS message number. Must be 8 (field automatically set to "8") - RepeatIndicator(uint): Indicated how many times a message has been repeated - UserID(uint): Unique ship identification number (MMSI) - Spare(uint): Reserved for definition by a regional authority. (field automatically set to "0") - dac(uint): Designated Area Code - 366 for the United States (field automatically set to "366") - fid(uint): Functional IDentifier - 63 (field automatically set to "63") - month(uint): Start time of most recent notice UTC month - day(uint): Start time of most recent notice UTC day of the month 1..31 - hour(uint): Start time of most recent notice UTC hours 0..23 - min(uint): Start time of most recent notice UTC minutes - longitude(decimal): Center of the area/zone East West location - latitude(decimal): Center of the area/zone North South location - timetoexpire(uint): Minutes from the start time until the notice expires. Max is aprox 23 days - radius(udecimal): Distance from center of detection zone (lat/lon above). Distance in increments of 10 meters - areatype(uint): What does this circular area represent @type bv: BitVector @param bv: Bits defining a message @param validate: Set to true to cause checking to occur. Runs slower. FIX: not implemented. @rtype: dict @return: params ''' #Would be nice to check the bit count here.. #if validate: # assert (len(bv)==FIX: SOME NUMBER) r = {} r['MessageID']=8 r['RepeatIndicator']=int(bv[6:8]) r['UserID']=int(bv[8:38]) r['Spare']=0 r['dac']=366 r['fid']=63 r['month']=int(bv[56:60]) r['day']=int(bv[60:65]) r['hour']=int(bv[65:70]) r['min']=int(bv[70:76]) r['longitude']=Decimal(binary.signedIntFromBV(bv[76:104]))/Decimal('600000') r['latitude']=Decimal(binary.signedIntFromBV(bv[104:131]))/Decimal('600000') r['timetoexpire']=int(bv[131:146]) r['radius']=Decimal(int(bv[146:160]))/Decimal('0.1') r['areatype']=int(bv[160:168]) return r
def decode(bv, validate=False): '''Unpack a whalenotice message. Fields in params: - MessageID(uint): AIS message number. Must be 8 (field automatically set to "8") - RepeatIndicator(uint): Indicated how many times a message has been repeated - UserID(uint): Unique ship identification number (MMSI) - Spare(uint): Reserved for definition by a regional authority. (field automatically set to "0") - dac(uint): Designated Area Code - 366 for the United States (field automatically set to "366") - fid(uint): Functional IDentifier - 63 for the Whale Notice (field automatically set to "63") - day(uint): Time of most recent whale detection. UTC day of the month 1..31 - hour(uint): Time of most recent whale detection. UTC hours 0..23 - min(uint): Time of most recent whale detection. UTC minutes - stationid(uint): Identifier of the station that recorded the whale. Usually a number. - longitude(decimal): Center of the detection zone. East West location - latitude(decimal): Center of the detection zone. North South location - timetoexpire(uint): Minutes from the detection time until the notice expires - radius(uint): Distance from center of detection zone (lat/lon above) @type bv: BitVector @param bv: Bits defining a message @param validate: Set to true to cause checking to occur. Runs slower. FIX: not implemented. @rtype: dict @return: params ''' #Would be nice to check the bit count here.. #if validate: # assert (len(bv)==FIX: SOME NUMBER) r = {} r['MessageID']=8 r['RepeatIndicator']=int(bv[6:8]) r['UserID']=int(bv[8:38]) r['Spare']=0 r['dac']=366 r['fid']=63 r['day']=int(bv[56:61]) r['hour']=int(bv[61:66]) r['min']=int(bv[66:72]) r['stationid']=int(bv[72:80]) r['longitude']=Decimal(binary.signedIntFromBV(bv[80:108]))/Decimal('600000') r['latitude']=Decimal(binary.signedIntFromBV(bv[108:135]))/Decimal('600000') r['timetoexpire']=int(bv[135:151]) r['radius']=int(bv[151:167]) return r
def decode(bv, validate=False): r = {} r['MessageID']=int(bv[:6]) r['RepeatIndicator']=int(bv[6:8]) r['UserID']=int(bv[8:38]) r['NavigationStatus']=int(bv[38:42]) r['ROT']=binary.signedIntFromBV(bv[42:50]) r['SOG']=Decimal(int(bv[50:60]))/Decimal('10') r['PositionAccuracy']=int(bv[60:61]) r['longitude']=Decimal(binary.signedIntFromBV(bv[61:89]))/Decimal('600000') r['latitude']=Decimal(binary.signedIntFromBV(bv[89:116]))/Decimal('600000') r['COG']=Decimal(int(bv[116:128]))/Decimal('10') r['TrueHeading']=int(bv[128:137]) r['TimeStamp']=int(bv[137:143]) r['RegionalReserved']=0 r['Spare']=0 r['RAIM']=bool(int(bv[148:149])) r.update(commstate.sotdma_parse_bits(bv[-19:])) return r
def decode(bv, validate=False): r = {} r['MessageID'] = int(bv[:6]) r['RepeatIndicator'] = int(bv[6:8]) r['UserID'] = int(bv[8:38]) r['NavigationStatus'] = int(bv[38:42]) r['ROT'] = binary.signedIntFromBV(bv[42:50]) r['SOG'] = Decimal(int(bv[50:60])) / Decimal('10') r['PositionAccuracy'] = int(bv[60:61]) r['longitude'] = Decimal(binary.signedIntFromBV( bv[61:89])) / Decimal('600000') r['latitude'] = Decimal(binary.signedIntFromBV( bv[89:116])) / Decimal('600000') r['COG'] = Decimal(int(bv[116:128])) / Decimal('10') r['TrueHeading'] = int(bv[128:137]) r['TimeStamp'] = int(bv[137:143]) r['RegionalReserved'] = 0 r['Spare'] = 0 r['RAIM'] = bool(int(bv[148:149])) r.update(commstate.sotdma_parse_bits(bv[-19:])) return r
def decode(bv, validate=False): '''Unpack a alltypesmsg message. Fields in params: - dac(uint): Designated Area Code (field automatically set to "366") - reqDecimal(decimal): required decimal value... FIX: scale or no? (field automatically set to "122") - unavail_uint(uint): Unavailable unsigned integer - anUInt(uint): NO unavailable unsigned integer - anInt(int): NO unavailable signed integer - aBool(bool): Simple bool - aStr(aisstr6): An ais string of 5 characters - anUDecimal(udecimal): An unsigned decimal. Allow smaller numbers - aDecimal(decimal): A decimal - aFloat(float): An IEEE floating point number @type bv: BitVector @param bv: Bits defining a message @param validate: Set to true to cause checking to occur. Runs slower. FIX: not implemented. @rtype: dict @return: params ''' #Would be nice to check the bit count here.. #if validate: # assert (len(bv)==FIX: SOME NUMBER) r = {} r['dac']=366 r['reqDecimal']=122/Decimal('1') r['unavail_uint']=int(bv[24:26]) r['anUInt']=int(bv[26:28]) r['anInt']=binary.signedIntFromBV(bv[28:31]) r['aBool']=bool(int(bv[31:32])) r['aStr']=aisstring.decode(bv[32:62]) r['anUDecimal']=Decimal(int(bv[62:78]))/Decimal('10') r['aDecimal']=Decimal(binary.signedIntFromBV(bv[78:94]))/Decimal('10') r['aFloat']=binary.bitvec2float(bv[94:126]) return r
def decode(bv, validate=False): '''Unpack a alltypesmsg message. Fields in params: - dac(uint): Designated Area Code (field automatically set to "366") - reqDecimal(decimal): required decimal value... FIX: scale or no? (field automatically set to "122") - unavail_uint(uint): Unavailable unsigned integer - anUInt(uint): NO unavailable unsigned integer - anInt(int): NO unavailable signed integer - aBool(bool): Simple bool - aStr(aisstr6): An ais string of 5 characters - anUDecimal(udecimal): An unsigned decimal. Allow smaller numbers - aDecimal(decimal): A decimal - aFloat(float): An IEEE floating point number @type bv: BitVector @param bv: Bits defining a message @param validate: Set to true to cause checking to occur. Runs slower. FIX: not implemented. @rtype: dict @return: params ''' #Would be nice to check the bit count here.. #if validate: # assert (len(bv)==FIX: SOME NUMBER) r = {} r['dac'] = 366 r['reqDecimal'] = 122 / Decimal('1') r['unavail_uint'] = int(bv[24:26]) r['anUInt'] = int(bv[26:28]) r['anInt'] = binary.signedIntFromBV(bv[28:31]) r['aBool'] = bool(int(bv[31:32])) r['aStr'] = aisstring.decode(bv[32:62]) r['anUDecimal'] = Decimal(int(bv[62:78])) / Decimal('10') r['aDecimal'] = Decimal(binary.signedIntFromBV(bv[78:94])) / Decimal('10') r['aFloat'] = binary.bitvec2float(bv[94:126]) return r
def decode(bv, validate=False): """Unpack a waterlevel message. Fields in params: - MessageID(uint): AIS message number. Must be 8 (field automatically set to "8") - RepeatIndicator(uint): Indicated how many times a message has been repeated - UserID(uint): Unique ship identification number (MMSI) - Spare(uint): Reserved for definition by a regional authority. (field automatically set to "0") - dac(uint): Designated Area Code (field automatically set to "366") - fid(uint): Functional Identifier (field automatically set to "63") - month(uint): Time the measurement represents month 1..12 - day(uint): Time the measurement represents day of the month 1..31 - hour(uint): Time the measurement represents UTC hours 0..23 - min(uint): Time the measurement represents minutes - stationid(aisstr6): Character identifier of the station. Usually a number. - waterlevel(int): Water level in centimeters - datum(uint): What reference datum applies to the value - sigma(uint): Standard deviation of 1 second samples used to compute the water level height. FIX: is this the correct description of sigma? - source(uint): How the water level was derived @type bv: BitVector @param bv: Bits defining a message @param validate: Set to true to cause checking to occur. Runs slower. FIX: not implemented. @rtype: dict @return: params """ # Would be nice to check the bit count here.. # if validate: # assert (len(bv)==FIX: SOME NUMBER) r = {} r["MessageID"] = 8 r["RepeatIndicator"] = int(bv[6:8]) r["UserID"] = int(bv[8:38]) r["Spare"] = 0 r["dac"] = 366 r["fid"] = 63 r["month"] = int(bv[56:60]) r["day"] = int(bv[60:65]) r["hour"] = int(bv[65:70]) r["min"] = int(bv[70:76]) r["stationid"] = aisstring.decode(bv[76:118]) r["waterlevel"] = binary.signedIntFromBV(bv[118:134]) r["datum"] = int(bv[134:139]) r["sigma"] = int(bv[139:146]) r["source"] = int(bv[146:149]) return r
def decode(bv, validate=False): '''Unpack a waterlevel message. Fields in params: - MessageID(uint): AIS message number. Must be 8 (field automatically set to "8") - RepeatIndicator(uint): Indicated how many times a message has been repeated - UserID(uint): Unique ship identification number (MMSI) - Spare(uint): Reserved for definition by a regional authority. (field automatically set to "0") - dac(uint): Designated Area Code (field automatically set to "366") - fid(uint): Functional Identifier (field automatically set to "63") - month(uint): Time the measurement represents month 1..12 - day(uint): Time the measurement represents day of the month 1..31 - hour(uint): Time the measurement represents UTC hours 0..23 - min(uint): Time the measurement represents minutes - stationid(aisstr6): Character identifier of the station. Usually a number. - waterlevel(int): Water level in centimeters - datum(uint): What reference datum applies to the value - sigma(uint): Standard deviation of 1 second samples used to compute the water level height. FIX: is this the correct description of sigma? - source(uint): How the water level was derived @type bv: BitVector @param bv: Bits defining a message @param validate: Set to true to cause checking to occur. Runs slower. FIX: not implemented. @rtype: dict @return: params ''' #Would be nice to check the bit count here.. #if validate: # assert (len(bv)==FIX: SOME NUMBER) r = {} r['MessageID'] = 8 r['RepeatIndicator'] = int(bv[6:8]) r['UserID'] = int(bv[8:38]) r['Spare'] = 0 r['dac'] = 366 r['fid'] = 63 r['month'] = int(bv[56:60]) r['day'] = int(bv[60:65]) r['hour'] = int(bv[65:70]) r['min'] = int(bv[70:76]) r['stationid'] = aisstring.decode(bv[76:118]) r['waterlevel'] = binary.signedIntFromBV(bv[118:134]) r['datum'] = int(bv[134:139]) r['sigma'] = int(bv[139:146]) r['source'] = int(bv[146:149]) return r
def decodewatertemp(bv, validate=False): return Decimal(binary.signedIntFromBV(bv[182:192])) / Decimal('10')
def decodePosition_longitude(bv, validate=False): return Decimal(binary.signedIntFromBV(bv[79:107]))/Decimal('600000')
def decodepos_latitude(bv, validate=False): return Decimal(binary.signedIntFromBV(bv[87:111]))/Decimal('60000')
def decodeanInt(bv, validate=False): return binary.signedIntFromBV(bv[28:31])
def decodedewpoint(bv, validate=False): return Decimal(binary.signedIntFromBV(bv[164:174]))/Decimal('10')
def decodelatitude(bv, validate=False): return Decimal(binary.signedIntFromBV(bv[104:131]))/Decimal('600000')
def int_dec(bv): '''@rtype: int''' return int(binary.signedIntFromBV(bv))
def decodecorner2_lat(bv, validate=False): return Decimal(binary.signedIntFromBV(bv[122:139]))/Decimal('600')
def float_dec(bv): '''@rtype: float''' return float(binary.signedIntFromBV(bv))
def decodecorner1_lat(bv, validate=False): return Decimal(binary.signedIntFromBV(bv[87:104]))/Decimal('600')
def decodecorner2_lon(bv, validate=False): return Decimal(binary.signedIntFromBV(bv[104:122]))/Decimal('600')
def decodey(bv, validate=False): return Decimal(binary.signedIntFromBV(bv[58:75])) / Decimal('600')
def decodeaDecimal(bv, validate=False): return Decimal(binary.signedIntFromBV(bv[78:94]))/Decimal('10')
def decodePosition_latitude(bv, validate=False): return Decimal(binary.signedIntFromBV(bv[107:134]))/Decimal('600000')
def decodelongitude(bv, validate=False): return Decimal(binary.signedIntFromBV(bv[76:104]))/Decimal('600000')
def decimal_dec(bv): '''@rtype: Decimal''' return Decimal(binary.signedIntFromBV(bv))
def decodewaterlevel(bv, validate=False): return binary.signedIntFromBV(bv[112:128])
def decodewatertemp(bv, validate=False): return Decimal(binary.signedIntFromBV(bv[182:192]))/Decimal('10')
def decodex(bv, validate=False): return Decimal(binary.signedIntFromBV(bv[40:58])) / Decimal('600')
def decodeaDecimal(bv, validate=False): return Decimal(binary.signedIntFromBV(bv[78:94])) / Decimal('10')
def decodepos_longitude(bv, validate=False): return Decimal(binary.signedIntFromBV(bv[62:87]))/Decimal('60000')
def build_dist_database(database_filename, log_files, verbose=False): cx = sqlite3.connect(database_filename) print 'WARNING: not saving the station name' cx.execute(''' CREATE TABLE IF NOT EXISTS distance ( -- Save space, no key -- ts INTEGER, -- Save more space julian_day INTEGER, -- x REAL, -- y REAL, dist_km REAL --, --station VARCHAR(15) ); ''') cu = cx.cursor() counts = {'nogps': 0} for filename in log_files: if verbose: print 'file:',filename sys.stdout.flush() for line_num, line in enumerate(file(filename)): if 'AIVDM,1,1' not in line: continue match = uscg_ais_nmea_regex.search(line).groupdict() message_id = match['body'][0] # First letter is the message type if message_id not in ('1','2','3'): continue if len(match['body']) != 28: # 6 bits per character raise AisErrorBadNumBits('expected 168, got %d' % len(match['body']) / 6) bits = binary.ais6tobitvec(match['body'][:20]) # Don't need any of the other bits, so do not waste time x = binary.signedIntFromBV(bits[61:89]) / 600000. y = binary.signedIntFromBV(bits[89:116]) / 600000. if x > 180 or y > 90: counts['nogps'] += 1 continue station = match['station'] julian_day = int(datetime.datetime.utcfromtimestamp(int(match['timeStamp'])).strftime('%j')) d_km = dist_utm_km( (x,y), station_locations[station] ) #cu.execute('INSERT INTO distance VALUES (:julian_day, :x, :y, :dist_km, :station)', #{'julian_day': julian_day, 'x':x, 'y':y, 'dist_km': d_km, 'station':station} ) #cu.execute('INSERT INTO distance VALUES (:julian_day, :x, :y, :dist_km)', # {'julian_day': julian_day, 'x':x, 'y':y, 'dist_km': d_km, } ) cu.execute('INSERT INTO distance VALUES (:julian_day, :dist_km)', {'julian_day': julian_day, 'dist_km': d_km, } ) if line_num % 10000 == 9999: cx.commit() cx.commit() if False: print 'Creating indexes' try: cx.execute('CREATE INDEX idx_dist_day ON distance(julian_day);') cx.execute('CREATE INDEX idx_dist_dist ON distance(dist_km);') #cx.execute('CREATE INDEX idx_dist_station ON distance(station);') cx.commit() except sqlite3.OperationalError: print 'Appears indexes were already created' return cx, counts
def build_dist_database(database_filename, log_files, verbose=False): cx = sqlite3.connect(database_filename) print 'WARNING: not saving the station name' cx.execute(''' CREATE TABLE IF NOT EXISTS distance ( -- Save space, no key -- ts INTEGER, -- Save more space julian_day INTEGER, -- x REAL, -- y REAL, dist_km REAL --, --station VARCHAR(15) ); ''') cu = cx.cursor() counts = {'nogps': 0} for filename in log_files: if verbose: print 'file:', filename sys.stdout.flush() for line_num, line in enumerate(file(filename)): if 'AIVDM,1,1' not in line: continue match = uscg_ais_nmea_regex.search(line).groupdict() message_id = match['body'][0] # First letter is the message type if message_id not in ('1', '2', '3'): continue if len(match['body']) != 28: # 6 bits per character raise AisErrorBadNumBits('expected 168, got %d' % len(match['body']) / 6) bits = binary.ais6tobitvec( match['body'][:20] ) # Don't need any of the other bits, so do not waste time x = binary.signedIntFromBV(bits[61:89]) / 600000. y = binary.signedIntFromBV(bits[89:116]) / 600000. if x > 180 or y > 90: counts['nogps'] += 1 continue station = match['station'] julian_day = int( datetime.datetime.utcfromtimestamp(int( match['timeStamp'])).strftime('%j')) d_km = dist_utm_km((x, y), station_locations[station]) #cu.execute('INSERT INTO distance VALUES (:julian_day, :x, :y, :dist_km, :station)', #{'julian_day': julian_day, 'x':x, 'y':y, 'dist_km': d_km, 'station':station} ) #cu.execute('INSERT INTO distance VALUES (:julian_day, :x, :y, :dist_km)', # {'julian_day': julian_day, 'x':x, 'y':y, 'dist_km': d_km, } ) cu.execute('INSERT INTO distance VALUES (:julian_day, :dist_km)', { 'julian_day': julian_day, 'dist_km': d_km, }) if line_num % 10000 == 9999: cx.commit() cx.commit() if False: print 'Creating indexes' try: cx.execute('CREATE INDEX idx_dist_day ON distance(julian_day);') cx.execute('CREATE INDEX idx_dist_dist ON distance(dist_km);') #cx.execute('CREATE INDEX idx_dist_station ON distance(station);') cx.commit() except sqlite3.OperationalError: print 'Appears indexes were already created' return cx, counts
def decodecorner1_lon(bv, validate=False): return Decimal(binary.signedIntFromBV(bv[69:87]))/Decimal('600')