首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >NMEA AIS发生器

NMEA AIS发生器
EN

Code Review用户
提问于 2015-04-19 14:57:23
回答 1查看 1.2K关注 0票数 2

我想做一些NMEA AIS数据发生器。现在我编写了这段代码,它运行得很好(完成了我所需要的),但我确信它是坏的,需要优化。

我看到的问题是,我通过字符串变量将整数转换为6位字二进制,我确信它根本不是最优的。

代码语言:javascript
复制
#!/usr/bin/python

import math

CharTable =[["0", "@", "000000"], ["1", "A", "000001"], ["2", "B", "000010"], ["3", "C", "000011"], ["4", "D", "000100"], ["5", "E", "000101"],
            ["6", "F", "000110"], ["7", "G", "000111"], ["8", "H", "001000"], ["9", "I", "001001"], [":", "J", "001010"], [";", "K", "001011"],
            ["<", "L", "001100"], ["=", "M", "001101"], [">", "N", "001110"], ["?", "O", "001111"], ["@", "P", "010000"], ["A", "Q", "010001"],
            ["B", "R", "010010"], ["C", "S", "010011"], ["D", "T", "010100"], ["E", "U", "010101"], ["F", "V", "010110"], ["G", "W", "010111"],
            ["H", "X", "011000"], ["I", "Y", "011001"], ["J", "Z", "011010"], ["K", "[", "011011"], ["L", "\\", "011100"], ["M", "]", "011101"],
            ["N", "^", "011110"], ["O", "_", "011111"], ["P", " ", "100000"], ["Q", "!", "100001"], ["R", "\"", "100010"], ["S", "#", "100011"],
            ["T", "$", "100100"], ["U", "%", "100101"], ["V", "&", "100110"], ["W", "'", "100111"], ["`", "(", "101000"], ["a", ")", "101001"],
            ["b", "*", "101010"], ["c", "+", "101011"], ["d", ",", "101100"], ["e", "-", "101101"], ["f", ".", "101110"], ["g", "/", "101111"],
            ["h", "0", "110000"], ["i", "1", "110001"], ["j", "2", "110010"], ["k", "3", "110011"], ["l", "4", "110100"], ["m", "5", "110101"],
            ["n", "6", "110110"], ["o", "7", "110111"], ["p", "8", "111000"], ["q", "9", "111001"], ["r", ":", "111010"], ["s", ";", "111011"],
            ["t", "<", "111100"], ["u", "=", "111101"], ["v", ">", "111110"], ["w", "?", "111111"]]

PT = "AIVDM"
CHAN = "A"
MT = '000001'
RI = '00'
FILL = '000000'
NS = 5


def Invert(BinStr):     # Oh shit! I'm a lame programmer and can't find a function to swap bits in binary!
    return BinStr.replace("0", "A").replace("1", "0").replace("A", "1")

def convert(val,bits): # This magic function converts dec to bin in right format
    if (val < 0 ):
        val = -val
        val = (str(bin(~val)))[3:].zfill(bits)
        val = Invert (val)
    else:
        val = (str(bin(val)))[2:].zfill(bits)
    return val

def checksum(s):
    c = 0
    for ch in s:
        c ^= ord(ch)
    c = hex(c).upper()[2:]
    return c

def GenAis(PT, CHAN, MT, RI, MMSI, NS, ROT, SOG, PA, LON, LAT, COG, HDG, TS, FILL, CommState):
    # Preparing Variables
    MMSI = str((bin(MMSI)))[2:].zfill(30)
    NS = str((bin(NS)))[2:].zfill(4)
    SOG = str((bin(round(SOG*10))))[2:].zfill(10)
    LON = round(LON*600000)
    LAT = round(LAT*600000)
    COG = round(COG*10)

    # Converting Vars to bin
    LON = convert(LON,28)
    LAT = convert(LAT,27)
    HDG = convert(HDG,9)
    COG = convert(COG,12)
    ROT = convert(ROT,8)
    TS  = convert(TS,6)
    CommState = convert(CommState,19)

    MESSAGE_BIN = MT + RI + MMSI + NS + ROT + SOG + PA + LON + LAT + COG + HDG + TS + FILL + CommState
 #   print (MESSAGE_BIN)

    MESSENC = ""
    LEN = 28 #28 6-byte words = 168 bits
    P = 0
    # Starting encoding binary string to 6-byte word:
    while P <= LEN:
        TMPSTR = MESSAGE_BIN[(6*P):(6*P+6)]
        # print (TMPSTR)
        P += 1
        for PAIR in CharTable:
            if PAIR[2] == TMPSTR:
                MESSENC += PAIR[0]
#    print (MESSENC)
    MESSAIS = (PT + ',1,1,,' + CHAN + ',' + MESSENC + ',0')
    # CS = '4E'
    CS = checksum(MESSAIS)
    return ("!" + MESSAIS + '*' + CS)

# So here the program starts

MMSI = 366730000
PA = '0'
LON = -122.39253
LAT = 37.803803
HDG = 511
COG = 51.3
SOG = 20.8
ROT = 128
ACC = 0
TS = 50
CommState = 67427

print (GenAis(PT, CHAN, MT, RI, MMSI, NS, ROT, SOG, PA, LON, LAT, COG, HDG, TS, FILL, CommState))
EN

回答 1

Code Review用户

发布于 2015-04-19 16:39:45

如果你只是在寻找不同的方法来做同样的事情,下面是几个例子:

使用convertInvert格式字符串语法替代方案

代码语言:javascript
复制
def convert(val,bits):
    # format string to convert to binary, right justified, zero fill, optional width
    format_string = '{:0>' + str(bits) + 'b}'
    result = format_string.format(abs(val))
    if val < 0:
        # invert
        return ''.join('0' if c == '1' else '1' for c in result)
    else:
        return result

>>> 
>>> convert(10, 8)
'00001010'
>>> convert(-10, 8)
'11110101'
>>> 

替代checksum的方法:

代码语言:javascript
复制
import functools
def checksum1(s):
    cksum = functools.reduce(operator.xor, map(ord, s))
    return '{:x}'.format(cksum)

使CharTable成为映射将是一个明确的改进:

代码语言:javascript
复制
CharTable ={"000000":"0", "000001":"1", "000010":"2"}

然后这个循环

代码语言:javascript
复制
        for PAIR in CharTable:
            if PAIR[2] == TMPSTR:
            MESSENC += PAIR[0]

可以用

代码语言:javascript
复制
        MESSENC += CharTable[TMPSTR]
票数 2
EN
页面原文内容由Code Review提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://codereview.stackexchange.com/questions/87617

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档