1 package iotruntime.brillo;
4 import java.io.BufferedWriter;
5 import java.io.PrintWriter;
6 import java.io.FileWriter;
7 import java.io.IOException;
8 import java.net.HttpURLConnection;
9 import java.net.MalformedURLException;
10 import java.net.ProtocolException;
12 import java.lang.Class;
13 import java.lang.reflect.*;
17 import com.google.api.services.clouddevices.model.CommandDefNew;
18 import com.google.api.services.clouddevices.model.Device;
21 /** IoTBrilloWeaveCodeGenerator class that connects to
22 * Google Brillo/Weave server based on user's credentials
23 * and creates user's class and interface
26 * 0) Compile iotruntime
27 * 1) Run this code generator
28 * - go to $(IOTJAVA_CLASSPATH)/iot/bin/iotruntime/brillo/
29 * - run this class with this command line:
30 * java -cp .:../../:../../../jars/brillo/*:../../../jars/brillo/libs/* iotruntime.brillo.IoTBrilloWeaveCodeGenerator -help
31 * - follow the instructions to generate codes
32 * 2) If credentials_cache.json hasn't been created then one will be created
33 * 3) Both interface and implementation java API source files will be created
34 * 4) We can move them to the right directories with the credentials_cache.json
35 * - move the interface java file into folder "interfaces"
36 * - create a folder in "iot/benchmarks/drivers" with the class name and put
37 * the class java file there; don't forget to create <class>.config file
38 * and modify the Makefile
39 * 5) A device driver can be created based on the created API's
41 * @author Rahmadi Trimananda <rahmadi.trimananda @ uci.edu>
45 public class IoTBrilloWeaveCodeGenerator {
48 * IoTBrilloWeaveCodeGenerator properties
50 private PrintWriter pw;
51 private String strInterfaceName;
52 private String strClassName;
53 private IoTBrilloWeaveCloudConnection iotBrillo;
58 public IoTBrilloWeaveCodeGenerator(String[] strArgs) {
60 this.strInterfaceName = strArgs[0];
61 this.strClassName = strArgs[1];
62 this.iotBrillo = new IoTBrilloWeaveCloudConnection(strArgs[2], strArgs[3], strArgs[4]);
63 this.iotBrillo.connectionSetup(strArgs[5]);
72 public void generateInterface() throws IOException {
74 // Initialize FileWriter and PrintWriter
75 FileWriter fwInterface = new FileWriter(strInterfaceName + ".java");
76 this.pw = new PrintWriter(new BufferedWriter(fwInterface));
77 // Write the interface header
78 generateInterfaceImports();
80 println("public interface " + strInterfaceName + " extends Remote {");
82 generateInterfaceBody(this.iotBrillo.getDeviceObject());
91 * Generate interface import statements
95 public void generateInterfaceInit() {
96 println("public void init() throws RemoteException;");
101 * Generate interface init method
105 public void generateInterfaceImports() {
106 println("package iotcode.interfaces;");
108 println("import java.rmi.Remote;");
109 println("import java.rmi.RemoteException;");
114 * Generate interface body
116 * @param device Device object that contains JSON parameters
119 private void generateInterfaceBody(Device device) {
121 generateInterfaceInit();
122 Map<String,Map<String,CommandDefNew>> mapCommand = device.getCommandDefs();
123 for(String strCmd : mapCommand.keySet()) {
124 Map<String,CommandDefNew> mapSubCommand = mapCommand.get(strCmd);
125 for(String strSubCmd : mapSubCommand.keySet()) {
126 print("public void " + strCmd + "_" + strSubCmd + "(");
127 CommandDefNew cmd = mapSubCommand.get(strSubCmd);
128 if (cmd.getParameters() != null) {
129 // If we have parameters ...
131 Map<String,Map<String,Object>> mapParam = cmd.getParameters();
132 for (String strParamName : mapParam.keySet()) {
134 Map<String,Object> mapParamProp = mapParam.get(strParamName);
135 for (String strParamProp : mapParamProp.keySet()) {
136 if (strParamProp.equals("type")) {
137 print(getJavaType(mapParamProp.get(strParamProp).toString()) + " ");
138 if (iParamCount == mapParam.size())
139 println(strParamName + ") throws RemoteException;");
141 print(strParamName + ", ");
146 // If we don't have parameters ...
147 println(") throws RemoteException;");
155 * Type translator from JSON syntax to Java
159 private String getJavaType(String strJsonType) {
161 if (strJsonType.equals("string")) {
163 } else if (strJsonType.equals("integer")) {
165 } else if (strJsonType.equals("boolean")) {
167 } else if (strJsonType.equals("number")) {
169 } else { // NULL is returned when type is not recognized
180 public void generateClass() throws IOException {
182 // Initialize FileWriter and PrintWriter
183 FileWriter fwClass = new FileWriter(strClassName + ".java");
184 this.pw = new PrintWriter(new BufferedWriter(fwClass));
185 // Write the import statements
188 println("public class " + strClassName +
189 " extends IoTBrilloWeave" +
190 " implements " + strInterfaceName + " {");
194 generateConstructor();
198 generateClassAPIs(this.iotBrillo.getDeviceObject());
206 * Generate @config statements for IoTDeviceAddress
210 public void generateAtConfigs() {
212 println("@config private IoTSet<IoTAddress> GoogleAccountAddress;");
213 println("@config private IoTSet<IoTAddress> GoogleAPIsAddress;");
218 * Generate init method
222 public void generateInit() {
224 println("public void init() {");
225 println("Iterator itr = GoogleAccountAddress.iterator();");
226 println("IoTAddress address = (IoTAddress)itr.next();");
227 println("super.setAuthScope(address.getHostName());");
233 * Generate class APIs
235 * @param device Device object that contains JSON parameters
238 private void generateClassAPIs(Device device) {
240 // Generate method header
241 Map<String,Map<String,CommandDefNew>> mapCommand = device.getCommandDefs();
242 for(String strCmd : mapCommand.keySet()) {
243 Map<String,CommandDefNew> mapSubCommand = mapCommand.get(strCmd);
244 for(String strSubCmd : mapSubCommand.keySet()) {
245 print("public void " + strCmd + "_" + strSubCmd + "(");
246 CommandDefNew cmd = mapSubCommand.get(strSubCmd);
247 boolean doesParamExist = false;
248 if (cmd.getParameters() != null) {
249 // If we have parameters ...
250 doesParamExist = true;
252 Map<String,Map<String,Object>> mapParam = cmd.getParameters();
253 for (String strParamName : mapParam.keySet()) {
255 Map<String,Object> mapParamProp = mapParam.get(strParamName);
256 for (String strParamProp : mapParamProp.keySet()) {
257 if (strParamProp.equals("type")) {
258 print(getJavaType(mapParamProp.get(strParamProp).toString()) + " ");
259 if (iParamCount == mapParam.size())
260 println(strParamName + ") {");
262 print(strParamName + ", ");
267 // If we don't have parameters ...
270 generateMethodBody(cmd, doesParamExist, strCmd, strSubCmd);
271 generateCommandInsertionAndException();
280 * Generate method body
282 * @param cmd Object CommandDefNew that contains information about the command
283 * @param doesParamExist Boolean that tracks if the method has parameters
284 * @param strCmd String that contains the main command name
285 * @param strSubCmd String that contains the sub command name
288 private void generateMethodBody(CommandDefNew cmd, boolean doesParamExist, String strCmd, String strSubCmd) {
290 if (doesParamExist) {
291 // If we have parameters ...
292 //int iParamCount = 0;
293 println("Map<String, Object> parameters = new HashMap<String, Object>();");
294 Map<String,Map<String,Object>> mapParam = cmd.getParameters();
295 for (String strParamName : mapParam.keySet()) {
297 Map<String,Object> mapParamProp = mapParam.get(strParamName);
298 for (String strParamProp : mapParamProp.keySet()) {
299 if (strParamProp.equals("type")) {
300 //print(getJavaType(mapParamProp.get(strParamProp).toString()) + " ");
301 println("parameters.put(\"" + strParamName + "\", " + strParamName + ");");
306 println("Command command = new Command()");
307 println("\t.setName(\"" + strCmd + "." + strSubCmd + "\")");
309 println("\t.setParameters(parameters)");
310 println("\t.setDeviceId(device.getId());");
315 * Generate command insertion and exception statements
319 private void generateCommandInsertionAndException() {
321 println("command = apiClient.commands().insert(command).execute(); }");
322 println("catch (IOException e) {");
323 println("throw new RuntimeException(\"Could not insert command\", e); }");
326 println("System.out.println(\"Sent command to the device:\" + jsonFactory.toPrettyString(command)); }");
327 println("catch (IOException e) {");
328 println("throw new RuntimeException(e); }");
333 * Generate import statements
337 private void generateImports() {
339 println("package iotcode." + strClassName + ";");
341 println("import com.google.api.client.json.jackson2.JacksonFactory;");
342 println("import com.google.api.services.clouddevices.CloudDevices;");
343 println("import com.google.api.services.clouddevices.model.Command;");
344 println("import com.google.api.services.clouddevices.model.Device;");
346 println("import java.io.IOException;");
347 println("import java.util.HashMap;");
348 println("import java.util.Iterator;");
349 println("import java.util.Map;");
351 println("import iotcode.interfaces.LEDFlasher;");
352 println("import iotruntime.brillo.IoTBrilloWeave;");
353 println("import iotruntime.brillo.IoTBrilloWeaveCloudConnection;");
354 println("import iotruntime.slave.IoTAddress;");
355 println("import iotruntime.slave.IoTSet;");
356 println("import iotchecker.qual.*;");
361 * Generate constructor
365 private void generateConstructor() {
366 // Write the constructor
367 println("public " + strClassName +
368 "(String _clientId, String _clientSecret, String _apiKey, String _deviceId) {");
369 println("super(_clientId, _clientSecret, _apiKey, _deviceId);");
375 * Display help message
379 public static void displayHelpMessage() {
380 System.out.println();
381 System.out.println("Please use this code generator in the following syntax:");
382 System.out.print("java -cp <classpath> IoTBrilloWeaveCodeGenerator <interface_name> ");
383 System.out.println("<class_name> <client_id> <client_secret> <api_key> <device_id>");
384 System.out.println("e.g.");
385 System.out.print("java -cp .:../clouddevices/*:../clouddevices/libs/* IoTBrilloWeaveCodeGenerator ");
386 System.out.print("LEDFlasherTest LEDFlasherTestImplementation 627170482755-4l2gd5m3lf6ej674vqr8sdc14gmeva3e.apps.googleusercontent.com ");
387 System.out.println("Yhj6QzCxeO2B0i25JHqYShsi AIzaSyDcYp9RQAV2ELZWxVIjPBAzIPGiXAAORs0 77173ed5-3303-4c54-f852-b8f51fb7b31f");
388 System.out.println();
389 System.out.println("To show this help message: java IoTBrilloWeaveCodeGenerator --help");
390 System.out.println();
395 * Helper functions that help print to files
397 boolean newline=true;
400 private void print(String str) {
405 for(int i=0; i<tab; i++)
413 private void println(String str) {
418 for(int i=0; i<tab; i++)
426 private void updatetabbing(String str) {
427 tablevel += count(str,'{') - count(str,'}');
430 private int count(String str, char key) {
431 char[] array = str.toCharArray();
433 for(int i=0; i<array.length; i++) {
442 * Call main function for file generations
444 * @param args[0] Interface name
445 * @param args[1] Class name
446 * @param args[2] Client ID
447 * @param args[3] Client secret
448 * @param args[4] API key
449 * @param args[5] Device ID
451 public static void main(String[] args) throws IOException {
453 if(args.length < 6 || args[0].contains("help")) {
454 displayHelpMessage();
456 IoTBrilloWeaveCodeGenerator iotBrilloCodeGen = new IoTBrilloWeaveCodeGenerator(args);
457 iotBrilloCodeGen.generateInterface();
458 iotBrilloCodeGen.generateClass();