1 package iotruntime.slave;
4 import iotruntime.zigbee.*;
5 import iotruntime.messages.*;
6 import iotruntime.master.RuntimeOutput;
10 import java.io.FileInputStream;
11 import java.io.FileOutputStream;
12 import java.io.ObjectInputStream;
13 import java.io.ObjectOutputStream;
14 import java.io.InputStream;
15 import java.io.OutputStream;
16 import java.io.IOException;
17 import java.io.FileNotFoundException;
18 import java.lang.ClassNotFoundException;
19 import java.lang.Class;
20 import java.lang.reflect.*;
21 import java.lang.ClassLoader;
22 import java.net.InetAddress;
23 import java.net.Socket;
24 import java.net.UnknownHostException;
26 import java.net.URLClassLoader;
27 import java.rmi.registry.LocateRegistry;
28 import java.rmi.registry.Registry;
29 import java.rmi.Remote;
30 import java.rmi.RemoteException;
31 import java.rmi.AlreadyBoundException;
32 import java.rmi.NotBoundException;
33 import java.rmi.server.UnicastRemoteObject;
34 import java.util.Arrays;
35 import java.util.Properties;
36 import java.util.HashMap;
40 import net.lingala.zip4j.exception.ZipException;
41 import net.lingala.zip4j.core.ZipFile;
43 /** Class IoTSlave is run by IoTMaster on a different JVM's.
44 * It needs to respond to IoTMaster's commands
46 * @author Rahmadi Trimananda <rahmadi.trimananda @ uci.edu>
50 public class IoTSlave {
53 * IoTSlave class properties
55 private Message sIoTMasterMsg;
56 private String sIoTMasterHostAdd;
57 private String sMainObjectName;
59 private int iRMIRegPort;
60 private int iRMIStubPort;
61 private String strFieldName;
62 private Class<?> clsMain;
63 private Object objMainCls;
64 private Object iRelFirstObject;
65 private Object iRelSecondObject;
66 private Socket socket;
67 private ObjectOutputStream outStream;
68 private ObjectInputStream inStream;
69 private Map<String,Object> mapObjNameStub;
72 * IoTSet object, e.g. IoTSet<ProximitySensor> proximity_sensors;
73 * IoTRelation object, e.g. IoTRelation<ProximitySensor, LightBulb> ps_lb_relation;
75 private ISet<Object> isetObject;
76 private IoTSet<Object> iotsetObject;
77 private IRelation<Object,Object> irelObject;
78 private IoTRelation<Object,Object> iotrelObject;
80 // Constants that are to be extracted from config file
81 private static String STR_JAR_FILE_PATH;
82 private static String STR_OBJ_CLS_PFX;
83 private static String STR_INTERFACE_PFX;
84 private static String SKEL_CLASS_SUFFIX;
85 private static String STUB_CLASS_SUFFIX;
86 private static boolean BOOL_VERBOSE;
87 private static boolean CAPAB_BASED_RMI;
90 * IoTSlave class constants - not to be changed by users
92 private static final String STR_IOT_SLAVE_NAME = "IoTSlave";
93 private static final String STR_CFG_FILE_EXT = ".config";
94 private static final String STR_CLS_FILE_EXT = ".class";
95 private static final String STR_JAR_FILE_EXT = ".jar";
96 private static final String STR_ZIP_FILE_EXT = ".zip";
97 private static final String STR_UNZIP_DIR = "./";
98 private static final Class<?>[] STR_URL_PARAM = new Class[] {URL.class };
99 private static final String STR_YES = "Yes";
100 private static final String STR_NO = "No";
106 public IoTSlave(String[] argInp) {
108 sIoTMasterMsg = null;
109 sIoTMasterHostAdd = argInp[0];
110 iComPort = Integer.parseInt(argInp[1]);
111 iRMIRegPort = Integer.parseInt(argInp[2]);
112 iRMIStubPort = Integer.parseInt(argInp[3]);
113 sMainObjectName = null;
121 iRelFirstObject = null;
122 iRelSecondObject = null;
126 mapObjNameStub = new HashMap<String,Object>();
128 STR_JAR_FILE_PATH = null;
129 STR_OBJ_CLS_PFX = null;
130 STR_INTERFACE_PFX = null;
131 SKEL_CLASS_SUFFIX = null;
132 STUB_CLASS_SUFFIX = null;
133 BOOL_VERBOSE = false;
134 CAPAB_BASED_RMI = false;
138 * A method to initialize constants from config file
142 private void parseIoTSlaveConfigFile() {
143 // Parse configuration file
144 Properties prop = new Properties();
145 String strCfgFileName = STR_IOT_SLAVE_NAME + STR_CFG_FILE_EXT;
146 File file = new File(strCfgFileName);
148 FileInputStream fis = new FileInputStream(file);
150 } catch (IOException ex) {
151 System.out.println("IoTMaster: Error reading config file: " + strCfgFileName);
152 ex.printStackTrace();
154 System.out.println("IoTMaster: Extracting information from config file: " + strCfgFileName);
155 // Initialize constants from config file
156 STR_JAR_FILE_PATH = prop.getProperty("JAR_FILE_PATH");
157 STR_OBJ_CLS_PFX = prop.getProperty("OBJECT_CLASS_PREFIX");
158 STR_INTERFACE_PFX = prop.getProperty("INTERFACE_PREFIX");
159 SKEL_CLASS_SUFFIX = prop.getProperty("SKEL_CLASS_SUFFIX");
160 STUB_CLASS_SUFFIX = prop.getProperty("STUB_CLASS_SUFFIX");
161 if (prop.getProperty("VERBOSE").equals(STR_YES)) {
164 if (prop.getProperty("CAPAB_BASED_RMI").equals(STR_YES)) {
165 CAPAB_BASED_RMI = true;
168 System.out.println("JAR_FILE_PATH=" + STR_JAR_FILE_PATH);
169 System.out.println("OBJECT_CLASS_PREFIX=" + STR_OBJ_CLS_PFX);
170 System.out.println("INTERFACE_PREFIX=" + STR_INTERFACE_PFX);
171 System.out.println("SKEL_CLASS_SUFFIX=" + SKEL_CLASS_SUFFIX);
172 System.out.println("STUB_CLASS_SUFFIX=" + STUB_CLASS_SUFFIX);
173 System.out.println("CAPAB_BASED_RMI=" + CAPAB_BASED_RMI);
174 System.out.println("IoTMaster: Information extracted successfully!");
178 * Adds the content pointed by the URL to the classpath dynamically at runtime (hack!!!)
180 * @param url the URL pointing to the content to be added
181 * @throws IOException
182 * @see <a href="http://stackoverflow.com/questions/60764/how-should-i-load-jars-dynamically-at-runtime</a>
184 private static void addURL(URL url) throws IOException {
186 URLClassLoader sysloader = (URLClassLoader)ClassLoader.getSystemClassLoader();
187 Class<?> sysclass = URLClassLoader.class;
191 Method method = sysclass.getDeclaredMethod("addURL", STR_URL_PARAM);
192 method.setAccessible(true);
193 method.invoke(sysloader,new Object[] { url });
195 } catch (Throwable t) {
198 throw new IOException("IoTSlave: Could not add URL to system classloader!");
203 * A private method to create object
207 private void createCapabBasedRMIJava(MessageCreateObject sMessage) throws
208 ClassNotFoundException, NoSuchMethodException, UnknownHostException {
211 System.out.println("\n\nDEBUG: Create capab based RMI here!");
212 System.out.println("DEBUG: sMessage host address: " + sMessage.getHostAddress());
213 System.out.println("DEBUG: sMessage object class: " + sMessage.getObjectClass());
214 System.out.println("DEBUG: sMessage object name: " + sMessage.getObjectName());
215 System.out.println("DEBUG: sMessage interface name: " + sMessage.getObjectInterfaceName());
216 System.out.println("DEBUG: sMessage reg port: " + sMessage.getRMIRegPort());
217 System.out.println("DEBUG: sMessage stub port: " + sMessage.getRMIStubPort());
218 System.out.println("DEBUG: sMessage object fields: " + Arrays.toString(sMessage.getObjectFields()));
219 System.out.println("DEBUG: sMessage object fields: " + Arrays.toString(sMessage.getObjectFldCls()));
220 System.out.println("\n\n");
222 // Instantiate the skeleton and put in the object
223 String strObjSkelName = STR_OBJ_CLS_PFX + "." + sMessage.getObjectClass() +
224 "." + sMessage.getObjectInterfaceName() + SKEL_CLASS_SUFFIX;
225 RuntimeOutput.print("IoTSlave: Skeleton object: " + strObjSkelName, BOOL_VERBOSE);
226 Class<?> clsSkel = Class.forName(strObjSkelName);
227 Class<?> clsInt = Class.forName(STR_OBJ_CLS_PFX + "." + STR_INTERFACE_PFX +
228 "." + sMessage.getObjectInterfaceName());
229 //Class[] clsSkelParams = { clsInt, String.class, int.class }; // Port number is integer
230 Class[] clsSkelParams = { clsInt, int.class, int.class }; // Port number is integer
231 Constructor<?> objSkelCons = clsSkel.getDeclaredConstructor(clsSkelParams);
232 //String callbackAddress = InetAddress.getLocalHost().getHostAddress(); // Callback address is this machine's address
233 //Object objSkelParams[] = { objMainCls, callbackAddress, iRMIStubPort };
234 Object objSkelParams[] = { objMainCls, iRMIStubPort, iRMIRegPort };
235 // Create a new thread for each skeleton
236 Thread objectThread = new Thread(new Runnable() {
239 Object objSkel = objSkelCons.newInstance(objSkelParams);
240 } catch (InstantiationException |
241 IllegalAccessException |
242 InvocationTargetException ex) {
243 ex.printStackTrace();
247 objectThread.start();
248 RuntimeOutput.print("IoTSlave: Done generating object!", BOOL_VERBOSE);
252 * A private method to create object
256 private void createObject() throws IOException,
257 ClassNotFoundException, NoSuchMethodException, InstantiationException,
258 RemoteException, AlreadyBoundException, IllegalAccessException,
259 InvocationTargetException {
262 System.out.println("\n\nDEBUG: CREATE DRIVER OBJECT!!!\n\n");
264 // Translating into the actual Message class
265 MessageCreateObject sMessage = (MessageCreateObject) sIoTMasterMsg;
266 // Instantiate object using reflection
267 String strObjClassName = STR_OBJ_CLS_PFX + "." + sMessage.getObjectClass() +
268 "." + sMessage.getObjectClass();
269 File file = new File(STR_JAR_FILE_PATH + sMessage.getObjectClass() + STR_JAR_FILE_EXT);
270 RuntimeOutput.print("IoTSlave: DEBUG print path: " + STR_JAR_FILE_PATH +
271 sMessage.getObjectClass() + STR_JAR_FILE_EXT, BOOL_VERBOSE);
272 addURL(file.toURI().toURL());
273 clsMain = Class.forName(strObjClassName);
274 Class[] clsParams = sMessage.getObjectFldCls();
275 Constructor<?> ct = clsMain.getDeclaredConstructor(clsParams);
276 Object objParams[] = sMessage.getObjectFields();
277 objMainCls = ct.newInstance(objParams);
278 RuntimeOutput.print("IoTSlave: Creating RMI skeleton: " +
279 sMessage.getHostAddress() + ":" + sMessage.getRMIRegPort() +
280 " with RMI stub port: " + iRMIStubPort, BOOL_VERBOSE);
281 if (CAPAB_BASED_RMI) {
282 // Use the new capability-based RMI in Java
283 createCapabBasedRMIJava(sMessage);
285 // Register object to RMI - there are 2 ports: RMI registry port and RMI stub port
286 Object objStub = (Object)
287 UnicastRemoteObject.exportObject((Remote) objMainCls, iRMIStubPort);
288 Registry registry = LocateRegistry.createRegistry(iRMIRegPort);
289 registry.bind(sMessage.getObjectName(), (Remote) objStub);
291 outStream.writeObject(new MessageSimple(IoTCommCode.ACKNOWLEDGED));
292 RuntimeOutput.print("IoTSlave: Registering object via RMI!", BOOL_VERBOSE);
298 * A private method to transfer file
302 private void transferFile() throws IOException,
303 UnknownHostException, FileNotFoundException {
305 // Translating into the actual Message class
306 MessageSendFile sMessage = (MessageSendFile) sIoTMasterMsg;
308 // Send back the received message as acknowledgement
309 outStream.writeObject(new MessageSimple(IoTCommCode.ACKNOWLEDGED));
311 // Write file to the current location
312 Socket filesocket = new Socket(sIoTMasterHostAdd, iComPort);
313 InputStream inFileStream = filesocket.getInputStream();
314 OutputStream outFileStream = new FileOutputStream(sMessage.getFileName());
315 byte[] bytFile = new byte[Math.toIntExact(sMessage.getFileSize())];
318 while ((iCount = inFileStream.read(bytFile)) > 0) {
319 outFileStream.write(bytFile, 0, iCount);
321 // Unzip if this is a zipped file
322 if (sMessage.getFileName().contains(STR_ZIP_FILE_EXT)) {
323 RuntimeOutput.print("IoTSlave: Unzipping file: " + sMessage.getFileName(), BOOL_VERBOSE);
325 ZipFile zipFile = new ZipFile(sMessage.getFileName());
326 zipFile.extractAll(STR_UNZIP_DIR);
327 } catch (ZipException ex) {
328 System.out.println("IoTSlave: Error in unzipping file!");
329 ex.printStackTrace();
332 outStream.writeObject(new MessageSimple(IoTCommCode.ACKNOWLEDGED));
333 RuntimeOutput.print("IoTSlave: Receiving file transfer!", BOOL_VERBOSE);
337 * A private method to create a main object
341 private void createMainObject() throws IOException,
342 ClassNotFoundException, InstantiationException, IllegalAccessException,
343 InvocationTargetException {
345 // Translating into the actual Message class
346 MessageCreateMainObject sMessage = (MessageCreateMainObject) sIoTMasterMsg;
349 System.out.println("\n\nDEBUG: CREATE MAIN OBJECT!!!");
350 System.out.println("DEBUG: sMessage object name: " + sMessage.getObjectName());
352 // Getting controller class
353 File file = new File(STR_JAR_FILE_PATH + sMessage.getObjectName() + STR_JAR_FILE_EXT);
354 RuntimeOutput.print("IoTSlave: DEBUG print path: " + STR_JAR_FILE_PATH +
355 sMessage.getObjectName() + STR_JAR_FILE_EXT, BOOL_VERBOSE);
356 addURL(file.toURI().toURL());
357 // We will always have a package name <object name>.<object name>
358 // e.g. SmartLightsController.SmartLightsController
359 sMainObjectName = sMessage.getObjectName();
360 clsMain = Class.forName(sMainObjectName + "." + sMainObjectName);
361 objMainCls = clsMain.newInstance();
363 // Send back the received message as acknowledgement
364 outStream.writeObject(new MessageSimple(IoTCommCode.ACKNOWLEDGED));
365 RuntimeOutput.print("IoTSlave: Instantiating main controller/device class "
366 + sMessage.getObjectName(), BOOL_VERBOSE);
371 * A private method to create a new IoTSet
375 private void createNewIoTSet() throws IOException {
377 // Translating into the actual Message class
378 MessageCreateSetRelation sMessage = (MessageCreateSetRelation) sIoTMasterMsg;
381 System.out.println("\n\nDEBUG: CREATE NEW IOT SET!!!");
382 System.out.println("DEBUG: sMessage object field name: " + sMessage.getObjectFieldName());
384 // Initialize field name
385 strFieldName = sMessage.getObjectFieldName();
386 RuntimeOutput.print("IoTSlave: Setting up field " + strFieldName, BOOL_VERBOSE);
388 // Creating a new IoTSet object
389 isetObject = new ISet<Object>();
391 // Send back the received message as acknowledgement
392 outStream.writeObject(new MessageSimple(IoTCommCode.ACKNOWLEDGED));
393 RuntimeOutput.print("IoTSlave: Creating a new IoTSet object!", BOOL_VERBOSE);
398 * A private method to create a new IoTRelation
402 private void createNewIoTRelation() throws IOException {
404 // Translating into the actual Message class
405 MessageCreateSetRelation sMessage = (MessageCreateSetRelation) sIoTMasterMsg;
408 System.out.println("\n\nDEBUG: CREATE NEW IOT RELATION!!!");
409 System.out.println("DEBUG: sMessage object field name: " + sMessage.getObjectFieldName());
411 // Initialize field name
412 strFieldName = sMessage.getObjectFieldName();
413 RuntimeOutput.print("IoTSlave: Setting up field " + strFieldName, BOOL_VERBOSE);
415 // Creating a new IoTRelation object
416 irelObject = new IRelation<Object,Object>();
418 // Send back the received message as acknowledgement
419 outStream.writeObject(new MessageSimple(IoTCommCode.ACKNOWLEDGED));
420 RuntimeOutput.print("IoTSlave: Creating a new IoTRelation object!", BOOL_VERBOSE);
425 * A private method to get an object from the registry
429 private Object getObjectFromRegistry() throws RemoteException,
430 ClassNotFoundException, NotBoundException {
432 // Translating into the actual Message class
433 MessageGetObject sMessage = (MessageGetObject) sIoTMasterMsg;
435 // Locate RMI registry and add object into IoTSet
437 LocateRegistry.getRegistry(sMessage.getHostAddress(), sMessage.getRMIRegPort());
438 RuntimeOutput.print("IoTSlave: Looking for RMI registry: " +
439 sMessage.getHostAddress() + ":" + sMessage.getRMIRegPort() +
440 " with RMI stub port: " + sMessage.getRMIStubPort(), BOOL_VERBOSE);
441 Object stubObj = registry.lookup(sMessage.getObjectName());
442 RuntimeOutput.print("IoTSlave: Looking for object name: " + sMessage.getObjectName(), BOOL_VERBOSE);
444 // Class conversion to interface class of this class,
445 // e.g. ProximitySensorImpl has ProximitySensor interface
446 String strObjClassInterfaceName = STR_OBJ_CLS_PFX + "." + STR_INTERFACE_PFX + "." +
447 sMessage.getObjectInterfaceName();
448 Class<?> clsInf = Class.forName(strObjClassInterfaceName);
449 Object stubObjConv = clsInf.cast(stubObj);
455 * A private method to get an object and create a stub
457 * This is using the capability-based RMI skeleton and stub scheme
461 private Object getObjectFromStub() throws RemoteException,
462 ClassNotFoundException, NoSuchMethodException, InstantiationException,
463 IllegalAccessException, NotBoundException, InvocationTargetException, UnknownHostException {
465 // Translating into the actual Message class
466 MessageGetObject sMessage = (MessageGetObject) sIoTMasterMsg;
468 System.out.println("DEBUG: sMessage host address: " + sMessage.getHostAddress());
469 System.out.println("DEBUG: sMessage object class: " + sMessage.getObjectClass());
470 System.out.println("DEBUG: sMessage object name: " + sMessage.getObjectName());
471 System.out.println("DEBUG: sMessage interface name: " + sMessage.getObjectInterfaceName());
472 System.out.println("DEBUG: sMessage reg port: " + sMessage.getRMIRegPort());
473 System.out.println("DEBUG: sMessage stub port: " + sMessage.getRMIStubPort());
474 System.out.println("DEBUG: sMessage callback ports: " + Arrays.toString(sMessage.getRMICallbackPorts()));
475 System.out.println("\n\n");
477 Object stubObjConv = null;
478 String strObjectName = sMessage.getObjectName();
479 String strObjClassInterfaceName = STR_OBJ_CLS_PFX + "." + STR_INTERFACE_PFX + "." +
480 sMessage.getObjectStubInterfaceName();
481 Class<?> clsInf = Class.forName(strObjClassInterfaceName);
482 if (mapObjNameStub.containsKey(strObjectName)) {
483 RuntimeOutput.print("IoTSlave: Getting back object on slave: " + strObjectName, BOOL_VERBOSE);
484 stubObjConv = clsInf.cast(mapObjNameStub.get(strObjectName));
486 // Instantiate the stub and put in the object
487 String strObjStubName = sMainObjectName + "." + sMessage.getObjectStubInterfaceName() + STUB_CLASS_SUFFIX;
488 Class<?> clsStub = Class.forName(strObjStubName); // Port number is integer
489 //Class[] clsStubParams = { int.class, String.class, String.class, int.class, int[].class };
490 Class[] clsStubParams = { int.class, int.class, int.class, int.class, String.class, int.class };
491 Constructor<?> objStubCons = clsStub.getDeclaredConstructor(clsStubParams);
492 //Integer[] portsInteger = sMessage.getRMICallbackPorts();
493 //int[] ports = Arrays.stream(portsInteger).mapToInt(Integer::intValue).toArray();
496 //String callbackAddress = InetAddress.getLocalHost().getHostAddress(); // Callback address is this machine's address
497 //Object objStubParams[] = { sMessage.getRMIStubPort(), sMessage.getHostAddress(), callbackAddress, rev, ports };
498 Object objStubParams[] = { 0, 0, sMessage.getRMIStubPort(), sMessage.getRMIRegPort(), sMessage.getHostAddress(), rev };
499 RuntimeOutput.print("IoTSlave: Creating RMI stub: " +
500 sMessage.getHostAddress() + ":" + sMessage.getRMIRegPort() +
501 " and RMI stub port: " + sMessage.getRMIStubPort(), BOOL_VERBOSE);
502 Object stubObj = objStubCons.newInstance(objStubParams);
503 // Class conversion to interface class of this class,
504 // e.g. ProximitySensorImpl has ProximitySensor interface
505 RuntimeOutput.print("IoTSlave: Registering new stub object: " + strObjectName, BOOL_VERBOSE);
506 mapObjNameStub.put(strObjectName, stubObj);
507 stubObjConv = clsInf.cast(stubObj);
514 * A private method to get an IoTSet object
518 private void getIoTSetObject() throws IOException,
519 ClassNotFoundException, RemoteException, NotBoundException, NoSuchMethodException,
520 InstantiationException, IllegalAccessException, InvocationTargetException {
523 System.out.println("\n\nDEBUG: GET IOT SET OBJECT!!!");
525 Object objRegistry = null;
527 objRegistry = getObjectFromStub();
529 objRegistry = getObjectFromRegistry();
530 isetObject.add(objRegistry);
531 RuntimeOutput.print("IoTSlave: This IoTSet now has: " + isetObject.size() + " entry(s)", BOOL_VERBOSE);
533 // Send back the received message as acknowledgement
534 outStream.writeObject(new MessageSimple(IoTCommCode.ACKNOWLEDGED));
535 RuntimeOutput.print("IoTSlave: Getting an object for IoTSet!", BOOL_VERBOSE);
539 * A private method to get an IoTRelation first object
543 private void getIoTRelationFirstObject() throws IOException,
544 ClassNotFoundException, RemoteException, NotBoundException, NoSuchMethodException,
545 InstantiationException, IllegalAccessException, InvocationTargetException {
548 System.out.println("\n\nDEBUG: GET IOT RELATION FIRST OBJECT!!!");
550 Object objRegistry = null;
552 objRegistry = getObjectFromStub();
554 objRegistry = getObjectFromRegistry();
555 iRelFirstObject = objRegistry;
557 // Send back the received message as acknowledgement
558 outStream.writeObject(new MessageSimple(IoTCommCode.ACKNOWLEDGED));
559 RuntimeOutput.print("IoTSlave: Getting a first object for IoTRelation!", BOOL_VERBOSE);
564 * A private method to get an IoTRelation second object
568 private void getIoTRelationSecondObject() throws IOException,
569 ClassNotFoundException, RemoteException, NotBoundException, NoSuchMethodException,
570 InstantiationException, IllegalAccessException, InvocationTargetException {
573 System.out.println("\n\nDEBUG: GET IOT RELATION SECOND OBJECT!!!");
575 Object objRegistry = null;
577 objRegistry = getObjectFromStub();
579 objRegistry = getObjectFromRegistry();
580 iRelSecondObject = objRegistry;
582 // Now add the first and the second object into IoTRelation
583 irelObject.put(iRelFirstObject, iRelSecondObject);
584 RuntimeOutput.print("IoTSlave: This IoTRelation now has: " + irelObject.size() + " entry(s)", BOOL_VERBOSE);
586 // Send back the received message as acknowledgement
587 outStream.writeObject(new MessageSimple(IoTCommCode.ACKNOWLEDGED));
588 RuntimeOutput.print("IoTSlave: Getting a second object for IoTRelation!", BOOL_VERBOSE);
593 * A private method to reinitialize IoTSet field
597 private void reinitializeIoTSetField() throws IOException,
598 IllegalAccessException, NoSuchFieldException {
600 // Reinitialize IoTSet field after getting all the objects
601 iotsetObject = new IoTSet<Object>(isetObject.values());
604 System.out.println("\n\nDEBUG: REINITIALIZE IOT SET FIELD!!!");
605 System.out.println("DEBUG: Field name: " + strFieldName + "\n\n");
607 // Private fields need getDeclaredField(), while public fields use getField()
608 Field fld = clsMain.getDeclaredField(strFieldName);
609 boolean bAccess = fld.isAccessible();
610 fld.setAccessible(true);
611 fld.set(objMainCls, iotsetObject);
612 fld.setAccessible(bAccess);
613 RuntimeOutput.print("IoTSlave: Reinitializing field " + strFieldName, BOOL_VERBOSE);
615 // Send back the received message as acknowledgement
616 outStream.writeObject(new MessageSimple(IoTCommCode.ACKNOWLEDGED));
617 RuntimeOutput.print("IoTSlave: Reinitializing IoTSet field!", BOOL_VERBOSE);
622 * A private method to reinitialize IoTRelation field
626 private void reinitializeIoTRelationField() throws IOException,
627 IllegalAccessException, NoSuchFieldException {
629 // Reinitialize IoTSet field after getting all the objects
630 iotrelObject = new IoTRelation<Object,Object>(irelObject.relationMap(), irelObject.size());
633 System.out.println("\n\nDEBUG: REINITIALIZE IOT RELATION FIELD!!!");
634 System.out.println("DEBUG: Field name: " + strFieldName + "\n\n");
636 // Private fields need getDeclaredField(), while public fields use getField()
637 Field fld = clsMain.getDeclaredField(strFieldName);
638 boolean bAccess = fld.isAccessible();
639 fld.setAccessible(true);
640 fld.set(objMainCls, iotrelObject);
641 fld.setAccessible(bAccess);
642 RuntimeOutput.print("IoTSlave: Reinitializing field " + strFieldName, BOOL_VERBOSE);
644 // Send back the received message as acknowledgement
645 outStream.writeObject(new MessageSimple(IoTCommCode.ACKNOWLEDGED));
646 RuntimeOutput.print("IoTSlave: Reinitializing IoTRelation field!", BOOL_VERBOSE);
651 * A private method to get the device driver object's IoTSet
653 * This is to handle device driver's IoTSet that contains IP addresses
657 private void getDeviceIoTSetObject() throws IOException {
659 // Translating into the actual Message class
660 MessageGetDeviceObject sMessage = (MessageGetDeviceObject) sIoTMasterMsg;
663 System.out.println("\n\nDEBUG: GET DEVICE IOT SET OBJECT!!!");
664 System.out.println("DEBUG: sMessage host address: " + sMessage.getHostAddress());
665 System.out.println("DEBUG: sMessage source port: " + sMessage.getSourceDeviceDriverPort());
666 System.out.println("DEBUG: sMessage destination port: " + sMessage.getDestinationDeviceDriverPort());
667 System.out.println("DEBUG: sMessage source wild card: " + sMessage.isSourcePortWildCard());
668 System.out.println("DEBUG: sMessage desination wild card: " + sMessage.isDestinationPortWildCard() + "\n\n");
670 // Get IoTSet objects for IP address set on device driver/controller
671 IoTDeviceAddress objDeviceAddress = new IoTDeviceAddress(sMessage.getHostAddress(),
672 sMessage.getSourceDeviceDriverPort(),
673 sMessage.getDestinationDeviceDriverPort(),
674 sMessage.isSourcePortWildCard(),
675 sMessage.isDestinationPortWildCard());
676 RuntimeOutput.print("IoTSlave: Device address transferred: " + sMessage.getHostAddress(), BOOL_VERBOSE);
677 isetObject.add(objDeviceAddress);
678 RuntimeOutput.print("IoTSlave: This IoTSet now has: " + isetObject.size() + " entry(s)", BOOL_VERBOSE);
680 // Send back the received message as acknowledgement
681 outStream.writeObject(new MessageSimple(IoTCommCode.ACKNOWLEDGED));
682 RuntimeOutput.print("IoTSlave: Getting an object for IoTSet!", BOOL_VERBOSE);
687 * A private method to get the device driver object's IoTSet for IoTZigbeeAddress
689 * This is to handle device driver's IoTSet that contains Zigbee addresses
693 private void getZBDevIoTSetObject() throws IOException {
695 // Translating into the actual Message class
696 MessageGetSimpleDeviceObject sMessage = (MessageGetSimpleDeviceObject) sIoTMasterMsg;
699 System.out.println("\n\nDEBUG: GET ZIGBEE DEVICE IOT SET OBJECT!!!");
700 System.out.println("DEBUG: sMessage host address: " + sMessage.getHostAddress() + "\n\n");
702 // Get IoTSet objects for IP address set on device driver/controller
703 IoTZigbeeAddress objZBDevAddress = new IoTZigbeeAddress(sMessage.getHostAddress());
704 RuntimeOutput.print("IoTSlave: Device address transferred: " + sMessage.getHostAddress(), BOOL_VERBOSE);
705 isetObject.add(objZBDevAddress);
706 RuntimeOutput.print("IoTSlave: This IoTSet now has: " + isetObject.size() + " entry(s)", BOOL_VERBOSE);
708 // Send back the received message as acknowledgement
709 outStream.writeObject(new MessageSimple(IoTCommCode.ACKNOWLEDGED));
710 RuntimeOutput.print("IoTSlave: Getting an object for IoTSet!", BOOL_VERBOSE);
716 * A private method to get IoTAddress objects for IoTSet
720 private void getAddIoTSetObject() throws IOException {
722 // Translating into the actual Message class
723 MessageGetSimpleDeviceObject sMessage = (MessageGetSimpleDeviceObject) sIoTMasterMsg;
726 System.out.println("\n\nDEBUG: GET ADD IOT SET OBJECT!!!");
727 System.out.println("DEBUG: sMessage host address: " + sMessage.getHostAddress() + "\n\n");
729 // Get IoTSet objects for IP address set on device driver/controller
730 IoTAddress objAddress = new IoTAddress(sMessage.getHostAddress());
731 RuntimeOutput.print("IoTSlave: Address transferred: " + sMessage.getHostAddress(), BOOL_VERBOSE);
732 isetObject.add(objAddress);
733 RuntimeOutput.print("IoTSlave: This IoTSet now has: " + isetObject.size() + " entry(s)", BOOL_VERBOSE);
734 // Send back the received message as acknowledgement
735 outStream.writeObject(new MessageSimple(IoTCommCode.ACKNOWLEDGED));
736 RuntimeOutput.print("IoTSlave: Getting an object for IoTSet!", BOOL_VERBOSE);
741 * A private method to invoke init() method in the controller object
745 private void invokeInitMethod() throws IOException {
748 System.out.println("\n\nDEBUG: INVOKE INIT METHOD!!!\n\n");
753 Class<?> noparams[] = {};
754 Method method = clsMain.getDeclaredMethod("init", noparams);
755 method.invoke(objMainCls);
756 } catch (NoSuchMethodException |
757 IllegalAccessException |
758 InvocationTargetException ex) {
759 System.out.println("IoTSlave: Exception: "
761 ex.printStackTrace();
766 // Start a new thread to invoke the init function
767 RuntimeOutput.print("IoTSlave: Invoke init method! Job done!", BOOL_VERBOSE);
769 // Send back the received message as acknowledgement
770 outStream.writeObject(new MessageSimple(IoTCommCode.ACKNOWLEDGED));
775 * A public method to do communication with IoTMaster
777 * @params iIndex Integer index
780 public void commIoTMaster() {
784 // Loop, receive and process commands from IoTMaster
785 socket = new Socket(sIoTMasterHostAdd, iComPort);
786 outStream = new ObjectOutputStream(socket.getOutputStream());
787 inStream = new ObjectInputStream(socket.getInputStream());
791 // Get the first payload
792 RuntimeOutput.print("IoTSlave: Slave waiting...", BOOL_VERBOSE);
793 sIoTMasterMsg = (Message) inStream.readObject();
795 // Check payload message from IoTMaster and make a decision
796 switch (sIoTMasterMsg.getMessage()) {
806 case CREATE_MAIN_OBJECT:
810 case CREATE_NEW_IOTSET:
814 case CREATE_NEW_IOTRELATION:
815 createNewIoTRelation();
818 case GET_IOTSET_OBJECT:
822 case GET_IOTRELATION_FIRST_OBJECT:
823 getIoTRelationFirstObject();
826 case GET_IOTRELATION_SECOND_OBJECT:
827 getIoTRelationSecondObject();
830 case REINITIALIZE_IOTSET_FIELD:
831 reinitializeIoTSetField();
834 case REINITIALIZE_IOTRELATION_FIELD:
835 reinitializeIoTRelationField();
838 case GET_DEVICE_IOTSET_OBJECT:
839 getDeviceIoTSetObject();
842 case GET_ZB_DEV_IOTSET_OBJECT:
843 getZBDevIoTSetObject();
846 case GET_ADD_IOTSET_OBJECT:
847 getAddIoTSetObject();
850 case INVOKE_INIT_METHOD:
862 RuntimeOutput.print("IoTSlave: Session ends!", BOOL_VERBOSE);
864 // Closing streams and end session
868 RuntimeOutput.print("IoTSlave: Closing!", BOOL_VERBOSE);
869 // We have to continuously loop because we are preserving our stubs and skeletons
872 } catch (IOException |
873 ClassNotFoundException |
874 NoSuchMethodException |
875 InstantiationException |
876 AlreadyBoundException |
877 IllegalAccessException |
878 InvocationTargetException |
880 NoSuchFieldException ex) {
881 System.out.println("IoTSlave: Exception: "
883 ex.printStackTrace();
887 public static void main(String args[]) {
888 IoTSlave iotSlave = new IoTSlave(args);
889 iotSlave.parseIoTSlaveConfigFile();
890 iotSlave.commIoTMaster();