package com.ibm.iotf.client.device; import java.io.IOException; import java.util.Date; import java.util.Properties; import java.util.Random; import junit.framework.TestCase; import org.eclipse.paho.client.mqttv3.MqttException; import org.junit.FixMethodOrder; import org.junit.runners.MethodSorters; import com.google.gson.JsonArray; import com.google.gson.JsonElement; import com.google.gson.JsonObject; import com.google.gson.JsonParser; import com.ibm.iotf.client.api.APIClient; import com.ibm.iotf.devicemgmt.DeviceAction; import com.ibm.iotf.devicemgmt.DeviceActionHandler; import com.ibm.iotf.devicemgmt.DeviceData; import com.ibm.iotf.devicemgmt.DeviceFirmware; import com.ibm.iotf.devicemgmt.DeviceFirmwareHandler; import com.ibm.iotf.devicemgmt.DeviceInfo; import com.ibm.iotf.devicemgmt.DeviceMetadata; import com.ibm.iotf.devicemgmt.LogSeverity; import com.ibm.iotf.devicemgmt.DeviceAction.Status; import com.ibm.iotf.devicemgmt.DeviceFirmware.FirmwareState; import com.ibm.iotf.devicemgmt.DeviceFirmware.FirmwareUpdateStatus; import com.ibm.iotf.devicemgmt.device.ManagedDevice; @FixMethodOrder(MethodSorters.NAME_ASCENDING) public class DeviceManagementTest extends TestCase { private static Random random = new Random(); private static ManagedDevice dmClient; private static APIClient apiClient = null; private static boolean setupDone = false; private static int count = 0; private final static String DEVICE_PROPERTIES_FILE = "/device.properties"; private final static String APPLICATION_PROPERTIES_FILE = "/application.properties"; private static final String DEVICE_TYPE; private static final String DEVICE_ID; private static final String rebootRequestToBeInitiated; private static final String factoryRequestToBeInitiated; private static final String downloadRequest; private static final String updateRequest; static { createAPIClient(); /** * Load device properties */ Properties props = new Properties(); try { props.load(DeviceManagementTest.class.getResourceAsStream(DEVICE_PROPERTIES_FILE)); } catch (IOException e1) { System.err.println("Not able to read the properties file, exiting.."); System.exit(-1); } DEVICE_TYPE = props.getProperty("Device-Type"); DEVICE_ID = props.getProperty("Device-ID"); rebootRequestToBeInitiated = "{\"action\": \"device/reboot\"," + "\"devices\": [ {\"typeId\": \"" + DEVICE_TYPE +"\"," + "\"deviceId\": \"" + DEVICE_ID + "\"}]}"; factoryRequestToBeInitiated = "{\"action\": \"device/factoryReset\"," + "\"devices\": [ {\"typeId\": \"" + DEVICE_TYPE +"\"," + "\"deviceId\": \"" + DEVICE_ID + "\"}]}"; downloadRequest = "{\"action\": \"firmware/download\", \"parameters\": [{\"name\": \"version\", \"value\": \"0.1.10\" }," + "{\"name\": \"name\", \"value\": \"RasPi01 firmware\"}, {\"name\": \"verifier\", \"value\": \"123df\"}," + "{\"name\": \"uri\",\"value\": \"https://github.com/ibm-messaging/iot-raspberrypi/releases/download/1.0.2.1/iot_1.0-2_armhf.deb\"}" + "],\"devices\": [{\"typeId\": \"" + DEVICE_TYPE + "\",\"deviceId\": \"" + DEVICE_ID + "\"}]}"; updateRequest = "{\"action\": \"firmware/update\", \"devices\": [{\"typeId\": \"" + DEVICE_TYPE + "\",\"deviceId\": \"" + DEVICE_ID + "\"}]}"; } private static DeviceHandlerSample actionHandler = new DeviceHandlerSample(); private static FirmwareHandlerSample firmwareHandler = new FirmwareHandlerSample(); public void setUp() { if(setupDone == true && dmClient.isConnected() == true) { return; } // do the setup try { createManagedClient(DEVICE_PROPERTIES_FILE); setupDone = true; } catch (Exception e) { // TODO Auto-generated catch block e.printStackTrace(); } } public void tearDown() { count++; if(count == 9) { dmClient.disconnect(); } } private static void createAPIClient() { /** * Load device properties */ Properties props = new Properties(); try { props.load(DeviceManagementTest.class.getResourceAsStream(APPLICATION_PROPERTIES_FILE)); } catch (IOException e1) { System.err.println("Not able to read the properties file, exiting.."); System.exit(-1); } try { //Instantiate the class by passing the properties file apiClient = new APIClient(props); } catch (Exception e) { e.printStackTrace(); System.exit(-1); } } private static class FirmwareHandlerSample extends DeviceFirmwareHandler { private volatile String name; private volatile String version; private volatile String url; private volatile String verifier; private volatile boolean firmwareUpdateCalled = false; @Override public void downloadFirmware(final DeviceFirmware deviceFirmware) { System.out.println("Firmware download request received"); new Thread() { public void run() { deviceFirmware.setUpdateStatus(FirmwareUpdateStatus.SUCCESS); deviceFirmware.setState(FirmwareState.DOWNLOADED); name = deviceFirmware.getName(); version = deviceFirmware.getVersion(); url = deviceFirmware.getUrl(); verifier = deviceFirmware.getVerifier(); try { Thread.sleep(5000); } catch (InterruptedException e) { // TODO Auto-generated catch block e.printStackTrace(); } // Fake completion //deviceFirmware.setUpdateStatus(FirmwareUpdateStatus.SUCCESS); deviceFirmware.setState(FirmwareState.DOWNLOADED); } }.start(); } @Override public void updateFirmware(final DeviceFirmware deviceFirmware) { System.out.println("Firmware update request received"); new Thread() { public void run() { firmwareUpdateCalled = true; try { Thread.sleep(5000); } catch (InterruptedException e) { // TODO Auto-generated catch block e.printStackTrace(); } // Pretend that the update is successful deviceFirmware.setUpdateStatus(FirmwareUpdateStatus.SUCCESS); deviceFirmware.setState(FirmwareState.IDLE); } }.start(); } } private static class DeviceHandlerSample extends DeviceActionHandler { private volatile boolean reboot = false; private volatile boolean factoryReset = false; public ManagedDevice dmClient; @Override public void handleReboot(DeviceAction action) { System.out.println("Reboot request initiated"); action.setStatus(Status.ACCEPTED); new Thread() { public void run() { try { Thread.sleep(5000); boolean status = dmClient.sendManageRequest(0, true, true); System.out.println("sent a manage request : " + status); } catch (MqttException e) { // TODO Auto-generated catch block e.printStackTrace(); } catch (InterruptedException e) { // TODO Auto-generated catch block e.printStackTrace(); } reboot = true; } }.start(); } @Override public void handleFactoryReset(DeviceAction action) { System.out.println("Factory reset initiated"); action.setStatus(Status.ACCEPTED); new Thread() { public void run() { try { Thread.sleep(5000); boolean status = dmClient.sendManageRequest(0, true, true); System.out.println("sent a manage request : " + status); } catch (MqttException e) { // TODO Auto-generated catch block e.printStackTrace(); } catch (InterruptedException e) { // TODO Auto-generated catch block e.printStackTrace(); } factoryReset = true; } }.start(); } } public void test08RebootRequest() throws Exception { try { dmClient.connect(5); dmClient.sendManageRequest(0, true, true); } catch (MqttException e) { fail(e.getMessage()); } try { dmClient.addDeviceActionHandler(actionHandler); } catch(Exception e) { // ignore the error } actionHandler.dmClient = dmClient; JsonObject jsonReboot = (JsonObject) new JsonParser().parse(rebootRequestToBeInitiated); System.out.println(jsonReboot); boolean status = apiClient.initiateDeviceManagementRequest(jsonReboot); System.out.println(status); int counter = 0; // wait for sometime while(counter <= 20) { if(actionHandler.reboot) { break; } Thread.sleep(1000); counter++; } JsonObject response = apiClient.getAllDeviceManagementRequests(); JsonArray requests = response.getAsJsonObject().get("results").getAsJsonArray(); JsonElement request = requests.get(requests.size() - 1); System.out.println("get status of the DM request .. "+request.getAsJsonObject().get("id").getAsString()); System.out.println(apiClient.getDeviceManagementRequestStatus(request.getAsJsonObject().get("id").getAsString())); assertTrue("The device reboot request is not received", actionHandler.reboot); } public void test09FactoryResetRequest() throws Exception { try { dmClient.connect(); dmClient.sendManageRequest(0, true, true); } catch (MqttException e) { fail(e.getMessage()); } try { dmClient.addDeviceActionHandler(actionHandler); } catch(Exception e) { // ignore the error } actionHandler.dmClient = dmClient; JsonObject factory = (JsonObject) new JsonParser().parse(factoryRequestToBeInitiated); System.out.println(factory); boolean response = apiClient.initiateDeviceManagementRequest(factory); System.out.println(response); int counter = 0; // wait for sometime while(counter <= 20) { // For some reason the volatile doesn't work, so using the lock if(actionHandler.factoryReset) { break; } Thread.sleep(1000); counter++; } assertTrue("The device factory reset request is not received", actionHandler.factoryReset); } public void test06FirmwareDownload() throws Exception { try { dmClient.connect(true); dmClient.sendManageRequest(0, true, true); } catch (MqttException e) { fail(e.getMessage()); } try { dmClient.addFirmwareHandler(firmwareHandler); } catch(Exception e) { // ignore the error } JsonObject download = (JsonObject) new JsonParser().parse(downloadRequest); System.out.println(download); boolean response = apiClient.initiateDeviceManagementRequest(download); System.out.println(response); // wait for sometime Thread.sleep(1000 * 20); assertTrue("The firmware request/parameters not received", "123df".equals(firmwareHandler.verifier)); assertTrue("The firmware request/parameters not received", "RasPi01 firmware".equals(firmwareHandler.name)); assertTrue("The firmware request/parameters not received", "0.1.10".equals(firmwareHandler.version)); assertTrue("The firmware request/parameters not received", "https://github.com/ibm-messaging/iot-raspberrypi/releases/download/1.0.2.1/iot_1.0-2_armhf.deb".equals(firmwareHandler.url)); } public void test07FirmwareUpdate() throws Exception { try { dmClient.connect(); dmClient.sendManageRequest(0, true, true); } catch (MqttException e) { fail(e.getMessage()); } try { dmClient.addFirmwareHandler(firmwareHandler); } catch(Exception e) { // ignore the error } JsonObject update = (JsonObject) new JsonParser().parse(updateRequest); System.out.println(update); boolean response = apiClient.initiateDeviceManagementRequest(update); System.out.println(response); // wait for sometime Thread.sleep(1000 * 20); assertTrue("The firmware request/parameters not received", firmwareHandler.firmwareUpdateCalled); } public void test01ManageRequest() { boolean status = false; try { status = dmClient.sendManageRequest(0, true, false); DeviceData devicedata = dmClient.getDeviceData(); if(devicedata == null) { fail("Device data must not be null"); } } catch (MqttException e) { fail(e.getMessage()); } assertTrue("Manage request is unsuccessfull", status); } public void test02UnManageRequest() { boolean status = false; try { status = dmClient.sendManageRequest(0, true, false); status = dmClient.sendUnmanageRequest(); } catch (MqttException e) { fail(e.getMessage()); } assertTrue("UnManage request is unsuccessfull", status); } public void test03LocationUpdate() throws MqttException { dmClient.sendManageRequest(0, true, false); double latitude = random.nextDouble() + 30; double longitude = random.nextDouble() - 98; double elevation = (double)random.nextInt(100); int rc = dmClient.updateLocation(latitude, longitude, elevation); assertTrue("Location update is unsuccessfull", rc==200); // user overloaded method rc = dmClient.updateLocation(latitude, longitude, elevation, new Date()); assertTrue("Location update is unsuccessfull", rc==200); // user overloaded method rc = dmClient.updateLocation(latitude, longitude, elevation, new Date(), 1d); assertTrue("Location update is unsuccessfull", rc==200); } public void test04Errorcodes() throws MqttException { dmClient.sendManageRequest(0, true, false); int errorCode = random.nextInt(500); int rc = dmClient.addErrorCode(errorCode); assertTrue("Errorcode addition unsuccessfull", rc==200); // Let us clear the errorcode now rc = dmClient.clearErrorCodes(); assertTrue("clear Errorcode operation is unsuccessfull", rc==200); } public void test05LogMessages() throws MqttException { dmClient.sendManageRequest(0, true, false); String message = "Log event 1"; Date timestamp = new Date(); LogSeverity severity = LogSeverity.informational; int rc = dmClient.addLog(message, timestamp, severity); assertTrue("Log addition unsuccessfull", rc==200); // Use overloaded methods rc = dmClient.addLog("Log event with data", timestamp, severity, "Sample data"); assertTrue("Log addition unsuccessfull", rc==200); // Let us clear the errorcode now rc = dmClient.clearLogs(); assertTrue("clear Log operation is unsuccessfull", rc==200); } /** * This method builds the device objects required to create the * ManagedClient * * @param propertiesFile * @throws Exception */ private void createManagedClient(String propertiesFile) throws Exception { /** * Load device properties */ Properties deviceProps = new Properties(); try { deviceProps.load(DeviceManagementTest.class.getResourceAsStream(propertiesFile)); } catch (IOException e1) { System.err.println("Not able to read the properties file, exiting.."); System.exit(-1); } DeviceFirmware firmware = new DeviceFirmware.Builder(). version("1.0.1"). name("iot-arm.deb"). url(""). verifier("12345"). state(FirmwareState.IDLE). build(); DeviceInfo deviceInfo = new DeviceInfo.Builder(). serialNumber("1234errrrrr"). manufacturer("IBM"). model("T450"). deviceClass("A+"). description("Lenovo ThinkPad"). fwVersion("Windows10"). hwVersion("1.2.3"). descriptiveLocation("ELGC-6F-C138"). build(); /** * Create a DeviceMetadata object */ JsonObject data = new JsonObject(); data.addProperty("customField", "customValue"); DeviceMetadata metadata = new DeviceMetadata(data); metadata.setMetadata(new JsonObject()); DeviceData deviceData = new DeviceData.Builder(). deviceInfo(deviceInfo). deviceFirmware(firmware). metadata(metadata). build(); dmClient = new ManagedDevice(deviceProps, deviceData); } /** * This method connects the device to the Watson IoT Platform */ private void connect() throws Exception { dmClient.connect(); } }