【智体OS】官方上新发布rtphone分布式安卓设备远程控制插件:实现远程访问和管理手机
dtns.network是一款主要由JavaScript编写的智体世界引擎(内嵌了three.js编辑器的定制版-支持以第一视角浏览3D场馆),可以在浏览器和node.js、deno、electron上运行,它是一个跨平台的软件,支持多个操作系统使用!
dtns.connector是dtns.network的客户端软件,允许多用户方便*地连接dtns.network的智体设备。支持使用内置的poplang智体编程语言实现3D组件的智能化编程——语法超简单,一句话语法,人人轻松上手!通过poplang智体编程,可轻松创建、编辑、分发xverse-3D智体应用。
本次更新的内容为:rtphone实时分布式安卓设备远程访问和实时控制(基于dtns-rtpc-api和dtns.dpkg插件机制——插件包仅11kb大小,大大增强了远程访问和管理安卓设备的能力)!
更新内容
1、使用dpkg机制,集成dtns-rtphone-api,开发了rtphone分布式远程访问和实时控制的DPKG插件rtpc1.3.dpkg(dtns.top官网下载)
2、rtphone暂时支持屏幕同步功能、点击功能(亦可点击输入框唤醒键盘输入功能)
3、支持访问内网算力设备,主要是依赖于dtns-api来进行访问(分布式设备终端远程访问),可取代大部分的代理访问机制。
4、可方便集成到了dtns.os的系统应用面板中。
5、可使用poplang调用dtns-rtphone-api,实现安卓操作系统的机器人(详见过往文章)
完全开源:rtphone开源、dtns.os和dtns.network等项目均开源。详见文末、或访问dtns.top智体OS官网。
使用教程
一、打开dtns.connector的dweb头榜界面,点击上传了的rtphone1.3.dpkg(或任意其它最新版本)
二、进入rtphone远程访问和实时管理插件,可以看到最新的手机屏幕内容(这里查看的是时钟应用的界面——手机已经打开该应用)
三、点击右上角的“同步”,可实现手机屏幕显示内容进行实时同步
四、可以看到秒表的时间实时变化,点击右上角可停止同步更新(受限于adb截屏速度,2秒钟完成一次屏幕内容的同步刷新)
五、可点击下方的暂停按钮,实现对该应用的远程控制(大部分应用均可方便远程控制)
六、点击切换至闹钟主界面
rtphone1.3.dpkg的源码分享
/* eslint-disable */
<!--
* @Description: RtPhoneClient
* @Author: poplang
* @Date: 2024-12-6
* @LastEditors:
* @LastEditTime:
-->
<template>
<div style="width: 100%;height: 100%;padding:0px;margin: 0px;" >
<div @click="back" style="color:black;position: fixed;left:8px;top:8px;z-index: 399;"> ❮返回 </div>
<div style="color:black;position: fixed;left:0;right:0;top:8px;z-index: 359;text-align: center; font-size: 18px;font-weight: 800;">{{ title }}</div>
<div style="color:black;position: fixed;right:8px;top:8px;z-index: 399;"><span @click="goBack" style="margin-right: 8px">back</span><span @click="goMenu" style="margin-right: 8px">menu</span><span @click="goHome" style="margin-right: 8px">home</span><span @click="syncScreen" style="margin-right: 8px">{{ syncScreenTips }}</span>
<!-- <span @click="queryScreen">刷新</span> -->
</div>
<!-- <div style="color:red;position: fixed;right:8px;top:8px;z-index: 399;"><b>[分数] {{ top_cnt }} : {{ success_cnt }}</b></div> -->
<!-- <div v-show="showInput" style="position: fixed;z-index: 199; display:flex;bottom: 5px;left:0;right: 0;height: auto;text-align: center;margin-bottom: 2px;padding:0px 10px 0px 10px;">
<input @keydown.enter="keyDown" style="width:100%; height:28px; padding-left:5px; border:1px solid #eeeeee; font-size:13px;" v-model="msg" />
<button @click="send" style="color: rgb(255, 255, 255);width:70px;border-radius: 0px; font-size: 13px; height: 28px; background-color: rgb(18, 173, 245); border: none;">发送</button>
</div> -->
<div style="position:fixed;top: 50px;bottom: 0px;left: 0px;right: 0px;z-index: 9;overflow-x: auto;overflow-y: auto;">
<img :src="base64" style="width: auto;height: auto;" @mousedown="mousedown"/>
</div>
</div>
</template>
<script>
export default {
name: "RtPhoneClient",
props: ["value"],
components: { },
data() {
return {
title:'RtPhone客户端',
// showInput:false,
base64:null,
// syncScreenId:0,
syncScreenNowFlag:false,
syncScreenTips:'同步',
syncScreenTipsStart:'同步',
syncScreenTipsStop:'停止',
}
},
async created()
{
this.user_id = localStorage.user_id
// setInterval(this.queryScreen,10000)
},
mounted(){
this.queryScreen()
},
beforeRouteLeave(to,from,next){
// if(this.syncScreenId) clearInterval(this.syncScreenId)
this.stopSyncScreen()
console.log('into beforeRouteLeave')
next();
},
methods: {
back(){
this.stopSyncScreen()
this.$router.go(-1)
},
async goBack()
{
if(this.click_event_now_flag) console.log('this.click_event_now_flag is true')
if(typeof g_dtnsManager =='undefined') return false
this.click_event_now_flag = true
let ret = await g_dtnsManager.run('dtns://web3:'+rpc_client.roomid+'/rtphone/robot/do',{action:' shell input keyevent 4 '})//,click:true
if(!ret || !ret.ret) g_dchatManager.viewContext.$toast('点击失败,原因:'+(ret ? ret.msg:'未知网络原因'))
await new Promise((res)=>setTimeout(res,100))
this.click_event_now_flag = false
},
async goHome()
{
if(this.click_event_now_flag) console.log('this.click_event_now_flag is true')
if(typeof g_dtnsManager =='undefined') return false
this.click_event_now_flag = true
let ret = await g_dtnsManager.run('dtns://web3:'+rpc_client.roomid+'/rtphone/robot/do',{action:' shell input keyevent 3 '})//,click:true
if(!ret || !ret.ret) g_dchatManager.viewContext.$toast('点击失败,原因:'+(ret ? ret.msg:'未知网络原因'))
await new Promise((res)=>setTimeout(res,100))
this.click_event_now_flag = false
},
async goMenu()
{
if(this.click_event_now_flag) console.log('this.click_event_now_flag is true')
if(typeof g_dtnsManager =='undefined') return false
this.click_event_now_flag = true
let ret = await g_dtnsManager.run('dtns://web3:'+rpc_client.roomid+'/rtphone/robot/do',{action:' shell input keyevent 82 '})//,click:true
if(!ret || !ret.ret) g_dchatManager.viewContext.$toast('点击失败,原因:'+(ret ? ret.msg:'未知网络原因'))
await new Promise((res)=>setTimeout(res,100))
this.click_event_now_flag = false
},
stopSyncScreen()
{
if(this.syncScreenNowFlag)
{
// clearInterval(this.syncScreenId)
this.syncScreenNowFlag = false
this.syncScreenTips = this.syncScreenTipsStart
}
},
async syncScreen()
{
if(this.syncScreenNowFlag) return this.stopSyncScreen()
this.syncScreenNowFlag = true//setInterval(this.queryScreen,5000)
this.syncScreenTips = this.syncScreenTipsStop
while(this.syncScreenNowFlag)
{
await this.queryScreen() //得到查询结果(可能1-15s完成600kb的png截图下载)
await new Promise((res)=>setTimeout(res,100))
}
},
async queryScreen()
{
if(typeof g_dtnsManager =='undefined') return false
let ret = await g_dtnsManager.run('dtns://web3:'+rpc_client.roomid+'/rtphone/robot/screencap',{f:'webp',q:10})
if(ret && ret.ret) this.base64 = ret.base64
else console.log('query-screen-ret:',ret)
},
async mousedown(e)
{
if(this.click_event_now_flag) console.log('this.click_event_now_flag is true')
console.log('RtPhoneClient.vue mousedown-event:',e)
let x = e.offsetX , y = e.offsetY//e.layerX, y = e.layerY//e.clientX, y = e.clientY
if(typeof g_dtnsManager =='undefined') return false
this.click_event_now_flag = true
let ret = await g_dtnsManager.run('dtns://web3:'+rpc_client.roomid+'/rtphone/robot/do',{action:' shell input tap '+x+' '+y})//,click:true
if(!ret || !ret.ret) g_dchatManager.viewContext.$toast('点击失败,原因:'+(ret ? ret.msg:'未知网络原因'))
await new Promise((res)=>setTimeout(res,100))
this.click_event_now_flag = false
},
send()
{
},
keyDown()
{
}
}
}
</script>
<style scoped>
</style>
注:我们看到,基于dtns-api(封装为g_dtnsManager客户端js-SDK),可以轻松地访问dtns-rtphone-api,从而实现安卓的远程访问和控制。功能强大,但开发极简。并且支持使用poplang开发各种各样的视觉智能机器人(安卓手机控制),实现任意的业务流引擎的快速定制。
总结:dtns-rtpc-api,结合dtns.connector上的DPKG插件机制,3d-agent智体应用开发语言poplang,可以在极短时间内做出强大的智体应用3.0(agent)用于智能安卓手机控制。进一步拓展了智体OS的分布式智能的适用领域(例如智能家电、服务机器人等等)。