-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathDataReaderServer.cpp
More file actions
240 lines (211 loc) · 8.09 KB
/
Copy pathDataReaderServer.cpp
File metadata and controls
240 lines (211 loc) · 8.09 KB
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
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
#include "DataReaderServer.h"
/**
* This method is responsible for setting the port and speed of information reading (hertz).
* Also a pointer to the symbol table for both binded and unbinded variables.
* @param newPort number of port for the connection.
* @param newHerz number of times to read in second.
* @param symbolTablePtr pointer to symbol table.
*/
void DataReaderServer::set(string newPort, string newHerz, SymbolTable *symbolTablePtr) {
port = stoi(newPort);
herz = stoi(newHerz);
this->symbolMap = symbolTablePtr;
}
void DataReaderServer::attachThread(pthread_t newThread){
myThread = newThread;
}
/**
* This method checks if a given variable name is binded.
* @param variableName variable name for the check.
* @return bool true if in map, else false.
*/
bool DataReaderServer::isInBindMap(string subject) {
if (bindTable.find(subject) == bindTable.end()) {
return false;
}
return true;
}
/**
* This method sets a symbol(variable) and the fitting value in the symbol map.
* @param symbol variable name.
* @param value value of the variable.
*/
void DataReaderServer::setSymbol(string symbol, double value) {
this->symbolMap->set(symbol, value);
}
/**
* This method return the bind address of a given variable.
* @param varName name of variable.
* @return bind address.
*/
string DataReaderServer::getBindAddress(string varName) {
return bindTable.at(varName);
}
/**
* This method sets a variable name and the fitting address in the bind map.
* @param varName variable name.
* @param address address of the binded value.
*/
void DataReaderServer::setBind(string var, string address) {
this->bindTable[var] = address;
}
/**
* This method sets the socket for the connection.
* @param newSock given socket.
*/
void DataReaderServer::setSock(int newSock) {
sockfd = newSock;
}
/**
* This method returns the socket for the connection.
* @return sockfd socket of the connection.
*/
int DataReaderServer::getSock() {
return sockfd;
}
/**
* This method updates the wanted samples (from the xml file) and updates
* them by the samples given from the client.
* @param sample sample for the operation.
*/
void DataReaderServer::takeSamplesToTable(string parseMe) {
string delim = ",";
vector<string> sol;
//First step is to split the information
int start = 0;
int end = parseMe.find(delim);
while (end != std::string::npos) {
sol.push_back((parseMe.substr(start, end - start)));
start = end + delim.length();
end = parseMe.find(delim, start);
}
sol.push_back((parseMe.substr(start, end - start)));
//Second step is to put that to the map//
strobes["\"/instrumentation/airspeed-indicator/indicated-speed-kt\""] = stod(sol.at(0));
strobes["\"/instrumentation/altimeter/indicated-altitude-ft\""] = stod(sol.at(1));
strobes["\"/instrumentation/altimeter/pressure-alt-ft\""] = stod(sol.at(2));
strobes["\"/instrumentation/attitude-indicator/indicated-pitch-deg\""] = stod(sol.at(3));
strobes["\"/instrumentation/attitude-indicator/indicated-roll-deg\""] = stod(sol.at(4));
strobes["\"/instrumentation/attitude-indicator/internal-pitch-deg\""] = stod(sol.at(5));
strobes["\"/instrumentation/attitude-indicator/internal-roll-deg\""] = stod(sol.at(6));
strobes["\"/instrumentation/encoder/indicated-altitude-ft\""] = stod(sol.at(7));
strobes["\"/instrumentation/encoder/pressure-alt-ft\""] = stod(sol.at(8));
strobes["\"/instrumentation/gps/indicated-altitude-ft\""] = stod(sol.at(9));
strobes["\"/instrumentation/gps/indicated-ground-speed-kt\""] = stod(sol.at(10));
strobes["\"/instrumentation/gps/indicated-vertical-speed\""] = stod(sol.at(11));
strobes["\"/instrumentation/heading-indicator/indicated-heading-deg\""] = stod(sol.at(12));
strobes["\"/instrumentation/heading-indicator/offset-deg\""] = stod(sol.at(13));
strobes["\"/instrumentation/slip-skid-ball/indicated-slip-skid\""] = stod(sol.at(14));
strobes["\"/instrumentation/turn-indicator/indicated-turn-rate\""] = stod(sol.at(15));
strobes["\"/instrumentation/vertical-speed-indicator/indicated-speed-fpm\""] = stod(sol.at(16));
strobes["\"/controls/flight/aileron\""] = stod(sol.at(17));
strobes["\"/controls/flight/elevator\""] = stod(sol.at(18));
strobes["\"/controls/flight/rudder\""] = stod(sol.at(19));
strobes["\"/controls/flight/flaps\""] = stod(sol.at(20));
strobes["\"/controls/engines/engine/throttle\""] = stod(sol.at(21));
strobes["\"/engines/engine/rpm\""] = stod(sol.at(22));
}
/**
* This method updates the symbol table according to the strobes taken from the client.
*/
void DataReaderServer::updateBindedValues() {
for (std::unordered_map<string, double>::iterator it = strobes.begin(); it != strobes.end(); ++it) {
// if the address of the binded variable was found in strobes, symbol table is updated:
this->setSymbol(it->first, it->second);
}
}
/**
* This method opens the socket for the connection of the client.
* Also creates pthread which then runs the server.
*/
void *DataReaderServer::open() {
int clilen;
struct sockaddr_in serv_addr, cli_addr;
/* First call to socket() function */
setSock(socket(AF_INET, SOCK_STREAM, 0));
if (getSock() < 0) {
perror("ERROR opening socket");
exit(1);
}
/* Initialize socket structure */
bzero((char *) &serv_addr, sizeof(serv_addr));
serv_addr.sin_family = AF_INET;
serv_addr.sin_addr.s_addr = INADDR_ANY;
serv_addr.sin_port = htons(port);
/* Now bind the host address using bind() call.*/
if (bind(getSock(), (struct sockaddr *) &serv_addr, sizeof(serv_addr)) < 0) {
perror("ERROR on binding");
exit(1);
}
/* Now start listening for the clients, here process will
* go in sleep mode and will wait for the incoming connection
*/
listen(getSock(), 5);
clilen = sizeof(cli_addr);
/* Accept actual connection from the client */
this->newSockFd = accept(getSock(), (struct sockaddr *) &cli_addr, (socklen_t *) &clilen);
if (this->newSockFd < 0) {
perror("ERROR on accept");
exit(1);
}
// If connection is established then start communicating on a pthread
pthread_create(&this->myThread, nullptr, runServer, this);
attachThread(this->myThread);
}
/**
* This method is used by the pthread to run the opened server.
* @param a void pointer.
* @return void pointer.
*/
void *DataReaderServer::runServer(void *a) {
return ((DataReaderServer *) a)->runServerFunc(a);
}
/**
* This method runs the server: reads information from client from
* the socket, and updates samples map and symbol map accordingly.
* @param a void pointer.
* @return void pointer.
*/
void *DataReaderServer::runServerFunc(void *a) {
int index = 0;
int n = 0;
char buffer[256];
bzero(buffer, 256);
string remainder, backRemainder, information;
bool isDataEnd = false;
while (true) { //SCAT here
n = read(this->newSockFd, buffer, 255);
if (n < 0) {
this->closeServer();
pthread_exit(a);
}
information = string(buffer);
if (backRemainder != "") {
remainder = backRemainder;
backRemainder = "";
}
index = information.find("\n");
// if the line terminator was not found, append all of the information.
if (index == std::string::npos) {
remainder += information;
} else {
// appends the remainder of the information until the next line.
remainder += information.substr(0, index);
backRemainder = information.substr(index + 1, information.length());
isDataEnd = true;
}
if (isDataEnd) {
takeSamplesToTable(remainder);
updateBindedValues();
remainder = "";
isDataEnd = false;
}
}
}
/**
* This method closes the reader server.
*/
void DataReaderServer::closeServer() {
pthread_join(myThread, nullptr);
close(sockfd); //SCAT no close but hightly needed!
}