
這個檔案整理 此專案下 程式代碼的流程與思路
只會挑出重要的變數與方法描述
以利後續開發使用

# 開發此專案的注意事項
- 預設 autopilot 的 component id = 1
- 不允許 system id 重複
- 增加一個固定數值監控然後要到 ros2 topic 
  - mavlinkROS2Node.py 檔案內 
    - PublishRateController.topic_intervals 建立
    - VehicleStatusPublisher._publish_vehicle_status 登記
    - VehicleStatusPublisher._publish_XXX 實作
  - mavlinkObject.py 檔案內 
    - mavlink_bridge.message_handlers 登記
    - mavlink_bridge._handle_XXX 實作
    - mavlink_object.bridge_msg_types 登記 (這個可以用介面調)
  - mavlinkVehicleView.py 檔案內 
    - 注意對應的資料存放區


---
# 檔案結構

特別注意:
1. 有標註 [async method] 都是不該被直接呼叫的內部方法

- *valuable* 這個是變數 **沒有括號**
- *method (parameters...)* 這個是方法 **有括號**

## mainOrchestrator.py : 程式進入點

### **[Class]** Orchestrator 
    最上層的發配資源與啟動終端機面板的調配者
- *self.manager* 存放 async_io_manager 實例 
- *self.bridge* 存放 mavlink_bridge 實例 
- *self.plumber* 存放 serial_manager 實例
- *self.vehicle_registry* 存放 vehicle_registry 實例

- *self.panel_thread* 面板的執行緒
- *self.panelState* 暫存面板與調配者互動的資料流動區
  - 面板運行狀態 
  - 面板操作結果
  - 其他模組的運行狀態
---
- *mainLoop()* 核心方法 
  - 更新個模組狀態到 *self.panelState*
  - 對應面板來的操作指令
---
    對於 async_io_manager 控制實現
- *create_udp_object()*
- *delete_udp_object()*
- *add_target_to_object()*
- *remove_target_from_object()*
---
    關於載具管理與檢視
- *_update_vehicles_list()*
- *_prepare_vehicle_info()*
---
    關於 serial_manager 控制實現
- *create_serial_port_object()*


### **[Class]** ControlPanel 
    面板的核心運行物件
    把自己的變數 獨立出來都放到 PanelState 去
- *panel_thread()* 核心方法 
  - 主選單的引入
  - 主選單下所有的按鍵操作
  - 定義所有人為操作後續面板執行緒行為
- *menu_tree()* 基礎選單的定義檔
---
    關於 udp object 的操作
- *create_object_list_menu()* object 選單的定義檔
- *show_object_info()* 顯示 object 資訊
- *select_target_socket()* object 對於轉拋功能的操作
---
    關於 serial 的操作
- *create_serial_port_menu()*
- *create_linked_serial_menu()*
- *show_linked_serial_info()*
---
    關於載具檢視與操作
- *create_vehicles_list_menu()*
- *show_vehicle_info()*

### **[Class]** PanelState
    作為面板執行緒(ControlPanel)與調配者(Orchestrator)溝通的管道
    不包含具體實作方法 是 ControlPanel 的延伸
- *self.panel_info_msg_list* 顯示在面板上的資訊訊息

## mavlinkObject.py

### 全域變數
- *stream_bridge_ring* 
- *return_packet_ring*

### **[Class]** mavlink_bridge
    唯一實例
    實際去解析 mavlink 封包的地方
    接收 stream_bridge_ring 與 return_packet_ring 的資料
    這邊是比較偏自動化 不會被操作的
- *self.thread* 自己的執行緒
---
- *_run_thread()* 核心方法
- *_handle_XXXXX()* 每一種單項 mavlink 封包的解析
- *send_message()* 是 _send_to_socket() 的高階包裝 跟 ros2 介面做互動的方法
- *_send_to_socket()* 把要傳送的封包 丟給 mavlink 去處理

### **[Class]** async_io_manager
    唯一實例
    異步 event loop 
    沒有核心方法
    這邊主要是管理 mavlink_object 的地方 (但不會對於某個 mavlink_object 內部需求做操作)
    
- *self.thread* 自己的執行緒
- *self.managed_objects* 資料結構  socket_id: mavlink_object
---
- *add_mavlink_object(mavlink_object)* [call method] 把一個 mavlink_object 物件加入管理
- *_async_add_mavlink_object(mavlink_object)* [async method] 對應上面的內部方法 不該直接使用
- *remove_mavlink_object(socket_id)* [call method] 從管理區把指定 mavlink_object 移除

### **[Class]** mavlink_object
    儲存 mavlink socket
    處理 mavlink 封包分流的地方
- *cls.mavlinkObjects* 資料結構 { socket_id(序號) : mavlink_object(物件實例) }
- *self.mavlink_socket* 從 pymavlink 繼承的socket物件
- *self.state* 描述這個 socket 物件的狀態
---
- *process_data()* [async method] 核心方法
- *remove_target_socket()* *add_target_socket()*
- *message_put_queue()* 把要傳送的封包放到自己這個物件的暫存區 會由 process_data() 依照異步流程被實際丟出

## serialManager.py
    看這個檔案的重點再於要搞清楚 端口物件 還是 傳輸物件

### **[Class]** serial_manager
    異步 event loop 
    管理 mavlink_object 的地方
- *self.thread* 自己的執行緒
- *self.loop* 自己的事件迴圈
---
- *create_serial_link()* [call method] 把 serial 端口跟 UDP 端口打通
- *_async_create_serial_link()* [async method] 把兩種端口接起來的重點程序
- *remove_serial_link()* [call method] 關閉指定的 serial 端口
- *_async_remove_serial_link()* [async method]

### **[Class]** serial_object
    被塞在 serial_manager 裡面
    只是一個變數物件
    用來被儲存 serial 的資訊
- *self.transport*
- *self.protocol*
- *self.udp_handler* UDP 端口物件
- *self.serial_handler* Serial 端口物件

### **[Class]** UDPHandler
    處理 UDP 收發的端口 作為一個端口物件
    作為 UDP OutBound 使用 所以不會佔用系統監聽資源
- *self.transport* 自己的傳輸物件
---
- *datagram_received()* 先加碼成 Xbee 再呼叫 Serial 端口物件送出

### **[Class]** SerialHandler
    處理 Serial 收發的端口 作為一個端口物件
- *self.transport* 自己的傳輸物件
---
- *data_received()* 先組合 Serial 封包 再解碼 再呼叫 UDP 端口物件送出

## mavlinkVehicleView.py
    這個檔案是作為載具的資訊暫存庫使用 會搭配 ROS2 的功能 再做利用

# 開發記錄

## 已實現功能
1. mavlink 分流解析
2. mavlink socket 建立
3. mavlink socket 轉拋 proxy
4. 建立 Serial 轉 UDP 連結 並管理
5. 建立 serial 連線
6. 各單元模組化
7. 終端機介面控制
8. 基礎載具流量觀測
9. 載具狀態收集與彙整
10. a. ros2 topic 應用開發介面

### 待開發功能
5-1. 建立 serial 連線 並可以對接收器下達AT指令
5-2. 模組化 serial 連線機制 以利後期擴容其他模組
10. a. ros2  應用開發介面