利用MircoPython的ESP32驱动安信可的A9发短信时,发现其发送中文短信的PUD编码资料有点少。经测试后总结如下:
文章目录
- 一、PUD编码结构
- 简单应用版:
- 具体结构:
- PUD编码测试网站:[链接](http://www.sendsms.cn/pdu/)
- 二、处理电话号码
- 三、将正文转换为Unicode编码
- 四、 组合形成完整命令
一、PUD编码结构
简单应用版:
具体结构:
- 固定命令:
0001000D91
- 带区号的接收方电话号码头去+号,如果是电话长度奇数则末尾加上F,交换奇偶位
- 固定命令:
008
- 发送Unicode编码长度(两个字符)
- 使用Hex形式字符串Unicode编码组成的正文
注:以上都是字符流,并不是16进制。
PUD编码测试网站:链接
二、处理电话号码
注:这里默认给的phoneNumber只带区号没有+
def handlePhoneNumber(self,phoneNumber):
'根据PUD规范,带区号的电话号码头去+号,如果是电话长度奇数则末尾加上F,交换奇偶位'
if(len(phoneNumber)%2):
#+F补成偶数
phoneNumber+="F"
result=""
#交换奇偶,python字符串不能改,只能另外赋值
for j in range(0,len(phoneNumber),2):
result+=phoneNumber[j+1]+phoneNumber[j]
return result
三、将正文转换为Unicode编码
此处收到这位大佬的文章的启发,后面发现MicroPython是支持直接使用ord()命令来获取Unicode,所以事情变得比较简单。
def getUnicodeFromUTF8Char(char):
"获取UTF8字符的Unicode的字符Hex编码(用4个位十六进制字符串表示)"
result=hex(ord(char))[2:]#去除前面的0x
if(len(result)%2==1):
#长度非偶数前面补0
result="0"+result
if(len(result)==2):
#只有一个字符,补0补成4位
result="00"+result
return result
四、 组合形成完整命令
接着就是按照格式组装出完整的PUD代码了。由于使用AT命令发送短信时,往往需要调用AT+CMGS=n(n是长度)
,在发送PUD编码,故返回一个元组。
def getPUDCode(sendNumber,utf8Text):
"电话号码带区号(不带+),返回一个元组,其中第一个字节是CMGS的长度,第二个是正文"
result={}
#固定前缀
result[1]="0001000D91"
#加上处理后的电话号码
result[1]+=self.handlePhoneNumber(sendNumber)
#加上后戳
result[1]+="0008"
#加上正文长度,并去除前缀
textLen=hex(2*len(utf8Text))[2:]
if(len(textLen)==1):
#当长度只有一位时,先补0
result[1]+="0"
result[1]+=textLen
for char in utf8Text:
result[1]+=self.getUnicodeFromUTF8Char(char)
#计算长度,开始的00不计入
result[0]=str(int((len(result[1])/2))-1)
return result