Cleaning up drivers/Cpp, Cpp/Lifxtest, virtuals, and iotrmi/C++ (revisiting the C...
[iot2.git] / iotjava / iotruntime / cpp / iotslave / IoTSlave.java
1 import java.util.*;
2 import java.io.*;
3 import java.net.*;
4 import java.nio.*;
5 import static java.lang.Math.toIntExact;
6
7 public class IoTSlave {
8
9         private ServerSocket serverSocket;
10         private Socket socket;
11         private BufferedInputStream input;
12         private BufferedOutputStream output;
13
14         private static final String STR_LOCALHOST = "localhost";
15         private static final String STR_IOTSLAVE_CPP = "./IoTSlave.o";
16         private static final String STR_IOTSLAVE_PATH = "~/tmp/iot2/iotjava/iotruntime/cpp/iotslave/";
17
18         //private static final String STR_LOG_FILE_PATH = "./";
19         private static int INT_SIZE = 4;        // send length in the size of integer (4 bytes)
20
21
22         public IoTSlave() {
23
24                 serverSocket = null;
25                 socket = null;
26                 input = null;
27                 output = null;
28         }
29
30
31         /**
32          * Prepare server socket connection with C++ IoTSlave
33          */
34         public void setServerSocketCpp(int iPort) {
35
36                 try {
37                         serverSocket = new ServerSocket(iPort);
38                 }
39                 catch ( IOException e ) {
40                         e.printStackTrace();
41                 }
42         }
43
44
45         /**
46          * A method to send files from IoTMaster
47          *
48          * @param  filesocket File socket object
49          * @param  sFileName  File name
50          * @param  lFLength   File length
51          * @return            void
52          */
53         private void sendFile(Socket filesocket, String sFileName, long lFLength) throws IOException {
54
55                 File file = new File(sFileName);
56                 byte[] bytFile = new byte[toIntExact(lFLength)];
57                 InputStream inFileStream = new FileInputStream(file);
58
59                 OutputStream outFileStream = filesocket.getOutputStream();
60                 int iCount;
61                 while ((iCount = inFileStream.read(bytFile)) > 0) {
62                         outFileStream.write(bytFile, 0, iCount);
63                 }
64                 filesocket.close();
65         }
66
67
68         private void sendFile(String sFilePath, String sFileName) throws IOException {
69
70                 sendCommCode(IoTCommCode.TRANSFER_FILE);
71                 // Send file name
72                 sendString(sFileName); recvAck();
73                 File file = new File(sFilePath + sFileName);
74                 int iFileLen = toIntExact(file.length());
75                 System.out.println("IoTSlave: Sending file " + sFileName + " with length " + iFileLen + " bytes...");
76                 // Send file length
77                 sendInteger(iFileLen); recvAck();
78                 byte[] bytFile = new byte[iFileLen];
79                 InputStream inFileStream = new FileInputStream(file);
80
81                 OutputStream outFileStream = socket.getOutputStream();
82                 int iCount;
83                 while ((iCount = inFileStream.read(bytFile)) > 0) {
84                         outFileStream.write(bytFile, 0, iCount);
85                 }
86                 System.out.println("IoTSlave: File sent!");
87                 recvAck();
88         }
89
90         /**
91          * sendInteger() sends an integer in bytes
92          */
93         public void sendInteger(int intSend) throws IOException {
94
95                 // Transform integer into bytes
96                 ByteBuffer bb = ByteBuffer.allocate(INT_SIZE);
97                 bb.putInt(intSend);
98                 // Send the byte array
99                 output.write(bb.array(), 0, INT_SIZE);
100                 output.flush();
101         }
102
103
104         /**
105          * recvInteger() receives integer in bytes
106          */
107         public int recvInteger() throws IOException {
108
109                 // Wait until input is available
110                 while(input.available() == 0);
111                 // Read integer - 4 bytes
112                 byte[] recvInt = new byte[INT_SIZE];
113                 input.read(recvInt, 0, INT_SIZE);
114                 int retVal = ByteBuffer.wrap(recvInt).getInt();
115
116                 return retVal;
117         }
118
119
120         /**
121          * recvString() receives String in bytes
122          */
123         public String recvString() throws IOException {
124
125                 int strLen = recvInteger();
126                 // Wait until input is available
127                 while(input.available() == 0);
128                 // Read String per strLen
129                 byte[] recvStr = new byte[strLen];
130                 input.read(recvStr, 0, strLen);
131                 String retVal = new String(recvStr);
132
133                 return retVal;
134         }
135
136
137         /**
138          * sendString() sends a String in bytes
139          */
140         public void sendString(String strSend) throws IOException {
141
142                 // Transform String into bytes
143                 byte[] strSendBytes = strSend.getBytes();
144                 int strLen = strSend.length();
145                 // Send the string length first
146                 sendInteger(strLen);
147                 // Send the byte array
148                 output.write(strSendBytes, 0, strLen);
149                 output.flush();
150         }
151
152
153         /**
154          * Establish connection with C++ IoTSlave
155          */
156         public void connectCpp() throws IOException     {
157
158                 socket = serverSocket.accept();
159                 input = new BufferedInputStream(socket.getInputStream());
160                 output = new BufferedOutputStream(socket.getOutputStream());
161         }
162
163
164         /**
165          * Construct a SSH command to run C++ program
166          */
167         public static String constructCommand(String serverAddress, int serverPort, String strObjName) {
168
169                 String strCommand = "ssh rtrimana@localhost cd " + STR_IOTSLAVE_PATH + "; " +
170                                 STR_IOTSLAVE_CPP + " " + serverAddress + " " + serverPort + " " + strObjName;
171                 return strCommand;
172         }
173
174
175         /**
176          * Create a new thread to start a new C++ process
177          */
178         public static void createCppThread(String strCmd) {
179
180                 Thread thread = new Thread(new Runnable() {
181                         public void run() {
182                                 try {
183                                         Runtime runtime = Runtime.getRuntime();
184                                         Process process = runtime.exec(strCmd);
185                                 } catch(IOException ex) {
186                                         ex.printStackTrace();
187                                 }
188                         }
189                 });
190                 thread.start();
191                 //RuntimeOutput.print("IoTSlave: Executing: " + strCmd, BOOL_VERBOSE);
192                 System.out.println("IoTSlave: Executing: " + strCmd);
193         }
194
195
196         /**
197          * Convert integer to enum
198          */
199         public IoTCommCode getCode(int intCode) throws IOException {
200
201                 IoTCommCode[] commCode = IoTCommCode.values();
202                 IoTCommCode retCode = commCode[intCode];
203                 return retCode;
204
205         }
206
207
208         /**
209          * Receive ACK
210          */
211         public boolean recvAck() throws IOException {
212
213                 int intAck = recvInteger();
214                 IoTCommCode codeAck = getCode(intAck);
215                 if (codeAck == IoTCommCode.ACKNOWLEDGED)
216                         return true;
217                 return false;
218
219         }
220
221
222         /**
223          * Send END
224          */
225         public void sendEndTransfer() throws IOException {
226
227                 int endCode = IoTCommCode.END_TRANSFER.ordinal();
228                 sendInteger(endCode);
229         }
230
231
232         /**
233          * Send communication code to C++
234          */
235         public void sendCommCode(IoTCommCode inpCommCode) throws IOException {
236
237
238                 IoTCommCode commCode = inpCommCode;
239                 int intCode = commCode.ordinal();
240                 sendInteger(intCode); recvAck();
241         }
242
243
244         /**
245          * Create a main controller object for C++
246          */
247         public void createMainObjectCpp() throws IOException {
248
249                 sendCommCode(IoTCommCode.CREATE_MAIN_OBJECT);
250                 String strMainObjName = "Lifxtest";
251                 sendString(strMainObjName); recvAck();
252                 System.out.println("IoTSlave: Create a main object: " + strMainObjName);
253         }
254
255
256         /**
257          * Create a driver object for C++
258          */
259         public void createObjectCpp() throws IOException {
260
261                 sendCommCode(IoTCommCode.CREATE_OBJECT);
262                 String strDrvObjName = "LifxLightBulbLB2";
263                 String strDrvObjClsName = "LifxLightBulb";
264                 String strDrvObjIntfaceClsName = "LightBulb";
265                 String strDrvObjSkelClsName = "LightBulb_Skeleton";
266                 int iRegPort = 30313;
267                 int iStubPort = 55179;
268                 // TODO: On the actual slave we need to do conversion back to string before we send everything to C++ IoTSlave
269                 // TODO: Make it as array of string
270                 //String[] arrCppArgs = { "D073D50241DA0000" };
271                 String[] arrCppArgs = { "D073D5128E300000" };
272                 String[] arrCppArgClasses = { "string" };
273                 System.out.println("IoTSlave: Send request to create a driver object... ");
274                 System.out.println("IoTSlave: Driver object name: " + strDrvObjName);
275                 sendString(strDrvObjName); recvAck();
276                 System.out.println("IoTSlave: Driver object class name: " + strDrvObjClsName);
277                 sendString(strDrvObjClsName); recvAck();
278                 System.out.println("IoTSlave: Driver object interface name: " + strDrvObjIntfaceClsName);
279                 sendString(strDrvObjIntfaceClsName); recvAck();
280                 System.out.println("IoTSlave: Driver object skeleton class name: " + strDrvObjSkelClsName);
281                 sendString(strDrvObjSkelClsName); recvAck();
282                 System.out.println("IoTSlave: Driver object registry port: " + iRegPort);
283                 sendInteger(iRegPort); recvAck();
284                 System.out.println("IoTSlave: Driver object stub port: " + iStubPort);
285                 sendInteger(iStubPort); recvAck();
286                 int numOfArgs = arrCppArgs.length;
287                 System.out.println("IoTSlave: Send constructor arguments! Number of arguments: " + numOfArgs);
288                 sendInteger(numOfArgs); recvAck();
289                 for(String str : arrCppArgs) {
290                         sendString(str); recvAck();
291                 }
292                 System.out.println("IoTSlave: Send constructor argument classes!");
293                 for(String str : arrCppArgClasses) {
294                         sendString(str); recvAck();
295                 }
296         }
297
298
299         /**
300          * Create new IoTSet for C++
301          */
302         //public void createNewIoTSetCpp() throws IOException {
303         public void createNewIoTSetCpp(String strObjFieldName) throws IOException {
304
305                 sendCommCode(IoTCommCode.CREATE_NEW_IOTSET);
306                 System.out.println("IoTSlave: Creating new IoTSet...");
307                 //String strObjFieldName = "lb_addresses";
308                 System.out.println("IoTSlave: Send object field name: " + strObjFieldName);
309                 sendString(strObjFieldName); recvAck();
310         }
311
312
313         /**
314          * Get a IoTDeviceAddress object for C++
315          */
316         public void getDeviceIoTSetObjectCpp() throws IOException {
317
318                 sendCommCode(IoTCommCode.GET_DEVICE_IOTSET_OBJECT);
319                 System.out.println("IoTSlave: Getting IoTDeviceAddress...");
320                 //String strHostAddress = "192.168.2.232";
321                 String strHostAddress = "192.168.2.126";
322                 sendString(strHostAddress); recvAck();
323                 int iSourcePort = 43583;
324                 sendInteger(iSourcePort); recvAck();
325                 int iDestPort = 56700;
326                 sendInteger(iDestPort); recvAck();
327                 boolean bSourceWildCard = false;
328                 int iSourceWildCard = (bSourceWildCard ? 1 : 0);
329                 sendInteger(iSourceWildCard); recvAck();
330                 boolean bDestWildCard = false;
331                 int iDestWildCard = (bDestWildCard ? 1 : 0);
332                 sendInteger(iDestWildCard); recvAck();
333                 System.out.println("IoTSlave: Send host address: " + strHostAddress);
334         }
335
336
337         /**
338          * Get a IoTSet content object for C++
339          */
340         public void getIoTSetObjectCpp() throws IOException {
341
342                 sendCommCode(IoTCommCode.GET_IOTSET_OBJECT);
343                 System.out.println("IoTSlave: Getting IoTSet object content...");
344                 String strHostAddress = "localhost";
345                 String strDrvObjName = "LifxLightBulbLB2";
346                 String strDrvObjClsName = "LifxLightBulb";
347                 String strDrvObjIntfaceClsName = "LightBulb";
348                 String strDrvObjStubClsName = "LightBulbTest_Stub";     // Send a complete name with "_Stub"
349                 int iRegPort = 30313;
350                 int iStubPort = 55179;
351                 int[] callbackPorts = { 58551 };
352                 // Send info
353                 System.out.println("IoTSlave: Send host address: " + strHostAddress);
354                 sendString(strHostAddress); recvAck();
355                 System.out.println("IoTSlave: Driver object name: " + strDrvObjName);
356                 sendString(strDrvObjName); recvAck();
357                 System.out.println("IoTSlave: Driver object class name: " + strDrvObjClsName);
358                 sendString(strDrvObjClsName); recvAck();
359                 System.out.println("IoTSlave: Driver object interface name: " + strDrvObjIntfaceClsName);
360                 sendString(strDrvObjIntfaceClsName); recvAck();
361                 System.out.println("IoTSlave: Driver object skeleton class name: " + strDrvObjStubClsName);
362                 sendString(strDrvObjStubClsName); recvAck();
363                 System.out.println("IoTSlave: Driver object registry port: " + iRegPort);
364                 sendInteger(iRegPort); recvAck();
365                 System.out.println("IoTSlave: Driver object stub port: " + iStubPort);
366                 sendInteger(iStubPort); recvAck();
367                 sendInteger(callbackPorts.length); recvAck();
368                 for(int i : callbackPorts) {
369                         sendInteger(i); recvAck();
370                 }
371
372         }
373
374
375         /**
376          * Reinitialize IoTSet field for C++
377          */
378         private void reinitializeIoTSetFieldCpp() throws IOException {
379
380                 System.out.println("IoTSlave: About to Reinitialize IoTSet field!");
381                 sendCommCode(IoTCommCode.REINITIALIZE_IOTSET_FIELD);
382                 System.out.println("IoTSlave: Reinitialize IoTSet field!");
383         }
384
385
386         /**
387          * Invoke init() for C++
388          */
389         private void invokeInitMethodCpp() throws IOException {
390
391                 sendCommCode(IoTCommCode.INVOKE_INIT_METHOD);
392                 System.out.println("IoTSlave: Invoke init method!");
393         }
394
395
396         /**
397          * End session for C++
398          */
399         public void endSessionCpp() throws IOException {
400
401                 // Send message to end session
402                 IoTCommCode endSessionCode = IoTCommCode.END_SESSION;
403                 int intCode = endSessionCode.ordinal();
404                 sendInteger(intCode);
405                 //RuntimeOutput.print("IoTSlave: Send request to create a main object: " + strObjName, BOOL_VERBOSE);
406                 System.out.println("IoTSlave: Send request to end session!");
407         }
408
409
410         public static void main(String[] args) throws IOException, InterruptedException {
411
412                 /*int iPort = 12345;
413                 IoTSlave iotSlave = new IoTSlave();
414                 iotSlave.setServerSocketCpp(iPort);
415                 iotSlave.connectCpp();
416                 System.out.println("Connection established with client!");
417                 iotSlave.sendInteger(1234);
418                 System.out.println("Integer sent!");
419                 System.out.println("Integer received: " + iotSlave.recvInteger());
420                 String strRecv = iotSlave.recvString();
421                 System.out.println("Received string: " + strRecv);
422                 strRecv = strRecv + " - ACKNOWLEDGED!";
423                 System.out.println("Sending back string: " + strRecv);
424                 iotSlave.sendString(strRecv);*/
425
426                 // =========================================
427                 // Create IoTSlave for controller object!
428                 int iPortMain =12346;
429                 String strAddressMain = "localhost";
430                 String strObjNameMain = "Lifxtest";
431                 IoTSlave iotSlaveMain = new IoTSlave();
432                 iotSlaveMain.setServerSocketCpp(iPortMain);
433                 // Run thread to spawn C++ IoTSlave
434                 String strCmdMain = iotSlaveMain.constructCommand(strAddressMain, iPortMain, strObjNameMain);
435                 iotSlaveMain.createCppThread(strCmdMain);
436                 iotSlaveMain.connectCpp();
437                 System.out.println("IoTSlave: Connection established with main!");
438                 // First contact with C++ IoTSlave
439                 System.out.println("IoTSlave: IoTSlave.o main is ready: " + iotSlaveMain.recvAck());
440                 //iotSlaveMain.sendFile("../", "Lifxtest.so");
441                 //iotSlaveMain.sendFile("../", "LightBulbTest_Stub.so");
442                 //iotSlaveMain.sendFile("../", "Lifxtest.zip");
443                 //iotSlaveMain.sendFile("../resources/", "Lifxtest.jar");
444                 //iotSlaveMain.sendFile("../", "unzip.zip");
445                 
446
447                 // =========================================
448                 // Create IoTSlave for driver object!
449                 int iPort =12345;
450                 String strAddress = "localhost";
451                 String strObjName = "LifxLightBulbLB2";
452                 IoTSlave iotSlave = new IoTSlave();
453                 iotSlave.setServerSocketCpp(iPort);
454                 // Run thread to spawn C++ IoTSlave
455                 String strCmd = IoTSlave.constructCommand(strAddress, iPort, strObjName);
456                 IoTSlave.createCppThread(strCmd);
457                 iotSlave.connectCpp();
458                 //RuntimeOutput.print("IoTSlave: Connection established!", BOOL_VERBOSE);
459                 System.out.println("IoTSlave: Connection established!");
460                 // First contact with C++ IoTSlave
461                 System.out.println("IoTSlave: IoTSlave.o is ready: " + iotSlave.recvAck());
462                 //iotSlave.sendFile("../", "LifxLightBulb.so");
463                 //iotSlave.sendFile("../", "LightBulb_Skeleton.so");
464                 //iotSlave.sendFile("../", "LifxLightBulb.zip");
465                 //iotSlave.sendFile("../", "unzip2.zip");
466                 iotSlave.createObjectCpp();
467                 //iotSlave.createNewIoTSetCpp();
468                 iotSlave.createNewIoTSetCpp("lb_addresses");
469                 iotSlave.getDeviceIoTSetObjectCpp();
470                 iotSlave.reinitializeIoTSetFieldCpp();
471                 //iotSlave.endSessionCpp();
472
473                 // =========================================
474                 // Continue with main object
475                 iotSlaveMain.createMainObjectCpp();
476                 iotSlaveMain.createNewIoTSetCpp("lifx_light_bulb");
477                 iotSlaveMain.getIoTSetObjectCpp();
478                 iotSlaveMain.reinitializeIoTSetFieldCpp();
479                 iotSlaveMain.invokeInitMethodCpp();
480                 iotSlaveMain.endSessionCpp();
481
482                 // Send message to create a main object
483                 /*commCode = IoTCommCode.CREATE_MAIN_OBJECT;
484                 intCode = commCode.ordinal();
485                 iotSlave.sendInteger(intCode);
486                 //RuntimeOutput.print("IoTSlave: Send request to create a main object: " + strObjName, BOOL_VERBOSE);
487                 System.out.println("IoTSlave: Send request to create a main object: " + strObjName);
488                 //RuntimeOutput.print("IoTSlave: IoTSlave.o is ready: " + strAck, BOOL_VERBOSE);
489                 System.out.println("IoTSlave: IoTSlave.o is ready: " + strAck);*/
490
491                 //Thread.sleep(1000);
492
493         }
494 }