分布式软总线APP开发简介

AIOT作为互联网发展新趋势,万物互联逐渐成为行业焦点。分布式软总线是手机、平板、智能穿戴、智慧屏、车机等分布式设备的通信基座,开发者只需聚焦于业务逻辑的实现,无需关注组网方式与底层协议。AIOT演示 APP 主要用于分布式通讯演示,实现了 HarmonyOS 、欧拉系统以及聚元 PolyOS 之间基于分布式软总线的互联互通。

开发平台

  • 硬件平台:DAYU200开发板。

  • 软件平台:ARM64鸿蒙操作系统-OpenHarmony 3.1.3 Release

  • 开发修改内容:

    (1)foundationdistributedhardwaredevicemanager库修改。新增软总线的操作代码,新增软总线API接口,供APP调用。

    (2)basesecurity,修改权限管理问题。

APP核心代码

AIOT演示 APP 分布式软总线数据处理核心代码如下:

 import fileio from '@ohos.fileio';
 import prompt from'@system.prompt';
 import mediaLibrary from '@ohos.multimedia.mediaLibrary';
 import image from '@ohos.multimedia.image';
 import { calc, isOperator } from '../../common/calculator.js';
 import app from '@system.app';
 import RemoteDeviceModel from '../../common/RemoteDeviceModel.js';
 import featureAbility from '@ohos.ability.featureAbility';
 import ohos_data_ability from '@ohos.data.dataAbility';
 import { KvStoreModel } from '../../common/kvstoreModel.js';
 import ohos_data_rdb from '@ohos.data.rdb';
 import dataUriUtils from '@ohos.ability.dataUriUtils';

 let pressedEqual = false;
 let Isauto = false;
 let ReadRomotedata = "";
 let oprationResult = "";
 let kvStoreModel = new KvStoreModel();
 let remoteDeviceModel = new RemoteDeviceModel()
 let timerId = 0

 export default {
   data: {
     title: '图片推理',
     expression: '',
     result: '',
     selectedIndex: 1,
     itemNum: 0,
     imageNum: 0,
     isFA: false,
     isPush: false,
     isDistributed: false,
     deviceList: []
   },
   onInit() {
     this.grantPermission()
     this.$watch('expression', (value) => {
       if (value !== '') {
         console.info('Aiot[IndexPage] value  ' + value);
         console.info('Aiot[IndexPage] result =  ' + this.result);
         console.log('Aiot[IndexPage] put key start');
       }
     });
     this.initKVManager();
   },
   onShow() {
     featureAbility.getWant((error, want) => {
       console.info('Aiot[IndexPage] featureAbility.getWant =' + JSON.stringify(want.parameters));
       if (want.parameters.isFA === 'FA') {
         this.isFA = true;
         this.isDistributed = true;
       }
     });
   },
   grantPermission() {
     let context1 = featureAbility.getContext()
     let permissions = ["ohos.permission.DISTRIBUTED_DATASYNC","ohos.permission.READ_USER_STORAGE"];
      context1.requestPermissionsFromUser(permissions, 666, function (result) {
       console.info(`Aiot[IndexPage] grantPermission,requestPermissionsFromUser,result.requestCode=${result}`)
     })
    },
   dataChange(key, value) {
    console.log('Aiot[IndexPage] dataChange isDistributed = ' + this.isDistributed);
     if (this.isDistributed && kvStoreModel != null) {
       kvStoreModel.put(key, value);
     }
   },
   initKVManager() {
     kvStoreModel.setOnMessageReceivedListener('expression', (value) => {
       console.log('Aiot[IndexPage] data changed:' + value);
       if (value === 'exit') {
         console.info('Aiot[AiotPage] app exit!');
         app.terminate();
         return;
       }
       if (value === 'clear') {
         console.log('Aiot[IndexPage] data expression:clear');
         this.expression = '';
         this.result = '';
         return;
       }
       if (value === 'equal') {
         if (this.result !== '') {
           console.log('Aiot[IndexPage] data expression:equal');
           this.expression = this.result;
           this.result = '';
           pressedEqual = true;
         }
         return;
       }
       this.expression = value;
       pressedEqual = false;
       console.log('Aiot[IndexPage] data expression:' + this.expression);
      });
     timerId = setInterval(() => {
       if (this.isDistributed) {
         let temp = this.expression;
         this.expression = temp;
       }
     }, 200);
   },
   stopDataListener() {
     console.log('Aiot[IndexPage] stopDataListener');
     if (kvStoreModel === null || kvStoreModel === undefined) {
       return
     }
     kvStoreModel.off()
   },
   onHide() {
     if (remoteDeviceModel === undefined) {
       return
   }
     remoteDeviceModel.unregisterDeviceListCallback();
     if (this.isDistributed && kvStoreModel != null) {
       this.stopDataListener();
       this.isDistributed = false;
    }
     clearInterval(timerId)
     kvStoreModel = null
     remoteDeviceModel = undefined
   },
    showDialog() {
     console.info('Aiot[IndexPage] showDialog start');
      this.deviceList = [];
      if (remoteDeviceModel === undefined) {
      remoteDeviceModel = new RemoteDeviceModel()
    }
     remoteDeviceModel.registerDeviceListCallback(() => {
        console.info('Aiot[IndexPage] registerDeviceListCallback on remote device updated, count='
       + remoteDeviceModel.deviceList.length);
        let list = [];
       list.push({
         deviceId: '0',
         deviceName: 'Local-OpenHarmony-V3.1.3',
         deviceType: 0,
         networkId: '',
         checked: this.selectedIndex === 0
      });
    let tempList = remoteDeviceModel.discoverList.length > 0 ? remoteDeviceModel.discoverList : remoteDeviceModel.deviceList;
    for (let i = 0; i < tempList.length; i++) {
      console.info('Aiot[IndexPage] device ' + i + '/' + tempList.length
      + ' deviceId=' + tempList[i].deviceId + ' deviceName=' + tempList[i].deviceName
      + ' deviceType=' + tempList[i].deviceType);
      list.push({
        deviceId: tempList[i].deviceId,
        deviceName: tempList[i].deviceName,
        deviceType: tempList[i].deviceType,
        networkId: tempList[i].networkId,
        checked: this.selectedIndex === (i + 1)
      });
    }
    this.deviceList = list;
    this.$element('showDialog').close();
    this.$element('showDialog').show();
  });
},
cancelDialog() {
  this.$element('showDialog').close();
  if (remoteDeviceModel === undefined) {
    return;
  }
  remoteDeviceModel.unregisterDeviceListCallback();
},
SelectAppImage1() {
  this.imageNum = 1;
  this.expression = "111111111111111";
  },
SelectAppImage2() {
  this.imageNum = 2;
  this.expression = "2222222222222222";
  },
SelectAppImage3() {
  this.imageNum = 3;
  this.expression = "3333333333333333";
  },
SelectImageFile() {
   let option = {
   type: "media",
   count: 5
  };
mediaLibrary.getMediaLibrary().startMediaSelect(option, (err, result) => {
if (result) {
      result.forEach((value) => {
      console.log("value: " + value);
      this.imageNum = dataUriUtils.getId(value);
      let filename = '/common/hcg'+ this.imageNum + '.png';
      const el = this.$refs.canvas;
      var ctx = el.getContext('2d');
      var img = new Image();
      img.src = filename;
      img.onload = function () {
      console.log('Image load success');
      ctx.drawImage(img, 0, 0, 360, 250);
         };
      })
      } else {
              console.log("error: " + JSON.stringify(err));
            }
         });
      },
      ReadRevImage(){

      const el = this.$refs.canvashcg;
      var ctx = el.getContext('2d');
      var img = new Image();
      img.src = '/common/recv.png';
      img.onload = function () {
      console.log('Image load success');
      ctx.drawImage(img, 0, 0, 360, 250);
         };
      },
      selectDevice(item) {
      let index = this.deviceList.indexOf(item);
      this.itemNum = index;
      console.log(' HCG Aiot[IndexPage] select index:' + index);
      console.log(' HCG Aiot[IndexPage] select this.itemNum :' + this.itemNum );
      console.log(' hcg Aiot[IndexPage] select selectedIndex:' + this.selectedIndex);
      if (index === this.selectedIndex) {
      console.log('Aiot[IndexPage] index === this.selectedIndex');
      remoteDeviceModel.authenticateDevice(this.deviceList[index], () => {
              console.log('Aiot[IndexPage] auth and online finished');
              this.startAbility(this.deviceList[index].deviceId);
      });
      prompt.showDialog({
              title:" 提示",
              message:"已经开始认证,请耐心等待认证结果",
              buttons:[{"text":"确认","color":"#000000"}, {"text":"","color":"#000000"}],
      })
      setTimeout(function(){
              let Filepath = "/data/accounts/account_0/appdata/ohos.samples.aiotdemo/files/result.txt";
              let fd = fileio.openSync(Filepath, 0o2|0o100, 0o666);
              let buf = new ArrayBuffer(4096);
              fileio.read(fd, buf);
              let result = String.fromCharCode.apply(null, new Uint8Array(buf));
              oprationResult = result;
              prompt.showDialog({
              title:" 认证结果",
              message:result,
              buttons:[{"text":"确认","color":"#000000"}, {"text":"","color":"#000000"}],
              })

              fileio.close(fd);

      }, 20000);

      }
      this.selectedIndex = index;
      if (index === 0) {
      console.log('Aiot[IndexPage] stop ability');
      this.dataChange('expression', 'exit');
      this.isDistributed = false;
      this.stopDataListener();
      this.clearSelectState();
      return;
      }
      console.log('Aiot[IndexPage] start ability ......');
      this.isDistributed = true;
      if (remoteDeviceModel === undefined || remoteDeviceModel.discoverList.length <= 0)
      {
      console.log('Aiot[IndexPage] continue device:' + JSON.stringify(this.deviceList));
      this.startAbility(this.deviceList[index].deviceId);
      this.clearSelectState();
      return;
      }
      console.log('Aiot[IndexPage] start ability1, needAuth');
      remoteDeviceModel.authenticateDevice(this.deviceList[index], () => {
      console.log('Aiot[IndexPage] auth and online finished');
      this.startAbility(this.deviceList[index].deviceId);
      });
      this.clearSelectState();
      console.log('Aiot[IndexPage] start ability end....');
      },
      clearSelectState() {
      this.deviceList = [];
      this.$element('showDialog').close();
      },
      async startAbility(deviceId) {
      console.log('Aiot[IndexPage] startAbility deviceId:' + deviceId);
      await featureAbility.startAbility({
      want: {
              bundleName: 'ohos.samples.aiotdemo',
              abilityName: 'ohos.samples.aiotdemo.MainAbility',
              deviceId: deviceId,
              parameters: {
              isFA: 'FA'
              }
         }
      })
      console.log('Aiot[IndexPage] start ability finished');
      this.dataChange('expression', this.expression);
      console.log('Aiot[IndexPage] startAbility end');
      },
      handleClear() {
      this.expression = '';
      this.result = '';
      console.log('Aiot[IndexPage] handleClear');
      this.dataChange('expression', 'clear');
      },
      handleInput(value) {
      console.log('Aiot[IndexPage] handle input value:' + value);
      this.isPush = false;
      if (isOperator(value)) {
      this.isPressedEqual()
      if (!this.expression && (value === '*' || value === '/')) {
              return;
      }
      this.expression += value;
      } else {
      if (pressedEqual) {
              pressedEqual = false;
      }
      this.expression += value;
         }
      },

      SendImage() {
      remoteDeviceModel.SendImageRemote(this.deviceList[this.itemNum], this.expression, this.imageNum, () => {
      console.log('Aiot[IndexPage] Send Data');
      });

      prompt.showDialog({
      title:" 提示",
      message:"图片已经发送,请耐心等待发送结果",
      buttons:[{"text":"确认","color":"#000000"}, {"text":"","color":"#000000"}],
      })
      setTimeout(function(){
      let Filepath = "/data/accounts/account_0/appdata/ohos.samples.aiotdemo/files/result.txt";
      let fd = fileio.openSync(Filepath, 0o2|0o100, 0o666);
      let buf = new ArrayBuffer(4096);
      fileio.read(fd, buf);
      let result = String.fromCharCode.apply(null, new Uint8Array(buf));
      oprationResult = result;
      prompt.showDialog({
              title:" 操作结果",
              message:result,
              buttons:[{"text":"确认","color":"#000000"}, {"text":"","color":"#000000"}],
      })

      fileio.close(fd);

         }, 30000);
      },

      readData() {
      if (Isauto)
      {
              prompt.showDialog({
              title:" 数据",
              message:"已经开启自动接收数据,请不要再次点击,是否手动获取数据",
              buttons:[{"text":"是","color":"#000000"}, {"text":"否","color":"#000000"}],
              success: function ()
              {
                      let Filepath = "/data/accounts/account_0/appdata/ohos.samples.aiotdemo/files/openEuler.txt";
                      let fd = fileio.openSync(Filepath, 0o2|0o100, 0o666);
                      let buf = new ArrayBuffer(4096);
                      fileio.read(fd, buf);
                      let result = String.fromCharCode.apply(null, new Uint8Array(buf));
                      ReadRomotedata = result;
                      prompt.showDialog({
                      title:" 数据",
                      message:result,
                      buttons:[{"text":"确认","color":"#000000"}, {"text":"","color":"#000000"}],
                      })
                      fileio.close(fd);
              },
              cancel: function (data) {
                      console.log(' handling cancel')
                 },
              })
              return ;
      }
      Isauto =true;
      var timer = setInterval(function(){

              let Filepath = "/data/accounts/account_0/appdata/ohos.samples.aiotdemo/files/openEuler.txt";
              let fd = fileio.openSync(Filepath, 0o2|0o100, 0o666);
              let buf = new ArrayBuffer(4096);
              fileio.read(fd, buf);
              let result = String.fromCharCode.apply(null, new Uint8Array(buf));
              ReadRomotedata = result;
              prompt.showToast({
              message:"远端数据: " + result,
              duration: 10000,
              })
              fileio.close(fd);

      },15000)
      prompt.showToast({
              message:"您已经开启自动接收数据",
              duration: 10000,
         })
      },

      SendBusData() {

      remoteDeviceModel.SendDataRemote(this.deviceList[this.itemNum], this.expression, () => {
      console.log('Aiot[IndexPage] Send Data');
      });

      prompt.showDialog({
      title:" 提示",
      message:"数据已经发送,请耐心等待发送结果",
      buttons:[{"text":"确认","color":"#000000"}, {"text":"","color":"#000000"}],
      })
      setTimeout(function(){

      let Filepath = "/data/accounts/account_0/appdata/ohos.samples.aiotdemo/files/result.txt";
      let fd = fileio.openSync(Filepath, 0o2|0o100, 0o666);
      let buf = new ArrayBuffer(4096);
      fileio.read(fd, buf);
      console.log(' setTimeout  77777 ');
      let result = String.fromCharCode.apply(null, new Uint8Array(buf));
      oprationResult = result;
      prompt.showDialog({
              title:" 操作结果",
              message:result,
              buttons:[{"text":"确认","color":"#000000"}, {"text":"","color":"#000000"}],
      })

      fileio.close(fd);

         }, 10000);
      },
      renzheng() {

      remoteDeviceModel.RenzhengRemote(this.deviceList[this.itemNum], this.expression, () => {
      console.log('Aiot[IndexPage] Send Data');
         });
      },
      getNewTodo(e) {
      this.expression = e.value;
      },
      getNewTodohcg(e) {
      this.expression = "qqqqqqqqqqqqgggggggggggggggggggggddddddddddddddddddddddddqqqqqqqqqqqqq";
      },
      S1click() {
      prompt.showDialog({
      title:" 图片操作",
      message:"右边是图片操作按钮,点击Select Image选中图片,点击Send Image发送选中的图片,发送给远端后,PolyOS进行推理",
      buttons:[{"text":"确认","color":"#000000"}, {"text":"","color":"#000000"}],
         })
      },
      S2click() {
      prompt.showDialog({
      title:"数据操作",
      message:"右边是数据有关操作按钮,点击Read Data可以读取数据,收到的数据将会定时已浮窗的形式显示,浮窗显示10秒钟,点击Synchro按钮可以将数据同步到文本框中",
      buttons:[{"text":"确认","color":"#000000"}, {"text":"","color":"#000000"}],
         })
      },
      S3click() {
      prompt.showDialog({
      title:"推理结果",
      message:"推理结构将会以图片或者文本的形式返回,返回的图片在下面显示,推理结果可以同时以文本的形式返回。",
      buttons:[{"text":"确认","color":"#000000"}, {"text":"","color":"#000000"}],
         })
      },
      isPressedEqual() {
      if (pressedEqual) {
      pressedEqual = false;
      } else {
      const size = this.expression.length;
      if (size) {
              const last = this.expression.charAt(size - 1);
              if (isOperator(last)) {
              this.expression = this.expression.substring(0, this.expression.length - 1);
              }
           }
         }
      },
      handleBackspace() {
      if (pressedEqual) {
      this.expression = ReadRomotedata;
      this.result = ReadRomotedata;
      pressedEqual = false;
      console.log('Aiot[IndexPage] handleBackspace1');
      this.dataChange('expression', 'clear');
      } else {
      this.isPush = false;
      this.expression = this.expression.substring(0, this.expression.length - 1);
      if (!this.expression.length) {
              this.result = ReadRomotedata;
              console.log('Aiot[IndexPage] handleBackspace2');
              this.dataChange('expression', 'clear');
         }
      }
      this.expression = ReadRomotedata;
      this.result = ReadRomotedata;
      },
      handleEqual() {
      if (this.result !== '') {
      this.isPush = true;
      this.expression = this.result;
      this.result = '';
      pressedEqual = true;
      console.log('Aiot[IndexPage] handleEqual');
      this.dataChange('expression', 'equal');
         }
      },
      handleExist() {
      console.log('Aiot[IndexPage] handleExist');
      app.terminate();
         }
      };

APP界面介绍

  1. APP图标界面

AIOT 演示APP安装成功后,桌面图标显示如下:

../../_images/APP_icon.jpg

AIOT 演示APP图标

  1. APP主界面

AIOT 演示APP主界面如下:

../../_images/APP_menu.jpg

AIOT 演示APP主界面

  1. 操作说明

从主界面可以看到,在APP界面上有三个主要步骤的标志,点击指示图标,可以弹开每个步骤的简要说明。其中图片操作的简要介绍如下:

../../_images/picture_introduce.jpg

图片操作说明

数据操作的简要介绍如下:

../../_images/data_introduce.jpg

数据操作说明

推理结果操作的简要介绍如下:

../../_images/result_introduce.jpg

推理结果操作说明