前言

项目上需要实现一个自动发送短信的功能, 由于是内网环境, 所以不能调用阿里之类的短信业务, 于是想着着手从传统的短信猫方式进行实现, 不过某宝上现在已经屏蔽了短信猫相关的关键词, 不过可以搜USB短信模块很轻松的就搞到了这块SIM800C的板子, 内置了CH340T进行USB到串口协议的转换.

python3 发送字节到串口 python发送串口指令_ico

CH340T驱动

Windows: http://www.wch.cn/downloads/CH341SER_EXE.html Linux: http://www.wch.cn/download/CH341SER_LINUX_ZIP.html

串口指令实现过程

常用指令

指令

功能

返回值参考

AT+COPS?

查询是否入网

入网成功: +COPS: 0,0,"CHINA MOBILE" 失败: +COPS: 0

AT+CMGL=4AT+CMGL="ALL"

查看SIM卡中的所有短信

Unicode编码不带空格的内容

HEX模式下发送1A

相当于回车确认

HEX模式下发送1B

相当于取消

发送一条中文短信,使用以下指令

AT+CMGF=1
AT+CSMP=17,167,2,25
AT+CSCS="UCS2"
AT+CMGS="00310030003000380036" // 10086 的 unicode 码, 16进制
67E58BE28BDD8D39  //要发送的中文内容"查询话费"的unicode码(16进制无空格)
1A	// 切换至HEX模式下发送, 等同于回车确认, 1B等同于ESC取消

需要注意的是发送中文短信时接收的手机号和中文短信内容全部都要使用unicode格式的16进制编码, 测试阶段可以用转换工具来实现, 注意要把转换结果中的空格清除掉

python3 发送字节到串口 python发送串口指令_串口_02


用串口调试工具发送指令测试(Linux下可以用cutecom工具)

python3 发送字节到串口 python发送串口指令_串口_03


手机接收正常, ps:13:56那条是直接用TEXT模式发送包含中文字符短信的效果, 中文是乱码.

python3 发送字节到串口 python发送串口指令_python3 发送字节到串口_04

使用Python实现上面操作

首先需要pip3 install pyserial安装操作串口的轮子, 下面是串口的常用操作

import io
import time
import serial
import serial.tools.list_ports

# 字符串转16进制unicode编码
def str2unicode(raw_str):
    result = ''
    for c in raw_str:
        _hex = hex(ord(c))
        # 处理数字
        if len(_hex) == 4:
            _hex = _hex.replace('0x', '00')
        else:
            _hex = _hex.replace('0x', '')

        result += _hex.upper()
    return result

port_list = list(serial.tools.list_ports.comports())

target_phone = str2unicode('18500000000')
send_text = str2unicode('你好中文,英文符号,【落款6】')

if len(port_list) == 0:
    print('没有可用的串口')
else:
    # 使用第一个可用的串口
    s = serial.Serial(port_list[0].device, timeout=0.5)
    # 创建IO缓存
    sio = io.TextIOWrapper(io.BufferedRWPair(s, s))
    # 向串口发送字符串命令
    sio.write(f'AT+CMGF=1\nAT+CSMP=17,167,2,25\nAT+CSCS="UCS2"\nAT+CMGS="{target_phone}"\n')
    sio.flush()
    print(''.join(sio.readlines()))
    time.sleep(1)
    sio.write(send_text+'\n')
    sio.flush()
    print(''.join(sio.readlines()))
    
    s.write(b'\x1a')  # 发送HEX内容1A
    sio.flush()

    print(''.join(sio.readlines()))
	# 关闭串口
    s.close()
# 字符串转换
'\u4e2d'.encode('unicode-escape').decode('unicode-escape')	# 输出"中"