cf云端:CF-IOT云端通讯协议调试

概述

设备与服务器通讯使用 WebSocket 或 MQTT 协议,数据采用 json 格式,可直接解析, WebSocket 服务器后台使用“/CloudEmbeddedSDKWebsocket/(设备号)”接口,接收设备 发出的 Websocket 请求,并按该文档定义的 json 格式处理数据。

开发者对接该协议,需要向我司申请开发者密钥,密钥由服务器 IP 或域名按一定的算 法生成,考虑到项目安全性,开发者可以提交多个备用域名,申请多个开发者密钥,当新增 或变更服务器,需要对设备下发产品认证指令。

设备开机会检测产品激活码,如果本地没有激活码,会主动向我司产品认证服务器申请 激活码,激活成功后,除主动下发产品认证,不会跟我司服务器有任何通信。

设备与服务器通信需要鉴权,设备连接成功,首先会发出开发者密钥请求,服务器应答 开发者密钥,设备收到开发者密钥进行鉴权,鉴权结果会上行服务器,只有鉴权成功,设备 才会维持正常的通信链路。

由设备发往服务器的数据,遵循设备上行协议,由服务器发往设备的数据,遵循设备下 行协议。

稳定性保障

设备固件运行期间,有守护进程、看门狗进程提供稳定性保障措施,守护进程定时监测设备固件是否存在,如果发现未运行,则尝试启动,看门狗进程主要起监测固件是否正常运行(定时发送喂狗信号),以及与后台通信是否正常的作用。

在web配置界面,我们可以启用和关闭看门狗,当启用看门狗功能,固件每隔5分钟发送喂狗信号到用户后台,用户后台需返回上行数据,设备收到该信号,才会通过管道发送喂狗信号给看门狗进程,从而起到监测固件正常运行和网络通讯正常双重作用,如果关闭看门狗功能,固件则每隔5分钟直接通过管道发送喂狗信号给看门狗进程,可以起到监测固件正常运行的作用。

通讯方式

WebSocket

首先我们进入设备的web配置界面,将协议类型设置为WebSocket,然后保存设置,再重启设备,设备便会以WebSocket通讯方式接入用户后台,WebSocket 服务器后台使用“/CloudEmbeddedSDKWebsocket/(设备号)”接口对接设备。

MQTT

进入设备的web配置界面,将协议类型设置为MQTT,可使用默认的发布主题、注册主题以及客户端ID,然后保存设置,再重启设备,设备便会以MQTT通讯方式接入用户后台,用户后台订阅以上发布主题接收设备上行数据,用户后台下发数据到设备,需要指定以上注册主题。

通讯参数

上传时间间隔:gps数据定时上报的时间间隔,单位秒,gps数据无效时,停止上报。

心跳间隔:心跳包定时上报的时间间隔,单位秒,心跳包主要起维持链路作用,用户后台可根据心跳到达时间与当前时间差,判断设备链路是否读超时,可作为释放链接资源的判断条件。

读超时:固件允许用户后台下行数据时间与当前时间差的最大值,单位秒,设备固件根据读超时判断设备链路是否正常,若超时,固件会释放旧连接资源,并创建新的连接。若新连接创建失败,则会等一个读超时的时间,继续创建连接,直至连接创建成功。

设备配置

设备支持网页、短信、下行指令修改相关参数,下行指令主要由用户后台发起,我们放在后续章节详细讲解,下面主要介绍网页和短信修改参数。

网页配置

设备网页地址:http://192.168.100.1

默认用户名:admin,密码:123456

短信指令

短信指令功能
Upgrading系统升级
Reboot系统重启
Refresh DeviceActivationCode请求设备刷新激活码
Server api.uddgps.com 80 10 3 60 300

服务器域名:api.uddgps.com

服务器端口:80

回传间隔:10秒协议类型:3(websocket),4(mqtt)

心跳间隔:60秒

读超时:300秒 

MQTT ClientID UserName Password设置mqtt服务器登录信息
LuaVM_Upgrading http://www.***/lua.zip升级lua脚本
LuaVM_Load启动虚拟机
LuaVM_Stop停止虚拟机
LuaVM_Clear清除lua脚本

协议调试

为了方便调试,我们将设备协议类型设置为MQTT,采用一台免费并可网页调试的MQTT服务器来完成相关功能测试。

MQTT调试网址:MQTT Websocket Client

CF-IOT云端通讯协议:CF-IOT云端通讯协议_物联网平台研发的博客-CSDN博客_cf协议

进入该调试界面,我们点连接按钮后,网页端会创建一个websocket连接,如果与MQTT服务器连接成功,我们便可通过mqtt.p2hp.com这台服务器与设备进行双向通信,在与设备通信前,我们要订阅主题,并设置发布主题。

通常在这个界面我们订阅的主题,对应设备发布主题,设置的发布主题,对应设备的注册主题。

密钥、鉴权、激活码

设备创建链路后,首先发的第一个JSON数据包便是密钥请求,如果用户后台不应答开发者密钥进行鉴权,设备会按心跳间隔重复发此包,直至鉴权成功。

↑密钥请求

{"channel": "ServerKey_Request","DeviceNo": "864977047765106","Data": null}

↓密钥应答

{"channel": "ServerKey_Response","DeviceNo": "864977047765106","Data": {"ServerKey": "0F3EFB4E40C69C7A39C90E319732D6A3"}}

↑鉴权结果

{"channel": "Authentication","DeviceNo": "864977047765106","Data": {"Result": true}}

↑设备激活码请求

{"channel": "DeviceActivationCode_Request","DeviceNo": "864977047765106","Data": null}

设备第一次请求激活码,是从我司服务器申请,若请求成功,会将激活码保存本地,并上报一条包含激活码的固件信息到用户后台,用户后台应将该激活码保存,当设备数据文件损坏,我司授权服务器不能正常访问时,设备会发送该激活码请求包,用户后台应下发一条包含设备激活码的固件设置指令。

固件信息

↓查询固件

{"channel": "Parameters_Request","DeviceNo": "864977047765106","Data": {"ParameterName": "Firmware","Filter": ""}}

↑固件信息

{"channel": "Firmware_Parameters_Response","DeviceNo": "864977047765106","Data": {"ModuleState": {"IMEI": "864977047765106","CCID": "89860318245512075960","CSQ": "25,99","CSQtime": "2020-11-12 19:36:31","Revision": "EC20CEFILGR06A03M1G_OCPU_BETA0628"},"FunctionSwitch": {"Watchdog": false,"GPS": false},"DeviceActivationCode": ",E4DFE403DC960AC21DEDA29B4DDC2548,F63FBF4299C4F546B6B36D50F8CB47F6,9F069D3D4F7B29FE35EF9910898AC373,","Revision": "HeFeiQILIAN_miniCFIOT_v1.3.5.1.2_20201109"}}

↓设置固件

{"channel": "Firmware_Settings","DeviceNo": "864977047765106","Data": {"Switch_Watchdog": 1,"Switch_GPS": 1,"DeviceActivationCode": ""}}

↑心跳包

{"channel": "H","DeviceNo": "864977047765106","Data": null}

位置测试

↑GPS数据

{"channel": "GPS","DeviceNo": "864977047765106","Data": {"Longitude": 117.2304914,"Latitude": 31.842440516666667,"N_S": "N","E_W": "E","Speed": 0,"Direction": 164.2,"Mode": "A","DateTime": "2020-11-09 16:43:22.00"}}

↓按需秒刷新

用户后台定时下发该信号,设备在GPS数据有效时,自动秒传GPS数据,当停止下发该信号超过30秒,设备会自动关闭秒传GPS功能。

{"channel": "UpdateSendNowForGPSSignal","DeviceNo": "864977047765106","Data": null}

↑GPS刷新数据

{"channel": "GPS_Refresh_GPRMC","DeviceNo": "864977047765106","Data": "GPRMC,164826.00,A,3150.563094,N,11713.823810,E,0.0,341.0,091120,4.4,W,A"}

串口调试

↓串口初始化

{"channel": "Serial_Open","DeviceNo": "862607059109339","Data": {"portName": "Serial1","Baud": 9600,"DataBits": 8,"Parity": "None","StopBits": 1}}

↑串口连接事件

{"channel": "Hardware_onEvent","DeviceNo": "862607059109339","Data": {"EventName": "Serial_Open_Success","portName": "Serial1","Message": ""}}

↓写串口

{"channel": "Serial_writeData","DeviceNo": "862607059109339","Data": {"portName": "Serial1","Data": "ff 05 00 00 00 00 d8 14"}}

↑读串口

{"channel": "Serial_onData","DeviceNo": "862607059109339","Data": {"portName": "Serial1","Data": "ff 05 00 00 00 00 d8 14"}}

摄像机调试

↓摄像机搜索

固件每隔三分钟通过udp广播方式搜索摄像机、更新状态,网页配置界面里也可以手动搜索摄像机,用户后台可以下发摄像机搜索指令,实现主动搜索摄像机并更新摄像机状态。

{"channel": "SearchAllIPCamera","DeviceNo": "864977047765106","Data": null}

↓查询摄像机信息

{"channel": "Parameters_Request","DeviceNo": "864977047765106","Data": {"ParameterName": "IPCameraParameters","Filter": ""}}

Filter字段可指定摄像机IP

↑摄像机信息

{"channel": "IPCamera_Parameters_Response","DeviceNo": "864977047765106","Data": {"192.168.100.48": {"IP": "192.168.100.48","SerialNumber": "fe5002562668","UserName": "","Password": "","MediaArray": [{"ProfileToken": "stream0_0","Width": 1920,"Height": 1080,"RtspUrl": "rtsp://192.168.100.48/live/ch00_1"}, {"ProfileToken": "stream0_1","Width": 640,"Height": 480,"RtspUrl": "rtsp://192.168.100.48/live/ch00_0"}],"SelectMediaKey": "","StreamUrl": "","HLSurl": "","RTMPurl": "","Flvurl": "","TimeRange": {}},"192.168.100.75": {"IP": "192.168.100.75","SerialNumber": "","UserName": "","Password": "","MediaArray": [],"SelectMediaKey": "","StreamUrl": "","HLSurl": "","RTMPurl": "","Flvurl": "","TimeRange": {}}}}

从以上返回的摄像机列表里,IP为192.168.100.75的摄像机码流是空的,这是因为该摄像机启用了onvif鉴权,我们要给该摄像机配置用户名和密码,固件才能获取到码流信息。

↓摄像机鉴权

{"channel": "IPCamera_Settings","DeviceNo": "864977047765106","Data": {"Type": 0,"Data": {"IP": "192.168.100.75","UserName": "admin","Password": "admin"}}}

通过以上鉴权设置后,我们下发摄像机搜索指令,并查询摄像机,便可以获取到该摄像机码流信息了。

{"channel": "IPCamera_Parameters_Response","DeviceNo": "864977047765106","Data": {"192.168.100.75": {"IP": "192.168.100.75","SerialNumber": "007D50117625","UserName": "admin","Password": "admin","MediaArray": [{"ProfileToken": "MainStreamProfileToken","Width": 1920,"Height": 1080,"RtspUrl": "rtsp://192.168.100.75:554/11"}, {"ProfileToken": "SecondStreamProfileToken","Width": 640,"Height": 352,"RtspUrl": "rtsp://192.168.100.75:554/12"}],"SelectMediaKey": "","StreamUrl": "","HLSurl": "","RTMPurl": "","Flvurl": "","TimeRange": {}}}}

↓图像采集

{"channel": "Media_Screenshot","DeviceNo": "864977047765106","Data": {"SerialNumber": "007D50117625","MediaKey": "SecondStreamProfileToken_640_352","FileName": "testScreenshot","FtpPath": "/Media"}}

摄像机拍照操作,会上报相关通知事件

↑拍照成功事件

{"channel": "Media_onEvent","DeviceNo": "864977047765106","Data": {"EventName": "Media_Screenshot_Success","Message": "","FileName": "/Media/testScreenshot.jpg"}}

 ↑ftp上传成功事件

{"channel": "Ftp_onEvent","DeviceNo": "864977047765106","Data": {"EventName": "FTP_Upload_Success","Message": "","FileName": "/Media/testScreenshot.jpg"}}

↓视频录制

{"channel": "Media_VideoRecording","DeviceNo": "864977047765106","Data": {"SerialNumber": "007D50117625","MediaKey": "SecondStreamProfileToken_640_352","FileName": "testVideoRecording","FtpPath": "/Media","Duration": 10,"MediaType": "flv"}}

摄像机录制操作,会上报相关通知事件

↑录制成功事件

{"channel": "Media_onEvent","DeviceNo": "864977047765106","Data": {"EventName": "Media_VideoRecording_Success","Message": "","FileName": "/Media/testVideoRecording.flv"}}

 ↑ftp上传成功事件

{"channel": "Ftp_onEvent","DeviceNo": "864977047765106","Data": {"EventName": "FTP_Upload_Success","Message": "","FileName": "/Media/testVideoRecording.flv"}}

↓查询摄像机状态

{"channel": "Parameters_Request","DeviceNo": "864977047765106","Data": {"ParameterName": "IPCameraState","Filter": ""}}

 ↑摄像机状态信息

{"channel": "IPCameraState_Response","DeviceNo": "864977047765106","Data": [{"IP": "192.168.100.75","OnVifServiceUrl": "http://192.168.100.75:8080/onvif/device_service","Manufacturer": "IPCAM","FirmwareVersion": "V20.1.41.16.3-20200430","SerialNumber": "007D50117625","MediaArray": [{"ProfileToken": "MainStreamProfileToken","Width": 1920,"Height": 1080,"MainStream": false,"RtspUrl": "rtsp://192.168.100.75:554/11","SnapshotUri": "http://192.168.100.75:80/tmpfs/auto.jpg","PushStream": {"State": false,"HeartbeatTime": "0001-01-01T00:00:00Z","StreamUrl": "","HLSurl": "","RTMPurl": "","Flvurl": ""},"Screenshot": "","InUse": false}, {"ProfileToken": "SecondStreamProfileToken","Width": 640,"Height": 352,"MainStream": false,"RtspUrl": "rtsp://192.168.100.75:554/12","SnapshotUri": "http://192.168.100.75:80/tmpfs/auto.jpg","PushStream": {"State": false,"HeartbeatTime": "0001-01-01T00:00:00Z","StreamUrl": "","HLSurl": "","RTMPurl": "","Flvurl": ""},"Screenshot": "","InUse": false}],"State": true,"PlayState": false}]}

摄像机推流

设备支持按需推流、定时推流,并且两种推流方式可互补使用,如果在摄像机信息里设置了定时推流时间段,当处在非定时推流时间段,我们可以从用户后台定时下发按需推流指令来控制摄像机推流,在摄像机状态信息中,每路摄像机码流都有一个推流结构体,该结构体执行最终的推流操作,我们将推流操作加锁,这就意味着定时推流和按需推流具有互斥性,可以起到互补作用。

定时推流

在摄像机信息里,我们可以为摄像机的某个码流设置推流时间段,目前一个摄像机只能设置一路码流定时推流,并且支持网页和下发指令设置推流属性。

↓设置推流

{"channel": "IPCamera_Settings","DeviceNo": "864977047765106","Data": {"Type": 1,"Data": {"IP": "192.168.100.75","SelectMediaKey": "SecondStreamProfileToken_640_352","StreamUrl": "rtmp://tx.direct.huya.com/huyalive/*********","HLSurl": "","RTMPurl": "","Flvurl": ""}}}

↓设置推流时间段

{"channel": "IPCamera_Settings","DeviceNo": "864977047765106","Data": {"Type": 2,"Data": {"IP": "192.168.100.75","TimeRange": {"Friday": [{"StartTime": "06:00:00","EndTime": "18:00:00","StartTime1": 21600,"EndTime1": 64800}, {"StartTime": "19:00:00","EndTime": "20:00:00","StartTime1": 68400,"EndTime1": 72000}],"Monday": [{"StartTime": "06:00:00","EndTime": "18:00:00","StartTime1": 21600,"EndTime1": 64800}, {"StartTime": "19:00:00","EndTime": "20:00:00","StartTime1": 68400,"EndTime1": 72000}],"Saturday": [{"StartTime": "06:00:00","EndTime": "18:00:00","StartTime1": 21600,"EndTime1": 64800}, {"StartTime": "19:00:00","EndTime": "20:00:00","StartTime1": 68400,"EndTime1": 72000}],"Sunday": [{"StartTime": "06:00:00","EndTime": "18:00:00","StartTime1": 21600,"EndTime1": 64800}, {"StartTime": "19:00:00","EndTime": "20:00:00","StartTime1": 68400,"EndTime1": 72000}],"Thursday": [{"StartTime": "06:00:00","EndTime": "18:00:00","StartTime1": 21600,"EndTime1": 64800}, {"StartTime": "19:00:00","EndTime": "20:00:00","StartTime1": 68400,"EndTime1": 72000}],"Tuesday": [{"StartTime": "06:00:00","EndTime": "18:00:00","StartTime1": 21600,"EndTime1": 64800}, {"StartTime": "19:00:00","EndTime": "20:00:00","StartTime1": 68400,"EndTime1": 72000}],"Wednesday": [{"StartTime": "06:00:00","EndTime": "18:00:00","StartTime1": 21600,"EndTime1": 64800}, {"StartTime": "19:00:00","EndTime": "20:00:00","StartTime1": 68400,"EndTime1": 72000}]}}}}

↓按需推流

{"channel": "StartPushStream","DeviceNo": "864977047765106","Data": {"SerialNumber": "007D50117625","MediaKey": "SecondStreamProfileToken_640_352","StreamUrl": "rtmp://tx.direct.huya.com/huyalive/1199558764847-1199558764847-6888343667394952147-2399117653150-10057-A-1603817515-1?seq=1605155499051&type=simple","HLSurl": "","RTMPurl": "","Flvurl": ""}}

用户后台需要定时下发推流指令,才能维持推流过程,当停止下发该推流指令,30秒后自动停止推流。

LUA虚拟机

脚本升级

{"channel": "LuaVM_Upgrading","DeviceNo": "864977047765106","Data": {"URL": "http://www.***/lua.zip"}}

启动虚拟机

{"channel": "LuaVM_Load","DeviceNo": "864977047765106","Data": null}

停止虚拟机

{"channel": "LuaVM_Stop","DeviceNo": "864977047765106","Data": null}

清除脚本

{"channel": "LuaVM_Clear","DeviceNo": "864977047765106","Data": null}

相关推荐

相关文章