Python 调用 GSM A6

【环境准备】

1、操作系统:

1
Windows 7 x64 SP1

2、Python 版本:

1
python-3.6.3-amd64

3、第三方组件:

(1)、

1
pip3 install pyserial

(2)、下载smspdu

1
python3 setup.py build install


【列出所有串口】

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
#encoding: utf-8
#author: walker
#date: 2017-10-06 
#summary: Python 用 pyserial 列出所有串口
 
import serial.tools.list_ports
 
# 打印所有串口名
def ListPorts():
    serailPortList = list(serial.tools.list_ports.comports())
    print('serail port number: %d' % len(serailPortList))
    if len(serailPortList) < 1:
        print("Not found serail port!")
        return 
         
    for serailPort in serailPortList:
        se = serial.Serial(list(serailPort)[0], 9600, timeout=9)
        print('serail port name:%s' % se.portstr)
        se.close()
     
if __name__ == '__main__':
    ListPorts()


【发送纯英文(ASCII)短信】

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
#encoding: utf-8
#author: walker
#date: 2017-10-06 
#summary: Python 调用 GSM A6,发送英文短信
 
import time
import serial.tools.list_ports
         
class MessagerEn(object):
    # 构造函数,打开端口
    def __init__(self):        
        self.sePort = serial.Serial(port='COM3', baudrate=19200, bytesize=8, stopbits=1, timeout=3)
        time.sleep(3)
     
    # 析构函数,关闭端口
    def __del__(self): 
        self.sePort.close()
     
    # 重新打开端口
    def reopen(self):
        print('reopen ...')
        self.sePort.close()
        self.sePort = serial.Serial(port='COM3', baudrate=19200, bytesize=8, stopbits=1, timeout=3)
        time.sleep(3)
 
    # 执行指令
    # 返回从串口读取的返回值
    def execCmd(self, cmd, end='\r'):
        cmd = cmd + end
        bCmd = cmd.encode('ascii')
        print('write:%s' % bCmd)
        self.sePort.write(bCmd)
        response = self.sePort.readall()
        print('read :%s' % response)
        print()
         
        return response
     
    # 发送英文短信
    # 正确返回 True;错误返回 False
    def __sendMessageEn(self, phoneNumber, message):
        if not self.execCmd('AT+CMGF=1').endswith(b'\r\nOK\r\n'):     #设置TEXT MODE
            return False
             
        if not self.execCmd('AT+CSCS="GSM"').endswith(b'\r\nOK\r\n'):    
            return False
             
        if not self.execCmd('AT+CMGS="%s"' % phoneNumber).endswith(b'\r\n> '):     
            return False
         
        if not self.execCmd(message + '\x1A', end='').endswith(b'\r\nOK\r\n'):     # 十六进制的1A为结束符
            return False
             
        return True
     
    # 调用私有方法 __sendMessageEn
    # 在失败时重新打开串口
    def sendMessage(self, phoneNumber, message):
        for in range(03):
            if self.__sendMessageEn(phoneNumber, message):
                break
            self.reopen()
     
if __name__ == '__main__':
    messagerEn = MessagerEn()
    messagerEn.sendMessage('18688754379''xxx')
    messagerEn.sendMessage('18688754379''zzz')


【发送中文(Unicode)短信】

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
#encoding: utf-8
#author: walker
#date: 2017-10-06 
#summary: Python 调用 GSM A6,发送中文(Unicode)短信
  
import time
import serial.tools.list_ports
          
class Messager(object):
    # 构造函数,打开端口
    def __init__(self):        
        self.sePort = serial.Serial(port='COM3', baudrate=19200, bytesize=8, stopbits=1, timeout=3)
        time.sleep(3)
      
    # 析构函数,关闭端口
    def __del__(self): 
        self.sePort.close()
          
    # 重新打开端口
    def reopen(self):
        print('reopen ...')
        self.sePort.close()
        self.sePort = serial.Serial(port='COM3', baudrate=19200, bytesize=8, stopbits=1, timeout=3)
        time.sleep(3)
  
    # 执行指令
    # 返回从串口读取的返回值
    def execCmd(self, cmd, end='\r'):
        cmd = cmd + end
        bCmd = cmd.encode('ascii')
        print('write:%s' % bCmd)
        self.sePort.write(bCmd)
        response = self.sePort.readall()
        print('read :%s' % response)
        print()
          
        return response
      
    # 发送英文短信
    # 正确返回 True;错误返回 False
    def __sendMessage(self, phoneNumber, message):
        if not self.execCmd('AT+CMGF=0').endswith(b'\r\nOK\r\n'):     #设置PDU格式
            return False
              
        if not self.execCmd('AT+CSCS="GSM"').endswith(b'\r\nOK\r\n'):    
            return False
          
        pdu_content = self.encodeMessage(phoneNumber, message)
        cmd = 'AT+CMGS=%d' % ((len(pdu_content)-2)/2)
        if not self.execCmd(cmd).endswith(b'\r\n> '):    
            return False
          
        # 十六进制的1A为结束符
        if not self.execCmd(pdu_content + '\x1A', end='').endswith(b'\r\nOK\r\n'):    
            return False
              
        return True
      
    # 调用私有方法 __sendMessage
    # 在失败时重新打开串口
    def sendMessage(self, phoneNumber, message):
        for in range(03):
            if self.__sendMessage(phoneNumber, message):
                break
            self.reopen()
      
    # 将中文信息编码为PDU格式(ucs2)
    def encodeMessage(self, phoneNumber, message):
        tpdu = []
        if phoneNumber and message:             
            tpdu.append('001100')
             
            formatAddress = self.encodePhoneNumber(phoneNumber)
            tpdu.append(formatAddress)
  
            tpdu.append('0008AA')
              
            tpdu.append('%02X' % (len(message)*2))
            content = ''.join(['%02X' % c for c in message.encode('utf_16_be')])
            tpdu.append(content)
          
        print(''.join(tpdu))
        return ''.join(tpdu)
     
    # 将手机号编码为pdu所需格式
    def encodePhoneNumber(self, phoneNumber):
        #号码为11位数字
        if not re.match(r'\d{11}', phoneNumber):
            print('Error phoneNumber: %s' % phoneNumber)
         
        addr = '0D'  #号码长度13
        addr += '91'      #Type-of-Address,目标地址格式(TON/NPI) 
        #加86、F补成偶数个(14位),分7组翻转
        phoneNumber = '86' + phoneNumber + 'F'
        for in range(07):       
            addr += phoneNumber[2*i+1+ phoneNumber[2*i]
             
        return addr
      
if __name__ == '__main__':
    messager = Messager()
    messager.sendMessage('18688754379''你好')
    messager.sendMessage('18688754379''大家好')


相关阅读:

1、PDU编码(非常经典)

2、在线PDU格式编码/解码

3、使用python实现短信PDU编码


*** walker ***


附件:http://down.51cto.com/data/2367032

本文转自walker snapshot博客51CTO博客,原文链接http://blog.51cto.com/walkerqt/1970472如需转载请自行联系原作者


RQSLT

上一篇:Windows 10硬盘无损分区方法详解


下一篇:win10安装MySQL