当前位置: 首页 > wzjs >正文

三亚中国检科院生物安全中心门户网站建设seo的作用主要有

三亚中国检科院生物安全中心门户网站建设,seo的作用主要有,网络哪个公司好,win7 iis7 添加网站【HarmonyOS Next】三天撸一个BLE调试精灵 一、功能介绍 BLE调试精灵APP属于工具类APP,在用户使用的过程中,负责调试BLE设备从机端,比如蓝牙耳机、低功耗设备、带有BLE的空调等设备,可以在页面中清晰看到设备的厂商,…

【HarmonyOS Next】三天撸一个BLE调试精灵

一、功能介绍

BLE调试精灵APP属于工具类APP,在用户使用的过程中,负责调试BLE设备从机端,比如蓝牙耳机、低功耗设备、带有BLE的空调等设备,可以在页面中清晰看到设备的厂商,拥有扫描设备、连接设备、发送测试数据等主要的功能。当通过BLE调试精灵APP调试时,可以方便快捷的查看设备的属性。

本APP包含以下功能:

  • 扫描BLE从机设备
  • 区分从机设备的厂商
  • 广播包解析展示
  • 连接设备
  • 展示服务和特征值
  • 特征值的读、写、通知
  • 根据MTU分包大数据发送

在这里插入图片描述

二、基本知识

在实现BLE调试APP之前,需要对BLE有基本的了解。

  • BLE是低功耗蓝牙,用于可穿戴设备,IoT智能设备等众多物联网设备,功耗低、带宽也低。不同于经典蓝牙,经典蓝牙功耗高、带宽高。
  • BLE分为主机和从机,主动连接其它设备的是主机,比如手机是主机,可穿戴设备等是从机
  • 在有些平台下需要先扫描才能进行连接。
  • 在纯血鸿蒙平台下,从机的MAC地址无法获取,而是被包装成了deviceId,类似于某水果平台。
  • 广播中厂商信息、UUID有一定的规范,厂商可对应具体的厂家,由蓝牙技术联盟分配,UUID有比如获取电量等服务。
  • 连接的过程中通常会自定义超时时间、重连次数。
  • 下发数据时通常会根据MTU进行数据包的分割。
  • 基本的字节操作。

三、技术解析

1. 侧边栏容器

SideBarContainer 组件是鸿蒙的内置组件,配合状态管理,可以很轻松的实现侧边栏展示与隐藏的效果。
用内置属性controlButton展示不同的按钮,用@State tabShow控制侧边栏展示与隐藏的状态,用背景颜色达到蒙版的效果。

 SideBarContainer(SideBarContainerType.Overlay) {Column() {DrawerTab();}.height('100%')Column() {MainPage({ tabShow: this.tabShow })}.onClick(() => {animateTo({duration: 500,curve: Curve.EaseOut,playMode: PlayMode.Normal,}, () => {this.tabShow = false;})}).width('100%').height('100%').backgroundColor(this.tabShow ? '#c1c2c4' : '')}.showSideBar(this.tabShow).controlButton({left: 6,top: 6,height: 40,width: 40,icons: {shown: $r("app.media.tab_change_back"),hidden: $r("app.media.tab_change"),switching: $r("app.media.tab_change")}}).onChange((value: boolean) => {this.tabShow = value;})
2. BLE扫描

startBLEScan 方法进行扫描,使用ScanFilter进行扫描过滤,使用ScanOptions可传入扫描的配置,比如用最快速的响应扫描所有的设备。
BLEDeviceFind 监听该事件接收扫描的结果回调。

      ble.on("BLEDeviceFind", this.onReceiveEvent);let scanFilter: ble.ScanFilter = {//name: scanName,};let scanOptions: ble.ScanOptions = {interval: 0,dutyMode: ble.ScanDuty.SCAN_MODE_LOW_LATENCY,matchMode: ble.MatchMode.MATCH_MODE_AGGRESSIVE}ble.startBLEScan([scanFilter], scanOptions);

当扫描到一定时间时,停止扫描。

       // 取消上一次定时器if (this.mScanTimerId != 0) {clearTimeout(this.mScanTimerId)}this.mScanTimerId = setTimeout(() => {BleLogger.debug(TAG, "setTimeout")this.stopBLEScan();if (this.mCallback) {this.mCallback.scanFinish();}}, scanTime);

扫描到结果ble.ScanResult对象,包含deviceId、广播包等数据,deviceId相当于本次扫描过程中的设备的唯一标识,可在后续的流程中用于连接;广播包一般是31个字节,在BLE5.0及以上可超出31个字节,使用拓展广播包,广播包由LTV格式构成,可以在LTV格式中解析出厂商代码,厂商代码可对应成具体厂家。

解析LTV格式:

/*** LTV格式数据*/
export class LtvInfo {length: number;tag: number;value: Uint8Array;constructor(length: number, tag: number, value: Uint8Array) {this.length = length;this.tag = tag;this.value = value;}
}export class BleBeaconUtil2 {/*** 解析 BLE 广播数据* @param advData 广播数据字节数组* @returns 解析结果的 Map,键是数据类型,值是对应的数据内容*/public static parseData(advData: Uint8Array): Array<LtvInfo> {let result: Array<LtvInfo> = []; // 存放解析后的结果let index = 0; // 用于遍历数据while (index < advData.length) {let length = advData[index]; // 获取当前数据单元的长度index++;if (length === 0) {break; // 长度为 0 时结束解析}const type = advData[index]; // 获取数据类型index++;const data = advData.slice(index, index + length - 1); // 获取实际数据index += length - 1; // 更新索引// 根据不同类型解析数据let ltvInfo: LtvInfo = BleBeaconUtil2.parseDataType(length, type, data);result.push(ltvInfo);}return result; // 返回解析后的数据}/*** 根据广播数据的类型解析具体的数据* @param type 数据类型* @param data 对应类型的数据* @param result 存放解析结果的对象*/private static parseDataType(length: number, type: number, data: Uint8Array): LtvInfo {return new LtvInfo(length, type, data);}
}

获取厂商代码,厂商代码和厂家对应信息应构成Map<number, string>数据结构,具体厂商代码在该网址下进行获取
https://bitbucket.org/bluetooth-SIG/public/raw/HEAD/assigned_numbers/company_identifiers/company_identifiers.yaml

 /*** 获取厂商代码* @returns*/public getManufacturerData(ltvArray: Array<LtvInfo>): number {let manufacturerData = new Uint8Array(2);if (ltvArray.length == 0) {return 0;}for (const ltvInfo of ltvArray) {if (ltvInfo.tag === 0xff) {if (ltvInfo.value && ltvInfo.value.length > 2) {manufacturerData[0] = ltvInfo.value[1];manufacturerData[1] = ltvInfo.value[0];return ByteUtils.byteToShortBig(manufacturerData);}}}return 0;}
3. BLE连接

GattClientDevice.connect 传入deviceId用于连接,可自定义超时逻辑。

  /*** 开始链接* @param deviceId*/private connect(deviceId: string) {this.notifyConnectStart(deviceId);this.mDevice = ble.createGattClientDevice(deviceId);this.mDevice.on('BLEConnectionStateChange', this.ConnectStateChanged.bind(this));try {this.mDevice.connect();} catch (e) {// todo 比如,蓝牙突然关闭时的错误this.notifyConnectError(BleException.ERROR_CODE_CONNECT_10001, this.mDeviceId);return;}this.cancelTimeoutRunnable();this.startTimeoutRunnable(this.mConnectTimeout);}

在核心回调中处理连接成功或失败的状态,抛给业务层。值得注意的是,并不是连接成功之后就算业务上的连接成功,还需要发现服务,如需进行数据交互,还需要启用通知->设置MTU操作,都完成之后,才是业务层面的连接成功。

4. 获取服务和特征值

BLE丛机包含多个服务,每个服务都有一个UUID,主服务下可包含多个子服务,子服务下可以包含多个特征值。

连接成功之后得到services: Array<ble.GattService>,从中循环取出服务和特征值并展示。

 List() {ForEach(this.deviceInfo.services, (item: ble.GattService) => {ListItem() {/* item view */ServiceItemView({ item: item, deviceId: this.deviceInfo.deviceId })}})}List() {ForEach(this.item.characteristics, (itemChild: ble.BLECharacteristic) => {ListItem() {Column() {Text(this.getName(itemChild.characteristicUuid)).fontSize($r('app.float.font_normal')).fontWeight(FontWeight.Bold)BlockView({ block: 2 })Text('UUID:' + itemChild.characteristicUuid).fontSize(12)BlockView({ block: 2 })Text('可操作属性')ServiceItemButtonView({ itemChild: itemChild, deviceId: this.deviceId })// 子服务-描述符if (itemChild.descriptors) {ForEach(itemChild.descriptors, (itemChildDes: ble.BLEDescriptor) => {ListItem() {Column() {Text('Descriptors').fontSize($r('app.float.font_normal')).fontWeight(FontWeight.Bold)BlockView({ block: 2 })Text('UUID:' + itemChildDes.descriptorUuid).fontSize(12)}.alignItems(HorizontalAlign.Start)}})}}.alignItems(HorizontalAlign.Start).width('100%').padding({left: 30,right: 10,top: 10,bottom: 10})}})}.divider({strokeWidth: 1,color: '#cccccc'}).backgroundColor('#eeeeee')
5. 特征值

特征值一共有五个。

  • Read:可读取数据(如设备名称、电量)
  • Write:可写入数据(如配置参数)
  • Notify:丛机主动通知主机(无需确认)
  • Indicate:丛机通知主机(需确认,比Notify多了一个确认)
  • Write Without Response:写入无需回复(低延迟,如控制指令)

用最常见的数据通信举例,主机给丛机发送一个文件数据,丛机给主机回复收到。

this.mDeviceble.GattClientDevice对象,在连接时根据createGattClientDevice获取。

首先请求设置MTU,拿到MTU之后,再对数据进行分包

private mtuChangeCallback = (mtu: number) => {BleLogger.debug(TAG, 'set mtu change:' + mtu)if (!this.mDeviceId) {this.notifyError(BleException.ERROR_CODE_CONNECT_10009, this.mDeviceId);return;}let bluetoothGatt = BleConnectionList.getInstance().get(this.mDeviceId);if (!bluetoothGatt) {this.notifyError(BleException.ERROR_CODE_CONNECT_10009, this.mDeviceId);return;}bluetoothGatt.off('BLEMtuChange', this.mtuChangeCallback);BLESdkConfig.getInstance().setBleMaxMtu(mtu);this.notifySuccess(mtu, this.mDeviceId);}

将分隔的组成一个队列,队列中每个数据的长度是MTU

let queuePacket: Queue<Uint8Array> =BleDataUtils.splitByte(requestPacket, BLESdkConfig.getInstance().getBleMaxMtu());

将数据依次取出,然后发送数据

let data: Uint8Array = this.mDataQueue.pop();
let bluetoothGatt = BleConnectionList.getInstance().get(this.mDeviceId!);
// 携带数据
this.mBleCharacteristic.characteristicValue = this.typedArrayToBuffer(data);
bluetoothGatt.writeCharacteristicValue(this.mBleCharacteristic, this.mWriteType,
this.writeCharacteristicValueCallBack.bind(this))

至此功能讲解完毕,有问题欢迎沟通。

http://www.dtcms.com/wzjs/285109.html

相关文章:

  • 长沙整合推广2023网站seo
  • 网站维护电话2345系统导航
  • 个人简历网免费模板seo网站有优化培训班吗
  • 英国做电商网站有哪些郑州seo价格
  • wordpress在本地建站seo短视频加密路线
  • 网站建设参考文献2017软文范例100字以内
  • 网络服务器主要有系统优化app最新版
  • 网站开发人员工资计入无形资产拼多多标题关键词优化方法
  • 做电影网站赚钱的方法网络优化初学者难吗
  • 什么样的网站高大上余姚关键词优化公司
  • 宜城网站建设推广营销大的公司
  • 视频网站开发背景公司宣传网站制作
  • 政府门户网站程序百度图片
  • 做网站怎么让百度收录了百度推广关键词价格查询
  • 企业文化建设的内容有哪些泰安seo公司
  • 男和男做那个视频网站好微信公众号软文怎么写
  • 昆明酒店网站建设班级优化大师下载安装app
  • 日历api接口杭州网站推广与优化
  • 网上代做论文的网站好软文是什么意思?
  • 西安制作公司网页多少钱百度seo快速排名优化
  • 国外网站能否做百科参考资料济南公司网站推广优化最大的
  • 闵行做网站公司怎么做seo
  • 网站建设教程免费夕滋湖南岚鸿官网百度助手官网
  • 网站域名到期如何续费网络推广外包要多少钱
  • 做养生类项目的网站百度seo排名点击器app
  • 做媛网站线在成都网站推广公司
  • 平台公司是什么意思福州seo技术培训
  • 盐城建设公司网站网站排名优化
  • 青海省建设局网站首页友情链接作用
  • 网络有哪些广告推广方式seo实战培训王乃用