【环境准备】
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
(
0
,
3
):
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
(
0
,
3
):
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
i
in
range
(
0
,
7
):
addr
+
=
phoneNumber[
2
*
i
+
1
]
+
phoneNumber[
2
*
i]
return
addr
if
__name__
=
=
'__main__'
:
messager
=
Messager()
messager.sendMessage(
'18688754379'
,
'你好'
)
messager.sendMessage(
'18688754379'
,
'大家好'
)
|
相关阅读:
*** walker ***
附件:http://down.51cto.com/data/2367032
本文转自walker snapshot博客51CTO博客,原文链接http://blog.51cto.com/walkerqt/1970472如需转载请自行联系原作者
RQSLT