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;
71 * IoTSet object, e.g. IoTSet<ProximitySensor> proximity_sensors;
72 * IoTRelation object, e.g. IoTRelation<ProximitySensor, LightBulb> ps_lb_relation;
74 private ISet<Object> isetObject;
75 private IoTSet<Object> iotsetObject;
76 private IRelation<Object,Object> irelObject;
77 private IoTRelation<Object,Object> iotrelObject;
79 // Constants that are to be extracted from config file
80 private static String STR_JAR_FILE_PATH;
81 private static String STR_OBJ_CLS_PFX;
82 private static String STR_INTERFACE_PFX;
83 private static String SKEL_CLASS_SUFFIX;
84 private static String STUB_CLASS_SUFFIX;
85 private static boolean BOOL_VERBOSE;
86 private static boolean CAPAB_BASED_RMI;
89 * IoTSlave class constants - not to be changed by users
91 private static final String STR_IOT_SLAVE_NAME = "IoTSlave";
92 private static final String STR_CFG_FILE_EXT = ".config";
93 private static final String STR_CLS_FILE_EXT = ".class";
94 private static final String STR_JAR_FILE_EXT = ".jar";
95 private static final String STR_ZIP_FILE_EXT = ".zip";
96 private static final String STR_UNZIP_DIR = "./";
97 private static final Class<?>[] STR_URL_PARAM = new Class[] {URL.class };
98 private static final String STR_YES = "Yes";
99 private static final String STR_NO = "No";
105 public IoTSlave(String[] argInp) {
107 sIoTMasterMsg = null;
108 sIoTMasterHostAdd = argInp[0];
109 iComPort = Integer.parseInt(argInp[1]);
110 iRMIRegPort = Integer.parseInt(argInp[2]);
111 iRMIStubPort = Integer.parseInt(argInp[3]);
112 sMainObjectName = null;
120 iRelFirstObject = null;
121 iRelSecondObject = null;
126 STR_JAR_FILE_PATH = null;
127 STR_OBJ_CLS_PFX = null;
128 STR_INTERFACE_PFX = null;
129 SKEL_CLASS_SUFFIX = null;
130 STUB_CLASS_SUFFIX = null;
131 BOOL_VERBOSE = false;
132 CAPAB_BASED_RMI = false;
136 * A method to initialize constants from config file
140 private void parseIoTSlaveConfigFile() {
141 // Parse configuration file
142 Properties prop = new Properties();
143 String strCfgFileName = STR_IOT_SLAVE_NAME + STR_CFG_FILE_EXT;
144 File file = new File(strCfgFileName);
146 FileInputStream fis = new FileInputStream(file);
148 } catch (IOException ex) {
149 System.out.println("IoTMaster: Error reading config file: " + strCfgFileName);
150 ex.printStackTrace();
152 System.out.println("IoTMaster: Extracting information from config file: " + strCfgFileName);
153 // Initialize constants from config file
154 STR_JAR_FILE_PATH = prop.getProperty("JAR_FILE_PATH");
155 STR_OBJ_CLS_PFX = prop.getProperty("OBJECT_CLASS_PREFIX");
156 STR_INTERFACE_PFX = prop.getProperty("INTERFACE_PREFIX");
157 SKEL_CLASS_SUFFIX = prop.getProperty("SKEL_CLASS_SUFFIX");
158 STUB_CLASS_SUFFIX = prop.getProperty("STUB_CLASS_SUFFIX");
159 if (prop.getProperty("VERBOSE").equals(STR_YES)) {
162 if (prop.getProperty("CAPAB_BASED_RMI").equals(STR_YES)) {
163 CAPAB_BASED_RMI = true;
166 System.out.println("JAR_FILE_PATH=" + STR_JAR_FILE_PATH);
167 System.out.println("OBJECT_CLASS_PREFIX=" + STR_OBJ_CLS_PFX);
168 System.out.println("INTERFACE_PREFIX=" + STR_INTERFACE_PFX);
169 System.out.println("SKEL_CLASS_SUFFIX=" + SKEL_CLASS_SUFFIX);
170 System.out.println("STUB_CLASS_SUFFIX=" + STUB_CLASS_SUFFIX);
171 System.out.println("CAPAB_BASED_RMI=" + CAPAB_BASED_RMI);
172 System.out.println("IoTMaster: Information extracted successfully!");
176 * Adds the content pointed by the URL to the classpath dynamically at runtime (hack!!!)
178 * @param url the URL pointing to the content to be added
179 * @throws IOException
180 * @see <a href="http://stackoverflow.com/questions/60764/how-should-i-load-jars-dynamically-at-runtime</a>
182 private static void addURL(URL url) throws IOException {
184 URLClassLoader sysloader = (URLClassLoader)ClassLoader.getSystemClassLoader();
185 Class<?> sysclass = URLClassLoader.class;
189 Method method = sysclass.getDeclaredMethod("addURL", STR_URL_PARAM);
190 method.setAccessible(true);
191 method.invoke(sysloader,new Object[] { url });
193 } catch (Throwable t) {
196 throw new IOException("IoTSlave: Could not add URL to system classloader!");
201 * A private method to create object
205 private void createCapabBasedRMIJava(MessageCreateObject sMessage) throws
206 ClassNotFoundException, NoSuchMethodException, UnknownHostException {
208 // Instantiate the skeleton and put in the object
209 String strObjSkelName = STR_OBJ_CLS_PFX + "." + sMessage.getObjectClass() +
210 "." + sMessage.getObjectInterfaceName() + SKEL_CLASS_SUFFIX;
211 RuntimeOutput.print("IoTSlave: Skeleton object: " + strObjSkelName, BOOL_VERBOSE);
212 Class<?> clsSkel = Class.forName(strObjSkelName);
213 Class<?> clsInt = Class.forName(STR_OBJ_CLS_PFX + "." + STR_INTERFACE_PFX +
214 "." + sMessage.getObjectInterfaceName());
215 Class[] clsSkelParams = { clsInt, String.class, int.class }; // Port number is integer
216 Constructor<?> objSkelCons = clsSkel.getDeclaredConstructor(clsSkelParams);
217 String callbackAddress = InetAddress.getLocalHost().getHostAddress(); // Callback address is this machine's address
218 Object objSkelParams[] = { objMainCls, callbackAddress, iRMIStubPort };
219 // Create a new thread for each skeleton
220 Thread objectThread = new Thread(new Runnable() {
223 Object objSkel = objSkelCons.newInstance(objSkelParams);
224 } catch (InstantiationException |
225 IllegalAccessException |
226 InvocationTargetException ex) {
227 ex.printStackTrace();
231 objectThread.start();
232 RuntimeOutput.print("IoTSlave: Done generating object!", BOOL_VERBOSE);
236 * A private method to create object
240 private void createObject() throws IOException,
241 ClassNotFoundException, NoSuchMethodException, InstantiationException,
242 RemoteException, AlreadyBoundException, IllegalAccessException,
243 InvocationTargetException {
245 // Translating into the actual Message class
246 MessageCreateObject sMessage = (MessageCreateObject) sIoTMasterMsg;
247 // Instantiate object using reflection
248 String strObjClassName = STR_OBJ_CLS_PFX + "." + sMessage.getObjectClass() +
249 "." + sMessage.getObjectClass();
250 File file = new File(STR_JAR_FILE_PATH + sMessage.getObjectClass() + STR_JAR_FILE_EXT);
251 RuntimeOutput.print("IoTSlave: DEBUG print path: " + STR_JAR_FILE_PATH +
252 sMessage.getObjectClass() + STR_JAR_FILE_EXT, BOOL_VERBOSE);
253 addURL(file.toURI().toURL());
254 clsMain = Class.forName(strObjClassName);
255 Class[] clsParams = sMessage.getObjectFldCls();
256 Constructor<?> ct = clsMain.getDeclaredConstructor(clsParams);
257 Object objParams[] = sMessage.getObjectFields();
258 objMainCls = ct.newInstance(objParams);
259 RuntimeOutput.print("IoTSlave: Creating RMI skeleton: " +
260 sMessage.getHostAddress() + ":" + sMessage.getRMIRegPort() +
261 " with RMI stub port: " + iRMIStubPort, BOOL_VERBOSE);
262 if (CAPAB_BASED_RMI) {
263 // Use the new capability-based RMI in Java
264 createCapabBasedRMIJava(sMessage);
266 // Register object to RMI - there are 2 ports: RMI registry port and RMI stub port
267 Object objStub = (Object)
268 UnicastRemoteObject.exportObject((Remote) objMainCls, iRMIStubPort);
269 Registry registry = LocateRegistry.createRegistry(iRMIRegPort);
270 registry.bind(sMessage.getObjectName(), (Remote) objStub);
272 outStream.writeObject(new MessageSimple(IoTCommCode.ACKNOWLEDGED));
273 RuntimeOutput.print("IoTSlave: Registering object via RMI!", BOOL_VERBOSE);
279 * A private method to transfer file
283 private void transferFile() throws IOException,
284 UnknownHostException, FileNotFoundException {
286 // Translating into the actual Message class
287 MessageSendFile sMessage = (MessageSendFile) sIoTMasterMsg;
289 // Send back the received message as acknowledgement
290 outStream.writeObject(new MessageSimple(IoTCommCode.ACKNOWLEDGED));
292 // Write file to the current location
293 Socket filesocket = new Socket(sIoTMasterHostAdd, iComPort);
294 InputStream inFileStream = filesocket.getInputStream();
295 OutputStream outFileStream = new FileOutputStream(sMessage.getFileName());
296 byte[] bytFile = new byte[Math.toIntExact(sMessage.getFileSize())];
299 while ((iCount = inFileStream.read(bytFile)) > 0) {
300 outFileStream.write(bytFile, 0, iCount);
302 // Unzip if this is a zipped file
303 if (sMessage.getFileName().contains(STR_ZIP_FILE_EXT)) {
304 RuntimeOutput.print("IoTSlave: Unzipping file: " + sMessage.getFileName(), BOOL_VERBOSE);
306 ZipFile zipFile = new ZipFile(sMessage.getFileName());
307 zipFile.extractAll(STR_UNZIP_DIR);
308 } catch (ZipException ex) {
309 System.out.println("IoTSlave: Error in unzipping file!");
310 ex.printStackTrace();
313 outStream.writeObject(new MessageSimple(IoTCommCode.ACKNOWLEDGED));
314 RuntimeOutput.print("IoTSlave: Receiving file transfer!", BOOL_VERBOSE);
318 * A private method to create a main object
322 private void createMainObject() throws IOException,
323 ClassNotFoundException, InstantiationException, IllegalAccessException,
324 InvocationTargetException {
326 // Translating into the actual Message class
327 MessageCreateMainObject sMessage = (MessageCreateMainObject) sIoTMasterMsg;
329 // Getting controller class
330 File file = new File(STR_JAR_FILE_PATH + sMessage.getObjectName() + STR_JAR_FILE_EXT);
331 RuntimeOutput.print("IoTSlave: DEBUG print path: " + STR_JAR_FILE_PATH +
332 sMessage.getObjectName() + STR_JAR_FILE_EXT, BOOL_VERBOSE);
333 addURL(file.toURI().toURL());
334 // We will always have a package name <object name>.<object name>
335 // e.g. SmartLightsController.SmartLightsController
336 sMainObjectName = sMessage.getObjectName();
337 clsMain = Class.forName(sMainObjectName + "." + sMainObjectName);
338 objMainCls = clsMain.newInstance();
340 // Send back the received message as acknowledgement
341 outStream.writeObject(new MessageSimple(IoTCommCode.ACKNOWLEDGED));
342 RuntimeOutput.print("IoTSlave: Instantiating main controller/device class "
343 + sMessage.getObjectName(), BOOL_VERBOSE);
348 * A private method to create a new IoTSet
352 private void createNewIoTSet() throws IOException {
354 // Translating into the actual Message class
355 MessageCreateSetRelation sMessage = (MessageCreateSetRelation) sIoTMasterMsg;
357 // Initialize field name
358 strFieldName = sMessage.getObjectFieldName();
359 RuntimeOutput.print("IoTSlave: Setting up field " + strFieldName, BOOL_VERBOSE);
361 // Creating a new IoTSet object
362 isetObject = new ISet<Object>();
364 // Send back the received message as acknowledgement
365 outStream.writeObject(new MessageSimple(IoTCommCode.ACKNOWLEDGED));
366 RuntimeOutput.print("IoTSlave: Creating a new IoTSet object!", BOOL_VERBOSE);
371 * A private method to create a new IoTRelation
375 private void createNewIoTRelation() throws IOException {
377 // Translating into the actual Message class
378 MessageCreateSetRelation sMessage = (MessageCreateSetRelation) sIoTMasterMsg;
380 // Initialize field name
381 strFieldName = sMessage.getObjectFieldName();
382 RuntimeOutput.print("IoTSlave: Setting up field " + strFieldName, BOOL_VERBOSE);
384 // Creating a new IoTRelation object
385 irelObject = new IRelation<Object,Object>();
387 // Send back the received message as acknowledgement
388 outStream.writeObject(new MessageSimple(IoTCommCode.ACKNOWLEDGED));
389 RuntimeOutput.print("IoTSlave: Creating a new IoTRelation object!", BOOL_VERBOSE);
394 * A private method to get an object from the registry
398 private Object getObjectFromRegistry() throws RemoteException,
399 ClassNotFoundException, NotBoundException {
401 // Translating into the actual Message class
402 MessageGetObject sMessage = (MessageGetObject) sIoTMasterMsg;
404 // Locate RMI registry and add object into IoTSet
406 LocateRegistry.getRegistry(sMessage.getHostAddress(), sMessage.getRMIRegPort());
407 RuntimeOutput.print("IoTSlave: Looking for RMI registry: " +
408 sMessage.getHostAddress() + ":" + sMessage.getRMIRegPort() +
409 " with RMI stub port: " + sMessage.getRMIStubPort(), BOOL_VERBOSE);
410 Object stubObj = registry.lookup(sMessage.getObjectName());
411 RuntimeOutput.print("IoTSlave: Looking for object name: " + sMessage.getObjectName(), BOOL_VERBOSE);
413 // Class conversion to interface class of this class,
414 // e.g. ProximitySensorImpl has ProximitySensor interface
415 String strObjClassInterfaceName = STR_OBJ_CLS_PFX + "." + STR_INTERFACE_PFX + "." +
416 sMessage.getObjectInterfaceName();
417 Class<?> clsInf = Class.forName(strObjClassInterfaceName);
418 Object stubObjConv = clsInf.cast(stubObj);
424 * A private method to get an object and create a stub
426 * This is using the capability-based RMI skeleton and stub scheme
430 private Object getObjectFromStub() throws RemoteException,
431 ClassNotFoundException, NoSuchMethodException, InstantiationException,
432 IllegalAccessException, NotBoundException, InvocationTargetException, UnknownHostException {
434 // Translating into the actual Message class
435 MessageGetObject sMessage = (MessageGetObject) sIoTMasterMsg;
436 // Instantiate the stub and put in the object
437 String strObjStubName = sMainObjectName + "." + sMessage.getObjectStubInterfaceName() + STUB_CLASS_SUFFIX;
438 RuntimeOutput.print("IoTSlave: Stub object: " + strObjStubName, BOOL_VERBOSE);
439 Class<?> clsStub = Class.forName(strObjStubName); // Port number is integer
440 Class[] clsStubParams = { int.class, String.class, String.class, int.class, int[].class };
441 Constructor<?> objStubCons = clsStub.getDeclaredConstructor(clsStubParams);
442 Integer[] portsInteger = sMessage.getRMICallbackPorts();
443 int[] ports = Arrays.stream(portsInteger).mapToInt(Integer::intValue).toArray();
445 String callbackAddress = InetAddress.getLocalHost().getHostAddress(); // Callback address is this machine's address
446 Object objStubParams[] = { sMessage.getRMIStubPort(), sMessage.getHostAddress(), callbackAddress,
448 RuntimeOutput.print("IoTSlave: Creating RMI stub: " +
449 sMessage.getHostAddress() + ":" + sMessage.getRMIRegPort() +
450 " with callback address: " + callbackAddress + " and RMI stub port: " + sMessage.getRMIStubPort(), BOOL_VERBOSE);
451 Object stubObj = objStubCons.newInstance(objStubParams);
452 RuntimeOutput.print("IoTSlave: Object name: " + sMessage.getObjectName(), BOOL_VERBOSE);
453 RuntimeOutput.print("IoTSlave: Stub address: " + callbackAddress, BOOL_VERBOSE);
454 // Class conversion to interface class of this class,
455 // e.g. ProximitySensorImpl has ProximitySensor interface
456 String strObjClassInterfaceName = STR_OBJ_CLS_PFX + "." + STR_INTERFACE_PFX + "." +
457 sMessage.getObjectStubInterfaceName();
458 Class<?> clsInf = Class.forName(strObjClassInterfaceName);
459 Object stubObjConv = clsInf.cast(stubObj);
465 * A private method to get an IoTSet object
469 private void getIoTSetObject() throws IOException,
470 ClassNotFoundException, RemoteException, NotBoundException, NoSuchMethodException,
471 InstantiationException, IllegalAccessException, InvocationTargetException {
473 Object objRegistry = null;
475 objRegistry = getObjectFromStub();
477 objRegistry = getObjectFromRegistry();
478 isetObject.add(objRegistry);
479 RuntimeOutput.print("IoTSlave: This IoTSet now has: " + isetObject.size() + " entry(s)", BOOL_VERBOSE);
481 // Send back the received message as acknowledgement
482 outStream.writeObject(new MessageSimple(IoTCommCode.ACKNOWLEDGED));
483 RuntimeOutput.print("IoTSlave: Getting an object for IoTSet!", BOOL_VERBOSE);
487 * A private method to get an IoTRelation first object
491 private void getIoTRelationFirstObject() throws IOException,
492 ClassNotFoundException, RemoteException, NotBoundException, NoSuchMethodException,
493 InstantiationException, IllegalAccessException, InvocationTargetException {
495 Object objRegistry = null;
497 objRegistry = getObjectFromStub();
499 objRegistry = getObjectFromRegistry();
500 iRelFirstObject = objRegistry;
502 // Send back the received message as acknowledgement
503 outStream.writeObject(new MessageSimple(IoTCommCode.ACKNOWLEDGED));
504 RuntimeOutput.print("IoTSlave: Getting a first object for IoTRelation!", BOOL_VERBOSE);
509 * A private method to get an IoTRelation second object
513 private void getIoTRelationSecondObject() throws IOException,
514 ClassNotFoundException, RemoteException, NotBoundException, NoSuchMethodException,
515 InstantiationException, IllegalAccessException, InvocationTargetException {
517 Object objRegistry = null;
519 objRegistry = getObjectFromStub();
521 objRegistry = getObjectFromRegistry();
522 iRelSecondObject = objRegistry;
524 // Now add the first and the second object into IoTRelation
525 irelObject.put(iRelFirstObject, iRelSecondObject);
526 RuntimeOutput.print("IoTSlave: This IoTRelation now has: " + irelObject.size() + " entry(s)", BOOL_VERBOSE);
528 // Send back the received message as acknowledgement
529 outStream.writeObject(new MessageSimple(IoTCommCode.ACKNOWLEDGED));
530 RuntimeOutput.print("IoTSlave: Getting a second object for IoTRelation!", BOOL_VERBOSE);
535 * A private method to reinitialize IoTSet field
539 private void reinitializeIoTSetField() throws IOException,
540 IllegalAccessException, NoSuchFieldException {
542 // Reinitialize IoTSet field after getting all the objects
543 iotsetObject = new IoTSet<Object>(isetObject.values());
545 // Private fields need getDeclaredField(), while public fields use getField()
546 Field fld = clsMain.getDeclaredField(strFieldName);
547 boolean bAccess = fld.isAccessible();
548 fld.setAccessible(true);
549 fld.set(objMainCls, iotsetObject);
550 fld.setAccessible(bAccess);
551 RuntimeOutput.print("IoTSlave: Reinitializing field " + strFieldName, BOOL_VERBOSE);
553 // Send back the received message as acknowledgement
554 outStream.writeObject(new MessageSimple(IoTCommCode.ACKNOWLEDGED));
555 RuntimeOutput.print("IoTSlave: Reinitializing IoTSet field!", BOOL_VERBOSE);
560 * A private method to reinitialize IoTRelation field
564 private void reinitializeIoTRelationField() throws IOException,
565 IllegalAccessException, NoSuchFieldException {
567 // Reinitialize IoTSet field after getting all the objects
568 iotrelObject = new IoTRelation<Object,Object>(irelObject.relationMap(), irelObject.size());
570 // Private fields need getDeclaredField(), while public fields use getField()
571 Field fld = clsMain.getDeclaredField(strFieldName);
572 boolean bAccess = fld.isAccessible();
573 fld.setAccessible(true);
574 fld.set(objMainCls, iotrelObject);
575 fld.setAccessible(bAccess);
576 RuntimeOutput.print("IoTSlave: Reinitializing field " + strFieldName, BOOL_VERBOSE);
578 // Send back the received message as acknowledgement
579 outStream.writeObject(new MessageSimple(IoTCommCode.ACKNOWLEDGED));
580 RuntimeOutput.print("IoTSlave: Reinitializing IoTRelation field!", BOOL_VERBOSE);
585 * A private method to get the device driver object's IoTSet
587 * This is to handle device driver's IoTSet that contains IP addresses
591 private void getDeviceIoTSetObject() throws IOException {
593 // Translating into the actual Message class
594 MessageGetDeviceObject sMessage = (MessageGetDeviceObject) sIoTMasterMsg;
596 // Get IoTSet objects for IP address set on device driver/controller
597 IoTDeviceAddress objDeviceAddress = new IoTDeviceAddress(sMessage.getHostAddress(),
598 sMessage.getSourceDeviceDriverPort(),
599 sMessage.getDestinationDeviceDriverPort(),
600 sMessage.isSourcePortWildCard(),
601 sMessage.isDestinationPortWildCard());
602 RuntimeOutput.print("IoTSlave: Device address transferred: " + sMessage.getHostAddress(), BOOL_VERBOSE);
603 isetObject.add(objDeviceAddress);
604 RuntimeOutput.print("IoTSlave: This IoTSet now has: " + isetObject.size() + " entry(s)", BOOL_VERBOSE);
606 // Send back the received message as acknowledgement
607 outStream.writeObject(new MessageSimple(IoTCommCode.ACKNOWLEDGED));
608 RuntimeOutput.print("IoTSlave: Getting an object for IoTSet!", BOOL_VERBOSE);
613 * A private method to get the device driver object's IoTSet for IoTZigbeeAddress
615 * This is to handle device driver's IoTSet that contains Zigbee addresses
619 private void getZBDevIoTSetObject() throws IOException {
621 // Translating into the actual Message class
622 MessageGetSimpleDeviceObject sMessage = (MessageGetSimpleDeviceObject) sIoTMasterMsg;
624 // Get IoTSet objects for IP address set on device driver/controller
625 IoTZigbeeAddress objZBDevAddress = new IoTZigbeeAddress(sMessage.getHostAddress());
626 RuntimeOutput.print("IoTSlave: Device address transferred: " + sMessage.getHostAddress(), BOOL_VERBOSE);
627 isetObject.add(objZBDevAddress);
628 RuntimeOutput.print("IoTSlave: This IoTSet now has: " + isetObject.size() + " entry(s)", BOOL_VERBOSE);
630 // Send back the received message as acknowledgement
631 outStream.writeObject(new MessageSimple(IoTCommCode.ACKNOWLEDGED));
632 RuntimeOutput.print("IoTSlave: Getting an object for IoTSet!", BOOL_VERBOSE);
638 * A private method to get IoTAddress objects for IoTSet
642 private void getAddIoTSetObject() throws IOException {
644 // Translating into the actual Message class
645 MessageGetSimpleDeviceObject sMessage = (MessageGetSimpleDeviceObject) sIoTMasterMsg;
647 // Get IoTSet objects for IP address set on device driver/controller
648 IoTAddress objAddress = new IoTAddress(sMessage.getHostAddress());
649 RuntimeOutput.print("IoTSlave: Address transferred: " + sMessage.getHostAddress(), BOOL_VERBOSE);
650 isetObject.add(objAddress);
651 RuntimeOutput.print("IoTSlave: This IoTSet now has: " + isetObject.size() + " entry(s)", BOOL_VERBOSE);
652 // Send back the received message as acknowledgement
653 outStream.writeObject(new MessageSimple(IoTCommCode.ACKNOWLEDGED));
654 RuntimeOutput.print("IoTSlave: Getting an object for IoTSet!", BOOL_VERBOSE);
659 * A private method to invoke init() method in the controller object
663 private void invokeInitMethod() throws IOException {
668 Class<?> noparams[] = {};
669 Method method = clsMain.getDeclaredMethod("init", noparams);
670 method.invoke(objMainCls);
671 } catch (NoSuchMethodException |
672 IllegalAccessException |
673 InvocationTargetException ex) {
674 System.out.println("IoTSlave: Exception: "
676 ex.printStackTrace();
681 // Start a new thread to invoke the init function
682 RuntimeOutput.print("IoTSlave: Invoke init method! Job done!", BOOL_VERBOSE);
684 // Send back the received message as acknowledgement
685 outStream.writeObject(new MessageSimple(IoTCommCode.ACKNOWLEDGED));
690 * A public method to do communication with IoTMaster
692 * @params iIndex Integer index
695 public void commIoTMaster() {
699 // Loop, receive and process commands from IoTMaster
700 socket = new Socket(sIoTMasterHostAdd, iComPort);
701 outStream = new ObjectOutputStream(socket.getOutputStream());
702 inStream = new ObjectInputStream(socket.getInputStream());
706 // Get the first payload
707 RuntimeOutput.print("IoTSlave: Slave waiting...", BOOL_VERBOSE);
708 sIoTMasterMsg = (Message) inStream.readObject();
710 // Check payload message from IoTMaster and make a decision
711 switch (sIoTMasterMsg.getMessage()) {
721 case CREATE_MAIN_OBJECT:
725 case CREATE_NEW_IOTSET:
729 case CREATE_NEW_IOTRELATION:
730 createNewIoTRelation();
733 case GET_IOTSET_OBJECT:
737 case GET_IOTRELATION_FIRST_OBJECT:
738 getIoTRelationFirstObject();
741 case GET_IOTRELATION_SECOND_OBJECT:
742 getIoTRelationSecondObject();
745 case REINITIALIZE_IOTSET_FIELD:
746 reinitializeIoTSetField();
749 case REINITIALIZE_IOTRELATION_FIELD:
750 reinitializeIoTRelationField();
753 case GET_DEVICE_IOTSET_OBJECT:
754 getDeviceIoTSetObject();
757 case GET_ZB_DEV_IOTSET_OBJECT:
758 getZBDevIoTSetObject();
761 case GET_ADD_IOTSET_OBJECT:
762 getAddIoTSetObject();
765 case INVOKE_INIT_METHOD:
777 RuntimeOutput.print("IoTSlave: Session ends!", BOOL_VERBOSE);
779 // Closing streams and end session
783 RuntimeOutput.print("IoTSlave: Closing!", BOOL_VERBOSE);
784 // We have to continuously loop because we are preserving our stubs and skeletons
787 } catch (IOException |
788 ClassNotFoundException |
789 NoSuchMethodException |
790 InstantiationException |
791 AlreadyBoundException |
792 IllegalAccessException |
793 InvocationTargetException |
795 NoSuchFieldException ex) {
796 System.out.println("IoTSlave: Exception: "
798 ex.printStackTrace();
802 public static void main(String args[]) {
803 IoTSlave iotSlave = new IoTSlave(args);
804 iotSlave.parseIoTSlaveConfigFile();
805 iotSlave.commIoTMaster();