大疆上云API示例代碼部署小記
最近接手了一個項目,在不增加新的預算的前提下,實現將大疆無人機里拍攝的照片自動上傳到服務器。
上其官網研究了一翻,再加上幾個好友的溝通,目前已知有兩種方法,一種是使用MSDK,自己開發一個APP安裝到手柄上,自行實現照片下載至手柄與上傳至服務器。第二種則是使用上云API,自己開發服務端,按協議要求實現指定接口實現圖傳。兩種方案的差異可由下圖所示。由于大疆已提供服務端樣例,加之目前需求非常簡單,故采用方案二。

一、準備上云API
首先,上大疆官網注冊,先注冊開發者賬號,再注冊APP,過程不詳述,最后可得到APP的ID、KEY、License,備用。
對于我來講,使用docker模式更容易實現產品部署。首先,在服務器上下載樣例包。
axel -n 20 https://terra-sz-hc1pro-cloudapi.oss-cn-shenzhen.aliyuncs.com/c0af9fe0d7eb4f35a8fe5b695e4d0b96/docker/cloud_api_sample_docker.zip
解壓至同名目錄
unzip cloud_api_sample_docker.zip
二、編排Minio
目前上云API是將圖片存儲在對像存儲器中,私有化方案目前只能選擇minio。本處采用docker-compose方式布署。首先將docker源更新為國內源,加快拉取速度。打開配置文件
sudo ne /etc/docker/daemon.json
將國內常見的源地址加入
{
"data-root": "/opt/docker",
"registry-mirrors": ["https://hub-mirror.c.163.com/", "https://dockerproxy.com/", "https://quay.mirrors.ustc.edu.cn"]
}
最后,更新系統環境變量并重啟
sudo systemctl daemon-reload
sudo systemctl restart docker
打開解壓后根目錄下現有編排文件 docker-compose.yml ,將minio段添加進入,并加入相同網橋與啟動依賴
services: cloud_api_sample: depends_on: - minio minio: image: "minio/minio:latest" ports: - "9000:9000" - "9001:9001" volumes: - "/opt/minio/data:/data1" - "/opt/minio/config:/data2" environment: - MINIO_ROOT_USER=minioadmin - MINIO_ROOT_PASSWORD=minioadmin command: server --console-address ":9001" /data1 hostname: cloud_api_sample_minio networks: - cloud_service_bridge
三、部署官網組件
將根目錄的鏡像加載至docker中,里面包含了mysql、redis等組件
sudo docker load < cloud_api_sample_docker_v1.10.0.tar
修改后端配置文件 cloud_api_sample/source/backend_service/sample/src/main/resources/application.yml ,為mysql、redis、mqtt配置訪問ip。docker-compose編排文件中使用橋接方式指定的網段為 192.168.6.0/24 ,所以宿主機分配的ip為 192.168.6.1,為cloud-api配置前面申請的id、key、license。oss啟用minio,其endpoint需配成宿主機固有的ip。由于不存在直播需求,將livestream中的gb28181配置節注釋,否則系統啟動報錯。
spring: datasource: druid: url: jdbc:mysql://192.168.6.1:3306/cloud_sample?useSSL=false&allowPublicKeyRetrieval=true redis: host: 192.168.6.1 mqtt: BASIC: host: 192.168.6.1 DRC: host: 192.168.6.1 oss: endpoint: http://192.168.192.254:9000 cloud-api: app: id: 按需 key:按需 license: 按需 livestream: url: # gb28181: # serverIP: Please enter the server ip. # serverPort: Please enter the server port. # serverID: Please enter the server id. # agentID: Please enter the agent id. # agentPassword: Please enter the agent password. # localPort: Please enter the local port. # channel: Please enter the channel. # # # Webrtc: Only supports using whip standard
為了加快編譯速度,建議將maven源修改為國內。打開 cloud_api_sample/source/backend_service/pom.xml ,增加 repositories 配置節,我實際配置為阿里源,如下所示
<project> …… <repositories> <repository> <id>aliyun</id> <name>aliyun</name> <url>https://maven.aliyun.com/repository/public/</url> <releases> <enabled>true</enabled> </releases> <snapshots> <enabled>false</enabled> </snapshots> </repository> </repositories> <pluginRepositories> <pluginRepository> <id>aliyunPlugin</id> <name>aliyunPlugin</name> <url>https://maven.aliyun.com/repository/public/</url> <releases> <enabled>true</enabled> </releases> <snapshots> <enabled>false</enabled> </snapshots> </pluginRepository> </pluginRepositories> </project>
修改鏡像打包文件 cloud_api_sample/source/backend_service/Dockerfile ,使用2倍線程數打包jar包,實測可加快30%的打包速度。
RUN mvn clean package -T 2C -Dmaven.test.skip=true
完成上述修改后,在解壓根目錄下執行后臺編譯命令
./update_backend.sh
修改前端配置文件 cloud_api_sample/source/nginx/front_page/src/api/http/config.ts ,為license節配置前面申請的id、key、license。為http節配置客戶端訪問后臺服務的基地址及webSocket基地址(需配成宿主機固有的ip)。目前不存在直播需求,不需配置livestreaming節。配置高德地圖Web端應用key,相關知識可自行查閱。
// license appId: '按需', // You need to go to the development website to apply. appKey: '按需', // You need to go to the development website to apply. appLicense: '按需', // You need to go to the development website to apply. // http baseURL: 'http://192.168.192.254:6789/', // This url must end with "/". Example: 'http://192.168.1.1:6789/' websocketURL: 'ws://192.168.192.254:6789/api/v1/ws', // Example: 'ws://192.168.1.1:6789/api/v1/ws' // map amapKey: '按需',
為修復編譯錯誤,打開 cloud_api_sample/source/nginx/front_page/package-lock.json ,將所有 https://registry.nlark.com/ 統一替換為 https://registry.npmmirror.com/ 。
完成上述修改后,在解壓根目錄下執行前臺編譯命令
./update_front.sh
網站默認采用8080端口訪問。如服務器中已有沖突,可修改根目錄下 dock-compose.yml 文件參數調整為合適端口。如下方修改為8088。
services:
nginx:
ports:
- "8088:8080"
最后,在解壓根目錄下執行啟動命令
sudo docker-compose up -d
四、修改界面標題
在交付使用前,需要將界面上顯示的如 Test 或 Demo等字樣替換為客戶實際名稱。
打開數據庫表 manage_workspace ,將workspace_name、workspace_desc、platform_name修改為實際的工作空間名、工作空間描述、平臺名稱,這里可影響web端的logo名稱,遙控器pilot 2主界面云端名稱顯示,云端界面標題及界面顯示。
打開前端代碼文件 cloud_api_sample/source/nginx/front_page/index.html,修改第7行title標簽內容,可影響web端網頁標題
打開 cloud_api_sample/source/nginx/front_page/src/pages/page-web/index.vue,修改第8行p標簽內容,可影響web端登錄界面系統名稱
打開 cloud_api_sample/source/nginx/front_page/src/pages/page-pilot/pilot-index.vue,修改第7行p標簽內容,可影響遙控器端pilot 2登錄界面系統名稱。遙控器無緩存清理功能,如果使用后再更新代碼,可能會出現編譯后文件名依然一樣,然后遙控器依然讀取本地緩存的情況。這個時候可通過反復增減空格等方式修改文件然后編譯,直至編譯后文件名不同,并配合nginx添加請求頭強制讓瀏覽器所有緩存過期,達到更新遙控器本地緩存的目的。
五、模擬測試
首選測試minio可用性。在引入 MinIO Java SDK、Hotool工具集后,在resources/imgs下存放圖片,則使用如下代碼可實現文件的上傳下載刪除。
private static String url = "http://192.168.192.254:9000"; private static String accessKey = "minioadmin"; private static String secretKey = "minioadmin"; private static String bucketName = "cloud-bucket"; private static String regionName = "us-east-1"; try (MinioClient minioClient = MinioClient.builder() .endpoint(url).credentials(accessKey, secretKey).build(); Scanner sc = new Scanner(System.in);) { System.out.println("開始執行"); // 上傳文件 for (File file : FileUtil.loopFiles("imgs")) { UploadObjectArgs upArgs = UploadObjectArgs.builder().bucket(bucketName) .object(file.getName()).filename(file.getAbsolutePath()) .build(); minioClient.uploadObject(upArgs); System.out.println("上傳圖片:" + file.getName()); } System.out.println("圖片已上傳完畢"); sc.nextLine(); // 下載文件 ListObjectsArgs listArgs = ListObjectsArgs.builder() .bucket(bucketName).recursive(true).build(); List<DeleteObject> delList = new LinkedList<>(); for (Result<Item> item : minioClient.listObjects(listArgs)) { DownloadObjectArgs downArgs = DownloadObjectArgs.builder() .bucket(bucketName).object(item.get().objectName()) .filename(item.get().objectName().replace("/", "_")) .overwrite(true).build(); minioClient.downloadObject(downArgs); delList.add(new DeleteObject(item.get().objectName())); System.out.println("下載圖片:" + item.get().objectName()); } System.out.println("圖片已下載完畢"); sc.nextLine(); // 刪除文件 RemoveObjectsArgs reArgs = RemoveObjectsArgs.builder().bucket(bucketName).objects(delList).build(); for (Result<DeleteError> error : minioClient.removeObjects(reArgs)) { System.out.println(error.get().message()); } System.out.println("圖片已刪除完畢"); sc.nextLine(); System.out.println("結束執行"); }
在上云方面,使用工具連上mysql數據庫,在media_file表中插入對應圖片數據。以1.jpg為例,插入語句如下
INSERT INTO `cloud_sample`.`media_file` (`id`, `file_id`, `file_name`, `file_path`, `workspace_id`, `fingerprint`, `tinny_fingerprint`, `object_key`, `sub_file_type`, `is_original`, `drone`, `payload`, `job_id`, `create_time`, `update_time`) VALUES (1, '7858e36e-d62d-41dd-bee9-824521e6c810', '1.jpg', 'b', 'e3dea0f5-37f2-4d79-ae58-490af3228069', '', '', '1.jpg', NULL, 1, '3', '4', '5', 1719893248236, 1719893248236);
使用上述代碼上傳圖片1.jpg,并在庫中插入上述數據后,登錄上云API,進入 Workspace -> Media Files頁面,即可看到1.jpg圖片數據。點擊Action下的按鈕如下載成功,則說明上云API與minio連通成功。
六、域名訪問
上述描述均為直接使用ip訪問的場景,即無人機遙控器、上云API、minio、管理端電腦均在內網。可通過如下修改,使其支持外網域名訪問。
首先,修改 cloud_api_sample/source/nginx/default.conf 文件,建議所有外網請求均通過相同端口接收,然后通過不同地址轉發至不同服務。如下示例中,在原有基礎上, sample管理后臺接口請求(注意其 proxy_pass 必須已斜杠結尾,使轉發后的地址將不附帶sample段), /api/v1/ws 管理ws請求,如下所示:
server { listen 8080 default_server; server_name ""; error_log /var/log/nginx/error.log; access_log /var/log/nginx/access.log main; location /sample/ { proxy_pass http://192.168.6.1:6789/; #proxy_set_header Host $host; #proxy_set_header X-Real-IP $remote_addr; #proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; } location /api/v1/ws { proxy_pass http://192.168.6.1:6789/api/v1/ws; proxy_http_version 1.1; proxy_set_header Upgrade $http_upgrade; proxy_set_header Connection "Upgrade"; #proxy_set_header Host $host; #proxy_set_header X-Real-IP $remote_addr; #proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; } #location /minio/ { #cloud-bucket # proxy_pass http://192.168.6.1:9000/; # proxy_set_header Host $http_host; # #proxy_set_header X-Real-IP $remote_addr; # #proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; #} location / { #expires -1; #add_header Cache-Control "private, no-store, no-cache, must-revalidate, proxy-revalidate"; proxy_set_header X-Forwarded-For $remote_addr; root /home/vue_server/; try_files $uri $uri/ /index.html; } }
與之對應的,前端配置文件 config.ts 中,其 baseURL 與 websocketURL 需修改為域名,注意 baseURL需增加/sample/地址段用于nginx轉發識別,所下所示:
baseURL: 'http://域名:端口/sample/', // This url must end with "/". Example: 'http://192.168.1.1:6789/'
websocketURL: 'ws://域名:端口/api/v1/ws', // Example: 'ws://192.168.1.1:6789/api/v1/ws'
后端配置文件 application.yml 中,將對像存儲oss的 endPoint 修改為域名,將mqtt的 host 與 port修改為域名。注意,此域名需保證后臺服務也能訪問。由于nginx是將根目錄轉發到前端,非根目錄的http或ws請求轉發到后臺,mqtt是處理tcp請求,oss(minio)不允許在endpoint中配置路徑,導致上傳文件的地址是在根目錄與nginx有沖突,這三者需要使用不同的端口號。
mqtt:
BASIC:
host: 域名
port: 端口
oss:
endpoint: http://域名:端口
七、無人機連接
完成上述準備后,打開無人機及遙控器,使兩者之間正常連接,然后打開遙控器飛控軟件 DJI Pilot 2, 上云功能區默認顯示Not Logged In即未登錄,點擊后界面將跳轉至地址頁,如下圖所示:

在URL輸入框中輸入上云后臺地址,格式為http://地址:端口/pilot-login,基于配置地址為域名或ip均可,然后點擊右上角的connection按鈕。如下圖所示

界面將跳到至登錄頁,輸入用戶名與密碼后點擊藍色Login按鈕,如下圖所示

登錄成功后,遙控器會發送mqtt消息,服務端收到后會回復mqtt消息,遙控器收到后即完成連接,自動讀取并顯示遙控器云端SN號與無人機SN號,如下圖所示:

點擊Device Binding按鈕,系統跳轉至綁定界面,點擊Bind按鈕后實現無人機與云端的綁定,方便后續操作。

點擊左上角的 Test Group One 按鈕,可以查看各個模塊的連接信息,顯示綠色的 Connected 則表示已完成連接初始化。

八、無人機傳圖
在主界面點擊Media File Upload按鈕,進入圖像傳輸配置頁面,如下圖所示:

打開 Auto Photo Upload開關,選擇默認的Original Photo選擇,實現原始圖像的自動上傳。(默認已打開)

當拍攝后,圖庫里的照片將自動傳輸至云端,如拍攝界面的左上側紅框顯示,上下小箭頭消失后即上傳完成。

可在云端查看上傳的照片,如照片所示

如果不想自動傳輸,則關閉選項后,進入圖庫后,點擊打開需要上傳的照片,將自動實現上傳,右下角顯示上傳進度,當到達100%時,完成上傳。

依然可在云端查看上傳的照片,如照片所示

點擊明細后可在云端查看圖片

參考
centos 7 端口占用查看進程、根據進程名稱查詢進程信息、根據進程編號查詢進程信息、殺掉進程操作
linux rhel虛擬機中如何給磁盤動態擴容(硬盤直接擴展)
Linux - 通過LVM對磁盤進行動態擴容 (Linux的邏輯卷)
docker-compose 搭建 minio 分布式對象存儲 最新版(使用教程)
[docker] 淺談Docker:網絡模式及從容器內部訪問宿主機的IP地址
minio報錯SignatureDoesNotMatch解決方案
docker安裝 MinIO對象存儲(已解決 走nginx代理情況下, SignatureDesNotMatch簽名不一致問題)
Nginx配置域名反向代理MQTT 配置mqtt /ws /wss訪問域名連接。

浙公網安備 33010602011771號