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.Properties;
35 import java.util.HashMap;
39 import net.lingala.zip4j.exception.ZipException;
40 import net.lingala.zip4j.core.ZipFile;
42 /** Class IoTSlave is run by IoTMaster on a different JVM's.
43 * It needs to respond to IoTMaster's commands
45 * @author Rahmadi Trimananda <rahmadi.trimananda @ uci.edu>
49 public class IoTSlave {
52 * IoTSlave class properties
54 private Message sIoTMasterMsg;
55 private String sIoTMasterHostAdd;
56 private String sMainObjectName;
58 private int iRMIRegPort;
59 private int iRMIStubPort;
60 private String strFieldName;
61 private Class<?> clsMain;
62 private Object objMainCls;
63 private Object iRelFirstObject;
64 private Object iRelSecondObject;
65 private Socket socket;
66 private ObjectOutputStream outStream;
67 private ObjectInputStream inStream;
70 * IoTSet object, e.g. IoTSet<ProximitySensor> proximity_sensors;
71 * IoTRelation object, e.g. IoTRelation<ProximitySensor, LightBulb> ps_lb_relation;
73 private ISet<Object> isetObject;
74 private IoTSet<Object> iotsetObject;
75 private IRelation<Object,Object> irelObject;
76 private IoTRelation<Object,Object> iotrelObject;
78 // Constants that are to be extracted from config file
79 private static String STR_JAR_FILE_PATH;
80 private static String STR_OBJ_CLS_PFX;
81 private static String STR_INTERFACE_PFX;
82 private static String SKEL_CLASS_SUFFIX;
83 private static String STUB_CLASS_SUFFIX;
84 private static boolean BOOL_VERBOSE;
85 private static boolean CAPAB_BASED_RMI;
88 * IoTSlave class constants - not to be changed by users
90 private static final String STR_IOT_SLAVE_NAME = "IoTSlave";
91 private static final String STR_CFG_FILE_EXT = ".config";
92 private static final String STR_CLS_FILE_EXT = ".class";
93 private static final String STR_JAR_FILE_EXT = ".jar";
94 private static final String STR_ZIP_FILE_EXT = ".zip";
95 private static final String STR_UNZIP_DIR = "./";
96 private static final Class<?>[] STR_URL_PARAM = new Class[] {URL.class };
97 private static final String STR_YES = "Yes";
98 private static final String STR_NO = "No";
104 public IoTSlave(String[] argInp) {
106 sIoTMasterMsg = null;
107 sIoTMasterHostAdd = argInp[0];
108 iComPort = Integer.parseInt(argInp[1]);
109 iRMIRegPort = Integer.parseInt(argInp[2]);
110 iRMIStubPort = Integer.parseInt(argInp[3]);
111 sMainObjectName = null;
119 iRelFirstObject = null;
120 iRelSecondObject = null;
125 STR_JAR_FILE_PATH = null;
126 STR_OBJ_CLS_PFX = null;
127 STR_INTERFACE_PFX = null;
128 SKEL_CLASS_SUFFIX = null;
129 STUB_CLASS_SUFFIX = null;
130 BOOL_VERBOSE = false;
131 CAPAB_BASED_RMI = false;
135 * A method to initialize constants from config file
139 private void parseIoTSlaveConfigFile() {
140 // Parse configuration file
141 Properties prop = new Properties();
142 String strCfgFileName = STR_IOT_SLAVE_NAME + STR_CFG_FILE_EXT;
143 File file = new File(strCfgFileName);
145 FileInputStream fis = new FileInputStream(file);
147 } catch (IOException ex) {
148 System.out.println("IoTMaster: Error reading config file: " + strCfgFileName);
149 ex.printStackTrace();
151 System.out.println("IoTMaster: Extracting information from config file: " + strCfgFileName);
152 // Initialize constants from config file
153 STR_JAR_FILE_PATH = prop.getProperty("JAR_FILE_PATH");
154 STR_OBJ_CLS_PFX = prop.getProperty("OBJECT_CLASS_PREFIX");
155 STR_INTERFACE_PFX = prop.getProperty("INTERFACE_PREFIX");
156 SKEL_CLASS_SUFFIX = prop.getProperty("SKEL_CLASS_SUFFIX");
157 STUB_CLASS_SUFFIX = prop.getProperty("STUB_CLASS_SUFFIX");
158 if (prop.getProperty("VERBOSE").equals(STR_YES)) {
161 if (prop.getProperty("CAPAB_BASED_RMI").equals(STR_YES)) {
162 CAPAB_BASED_RMI = true;
165 System.out.println("JAR_FILE_PATH=" + STR_JAR_FILE_PATH);
166 System.out.println("OBJECT_CLASS_PREFIX=" + STR_OBJ_CLS_PFX);
167 System.out.println("INTERFACE_PREFIX=" + STR_INTERFACE_PFX);
168 System.out.println("SKEL_CLASS_SUFFIX=" + SKEL_CLASS_SUFFIX);
169 System.out.println("STUB_CLASS_SUFFIX=" + STUB_CLASS_SUFFIX);
170 System.out.println("CAPAB_BASED_RMI=" + CAPAB_BASED_RMI);
171 System.out.println("IoTMaster: Information extracted successfully!");
175 * Adds the content pointed by the URL to the classpath dynamically at runtime (hack!!!)
177 * @param url the URL pointing to the content to be added
178 * @throws IOException
179 * @see <a href="http://stackoverflow.com/questions/60764/how-should-i-load-jars-dynamically-at-runtime</a>
181 private static void addURL(URL url) throws IOException {
183 URLClassLoader sysloader = (URLClassLoader)ClassLoader.getSystemClassLoader();
184 Class<?> sysclass = URLClassLoader.class;
188 Method method = sysclass.getDeclaredMethod("addURL", STR_URL_PARAM);
189 method.setAccessible(true);
190 method.invoke(sysloader,new Object[] { url });
192 } catch (Throwable t) {
195 throw new IOException("IoTSlave: Could not add URL to system classloader!");
200 * A private method to create object
204 private void createCapabBasedRMIJava(MessageCreateObject sMessage) throws
205 ClassNotFoundException, NoSuchMethodException {
207 // Instantiate the skeleton and put in the object
208 String strObjSkelName = STR_OBJ_CLS_PFX + "." + sMessage.getObjectClass() +
209 "." + sMessage.getObjectInterfaceName() + SKEL_CLASS_SUFFIX;
210 RuntimeOutput.print("IoTSlave: Skeleton object: " + strObjSkelName, BOOL_VERBOSE);
211 Class<?> clsSkel = Class.forName(strObjSkelName);
212 Class<?> clsInt = Class.forName(STR_OBJ_CLS_PFX + "." + STR_INTERFACE_PFX +
213 "." + sMessage.getObjectInterfaceName());
214 Class[] clsSkelParams = { clsInt, String.class, int.class }; // Port number is integer
215 Constructor<?> objSkelCons = clsSkel.getDeclaredConstructor(clsSkelParams);
216 String callbackAddress = InetAddress.getLocalHost().getHostAddress(); // Callback address is this machine's address
217 Object objSkelParams[] = { objMainCls, callbackAddress, iRMIStubPort };
218 // Create a new thread for each skeleton
219 Thread objectThread = new Thread(new Runnable() {
222 Object objSkel = objSkelCons.newInstance(objSkelParams);
223 } catch (InstantiationException |
224 IllegalAccessException |
225 InvocationTargetException ex) {
226 ex.printStackTrace();
230 objectThread.start();
231 RuntimeOutput.print("IoTSlave: Done generating object!", BOOL_VERBOSE);
235 * A private method to create object
239 private void createObject() throws IOException,
240 ClassNotFoundException, NoSuchMethodException, InstantiationException,
241 RemoteException, AlreadyBoundException, IllegalAccessException,
242 InvocationTargetException {
244 // Translating into the actual Message class
245 MessageCreateObject sMessage = (MessageCreateObject) sIoTMasterMsg;
246 // Instantiate object using reflection
247 String strObjClassName = STR_OBJ_CLS_PFX + "." + sMessage.getObjectClass() +
248 "." + sMessage.getObjectClass();
249 File file = new File(STR_JAR_FILE_PATH + sMessage.getObjectClass() + STR_JAR_FILE_EXT);
250 RuntimeOutput.print("IoTSlave: DEBUG print path: " + STR_JAR_FILE_PATH +
251 sMessage.getObjectClass() + STR_JAR_FILE_EXT, BOOL_VERBOSE);
252 addURL(file.toURI().toURL());
253 clsMain = Class.forName(strObjClassName);
254 Class[] clsParams = sMessage.getObjectFldCls();
255 Constructor<?> ct = clsMain.getDeclaredConstructor(clsParams);
256 Object objParams[] = sMessage.getObjectFields();
257 objMainCls = ct.newInstance(objParams);
258 RuntimeOutput.print("IoTSlave: Creating RMI skeleton: " +
259 sMessage.getHostAddress() + ":" + sMessage.getRMIRegPort() +
260 " with RMI stub port: " + iRMIStubPort, BOOL_VERBOSE);
261 if (CAPAB_BASED_RMI) {
262 // Use the new capability-based RMI in Java
263 createCapabBasedRMIJava(sMessage);
265 // Register object to RMI - there are 2 ports: RMI registry port and RMI stub port
266 Object objStub = (Object)
267 UnicastRemoteObject.exportObject((Remote) objMainCls, iRMIStubPort);
268 Registry registry = LocateRegistry.createRegistry(iRMIRegPort);
269 registry.bind(sMessage.getObjectName(), (Remote) objStub);
271 outStream.writeObject(new MessageSimple(IoTCommCode.ACKNOWLEDGED));
272 RuntimeOutput.print("IoTSlave: Registering object via RMI!", BOOL_VERBOSE);
278 * A private method to transfer file
282 private void transferFile() throws IOException,
283 UnknownHostException, FileNotFoundException {
285 // Translating into the actual Message class
286 MessageSendFile sMessage = (MessageSendFile) sIoTMasterMsg;
288 // Send back the received message as acknowledgement
289 outStream.writeObject(new MessageSimple(IoTCommCode.ACKNOWLEDGED));
291 // Write file to the current location
292 Socket filesocket = new Socket(sIoTMasterHostAdd, iComPort);
293 InputStream inFileStream = filesocket.getInputStream();
294 OutputStream outFileStream = new FileOutputStream(sMessage.getFileName());
295 byte[] bytFile = new byte[Math.toIntExact(sMessage.getFileSize())];
298 while ((iCount = inFileStream.read(bytFile)) > 0) {
299 outFileStream.write(bytFile, 0, iCount);
301 // Unzip if this is a zipped file
302 if (sMessage.getFileName().contains(STR_ZIP_FILE_EXT)) {
303 RuntimeOutput.print("IoTSlave: Unzipping file: " + sMessage.getFileName(), BOOL_VERBOSE);
305 ZipFile zipFile = new ZipFile(sMessage.getFileName());
306 zipFile.extractAll(STR_UNZIP_DIR);
307 } catch (ZipException ex) {
308 System.out.println("IoTSlave: Error in unzipping file!");
309 ex.printStackTrace();
312 outStream.writeObject(new MessageSimple(IoTCommCode.ACKNOWLEDGED));
313 RuntimeOutput.print("IoTSlave: Receiving file transfer!", BOOL_VERBOSE);
317 * A private method to create a main object
321 private void createMainObject() throws IOException,
322 ClassNotFoundException, InstantiationException, IllegalAccessException,
323 InvocationTargetException {
325 // Translating into the actual Message class
326 MessageCreateMainObject sMessage = (MessageCreateMainObject) sIoTMasterMsg;
328 // Getting controller class
329 File file = new File(STR_JAR_FILE_PATH + sMessage.getObjectName() + STR_JAR_FILE_EXT);
330 RuntimeOutput.print("IoTSlave: DEBUG print path: " + STR_JAR_FILE_PATH +
331 sMessage.getObjectName() + STR_JAR_FILE_EXT, BOOL_VERBOSE);
332 addURL(file.toURI().toURL());
333 // We will always have a package name <object name>.<object name>
334 // e.g. SmartLightsController.SmartLightsController
335 sMainObjectName = sMessage.getObjectName();
336 clsMain = Class.forName(sMainObjectName + "." + sMainObjectName);
337 objMainCls = clsMain.newInstance();
339 // Send back the received message as acknowledgement
340 outStream.writeObject(new MessageSimple(IoTCommCode.ACKNOWLEDGED));
341 RuntimeOutput.print("IoTSlave: Instantiating main controller/device class "
342 + sMessage.getObjectName(), BOOL_VERBOSE);
347 * A private method to create a new IoTSet
351 private void createNewIoTSet() throws IOException {
353 // Translating into the actual Message class
354 MessageCreateSetRelation sMessage = (MessageCreateSetRelation) sIoTMasterMsg;
356 // Initialize field name
357 strFieldName = sMessage.getObjectFieldName();
358 RuntimeOutput.print("IoTSlave: Setting up field " + strFieldName, BOOL_VERBOSE);
360 // Creating a new IoTSet object
361 isetObject = new ISet<Object>();
363 // Send back the received message as acknowledgement
364 outStream.writeObject(new MessageSimple(IoTCommCode.ACKNOWLEDGED));
365 RuntimeOutput.print("IoTSlave: Creating a new IoTSet object!", BOOL_VERBOSE);
370 * A private method to create a new IoTRelation
374 private void createNewIoTRelation() throws IOException {
376 // Translating into the actual Message class
377 MessageCreateSetRelation sMessage = (MessageCreateSetRelation) sIoTMasterMsg;
379 // Initialize field name
380 strFieldName = sMessage.getObjectFieldName();
381 RuntimeOutput.print("IoTSlave: Setting up field " + strFieldName, BOOL_VERBOSE);
383 // Creating a new IoTRelation object
384 irelObject = new IRelation<Object,Object>();
386 // Send back the received message as acknowledgement
387 outStream.writeObject(new MessageSimple(IoTCommCode.ACKNOWLEDGED));
388 RuntimeOutput.print("IoTSlave: Creating a new IoTRelation object!", BOOL_VERBOSE);
393 * A private method to get an object from the registry
397 private Object getObjectFromRegistry() throws RemoteException,
398 ClassNotFoundException, NotBoundException {
400 // Translating into the actual Message class
401 MessageGetObject sMessage = (MessageGetObject) sIoTMasterMsg;
403 // Locate RMI registry and add object into IoTSet
405 LocateRegistry.getRegistry(sMessage.getHostAddress(), sMessage.getRMIRegPort());
406 RuntimeOutput.print("IoTSlave: Looking for RMI registry: " +
407 sMessage.getHostAddress() + ":" + sMessage.getRMIRegPort() +
408 " with RMI stub port: " + sMessage.getRMIStubPort(), BOOL_VERBOSE);
409 Object stubObj = registry.lookup(sMessage.getObjectName());
410 RuntimeOutput.print("IoTSlave: Looking for object name: " + sMessage.getObjectName(), BOOL_VERBOSE);
412 // Class conversion to interface class of this class,
413 // e.g. ProximitySensorImpl has ProximitySensor interface
414 String strObjClassInterfaceName = STR_OBJ_CLS_PFX + "." + STR_INTERFACE_PFX + "." +
415 sMessage.getObjectInterfaceName();
416 Class<?> clsInf = Class.forName(strObjClassInterfaceName);
417 Object stubObjConv = clsInf.cast(stubObj);
423 * A private method to get an object and create a stub
425 * This is using the capability-based RMI skeleton and stub scheme
429 private Object getObjectFromStub() throws RemoteException,
430 ClassNotFoundException, NoSuchMethodException, InstantiationException,
431 IllegalAccessException, NotBoundException, InvocationTargetException, UnknownHostException {
433 // Translating into the actual Message class
434 MessageGetObject sMessage = (MessageGetObject) sIoTMasterMsg;
435 // Instantiate the stub and put in the object
436 String strObjStubName = sMainObjectName + "." + sMessage.getObjectStubInterfaceName() + STUB_CLASS_SUFFIX;
437 RuntimeOutput.print("IoTSlave: Stub object: " + strObjStubName, BOOL_VERBOSE);
438 Class<?> clsStub = Class.forName(strObjStubName); // Port number is integer
439 Class[] clsStubParams = { int.class, String.class, String.class, int.class, int[].class };
440 Constructor<?> objStubCons = clsStub.getDeclaredConstructor(clsStubParams);
441 int[] ports = { sMessage.getRMIRegPort() }; // TODO: Change this temporary use of reg port for callbacks
443 String callbackAddress = InetAddress.getLocalHost().getHostAddress(); // Callback address is this machine's address
444 Object objStubParams[] = { sMessage.getRMIStubPort(), sMessage.getHostAddress(), callbackAddress,
446 RuntimeOutput.print("IoTSlave: Creating RMI stub: " +
447 sMessage.getHostAddress() + ":" + sMessage.getRMIRegPort() +
448 " with callback address: " + callbackAddress + " and RMI stub port: " + sMessage.getRMIStubPort(), BOOL_VERBOSE);
449 Object stubObj = objStubCons.newInstance(objStubParams);
450 RuntimeOutput.print("IoTSlave: Object name: " + sMessage.getObjectName(), BOOL_VERBOSE);
451 RuntimeOutput.print("IoTSlave: Stub address: " + callbackAddress, BOOL_VERBOSE);
452 // Class conversion to interface class of this class,
453 // e.g. ProximitySensorImpl has ProximitySensor interface
454 String strObjClassInterfaceName = STR_OBJ_CLS_PFX + "." + STR_INTERFACE_PFX + "." +
455 sMessage.getObjectStubInterfaceName();
456 Class<?> clsInf = Class.forName(strObjClassInterfaceName);
457 Object stubObjConv = clsInf.cast(stubObj);
463 * A private method to get an IoTSet object
467 private void getIoTSetObject() throws IOException,
468 ClassNotFoundException, RemoteException, NotBoundException, NoSuchMethodException,
469 InstantiationException, IllegalAccessException, InvocationTargetException {
471 Object objRegistry = null;
473 objRegistry = getObjectFromStub();
475 objRegistry = getObjectFromRegistry();
476 isetObject.add(objRegistry);
477 RuntimeOutput.print("IoTSlave: This IoTSet now has: " + isetObject.size() + " entry(s)", BOOL_VERBOSE);
479 // Send back the received message as acknowledgement
480 outStream.writeObject(new MessageSimple(IoTCommCode.ACKNOWLEDGED));
481 RuntimeOutput.print("IoTSlave: Getting an object for IoTSet!", BOOL_VERBOSE);
485 * A private method to get an IoTRelation first object
489 private void getIoTRelationFirstObject() throws IOException,
490 ClassNotFoundException, RemoteException, NotBoundException, NoSuchMethodException,
491 InstantiationException, IllegalAccessException, InvocationTargetException {
493 Object objRegistry = null;
495 objRegistry = getObjectFromStub();
497 objRegistry = getObjectFromRegistry();
498 iRelFirstObject = objRegistry;
500 // Send back the received message as acknowledgement
501 outStream.writeObject(new MessageSimple(IoTCommCode.ACKNOWLEDGED));
502 RuntimeOutput.print("IoTSlave: Getting a first object for IoTRelation!", BOOL_VERBOSE);
507 * A private method to get an IoTRelation second object
511 private void getIoTRelationSecondObject() throws IOException,
512 ClassNotFoundException, RemoteException, NotBoundException, NoSuchMethodException,
513 InstantiationException, IllegalAccessException, InvocationTargetException {
515 Object objRegistry = null;
517 objRegistry = getObjectFromStub();
519 objRegistry = getObjectFromRegistry();
520 iRelSecondObject = objRegistry;
522 // Now add the first and the second object into IoTRelation
523 irelObject.put(iRelFirstObject, iRelSecondObject);
524 RuntimeOutput.print("IoTSlave: This IoTRelation now has: " + irelObject.size() + " entry(s)", BOOL_VERBOSE);
526 // Send back the received message as acknowledgement
527 outStream.writeObject(new MessageSimple(IoTCommCode.ACKNOWLEDGED));
528 RuntimeOutput.print("IoTSlave: Getting a second object for IoTRelation!", BOOL_VERBOSE);
533 * A private method to reinitialize IoTSet field
537 private void reinitializeIoTSetField() throws IOException,
538 IllegalAccessException, NoSuchFieldException {
540 // Reinitialize IoTSet field after getting all the objects
541 iotsetObject = new IoTSet<Object>(isetObject.values());
543 // Private fields need getDeclaredField(), while public fields use getField()
544 Field fld = clsMain.getDeclaredField(strFieldName);
545 boolean bAccess = fld.isAccessible();
546 fld.setAccessible(true);
547 fld.set(objMainCls, iotsetObject);
548 fld.setAccessible(bAccess);
549 RuntimeOutput.print("IoTSlave: Reinitializing field " + strFieldName, BOOL_VERBOSE);
551 // Send back the received message as acknowledgement
552 outStream.writeObject(new MessageSimple(IoTCommCode.ACKNOWLEDGED));
553 RuntimeOutput.print("IoTSlave: Reinitializing IoTSet field!", BOOL_VERBOSE);
558 * A private method to reinitialize IoTRelation field
562 private void reinitializeIoTRelationField() throws IOException,
563 IllegalAccessException, NoSuchFieldException {
565 // Reinitialize IoTSet field after getting all the objects
566 iotrelObject = new IoTRelation<Object,Object>(irelObject.relationMap(), irelObject.size());
568 // Private fields need getDeclaredField(), while public fields use getField()
569 Field fld = clsMain.getDeclaredField(strFieldName);
570 boolean bAccess = fld.isAccessible();
571 fld.setAccessible(true);
572 fld.set(objMainCls, iotrelObject);
573 fld.setAccessible(bAccess);
574 RuntimeOutput.print("IoTSlave: Reinitializing field " + strFieldName, BOOL_VERBOSE);
576 // Send back the received message as acknowledgement
577 outStream.writeObject(new MessageSimple(IoTCommCode.ACKNOWLEDGED));
578 RuntimeOutput.print("IoTSlave: Reinitializing IoTRelation field!", BOOL_VERBOSE);
583 * A private method to get the device driver object's IoTSet
585 * This is to handle device driver's IoTSet that contains IP addresses
589 private void getDeviceIoTSetObject() throws IOException {
591 // Translating into the actual Message class
592 MessageGetDeviceObject sMessage = (MessageGetDeviceObject) sIoTMasterMsg;
594 // Get IoTSet objects for IP address set on device driver/controller
595 IoTDeviceAddress objDeviceAddress = new IoTDeviceAddress(sMessage.getHostAddress(),
596 sMessage.getSourceDeviceDriverPort(),
597 sMessage.getDestinationDeviceDriverPort(),
598 sMessage.isSourcePortWildCard(),
599 sMessage.isDestinationPortWildCard());
600 RuntimeOutput.print("IoTSlave: Device address transferred: " + sMessage.getHostAddress(), BOOL_VERBOSE);
601 isetObject.add(objDeviceAddress);
602 RuntimeOutput.print("IoTSlave: This IoTSet now has: " + isetObject.size() + " entry(s)", BOOL_VERBOSE);
604 // Send back the received message as acknowledgement
605 outStream.writeObject(new MessageSimple(IoTCommCode.ACKNOWLEDGED));
606 RuntimeOutput.print("IoTSlave: Getting an object for IoTSet!", BOOL_VERBOSE);
611 * A private method to get the device driver object's IoTSet for IoTZigbeeAddress
613 * This is to handle device driver's IoTSet that contains Zigbee addresses
617 private void getZBDevIoTSetObject() throws IOException {
619 // Translating into the actual Message class
620 MessageGetSimpleDeviceObject sMessage = (MessageGetSimpleDeviceObject) sIoTMasterMsg;
622 // Get IoTSet objects for IP address set on device driver/controller
623 IoTZigbeeAddress objZBDevAddress = new IoTZigbeeAddress(sMessage.getHostAddress());
624 RuntimeOutput.print("IoTSlave: Device address transferred: " + sMessage.getHostAddress(), BOOL_VERBOSE);
625 isetObject.add(objZBDevAddress);
626 RuntimeOutput.print("IoTSlave: This IoTSet now has: " + isetObject.size() + " entry(s)", BOOL_VERBOSE);
628 // Send back the received message as acknowledgement
629 outStream.writeObject(new MessageSimple(IoTCommCode.ACKNOWLEDGED));
630 RuntimeOutput.print("IoTSlave: Getting an object for IoTSet!", BOOL_VERBOSE);
636 * A private method to get IoTAddress objects for IoTSet
640 private void getAddIoTSetObject() throws IOException {
642 // Translating into the actual Message class
643 MessageGetSimpleDeviceObject sMessage = (MessageGetSimpleDeviceObject) sIoTMasterMsg;
645 // Get IoTSet objects for IP address set on device driver/controller
646 IoTAddress objAddress = new IoTAddress(sMessage.getHostAddress());
647 RuntimeOutput.print("IoTSlave: Address transferred: " + sMessage.getHostAddress(), BOOL_VERBOSE);
648 isetObject.add(objAddress);
649 RuntimeOutput.print("IoTSlave: This IoTSet now has: " + isetObject.size() + " entry(s)", BOOL_VERBOSE);
650 // Send back the received message as acknowledgement
651 outStream.writeObject(new MessageSimple(IoTCommCode.ACKNOWLEDGED));
652 RuntimeOutput.print("IoTSlave: Getting an object for IoTSet!", BOOL_VERBOSE);
657 * A private method to invoke init() method in the controller object
661 private void invokeInitMethod() throws IOException {
666 Class<?> noparams[] = {};
667 Method method = clsMain.getDeclaredMethod("init", noparams);
668 method.invoke(objMainCls);
669 } catch (NoSuchMethodException |
670 IllegalAccessException |
671 InvocationTargetException ex) {
672 System.out.println("IoTSlave: Exception: "
674 ex.printStackTrace();
679 // Start a new thread to invoke the init function
680 RuntimeOutput.print("IoTSlave: Invoke init method! Job done!", BOOL_VERBOSE);
682 // Send back the received message as acknowledgement
683 outStream.writeObject(new MessageSimple(IoTCommCode.ACKNOWLEDGED));
688 * A public method to do communication with IoTMaster
690 * @params iIndex Integer index
693 public void commIoTMaster() {
697 // Loop, receive and process commands from IoTMaster
698 socket = new Socket(sIoTMasterHostAdd, iComPort);
699 outStream = new ObjectOutputStream(socket.getOutputStream());
700 inStream = new ObjectInputStream(socket.getInputStream());
704 // Get the first payload
705 RuntimeOutput.print("IoTSlave: Slave waiting...", BOOL_VERBOSE);
706 sIoTMasterMsg = (Message) inStream.readObject();
708 // Check payload message from IoTMaster and make a decision
709 switch (sIoTMasterMsg.getMessage()) {
719 case CREATE_MAIN_OBJECT:
723 case CREATE_NEW_IOTSET:
727 case CREATE_NEW_IOTRELATION:
728 createNewIoTRelation();
731 case GET_IOTSET_OBJECT:
735 case GET_IOTRELATION_FIRST_OBJECT:
736 getIoTRelationFirstObject();
739 case GET_IOTRELATION_SECOND_OBJECT:
740 getIoTRelationSecondObject();
743 case REINITIALIZE_IOTSET_FIELD:
744 reinitializeIoTSetField();
747 case REINITIALIZE_IOTRELATION_FIELD:
748 reinitializeIoTRelationField();
751 case GET_DEVICE_IOTSET_OBJECT:
752 getDeviceIoTSetObject();
755 case GET_ZB_DEV_IOTSET_OBJECT:
756 getZBDevIoTSetObject();
759 case GET_ADD_IOTSET_OBJECT:
760 getAddIoTSetObject();
763 case INVOKE_INIT_METHOD:
775 RuntimeOutput.print("IoTSlave: Session ends!", BOOL_VERBOSE);
777 // Closing streams and end session
781 RuntimeOutput.print("IoTSlave: Closing!", BOOL_VERBOSE);
782 // We have to continuously loop because we are preserving our stubs and skeletons
785 } catch (IOException |
786 ClassNotFoundException |
787 NoSuchMethodException |
788 InstantiationException |
789 AlreadyBoundException |
790 IllegalAccessException |
791 InvocationTargetException |
793 NoSuchFieldException ex) {
794 System.out.println("IoTSlave: Exception: "
796 ex.printStackTrace();
800 public static void main(String args[]) {
801 IoTSlave iotSlave = new IoTSlave(args);
802 iotSlave.parseIoTSlaveConfigFile();
803 iotSlave.commIoTMaster();