迅鸣物联网文档

迅鸣物联网文档


蓝牙控制板底层通信协议V1版

<p>蓝牙控制板相关协议</p> <h3>一.主服务</h3> <p><code>serviceId:0000fff0-0000-1000-8000-00805f9b34fb</code></p> <p>蓝牙扫描时可通过指定<strong>serviceId</strong>过滤设备</p> <h3>二.广播数据</h3> <p><code>advertisData:0x010136630D040098</code></p> <p>36630D040098为设备的mac地址,用于IOS系统识别设备的身份</p> <h3>三.应用服务</h3> <pre><code>服务ID:00000001-0000-1000-8000-00805F9B34FB characteristicId-write:000284CF-F7E3-55B4-6C4C-9FD140100A16 characteristicId-notify:000384CF-F7E3-55B4-6C4C-9FD140100A16</code></pre> <p>characteristicId-write:写指令及相关参数</p> <p>characteristicId-notify:控制板响应通知</p> <h3>四.流程1-设备连接</h3> <ol> <li>扫描通过主服务过滤扫描设备</li> <li>mac地址/deviceId连接设备</li> <li>发现应用服务</li> <li>开启characteristicId-notify特征监听</li> </ol> <p>当主机与设备连接成功后在开启监听characteristicId-notify的情况下会收到设备的<strong>认证参数</strong></p> <p><code>认证参数:0x31584d5f6c63685776363338314635434241</code></p> <p>ASCII对照:31=字符1 58=字符X 依次类推可得结果:<code>1XM_lock_v6381F5CBA</code></p> <p><code>1</code>流程ID:连接成功</p> <p><code>XM_lock_v6</code>10个字符长度的设备名称</p> <p><code>381F5CBA</code>8个字符长度的随机串,每次连接和断开会重置</p> <p>取<code>XM_lock_v6381F5CBA</code>保存,用于后期交互验证【以下均称为<strong>认证串</strong>】</p> <h3>五.流程2-指令发送</h3> <p>指令集:</p> <pre><code> * id 响应次数 名称 * 20 2次 读配置 * 21 2次 开锁 V * 24 1次 改密码 V * 25 1次 改名字 V * 26 1次 查状态 V * 27 1次 写27 V * 28 1次 写28 V * 29 1次 读版本 V * 2a 1次 带参数的开锁 V * 2b 1次 带参数的关锁 V</code></pre> <p><code>8字符密码:默认00000000可通过指令更改</code></p> <p><code>下述+均为字符串的拼接</code></p> <h4>读取锁的配置信息20:</h4> <p>指令id:20</p> <p>密钥: 认证串+8字符密码(字符串拼接)通过hex_md5加密后toUpperCase().substring(0, 8)</p> <p>写characteristicId-write: </p> <pre><code class="language-javascript">// act 指令id // md5p 密钥 const genValue = function (act, md5p) { let sendresA = act + md5p; let sendresB = params let l = sendresA.length let buffer = new ArrayBuffer(l) let dataView = new DataView(buffer) for (var i = 0; i &amp;lt; sendresA.length; i++) { dataView.setUint8(i, sendresA.charAt(i).charCodeAt()) } return buffer }</code></pre> <p>第一次通知characteristicId-notify:<code>3330xxxxxxxxxxxxxxxxxxxx</code></p> <ul> <li>33 =&gt; 字符3</li> <li>30 =&gt; 字符0</li> </ul> <p>3330=&gt;30 表示对20的回复</p> <p>如果:xxxx....为0则密钥验证失败</p> <p>结果解析</p> <pre><code> let res = &amp;quot;3330xxxxxxxxxxxxxxxxxxxx&amp;quot;.substring(4, 24) let a = res.substr(0, 2); let b = res.substr(2, 4); let c = res.substr(6, 2); let d = res.substr(8, 2); let e = res.substr(10, 4); let f = res.substr(14, 4); let g = res.substr(18, 2)</code></pre> <p><img src="https://www.showdoc.com.cn/server/api/attachment/visitfile/sign/eaab17fa165448ad6d049a026e19f9ae" alt="" /></p> <p>(图一)</p> <p>各个结果对应内容如上图所示</p> <p>第二次通知characteristicId-notify:<code>3338xxxxxxxx</code></p> <pre><code> let res = &amp;quot;3330xxxxxxxx&amp;quot;.substring(4, 12) let a = res.substr(0, 2); let b = res.substr(2, 2); let c = res.substr(4, 2); let d = res.substr(6, 2);</code></pre> <p><img src="https://www.showdoc.com.cn/server/api/attachment/visitfile/sign/da8a8fcbf23c79c803b96949f2e2ceab" alt="" /></p> <p>(图二)</p> <h4>开指令21</h4> <p>指令id:21</p> <p>密钥: 认证串+8字符密码(字符串拼接)通过hex_md5加密后toUpperCase().substring(0, 8)</p> <p>写characteristicId-write: </p> <pre><code class="language-javascript">// act 指令id // md5p 密钥 const genValue = function (act, md5p) { let sendresA = act + md5p; let sendresB = params let l = sendresA.length let buffer = new ArrayBuffer(l) let dataView = new DataView(buffer) for (var i = 0; i &amp;lt; sendresA.length; i++) { dataView.setUint8(i, sendresA.charAt(i).charCodeAt()) } return buffer }</code></pre> <p>第一次通知characteristicId-notify:转换为ASCII字符串<code>310d120003000300</code></p> <ul> <li>31 对 21 指令的回复</li> <li>0D12 16进制电压</li> <li>0003 16进制开锁次数</li> <li>0003 16进制总开锁次数</li> <li>00 接收指令时的状态 [00关/10开]</li> </ul> <p>第二次通知characteristicId-notify:转换为ASCII字符串<code>310d120003000310</code></p> <ul> <li>31 对 21 指令的回复</li> <li>0D12 16进制电压</li> <li>0003 16进制开锁次数</li> <li>0003 16进制总开锁次数</li> <li>11 之心指令后状态 [00关/10开]</li> </ul> <p>对比两次回复 </p> <ul> <li>00-&gt;01 表示打开成功 </li> <li>00-&gt;00 表示打开失败 </li> <li>01-&gt;01 表示打开成功</li> </ul> <h4>改密码指令24</h4> <p>指令id:24</p> <p>密钥:认证串+8字符密码(字符串拼接)通过hex_md5加密后toUpperCase().substring(0, 8)</p> <p>参数:8字符新密码</p> <p>写characteristicId-write</p> <pre><code class="language-javascript"> // act 指令 // sendresB 8字符新密码 // md5p 密钥 function getValue(act,md5p,sendresB){ let sendresA = act + md5p + sendresB; let l = sendresA.length let buffer = new ArrayBuffer(l) let dataView = new DataView(buffer) for (var i = 0; i &amp;lt; sendresA.length; i++) { dataView.setUint8(i, sendresA.charAt(i).charCodeAt()) } return buffer } </code></pre> <p>通知characteristicId-notify:转换为ASCII字符串<code>340d120003000310</code></p> <p>如果为3400000000000000 表示旧密码验证错误</p> <p>断开连接后重新连接生效</p> <h4>改名称25</h4> <p>指令id:24</p> <p>密钥:认证串+8字符密码(字符串拼接)通过hex_md5加密后toUpperCase().substring(0, 8)</p> <p>参数:10字符新名称</p> <p>写characteristicId-write</p> <pre><code class="language-javascript"> // act 指令 // sendresB 10字符新名称 // md5p 密钥 function getValue(act,md5p,sendresB){ let sendresA = act + md5p + sendresB; let l = sendresA.length let buffer = new ArrayBuffer(l) let dataView = new DataView(buffer) for (var i = 0; i &amp;lt; sendresA.length; i++) { dataView.setUint8(i, sendresA.charAt(i).charCodeAt()) } return buffer } </code></pre> <p>通知characteristicId-notify:转换为ASCII字符串<code>350d120003000310</code></p> <p>如果为3500000000000000 表示密码验证错误</p> <p>断开连接后重新连接生效</p> <h4>查询当前状态26</h4> <p>指令id:26</p> <p>密钥:(认证串)toUpperCase().substr(10,8) // 此处不需要密码和md5 直接切</p> <p>写characteristicId-write</p> <pre><code class="language-javascript">// act 指令 // unp 直接切的认证串 function getValue(act,unp){ let sendresA = act + unp; let l = sendresA.length; let buffer = new ArrayBuffer(l) let dataView = new DataView(buffer) for (var i = 0; i &amp;lt; sendresA.length; i++) { dataView.setUint8(i, sendresA.charAt(i).charCodeAt()) } return buffer }</code></pre> <p>通知characteristicId-notify:<code>360d120003000310</code></p> <p>解析规则与21指令回复一致</p> <h4>写配置27【业务配置】</h4> <p>指令id:27</p> <p>密钥:认证串+8字符密码(字符串拼接)通过hex_md5加密后toUpperCase().substring(0, 8)</p> <p>参数:16进制的字符串规则为上述(图一)</p> <p>写characteristicId-write</p> <pre><code class="language-javascript">// act 指令id // md5p 密钥 // params 参数 const genValue = function (act, md5p,params) { let sendresA = act + md5p; let sendresB = params let l = sendresA.length + (sendresB.length / 2) let buffer = new ArrayBuffer(l) let dataView = new DataView(buffer) for (var i = 0; i &amp;lt; sendresA.length; i++) { dataView.setUint8(i, sendresA.charAt(i).charCodeAt()) } let mlist = [] for (let index = 0; index &amp;lt; sendresB.length; index++) { if (index % 2 == 0) { mlist.push(sendresB.substr(index, 2)) } } for (let index = 0; index &amp;lt; mlist.length; index++) { const element = parseInt(mlist[index], 16); dataView.setUint8(10 + index, element) } return buffer }</code></pre> <p>通知characteristicId-notify:转换为ASCII字符串<code>370d120003000310</code></p> <p>如果为3700000000000000 表示密码验证错误</p> <p>断开连接后重新连接生效</p> <h4>写配置28【系统配置】</h4> <p>指令id:28</p> <p>密钥:认证串+8字符密码(字符串拼接)通过hex_md5加密后toUpperCase().substring(0, 8)</p> <p>参数:16进制的字符串规则为上述(图二)</p> <p>写characteristicId-write</p> <pre><code class="language-javascript">// act 指令id // md5p 密钥 // params 参数 const genValue = function (act, md5p,params) { let sendresA = act + md5p; let sendresB = params let l = sendresA.length + (sendresB.length / 2) let buffer = new ArrayBuffer(l) let dataView = new DataView(buffer) for (var i = 0; i &amp;lt; sendresA.length; i++) { dataView.setUint8(i, sendresA.charAt(i).charCodeAt()) } let mlist = [] for (let index = 0; index &amp;lt; sendresB.length; index++) { if (index % 2 == 0) { mlist.push(sendresB.substr(index, 2)) } } for (let index = 0; index &amp;lt; mlist.length; index++) { const element = parseInt(mlist[index], 16); dataView.setUint8(10 + index, element) } return buffer }</code></pre> <p>通知characteristicId-notify:转换为ASCII字符串<code>380d120003000310</code></p> <p>如果为3800000000000000 表示密码验证错误</p> <p>断开连接后重新连接生效</p> <h4>读取版本29</h4> <p>指令id:29</p> <p>密钥:认证串+8字符密码(字符串拼接)通过hex_md5加密后toUpperCase().substring(0, 8)</p> <p>写characteristicId-write</p> <pre><code class="language-javascript">// act 指令 // md5p 密钥 const genValue = function (act, md5p) { let sendresA = act + md5p; let l = sendresA.length let buffer = new ArrayBuffer(l) let dataView = new DataView(buffer) for (var i = 0; i &amp;lt; sendresA.length; i++) { dataView.setUint8(i, sendresA.charAt(i).charCodeAt()) } return buffer }</code></pre> <p>通知characteristicId-notify:转换为ASCII字符串<code>39xxxx0003000310</code></p> <p><code>res.substr(2, 4)</code>即为版本信息</p> <p>如果为3900000000000000 表示密码验证错误</p> <h4>长时间开启2a</h4> <p>指令id:2a</p> <p>密钥:认证串+8字符密码(字符串拼接)通过hex_md5加密后toUpperCase().substring(0, 8)</p> <p>参数:00000000 [16进制字符串 ]</p> <p>​ 全0表示长开</p> <p>​ 最大ffffffff 单位:秒 表示开多长时间</p> <p>写characteristicId-write</p> <pre><code class="language-javascript">// act 指令id // md5p 密钥 // params 参数 const genValue = function (act, md5p,params) { let sendresA = act + md5p; let sendresB = params let l = sendresA.length + (sendresB.length / 2) let buffer = new ArrayBuffer(l) let dataView = new DataView(buffer) for (var i = 0; i &amp;lt; sendresA.length; i++) { dataView.setUint8(i, sendresA.charAt(i).charCodeAt()) } let mlist = [] for (let index = 0; index &amp;lt; sendresB.length; index++) { if (index % 2 == 0) { mlist.push(sendresB.substr(index, 2)) } } for (let index = 0; index &amp;lt; mlist.length; index++) { const element = parseInt(mlist[index], 16); dataView.setUint8(10 + index, element) } return buffer }</code></pre> <p>通知characteristicId-notify:转换为ASCII字符串<code>3a0d120003000310</code></p> <p>解析规则与21指令一致</p> <h4>关闭2b</h4> <p>指令id:2b</p> <p>密钥:认证串+8字符密码(字符串拼接)通过hex_md5加密后toUpperCase().substring(0, 8)</p> <p>写characteristicId-write</p> <pre><code class="language-javascript">// act 指令id // md5p 密钥 const genValue = function (act, md5p) { let sendresA = act + md5p; let sendresB = params let l = sendresA.length let buffer = new ArrayBuffer(l) let dataView = new DataView(buffer) for (var i = 0; i &amp;lt; sendresA.length; i++) { dataView.setUint8(i, sendresA.charAt(i).charCodeAt()) } return buffer }</code></pre> <p>通知characteristicId-notify:转换为ASCII字符串<code>3b0d120003000300</code></p> <p>解析规则与21指令一致</p> <h3>六.Demo</h3> <p>以下为Uniapp Demo 仅供参考 [uniapp-android-demo.zip](<a href="https://www.showdoc.com.cn/server/api/attachment/visitfile/sign/55bb11d576a4632806fa3495ae2074f9">https://www.showdoc.com.cn/server/api/attachment/visitfile/sign/55bb11d576a4632806fa3495ae2074f9</a> &quot;[uniapp-android-demo.zip&quot;)</p>

页面列表

ITEM_HTML