class CoapClientConnectorTest(unittest.TestCase): """ This test case class contains very basic integration tests for CoapClientConnector. It should not be considered complete, but serve as a starting point for the student implementing additional functionality within their Programming the IoT environment. """ @classmethod def setUpClass(self): logging.basicConfig( format='%(asctime)s:%(module)s:%(levelname)s:%(message)s', level=logging.DEBUG) logging.info("Testing CoapClientConnector class...") self.cfg = ConfigUtil() self.mcc = CoapClientConnector() def setUp(self): pass def tearDown(self): pass #@unittest.skip("Ignore for now.") def testConnectAndDiscover(self): #start server by "D:\360Downloads\jdk_8\bin\java.exe -jar cf-server-2.5.0-SNAPSHOT.jar" self.mcc.sendDiscoveryRequest(timeout=10) #@unittest.skip("Ignore for now.") def testConnectAndGetCon(self): self.mcc.sendGetRequest( resource=ResourceNameEnum.CDA_MGMT_STATUS_MSG_RESOURCE, enableCON=True, timeout=5) #@unittest.skip("Ignore for now.") def testConnectAndGetNon(self): self.mcc.sendGetRequest( resource=ResourceNameEnum.CDA_MGMT_STATUS_MSG_RESOURCE, enableCON=False, timeout=5) # @unittest.skip("Ignore for now.") def testConnectAndPutCon(self): msg = "This is a test." self.mcc.sendPutRequest( resource=ResourceNameEnum.CDA_MGMT_STATUS_MSG_RESOURCE, payload=msg, enableCON=True, timeout=5) # @unittest.skip("Ignore for now.") def testConnectAndPutNon(self): msg = "This is a test." self.mcc.sendPutRequest( resource=ResourceNameEnum.CDA_MGMT_STATUS_MSG_RESOURCE, payload=msg, enableCON=False, timeout=5) # @unittest.skip("Ignore for now.") def testConnectAndPostCon(self): msg = "This is a test." self.mcc.sendPostRequest( resource=ResourceNameEnum.CDA_MGMT_STATUS_MSG_RESOURCE, payload=msg, enableCON=True, timeout=5) # @unittest.skip("Ignore for now.") def testConnectAndPostNon(self): msg = "This is a test." self.mcc.sendPostRequest( resource=ResourceNameEnum.CDA_MGMT_STATUS_MSG_RESOURCE, payload=msg, enableCON=False, timeout=5) # @unittest.skip("Ignore for now.") def testConnectAndDeleteCon(self): self.mcc.sendDeleteRequest( resource=ResourceNameEnum.CDA_MGMT_STATUS_MSG_RESOURCE, enableCON=True, timeout=5) # @unittest.skip("Ignore for now.") def testConnectAndDeleteNon(self): self.mcc.sendDeleteRequest( resource=ResourceNameEnum.CDA_MGMT_STATUS_MSG_RESOURCE, enableCON=False, timeout=5) #@unittest.skip("Ignore for now.") def testConnectAndGet(self): # TODO: implement this pass #@unittest.skip("Ignore for now.") def testConnectAndDelete(self): # TODO: implement this pass #@unittest.skip("Ignore for now.") def testConnectAndPost(self): # TODO: implement this pass #@unittest.skip("Ignore for now.") def testConnectAndPut(self): # TODO: implement this pass #@unittest.skip("Ignore for now.") def testIntegrateWithGdaGetCdaCmdTopic(self): # TODO: implement this pass #@unittest.skip("Ignore for now.") def testIntegrateWithGdaPostCdaMgmtTopic(self): # TODO: implement this pass
class CoapClientConnectorTest(unittest.TestCase): """ This test case class contains very basic integration tests for CoapClientConnector using a separately running CoAP server. It should not be considered complete, but serve as a starting point for the student implementing additional functionality within their Programming the IoT environment. NOTE: This is different from CoapServerAdapterTest in that it depends upon an external CoAP server (e.g., the GDA's CoAP server). """ @classmethod def setUpClass(self): logging.basicConfig( format='%(asctime)s:%(module)s:%(levelname)s:%(message)s', level=logging.INFO) logging.info("Testing CoapClientConnector class...") self.dataMsgListener = DefaultDataMessageListener() self.pollRate = ConfigUtil().getInteger( ConfigConst.CONSTRAINED_DEVICE, ConfigConst.POLL_CYCLES_KEY, ConfigConst.DEFAULT_POLL_CYCLES) self.coapClient = CoapClientConnector() @classmethod def tearDownClass(self): pass def setUp(self): pass def tearDown(self): pass #@unittest.skip("Ignore for now.") def testConnectAndDiscover(self): """ Comment the annotation to test Connect and Discover """ self.coapClient.sendDiscoveryRequest(timeout=5) sleep(5) #@unittest.skip("Ignore for now.") def testConnectAndGetCon(self): """ Comment the annotation to test CON GET """ self.coapClient.sendGetRequest( \ resource = ResourceNameEnum.CDA_SENSOR_MSG_RESOURCE, name = ConfigConst.TEMP_SENSOR_NAME, enableCON = True, timeout = 5) sleep(5) self.coapClient.sendGetRequest( \ resource = ResourceNameEnum.CDA_SENSOR_MSG_RESOURCE, name = ConfigConst.TEMP_SENSOR_NAME, enableCON = True, timeout = 5) sleep(5) self.coapClient.sendGetRequest( \ resource = ResourceNameEnum.CDA_SENSOR_MSG_RESOURCE, name = ConfigConst.TEMP_SENSOR_NAME, enableCON = True, timeout = 5) @unittest.skip("Ignore for now.") def testConnectAndGetNon(self): """ Comment the annotation to test NON GET """ self.coapClient.sendGetRequest( \ resource = ResourceNameEnum.CDA_MGMT_STATUS_MSG_RESOURCE, enableCON = False, timeout = 5) @unittest.skip("Ignore for now.") def testConnectAndDeleteCon(self): """ Comment the annotation to test CON DELETE """ self.coapClient.sendDeleteRequest( \ resource = ResourceNameEnum.CDA_MGMT_STATUS_MSG_RESOURCE, enableCON = True, timeout = 5) @unittest.skip("Ignore for now.") def testConnectAndDeleteNon(self): """ Comment the annotation to test NON DELETE """ self.coapClient.sendDeleteRequest( \ resource = ResourceNameEnum.CDA_MGMT_STATUS_MSG_RESOURCE, enableCON = False, timeout = 5) @unittest.skip("Ignore for now.") def testObserveForTwoMinutes(self): """ Comment the annotation to test Observe """ self._startObserver() sleep(120) self._stopObserver() @unittest.skip("Ignore for now.") def testConnectAndPostCon(self): """ Comment the annotation to test CON POST """ msg = "This is a test." self.coapClient.sendPostRequest( resource=ResourceNameEnum.CDA_MGMT_STATUS_MSG_RESOURCE, payload=msg, enableCON=True, timeout=5) @unittest.skip("Ignore for now.") def testConnectAndPostNon(self): """ Comment the annotation to test NON POST """ msg = "This is a test." self.coapClient.sendPostRequest( resource=ResourceNameEnum.CDA_MGMT_STATUS_MSG_RESOURCE, payload=msg, enableCON=False, timeout=5) @unittest.skip("Ignore for now.") def testConnectAndPutCon(self): """ Comment the annotation to test CON PUT """ msg = "This is a test." self.coapClient.sendPutRequest( resource=ResourceNameEnum.CDA_MGMT_STATUS_MSG_RESOURCE, payload=msg, enableCON=True, timeout=5) @unittest.skip("Ignore for now.") def testConnectAndPutNon(self): """ Comment the annotation to test NON PUT """ msg = "This is a test." self.coapClient.sendPutRequest( resource=ResourceNameEnum.CDA_MGMT_STATUS_MSG_RESOURCE, payload=msg, enableCON=False, timeout=5) def _startObserver(self): self.coapClient.startObserver( resource=ResourceNameEnum.CDA_SENSOR_MSG_RESOURCE, name=ConfigConst.TEMP_SENSOR_NAME) self.coapClient.startObserver( resource=ResourceNameEnum.CDA_SYSTEM_PERF_MSG_RESOURCE, name=ConfigConst.SYSTEM_PERF_NAME) def _stopObserver(self): self.coapClient.stopObserver( resource=ResourceNameEnum.CDA_SENSOR_MSG_RESOURCE, name=ConfigConst.TEMP_SENSOR_NAME) self.coapClient.stopObserver( resource=ResourceNameEnum.CDA_SYSTEM_PERF_MSG_RESOURCE, name=ConfigConst.SYSTEM_PERF_NAME)
class CoapClientConnectorTest(unittest.TestCase): """ This test case class contains very basic integration tests for CoapClientConnector. It should not be considered complete, but serve as a starting point for the student implementing additional functionality within their Programming the IoT environment. """ @classmethod def setUpClass(self): logging.basicConfig( format='%(asctime)s:%(module)s:%(levelname)s:%(message)s', level=logging.DEBUG) logging.info("Testing CoapClientConnector class...") self.cfg = ConfigUtil() self.coapClient = CoapClientConnector() def setUp(self): pass def tearDown(self): self.coapClient.stopObserver(1) sleep(1) @unittest.skip("Ignore for now.") def testConnectAndDiscover(self): self.coapClient.sendDiscoveryRequest(timeout=10) sleep(5) logging.info("--------------------------->Test testConnectAndDiscover") """ ------------------------------------------------------------------ get test ------------------------------------------------------------------ """ @unittest.skip("Ignore for now.") def testConnectAndGetCon(self): # TODO: implement this self.coapClient.sendGetRequest( resource=ResourceNameEnum.CDA_MGMT_STATUS_MSG_RESOURCE, enableCON=True, timeout=5) sleep(5) logging.info("--------------------------->Test testConnectAndGetCon") @unittest.skip("Ignore for now.") def testConnectAndGetNon(self): # TODO: implement this self.coapClient.sendGetRequest( resource=ResourceNameEnum.CDA_MGMT_STATUS_MSG_RESOURCE, enableCON=False, timeout=5) sleep(5) logging.info("--------------------------->Test testConnectAndGetNon") """ ------------------------------------------------------------------ delete test ------------------------------------------------------------------ """ @unittest.skip("Ignore for now.") def testConnectAndDeleteCon(self): self.coapClient.sendDeleteRequest( resource=ResourceNameEnum.CDA_MGMT_STATUS_MSG_RESOURCE, enableCON=True, timeout=5) sleep(5) logging.info( "--------------------------->Test testConnectAndDeleteCon") @unittest.skip("Ignore for now.") def testConnectAndDeleteNon(self): self.coapClient.sendDeleteRequest( resource=ResourceNameEnum.CDA_MGMT_STATUS_MSG_RESOURCE, enableCON=False, timeout=5) sleep(5) logging.info( "--------------------------->Test testConnectAndDeleteNon") """ ------------------------------------------------------------------ put test ------------------------------------------------------------------ """ ##@unittest.skip("Ignore for now.") def testConnectAndPutCon(self): msg = "This is a test." self.coapClient.sendPutRequest( resource=ResourceNameEnum.CDA_MGMT_STATUS_MSG_RESOURCE, payload=msg, enableCON=True, timeout=5) sleep(5) self.coapClient.sendGetRequest( resource=ResourceNameEnum.CDA_MGMT_STATUS_MSG_RESOURCE, enableCON=True, timeout=5) logging.info("--------------------------->Test testConnectAndPutCon") @unittest.skip("Ignore for now.") def testConnectAndPutNon(self): msg = "This is a test." self.coapClient.sendPutRequest( resource=ResourceNameEnum.CDA_MGMT_STATUS_MSG_RESOURCE, payload=msg, enableCON=False, timeout=5) sleep(5) self.coapClient.sendGetRequest( resource=ResourceNameEnum.CDA_MGMT_STATUS_MSG_RESOURCE, enableCON=False, timeout=5) logging.info("--------------------------->Test testConnectAndPutNon") """ ------------------------------------------------------------------ post test ------------------------------------------------------------------ """ @unittest.skip("Ignore for now.") def testConnectAndPostCon(self): msg = "This is a test." self.coapClient.sendPostRequest( resource=ResourceNameEnum.CDA_MGMT_STATUS_MSG_RESOURCE, payload=msg, enableCON=True, timeout=5) sleep(5) logging.info("--------------------------->Test testConnectAndPostCon") @unittest.skip("Ignore for now.") def testConnectAndPostNon(self): msg = "This is a test." self.coapClient.sendPostRequest( resource=ResourceNameEnum.CDA_MGMT_STATUS_MSG_RESOURCE, payload=msg, enableCON=False, timeout=5) sleep(5) self.coapClient.sendGetRequest( resource=ResourceNameEnum.CDA_MGMT_STATUS_MSG_RESOURCE, enableCON=False, timeout=5) sleep(5) logging.info("--------------------------->Test testConnectAndPostNon") @unittest.skip("Ignore for now.") def testIntegrateWithGdaGetCdaCmdTopic(self): # TODO: implement this pass @unittest.skip("Ignore for now.") def testIntegrateWithGdaPostCdaMgmtTopic(self): # TODO: implement this pass
class CoapServerAdapterTest(unittest.TestCase): """ This test case class contains very basic integration tests for CoapServerAdapter and CoapClientConnector using your Python CoapServerAdapter instance. It should not be considered complete, but serve as a starting point for the student implementing additional functionality within their Programming the IoT environment. NOTE: This is different from CoapClientConnectorTest in that it uses an internal CoAP server; however, your PiotConfig.props for your CoAP client must point to the localhost for this to work, and you should NOT run another CoAP server (e.g., the GDA's CoAP server at the same time). """ @classmethod def setUpClass(self): logging.basicConfig( format='%(asctime)s:%(module)s:%(levelname)s:%(message)s', level=logging.INFO) logging.info( "Testing CoapServerAdapter and CoapClientConnector classes...") self.dataMsgListener = DefaultDataMessageListener() self.pollRate = ConfigUtil().getInteger( ConfigConst.CONSTRAINED_DEVICE, ConfigConst.POLL_CYCLES_KEY, ConfigConst.DEFAULT_POLL_CYCLES) self.coapClient = CoapClientConnector() self.coapServer = CoapServerAdapter( dataMsgListener=self.dataMsgListener) self.tempDataUpdateListener = GetTelemetryResourceHandler() self.sysPerfDataUpdateListener = GetSystemPerformanceResourceHandler() # add these CoAP resource handlers as listeners to the IDataMessageListener impl self.dataMsgListener.setTelemetryDataListener( ConfigConst.TEMP_SENSOR_NAME, self.tempDataUpdateListener) self.dataMsgListener.setSystemPerformanceDataListener( self.sysPerfDataUpdateListener) # add these CoAP resource handlers to the CoAP server self.coapServer.addResource( \ ResourceNameEnum.CDA_SENSOR_MSG_RESOURCE, \ ConfigConst.TEMP_SENSOR_NAME, \ self.tempDataUpdateListener) self.coapServer.addResource( \ ResourceNameEnum.CDA_SYSTEM_PERF_MSG_RESOURCE, \ ConfigConst.SYSTEM_PERF_NAME, \ self.sysPerfDataUpdateListener) # create a scheduler to update system perf data and temp sensor data at pollCycles self.scheduler = BackgroundScheduler() self.scheduler.add_job(self._updateTelemetry, 'interval', seconds=self.pollRate) # start the server and the scheduled data updater self.coapServer.startServer() self.scheduler.start() @classmethod def tearDownClass(self): self.scheduler.shutdown() self.coapServer.stopServer() def setUp(self): pass def tearDown(self): pass #@unittest.skip("Ignore for now.") def testConnectAndDiscover(self): """ Comment the annotation to test Connect and Discover """ self.coapClient.sendDiscoveryRequest(timeout=5) sleep(5) #@unittest.skip("Ignore for now.") def testConnectAndGetCon(self): """ Comment the annotation to test CON GET """ self.coapClient.sendGetRequest( \ resource = ResourceNameEnum.CDA_SENSOR_MSG_RESOURCE, name = ConfigConst.TEMP_SENSOR_NAME, enableCON = True, timeout = 5) sleep(5) self.coapClient.sendGetRequest( \ resource = ResourceNameEnum.CDA_SENSOR_MSG_RESOURCE, name = ConfigConst.TEMP_SENSOR_NAME, enableCON = True, timeout = 5) sleep(5) self.coapClient.sendGetRequest( \ resource = ResourceNameEnum.CDA_SENSOR_MSG_RESOURCE, name = ConfigConst.TEMP_SENSOR_NAME, enableCON = True, timeout = 5) @unittest.skip("Ignore for now.") def testConnectAndGetNon(self): """ Comment the annotation to test NON GET """ self.coapClient.sendGetRequest( \ resource = ResourceNameEnum.CDA_MGMT_STATUS_MSG_RESOURCE, enableCON = False, timeout = 5) @unittest.skip("Ignore for now.") def testConnectAndDeleteCon(self): """ Comment the annotation to test CON DELETE """ self.coapClient.sendDeleteRequest( \ resource = ResourceNameEnum.CDA_MGMT_STATUS_MSG_RESOURCE, enableCON = True, timeout = 5) @unittest.skip("Ignore for now.") def testConnectAndDeleteNon(self): """ Comment the annotation to test NON DELETE """ self.coapClient.sendDeleteRequest( \ resource = ResourceNameEnum.CDA_MGMT_STATUS_MSG_RESOURCE, enableCON = False, timeout = 5) @unittest.skip("Ignore for now.") def testObserveForTwoMinutes(self): """ Comment the annotation to test Observe """ self._startObserver() sleep(120) self._stopObserver() @unittest.skip("Ignore for now.") def testConnectAndPostCon(self): """ Comment the annotation to test CON POST """ msg = "This is a test." self.coapClient.sendPostRequest( resource=ResourceNameEnum.CDA_MGMT_STATUS_MSG_RESOURCE, payload=msg, enableCON=True, timeout=5) @unittest.skip("Ignore for now.") def testConnectAndPostNon(self): """ Comment the annotation to test NON POST """ msg = "This is a test." self.coapClient.sendPostRequest( resource=ResourceNameEnum.CDA_MGMT_STATUS_MSG_RESOURCE, payload=msg, enableCON=False, timeout=5) @unittest.skip("Ignore for now.") def testConnectAndPutCon(self): """ Comment the annotation to test CON PUT """ msg = "This is a test." self.coapClient.sendPutRequest( resource=ResourceNameEnum.CDA_MGMT_STATUS_MSG_RESOURCE, payload=msg, enableCON=True, timeout=5) @unittest.skip("Ignore for now.") def testConnectAndPutNon(self): """ Comment the annotation to test NON PUT """ msg = "This is a test." self.coapClient.sendPutRequest( resource=ResourceNameEnum.CDA_MGMT_STATUS_MSG_RESOURCE, payload=msg, enableCON=False, timeout=5) @classmethod def _updateTelemetry(self): sysPerfVal = random.uniform(1.0, 50.0) tempVal = random.uniform(18.0, 22.0) sysPerfData = SystemPerformanceData() sysPerfData.setName("SystemPerfMsg") sysPerfData.setCpuUtilization(sysPerfVal) sysPerfData.setDiskUtilization(sysPerfVal) sysPerfData.setMemoryUtilization(sysPerfData) # Uncomment the next SLOC to trigger data message listener callback for perf data #self.dataMsgListener.handleSystemPerformanceMessage(sysPerfData) sensorData = SensorData() sensorData.setName(ConfigConst.TEMP_SENSOR_NAME) sensorData.setValue(tempVal) self.dataMsgListener.handleSensorMessage(sensorData) def _startObserver(self): self.coapClient.startObserver( resource=ResourceNameEnum.CDA_SENSOR_MSG_RESOURCE, name=ConfigConst.TEMP_SENSOR_NAME) self.coapClient.startObserver( resource=ResourceNameEnum.CDA_SYSTEM_PERF_MSG_RESOURCE, name=ConfigConst.SYSTEM_PERF_NAME) def _stopObserver(self): self.coapClient.stopObserver( resource=ResourceNameEnum.CDA_SENSOR_MSG_RESOURCE, name=ConfigConst.TEMP_SENSOR_NAME) self.coapClient.stopObserver( resource=ResourceNameEnum.CDA_SYSTEM_PERF_MSG_RESOURCE, name=ConfigConst.SYSTEM_PERF_NAME)
class CoapClientPerformanceTest(unittest.TestCase): """ This test case class contains very basic performance tests for CoapClientConnector. It should not be considered complete, but serve as a starting point for the student implementing additional functionality within their Programming the IoT environment. """ NS_IN_MILLIS = 1000000 MAX_TEST_RUNS = 10000 @classmethod def setUpClass(self): logging.disable(level=logging.WARNING) def setUp(self): self.coapClient = CoapClientConnector() def tearDown(self): self.coapClient.disconnectClient() #@unittest.skip("Ignore for now.") def testGetRequestCon(self): """ Comment the annotation to perf test CON GET """ print("Testing GET - CON") self._execTestGet(self.MAX_TEST_RUNS, True) #@unittest.skip("Ignore for now.") def testGetRequestNon(self): """ Comment the annotation to perf test NON GET """ print("Testing GET - NON") self._execTestGet(self.MAX_TEST_RUNS, False) @unittest.skip("Ignore for now.") def testPostRequestCon(self): """ Comment the annotation to perf test CON POST """ print("Testing POST - CON") self._execTestPost(self.MAX_TEST_RUNS, True) @unittest.skip("Ignore for now.") def testPostRequestNon(self): """ Comment the annotation to perf test NON POST """ print("Testing POST - NON") self._execTestPost(self.MAX_TEST_RUNS, False) #@unittest.skip("Ignore for now.") def testPutRequestCon(self): """ Comment the annotation to perf test CON PUT """ print("Testing PUT - CON") self._execTestPut(self.MAX_TEST_RUNS, True) #@unittest.skip("Ignore for now.") def testPutRequestNon(self): """ Comment the annotation to perf test NON PUT """ print("Testing PUT - NON") self._execTestPut(self.MAX_TEST_RUNS, False) def _execTestGet(self, maxTestRuns: int, useCon: bool): startTime = time.time_ns() for seqNo in range(0, maxTestRuns): self.coapClient.sendGetRequest( resource=ResourceNameEnum.CDA_ACTUATOR_CMD_RESOURCE, enableCON=useCon) endTime = time.time_ns() elapsedMillis = (endTime - startTime) / self.NS_IN_MILLIS print("\nGET message - useCON = " + str(useCon) + " [" + str(maxTestRuns) + "]: " + str(elapsedMillis) + " ms") sleep(2) def _execTestPost(self, maxTestRuns: int, useCon: bool): sensorData = SensorData() payload = DataUtil().sensorDataToJson(sensorData) startTime = time.time_ns() for seqNo in range(0, maxTestRuns): self.coapClient.sendPostRequest( resource=ResourceNameEnum.CDA_SENSOR_MSG_RESOURCE, enableCON=useCon, payload=payload) endTime = time.time_ns() elapsedMillis = (endTime - startTime) / self.NS_IN_MILLIS print("\nPOST message - useCON = " + str(useCon) + " [" + str(maxTestRuns) + "]: " + str(elapsedMillis) + " ms. Payload Len: " + str(len(payload))) sleep(2) def _execTestPut(self, maxTestRuns: int, useCon: bool): sensorData = SensorData() payload = DataUtil().sensorDataToJson(sensorData) startTime = time.time_ns() for seqNo in range(0, maxTestRuns): self.coapClient.sendPostRequest( resource=ResourceNameEnum.CDA_SENSOR_MSG_RESOURCE, enableCON=useCon, payload=payload) endTime = time.time_ns() elapsedMillis = (endTime - startTime) / self.NS_IN_MILLIS print("\nPUT message - useCON = " + str(useCon) + " [" + str(maxTestRuns) + "]: " + str(elapsedMillis) + " ms. Payload Len: " + str(len(payload))) sleep(2)
class DeviceDataManager(IDataMessageListener): """ Shell representation of class for student implementation. """ def __init__(self, enableMqtt: bool = True, enableCoap: bool = False): """ Initialization of class. Create an instance of DeviceDataManager """ self.configUtil = ConfigUtil() self.enableEmulator = self.configUtil.getBoolean( ConfigConst.CONSTRAINED_DEVICE, ConfigConst.ENABLE_EMULATOR_KEY) self.enableRedis = False self.sysPerfManager = SystemPerformanceManager() self.sysPerfManager.setDataMessageListener(self) self.sensorAdapterManager = SensorAdapterManager( useEmulator=self.enableEmulator) self.sensorAdapterManager.setDataMessageListener(self) self.actuatorAdapterManager = ActuatorAdapterManager( useEmulator=self.enableEmulator) self.actuatorAdapterManager.setDataMessageListener(self) ##add by miaoyao @10/30/2020 if self.enableRedis: self.redisClient = RedisPersistenceAdapter() self.enableHandleTempChangeOnDevice = self.configUtil.getBoolean( ConfigConst.CONSTRAINED_DEVICE, ConfigConst.ENABLE_HANDLE_TEMP_CHANGE_ON_DEVICE_KEY) self.triggerHvacTempFloor = self.configUtil.getFloat( ConfigConst.CONSTRAINED_DEVICE, ConfigConst.TRIGGER_HVAC_TEMP_FLOOR_KEY) self.triggerHvacTempCeiling = self.configUtil.getFloat( ConfigConst.CONSTRAINED_DEVICE, ConfigConst.TRIGGER_HVAC_TEMP_CEILING_KEY) ##add by miaoyao for final project self.enableHandleSoilHumidityChangeOnDevice = self.configUtil.getBoolean( ConfigConst.CONSTRAINED_DEVICE, ConfigConst.ENABLE_HANDLE_SOIL_HUMIDITY_CHANGE_ON_DEVICE_KEY) self.triggerWaterDeviceHumiFloor = self.configUtil.getFloat( ConfigConst.CONSTRAINED_DEVICE, ConfigConst.TRIGGER_WATER_SOIL_HUMI_FLOOR_KEY) self.triggerWaterDeviceHumiCeiling = self.configUtil.getFloat( ConfigConst.CONSTRAINED_DEVICE, ConfigConst.TRIGGER_WATER_SOIL_HUMI_CEILING_KEY) ##add by miaoyao @11/02/2020 ##self.enableMqtt = self.configUtil.getBoolean(ConfigConst.CONSTRAINED_DEVICE, ConfigConst.ENABLE_MQTT_KEY) self.enableMqtt = enableMqtt self.enableCoap = enableCoap if self.enableMqtt: self.mqttClient = MqttClientConnector() self.mqttClient.setDataMessageListener(self) if self.enableCoap: self.coapClient = CoapClientConnector() self.coapClient.setDataMessageListener(self) def handleActuatorCommandResponse(self, data: ActuatorData) -> bool: """ handle the ActuatorCommandResponse @return bool """ # Use the DataUtil class to convert the ActuatorData to JSON. logging.info( "[CDA_CALLBACK]----->>>The handleActuatorCommandResponse method is being called" ) adJson = DataUtil.actuatorDataToJson(self, data) self._handleUpstreamTransmission( ResourceNameEnum.CDA_ACTUATOR_RESPONSE_RESOURCE, adJson) def handleActuatorCommandMessage(self, data: ActuatorData) -> bool: """ handle the handleActuatorCommandMessage @return bool """ logging.info( "[CDA_CALLBACK]----->>>The handleActuatorCommandMessage method is being called" ) if data: logging.info("Processing actuator command message.") # TODO: add further validation before sending the command self.actuatorAdapterManager.sendActuatorCommand(data) return True else: logging.warning( "Received invalid ActuatorData command message. Ignoring.") return False def handleIncomingMessage(self, resourceEnum: ResourceNameEnum, msg: str) -> bool: """ handle the IncomingMessage @return bool """ logging.info( "[CDA_CALLBACK]----->>>The handleIncomingMessage method is being called" ) # Use the DataUtil class to convert the msg content (which should be JSON) to an ActuatorData instance ad = DataUtil.jsonToActuatorData(self, msg) self._handleIncomingDataAnalysis(msg) def handleSensorMessage(self, data: SensorData) -> bool: """ handle the SensorMessage @return bool """ logging.info( "[CDA_CALLBACK]----->>>The handleSensorMessage method is being called" ) # Use the DataUtil class to convert the SensorData to JSON sdJosn = DataUtil.sensorDataToJson(self, data) self._handleUpstreamTransmission( ResourceNameEnum.CDA_SENSOR_MSG_RESOURCE, sdJosn) self._handleSensorDataAnalysis(data) if self.enableRedis: self.redisClient.storeData( ResourceNameEnum.CDA_SENSOR_MSG_RESOURCE, data) def handleSystemPerformanceMessage(self, data: SystemPerformanceData) -> bool: """ handle the SystemPerformanceMessage @return bool """ logging.info( "[CDA_CALLBACK]----->>>The handleSystemPerformanceMessage method is being called" ) spmJson = DataUtil.systemPerformanceDataToJson(self, data) self._handleUpstreamTransmission( ResourceNameEnum.CDA_SYSTEM_PERF_MSG_RESOURCE, spmJson) def startManager(self): """ Start the DeviceDataManager. Calls startManager() on the sysPerfManager instance. Calls startManager() on the sensorAdapterManager instance. """ logging.info("----->>>The DeviceDataManager will be started") self.sysPerfManager.startManager() self.sensorAdapterManager.startManager() if self.enableRedis: self.redisClient.connectClient() if self.enableMqtt: self.mqttClient.connectClient() def stopManager(self): """ Stop the DeviceDataManager. Calls stopManager() on the sysPerfManager instance. Calls stopManager() on the sensorAdapterManager instance. """ self.sysPerfManager.stopManager() self.sensorAdapterManager.stopManager() if self.enableRedis: self.redisClient.disconnectClient() if self.enableMqtt: self.mqttClient.disconnectClient() logging.info("----->>>The DeviceDataManager stopped") def _handleIncomingDataAnalysis(self, msg: str): """ Call this from handleIncomeMessage() to determine if there's any action to take on the message. Steps to take: 1) Validate msg: Most will be ActuatorData, but you may pass other info as well. 2) Convert msg: Use DataUtil to convert if appropriate. 3) Act on msg: Determine what - if any - action is required, and execute. """ logging.info( "[CDA_CALLBACK]----->>>The _handleIncomingDataAnalysis method is being called" ) ad = DataUtil.jsonToActuatorData(self, msg) self.actuatorAdapterManager.sendActuatorCommand(ad) def _handleSensorDataAnalysis(self, data: SensorData): """ Call this from handleSensorMessage() to determine if there's any action to take on the message. Steps to take: 1) Check config: Is there a rule or flag that requires immediate processing of data? 2) Act on data: If # 1 is true, determine what - if any - action is required, and execute. """ logging.info( "[CDA_CALLBACK]----->>>The _handleSensorDataAnalysis method is being called" ) """ """ if self.enableHandleTempChangeOnDevice and data.getSensorType( ) == SensorData.TEMP_SENSOR_TYPE: ad = ActuatorData(actuatorType=ActuatorData.HVAC_ACTUATOR_TYPE) value = data.getValue() if value >= self.triggerHvacTempFloor and value <= self.triggerHvacTempCeiling: ad.setCommand(ActuatorData.COMMAND_OFF) else: ad.setCommand(ActuatorData.COMMAND_ON) self.actuatorAdapterManager.sendActuatorCommand(ad) """ """ if self.enableHandleSoilHumidityChangeOnDevice and data.getSensorType( ) == SensorData.SOIL_HUMIDITY_SENSOR_TYPE: ad = ActuatorData( actuatorType=ActuatorData.SPRINKLER_ACTUATOR_TYPE) value = data.getValue() if value >= self.triggerWaterDeviceHumiCeiling: ad.setCommand(ActuatorData.COMMAND_OFF) self.actuatorAdapterManager.sendActuatorCommand(ad) elif value <= self.triggerWaterDeviceHumiFloor: ad.setCommand(ActuatorData.COMMAND_ON) self.actuatorAdapterManager.sendActuatorCommand(ad) self.coapClient.sendGetRequest( ResourceNameEnum.CDA_ACTUATOR_CMD_RESOURCE, False, 5) else: self.coapClient.sendGetRequest( ResourceNameEnum.CDA_CLOUD_ACTUATOR_CMD_RESOURCE, False, 5) def _handleUpstreamTransmission(self, resourceName: ResourceNameEnum, msg: str): """ Call this from handleActuatorCommandResponse(), handlesensorMessage(), and handleSystemPerformanceMessage() to determine if the message should be sent upstream. Steps to take: 1) Check connection: Is there a client connection configured (and valid) to a remote MQTT or CoAP server? 2) Act on msg: If # 1 is true, send message upstream using one (or both) client connections. """ logging.info( "[callback]----->>>The _handleUpstreamTransmission method is being called" ) if self.enableMqtt: self.mqttClient.publishMessage(resourceName, msg) """