说明:
本文主要是记录网关与移动端、web端的通讯协议格式转换,由于本项目运用阿里云物联网套件做为云服务器,使用阿里云MQTT协议进行通信。一般而言,硬件终端协议是十六进制形式的字符串,所以来自软件端的控制协议最好也是可以支持直接发送十六进制字符串形式。
但一方面目前集成MQTT协议的WIFI模块(辰天工作室ESP8266十二月底全兼容版本)串口输出数据带有其他字符串,解析方面有一定不稳定性,也没有找到更好的办法。另一方便软件端(IOS)没办法直接传送十六进制字符串,调试了两天,最后终于能够发送过来,但转换期间包含0的一位可能直接被忽略。最后决定以字符串的形式传过来,但是要以和协议内容形式一样的字符串发送。比如十六进制数0x5A 0xFF,则以“5AFF”形式的字符串发送过来,此处就将0x5A直接转换成字符串形式的“5A”。
一、代码逻辑
十六进制数的字符范围是0~F,为了统一,此处全部使用大写,而根据ASCII表对应的十进制数/十六进制数/字符……规律,可将其分为0~9和A~F两部分进行转换。
首先ASCII表中‘0~9’字符分别是48~57,‘A~F’字符分别是65~70,所以对应起来就是:
字符 十进制 / 差值 / 待转换的十六进制 待转换的十进制
0 48 48 0 0
1 49 48 1 1
... ... ... ... ...
A 65 55 A 10
... ... ... ... ...
F 70 55 F 15
由上表可以看出,
在0~9之间,字符-48=对应十六进制字符;
在A~F之间,字符-55=对应十六进制字符;
根据上面的算法,即可实现相关代码。
二、C语言代码
/*
*@brief:字符串转换成同形式的十六进制字符(比如字符串5A01007A,则WIFI_CTRLBUF中存的十六进制为0x5A 0x01 0x00 0x7A)
*@param:PRODUCTNAME:阿里云物联网套件中的产品名称(字符串格式)
DEVICENAME:阿里云物联网套件中设备名称(字符串格式)
TOPIC:阿里云物联网套件中设备不包含产品名称和设备名称的主题(字符串格式)
DATALENGTH_OUT:转换后的十六进制字节长度
*@retur:如果字符串数据在0~9和A~F范围,则满足条件转换成功,返回1;否则返回0。
*/
unsigned char ASCII_TO_HEX(char *PRODUCTNAME,char *DEVICENAME,char *TOPIC,unsigned int DATALENGTH_OUT)
{
u8 i,errflag = 1;
unsigned int LENGTH;
LENGTH = strlen(PRODUCTNAME) + strlen(DEVICENAME) + strlen(TOPIC) + 16;
DATALENGTH_OUT = (DATALENGTH_OUT*2 + LENGTH);
for(i=LENGTH;i<DATALENGTH_OUT;i+=2)
{
if(Data_RX_BUF[i] <= 'F' && Data_RX_BUF[i] >= 'A')
{
if(Data_RX_BUF[i+1] <= 'F' && Data_RX_BUF[i+1] >= 'A')
WIFI_CTRLBUF[(unsigned int)(i-48)/2] = ((Data_RX_BUF[i]-55) << 4) + (Data_RX_BUF[i+1]-55);
else
WIFI_CTRLBUF[(unsigned int)(i-48)/2] = ((Data_RX_BUF[i]-55) << 4) + (Data_RX_BUF[i+1]-48);
}
else if(Data_RX_BUF[i] <= '9' && Data_RX_BUF[i] >= '0')
{
if(Data_RX_BUF[i+1] <= '9' && Data_RX_BUF[i+1] >= '0')
WIFI_CTRLBUF[(unsigned int)(i-48)/2] = ((Data_RX_BUF[i]-48) << 4) + (Data_RX_BUF[i+1]-48);
else
WIFI_CTRLBUF[(unsigned int)(i-48)/2] = ((Data_RX_BUF[i]-48) << 4) + (Data_RX_BUF[i+1]-55);
}
else
errflag = 0;
break;
}
if(errflag)
return 1;
else
return 0;
}
/*
*@brief:十六进制字符转换成同形式的字符串(比如十六进制数组0x5A 0x01 0x00 0x7A,则BUFFER_BACKUP中存的字符串为5A01007A)
*@param:NONE
*@retur:1
*/
unsigned char HEX_TO_ASCII(void)
{
u8 i,data_H,data_L;
for(i=0;i<34;i+=2)
{
data_L = BUFFER_BACK_LORAGET[i]/0xF1;
data_H = BUFFER_BACK_LORAGET[i] >> 4;
if(data_L <= 0x09 && data_L >= 0x00)
{
BUFFER_BACKUP[i+1] = data_L + 48;
}
else if(data_L <= 0x0F && data_L >= 0x0A)
{
BUFFER_BACKUP[i+1] = data_L + 55;
}
if(data_H <= 0x09 && data_H >= 0x00)
{
BUFFER_BACKUP[i] = data_H + 48;
}
else if(data_H <= 0x0F && data_H >= 0x0A)
{
BUFFER_BACKUP[i] = data_L + 55;
}
}
return 1;
}