-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathtransport.c
224 lines (195 loc) · 6.01 KB
/
transport.c
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
#include "transport.h"
static const char* TAG_transport = "transport";
/**
* @brief Initialises message queue
*
* @return esp_err_t ESP_OK - if queue init sucessfully, ESP_FAIL - if queue init failed
**/
esp_err_t init_queue(void)
{
pid_struct_queue = xQueueCreate(1000, sizeof(struct pid_terms));
pid_const_read_write_mutex = xSemaphoreCreateMutex();
if (pid_struct_queue == NULL)
{
logE(TAG_transport, "%s", "Queue creation failed");
return ESP_FAIL;
}
else
{
logI(TAG_transport, "%s", "Queue created");
return ESP_OK;
}
if (pid_const_read_write_mutex == NULL)
{
logE(TAG_transport, "%s", "Read/Write Mutex creation failed");
return ESP_FAIL;
}
else
{
logI(TAG_transport, "%s", "Read/Write Mutex created");
return ESP_OK;
}
}
/**
* @brief Initialises transport, i.e. connect to wifi
**/
void init_transport(void)
{
ESP_ERROR_CHECK(nvs_flash_init());
ESP_ERROR_CHECK(esp_netif_init());
ESP_ERROR_CHECK(esp_event_loop_create_default());
ESP_ERROR_CHECK(example_connect());
}
/**
* @brief Sends pid_data struct to message queue
*
* @param pid_data pid_terms struct contains pid values
* @return esp_err_t ESP_OK - if queue init sucessfully, ESP_FAIL - if queue init failed
**/
esp_err_t send_to_queue(struct pid_terms pid_data)
{
BaseType_t qerror = xQueueSendToBack(pid_struct_queue, (void*)&pid_data, (TickType_t) 0/portTICK_PERIOD_MS);
if(qerror == pdPASS)
{
logD(TAG_transport, "%s", "Data sent to Queue");
return ESP_OK;
}
else if(qerror == errQUEUE_FULL)
{
logE(TAG_transport, "%s", "Data not sent to Queue, Queue full");
return ESP_FAIL;
}
else
{
logE(TAG_transport, "%s", "Unknown error");
return ESP_FAIL;
}
}
/**
* @brief Receive data from queue
*
* @return struct data_recv - struct containing pid_terms and esp_err_t as members. pid_terms contains pid terms
**/
struct data_recv receive_from_queue(void)
{
struct pid_terms data;
struct data_recv ret_data;
BaseType_t qerror = xQueueReceive(pid_struct_queue, &(data), (TickType_t) 10000/portTICK_PERIOD_MS);
configASSERT(qerror);
if(qerror == pdPASS)
{
logD(TAG_transport, "%s", "Data received from Queue");
ret_data.data = data;
ret_data.err = ESP_OK;
}
else if(qerror == pdFALSE)
{
logW(TAG_transport, "%s", "Data not received from Queue");
ret_data.err = ESP_FAIL;
}
else
{
logE(TAG_transport, "%s", "Unknown error");
ret_data.err = ESP_FAIL;
}
return ret_data;
}
/**
* @brief Handles UDP client, which sends pid_terms received through message queue
**/
void pid_transport()
{
struct network_data* handle = malloc(sizeof(struct network_data));
network_manager(handle);
while (true)
{
struct data_recv pid = receive_from_queue();
char* message = NULL;
if (pid.err == ESP_OK)
{
message = create_pid_data_to_json(pid.data.current, pid.data.error, pid.data.P, pid.data.I, pid.data.D);
int len = send_data(handle, message);
logD(TAG_transport, "%d %s", len, "bytes of data sent");
}
else if(pid.err == ESP_FAIL)
{
message = "no data received from Queue";
int len = send_data(handle, message);
logW(TAG_transport, "%d %s", len, "no data received from Queue");
}
else
{
message = "Unknown error";
int len = send_data(handle, message);
logE(TAG_transport, "%d %s", len, "Unknown error");
}
}
close_network_manager(handle);
}
/**
* @brief Handles TCP client, which receives pid_constants from server, and parses the data and stores it in a global struct pid_const_data
**/
void pid_const_transport()
{
struct tcp_network_data* handle = malloc(sizeof(struct tcp_network_data));
tcp_network_manager(handle);
char* message = NULL;
int message_len = 0;
char message_len_buffer[15];
while (true)
{
message = tcp_recieve_data(handle);
if (message != NULL)
{
message_len = strlen(message);
if (xSemaphoreTake(pid_const_read_write_mutex, (TickType_t) 100) == pdTRUE && message_len > 0)
{
logI(TAG_transport, "%s", "pid_const_data ownership taken for writing");
pid_const_data = read_pid_data_from_json(message);
xSemaphoreGive(pid_const_read_write_mutex);
logI(TAG_transport, "%s", "pid_const_data ownership released");
}
else
{
xSemaphoreGive(pid_const_read_write_mutex);
logW(TAG_transport, "%s", "pid_const_data already locked, couldn't take ownership or tcp recv message is corrupted");
}
sprintf(message_len_buffer, "%d", message_len);
}
else
{
logE(TAG_transport, "%s", "tcp receive failed");
vTaskDelete(pid_const_transport_handle);
}
int err = tcp_send_data(handle, message_len_buffer);
if (err > 0)
{
strcpy(message_len_buffer, "");
}
else
{
logE(TAG_transport, "%s", "tcp send failed");
vTaskDelete(pid_const_transport_handle);
}
}
}
/**
* @brief Returns pid_const_data struct. Checks if the resource is blocked by mutex for writing or it is accessible, waits till pid_const_data is accessible and returns it
*
* @return struct pid_const - Returns pid_const_data, can be used to access Kp, Ki, Kd and current values
**/
struct pid_const pid_const_read()
{
while(true)
{
if(xSemaphoreGetMutexHolder(pid_const_read_write_mutex) == NULL)
{
return pid_const_data;
break;
}
else
{
logW(TAG_transport, "%s", "pid_const_data is locked for writing");
}
}
}