EZ-WifiBroadcast 在 OpenWrt 上的移植與修改 另一種數字圖傳思路 - 模型電子 - 模友之吧 - Powered by Discuz!
快捷導航

EZ-WifiBroadcast 在 OpenWrt 上的移植與修改 另一種數字圖傳思路

[複制鍊接]
發表于 2019-7-13 16:05:20 | 顯示全部樓層 |閱讀模式

馬上注冊,結交更多好友,享用更多功能,讓你輕松玩轉社區。

您需要 登錄 才可以下載或查看,沒有帳号?注冊成為模友吧會員

x
本帖最後由 libc0607 于 2019-7-13 16:20 編輯

(最近半年除了交過幾次闆子作業之外主要在搞這個東西……斷斷續續……
EZ-WifiBroadcast 就是那個樹莓派圖傳 在這價位來說效果還算不錯 雖然早就知道有這麼個東西了但是沒時間搞……
主要是以自己的思路從頭開始重新組合了這個項目 改掉了一些個人覺得不太舒服的部分 并且又把成本降了一些 (到大約1/3?沒具體算過)

OpenWrt 固件源碼在 https://github.com/libc0607/lede/tree/air  注意分支 别的分支無關……
基于 Lean 的固件 修改部分在 mac80211 及 ath9k 關于解鎖功率/頻率 等 主要參考的還是原始項目的 kernel/ 下
OpenWrt 的軟件包部分在 https://github.com/libc0607/yjsnpi-broadcast-openwrt
暫時包含 本體 ezwifibroadcast / LuCI 界面 luci-app-wbc / libiniparser 一個庫
源碼本體在 https://github.com/libc0607/YJSNPI-Broadcast 直接 Fork 自原項目
包含 ezwifibroadcast 軟件包的本體源碼 樹莓派上運行的源碼 一些庫 以及一些配置文件
(起這個名字因為 想選一種動物->野獸->最厲害的野獸->它們的先輩 233)
上面的源碼僅處于勉強能用的狀态,暫時還沒能也沒敢上飛機……歡迎 Star

圖片是挺長時間之前拍的了 主要作為了解 等上了飛機再更新圖……
QQ圖片20190713160201.jpg

QQ圖片20190713160127.jpg

(圖中的屏幕轉接闆在 https://lceda.cn/libc0607/raspi-lcd-usbdev  )

QQ截圖20190713162454.png


QQ截圖20190713162514.png

原項目的結構大概是 樹莓派作為世界的中心 完成視頻編/解碼及無線的監聽/注入 幾乎所有的邏輯寫在 .profile 内
我的版本試圖将傳輸部分與視頻部分的耦合程度降低一些 樹莓派僅編解碼及 OSD 傳輸部分轉移到 OpenWrt 上 并且可以通過網頁配置這些東西
主要的進程都守護一下(procd 及 monit)
兩部分中間通過網絡傳輸 可以是通過 USB 接口的g_ether模式 也可以是普通的以太網接口
無線路由推薦用那種内置網卡是 ath9k 驅動且帶 usb 的 内存越大越好 像 ar934x qca9531 之類的就都不錯
一個原因是 ath9k 的網卡可以開 5MHz 頻寬的模式 犧牲清晰度的情況下 接收靈敏度可以再提高 3~5 個 dBm
另外是這些網卡都可以在 2.3G 及 2.5G 等頻率工作
另吐槽一下,基于樹莓派搞 hdmi 視頻輸入總是繞不開東芝那個至少需要四層闆的 bga 芯片……也不知道有沒有國産可以代用……所以就不搞了……

會帶來的好處比如 地面端不需要買派 2 以上 不用買貴得莫名其妙的二手網卡和顯示屏。。。之類的
現在樓主用的是派 0 配 DPI 的 LCD 屏 屏本體不到 30  
發射端使用 19.9 的樂視路由帶功放 接收可以選擇自帶雙極化定向天線和功放但隻要 27 不包郵的百米生活……
然後借助 OpenWrt 可以非常非常方便地實現 4G 圖傳 插一塊 Air720 開個國内阿裡雲跑 frp 也就一百多(
缺點大概是在飛機上綁一個路由器是不是搞錯了什麼(?)(其實有考慮過做專用的闆……但總是有問題……
兩張圖大概解釋一下結構區别


QQ截圖20190713154801.png

yj.png



其他部分的改進大概需要講很長時間的原項目結構(1.6RC6 版的),所以不會一下子就講完……慢慢碼好了 可能後續會更新一點原項目結構講解
樓主之後因為上學的原因時間可能會更少,希望可以抛磚引玉讓數字圖傳便宜一點點233





補充内容 (2019-7-16 11:31):
樓下正在努力更新 原項目&我的修改版 的 結構講解&代碼筆記
希望有人看到感興趣了能一起搞搞(((

評分

參與人數 1牛币 +10 收起 理由
飛來峰 + 10 很給力!

查看全部評分

發表于 2019-7-13 17:56:57 | 顯示全部樓層 來自安卓客戶端來自安卓客戶端
除了有點臭都挺好的
發表于 2019-7-13 21:58:05 | 顯示全部樓層
挺好的{:1_1:}{:1_1:}
 樓主| 發表于 2019-7-14 12:13:09 | 顯示全部樓層
原版項目在國内也沒見到什麼公開的中文分析,但這事兒總得有人幹。。樓主希望可以帶動更多的人在此基礎上改進。下文分析會基于 EZ-WifiBroadcast 的 1.6RC6 版。

0. 硬件
最常見的問題 “為什麼是樹莓派,而不是xx……?我看xx(水果)派便宜好多呢”
在 2019年7月 能搞定h265的派4出現之前:這個派是最容易搞定h.264視頻的硬件編解碼的:raspivid 輸出視頻流,hello_video.bin 解碼,基本不需要修改。
至于深受隻看價格的人的喜愛的sunxi(?)SoC 啥的,看看能不能非常方便地搞定硬件視頻編解碼先。。如果是自己做闆的話,加上512M内存後成本還不一定比派0低。
如果不做實時編碼的話不僅要占用掉很大的帶寬(從而對信号質量要求高-距離短),搞不好比模拟還糊。

我的修改版也無法避免地使用了樹莓派0 233 因為又嫌麻煩又嫌貴的話就找不到什麼替代品了。。以後可能會挖坑搞搞海思比如3516啥的

網卡原項目主要推薦的是 AR9271,這個SoC連firmware都開源了(https://github.com/qca/open-ath9k-htc-firmware)。
原項目由于這個SoC默認的包注入速率不會按照radiotap頭部來的問題也有修改這個固件(見 https://bitbucket.org/befi/wifibroadcast/src/62d3d35a2374d2b02d0c77a5b6988f2e96fd5913/patches/AR9271/firmware/)。
Ralink的卡主要是RT5572/RT3572,螃蟹的RTL8812*也在支持列表裡了。
用這些芯片且帶功放的卡在國内平台貌似都比較難淘到合适的,都被搞破解的炒到高價(?)。。不過前幾天看到有一批大功率的8812不知道咋樣(?)
另一個思路就是買低功率的卡外接功放。接線上無非就是電源線夠粗,數據線擰一塊兒,供電要足之類的話。。

使用 qca 的路由器芯片就可以避開無線芯片固件問題,實際注入時會按照radiotap中填寫的值發送。
 樓主| 發表于 2019-7-14 12:19:56 | 顯示全部樓層
1. 軟件
這個坑開得有點大不知道能解釋成什麼樣……我盡力吧

https://github.com/rodizio1/EZ-WifiBroadcast
在Github的1.6RC6分支下可以看到各個程序,它們看似獨立但卻以十分複雜的方式耦合在一起(狗頭保命)。
這個分支是鏡像裡的主要文件,不包括各種運行環境(下面會提到鏡像構建和運行環境)。。
/boot 目錄下就是sd卡能在windows下看到的那個分區,裡面主要是各種配置文件和内核。
/root 是root的主目錄,主程序啥的都在這裡。


/boot下與官方鏡像相比主要新增/變動的東西:
./osdfonts/ 給OSD用的字體,顯示用的各種符号都在這
./apconfig.txt 通過Wi-Fi共享視頻的設置
./cmdline.txt 改動關于默認console,root分區不用uuid指定,tf卡隻讀,關掉啟動輸出,加快啟動,以及dwc驅動的一些設置 等等等等
./config.txt 各種超頻以提升性能,加快啟動,以及一些接口設定
./cmavnode.conf 給cmavnode用的配置文件,這個程序本體是個用c艹寫的mavlink轉發器
./joyconfig.txt 搖杆設定,也是個c的頭文件,不是重點
./osdconfig.txt osd設定,本質是一個c的頭文件,改完之後每次啟動都會跟osd的源碼一起重新編譯
./wifibroadcast-1.txt 大部分與圖傳這件事本身有關的設置,是個shell腳本,會在.profile裡被source進去
./kernel.img 派01的内核 一堆魔改
./kernel7.img 派23的内核 一堆魔改        // 内核魔改看develop分支/kernel下的patch和兩個config



/root下:
./FlirScripts 及 ./flir8p1-gpl 關于 FlirOne,貌似是熱成像?我也沒玩過,就先略過;
./cmavnode 與 mavlink 有關,見 https://github.com/MonashUAS/cmavnode
./gnuplot 畫統計圖用的
./mavlink-router 與 mavlink 有關,見 https://github.com/intel/mavlink-router
./wifibroadcast 大部分主程序的源碼/可執行文件,下面會詳細提到
./wifibroadcast_misc 雜七雜八的功能,比如撥碼開關選擇配置文件、步進電機控制等
./wifibroadcast_osd OSD的源碼,每次啟動都會将osd程序重新編譯到/tmp目錄下(因為/root隻讀了)
./wifibroadcast_rc 與RC相關,這部分我也沒咋研究。。主要是那個rctx
./wifibroadcast_status   wbc_status,在屏幕上顯示一行字的那個功能;比如插上U盤後的那個可以移除的提示就是它幹的
./各種profile  實際上被當作啟動腳本



 樓主| 發表于 2019-7-14 12:31:08 | 顯示全部樓層
原版的組裝和使用方法實在是懶得翻譯,推薦去原項目wiki查看。https://github.com/rodizio1/EZ-WifiBroadcast/wiki 啥都有。
這裡主要解釋他們不是寫給人看的部分

在原版項目中,/root/.profile 是啟動并root登陸後實際運行的文件,這個項目的絕大多數主要功能都寫在這裡。在每個root登陸的終端(其實主要是tty1~tty12)都會運行一遍這個腳本,裡面為每個tty分配了不同的任務,同時運行。

關于.profile啟動的大緻幾個關鍵點流程解釋:
查找 ”# Start of script“ 找到文件的實際開頭(1.6RC6 鏡像中的1820行,下同);
首先判斷自己是第幾個tty(Ln1827)及是否接了攝像頭(Ln1833)——接了會被認為是天上的Pi (裡面稱之為Air Pi),沒接就是 Ground Pi;
如果是RX,下一步根據屏幕分辨率設置終端字體(Ln1848);
Ln1867開始加載配置文件,配置文件加載過程如下:啟動時會運行 /root/wifibroadcast_misc/wbcconfig.sh,裡面調用 /root/wifibroadcast_misc/gpio-config.py 根據GPIO狀态判斷該加載/boot下的哪個wifibroadcast-*.txt,然後使用dos2unix轉換對應的文件到/tmp/settings.sh 并source進來
Ln1885開始把設定的DATARATE轉換成視頻、遙測、上行的實際發射速率
Ln1923根據設定的fps選擇實際顯示程序,他們有幾個不同修改的hello_video.bin,程序的功能就是從标準輸入硬解碼視頻顯示


Ln1980開始進入主switch-case,不同的tty執行不同的任務。

 樓主| 發表于 2019-7-15 13:30:25 | 顯示全部樓層
本帖最後由 libc0607 于 2019-7-16 10:48 編輯

進入主Case之後每個tty會負責不同的任務,故下文将按照每個不同的任務簡單描述一下。。其實是自己看代碼時的筆記為方便這裡也傳一份profile文件
profile-1.6rc6.rar (14.49 KB, 下載次數: 1)
發表于 2019-7-15 14:49:29 | 顯示全部樓層 來自安卓客戶端來自安卓客戶端
這是啥
 樓主| 發表于 2019-7-16 11:27:25 | 顯示全部樓層
本帖最後由 libc0607 于 2019-7-16 11:51 編輯

然後另一個重點是數據回傳,Telemetry,這部分功能與osd密不可分,所以放在一塊兒做筆記
profile的第1992行開始, tty2:地面運行 osdrx_function,天上運行 osdtx_function

osdrx_function在999行
先提一下兩個版本的區别
osd接收端啟動的過程有些麻煩,原項目配置osd的方式為修改一個/boot目錄下的頭文件(https://github.com/rodizio1/EZ-WifiBroadcast/blob/1.6RC6/boot/osdconfig.txt)并在每次啟動時重新編譯到/tmp下。
(見 https://github.com/rodizio1/EZ-WifiBroadcast/wiki/Software-~-Advanced-~-Telemetry-&-OSD )
我的版本将這部分改為文件預先編譯好,通過參數載入配置文件的方式來指定osd位置(https://github.com/libc0607/YJSNPI-Broadcast/blob/op/boot/osdconfig.ini)
另一個改動是數據的流向,原項目為 rx_rc_telemetry_buf 或串口輸入 -> /root/telemetryfifo* -> /tmp/osd
由于我的版本中需要和OpenWrt協同工作,故改為監聽udp端口獲取數傳數據
1002 先将/boot/osdconfig.txt 轉為unix格式
1004~ 重新編譯osd程序
1018~ 等待hello_video運行後再啟動osd
1028~ 選擇是從空中接收數傳數據還是從串口直接輸入,然後據此設定TELEMETRY_RX_CMD這個變量
空中接收則使用rx_rc_telemetry_buf;如果是串口輸入就先用stty設置串口屬性,并把該變量設為 cat 串口
數傳部分的數據流向與視頻基本相同,涉及到将數據分到6個fifo中,這部分他有寫一些注釋就不翻譯了:
        # telemetryfifo1: local display, osd
        # telemetryfifo2: secondary display, hotspot/usb-tethering
        # telemetryfifo3: recording
        # telemetryfifo4: wbc relay
        # telemetryfifo5: mavproxy downlink
        # telemetryfifo6: serial downlink
fifo1: 實際由/tmp/osd作為讀端,見https://github.com/rodizio1/EZ-WifiBroadcast/blob/1.6RC6/root/wifibroadcast_osd/main.c#L97
fifo2:給第二屏用,在tether_check_function與hotspot_check_function中使用socat為讀端通過udp發送出去
fifo3:作為日志記錄,在1052行,讀取并保存到 /wbc_tmp/telemetrydowntmp.raw
fifo4:中繼模式下使用,1057行通過cat讀取并再次使用tx_telemetry發送
fifo5:mavproxy downlink,在tether_check_function與hotspot_check_function中又将數據定向到了/dev/pts/0(在rx_function中建立的虛拟終端,804~)
fifo6:1042行讀取,數據發到TELEMETRY_OUTPUT_SERIALPORT_GROUND這個串口輸出,是在/boot/wifibroadcast-*.txt中的設置

然後比上面視頻一分四更騷的操作來了,1065 1067 和 1070,用了一大堆ftee把回傳數據一分六存到fifo中…………………………
(不知道說啥好反正ftee也是抄來的(https://github.com/racic/ftee)為啥不改改源碼直接一分六((
1072~ 錯誤處理,收集信息,退出

  
osdtx_function 運行在天上 這個超短 也沒什麼複雜邏輯
主要是1087~等待網卡配置完畢
1103 從串口讀取,數據發給tx_telemetry發送,下面都是錯誤處理,沒了

懶人一鍵版:
天上發射端 從串口讀數據 送到tx_telemetry 發送
地上接收端 rx_rc_telemetry_buf 接收後一分六 用于osd 第二屏 記錄 中繼 等等用途
原版的osd是每次啟動用/boot/osdconfig.txt新鮮編譯的





發表于 2019-7-16 12:28:36 | 顯示全部樓層
用樹莓派的話功耗有點大,再說樹莓派自帶的WiFi功率太小了,估計二三十米就斷了。
 樓主| 發表于 2019-7-16 13:28:25 | 顯示全部樓層
宜興模友 發表于 2019-7-16 12:28
用樹莓派的話功耗有點大,再說樹莓派自帶的WiFi功率太小了,估計二三十米就斷了。 ...

我自己用的派0的發熱不算大,我在測試的時候地面端cpu占用也隻有30%上下,沒加散熱片也不會很熱。原版用的派23就明顯熱很多了。
自帶的wifi确實雞肋,所以原版和我的都沒用它
 樓主| 發表于 7 天前 | 顯示全部樓層
咕了兩個星期,更新一點

關于 packet  injection 與 radiotap header
由于這玩意兒實在搜不到什麼連鴿子都能看懂的中文版的解釋所以按照自己的理解随便寫點 可能有誤請指出

當把支持 monitor mode 下稱監聽模式 的網卡設置成監聽模式後,它就可以監聽在你設定的頻率上能被這網卡認出來的包
有很多網卡支持這個模式 如原項目的ar9271/rtl8812之類  也有一些網卡不支持如 ath6k ath10k那些
這些不支持常見原因是因為沒有支持這個功能的firmware
firmware就是字面意思 可以當作是初始化網卡時主機傳給網卡内部cpu運行的程序
有的firmware開源了 如ar9271那個 上面有提到 更多的沒有開源
firmware的有些行為會無法預測 如ar9271在注入的時候不管你填什麼速率 g還是n 都會按1mbps發送 因為順序寫死在firmware裡了
還有rtl8192啥的忘了一個 發data包全部默認mcs7 發rts包全部默認1mbps = =...還改不了
所以給圖傳選個能用的網卡比較難= =

監聽模式下同時也可以按照你的要求繞過協議棧發送一些自定義的包 叫做 packet injection 注入
對于這個項目而言 好處是繞過了協議棧的确認重傳等等一大堆複雜的問題 底層可以由自己控制 可以降低延遲 等等
在用戶态的應用程序告訴驅動該怎麼發送這個包的時候 除了包的本體 還需要帶上一些額外的信息 常見的如 速率 頻率  guard interval 等等
這些信息在注入時需要你自己确定好 按照格式寫在頭部傳遞給内核 然後驅動會讀取這些内容并按照你的設定發送
同樣在收包的時候 驅動會按照相同的格式填好信息并返回給用戶态的應用程序
這套描述附加信息并寫在頭部的方式叫 radiotap

下面會簡單描述一下這東西在ez-wifibroadcast項目裡怎麼玩的
先以我用wireshark随便抓到的一個包(接收)為例解釋一下它的包頭結構


0x00,                                                 // Header revision
0x00,                                                 // padding (for (uint16)length )
0x24, 0x00,                                        // Length, (le)uint16
0x2f, 0x40, 0x00, 0xa0,                         // Present flags word (bit31=1, has next present flag)
0x20, 0x08, 0x00, 0x00,                        // Second Present flags word


0x00, 0x00, 0x00, 0x00,                        // padding (timestamp uint64)
0xf1, 0x18, 0xc2, 0x3f, 0x00, 0x00, 0x00, 0x00,        
                                                        // Timestamp, uint64, 1069684977
0x10,                                                 // flags (See enum ieee80211_radiotap_flags)
0x30,                                                 // Data rate (500kHz unit)
0x85, 0x09,                                         // 0x0985, 2437, Channel frequency MHz
0xc0, 0x00,                                        // Channel flags (See enum ieee80211_radiotap_channel_flags)
0xcb,                                                 // Signal, int8, -53, dBm
0x00,                                                 // Antenna 0
0x00, 0x00,                                        // RX Flags (See enum ieee80211_radiotap_rx_flags)


// Second Present flags word
0xcb,                                                 // Signal, int8, -53, dBm
0x00, 0x00,                                        // Antenna 1


結構都寫了注釋 應該很好看懂
present flag 用每一bit指示後面是否有出現相應的數據項
可以存在多個 present flag 若某一個present flag 轉大端後的最高位為1 則指示緊接着的四個字節是下一個present flag
這段數據中的第一個 present flag如下 (僅寫出了為1的位)

1010 0000 0000 0000 0100 0000 0010 1111‬
.... .... .... .... .... .... .... ...1 = TSFT: Present
.... .... .... .... .... .... .... ..1. = Flags: Present
.... .... .... .... .... .... .... .1.. = Rate: Present
.... .... .... .... .... .... .... 1... = Channel: Present
.... .... .... .... .... .... ..1. .... = dBm Antenna Signal: Present
.... .... .... .... .1.. .... .... .... = RX flags: Present
..1. .... .... .... .... .... .... .... = Radiotap NS next: True
1... .... .... .... .... .... .... .... = Ext: Present



最高位指示有下一個present flag,如下:
0000 0000 0000 0000 0000 1000 0010 0000
.... .... .... .... .... .... ..1. .... = dBm Antenna Signal: Present
.... .... .... .... .... 1... .... .... = Antenna: Present



關于padding在radiotap的規範裡有提到 由于每項數據的大小都是不同的 所以在确認是否需要padding 的時候 看下一個數據的大小 把下一個數據對齊到該大小的整數倍 與前一項中間的空位就都填0
比如第一個數據uint8在0x0,第二個放uint32的話就要在前面補3個0x00,這樣這個uint32就是對齊的
每個數據占用的大小見Linux内核源碼的 include/net/ieee80211_radiotap.h  數據排列順序按照 present flags 字段中先轉為大端序後 從低位到高位的順序
數據本體為小端序

所以按照上面兩個present flag 的解析,後面的數據順序應該如下:
TSFT +Flags +Rate +Channel +dBm Antenna Signal +RX flags +Radiotap NS next +dBm Antenna Signal(2) +Antenna(2)    (并按需padding)

然後對着注釋就能看明白了。。


至于發送的時候,摘取原項目tx_measure中一點 見 https://github.com/rodizio1/EZ-WifiBroadcast/blob/1.6RC6/root/wifibroadcast/tx_measure.c#L160
packet_header_init() 這個函數負責填寫發送緩沖區的radiotap頭部與ieee80211頭部
具體做的事是 把 u8aRadiotapHeader 以及 u8aIeeeHeader_rts, u8aIeeeHeader_data_short, u8aIeeeHeader_data中(看你的配置)的一個複制到緩沖區的開頭
并按照配置填寫rate與port
摘錄如下
static u8 u8aRadiotapHeader[] = {        0x00, 0x00, // <-- radiotap version        0x0c, 0x00, // <- radiotap header length        0x04, 0x80, 0x00, 0x00, // <-- radiotap present flags        0x00, // datarate (will be overwritten later in packet_header_init)        0x00,        0x00, 0x00};


結構完全可以用上面提到的解釋 就不寫了
值得注意的是這個在使用ar9271(ath9k_htc)網卡時填寫rate也沒用,因為他們是靠搞了一堆不同的firmware切換來達成發送速率切換的

另外 上面提到的rate字段僅對802.11abg起作用  
如果想要通過radiotap指定發送802.11n或是802.11ac的包 甚至開啟ldpc摳2個dbm出來的話
需要網卡驅動支持按照radiotap發包(atk9k就沒毛病。。)ldpc需要網卡硬件支持
并在present flag中 設定 mcs 或 vht 的位 并在對應位置增加數據

具體可以見我寫的 https://github.com/libc0607/YJSNPI-Broadcast/blob/op/root/wifibroadcast/tx_test.c 是一個可以拿來發測試包的小程序 寫了注釋


參考資料
https://github.com/torvalds/linux/blob/master/include/net/ieee80211_radiotap.h
https://warmcat.com/git/packetspammer/tree/packetspammer.c
https://github.com/torvalds/linux/blob/master/Documentation/networking/radiotap-headers.txt
https://github.com/torvalds/linux/tree/master/Documentation/networking/mac80211-injection.txt




















 樓主| 發表于 6 天前 | 顯示全部樓層
本帖最後由 libc0607 于 2019-8-2 12:31 編輯

共享内存筆記

wifibroadcast各進程通過共享内存的方式傳遞一些信息
共享内存結構體在 lib.h 中定義 https://github.com/rodizio1/EZ-WifiBroadcast/blob/1.6RC6/root/wifibroadcast/lib.h   變量名起得非常容易理解 就不解釋了

命令行參數中的 port 被原項目定義為 ieee 802.11 header 中的一個 byte 并以此區分過濾不同作用的包
具體位置可以在項目中搜索 u8aIeeeHeader_data, u8aIeeeHeader_rts, u8aIeeeHeader_data_short 定義,内含注釋
雖然看上去可以通過命令行自由指定(還像這樣用括号注明了0-255),但由于與共享内存的名字相關,所以又不能随便指定

port的分配:
Air Pi                                 <--> Ground Pi
-------------------------------------
0:tx_rawsock                  --> rx (Video)
1:tx_telemetry          --> rx_rc_telemetry_buf (telemetry)
3:rx_rc_telemetry  <--  tx_telemetry (Uplink)
4: mspdownlink 沒用過 不讨論



在所有的其他程序運行前 都要先用sharedmem_init_*x 初始化

air pi 包含
/wifibroadcast_tx_status_0                        
        類型:wifibroadcast_tx_status_t
        寫端:tx_rawsock
        讀端:rssitx
        内容:視頻發射統計等
        
/wifibroadcast_rx_status_0                        
        類型:wifibroadcast_rx_status_t
        寫端:rx (中繼模式下)
        讀端:tx_rawsock, tx_telemetry
        内容:視頻接收統計
        
/wifibroadcast_rx_status_3                        
        類型:wifibroadcast_rx_status_t
        寫端:rx_rc_telemetry
        讀端:rssitx
        内容:uplink接收統計

/wifibroadcast_rx_status_rc                        
        類型:wifibroadcast_rx_status_t_rc
        寫端:rx_rc_telemetry
        讀端:rssitx
        内容:rc接收統計



ground pi 包含
/wifibroadcast_rx_status_0                        
        類型:wifibroadcast_rx_status_t
        寫端:rx
        讀端:osd tx_telemetry check_alive rssi_forward
        内容:視頻接收統計
        
/wifibroadcast_rx_status_1                        
        類型:wifibroadcast_rx_status_t
        寫端:rx_rc_telemetry_buf
        讀端:osd rssi_forward
        内容:telemetry接收統計
        
/wifibroadcast_rx_status_rc                        
        類型:wifibroadcast_rx_status_t_rc
        寫端:rssirx
        讀端:osd rssi_forward
        内容:Air Pi 上的rc接收統計
        
/wifibroadcast_rx_status_uplink               
        類型:wifibroadcast_rx_status_t
        寫端:rssirx
        讀端:osd
        内容:Air Pi 上的uplink接收統計
        (寫到這裡發現我的rssi_forward*沒轉發這個。。)
        
/wifibroadcast_rx_status_sysair               
        類型:wifibroadcast_rx_status_t_sysair
        寫端:rssirx
        讀端:osd rssi_forward
        内容:Air Pi 的系統狀态
        

另外除了上面列出的,還有tx_measure.c 但隻是用來測試,不是重點
rx_status.c 是一個讀取共享内存的小工具

看到這就很清楚了,rssitx/rssirx這一對主要是用于轉發 air pi 中的共享内存到 ground pi 的
rssitx 實際發送的内容可以在 https://github.com/rodizio1/EZ-WifiBroadcast/blob/1.6RC6/root/wifibroadcast/rssitx.c#L74 看到
摘要如下:
int8_t signal;
uint32_t lostpackets;
int8_t signal_rc;
uint32_t lostpackets_rc;
uint8_t cpuload;
uint8_t temp;
uint32_t injected_block_cnt;
uint32_t skipped_fec_cnt;
uint32_t injection_fail_cnt;
long long injection_time_block;
uint16_t bitrate_kbit;
uint16_t bitrate_measured_kbit;
uint8_t cts;
uint8_t undervolt;








 樓主| 發表于 4 天前 | 顯示全部樓層
本帖最後由 libc0607 于 2019-8-4 23:04 編輯

osd筆記

原項目代碼在 https://github.com/rodizio1/EZ-WifiBroadcast/tree/1.6RC6/root/wifibroadcast_osd
osd的原項目wiki在 https://github.com/rodizio1/EZ-WifiBroadcast/wiki/Software-~-Advanced-~-Telemetry-&-OSD

這個項目的osd是獲取到原始telemetry數據後在本地疊加的
并且因為telemetry數據量小 甚至可以做到在視頻剛剛沒信号的時候osd還能工作

主要用到(也是編譯中主要的坑)是一個叫openvg的畫圖用的庫
原項目裡用的是一個fork出來的版本 見https://github.com/SamuelBrucksch/openvg

工作流程
首先 啟動的時候 按照上文所說 會在profile中先編譯再啟動它
編譯的時候引用osdconfig.h 這個文件是在電腦上設置時的 boot盤中的osdconfig.txt
從main.c開始看 為簡潔将不會提到使用timestamp進行fps等性能統計的相關代碼
main.c中,首先初始化了共享内存和render
然後打開 /root/telemetryfifo1 和 /tmp/undervolt 兩個文件
上文分析profile時提到過 /tmp/undervolt 是地面端的低供電檢測
/root/telemetryfifo1是一個命名管道
rx_rc_telemetry_buf接收到的telemetry消息會送到這個管道一份 osd即為讀端

L140進入主循環
使用select的方式循環讀取telemetry的命名管道至buf中 超時時間設置為50ms
當成功讀到數據後 L158~L166 根據在osdconfig.txt中設置的telemetry類型
送到不同的處理函數 将信息處理好放在td這個telemetry_data_t結構體中
主要如下 (先略過 下文再說)
frsky_parse_buffer(&fs, &td, buf, n);
do_render = ltm_read(&td, buf, n);
do_render = mavlink_read(&td, buf, n);
smartport_read(&td, buf, n);
往下 L176 render()執行渲染
觸發渲染的條件是 有需要盡快更新的數據(do_render==1,這個變量如上文,是由處理telemetry數據的函數返回的)
或是3個50ms内沒有更新(也就是osd最差情況下的刷新率是150ms/幀)
同時 每隔約1000ms會觸發一次地面派的溫度與cpu占用更新(L188~L202)
主循環到此為止

上面的四個将telemetry數據處理到telemetry_data_t結構體中的函數分别位于frsky.c ltm.c mavlink.c smartport.c
這四個.c裡面基本都是關于協議實現的東西 隻要解析正确即可 無需改動
telemetry_data_t 的定義與初始化見telemetry.h與telemetry.c 也無需大改

吃瓜群衆最關心的osd界面渲染在render.c中
render_init() 從/boot/osdfonts/ 中按照用戶設定加載字體
頂層函數為 void render(telemetry_data_t *td, uint8_t cpuload_gnd, uint8_t temp_gnd, uint8_t undervolt, int osdfps)
該函數的主要功能即為根據各種用戶設定決定該用什麼顔色顯示什麼信息在哪
(一片#ifdef的海洋)
(我的版本改成ini的if判斷了(
render_init調用的下一層函數為 draw_* 參數主要包含要顯示的信息 顯示位置及比例
draw_*層會調用TextEnd TextWidth 等實際完成繪制的函數 Fill Stroke 設置文字顔色與邊緣顔色 等等

另外 關于osd實際從共享内存中讀取的内容 我整理了一下列了出來

/wifibroadcast_rx_status_0        
rx_status->adapter.current_signal_dbm
rx_status->adapter.received_packet_cnt
rx_status->adapter.signal_good
rx_status->adapter.type
rx_status->adapter.wrong_crc_cnt
rx_status->damaged_block_cnt
rx_status->kbitrate
rx_status->lost_packet_cnt
rx_status->lost_per_block_cnt
rx_status->received_block_cnt
rx_status->received_packet_cnt
rx_status->tx_restart_cnt
rx_status->wifi_adapter_cnt

/wifibroadcast_rx_status_rc        
rx_status_rc->adapter[0].current_signal_dbm
rx_status_rc->lost_packet_cnt

/wifibroadcast_rx_status_sysair        
rx_status_sysair->bitrate_kbit
rx_status_sysair->bitrate_measured_kbit
rx_status_sysair->cpuload
rx_status_sysair->cts
rx_status_sysair->injection_fail_cnt
rx_status_sysair->injection_time_block
rx_status_sysair->skipped_fec_cn
rx_status_sysair->temp
rx_status_sysair->undervolt

/wifibroadcast_rx_status_uplink        
rx_status_uplink->adapter[0].current_signal_dbm
rx_status_uplink->lost_packet_cnt

總結一下
如果想漢化一下加入中文提示?主要改動draw_*層函數,畫中文上去即可
如果添加一個新的功能顯示?首先解決數據來源,然後新建draw_*,在render()中調用即可
如果加入osd調參?坑太大了我不做。。。(狗頭

 樓主| 發表于 前天 22:37 | 顯示全部樓層
關于集成度高一點的天空端

核心用了windora bit 3.1 可以外接pcie網卡 我圖裡挂了個ar9287因為便宜不心疼
屏幕闆是dpi模式 二手裸屏20多能收到 因為一開始就定位為“不需要抱着個顯示器出去飛”這種所以也沒追求特别高清 就隻800x480

天空端闆子在 https://lceda.cn/libc0607/pi0-widora-video
屏幕闆在 https://lceda.cn/libc0607/raspi-lcd-usbdev


223636znaw5aq87qav00q7.jpg

223634qhhyxhwzxkzioijk.jpg

223633w6hqjx8rxq4hxhv7.jpg

本版積分規則

模友之吧 中國唯一免費送模型網站

反饋建議:2376808768@qq.com

合作夥伴

掃碼關注微信公衆平台
本站由 承德紅璐科技 提供技術支持  Powered by Discuz!©2011-2015 模友之吧 | 冀ICP備13020518号©
快速回複 返回頂部 返回列表
http://m.juhua355426.cn|http://wap.juhua355426.cn|http://www.juhua355426.cn||http://juhua355426.cn