e4d48641615895ed5514ee3e2e95c8e9e14244e6
[iot2.git] / iotjava / iotruntime / cpp / iotslave / IoTSlave.cpp
1 #include <iostream>
2 #include <fstream>
3
4 #include "IoTSlave.hpp"
5
6 IoTSlave::IoTSlave(string _serverAddress, int _serverPort, string _objectName) {
7
8         //isDriverObject = false;               // Default to false
9         serverAddress = _serverAddress;
10         serverPort = _serverPort;
11         objectName = _objectName;
12         socket = new TCPSocket(serverAddress, serverPort);
13         openFile(objectName);
14         writeToFile("IoTSlave object created! Connection established!");
15 }
16
17
18 IoTSlave::~IoTSlave() {
19
20         if (socket != NULL) {
21                 delete socket;
22                 socket = NULL;
23         }
24         /*if (objMainCls != NULL) {
25                 delete objMainCls;
26                 objMainCls = NULL;
27         }
28         if (objSkelCls != NULL) {
29                 delete objSkelCls;
30                 objSkelCls = NULL;
31         }*/
32         for (IoTSet<void*>* iotset : vecIoTSet) {
33                 delete iotset;
34                 iotset = NULL;
35         }
36         closeFile();
37 }
38
39
40 // Private helper functions
41 int* IoTSlave::byteToInt(int* result, char* bytes) {
42
43         int i = 0;
44         memcpy(&i, bytes, sizeof(int));
45         *result = be32toh(i);
46
47         return result;
48 }
49
50
51 char* IoTSlave::intToByteArray(int i, char* bytes) {
52
53         int iInvert = htobe32(i);
54         memcpy(bytes, &iInvert, sizeof(int));
55
56         return bytes;
57 }
58
59
60 void* IoTSlave::getObjectConverted(void* retObj, string object, string objectClass) {
61
62         // Returning new objects in heap - so we need to delete them afterwards
63         if (objectClass.compare(STRINGCLASS) == 0) {
64                 string* retStr = new string(object);
65                 retObj = retStr;
66         } else if (objectClass.compare(INTCLASS) == 0) {
67                 int* retInt = new int(atoi(object.c_str()));
68                 retObj = retInt;
69         } else  // return NULL if class is not identifiable
70                 return NULL;
71
72         return retObj;
73 }
74
75
76 // Factoring out iteration
77 char* IoTSlave::recvIter(char* recvBuffer, int recvLen) {
78
79     int bytesReceived = 0;              // Bytes read on each recv()
80     int totalBytesReceived = 0;         // Total bytes read
81
82         while (totalBytesReceived < recvLen) {
83                 // Receive up to the buffer size bytes from the sender
84                 if ((bytesReceived = (socket->recv(recvBuffer, RCVBUFSIZE))) <= 0) {
85                         string errMsg = "IoTSlave: Unable to read!";
86                         cerr << errMsg << endl;
87                         writeToFile(errMsg);
88                         exit(1);
89                 }
90                 totalBytesReceived += bytesReceived;     // Keep tally of total bytes
91         }
92
93         return recvBuffer;
94 }
95
96
97 // Factoring out iteration
98 char* IoTSlave::recvFileIter(char* recvBuffer, int recvLen) {
99
100     int bytesReceived = 0;              // Bytes read on each recv()
101     int totalBytesReceived = 0;         // Total bytes read
102
103         while (totalBytesReceived < recvLen) {
104                 // Receive up to the buffer size bytes from the sender
105                 if ((bytesReceived = (socket->recv(recvBuffer, recvLen))) <= 0) {
106                         string errMsg = "IoTSlave: Unable to read!";
107                         cerr << errMsg << endl;
108                         writeToFile(errMsg);
109                         exit(1);
110                 }
111                 totalBytesReceived += bytesReceived;     // Keep tally of total bytes
112         }
113
114         return recvBuffer;
115 }
116
117
118 void IoTSlave::openFile(string fileName) {
119
120         log.open(FILEPATH + fileName + FILEEXT);
121 }
122
123
124 void IoTSlave::writeToFile(string logMsg) {
125
126         log << "IoTSlave: " << logMsg << endl;
127 }
128
129
130 void IoTSlave::closeFile() {
131
132         log.close();
133 }
134
135
136 void IoTSlave::getObjectHandler(string objectClassName) {
137
138         // Object handling
139         string strObj = FILEPATH + objectClassName + SOEXT;
140         void* handle = dlopen (strObj.c_str(), RTLD_LAZY);
141         if (!handle) {
142                 fputs (dlerror(), stderr);
143                 writeToFile("Error handling object!");
144                 exit(1);
145         }
146         writeToFile("Object handled!");
147         // Create handler
148         string createFunction = CREATEFUNCTION + objectClassName;
149         create_object = (create_t*) dlsym(handle, createFunction.c_str());
150         const char* dlsym_error = dlerror();
151     if (dlsym_error) {
152         cerr << "Cannot load symbol create: " << dlsym_error << '\n';
153                 writeToFile("Cannot load symbol create!");
154         exit(1);
155     }
156         writeToFile("Object factory created for " + objectClassName);
157         // Destroy handler
158         string destroyFunction = DESTROYFUNCTION + objectClassName;
159     destroy_object = (destroy_t*) dlsym(handle, destroyFunction.c_str());
160     dlsym_error = dlerror();
161     if (dlsym_error) {
162         cerr << "Cannot load symbol destroy: " << dlsym_error << '\n';
163                 writeToFile("Cannot load symbol destroy!");
164         exit(1);
165     }
166         writeToFile("Object destroyer created for " + objectClassName);
167         // Create initializer
168         string initFunction = INITFUNCTION + objectClassName;
169     init_object = (init_t*) dlsym(handle, initFunction.c_str());
170     dlsym_error = dlerror();
171     if (dlsym_error) {
172         cerr << "Cannot load symbol init: " << dlsym_error << '\n';
173                 writeToFile("Cannot load symbol init!");
174         exit(1);
175     }
176         writeToFile("Object initializer created for " + objectClassName);
177 }
178
179
180 // Run init_object function
181 void IoTSlave::runInitObject(IoTSlave* iotslave) {
182
183         iotslave->init_object(iotslave->objMainCls);
184 }
185
186
187 // Instantiate main object!
188 // Use handler obtained by getObjectHandler() and instantiate object!
189 void IoTSlave::instantiateMainObject() {
190
191         // IoTSet + IoTRelation objects
192         int paramSize = vecIoTSet.size() + vecIoTRel.size();
193         void* params[paramSize];
194         int j = 0;
195         for(int i=0; i<vecIoTSet.size(); i++) {
196                 params[j] = vecIoTSet[i]; j++;
197         }
198         writeToFile("Vector IoTSet size: " + to_string(vecIoTSet.size()));
199         for(int i=0; i<vecIoTRel.size(); i++) {
200                 params[j] = vecIoTRel[i]; j++;
201         }
202         writeToFile("Vector IoTRelation size: " + to_string(vecIoTRel.size()));
203         objMainCls = create_object(params);
204         writeToFile("Object created for " + mainObjectName);
205         init_object(objMainCls);
206         //thread th1 (&IoTSlave::runInitObject, this, this);
207         //th1.detach();
208         //thread th1 (&IoTSlave::runInitObject, this, this);
209         //th1.join();
210         writeToFile("Initialized object " + mainObjectName);
211 }
212
213
214 // Instantiate driver object!
215 // Use handler obtained by getObjectHandler() and instantiate object!
216 void IoTSlave::instantiateDriverObject() {
217
218         // IoTDeviceAddress + other arguments
219         int paramSize = vecIoTSet.size() + args.size();
220         void* params[paramSize];
221         for(int i=0; i<vecIoTSet.size(); i++) {
222                 params[i] = vecIoTSet[i];       // Just the first object is taken in this case
223         }
224         writeToFile("Vector IoTSet size: " + to_string(vecIoTSet.size()));
225         writeToFile("Arg size: " + to_string(args.size()));
226         int countArg = vecIoTSet.size();        // Start from after the address set
227         // Iterate over arguments
228         for(int i=0; i<args.size(); i++) {
229                 params[countArg] = getObjectConverted(params[countArg], args[i], argClasses[i]);
230                 countArg++; 
231         }
232         objMainCls = create_object(params);
233         // Delete unused object after conversion and instantiation
234         for(int i=1; i<paramSize; i++) {
235                 if (argClasses[i-1].compare(STRINGCLASS) == 0) {                
236                         delete (string*) params[i];
237                 } else if (argClasses[i-1].compare(INTCLASS) == 0)
238                         delete (int*) params[i];
239         }               
240         writeToFile("Object created for " + objectClassName);
241 }
242
243
244 // Use handler obtained by getObjectHandler() and instantiate skeleton object!
245 void IoTSlave::instantiateSkelObject() {
246
247         void* params[SKELPARAMSIZE];
248         params[0] = objMainCls;
249         //string callbackAddress = LOCALHOST;
250         //params[1] = &callbackAddress;
251         //params[2] = &objectStubPort;
252         params[1] = &objectStubPort;
253         params[2] = &objectRegPort;
254         writeToFile("Skeleton Object " + objectSkelClass + " created for " + objectClassName);
255         // After this, this slave needs to be killed using "pkill IoTSlave" because it's waiting in an infinite while-loop
256         objSkelCls = create_object(params);
257 }
258
259
260 // Use handler obtained by getObjectHandler() and instantiate stub object!
261 void IoTSlave::instantiateStubObject() {
262
263         void* params[STUBPARAMSIZE];
264         params[0] = &objectStubPort;
265         params[1] = &objectRegPort;
266         params[2] = &hostAddress;
267         //params[0] = &objectStubPort;
268         //params[1] = &hostAddress;
269         //string callbackAddress = LOCALHOST;
270         //params[2] = &callbackAddress;
271         int rev = 0;
272         params[3] = &rev;
273         bool result = false;
274         params[4] = &result;
275         //params[5] = ports;
276         writeToFile("Stub Object " + objectStubClass + " created for " + objectClassName);
277         writeToFile("Success 1!");
278         objStubCls = create_object(params);
279         writeToFile("Success 2!");
280 }
281
282
283 // Public methods
284 string IoTSlave::getServerAddress() {
285
286         return serverAddress;
287 }
288
289
290 int IoTSlave::getServerPort() {
291
292         return serverPort;
293 }
294
295
296 string IoTSlave::getObjectName() {
297
298         return objectName;
299 }
300
301
302 void IoTSlave::sendInteger(int intSend) {
303
304         char charInt[sizeof(int)];
305         // Convert int to byte array and fix endianness
306         intToByteArray(intSend, charInt);
307         // Send the length first
308         void* toSend = charInt;
309         socket->send(toSend, sizeof(int));
310 }
311
312
313 int IoTSlave::recvInteger() {
314
315         int toBeReceived = sizeof(int);
316         char recvInt[sizeof(int)];                      // Normally 4 bytes
317
318         // Receive and iterate until complete
319         //writeToFile("Receiving Integer! Size: " + to_string(toBeReceived));
320         recvIter(recvInt, toBeReceived);
321
322         int retVal = 0;
323         byteToInt(&retVal, recvInt);
324
325         return retVal;
326 }
327
328
329 void IoTSlave::sendString(string strSend) {
330
331         // Send the length first
332         int strLen = strSend.length();
333         sendInteger(strLen);
334
335         // Send the string
336         char* chStrSend = new char[strLen];
337         strcpy(chStrSend, strSend.c_str());
338         void* toSend = chStrSend;
339         socket->send(toSend, strLen);
340         // Avoid memory leak
341         delete[] chStrSend;
342 }
343
344
345 string IoTSlave::recvString() {
346
347         // Get the length of string first
348         int strLen = recvInteger();
349         char* recvStr = new char[strLen];
350
351         // Receive and iterate until complete
352         //writeToFile("Receiving String! Size: " + to_string(strLen));
353         recvIter(recvStr, strLen);
354
355         string retVal(recvStr, strLen);
356         delete[] recvStr;
357
358         return retVal;
359 }
360
361
362 // Receive file from IoTMaster
363 void IoTSlave::transferFile() {
364
365         string fileName = recvFile(); sendAck();
366         //unzipFile(fileName);
367 }
368
369
370 void IoTSlave::unzipFile(string fileName) {
371
372         // Unzip file (what we are sending is a zipped file)
373         // TODO: perhaps we need to replace this with libzip or zlib later      
374         writeToFile("Unzipping file!");
375         string chmodCmd = FILEPATH + fileName + SHELL;
376         //std::system(chmodCmd.c_str());
377         thread th1 (std::system, chmodCmd.c_str());
378         th1.detach();
379         writeToFile("Finished unzipping file!");
380 }
381
382
383 string IoTSlave::recvFile() {
384
385         // Get the length of string first
386         string fileName = recvString(); sendAck();
387         int fileLen = recvInteger(); sendAck();
388         writeToFile("Receiving file " + fileName + " with length " + to_string(fileLen) + " bytes...");
389         char* recvFil = new char[fileLen];
390         // Receive and iterate until complete
391         recvFileIter(recvFil, fileLen);
392         // Write into file
393         ofstream fileStream;
394         fileStream.open(FILEPATH + fileName);
395         if (!fileStream) {
396                 writeToFile("Error opening file: " + FILEPATH + fileName);
397                 exit(1);
398         }
399         fileStream.write(recvFil, fileLen);
400         delete[] recvFil;
401         fileStream.close();
402         // TODO: Experimental
403         //string chmodCmd = FILEPATH + fileName + SHELL;
404         //execv(chmodCmd.c_str(), 0);
405         return fileName;
406 }
407
408
409 // Create a driver object, e.g. LifxLightBulb
410 void IoTSlave::createObject() {
411
412         writeToFile("Creating a driver object now...");
413         // Receiving object info
414         objectName = recvString(); sendAck();
415         writeToFile("=> Driver object name: " + objectName);
416         objectClassName = recvString(); sendAck();
417         writeToFile("=> Driver object class name: " + objectClassName);
418         objectInterfaceName = recvString(); sendAck();
419         writeToFile("=> Driver object interface name: " + objectInterfaceName);
420         objectSkelClass = recvString(); sendAck();
421         writeToFile("=> Driver object skeleton class name: " + objectSkelClass);
422         objectRegPort = recvInteger(); sendAck();
423         writeToFile("=> Driver object registry port: " + to_string(objectRegPort));
424         objectStubPort = recvInteger(); sendAck();
425         writeToFile("=> Driver object stub port: " + to_string(objectStubPort));
426         int numOfArgs = recvInteger(); sendAck();
427         writeToFile("=> Number of args: " + to_string(numOfArgs));
428         for (int i = 0; i < numOfArgs; i++) {
429                 string arg = recvString(); sendAck();
430                 args.push_back(arg);
431                 writeToFile("==> Got argument: " + arg);
432         }
433         for (int i = 0; i < numOfArgs; i++) {
434                 string argClass = recvString(); sendAck();
435                 argClasses.push_back(argClass);
436                 writeToFile("==> Got argument class: " + argClass);
437         }
438         // We are just receiving object information here
439         // Instantiation will be done when IoTDeviceAddress has been sent
440 }
441
442
443 // Create a new IoTSet object to hold objects
444 void IoTSlave::createNewIoTSet() {
445
446         objectFieldName = recvString(); sendAck();
447         // Instantiating new IoTSet object
448         isetObject = new unordered_set<void*>();
449         writeToFile("Creating new IoTSet for field: " + objectFieldName);
450 }
451
452
453 // Get IoTDeviceAddress object reference and put it inside IoTSet object
454 void IoTSlave::getDeviceIoTSetObject() {
455
456         writeToFile("Getting IoTDeviceAddress... ");
457         // Get the IoTDeviceAddress info
458         hostAddress = recvString(); sendAck();
459         writeToFile("=> Host address: " + hostAddress);
460         int sourcePort = recvInteger(); sendAck();
461         writeToFile("=> Source port: " + to_string(sourcePort));
462         int destPort = recvInteger(); sendAck();
463         writeToFile("=> Destination port: " + to_string(destPort));
464         bool sourcePortWildCard = (bool) recvInteger(); sendAck();
465         writeToFile("=> Is source port wild card? " + to_string(sourcePortWildCard));
466         bool destPortWildCard = (bool) recvInteger(); sendAck();
467         writeToFile("=> Is destination port wild card? " + to_string(destPortWildCard));
468         // Create IoTDeviceAddress      
469         IoTDeviceAddress* objDeviceAddress = new IoTDeviceAddress(hostAddress, sourcePort, destPort, 
470                 sourcePortWildCard, destPortWildCard);
471         // Insert it into isetObject!
472         isetObject->insert(objDeviceAddress);
473         writeToFile("=> Inserting IoTDeviceAddress into set...");
474         writeToFile("==> Now we have " + to_string(isetObject->size()) + " object(s)!");
475         // Set flag to true;
476         //isDriverObject = true;
477 }
478
479
480 void IoTSlave::createStub() {
481         // Create Stub object
482         unordered_map<string,void*>::const_iterator itr = mapObjNameStub.find(objectName);
483         if (itr != mapObjNameStub.end()) {      // Stub has been created earlier
484                 writeToFile("=> Stub has been created! Getting back reference...");
485                 objStubCls = itr->second;
486         } else {        // Instantiate a new stub and map it
487                 writeToFile("=> Stub has not been created! Creating a new stub...");
488                 getObjectHandler(objectStubClass);
489                 instantiateStubObject();
490                 mapObjNameStub.insert(make_pair(objectName,objStubCls));
491                 writeToFile("=> Map has: " + to_string(mapObjNameStub.size()) + " members");
492                 // vector<int> for ports has been copied - now delete it
493                 delete ports;
494         }
495 }
496
497
498 // Get IoTSet object content reference and put it inside IoTSet object
499 // This is basically the stub objects
500 void IoTSlave::getIoTSetObject() {
501
502         writeToFile("Getting IoTSet object... ");
503         getIoTSetRelationObject();
504         createStub();
505         // Insert it into isetObject!
506         isetObject->insert(objStubCls);
507         writeToFile("=> Inserting stub object into set...");
508         writeToFile("==> Now we have " + to_string(isetObject->size()) + " object(s)!");
509 }
510
511
512 // Reinitialize IoTSet field!
513 void IoTSlave::reinitializeIoTSetField() {
514
515         writeToFile("Reinitialize IoTSet field...");
516         iotsetObject = new IoTSet<void*>(isetObject);
517         // Collect IoTSet field first in a vector
518         vecIoTSet.push_back(iotsetObject);
519
520 }
521
522
523 // Instantiate driver object
524 void IoTSlave::createDriverObject() {
525
526         // Instantiate driver object
527         getObjectHandler(objectClassName);
528         instantiateDriverObject();
529         // Instantiate skeleton object
530         getObjectHandler(objectSkelClass);
531         instantiateSkelObject();
532 }
533
534
535 // Create a new IoTRelation object to hold objects
536 void IoTSlave::createNewIoTRelation() {
537
538         objectFieldName = recvString(); sendAck();
539         // Instantiating new IoTSet object
540         irelObject = new unordered_multimap<void*,void*>();
541         writeToFile("Creating new IoTRelation for field: " + objectFieldName);
542 }
543
544
545 // Get IoTRelation object
546 void IoTSlave::getIoTSetRelationObject() {
547
548         hostAddress = recvString(); sendAck();
549         writeToFile("=> Host address: " + hostAddress);
550         objectName = recvString(); sendAck();
551         writeToFile("=> Driver object name: " + objectName);
552         objectClassName = recvString(); sendAck();
553         writeToFile("=> Driver object class name: " + objectClassName);
554         objectInterfaceName = recvString(); sendAck();
555         writeToFile("=> Driver object interface name: " + objectInterfaceName);
556         objectStubClass = recvString(); sendAck();
557         writeToFile("=> Driver object stub class name: " + objectStubClass);
558         objectRegPort = recvInteger(); sendAck();
559         writeToFile("=> Driver object registry port: " + to_string(objectRegPort));
560         objectStubPort = recvInteger(); sendAck();
561         writeToFile("=> Driver object stub port: " + to_string(objectStubPort));
562         int numOfPorts = recvInteger(); sendAck();
563         ports = new vector<int>();
564         for (int i = 0; i < numOfPorts; i++) {
565                 int port = recvInteger(); sendAck();
566                 ports->push_back(port);
567                 writeToFile("==> Got a new port: " + to_string(port));
568         }
569 }
570
571
572 // Get the first object of IoTRelation
573 void IoTSlave::getIoTRelationFirstObject() {
574
575         writeToFile("Getting IoTRelation first object... ");
576         getIoTSetRelationObject();
577         createStub();
578         // Hold the first object of IoTRelation
579         irelFirstObject = objStubCls;
580         writeToFile("=> Holding first stub object...");
581 }
582
583
584 // Get the second object of IoTRelation
585 void IoTSlave::getIoTRelationSecondObject() {
586
587         writeToFile("Getting IoTRelation second object... ");
588         getIoTSetRelationObject();
589         createStub();
590         // Hold the first object of IoTRelation
591         irelSecondObject = objStubCls;
592         writeToFile("=> Holding second stub object...");
593         pair<void*,void*>* iotrelPair = new pair<void*,void*>(irelFirstObject, irelSecondObject);
594         writeToFile("=> Creating a pair of stub objects and inserting into IoTRelation object...");
595         irelObject->insert(*iotrelPair);
596 }
597
598
599 // Reinitialize IoTRelation
600 void IoTSlave::reinitializeIoTRelationField() {
601
602         writeToFile("Reinitialize IoTRelation field...");
603         iotrelObject = new IoTRelation<void*,void*>(irelObject);
604         // Collect IoTSet field first in a vector
605         vecIoTRel.push_back(iotrelObject);
606 }
607
608
609 // Invoke init() method in main controller
610 void IoTSlave::invokeInitMethod() {
611
612         writeToFile("Invoke init() method for: " + mainObjectName);
613         // Instantiate main controller object
614         getObjectHandler(mainObjectName);
615         instantiateMainObject();
616
617 }
618
619
620 // Create a main object, e.g. Lifxtest
621 void IoTSlave::createMainObject() {
622
623         mainObjectName = recvString(); sendAck();
624         writeToFile("Creating main object: " + mainObjectName);
625         // Just receive the name of the class object here
626         // We will instantiate the object after we get the set/relation objects
627 }
628
629
630 void IoTSlave::sendAck() {
631
632         int codeAck = (int) ACKNOWLEDGED;
633         sendInteger(codeAck);
634 }
635
636
637 bool IoTSlave::recvEndTransfer() {
638
639         int codeEndTransfer = (int) END_TRANSFER;
640         int recvCode = recvInteger();
641         if (recvCode == codeEndTransfer)
642                 return true;
643         return false;
644 }
645
646
647 void IoTSlave::commIoTMaster() {
648
649         writeToFile("Starting main loop...");
650         // Main iteration/loop
651         while(true) {
652                 IoTCommCode message = (IoTCommCode) recvInteger(); 
653                 writeToFile("Message: " + to_string(message));
654                 sendAck();
655                 
656                 switch(message) {
657
658                         case CREATE_OBJECT:
659                                 createObject();
660                                 break;
661
662                         case TRANSFER_FILE:
663                                 transferFile();
664                                 break;
665
666                         case CREATE_MAIN_OBJECT:
667                                 createMainObject();
668                                 break;
669
670                         case CREATE_NEW_IOTSET:
671                                 createNewIoTSet();
672                                 break;
673
674                         case CREATE_NEW_IOTRELATION:
675                                 createNewIoTRelation();
676                                 break;
677
678                         case GET_IOTSET_OBJECT:
679                                 getIoTSetObject();
680                                 break;
681
682                         case GET_IOTRELATION_FIRST_OBJECT:
683                                 getIoTRelationFirstObject();
684                                 break;
685
686                         case GET_IOTRELATION_SECOND_OBJECT:
687                                 getIoTRelationSecondObject();
688                                 break;
689
690                         case REINITIALIZE_IOTSET_FIELD:
691                                 reinitializeIoTSetField();
692                                 break;
693
694                         case REINITIALIZE_IOTRELATION_FIELD:
695                                 reinitializeIoTRelationField();
696                                 break;
697
698                         case GET_DEVICE_IOTSET_OBJECT:
699                                 getDeviceIoTSetObject();
700                                 break;
701
702                         case GET_ZB_DEV_IOTSET_OBJECT:
703                                 //getZBDevIoTSetObject();
704                                 break;
705
706                         case GET_ADD_IOTSET_OBJECT:
707                                 //getAddIoTSetObject();
708                                 break;
709
710                         case INVOKE_INIT_METHOD:
711                                 invokeInitMethod();
712                                 break;
713
714                         case CREATE_DRIVER_OBJECT:
715                                 createDriverObject();
716                                 break;
717
718                         case END_SESSION:
719                                 // END of session
720                                 goto ENDLOOP;
721                                 break;
722
723                         default:
724                                 break;
725                 }
726         }
727         ENDLOOP:
728         writeToFile("End of loop!");
729 }
730
731
732 int main(int argc, char *argv[]) {
733
734         string serverAddress = argv[1];
735         char* servPort = argv[2];
736         int serverPort = atoi(servPort);
737         string strObjName = argv[3];
738         IoTSlave *iotSlave = new IoTSlave(serverAddress, serverPort, strObjName);
739         iotSlave->sendAck();
740         iotSlave->commIoTMaster();
741         
742         return 0;
743 }