DigitalTwinAPI之ontick功能使用说明
一、功能简介
ontick功能提供了一种高性能的DigitalTwinAPI接口调用方式。
常规的DigitalTwinAPI调用流程是这样的:客户端调用DigitalTwinAPI(通过网络传输),后台渲染进程接收命令,然后进行异步处理。这样就有几个方面的延迟:
(1)客户端的异步等待(命令发送后等待返回结果)
(2)网络传输(通过WebRTC)
(3)后台渲染进程的线程切换(接收线程收到数据后,投递到执行线程,执行线程处理后投递到发送线程)
通过上面的流程可以看到如果高频率的调用接口,性能是不会太高的。为了解决这一问题,实现了ontick功能。通过ontick功能,可以在渲染进程的每帧直接同步地调用DigitalTwinAPI,极大的提高了调用性能。
二、实现原理
ontick功能是通过渲染进程内嵌的chrome浏览器内核(cef)执行JS脚本达到目的的。有2个方法:registerTick和removeTick
通过调用registerTick,进程会创建一个cef浏览器引擎,参数url将被设置为浏览器要显示的页面,在此页面内的DigitalTwinAPI调用,都是在同进程直接调用底层C++接口的,C++处理完成后,通过回调cef页面的Javascript函数来通知JS进行后续操作。 由于是在同一个进程内进行JS/C++互操作,所以性能非常高。
三、使用详解
1
、接口说明
registerTick用于注册ontick功能,注意:全局只能注册一个tick页面,多次registerTick,后面的tick功能会覆盖掉前面的。参数说明:
- url tick功能是通过一个独立的html页面实现的,此参数用来设置页面的地址。注意:由于是在后台渲染进程执行,所以页面地址必须是完整的网络路径或者服务器上的本地绝对路径, 不能传递相对路径。
- debug 用来设置是否显示调试页面,由于cef调试JS比较麻烦,所以可以将此参数设置为true,将tick页面显示出来,将调试信息在页面上显示,这样就极大的方便了代码调试。
- initPos 用来设置tick组件的位置,参数是一个三维坐标点[x,y,z],此坐标必须位于当前可见范围内,否则tick功能可能失效。 此参数为临时参数,后面优化后可能去掉。
removeTick用于移除tick功能,调用此方法后,tick功能会停止。
2、tick页面说明
在tick页面里调用DigitalTwinAPI与常规调用有一些区别,主要体现在以下几个方面:
(1)DigitalTwinAPI初始化
var __g;
window.onload = function () {
__g = new DigitalTwinAPI();
}
一般在onload里初始化,与常规初始化不同,tick页面里初始化DigitalTwinAPI不需要传递任何参数。注意:这里也可以使用异步操作例如:
window.onload = async function () {
__g = new DigitalTwinAPI();
await __g.tag.delete(id);
await __g.tag.add(data);
}
(2)两个固定方法
tick页面里有2个被底层调用的固定方法:ontick和ontick_result,这2个方法构成一个闭环。
- ontick是主页面调用registerTick后,渲染进程在每帧都会回调的方法。
- 如果在ontick里调用了DigitalTwinAPI的方法,渲染进程执行完后,由ontick_result通知。
在这2个方法里调用DigitalTwinAPI有以下几个注意事项:
- 如果需要接收底层执行的结果,最后一个参数必须设置为null,例如下面的代码:
__g.tag.setText(id, 'Tag:' + (i++).toString(), null);
用于每帧设置标签文本,同时希望收到底层设置完以后的通知,那么就把最后一个参数设置为null,底层设置完后会调用ontick_result方法,ontick_result的参数就是详细的执行结果 - 如果把最后一个参数设置为null,那么该API调用后的方法返回值是JS层包装的将要传递到底层的命令对象,具体请看下面实例运行结果
- 如果不关心底层处理结果,可以不用设置最后一个参数为null,例如:
__g.tag.setText(id, 'Tag:' + (i++).toString());
此方法没有将最后一个参数设置为null,那么底层执行完后,将不会调用ontick_result - 如果将最后一个参数设置为null,那么ontick和ontick_result和底层的任务执行都是在同一个线程,也就是同步调用,所以性能很高。 但是如果没有设置最后一个参数为null,那就跟常规调用一样,是异步的,可以使用异步调用的3种方式,但是这是强烈不建议的,因为这样会严重影响性能,失去了tick的意义。
如下代码:
var __g;
var id = 'testTag';
var i = 0;
var data = {
id: id,
coordinate: [0, 50, 0],
text: 'Tag:0',
textSize: 20,
textColor: Color.Blue,
range: [1, 10000],
showLine: false
}
window.onload = function () {
__g = new DigitalTwinAPI();
__g.tag.delete(id);
__g.tag.add(data);
}
function ontick() {
let callData = __g.tag.setText(id, 'Tag:' + (i++).toString(), null);
document.getElementById('call_data').innerText = JSON.stringify(callData);
}
function ontick_result(o) {
if (o.command == CommandType.Tag_Update) {
__g.tag.get(id, null);
}
else if (o.command == CommandType.Tag_Get) {
document.getElementById('result_data').innerText = JSON.stringify(o);
}
}
上面代码实现的功能是:每帧改变标签的值,然后获取该标签的信息,在tick页面上显示出来。代码运行效果: