分布式软总线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界面介绍¶
APP图标界面
AIOT 演示APP安装成功后,桌面图标显示如下:
APP主界面
AIOT 演示APP主界面如下:
操作说明
从主界面可以看到,在APP界面上有三个主要步骤的标志,点击指示图标,可以弹开每个步骤的简要说明。其中图片操作的简要介绍如下:
数据操作的简要介绍如下:
推理结果操作的简要介绍如下: