解码 7 位 GSM

问题描述 投票:0回答:5

我发现这个post关于如何将 ascii 数据编码为 7 位 GSM 字符集,我将如何再次解码 7 位 GSM 字符(将其反转回 ascii)?

python encode codec gsm
5个回答
9
投票

例如:

C7F7FBCC2E03 代表“谷歌”
Python 3.4

def gsm7bitdecode(f):
   f = ''.join(["{0:08b}".format(int(f[i:i+2], 16)) for i in range(0, len(f), 2)][::-1])
   return ''.join([chr(int(f[::-1][i:i+7][::-1], 2)) for i in range(0, len(f), 7)])

print(gsm7bitdecode('C7F7FBCC2E03'))

谷歌


3
投票

有一个非常简单的解决方案:

Convert the hex in binary octets 将每个八位位组放入一个数组中,但顺序相反(整个八位位组,而不是位),因为这是它们的发送方式。以7位为组从右向左读取字符串 数字为GSM 7位表中的字符编码

例如:

C7F7FBCC2E03 代表“谷歌”

倒序的字符串是

03-2E-CC-FB-F7-C7

六个八位字节是

00000011-00101110-11001100-11111011-11110111-11000111

七重奏是

000000-1100101-1101100-1100111-1101111-1101111-1000111

然后从右往左读是:

GSM 7 位表中的七进制十进制值字符

1000111-71-G

1101111-111-o

1101111-111-o

1100111-103-g

1101100-108-l

1100101-101-e

丢弃最后的 0000000 值


2
投票

对于 Python2:

import binascii
gsm = ("@£$¥èéùìòÇ\nØø\rÅåΔ_ΦΓΛΩΠΨΣΘΞ\x1bÆæßÉ !\"#¤%&'()*+,-./0123456789:;<=>?"
       "¡ABCDEFGHIJKLMNOPQRSTUVWXYZÄÖÑÜ`¿abcdefghijklmnopqrstuvwxyzäöñüà")
ext = ("````````````````````^```````````````````{}`````\\````````````[~]`"
       "|````````````````````````````````````€``````````````````````````")

def gsm_encode(plaintext):
    result = []
    for c in plaintext:
        idx = gsm.find(c)
        if idx != -1:
            result.append(chr(idx))
            continue
        idx = ext.find(c)
        if idx != -1:
            result.append(chr(27) + chr(idx))
    return ''.join(result).encode('hex')

def gsm_decode(hexstr):
    res = hexstr.decode('hex')
    res = iter(res)
    result = []
    for c in res:
        if c == chr(27):
            c = next(res)
            result.append(ext[ord(c)])
        else:
            result.append(gsm[ord(c)])
    return ''.join(result)

code = gsm_encode("Hello World {}")
print(code)
# 64868d8d903a7390938d853a1b281b29
print(gsm_decode(code))
# Hello World {}

0
投票

我已经用 c 语言为 openwrt 设备编写了这样的解码器

uint8_t get_data ( char input, uint8_t * output )
{
    if ( input - '0' >= 0 && '9' - input >= 0 ) {
        * output = input - '0';
    } else if ( input - 'a' >= 0 && 'f' - input >= 0 ) {
        * output = input - 'a' + 10;
    } else if ( input - 'A' >= 0 && 'F' - input >= 0 ) {
        * output = input - 'A' + 10;
    } else {
        return 1;
    }
    return 0;
}

uint8_t get_data_pair ( const char * input, uint8_t * output )
{
    uint8_t data;
    if ( get_data ( * input, &data ) != 0 ) {
        return 1;
    }
    * output = data << 4;
    if ( get_data ( * ( input + 1 ), &data ) != 0 ) {
        return 2;
    }
    * output = * output | data;
    return 0;
}

int main ( int argc, char * argv [] )
{
    if ( argc != 2 ) {
        fputs ( "required argument: hex\n", stderr );
        return 1;
    }

    char * hex = argv[1];
    uint16_t data = 0;
    uint8_t data_length = 0;

    while ( *hex != '\0' ) {
        uint8_t new_data;
        if ( get_data_pair ( hex, &new_data ) != 0 ) {
            fprintf ( stderr, "invalid hex: bad pair %.2s\n", hex );
            putchar ( '\n' );
            return 2;
        }
        hex += 2;

        data = new_data << data_length | data;
        data_length += 8;

        while ( data_length >= 7 ) {
            putchar ( data & 0x7f );
            data = data >> 7;
            data_length -= 7;
        }
    }

    putchar ( '\n' );
    return 0;
}

0
投票

noiam的回答开头不错,但是第二行有错误;应该是:

return ''.join([chr(int(f[i:i+7], 2)) for i in range(0, len(f), 7)][::-1])

即便如此,它也不使用 GSM 03.38 中的字母表。经过一些工作后,我修改了 noiam 的工作以提出这个解决方案,它适用于我尝试过的所有数据。

def gsm7bitdecode(f):
    """
    https://stackoverflow.com/questions/13130935/decode-7-bit-gsm

    We make sure our hex string has an even number of digits, prepend a
    zero if necessary to make it so.

    Take one pair of hex digits at a time, convert each octet to
    a binary string, then reverse all the octets, and join these strings
    of binary digit together to create a string of zeros and ones.  This is f.

    Then starting from the beginning of f, take seven of these bits at a time,
    and convert to an integer.

    Reverse this array.

    If the first element of the list is zero, we remove it; it is padding.

    We go through these integers, and if the value is not 27 (escape), we
    use that integer as an index into the gsm array for our character.

    If we find an escape character, we look up the following integer in the
    ext array as our character.
    """
    if len(f) % 2 == 1:
        f = f"0{f}"
    f = ''.join([f"{int(f[i:i+2], 16):08b}" for i in range(0, len(f), 2)][::-1])
    ints = [int(f[i:i+7], 2) for i in range(0, len(f), 7)][::-1]
    result = []
    if ints[0] == 0:
        ints.pop(0)
    for i in ints:
        if i == 27:
            i = next(ints)
            result.append(ext[i])
        else:
            result.append(gsm[i])
    return ''.join(result)
© www.soinside.com 2019 - 2024. All rights reserved.