【智体OS】官方上新发布rtphone分布式安卓设备远程控制插件:实现远程访问和管理手机

时间:2024-12-10 14:38:22

【智体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(或任意其它最新版本)

1.png

二、进入rtphone远程访问和实时管理插件,可以看到最新的手机屏幕内容(这里查看的是时钟应用的界面——手机已经打开该应用)

2.png

三、点击右上角的“同步”,可实现手机屏幕显示内容进行实时同步

3.png

四、可以看到秒表的时间实时变化,点击右上角可停止同步更新(受限于adb截屏速度,2秒钟完成一次屏幕内容的同步刷新)

4.png

五、可点击下方的暂停按钮,实现对该应用的远程控制(大部分应用均可方便远程控制)

5.png

六、点击切换至闹钟主界面

6.png

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的分布式智能的适用领域(例如智能家电、服务机器人等等)。