c1f7335af508aab41101381dac13c8185ebba24f
[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 <iostream>
22
23 #include "debugout.h"
24
25 #include "mwinterface.h"
26 #include "controlwebsocket.h"
27 #include "viccommunicator.h"
28
29 using ::std::string;
30
31 MWNotifyInfo::MWNotifyInfo()
32 {
33     memset(nochangemask, 0, sizeof(nochangemask));
34     mutex = PTHREAD_MUTEX_INITIALIZER;
35 }
36
37 MWNotifyInfo::~MWNotifyInfo()
38 {
39     for (auto itr = notifyMap.begin(); itr != notifyMap.end(); itr++) {
40         (*itr).second.clear();
41     }
42     notifyMap.clear();
43 }
44
45 bool
46 MWNotifyInfo::insert(std::string name, int interval, int sense, char *mask)
47 {
48     if (sense == 0xff) {
49         eraseAllMask(name);
50     }
51     pthread_mutex_lock(&mutex);
52     if (notifyMap.find(name) == notifyMap.end()) {
53         for (auto itr = notifyMap[name].begin(); itr != notifyMap[name].end();
54              itr++) {
55             if (memcpy((*itr).mask, mask, STATUSSIZE) == 0) {
56                 (*itr).interval = interval;
57                 pthread_mutex_unlock(&mutex);
58                 return true;
59             }
60         }
61     }
62     pthread_mutex_unlock(&mutex);
63     NotifyOpt opt;
64     opt.interval = interval;
65     memcpy(opt.mask, mask, STATUSSIZE);
66     opt.lastChanged.tv_sec = 0;
67     opt.lastChanged.tv_usec = 0;
68     pthread_mutex_lock(&mutex);
69     notifyMap[name].push_back(opt);
70     pthread_mutex_unlock(&mutex);
71     return true;
72 }
73
74 bool
75 MWNotifyInfo::erase(std::string name, char *mask)
76 {
77     pthread_mutex_lock(&mutex);
78     if (notifyMap.find(name) == notifyMap.end()) {
79         pthread_mutex_unlock(&mutex);
80         return false;
81     }
82     for (auto itr = notifyMap[name].begin(); itr != notifyMap[name].end();
83          itr++) {
84         if (memcpy((*itr).mask, mask, STATUSSIZE) == 0) {
85             itr = notifyMap[name].erase(itr);
86             pthread_mutex_unlock(&mutex);
87             return true;
88         }
89     }
90     pthread_mutex_unlock(&mutex);
91     return false;
92 }
93
94 bool
95 MWNotifyInfo::eraseAllMask(std::string name)
96 {
97     pthread_mutex_lock(&mutex);
98     if (notifyMap.find(name) == notifyMap.end()) {
99         pthread_mutex_unlock(&mutex);
100         return false;
101     }
102     notifyMap[name].clear();
103     notifyMap.erase(name);
104     pthread_mutex_unlock(&mutex);
105     return true;
106 }
107
108 bool
109 MWNotifyInfo::checkNotify(std::string name, char *olddata, char *newdata,
110                           timeval newtime)
111 {
112     DebugOut() << "MWNotiryInfo checkNotify(" << name << ")" << std::endl;
113     pthread_mutex_lock(&mutex);
114     if (notifyMap.find(name) == notifyMap.end()) {
115         pthread_mutex_unlock(&mutex);
116         return false;
117     }
118     pthread_mutex_unlock(&mutex);
119     DebugOut(10) << "MWNotiryInfo checkStatus(" << name << ")" << std::endl;
120     char checkDiff[STATUSSIZE] = {};
121     for (int i = 0; i < STATUSSIZE; i++) {
122         checkDiff[i] = (*(olddata + i)) ^ (*(newdata + i));
123     }
124     DebugOut(10) << "MWNotiryInfo Update checkDiff" << std::endl;
125     pthread_mutex_lock(&mutex);
126     for (auto itr = notifyMap[name].begin(); itr != notifyMap[name].end();
127          itr++) {
128         for (int i = 0; i < STATUSSIZE; i++) {
129             DebugOut() << "checkDiff[" << i << "] = " << checkDiff[i]
130                        << ", (*itr).mask[i] = " << (*itr).mask[i]
131                        << " , checkDiff[i] & (*itr).mask[i] = "
132                        << (int)(checkDiff[i] & (*itr).mask[i]) << std::endl;
133             if ((checkDiff[i] & (*itr).mask[i]) != 0x00) {
134                 pthread_mutex_unlock(&mutex);
135                 return true;
136                 /* ToDo */
137                 /* Check Interval */
138             }
139         }
140     }
141     pthread_mutex_unlock(&mutex);
142     return false;
143 }
144
145 MWIF::MWIF()
146 {
147     for (int i = 0; i < SERVERNUM; i++) {
148         websocketserver[i] = NULL;
149     }
150 }
151
152 MWIF::~MWIF()
153 {
154     vehicleinfoArray.clear();
155     for (int i = 0; i < SERVERNUM; i++) {
156         if (websocketserver[i] != NULL) {
157             delete websocketserver[i];
158         }
159     }
160     websocketservermap.clear();
161     mwnotifyinfomap.clear();
162 }
163
164 bool
165 MWIF::initialize(VICCommunicator *com, AMBConfig *conf)
166 {
167     communicator = com;
168
169     vector<VehicleInfoDefine> table;
170     table = conf->getVehicleInfoConfig();
171     for (auto itr = table.begin(); itr != table.end(); itr++) {
172         MWVehicleInfo vi;
173         vi.name = string((*itr).KeyEventType);
174         memset(&vi.status, 0, STATUSSIZE);
175         vi.statussize = 0;
176         for (auto itr2 = (*itr).status.begin(); itr2 != (*itr).status.end();
177              itr2++) {
178             vi.statussize += (*itr2).typesize;
179             vi.delimeterposition.push_back((*itr2).typesize);
180         }
181         vehicleinfoArray.push_back(vi);
182         DebugOut() << "MWIF initialize mwvehicleinfo name = " << vi.name
183                    << std::endl;
184     }
185     PortInfo portinfo = conf->getPort();
186     DebugOut() << "MWIF initialize portinfo (" << portinfo.standard.dataPort
187                << "," << portinfo.standard.controlPort << ","
188                << portinfo.custom.dataPort << "," << portinfo.custom.controlPort
189                << ")\n";
190     createThread(&portinfo);
191     return true;
192 }
193
194 void
195 MWIF::send(MWVehicleInfo *vehicleinfo)
196 {
197     DebugOut(10) << "MWIF " << "send data is " << vehicleinfo->name << "("
198                  << vehicleinfo->status[0] << ")" << std::endl;
199     if (vehicleinfo == NULL) {
200         return;
201     }
202
203     MWVehicleInfo *curvehicleinfo = find(vehicleinfo->name);
204     if (curvehicleinfo != NULL) {
205         vehicleinfo->statussize = curvehicleinfo->statussize;
206         vehicleinfo->delimeterposition = curvehicleinfo->delimeterposition;
207         DebugOut(10) << "MWIF send : mwnotifyinfomap.size() = "
208                 << mwnotifyinfomap.size() << "\n";
209         for (auto itr = mwnotifyinfomap.begin(); itr != mwnotifyinfomap.end();
210                 itr++) {
211             if ((*itr).second.checkNotify(vehicleinfo->name,
212                                           curvehicleinfo->status,
213                                           vehicleinfo->status,
214                                           vehicleinfo->recordtime)) {
215                 DebugOut(10) << "MWIF send Notify" << std::endl;
216                 sendMessage((*itr).first, SUPPORT, vehicleinfo);
217             }
218         }
219         memcpy(curvehicleinfo->status, vehicleinfo->status, STATUSSIZE);
220         curvehicleinfo->recordtime = vehicleinfo->recordtime;
221     }
222 }
223
224 void
225 MWIF::recvRawdata(int commid, char *keyeventtype, timeval recordtime,
226                   void *data, size_t len)
227 {
228     DebugOut() << "MWIF recvRawdata(" << commid << "," << keyeventtype << ")\n";
229     if (find(string(keyeventtype)) != NULL) {
230         if (websocketservermap.find(commid) == websocketservermap.end()) {
231             return;
232         }
233         websocketserver[static_cast<int>(websocketservermap[commid])]->receive(
234                 commid, keyeventtype, recordtime, data, len);
235     }
236     // Error Message
237     else {
238         DebugOut() << "MWIF recvRawdata " << "Error Data." << std::endl;
239         MWVehicleInfo errorvi;
240         errorvi.name = string(keyeventtype);
241         errorvi.recordtime = recordtime;
242         errorvi.statussize = len - StandardMessage::KEYEVENTTYPESIZE
243                 - sizeof(timeval) - sizeof(int);
244         memset(errorvi.status, 0, STATUSSIZE);
245         sendMessage(commid, UNKNOWN, &errorvi);
246     }
247 }
248
249 void
250 MWIF::recvMessage(MessageType type, int commid, char *keyeventtype,
251                   timeval recordtime, void *data, size_t len)
252 {
253     DebugOut(10) << "MWIF recvMessage(" << commid << ")\n";
254     switch (type) {
255     case MessageType::SET:
256     {
257         DebugOut() << "MWIF recvMessage(" << commid << ",SET) " << keyeventtype
258                    << "\n";
259         DataOpt *opt = reinterpret_cast<DataOpt*>(data);
260         procSetMessage(commid, keyeventtype, recordtime, opt, len);
261         break;
262     }
263     case MessageType::GET:
264     {
265         DebugOut() << "MWIF recvMessage(" << commid << ",GET) " << keyeventtype
266                    << "\n";
267         EventOpt *opt = reinterpret_cast<EventOpt*>(data);
268         procGetMessage(commid, keyeventtype, recordtime, opt, len);
269         break;
270     }
271     case MessageType::CALLBACK:
272     {
273         DebugOut() << "MWIF recvMessage(" << commid << ",CALLBACK) "
274                    << keyeventtype << "\n";
275         EventOpt *opt = reinterpret_cast<EventOpt*>(data);
276         procCallbackMessage(commid, keyeventtype, recordtime, opt, len);
277         break;
278     }
279     default:
280     {
281         break;
282     }
283     }
284 }
285
286 void
287 MWIF::registDestination(ControlWebsocket::ServerProtocol type, int commid)
288 {
289     DebugOut() << "MWIF type = " << type << std::endl;
290     if (websocketserver[type]->registSocket(commid)) {
291         DebugOut() << "MWIF registDestination insert(" << commid << "," << type
292                    << ")\n";
293         websocketservermap.insert(make_pair(commid, type));
294     }
295 }
296
297 void
298 MWIF::unregistDestination(ControlWebsocket::ServerProtocol type, int commid)
299 {
300     if (websocketservermap.find(commid) != websocketservermap.end()) {
301         if (websocketserver[type]->unregistSocket(commid)) {
302             DebugOut() << "MWIF unregistDestination erase(" << commid << ","
303                        << type << ")\n";
304             websocketservermap.erase(commid);
305         }
306     }
307 }
308
309 void
310 MWIF::sendMessage(int commid, CommonStatus status, MWVehicleInfo *vehicleinfo)
311 {
312     DataOpt opt;
313     opt.common_status = status;
314     memcpy(opt.status, vehicleinfo->status, STATUSSIZE);
315     size_t len = StandardMessage::KEYEVENTTYPESIZE + sizeof(timeval)
316             + sizeof(int) + vehicleinfo->statussize;
317     DebugOut(10) << "MWIF sendMessage vehicleinfo->statussize = "
318                  << vehicleinfo->statussize << ", len = " << len << std::endl;
319     if (websocketservermap.find(commid) == websocketservermap.end()) {
320         return;
321     }
322     DebugOut() << "MWIF sendMessage controlwebsocket->send(" << commid << ","
323                << vehicleinfo->name << "),len = " << len << std::endl;
324     websocketserver[websocketservermap[commid]]->send(
325             commid, const_cast<char*>(vehicleinfo->name.c_str()),
326             vehicleinfo->recordtime, (void *)&opt, len);
327 }
328
329 void
330 MWIF::createThread(PortInfo *portinfo)
331 {
332     for (int i = 0; i < SERVERNUM; i++) {
333         websocketserver[i] = new ControlWebsocket();
334     }
335     websocketserver[ControlWebsocket::DATA_STANDARD]->initialize(
336             portinfo->standard.dataPort, ControlWebsocket::DATA_STANDARD, this);
337     websocketserver[ControlWebsocket::CONTROL_STANDARD]->initialize(
338             portinfo->standard.controlPort, ControlWebsocket::CONTROL_STANDARD,
339             this);
340     websocketserver[ControlWebsocket::DATA_CUSTOM]->initialize(
341             portinfo->custom.dataPort, ControlWebsocket::DATA_CUSTOM, this);
342     websocketserver[ControlWebsocket::CONTROL_CUSTOM]->initialize(
343             portinfo->custom.controlPort, ControlWebsocket::CONTROL_CUSTOM,
344             this);
345 }
346
347 MWVehicleInfo *
348 MWIF::find(string name)
349 {
350     for (auto itr = vehicleinfoArray.begin(); itr != vehicleinfoArray.end();
351             itr++) {
352         DebugOut(10) << "MWIF find" << (*itr).name << std::endl;
353         if ((*itr).name == name) {
354             return &(*itr);
355         }
356     }
357     DebugOut() << "MWIF find can't find property = " << name << std::endl;
358     return NULL;
359 }
360
361 void
362 MWIF::procSetMessage(int commid, char *keyeventtype, timeval recordtime,
363                      DataOpt *data, size_t len)
364 {
365     MWVehicleInfo *vehicleinfo = find(string(keyeventtype));
366     MWVehicleInfo updatevehicleinfo;
367     updatevehicleinfo.name = vehicleinfo->name;
368     updatevehicleinfo.recordtime = recordtime;
369     updatevehicleinfo.statussize = vehicleinfo->statussize;
370     memcpy(updatevehicleinfo.status, data->status, STATUSSIZE);
371     // Update AMB Data
372     communicator->setAMBVehicleInfo(&updatevehicleinfo);
373     // Update MW Data
374     vehicleinfo->recordtime = recordtime;
375     memcpy(vehicleinfo->status, updatevehicleinfo.status, STATUSSIZE);
376 }
377
378 void
379 MWIF::procGetMessage(int commid, char *keyeventtype, timeval recordtime,
380                      EventOpt *data, size_t len)
381 {
382     MWVehicleInfo vehicleinfo;
383     vehicleinfo.name = string(keyeventtype);
384     vehicleinfo.statussize = find(vehicleinfo.name)->statussize;
385     communicator->getAMBVehicleInfo(&vehicleinfo);
386     sendMessage(commid, SUPPORT, &vehicleinfo);
387 }
388
389 void
390 MWIF::procCallbackMessage(int commid, char *keyeventtype, timeval recordtime,
391                           EventOpt *data, size_t len)
392 {
393     MWVehicleInfo *vehicleinfo = find(string(keyeventtype));
394     //Set Mask bit.
395     int index = 0;
396     char mask[STATUSSIZE];
397     memset(mask, 0, STATUSSIZE);
398     for (int i = 0; i < static_cast<int>(vehicleinfo->delimeterposition.size());
399          i++) {
400         char flg = 0x00;
401         if (data->sense == 0xff || (i + 1) == data->sense) {
402             flg = 0xff;
403         }
404         for (int j = 0; j < vehicleinfo->delimeterposition[i]; j++) {
405             mask[index++] = flg;
406         }
407     }
408
409     MWNotifyInfo notifyinfo;
410     if (mwnotifyinfomap.find(commid) == mwnotifyinfomap.end()) {
411         mwnotifyinfomap.insert(make_pair(commid, notifyinfo));
412     }
413     else {
414         notifyinfo = mwnotifyinfomap[commid];
415     }
416     if (notifyinfo.insert(string(keyeventtype), data->common, data->sense,
417                           mask)) {
418         sendMessage(commid, SUPPORT, vehicleinfo);
419     }
420     else {
421         sendMessage(commid, NOTSUPPORT, vehicleinfo);
422     }
423     mwnotifyinfomap[commid] = notifyinfo;
424 }