---
tags: asrlab
---
# RSU architecture
## 架構圖
https://drive.google.com/file/d/1ApfR6PfXs5p9meRni39boEqW6jtZmvZP/view?usp=sharing

## 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 中。