本文的三位做者正阳、海洋、阿力,是来自不一样公司的工程师,将 Agora SDK 与智能小车结合,开发了一款可实时视频远程看房的创新性项目。本文将从方案设计到具体实现,详实分享他们的开发经验。三人也凭借该项目,在6月30日的Agora RTC Hack 上海站编程马拉松得到大奖。
此前听到多不少次“黑客马拉松”这样的活动,一群来自不一样地方的人聚在一块儿,组队、构思、开发,在48小时内作出产品雏形。咱们三人抱着去听听别人的创意,重在参与的想法参加了此次比赛。对于想要作的东西,在比赛前也只是有一个大概的方向:javascript
出于这样的构思,实现架构如上图所示。如今有了一个基本架构,也清楚了咱们要实现的功能,接下来就是分工了。考虑到咱们各有所长,分工以下:html
分工 | 人物 | 实现目标1 | 实现目标2 |
---|---|---|---|
小车驱动与摄像头端 | 海洋 | 使用 Android系统,完成摄像头驱动 | 在 Android系统中加入驱动,解析运动控制信号,实现小车运动 |
车载APP与用户APP | 正阳 | 将摄像头采集的视频传递出去,解析服务器信令,给小车发送运动信号 | 用户能够经过手机查看小车视频,并控制小车 |
服务器端与web前端 | 阿力 | 将视频传输服务器挂到公网上,用户能够用输入网址的方式查看小车视频 | 提供web前端,用户能够经过网页控制小车 |
小车采用了是4轮伺服电机驱动,搭配有视频采集模块、伺服电机驱动模块、STM32控制模块和摄像头云台模块,安装后总体效果图以下:前端
用户在远程操控小车各类动做以前,须要小车经过wifi链接到互联网。用户能够经过上位机(Android APP 或网页前端)控制小车先后左右移动或控制云台调整摄像头方向。java
视频采集模块包含有wifi模块,能够链接到wifi热点为视频传输提供网络基础。也提供HDMI接口与显示器链接,方便用户调试。摄像头经过USB的方式与视频采集模块链接,咱们采用免驱动的天敏6602型号摄像头,分辨率能够达到640*480,并可以自动调焦。linux
STM32控制模块采用 Arduino 接口与伺服电机驱动模块链接,STM32模块负责控制电机、云台信号的产生,并由伺服电机驱动模块直接驱动电机工做。伺服电机输入电压为6~12V,直流驱动。android
小车上的视频采集模块采用了定制的 Android 系统,提供网络链接、指令转发和视频流采集、传输功能。当上位机经过远程服务链接到小车后,上位机能够请求到当前小车摄像头上的视频信息;同时,视频采集模块也将上位机上传来的控制信号解析为指定格式和功能的协议数据,并经过串口发送到 STM32控制模块。git
小车上的STM32控制模块在接收到相关控制信号后,调整输出脉冲信号的占空比,由驱动板转换输出电平后直接控制伺服电机或云台模块作出相应的动做,从而完成上位机用户想要的操控功能。web
对于只须要实现简单的小车控制的话,咱们只须要实现经过串口向 STM32控制模块发送控制信号便可,简单的控制信号协议以下:shell
命令类型 | 包头 | 类型 | 命令 | 数据 | 包尾 |
---|---|---|---|---|---|
中止 | FF | 00 | 00 | 00 | FF |
前进 | FF | 00 | 01 | 00 | FF |
后退 | FF | 00 | 02 | 00 | FF |
左转 | FF | 00 | 03 | 00 | FF |
右转 | FF | 00 | 04 | 00 | FF |
云台上下 | FF | 01 | 01 | 角度值 | FF |
云台左右 | FF | 01 | 02 | 角度值 | FF |
为了实现咱们想要的实时视频与小车的远程控制功能,咱们须要采用声网的视频SDK,并运行在 Android 开发板上。开发板,咱们选用了Firefly的RK3128平台,采用Cortex-A7架构四核1.3GHz处理器、Mali-400MP2 GPU,板载千兆以太网口、2.4GHz Wi-Fi和蓝牙4.0,支持Android与Ubuntu双系统。编程
为了实现RK3128对小车的控制,咱们须要实现 RK3128经过 USB 转串口模块与STM32控制模块通讯。所以咱们首先要从新配置RK3128内核,使得RK3128支持 USB转串口驱动程序。
首先下载完RK3128 Android SDK并先验证文件MD5值:
md5sum /path/to/fireprime_android5.1_git_20180510.tar.gz fce0e6d65549939167923260142b2c1e fireprime_android5.1_git_20180510.tar.gz
确认无误后解压:
mkdir -p ~/proj/fireprime cd ~/proj/fireprime tar xvf /path/to/fireprime_android5.1_git_20180510.tar.gz git reset --hard git remote add bitbucket https://bitbucket.org/T-Firefly/firenow-lollipop.git git pull bitbucket fireprime:fireprime
配置并编译内核:
cd ~/proj/fireprime/kernel make rk3128-fireprime_defconfig make menuconfig make -j8 rk3128-fireprime.img
其中make menuconfig
这一步须要勾选上Device Drivers ---> USB support ---> USB Serial Converyer support ---> USB Serial Console device support / USB Generic Serial Driver,并勾选上 CP210x / CH341 / FTDI / PL2303 等经常使用串口工具设备。
编译Android系统:
cd ~/proj/fireprime . build.sh make -j8 ./mkimage.sh
最后编译完成后烧录分区镜像,并插入USB转串口工具查看系统dmesg
是否出现如下log信息:
[ 2213.003173] usb 1-1.3: new full-speed USB device number 6 using rockchip_ehct [ 2213.113759] usb 1-1.3: New USB device found, idVendor=10c4, idProduct=ea60 [ 2213.113839] usb 1-1.3: New USB device strings: Mfr=1, Product=2, SerialNumbe3 [ 2213.113883] usb 1-1.3: Product: CP2102 USB to UART Bridge Controller [ 2213.113921] usb 1-1.3: Manufacturer: Silicon Labs [ 2213.113956] usb 1-1.3: SerialNumber: 0001 [ 2213.120813] cp210x 1-1.3:1.0: cp210x converter detected [ 2213.209852] usb 1-1.3: reset full-speed USB device number 6 using rockchip_et [ 2213.320161] usb 1-1.3: cp210x converter now attached to ttyUSB0
出现串口设备附着到 ttyUSBx,即说明定制串口驱动成功。
以上为全编译Android SDK的方法,须要编译 Android 系统,相较于仅编译内核而言比较费时。咱们能够在上述make menuconfig
时将须要的串口驱动程序勾选为M,经过make modules
的方法,将驱动编译成.ko
文件,而后在 Android系统开机时自动加载驱动程序:
首先将.ko
驱动程序文件复制到 Android 文件系统内
adb shell su mount -o remount ,rw / mkdir /modules chmod 777 /modules chown -R nobody:nobody /modules exit exit adb push ./xxxx.ko /modules
编写启动运行脚本/data/serial.sh
#!/system/bin/sh insmod /modules/xxxx.ko mknod /dev/ttyUSB c 240 0
修改init.rc
并添加运行本身的脚本
service serial /system/bin/sh /data/serial.sh user root oneshot
视频传输和信令传输的部分,咱们经过声网 Agora SDK 来实现。因为涉及到与嵌入式开发板的结合,咱们主要参考的是声网在 Github 提供的各类案例中的抓娃娃机 demo。示例代码中的结构图以下:
示例代码有视频传输的部分,控制信令须要本身完成。
两个APP | 视频 | 控制信号 |
---|---|---|
小车端的 Android App | 发送视频信号 | 接受控制信号 |
用户手机端 Android App | 接受视频信号 | 发送控制信号 |
AndroidAPP中在res/values/strings_config.xml加入以下内容,将agora_app_id进行配置
<resources> <string name="agora_app_id">1a486ee31a30xxxxxxxxxx</string> </resources>
由于用到信令和视频传输两部分,须要两个.jar 文件分别为agora-rtc-sdk.jar和agora-sig-sdk.jar
并在build.gradle中肯定拥有以下描述:
dependencies { compile fileTree(dir: 'libs', include: ['*.jar']) testCompile 'junit:junit:4.12' compile 'com.android.support:appcompat-v7:23.4.0' }
就此,使用示例代码能够顺利开启视频传输功能。
信令的具体使用方法见Agora 的参考,这里不进行详尽描述。主要使用的函数以下:
// 初始化信令 SDK m_agoraAPI = AgoraAPIOnlySignal.getInstance(context, appID); // 登陆 Agora 信令系统 m_agoraAPI.login2(appId, account, token, uid, deviceID, retry_time_in_s, retry_count) //////////////点对点测试///////////// // 发送点对点消息 m_agoraAPI.messageInstantSend(account, uid, msg, msgID) // 设置对端收到消息回调( m_agoraAPI.onMessageInstantReceive(account, uid, msg){ //code there } /////////////频道测试/////////////// // 加入频道 m_agoraAPI.channelJoin(channelName) // 发送频道消息 m_agoraAPI.messageChannelSend(channelName, msg, msgID) // 设置对端接收到频道消息回调 m_agoraAPI.onMessageChannelReceive(channelID, account, uid, msg) { // code there } ////////////////////////////////// // 退出 Agora 信令系统 m_agoraAPI.logout()
对于小车端的 Android App 获得信令以后须要串口发送数据。所以如何实现 Android App 操做串口。这里简述两种方案:
对于短期实现功能来讲,方案2是更容易实现的方法,这里须要很是注意的一点,须要从新编译android的framework层给app赋予root权限
当信令解析完成,串口调试经过,就能够实现远程控制小车的行进了。
为了实现用户能够方便经过手机或者电脑在线实时看房,咱们须要经过web端链接小车的Android App端,获取实时传输过来的视频内容。在咱们的设想中,用户能够经过远程控制小车,这样能够方便用户了解房屋各个方面的状况。综上所述,咱们须要实现以下两个功能:
幸运的是,经过声网提供的服务,咱们能够很便捷的搭建这两个服务。
在本项目中,咱们使用声网的视频SDK实现网页端和小车APP端的视频链接,经过信令SDK发送消息,去控制小车的先后左右行走和摄像头上下左右摆动。
罗列一下咱们使用到的工具:
先在页面上引入视频和信令的 SDK。而后咱们先来实现视频链接。
// 建立 AgoraRTC 实例并加入频道 const client = AgoraRTC.CreateClient({mode:"interop"}) client.init(appId, function () { console.log("AgoraRTC client initialized"); client.join(channel_key, CHANNEL_NAME, null, function (uid) { console.log("User " + uid + " join channel successfully") console.log(new Date().toLocaleTimeString()) // do something } }
订阅远端的视频流并播放。
let stream = AgoraRTC.creatStream(merge(defaultConfig.config)) localStream.init(() =>{ client.on('stream-added', function (evt) { var stream = evt.stream; console.log("New stream added: " + stream.getId()); console.log("Subscribe ", stream); client.subscribe(stream, function (err) { console.log("Subscribe stream failed", err); }); }); client.on('stream-subscribed', function (evt) { var stream = evt.stream; console.log("Subscribe remote stream successfully: " + stream.getId()); if ($('div#video #agora_remote' + stream.getId()).length === 0) { $('div#video').append('<div id="agora_remote' + stream.getId() + '" style=" width:810px;height:607px;"></div>'); } stream.play('agora_remote' + stream.getId()); }); })
实现发送信息。
// 建立信令的对象 const signal = Signal(appId) // 在实验条件下,不设置token const token = '_no_need_token' // 登陆 const session = signal.login(account, token) session.onLoginSuccess = (uid) => { //发送消息给指定的帐号 signal.sendMessage(reciveAcount, message) }
完成上述的步骤以后,与小车端设置相同的appId和token(若有必要),设定好对应的参数,咱们就能够远程控制小车并获取视频了。
Hacker 们用实际行动,说明了 RTC 技术不只仅可应用于娱乐、社交、教育等领域,还能够迸发出更多新的创意。就在近期,Agora RTC Hack 还在全球其它城市火热进行中。有我的,也有来自创业公司的团队参赛并获奖。咱们将邀请其中几支来自世界各地的获奖团队参加到9月7日 - 8日举行的 RTC 2018 实时互联网大会。现场不只有 Google WebRTC 产品经理、华为多媒体实验室首席科学家、西北工业大学智能声学与临境通讯中心首席科学家、Twitch 首席研发工程师、AVS 标准工做组组长等技术大咖们带来的干货,还将有这些饱含创意与开发热情的小项目。想与他们聊一聊,交个朋友么?点击这里报名,现场约起来吧!