本文的三位做者正陽、海洋、阿力,是來自不一樣公司的工程師,在Agora RTC Hack 上海站編程馬拉松上,開發了一款可實時視頻遠程看房的智能小車。本文將從方案設計、硬件開發、Android 端開發、服務端部署,詳實分享他們的開發經歷。javascript
歡迎訪問 RTC 開發者社區,與更多RTC開發者交流經驗。html
此前聽到多不少次「黑客馬拉松」這樣的活動,一羣來自不一樣地方的人聚在一塊兒,組隊、構思、開發,在48小時內作出產品雛形。咱們三人抱着去聽聽別人的創意,重在參與的想法參加了此次比賽。對於想要作的東西,在比賽前也只是有一個大概的方向:前端
出於這樣的構思,實現架構如上圖所示。如今有了一個基本架構,也清楚了咱們要實現的功能,接下來就是分工了。考慮到咱們各有所長,分工以下:java
分工 | 人物 | 實現目標1 | 實現目標2 |
---|---|---|---|
小車驅動與攝像頭端 | 海洋 | 使用 Android系統,完成攝像頭驅動 | 在 Android系統中加入驅動,解析運動控制信號,實現小車運動 |
車載APP與用戶APP | 正陽 | 將攝像頭採集的視頻傳遞出去,解析服務器信令,給小車發送運動信號 | 用戶能夠經過手機查看小車視頻,並控制小車 |
服務器端與web前端 | 阿力 | 將視頻傳輸服務器掛到公網上,用戶能夠用輸入網址的方式查看小車視頻 | 提供web前端,用戶能夠經過網頁控制小車 |
小車採用了是4輪伺服電機驅動,搭配有視頻採集模塊、伺服電機驅動模塊、STM32控制模塊和攝像頭雲臺模塊,安裝後總體效果圖以下: linux
用戶在遠程操控小車各類動做以前,須要小車經過wifi鏈接到互聯網。用戶能夠經過上位機(Android APP 或網頁前端)控制小車先後左右移動或控制雲臺調整攝像頭方向。android
視頻採集模塊包含有wifi模塊,能夠鏈接到wifi熱點爲視頻傳輸提供網絡基礎。也提供HDMI接口與顯示器鏈接,方便用戶調試。攝像頭經過USB的方式與視頻採集模塊鏈接,咱們採用免驅動的天敏6602型號攝像頭,分辨率能夠達到640*480,並可以自動調焦。git
STM32控制模塊採用 Arduino 接口與伺服電機驅動模塊鏈接,STM32模塊負責控制電機、雲臺信號的產生,並由伺服電機驅動模塊直接驅動電機工做。伺服電機輸入電壓爲6~12V,直流驅動。web
小車上的視頻採集模塊採用了定製的 Android 系統,提供網絡鏈接、指令轉發和視頻流採集、傳輸功能。當上位機經過遠程服務鏈接到小車後,上位機能夠請求到當前小車攝像頭上的視頻信息;同時,視頻採集模塊也將上位機上傳來的控制信號解析爲指定格式和功能的協議數據,並經過串口發送到 STM32控制模塊。shell
小車上的STM32控制模塊在接收到相關控制信號後,調整輸出脈衝信號的佔空比,由驅動板轉換輸出電平後直接控制伺服電機或雲臺模塊作出相應的動做,從而完成上位機用戶想要的操控功能。編程
對於只須要實現簡單的小車控制的話,咱們只須要實現經過串口向 STM32控制模塊發送控制信號便可,簡單的控制信號協議以下:
命令類型 | 包頭 | 類型 | 命令 | 數據 | 包尾 |
---|---|---|---|---|---|
中止 | 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>
複製代碼
並在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 標準工做組組長等技術大咖們帶來的乾貨,還將有這些飽含創意與開發熱情的小項目。想與他們聊一聊,交個朋友麼?