HarmonyOS基于LYEVK-3861开发火焰报警系统

想了解更多内容,火焰请访问:

和华为官方合作共建的系统鸿蒙技术社区

https://harmonyos.51cto.com

前言

在各种灾害中,火灾是火焰最经常、最普遍地威胁公众安全和社会发展的系统主要灾害之一。火给人类带来文明进步、火焰光明和温暖。系统但是火焰,有时它是系统人类的朋友,有时是火焰人类的敌人。失去控制的系统火,就会给人类造成灾难。火焰说到火灾的系统控制,一套火焰感应报警系统就有其价值了。火焰那我们如何去检测火焰呢?系统

本文内容主要讲述基于LYEVK-3861物联网开发板套件的火焰传感器,开发一个具有火焰感应报警功能的火焰HarmonyOS应用,主要实现蓝牙设备扫描,连接,检测火焰,设置报警阈值。

1.效果演示

2.环境准备

本贴不对实验环境搭建做详细说明。具体准备实验环境请参考:

《HarmonyOS 官方文档》 LYEVK-3861 物联网开发板套件

3.蓝牙通信说明

3.1 蓝牙通信协议:

3.2 蓝牙通信流程:

3.3 数据透传协议:

3.3.1 串口协议:

3.3.2 数据协议:

(permission P:APP下发;G:设备请求;R:设备上报)

4.开发调试

蓝牙交互封装BleHelper工具类,通过BLE扫描和广播提供的亿华云开放能力,可以根据指定状态获取外围设备、启动或停止BLE扫描、广播。

4.1 进行BLE扫描

MyBleCentralManagerCallback继承BleCentralManagerCallback类实现scanResultEvent和scanFailedEvent回调函数,用于接收扫描结果。 BleCentralManager(BleCentralManagerCallback callback)接口获取中心设备管理对象。 调用startScan()扫描蓝牙设备。 /**    * 扫描设备    * @param filters 设备过滤器    * @since 2021-10-09    */   public void startScan(List<BleScanFilter> filters) {        centralManager = new BleCentralManager(context, new MyBleCentralManagerCallback());       centralManager.startScan(filters);   }   /**    * 扫描设备回调    *    * @since 2021-10-09    */   private class MyBleCentralManagerCallback implements BleCentralManagerCallback {        // 扫描结果的回调       @Override       public void scanResultEvent(BleScanResult bleScanResult) {            if (mBleManagerCallback != null) {                mBleManagerCallback.scanResultCallback(bleScanResult);           }           // 获取广播数据中的服务uuids           List<UUID> uuids = bleScanResult.getServiceUuids();           for (UUID uuid : uuids) {                if (SERVICE_UUID.equals(uuid.toString())) {                    peripheralDevice = bleScanResult.getPeripheralDevice();                   int length = peripheralDevice.toString().length();                   String deviceId = peripheralDevice.toString().substring(length - CUT_LENGTH, length);                   stopScan();                   bleConnect();               }           }       }       // 扫描失败回调       @Override       public void scanFailedEvent(int event) {            HiLog.debug(loglabel, "扫描失败 scanFailedEvent()");       }       // 组扫描成功回调       @Override       public void groupScanResultsEvent(List<BleScanResult> list) {            // 使用组扫描时在此对扫描结果进行处理       }   } 

4.2 建立连接

扫描成功,匹配服务UUID FFB0,调用bleConnect()连接开发板蓝牙。 触发connectionStateChangedEvent(int connectionState)回调,connectionState=2连接成功,然后调用discoverServices()接口发现服务。 在回调servicesDiscoveredEvent(int status)中获取外围设备支持的服务和特征值,此时才能调用read和write方法读取或者写入对应特征值数据。 characteristicChangedEvent(GattCharacteristic characteristic)特征变更的回调中,解析传感器上报数据、校验等。具体数据解析逻辑在ProtocolEntity中parseCharacteristic(String hexStr)方法。 /**    * 连接到BLE外围设备    *    * @since 2021-10-09    */   public void bleConnect() {        peripheralDevice.connect(false, new BlePeripheralCallback() {            // 在外围设备上发现服务的回调           @Override           public void servicesDiscoveredEvent(int status) {                super.servicesDiscoveredEvent(status);               if (status == BlePeripheralDevice.OPERATION_SUCC) {                    HiLog.debug(loglabel, "发现服务成功 servicesDiscoveredEvent()");                   for (GattService service : peripheralDevice.getServices()) {                        checkGattCharacteristic(service);                   }                   if (mBleManagerCallback != null) {                        mBleManagerCallback.connectCallback(status);                   }               }           }           private void checkGattCharacteristic(GattService service) {                for (GattCharacteristic tmpChara : service.getCharacteristics()) {                    if (tmpChara.getUuid().equals(UUID.fromString(NOTIFY_CHARACTER_UUID))) {                        // 启用特征通知                       peripheralDevice.setNotifyCharacteristic(tmpChara, true);                   }                   if (tmpChara.getUuid().equals(UUID.fromString(WRITE_CHARACTER_UUID))) {                        // 获取GattCharacteristic                       writeCharacteristic = tmpChara;                   }               }           }           // 连接状态变更的回调           @Override           public void connectionStateChangeEvent(int connectionState) {                super.connectionStateChangeEvent(connectionState);               if (connectionState == ProfileBase.STATE_CONNECTED && !isConnected) {                    HiLog.debug(loglabel, "连接成功 connectionStateChangeEvent() connectionState:" + connectionState);                   isConnected = true;                   // 连接成功在外围设备上发现GATT服务,部分手机发现服务失败,需要延迟调用discoverServices()                   peripheralDevice.discoverServices();               }           }           // 特征变更的回调           @Override           public void characteristicChangedEvent(GattCharacteristic characteristic) {                super.characteristicChangedEvent(characteristic);               byte[] value = characteristic.getValue();               if (value == null) return;               String toHexStr = DataUtils.toHex(value);               boolean isVerify = BleHelper.verifyProtocol(toHexStr);//校验               if (isVerify) {                    if (protocolEntity == null) {                        protocolEntity = new ProtocolEntity();                   }                   protocolEntity.parseCharacteristic(toHexStr);                   if (mBleManagerCallback != null) {                        mBleManagerCallback.characteristicChangedCallback(protocolEntity, toHexStr);                   }               }           }       });   } 

4.3 预警阈值下发

设置火焰报警距离阈值,tagId为0002,当火焰传感器发现火焰,并小于此设置的网站模板阈值时,设备上报预警。 通过发现服务servicesDiscoveredEvent()回调获取的writeCharacteristic特征,写入数据。数据下发格式按照3.3数据透传协议。 /**      * 主动去获取所Tag设备数据,通过Write(消息类型0x01), Notify接收数据      */     public void readInitiativeByTags(List<String> tagIds) {          String hex = getTagsCommandHexStr(tagIds);         bleManagerWrite(hex);     }     /**      * 写Tag设备数据,通过Write(消息类型0x01), Notify接收数据      */     public void writeBleByTag(String tagId, String value) {          String hex = getTagCommandHexStr(tagId, Integer.parseInt(value));         bleManagerWrite(hex);     }     private void bleManagerWrite(String hex) {          if (peripheralDevice == null) {              return;         }         writeCharacteristic.setValue(hex.getBytes(StandardCharsets.UTF_8));         peripheralDevice.writeCharacteristic(writeCharacteristic);     }     /**      * 获取所有Tag数据的Write指令      *      * @param tagIds tag集      */     private String getTagsCommandHexStr(List<String> tagIds) {          try {              StringBuilder sb = new StringBuilder();             String byte1 = PROTOCOL_ID; //串口协议标识             String byte2 = PROTOCOL_VERSION;             String byte3 = TYPE_OBTAIN;             int dataLen = 8 * tagIds.size();             String byte4 = DataUtils.encodeHex(dataLen, 4);             String byteTagLen = DataUtils.encodeHex(4, 4);             String byteTagValue = "00000000";             StringBuilder sbTag = new StringBuilder();             for (String it : tagIds) {                  sbTag.append(it).append(byteTagLen).append(byteTagValue);             }             sb.append(byte1).append(byte2).append(byte3).append(byte4).append(sbTag);             String hexStrSum = DataUtils.makeChecksum(sb.toString());             int protocolVerify = DataUtils.decodeHEX(hexStrSum) % 256;             String byteLast = DataUtils.encodeHex(protocolVerify);             sb.append(byteLast);             return sb.toString();         } catch (Exception e) {              e.printStackTrace();         }         return "";     }     /**      * 获取单个Tag数据的Write指令      *      * @param tagId  0001      * @Param value  写入值      */     private String getTagCommandHexStr(String tagId, int value) {          try {              StringBuilder sb = new StringBuilder();             String byte1 = PROTOCOL_ID; //串口协议标识             String byte2 = PROTOCOL_VERSION;             String byte3 = TYPE_ISSUED;             int dataLen = 8;             String byte4 = DataUtils.encodeHex(dataLen, 4);             String byteTagId = tagId;             String byteTagLen = DataUtils.encodeHex(4, 4);             String byteTagValue = DataUtils.encodeHex(value, 8);             sb.append(byte1).append(byte2).append(byte3).append(byte4)                    .append(byteTagId).append(byteTagLen).append(byteTagValue);             String hexStrSum = DataUtils.makeChecksum(sb.toString());             int protocolVerify = DataUtils.decodeHEX(hexStrSum) % 256;             String byteLast = DataUtils.encodeHex(protocolVerify);             sb.append(byteLast);             return sb.toString();         } catch (Exception e) {              e.printStackTrace();         }         return "";     } 

4.4 火焰距离上报

火焰距离上报,通知应用,开始预警。 通过3.3数据透传协议,解析设备上报的火焰距离。 /**   * 协议校验 (从协议标识首节至协议内容尾字节求累加和后再对 256 取余)   *   * @param hexStr 带空格的 A5 5A 01 00 00 08 00 02 00 04 00 00 00 8C   */  public static boolean verifyProtocol(String hexStr) {       if (hexStr.isEmpty()) return false;      String checkHex = hexStr.substring(0, hexStr.lastIndexOf(" "));      String lastHex = hexStr.substring(hexStr.lastIndexOf(" ") + 1);      String hexStrSum = DataUtils.makeChecksum(checkHex);      return DataUtils.decodeHEX(hexStrSum) % 256 == DataUtils.decodeHEX(lastHex);  }  /**    * 根据串口协议解析    */   public boolean parseCharacteristic(String hexStr) {        try {            String[] hexs = hexStr.split(" ");           version = DataUtils.decodeHEX(hexs[2]);           messageType = DataUtils.decodeHEX(hexs[3]);           dataLen = DataUtils.decodeHEX(hexs[4] + hexs[5]);           for (int i = 0; i < dataLen / 8; i++) {                int startIndex = 6 + (i * 8);               DeviceData deviceData = new DeviceData();               deviceData.tagId = DataUtils.decodeHEX(hexs[startIndex] + hexs[startIndex + 1]);               deviceData.len = DataUtils.decodeHEX(hexs[startIndex + 2] + hexs[startIndex + 3]);               deviceData.value = DataUtils.decodeHEX(hexs[startIndex + 4] + hexs[startIndex + 5] +                       hexs[startIndex + 6] + hexs[startIndex + 7]);               deviceListMap.put(deviceData.tagId, deviceData);           }           protocolVerify = DataUtils.decodeHEX(hexs[6 + dataLen]);       } catch (Exception e) {            e.printStackTrace();           return false;       }       return true;   } 

5.结语

以上就是LYEVK-3861物联网开发板火焰传感器的预警功能,和应用程序交互的一个相对简单的流程。场景的交互还有很多种,比如在此基础上搭建远程云端系统,实现远程火焰监控实时预警。有兴趣的伙伴也可以根据开发板其他传感器组合成不同的智能场景。

想了解更多内容,请访问:

和华为官方合作共建的鸿蒙技术社区

https://harmonyos.51cto.com

云服务器
滇ICP备2023000592号-31