---
# System prepended metadata

title: RSU architecture
tags: [asrlab]

---

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