一、数字管家与设备碰一碰的工作过程
– 示意图如下
这个碰一碰过程有2方面作用
– 1、对于数字管家起到自动拉起应用,创建或打开控制App界面。
– 2、对于设备端,给设备动态配网,把手机的Wifi信息告诉设备,这样设备发布后的联网问题就解决了。
1、问题
根据IoT联网设备运行条件,除了Wifi信息,还有云IoT的DeviceId和Secret才能正常运行。
目前碰一碰通过NFC可以把Wifi动态传递了,但是DeviceId和Secret还是要写死在代码中。如果希望发行多个产品多个ID,就要分别修改和编译,这不符合产品发布要求。
2、解决思路
通过NFC写入的应用调测助手可以看到DeviceId=ProductId_NodeId,而密钥也在其中,都写入到了NFC里面,那是不是开发板的程序不再写死ID和Secret,而是通过调测助手写入的内容读出来?
3、实操过程
以智能台灯为例,通过VSCode+Device Tool 3.1.0.200,创建工程时选择小熊派的智能台灯案例。
内部已经集成了一个NFC的读写模块,其中的方法只是对应着小熊派Nano上的NFC的,其中已经写好了一段读取JSON配置的代码。
因为我们还不知道NFC保存的是什么结构,就按字节读取,显示出来观察一下。
因为不知道实际写入NFC是什么格式内容,只能尝试一下。直接读取NFC的二进制数据,转换成十六进制和ASCII码看看是什么。
uint8_t memary_buf[16 * 15] = {0};
uint8_t payload_len = 0;
uint8_t start_index = 0; //取值开始位置
uint8_t count = 0; //取值数量
NT3H1101_Read_Userpages(15, memary_buf);
for (int i = 0; i < 16 * 15; i++)
{
printf("%c", byte2char(memary_buf[i]));
}
输出的内容为可以看到,从第35个字符后面就是NFC内容写人的明文了,124 6315c93c664c6f7938dc2087 208 Lamp_002 326 123456ABCDEFG123456ABCDEFG 401 1 510 teamX-Lamp 620 VVVVVXXXXXXXXXXXXXXX(空格为了分析容易看)。整个字节流,并不是都需要转换成ASCII码,memary_buf[35]就是个十进制正数,表明有效数据总长度。
从写入格式也不难看出,每节开头有序号和长度,按照这个格式进行分段读取就可以了。把ProductId和NodeId拼接起来就是DeviceID了。
payload_len = memary_buf[35]; //十进制的有效数据总长度
start_index = 35 + 4; // 表示长度的位置+4为数据位置
count = (memary_buf[35 + 2] - 48) * 10 + (memary_buf[35 + 3] - 48);
// product_id+_+node_id,pwd
printf("payload_len: %d\n", payload_len);
printf("start_index: %d\n", start_index);
printf("count: %d\n", count);
for (int i = 0; i < count; i++)
{
product[i] = byte2char(memary_buf[start_index + i]);
}
printf("product_id=%s\n", product);
//下一个起始位置和长度
start_index += count + 3;
count = (memary_buf[start_index - 2] - 48) * 10 + (memary_buf[start_index - 1] - 48);
for (int i = 0; i < count; i++)
{
nodeid[i] = byte2char(memary_buf[start_index + i]);
}
printf("node_id=%s\n", nodeid);
//下一个起始位置和长度
start_index += count + 3;
count = (memary_buf[start_index - 2] - 48) * 10 + (memary_buf[start_index - 1] - 48);
for (int i = 0; i < count; i++)
{
devicepwd[i] = byte2char(memary_buf[start_index + i]);
}
printf("pwd=%s\n", devicepwd);
sprintf(deviceid, "%s_%s", product, nodeid);
这样就可以得到NFC里面的设备信息了,主函数再做些改造,能读取里面信息,也可以联网后保存在开发板中,脱离每次依赖NFC。
ret = IoTDeviceInfo_Get(&(device.device_id), sizeof(device.device_id), &(device.secret), sizeof(device.secret));
if (ret != 0)
{
// GPIO_1复用为I2C1_SCL
IoTGpioSetFunc(HI_I2C_IDX_1, HI_IO_FUNC_GPIO_1_I2C1_SCL);
// baudrate: 400kbps
IoTI2cInit(HI_I2C_IDX_1, 400000);
int rr = get_nfc_device_data(&device);
printf("nfc result = %d\n", rr);
}
if (CLOUD_Connect(&(device.device_id), &(device.secret),
CONFIG_CLOUD_DEFAULT_SERVERIP, CONFIG_CLOUD_DEFAULT_SERVERPORT) != 0)
{
return;
}
else
{
IoTDeviceInfo_Set(&device.device_id, &device.secret);
}
遗留问题
此种方法主要能解决了编译代码,不再写死信息。但是目前这种NFC明文信息还是有安全隐患,下一步可以采用加密保护。