remove hard coded path into CMake files
[profile/ivi/ico-vic-amb-plugin.git] / src / mwinterface.cc
1 /**
2  * Copyright (C) 2012  TOYOTA MOTOR CORPORATION.
3  * 
4  * This library is free software; you can redistribute it and/or
5  * modify it under the terms of the GNU Lesser General Public
6  * License as published by the Free Software Foundation; either
7  * version 2.1 of the License, or (at your option) any later version.
8  * 
9  * This library is distributed in the hope that it will be useful,
10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
12  * Lesser General Public License for more details.
13  * 
14  * You should have received a copy of the GNU Lesser General Public
15  * License along with this library; if not, write to the Free Software
16  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
17  * 
18  */
19 #include <string.h>
20
21 #include <algorithm>
22 #include <iostream>
23
24 #include "debugout.h"
25
26 #include "mwinterface.h"
27 #include "controlwebsocket.h"
28 #include "viccommunicator.h"
29
30 using ::std::string;
31
32 MWNotifyInfo::MWNotifyInfo()
33 {
34     memset(nochangemask, 0, sizeof(nochangemask));
35     mutex = PTHREAD_MUTEX_INITIALIZER;
36 }
37
38 MWNotifyInfo::~MWNotifyInfo()
39 {
40     for (auto itr = notifyMap.begin(); itr != notifyMap.end(); itr++) {
41         (*itr).second.clear();
42     }
43     notifyMap.clear();
44 }
45
46 bool
47 MWNotifyInfo::insert(std::string name, int interval, int sense, char *mask)
48 {
49     if (sense == 0xff) {
50         eraseAllMask(name);
51     }
52     pthread_mutex_lock(&mutex);
53     if (notifyMap.find(name) == notifyMap.end()) {
54         for (auto itr = notifyMap[name].begin(); itr != notifyMap[name].end();
55              itr++) {
56             if (memcpy((*itr).mask, mask, STATUSSIZE) == 0) {
57                 (*itr).interval = interval;
58                 pthread_mutex_unlock(&mutex);
59                 return true;
60             }
61         }
62     }
63     pthread_mutex_unlock(&mutex);
64     NotifyOpt opt;
65     opt.interval = interval;
66     memcpy(opt.mask, mask, STATUSSIZE);
67     opt.lastChanged.tv_sec = 0;
68     opt.lastChanged.tv_usec = 0;
69     pthread_mutex_lock(&mutex);
70     notifyMap[name].push_back(opt);
71     pthread_mutex_unlock(&mutex);
72     return true;
73 }
74
75 bool
76 MWNotifyInfo::erase(std::string name, char *mask)
77 {
78     pthread_mutex_lock(&mutex);
79     if (notifyMap.find(name) == notifyMap.end()) {
80         pthread_mutex_unlock(&mutex);
81         return false;
82     }
83     for (auto itr = notifyMap[name].begin(); itr != notifyMap[name].end();
84          itr++) {
85         if (memcpy((*itr).mask, mask, STATUSSIZE) == 0) {
86             itr = notifyMap[name].erase(itr);
87             pthread_mutex_unlock(&mutex);
88             return true;
89         }
90     }
91     pthread_mutex_unlock(&mutex);
92     return false;
93 }
94
95 bool
96 MWNotifyInfo::eraseAllMask(std::string name)
97 {
98     pthread_mutex_lock(&mutex);
99     if (notifyMap.find(name) == notifyMap.end()) {
100         pthread_mutex_unlock(&mutex);
101         return false;
102     }
103     notifyMap[name].clear();
104     notifyMap.erase(name);
105     pthread_mutex_unlock(&mutex);
106     return true;
107 }
108
109 bool
110 MWNotifyInfo::checkNotify(std::string name, char *olddata, char *newdata,
111                           timeval newtime)
112 {
113     DebugOut(10) << "MWNotiryInfo checkNotify(" << name << ")" << std::endl;
114     pthread_mutex_lock(&mutex);
115     if (notifyMap.find(name) == notifyMap.end()) {
116         pthread_mutex_unlock(&mutex);
117         return false;
118     }
119     pthread_mutex_unlock(&mutex);
120     DebugOut(10) << "MWNotiryInfo checkStatus(" << name << ")" << std::endl;
121     char checkDiff[STATUSSIZE] = {};
122     for (int i = 0; i < STATUSSIZE; i++) {
123         checkDiff[i] = (*(olddata + i)) ^ (*(newdata + i));
124     }
125     DebugOut(10) << "MWNotiryInfo Update checkDiff" << std::endl;
126     pthread_mutex_lock(&mutex);
127     for (auto itr = notifyMap[name].begin(); itr != notifyMap[name].end();
128          itr++) {
129         for (int i = 0; i < STATUSSIZE; i++) {
130             DebugOut(10) << "checkDiff[" << i << "] = " << checkDiff[i]
131                        << ", (*itr).mask[i] = " << (*itr).mask[i]
132                        << " , checkDiff[i] & (*itr).mask[i] = "
133                        << (int)(checkDiff[i] & (*itr).mask[i]) << std::endl;
134             if ((checkDiff[i] & (*itr).mask[i]) != 0x00) {
135                 pthread_mutex_unlock(&mutex);
136                 return true;
137                 /* ToDo */
138                 /* Check Interval */
139             }
140         }
141     }
142     pthread_mutex_unlock(&mutex);
143     return false;
144 }
145
146 MWIF::MWIF()
147 {
148     for (int i = 0; i < SERVERNUM; i++) {
149         websocketserver[i] = NULL;
150     }
151     mutex_socketmap = PTHREAD_MUTEX_INITIALIZER;
152 }
153
154 MWIF::~MWIF()
155 {
156     vehicleinfoArray.clear();
157     for (int i = 0; i < SERVERNUM; i++) {
158         if (websocketserver[i] != NULL) {
159             delete websocketserver[i];
160         }
161     }
162     websocketservermap.clear();
163     mwnotifyinfomap.clear();
164     pthread_mutex_destroy(&mutex_socketmap);
165 }
166
167 bool
168 MWIF::initialize(VICCommunicator *com, AMBConfig *conf)
169 {
170     communicator = com;
171
172     vector<VehicleInfoDefine> table;
173     table = conf->getVehicleInfoConfig();
174     for (auto itr = table.begin(), itr_end = table.end(); itr != itr_end; itr++) {
175         MWVehicleInfo vi;
176         vi.name = string((*itr).KeyEventType);
177         memset(&vi.status, 0, STATUSSIZE);
178         vi.statussize = 0;
179         for (auto itr2 = (*itr).status.begin(); itr2 != (*itr).status.end();
180              itr2++) {
181             vi.statussize += (*itr2).typesize;
182             vi.delimeterposition.push_back((*itr2).typesize);
183         }
184         vehicleinfoArray.push_back(vi);
185         DebugOut(10) << "MWIF initialize mwvehicleinfo name = " << vi.name
186                    << std::endl;
187     }
188     DebugOut(1) << "INFO CHG_VIC_INF The number of VIC vehicle info is " << vehicleinfoArray.size() << ".\n";
189     PortInfo portinfo = conf->getPort();
190     DebugOut(1) << "INFO CHG_VIC_INF Portinfo list is (" << portinfo.standard.dataPort
191                 << "," << portinfo.standard.controlPort << ","
192                 << portinfo.custom.dataPort << "," << portinfo.custom.controlPort
193                 << ")\n";
194     createThread(&portinfo);
195     return true;
196 }
197
198 void
199 MWIF::send(MWVehicleInfo *vehicleinfo)
200 {
201     DebugOut(10) << "MWIF " << "send data is " << vehicleinfo->name << "("
202                  << vehicleinfo->status[0] << ")" << std::endl;
203     if (vehicleinfo == NULL) {
204         return;
205     }
206
207     MWVehicleInfo *curvehicleinfo = find(vehicleinfo->name);
208     if (curvehicleinfo != NULL) {
209         vehicleinfo->statussize = curvehicleinfo->statussize;
210         vehicleinfo->delimeterposition = curvehicleinfo->delimeterposition;
211         DebugOut(10) << "MWIF send : mwnotifyinfomap.size() = "
212                 << mwnotifyinfomap.size() << "\n";
213         for (auto itr = mwnotifyinfomap.begin(); itr != mwnotifyinfomap.end();
214                 itr++) {
215             if ((*itr).second.checkNotify(vehicleinfo->name,
216                                           curvehicleinfo->status,
217                                           vehicleinfo->status,
218                                           vehicleinfo->recordtime)) {
219                 DebugOut(10) << "MWIF send Notify" << std::endl;
220                 sendMessage((*itr).first, SUPPORT, vehicleinfo);
221             }
222         }
223         memcpy(curvehicleinfo->status, vehicleinfo->status, STATUSSIZE);
224         curvehicleinfo->recordtime = vehicleinfo->recordtime;
225     }
226 }
227
228 void
229 MWIF::recvRawdata(int commid, char *keyeventtype, timeval recordtime,
230                   void *data, size_t len)
231 {
232     DebugOut(10) << "MWIF recvRawdata(" << commid << "," << keyeventtype << ")\n";
233     if (find(string(keyeventtype)) != NULL) {
234         if (websocketservermap.find(commid) == websocketservermap.end()) {
235             return;
236         }
237         websocketserver[static_cast<int>(websocketservermap[commid])]->receive(
238                 commid, keyeventtype, recordtime, data, len);
239     }
240     // Error Message
241     else {
242         DebugOut(10) << "MWIF recvRawdata " << "Error Data." << std::endl;
243         MWVehicleInfo errorvi;
244         errorvi.name = string(keyeventtype);
245         errorvi.recordtime = recordtime;
246         errorvi.statussize = len - StandardMessage::KEYEVENTTYPESIZE
247                 - sizeof(timeval) - sizeof(int);
248         memset(errorvi.status, 0, STATUSSIZE);
249         sendMessage(commid, UNKNOWN, &errorvi);
250     }
251 }
252
253 void
254 MWIF::recvMessage(MessageType type, int commid, char *keyeventtype,
255                   timeval recordtime, void *data, size_t len)
256 {
257     MWVehicleInfo *vi;
258     if ((vi = find(string(keyeventtype))) == NULL) {
259         DebugOut(10) << "MWIF recvMessage " << "Error Data." << std::endl;
260         MWVehicleInfo errorvi;
261         errorvi.name = string(keyeventtype);
262         errorvi.recordtime = recordtime;
263         errorvi.statussize = len - StandardMessage::KEYEVENTTYPESIZE
264                 - sizeof(timeval) - sizeof(int);
265         memset(errorvi.status, 0, STATUSSIZE);
266         sendMessage(commid, UNKNOWN, &errorvi);
267         return;
268     }
269
270     DebugOut(10) << "MWIF recvMessage(" << commid << ")\n";
271     switch (type) {
272     case MessageType::SET:
273     {
274         DebugOut(8) << "MWIF recvMessage(" << commid << ",SET) " << keyeventtype
275                    << "\n";
276         DataOpt *opt = reinterpret_cast<DataOpt*>(data);
277         procSetMessage(commid, vi, keyeventtype, recordtime, opt, len);
278         break;
279     }
280     case MessageType::GET:
281     {
282         DebugOut(8) << "MWIF recvMessage(" << commid << ",GET) " << keyeventtype
283                    << "\n";
284         EventOpt *opt = reinterpret_cast<EventOpt*>(data);
285         procGetMessage(commid, keyeventtype, recordtime, opt, len);
286         break;
287     }
288     case MessageType::CALLBACK:
289     {
290         DebugOut(8) << "MWIF recvMessage(" << commid << ",CALLBACK) "
291                    << keyeventtype << "\n";
292         EventOpt *opt = reinterpret_cast<EventOpt*>(data);
293         procCallbackMessage(commid, keyeventtype, recordtime, opt, len);
294         break;
295     }
296     default:
297     {
298         break;
299     }
300     }
301 }
302
303 void
304 MWIF::registDestination(ControlWebsocket::ServerProtocol type, int commid)
305 {
306     DebugOut(10) << "MWIF type = " << type << std::endl;
307     pthread_mutex_lock(&mutex_socketmap);
308     if (websocketserver[type]->registSocket(commid)) {
309         DebugOut(10) << "MWIF registDestination insert(" << commid << "," << type
310                    << ")\n";
311         websocketservermap.insert(make_pair(commid, type));
312     }
313     pthread_mutex_unlock(&mutex_socketmap);
314 }
315
316 void
317 MWIF::unregistDestination(ControlWebsocket::ServerProtocol type, int commid)
318 {
319     pthread_mutex_lock(&mutex_socketmap);
320     if (websocketservermap.find(commid) != websocketservermap.end()) {
321         if (websocketserver[type]->unregistSocket(commid)) {
322             DebugOut(10) << "MWIF unregistDestination erase(" << commid << ","
323                        << type << ")\n";
324             websocketservermap.erase(commid);
325         }
326     }
327     pthread_mutex_unlock(&mutex_socketmap);
328 }
329
330 void
331 MWIF::sendMessage(int commid, CommonStatus status, MWVehicleInfo *vehicleinfo)
332 {
333     DataOpt opt;
334     opt.common_status = status;
335     memcpy(opt.status, vehicleinfo->status, STATUSSIZE);
336     size_t len = StandardMessage::KEYEVENTTYPESIZE + sizeof(timeval)
337             + sizeof(int) + vehicleinfo->statussize;
338     DebugOut(10) << "MWIF sendMessage vehicleinfo->statussize = "
339                  << vehicleinfo->statussize << ", len = " << len << std::endl;
340     if (websocketservermap.find(commid) == websocketservermap.end()) {
341         return;
342     }
343     DebugOut(10) << "MWIF sendMessage controlwebsocket->send(" << commid << ","
344                << vehicleinfo->name << "),len = " << len << std::endl;
345     websocketserver[websocketservermap[commid]]->send(
346             commid, const_cast<char*>(vehicleinfo->name.c_str()),
347             vehicleinfo->recordtime, (void *)&opt, len);
348 }
349
350 void
351 MWIF::createThread(PortInfo *portinfo)
352 {
353     for (int i = 0; i < SERVERNUM; i++) {
354         websocketserver[i] = new ControlWebsocket();
355     }
356     websocketserver[ControlWebsocket::DATA_STANDARD]->initialize(
357             portinfo->standard.dataPort, ControlWebsocket::DATA_STANDARD, this);
358     websocketserver[ControlWebsocket::CONTROL_STANDARD]->initialize(
359             portinfo->standard.controlPort, ControlWebsocket::CONTROL_STANDARD,
360             this);
361     websocketserver[ControlWebsocket::DATA_CUSTOM]->initialize(
362             portinfo->custom.dataPort, ControlWebsocket::DATA_CUSTOM, this);
363     websocketserver[ControlWebsocket::CONTROL_CUSTOM]->initialize(
364             portinfo->custom.controlPort, ControlWebsocket::CONTROL_CUSTOM,
365             this);
366 }
367
368 MWVehicleInfo *
369 MWIF::find(string name)
370 {
371     MWVehicleInfo vi;
372     vi.name = name;
373     auto itr = std::find(vehicleinfoArray.begin(), vehicleinfoArray.end(), vi);
374     if (itr == vehicleinfoArray.end()) {
375         DebugOut(10) << "MWIF find can't find property = " << name << std::endl;
376         return NULL;
377     }
378     else {
379         return &(*itr);
380     }
381 }
382
383 void
384 MWIF::procSetMessage(int commid, MWVehicleInfo *vi, char *keyeventtype, timeval recordtime,
385                      DataOpt *data, size_t len)
386 {
387     MWVehicleInfo updatevehicleinfo;
388     updatevehicleinfo.name = vi->name;
389     updatevehicleinfo.recordtime = recordtime;
390     updatevehicleinfo.statussize = vi->statussize;
391
392     memcpy(updatevehicleinfo.status, data->status, getStatussize(len));
393     // Update AMB Data
394     communicator->setAMBVehicleInfo(&updatevehicleinfo);
395     // Update MW Data
396     vi->recordtime = recordtime;
397     memcpy(vi->status, updatevehicleinfo.status, getStatussize(len));
398 }
399
400 void
401 MWIF::procGetMessage(int commid, char *keyeventtype, timeval recordtime,
402                      EventOpt *data, size_t len)
403 {
404     MWVehicleInfo vehicleinfo;
405     vehicleinfo.name = string(keyeventtype);
406     vehicleinfo.statussize = find(vehicleinfo.name)->statussize;
407     communicator->getAMBVehicleInfo(&vehicleinfo);
408     sendMessage(commid, SUPPORT, &vehicleinfo);
409 }
410
411 void
412 MWIF::procCallbackMessage(int commid, char *keyeventtype, timeval recordtime,
413                           EventOpt *data, size_t len)
414 {
415     MWVehicleInfo *vehicleinfo = find(string(keyeventtype));
416     //Set Mask bit.
417     int index = 0;
418     char mask[STATUSSIZE];
419     memset(mask, 0, STATUSSIZE);
420     for (int i = 0; i < static_cast<int>(vehicleinfo->delimeterposition.size());
421          i++) {
422         char flg = 0x00;
423         if (data->sense == 0xff || (i + 1) == data->sense) {
424             flg = 0xff;
425         }
426         for (int j = 0; j < vehicleinfo->delimeterposition[i]; j++) {
427             mask[index++] = flg;
428         }
429     }
430
431     MWNotifyInfo notifyinfo;
432     if (mwnotifyinfomap.find(commid) == mwnotifyinfomap.end()) {
433         mwnotifyinfomap.insert(make_pair(commid, notifyinfo));
434     }
435     else {
436         notifyinfo = mwnotifyinfomap[commid];
437     }
438     if (notifyinfo.insert(string(keyeventtype), data->common, data->sense,
439                           mask)) {
440         sendMessage(commid, SUPPORT, vehicleinfo);
441     }
442     else {
443         sendMessage(commid, NOTSUPPORT, vehicleinfo);
444     }
445     mwnotifyinfomap[commid] = notifyinfo;
446 }