【问题标题】:Building AIS Messages Decoder构建 AIS 消息解码器
【发布时间】:2015-02-19 04:41:59
【问题描述】:

我曾经使用 theis 包 (Python) https://github.com/schwehr/noaadata/tree/master/ais 解码 AIS 消息,直到我开始获取新格式的消息。 您可能知道,AIS 消息主要有两种类型。一部分(一条消息)或两部分(多条消息)。消息#5 总是分为两部分。示例:

!AIVDM,2,1,1,A,55?MbV02;H;s<HtKR20EHE:address@hidden@Dn2222222216L961O5Gf0NSQEp6ClRp8,0*1C
!AIVDM,2,2,1,A,88888888880,2*25

我曾经使用以下代码对此进行解码:

   nmeamsg = fields.split(',')
   if nmeamsg[0] != '!AIVDM': 
    return
   total = eval(nmeamsg[1])
   part = eval(nmeamsg[2])
   aismsg = nmeamsg[5]
   nmeastring = string.join(nmeamsg[0:-1],',')


   bv = binary.ais6tobitvec(aismsg)
   msgnum = int(bv[0:6])

--

elif (total>1):
     # Multi Slot Messages: 5,6,8,12,14,17,19,20?,21,24,26
     global multimsg
     if total==2:
       if msgnum==5:
         if nmeastring.count('!AIVDM')==2 and len(nmeamsg)==13: # make sure there are two parts concatenated together
           aismsg = nmeamsg[5]+nmeamsg[11]
           bv = binary.ais6tobitvec(aismsg)    

           msg5 = ais_msg_5.decode(bv)
           print "message5 :",msg5
           return msg5

现在我得到了一种新格式的消息:

!SAVDM,2,1,7,A,55@0hd01sq`pQ3W?O81L5@E:1=0U8U@000000016000006H0004m8523k@Dp,0*2A,1410825672
!SAVDM,2,2,7,A,4hC`2U@C`40,2*76,1410825672,1410825673

注意。最后一个索引处的数字是纪元格式的时间

我尝试调整我的代码来解码这种新格式。我成功地用一个部分解码消息。我的问题是多消息类型。

   nmeamsg = fields.split(',')
   if nmeamsg[0] != '!AIVDM' and nmeamsg[0] != '!SAVDM': 
    return
   total = eval(nmeamsg[1])
   part = eval(nmeamsg[2])
   aismsg = nmeamsg[5]
   nmeastring = string.join(nmeamsg[0:-1],',')
   dbtimestring = time.strftime('%Y-%m-%d %H:%M:%S', time.localtime(float(nmeamsg[7])))

   bv = binary.ais6tobitvec(aismsg)
   msgnum = int(bv[0:6])

解码器不能将两条线合二为一。所以解码失败,因为 message#5 应该包含两个字符串而不是一个。我得到的错误是在这些行中:

if nmeastring.count('!SAVDM')==2 and len(nmeamsg)==13: 
aismsg = nmeamsg[5]+nmeamsg[11]

其中len(nmeamsg) 始终为 8(第二行),nmeastring.count('!SAVDM') 始终为 1

我希望我清楚地解释了这一点,以便有人可以让我知道我在这里缺少什么。

更新

好的,我想我找到了原因。我将消息从文件逐行传递到脚本:

for line in file:
    i=i+1

    try:
        doais(line)

message#5 应该作为两行传递。关于如何实现这一点的任何想法?

更新

我是通过稍微修改代码来做到的:

for line in file:
    i=i+1

try:
        nmeamsg = line.split(',')
        aismsg = nmeamsg[5]
        bv = binary.ais6tobitvec(aismsg)
        msgnum = int(bv[0:6])
        print msgnum
        if nmeamsg[0] != '!AIVDM' and nmeamsg[0] != '!SAVDM': 
         print "wrong format"
        total = eval(nmeamsg[1])
        if total == 1:
         dbtimestring = time.strftime('%Y-%m-%d %H:%M:%S', time.localtime(float(nmeamsg[8])))
         doais(line,msgnum,dbtimestring,aismsg)
        if total == 2: #Multi-line messages
         lines= line+file.next()
         nmeamsg = lines.split(',')
         dbtimestring = time.strftime('%Y-%m-%d %H:%M:%S', time.localtime(float(nmeamsg[15])))
         aismsg = nmeamsg[5]+nmeamsg[12]
         doais(lines,msgnum,dbtimestring,aismsg)

【问题讨论】:

标签: python decode nmea ais


【解决方案1】:

如果您使用 Ruby,我可以推荐我写的 NMEA and AIS decoder ruby gemavailable on github。它基于由 Kurt 的一位同事维护的 the unofficial AIS spec at catb.org

它处理多部分消息的组合,从流中读取,并支持大量 NMEA 和 AIS 消息。目前正在开发解码 AIS 消息 6 和 8 的 50 个二进制子类型。

处理您发布的非标准行:

!SAVDM,2,1,7,A,55@0hd01sq`pQ3W?O81L5@E:1=0U8U@000000016000006H0004m8523k@Dp,0*2A,1410825672
!SAVDM,2,2,7,A,4hC`2U@C`40,2*76,1410825672,1410825673

有必要在校验和之后添加一个接受字段的新解析规则,但除此之外它应该会顺利进行。换句话说,你会复制the parser line here

    | BANG DATA CSUM  { result = NMEAPlus::AISMessageFactory.create(val[0], val[1], val[2]) }

并且有类似的东西

    | BANG DATA CSUM COMMA DATA { result = NMEAPlus::AISMessageFactory.create(val[0], val[1], val[2], val[4]) }

您如何处理这些额外的时间戳?几乎看起来它们已经被任何正在执行日志记录的软件附加,而不是成为实际消息的一部分。

【讨论】:

    【解决方案2】:

    请注意,noaadata 是我的旧研究代码。 libais 是我的生产库,用于 NOAA 的 ERMA 和 WhaleAlert。

    我通常将解码过程分为两遍。首先加入多行消息。我将此称为规范化(ais_normalize.py)。您在此步骤中有几个问题。首先,两个组成行在第二个字符串的右侧具有不同的时间戳。根据 USCG 旧的元数据标准,最后一个很重要。所以我的代码会假设这两行是不相关的。其次,您没有必填的站号字段。

    您从 SAVDM 中的何处获取 SA?什么设备(NMEA 词汇中的“说话者”)正在接收这些消息?

    【讨论】:

    • 感谢您指出您的新图书馆!我看到从 Python 切换到 C++。请问为什么?
    • 不幸的是,我对数据资源一无所知。我在日志文件中获取这些数据。我设法将这两行作为一条附加并生成多行消息。我更新了我的帖子并添加了代码。你怎么看?
    • noaadata + bitvector 非常慢。是的,它很灵活,非常适合研究和调试。然而,具有 c++ 核心和瘦 python 包装器的 libais 可能快 2 个数量级,并且 c++ 端可以嵌入到 java、c++ 和目标 c 应用程序(例如 android 和 ios 应用程序)中。
    • 生成呢?有人知道 Python AIS NMEA 生成器吗?
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-10-13
    • 2022-06-10
    • 2014-02-12
    • 1970-01-01
    • 1970-01-01
    • 2013-03-10
    相关资源
    最近更新 更多