--- tags: asrlab --- # RSU architecture ## 架構圖 https://drive.google.com/file/d/1ApfR6PfXs5p9meRni39boEqW6jtZmvZP/view?usp=sharing ![](https://i.imgur.com/D5Nw6NW.png) ## Application registeration ### application_attributes ```c app_obj_t XXX = { .name = "XXX", .id = 4, .priority = 3, .on_OBU_packet_rx = NULL, .on_OBU_packet_tx = NULL, .on_RSU_packet_rx = NULL, .on_RSU_packet_tx = NULL, .on_cloud_packet_rx = NULL, .on_cloud_packet_tx = NULL, .on_traffic_signal_command_tx = NULL, .on_registration = &XXX_on_registration, .next = NULL, }; ``` ### register 流程 所有的 app (applicaton) 會被紀錄在 `app_list` (a singly-linked-list) 中,呼叫 `app_register` 會將欲註冊之 app 放到 `app_list` 的最後面, 過程會檢查此 app 是否註冊過,成功插入會將 `app_num` + 1,`app_num` 代表目前以註冊的 app 數量。 接著將 app attributes 中的 funciton 插入 callback_list 中,目前總共有 9 條 callback_list 來紀錄 callback_function 以及其所對應的 app_name、app_id、app_priority。 最後找出存放 register function 的 callback_list (callback_list[8]) 中的最後一個 node,執行存放於這個 node 中的 register function,也就是存放在這個 app 的 attribute `on_registration` 中的 register function 來完成 register。 ## Command buffer ## 1. 接收端 ### traffic_signal_packet_rx_handler traffic_signal_packet_rx_thread 的 task,用來接收號控箱封包。 在 main funciton 中會 call `traffic_signal_port_init()` 設定 `serial_port_fd`,TC 箱發送訊息的 fd,接著利用 `read` 來讀取資料,一次讀取一個 byte。 第一次讀取時會確認是否為 header(0xAA),如果是就把 escape_flag 設為 1,接著讀取下一個 byte,根據下一個 byte 選擇對應的 funciton 來接收 packet,如果第一次讀到的結果不是 header,則繼續讀取下一個 byte,直到為 header 為止。 escape_flag 是為了閃避檢查 header 的 if block ```c if (read_buffer[0] == DLE_VAL && escape_flag == 0) { escape_flag = 1; continue; } ``` ### 封包類型 1. ACK: Acknowledgement,它是一種正向反饋,接收方收到數據後回覆消息告知發送方。 2. NACK: Negative Acknowledgement,則是一種負向反饋,接收方只有在沒有收到數據的時候才通知發送方。 3. INFO: 回傳 command 資訊 :::info 下完 command 後正常會收到 ACK 和 INFO ::: ## 2. 發送端 發送端利用 `timer_create` system call 並設定參數為 SIGEV_THREAD,當 timer expire (即過了一個 timer interval),kernel 會(在此 process 內)以 sigev_notification_attributes 為 thread attributes create 一個 thread, thread task 為 sigev_notify_function,並傳入 sigev_value 作為參數。 timer interval 由 settimer 來設定,這邊設定為 1 秒。 由 timer_create 建立的 thread,其 sigev_notify_function 都會被設為 `timer_event_handler`,這個函式處理所有的 timer event,這邊用到處理 `TIMER_EVENT_TRAFFIC_SIGNAL_COMMAND_BUF_POLLING` 的部份 ```c create_timer(&traffic_signal_status_report_timer_id, &traffic_signal_status_report_timer_num, timer_event_handler); set_timer(traffic_signal_status_report_timer_id, 1, 0, 1, 0); ``` ## Server `ae_create_time_event`: 將新建立的 sockfd 加入 epoll 中 ### TCP Server 為 TCP 連線的 client 建立新的 socket,接著將新建立的 socket 加入 epoll 中,client I/O 事件 ready 時,會將收到的 msg 放入 msg queue 中。 ### Smart AVI UDP Server 為 UDP 連線的 client 建立新的 socket, 接著將新建立的 socket 加入 epoll 中,client I/O 事件 ready 時,會將收到的 msg 放入 msg queue 中。 ### UDP Server 為 UDP 連線的 client 建立新的 socket, 接著將新建立的 socket 加入 epoll 中,client I/O 事件 ready 時,會將收到的 msg 放入 msg queue 中。 如果 `Is_Heartbeat` 為 1 時,會建立 OBU client 來與 RSU 溝通。 ### Dispatcher thread 透過 msg 的 device_id 分辨 msg 是來自 cloud 或 DSRC 或 SmartAVI,接著對應不同的 device 做不同的處理,相關處理在 com_packet_processing.c 中。