def test_WakeFromDeepSleepAndRunService(self): svc = TestService(Service.MODE_RUN_PERIODIC, {}, 20, test_ServiceScheduler.PeriodicServiceRun) svc_name = svc.SvcName self.Scheduler.ServiceRegister(svc) svc.SvcActivate() exc_occurred = False try: self.Scheduler.Run() except DeepSleepExceptionFailed: exc_occurred = True self.assertTrue(exc_occurred) self.assertTrue(machine.is_asleep()) new_svc = TestService(Service.MODE_RUN_PERIODIC, {}, 20, test_ServiceScheduler.PeriodicServiceRun, svc_name) new_sched = ServiceScheduler() new_sched.ServiceRegister(new_svc) exc_occurred = False try: new_sched.Run() except DeepSleepExceptionFailed: exc_occurred = True self.assertTrue(exc_occurred) self.assertEqual(new_svc.SvcRun.CallCount, 1) self.assertTrue(machine.is_asleep())
def __init__(self, netcon_obj): # Create objects. self.Time = SystemTime.InstanceGet() WebApp.NetCon = netcon_obj self.Scheduler = ServiceScheduler()
class WebApp: PRODUCT_NAME = "smartsensor" DIR = "./" ID = str(ubinascii.hexlify(machine.unique_id()).decode('utf-8')) RETRIES = 3 BROKER = '192.168.0.103' PORT = 1883 ApCfg = {"ssid": "SmartSensor-" + ID, "pwd": "mato", "ip": "192.168.0.200"} Time = None NetCon = None WebserverInterval = const(1) WebpageTitle = "SmartSensor - WiFi instellingen" Webpage = """<html><head> <title>""" + WebpageTitle + """</title> <meta name="viewport" content="width=device-width, initial-scale=1"> <link rel="icon" href="data:,"> <style>html{font-family: Helvetica; display:inline-block; margin: 0px auto; text-align: center;} h1{color: #0F3376; padding: 2vh;}p{font-size: 1.5rem;}.button{display: inline-block; background-color: #e7bd3b; border: none; border-radius: 4px; color: white; padding: 16px 40px; text-decoration: none; font-size: 30px; margin: 2px; cursor: pointer;} .button2{background-color: #4286f4;} </style> </head> <body> <h1>""" + WebpageTitle + """</h1> <h2>Sensor ID: """ + ID + """</h2> <form action="/wifi_settings.php"> Netwerk naam (SSID): <input type="text" name="ssid" value=""><br> Wachtwoord: <input type="password" name="pwd" value=""><br> <input type="submit" value="Opslaan"> </form> </body> </html>""" Ssid = None Pwd = None def __init__(self, netcon_obj): # Create objects. self.Time = SystemTime.InstanceGet() WebApp.NetCon = netcon_obj self.Scheduler = ServiceScheduler() def Setup(self): # Create LED driver instances. self.LedRed = Led(Pins.CFG_HW_PIN_LED_RED) self.LedGreen = Led(Pins.CFG_HW_PIN_LED_GREEN) self.LedBlue = Led(Pins.CFG_HW_PIN_LED_BLUE) wlan_ap = WLAN(network.AP_IF) self.NetCon.WlanInterface(wlan_ap, NetCon.MODE_ACCESS_POINT) self.Webserver = Webserver(self.Webpage) self.Webserver.RegisterQueryHandle('ssid', WebApp.QueryHandleWifiSsid) self.Webserver.RegisterQueryHandle('pwd', WebApp.QueryHandleWifiPwd) self.Webserver.SvcDependencies( {self.NetCon: Service.DEP_TYPE_RUN_ALWAYS_BEFORE_INIT}) self.Scheduler.ServiceRegister(self.NetCon) self.Scheduler.ServiceRegister(self.Webserver) self.Webserver.SvcIntervalSet(self.WebserverInterval) def Reset(self): return def Run(self): self.Scheduler.Run() @staticmethod def QueryHandleWifiSsid(query, value): print("{}:{}".format(query, value)) WebApp.Ssid = value if WebApp.Pwd is not None: WebApp.SaveAndReset() @staticmethod def QueryHandleWifiPwd(query, value): print("{}:{}".format(query, value)) WebApp.Pwd = value if WebApp.Ssid is not None: WebApp.SaveAndReset() @staticmethod def SaveAndReset(): WebApp.NetCon.StationSettingsStore(WebApp.Ssid, WebApp.Pwd) WebApp.NetCon.AccessPointStop() utime.sleep(1) machine.reset()
class DemoApp: PRODUCT_NAME = "smartsensor" DIR = "./" ID = str(ubinascii.hexlify(machine.unique_id()).decode('utf-8')) RETRIES = 3 BROKER = BROKER_IP_PI PORT = 1883 FILTER_DEPTH = const(6) DEEPSLEEP_THRESHOLD_SEC = const(5) MOIST_RANGE_MIN = const(200) MOIST_RANGE_MAX = const(2000) MOIST_NOTIF_TIME = const(1) MOIST_NOTIF_PRIO = const(5) SUPPLY_SETTLE_TIME_MS = const(50) NetCon = None UrlFields = { MessageSpecification.URL_FIELD_DEVICE_ID: ID, MessageSpecification.URL_FIELD_PRODUCT_NAME: PRODUCT_NAME } SamplesPerMessage = const(1) # Service intervals in seconds. MsgExInterval = const(20) MoistSensorReadInterval = const(2) EnvSensorReadInterval = const(15) NotificationInterval = const(2) APP_MODE_SCAN = const(0) APP_MODE_CALIBRATION = const(1) Mode = APP_MODE_SCAN StartApp = False CALIB_STATE_SET_LOW = const(0) CALIB_STATE_SET_HIGH = const(1) CALIB_STATE_SET_SYNC = const(2) CalibState = CALIB_STATE_SET_LOW def __init__(self, netcon_obj): # Configure the URL fields. MessageSpecification.Config(self.UrlFields) DemoApp.NetCon = netcon_obj def Setup(self): # self.EnMoist = Supply(Pins.CFG_HW_PIN_MOIST_EN, self.SUPPLY_SETTLE_TIME_MS) # self.VTemp = Supply(Pins.CFG_HW_PIN_TEMP_EN, self.SUPPLY_SETTLE_TIME_MS) # self.VLdr = Supply(Pins.CFG_HW_PIN_LDR_EN, self.SUPPLY_SETTLE_TIME_MS) # self.Ap2112 = Supply(Pins.CFG_HW_PIN_HI_PWR_EN, DemoApp.SUPPLY_SETTLE_TIME_MS) # self.Ap2112.Enable() rst_reason = ResetReason.ResetReason() print("[Setup] Reset reason: {}".format( ResetReason.ResetReasonToString(rst_reason))) # Create driver instances. self.VSensor = Supply(Pins.CFG_HW_PIN_MOIST_EN, self.SUPPLY_SETTLE_TIME_MS) self.CapMoist = CapMoisture(Pins.CFG_HW_PIN_MOIST, self.VSensor) self.Mcp9700Temp = Mcp9700Temp(Pins.CFG_HW_PIN_TEMP, self.VSensor) self.Ldr = PhTLight(Pins.CFG_HW_PIN_LDR, self.VSensor) self.RgbLed = RgbLed(Pins.CFG_HW_PIN_LED_RED, Pins.CFG_HW_PIN_LED_GREEN, Pins.CFG_HW_PIN_LED_BLUE) self.Button = UserButton(Pins.CFG_HW_PIN_BTN_0, context=self, press_cb=DemoApp.ButtonPressed, release_cb=DemoApp.ButtonRelease) self.Button.Enable() # Wait until mode has been selected by the user. while DemoApp.StartApp is False: utime.sleep(1) # Continued common setup sequence after mode selection: # Create the WLAN station interface. wlan_ap = WLAN(network.STA_IF) self.Time = SystemTime.InstanceGet() self.NetCon.WlanInterface(wlan_ap, NetCon.MODE_STATION) self.TempSensor = Sensor.Sensor(self.DIR, SensorReportTemp.NAME_TEMP, self.FILTER_DEPTH, self.Mcp9700Temp, self.FILTER_DEPTH) self.MoistSensor = Sensor.Sensor(self.DIR, SensorReportMoist.NAME_MOIST, self.FILTER_DEPTH, self.CapMoist, self.FILTER_DEPTH) self.LightSensor = Sensor.Sensor(self.DIR, SensorReportLight.NAME_LIGHT, self.FILTER_DEPTH, self.Ldr, self.FILTER_DEPTH) self.MqttClient = MQTTClient(self.ID, self.BROKER, self.PORT) self.MsgEx = MessageExchange(self.DIR, self.MqttClient, self.ID, self.RETRIES) self.MsgEp = Endpoint() self.Scheduler = ServiceScheduler(self.DEEPSLEEP_THRESHOLD_SEC) # Execute mode specific setup. if DemoApp.Mode is DemoApp.APP_MODE_SCAN: self.SetupScanMode() else: self.SetupCalibMode() def SetupCalibMode(self): # Set service dependencies. self.Time.SvcDependencies( {self.NetCon: Service.DEP_TYPE_RUN_ALWAYS_BEFORE_RUN}) self.MsgEx.SvcDependencies({ self.Time: Service.DEP_TYPE_RUN_ONCE_BEFORE_RUN, self.NetCon: Service.DEP_TYPE_RUN_ALWAYS_BEFORE_INIT }) self.MoistSensor.SvcDependencies( {self.Time: Service.DEP_TYPE_RUN_ONCE_BEFORE_RUN}) # Register all services to the scheduler. self.Scheduler.ServiceRegister(self.Time) self.Scheduler.ServiceRegister(self.NetCon) self.Scheduler.ServiceRegister(self.MsgEx) self.Scheduler.ServiceRegister(self.MoistSensor) # Create message specifications. self.MoistCalibLowMsgSpec = SensorReportMoistCalibLow() self.MoistCalibHighMsgSpec = SensorReportMoistCalibHigh() self.LogMsgSpec = LogMessage() # Create MessageFormatAdapters and couple them with their message specs. self.MoistCalibLowAdapt = MessageFormatAdapter( self.MsgEp, MessageFormatAdapter.SEND_ON_COMPLETE, self.MoistCalibLowMsgSpec) self.MoistCalibHighAdapt = MessageFormatAdapter( self.MsgEp, MessageFormatAdapter.SEND_ON_COMPLETE, self.MoistCalibHighMsgSpec) self.LogAdapt = MessageFormatAdapter( self.MsgEp, MessageFormatAdapter.SEND_ON_COMPLETE, self.LogMsgSpec) # Register message specs for exchange. self.MsgEx.RegisterMessageType(self.MoistCalibLowMsgSpec) self.MsgEx.RegisterMessageType(self.MoistCalibHighMsgSpec) self.MsgEx.RegisterMessageType(self.LogMsgSpec) self.CalibObserver = CalibrationObserver() self.CalibLowStream = self.MoistCalibLowAdapt.CreateStream( SensorReportMoistCalibLow.DATA_KEY_SENSOR_REPORT_SAMPLES, self.SamplesPerMessage) self.CalibHighStream = self.MoistCalibHighAdapt.CreateStream( SensorReportMoistCalibHigh.DATA_KEY_SENSOR_REPORT_SAMPLES, self.SamplesPerMessage) # Link the observers to the sensors. self.MoistSensor.ObserverAttachNewSample(self.CalibObserver) # Create a stream for the log messages. self.LogStream = self.LogAdapt.CreateStream( LogMessage.DATA_KEY_LOG_MSG, ExtLogging.WRITES_PER_LOG) # Configure the ExtLogging class. ExtLogging.ConfigGlobal(level=ExtLogging.INFO, stream=self.LogStream) # Set service modes. self.MsgEx.SvcMode = Service.MODE_RUN_ONCE # Set intervals for periodic services. self.MoistSensor.SvcIntervalSet(self.MoistSensorReadInterval) return def SetupScanMode(self): self.Notifyer = Notifyer(self.RgbLed) # Set service dependencies. self.Time.SvcDependencies( {self.NetCon: Service.DEP_TYPE_RUN_ALWAYS_BEFORE_RUN}) self.MoistSensor.SvcDependencies( {self.Time: Service.DEP_TYPE_RUN_ONCE_BEFORE_RUN}) self.Notifyer.SvcDependencies( {self.MoistSensor: Service.DEP_TYPE_RUN_ALWAYS_BEFORE_RUN}) self.TempSensor.SvcDependencies( {self.Time: Service.DEP_TYPE_RUN_ONCE_BEFORE_RUN}) self.LightSensor.SvcDependencies( {self.Time: Service.DEP_TYPE_RUN_ONCE_BEFORE_RUN}) self.MsgEx.SvcDependencies({ self.Time: Service.DEP_TYPE_RUN_ONCE_BEFORE_RUN, self.NetCon: Service.DEP_TYPE_RUN_ALWAYS_BEFORE_INIT, self.TempSensor: Service.DEP_TYPE_RUN_ONCE_BEFORE_RUN, self.LightSensor: Service.DEP_TYPE_RUN_ONCE_BEFORE_RUN }) # Register all services to the scheduler. self.Scheduler.ServiceRegister(self.Time) self.Scheduler.ServiceRegister(self.NetCon) self.Scheduler.ServiceRegister(self.MsgEx) self.Scheduler.ServiceRegister(self.MoistSensor) self.Scheduler.ServiceRegister(self.Notifyer) self.Scheduler.ServiceRegister(self.LightSensor) self.Scheduler.ServiceRegister(self.TempSensor) # Create message specifications. self.TempMsgSpec = SensorReportTemp() self.MoistMsgSpec = SensorReportMoist() self.LightMsgSpec = SensorReportLight() self.LogMsgSpec = LogMessage() # Create MessageFormatAdapters and couple them with their message specs. self.TempAdapt = MessageFormatAdapter( self.MsgEp, MessageFormatAdapter.SEND_ON_COMPLETE, self.TempMsgSpec) self.MoistAdapt = MessageFormatAdapter( self.MsgEp, MessageFormatAdapter.SEND_ON_COMPLETE, self.MoistMsgSpec) self.LightAdapt = MessageFormatAdapter( self.MsgEp, MessageFormatAdapter.SEND_ON_COMPLETE, self.LightMsgSpec) self.LogAdapt = MessageFormatAdapter( self.MsgEp, MessageFormatAdapter.SEND_ON_COMPLETE, self.LogMsgSpec) # Register message specs for exchange. self.MsgEx.RegisterMessageType(self.TempMsgSpec) self.MsgEx.RegisterMessageType(self.MoistMsgSpec) self.MsgEx.RegisterMessageType(self.LightMsgSpec) self.MsgEx.RegisterMessageType(self.LogMsgSpec) # Create observers for the sensor data. self.TempObserver = self.TempAdapt.CreateObserver( SensorReportTemp.DATA_KEY_SENSOR_REPORT_SAMPLES, self.SamplesPerMessage) self.MoistObserver = self.MoistAdapt.CreateObserver( SensorReportMoist.DATA_KEY_SENSOR_REPORT_SAMPLES, self.SamplesPerMessage) self.LightObserver = self.LightAdapt.CreateObserver( SensorReportLight.DATA_KEY_SENSOR_REPORT_SAMPLES, self.SamplesPerMessage) # Set the notification ranges and colors. moist_th_range = NotificationRange(self.MOIST_RANGE_MIN, self.MOIST_RANGE_MAX) moist_color_map = { RgbLed.RGB_COLOR_RED: NotificationRange(self.MOIST_RANGE_MAX, self.MOIST_RANGE_MIN), RgbLed.RGB_COLOR_BLUE: NotificationRange(self.MOIST_RANGE_MIN, self.MOIST_RANGE_MAX) } self.MoistNotif = Notification(moist_th_range, moist_color_map, self.MOIST_NOTIF_PRIO, self.MOIST_NOTIF_TIME) self.Notifyer.NotificationRegister(self.MoistNotif) # Link the observers to the sensors. self.TempSensor.ObserverAttachNewSample(self.TempObserver) self.MoistSensor.ObserverAttachNewSample(self.MoistObserver) self.MoistSensor.ObserverAttachNewSample(self.MoistNotif) self.LightSensor.ObserverAttachNewSample(self.LightObserver) # Create a stream for the log messages. self.LogStream = self.LogAdapt.CreateStream( LogMessage.DATA_KEY_LOG_MSG, ExtLogging.WRITES_PER_LOG) # Configure the ExtLogging class. ExtLogging.ConfigGlobal(level=ExtLogging.INFO, stream=self.LogStream) # Set service modes. self.MsgEx.SvcMode = Service.MODE_RUN_ONCE self.TempSensor.SvcMode = Service.MODE_RUN_ONCE self.LightSensor.SvcMode = Service.MODE_RUN_ONCE # Set intervals for periodic services. self.MoistSensor.SvcIntervalSet(self.MoistSensorReadInterval) self.Notifyer.SvcIntervalSet(self.NotificationInterval) def Run(self): # Execute mode run function. if DemoApp.Mode is DemoApp.APP_MODE_SCAN: self.RunScanMode() else: self.RunCalibMode() def RunScanMode(self): self.Button.Disable() self.Scheduler.Run(50) self.MoistSensor.SvcDisable() self.Notifyer.SvcDisable() self.MsgEx.SvcActivate() self.TempSensor.SvcActivate() self.LightSensor.SvcActivate() self.Scheduler.Run(15) self.Scheduler.RequestDeepSleep(0) def RunCalibMode(self): while DemoApp.CalibState is not DemoApp.CALIB_STATE_SET_SYNC: if DemoApp.CalibState is DemoApp.CALIB_STATE_SET_LOW: self.RgbLed.Red.On() elif DemoApp.CalibState is DemoApp.CALIB_STATE_SET_HIGH: self.RgbLed.Red.Off() self.RgbLed.Blue.On() self.Scheduler.Run(5) self.MoistSensor.SvcDisable() self.MsgEx.SvcActivate() self.RgbLed.Blue.Off() self.Scheduler.Run(15) self.Scheduler.RequestDeepSleep(0) def Reset(self): self.MsgEx.Reset() self.TempSensor.SamplesDelete() self.MoistSensor.SamplesDelete() self.LightSensor.SamplesDelete() self.NetCon.StationSettingsReset() def ButtonPressed(self, *args): if DemoApp.StartApp is False: self.RgbLed.Green.On() return def ButtonRelease(self, *args): if DemoApp.StartApp is False: self.RgbLed.Green.Off() hold_index = args[UserButton.CALLBACK_ARG_HOLD_INDEX] press_count = args[UserButton.CALLBACK_ARG_PRESS_COUNT] if hold_index is -1: DemoApp.Mode = DemoApp.APP_MODE_SCAN else: DemoApp.Mode = DemoApp.APP_MODE_CALIBRATION self.RgbLed.Red.On() DemoApp.StartApp = True # Activate the Message Exchange service to # sync the calibration with the server. elif DemoApp.StartApp is True and DemoApp.Mode is DemoApp.APP_MODE_CALIBRATION: if DemoApp.CalibState is DemoApp.CALIB_STATE_SET_LOW: calib_value = self.CalibObserver.CalibValue self.CalibLowStream.write(calib_value) DemoApp.CalibState = DemoApp.CALIB_STATE_SET_HIGH print("[App] Setting low calibration value") elif DemoApp.CalibState is DemoApp.CALIB_STATE_SET_HIGH: calib_value = self.CalibObserver.CalibValue self.CalibHighStream.write(calib_value) DemoApp.CalibState = DemoApp.CALIB_STATE_SET_SYNC print("[App] Setting high calibration value") return
def Setup(self): # self.EnMoist = Supply(Pins.CFG_HW_PIN_MOIST_EN, self.SUPPLY_SETTLE_TIME_MS) # self.VTemp = Supply(Pins.CFG_HW_PIN_TEMP_EN, self.SUPPLY_SETTLE_TIME_MS) # self.VLdr = Supply(Pins.CFG_HW_PIN_LDR_EN, self.SUPPLY_SETTLE_TIME_MS) # self.Ap2112 = Supply(Pins.CFG_HW_PIN_HI_PWR_EN, DemoApp.SUPPLY_SETTLE_TIME_MS) # self.Ap2112.Enable() rst_reason = ResetReason.ResetReason() print("[Setup] Reset reason: {}".format( ResetReason.ResetReasonToString(rst_reason))) # Create driver instances. self.VSensor = Supply(Pins.CFG_HW_PIN_MOIST_EN, self.SUPPLY_SETTLE_TIME_MS) self.CapMoist = CapMoisture(Pins.CFG_HW_PIN_MOIST, self.VSensor) self.Mcp9700Temp = Mcp9700Temp(Pins.CFG_HW_PIN_TEMP, self.VSensor) self.Ldr = PhTLight(Pins.CFG_HW_PIN_LDR, self.VSensor) self.RgbLed = RgbLed(Pins.CFG_HW_PIN_LED_RED, Pins.CFG_HW_PIN_LED_GREEN, Pins.CFG_HW_PIN_LED_BLUE) self.Button = UserButton(Pins.CFG_HW_PIN_BTN_0, context=self, press_cb=DemoApp.ButtonPressed, release_cb=DemoApp.ButtonRelease) self.Button.Enable() # Wait until mode has been selected by the user. while DemoApp.StartApp is False: utime.sleep(1) # Continued common setup sequence after mode selection: # Create the WLAN station interface. wlan_ap = WLAN(network.STA_IF) self.Time = SystemTime.InstanceGet() self.NetCon.WlanInterface(wlan_ap, NetCon.MODE_STATION) self.TempSensor = Sensor.Sensor(self.DIR, SensorReportTemp.NAME_TEMP, self.FILTER_DEPTH, self.Mcp9700Temp, self.FILTER_DEPTH) self.MoistSensor = Sensor.Sensor(self.DIR, SensorReportMoist.NAME_MOIST, self.FILTER_DEPTH, self.CapMoist, self.FILTER_DEPTH) self.LightSensor = Sensor.Sensor(self.DIR, SensorReportLight.NAME_LIGHT, self.FILTER_DEPTH, self.Ldr, self.FILTER_DEPTH) self.MqttClient = MQTTClient(self.ID, self.BROKER, self.PORT) self.MsgEx = MessageExchange(self.DIR, self.MqttClient, self.ID, self.RETRIES) self.MsgEp = Endpoint() self.Scheduler = ServiceScheduler(self.DEEPSLEEP_THRESHOLD_SEC) # Execute mode specific setup. if DemoApp.Mode is DemoApp.APP_MODE_SCAN: self.SetupScanMode() else: self.SetupCalibMode()
class test_ComponentIntegration(unittest.TestCase): PRODUCT_NAME = "smartsensor" DIR = "./" ID = '3f7e12c9' RETRIES = 3 BROKER = '192.168.0.103' PORT = 1883 ApCfg = {"ssid": "test", "pwd": "123", "ip": "127.0.0.1"} MqttClient = None MsgEx = None Time = None UrlFields = { MessageSpecification.URL_FIELD_DEVICE_ID: ID, MessageSpecification.URL_FIELD_PRODUCT_NAME: PRODUCT_NAME } TempSamples = [20, 21, 25, 30, 35, 35, 20, 12, 10, 40] MoistSamples = [200, 300, 350, 360, 290, 500, 250, 300, 240, 320] SamplesPerMessage = const(1) MsgExInterval = const(20) SensorReadInterval = const(10) RecvTopic = None RecvMsg = None RecvMsgCount = 0 def setUp(self): # Configure the URL fields. MessageSpecification.Config(self.UrlFields) # Create objects. filter_depth = len(self.TempSamples) / 2 dummy_temp_sensor = DummySensor.DummySensor(self.TempSamples) dummy_moist_sensor = DummySensor.DummySensor(self.MoistSamples) wlan_ap = WLAN() self.Time = SystemTime.InstanceGet() self.NetCon = NetCon(self.DIR, self.ApCfg, NetCon.MODE_STATION, wlan_ap) self.TempSensor = Sensor.Sensor(self.DIR, SensorReportTemp.NAME_TEMP, filter_depth, dummy_temp_sensor) self.MoistSensor = Sensor.Sensor(self.DIR, SensorReportMoist.NAME_MOIST, filter_depth, dummy_moist_sensor) self.MqttClient = MQTTClient(self.ID, self.BROKER, self.PORT) self.MsgEx = MessageExchange(self.DIR, self.MqttClient, self.ID, self.RETRIES) self.MsgEp = Endpoint() self.Scheduler = ServiceScheduler() # Set service dependencies. self.Time.SvcDependencies( {self.NetCon: Service.DEP_TYPE_RUN_ALWAYS_BEFORE_RUN}) self.MsgEx.SvcDependencies({ self.Time: Service.DEP_TYPE_RUN_ONCE_BEFORE_RUN, self.NetCon: Service.DEP_TYPE_RUN_ALWAYS_BEFORE_INIT }) self.TempSensor.SvcDependencies( {self.Time: Service.DEP_TYPE_RUN_ONCE_BEFORE_RUN}) self.MoistSensor.SvcDependencies( {self.Time: Service.DEP_TYPE_RUN_ONCE_BEFORE_RUN}) # Register all services to the scheduler. self.Scheduler.ServiceRegister(self.Time) self.Scheduler.ServiceRegister(self.NetCon) self.Scheduler.ServiceRegister(self.MsgEx) self.Scheduler.ServiceRegister(self.TempSensor) self.Scheduler.ServiceRegister(self.MoistSensor) # Create message specifications. self.TempMsgSpec = SensorReportTemp() self.MoistMsgSpec = SensorReportMoist() self.LogMsgSpec = LogMessage() # Create a Messaging Endpoint and MessageFormatAdapters. self.TempAdapt = MessageFormatAdapter( self.MsgEp, MessageFormatAdapter.SEND_ON_COMPLETE, self.TempMsgSpec) self.MoistAdapt = MessageFormatAdapter( self.MsgEp, MessageFormatAdapter.SEND_ON_COMPLETE, self.MoistMsgSpec) self.LogAdapt = MessageFormatAdapter( self.MsgEp, MessageFormatAdapter.SEND_ON_COMPLETE, self.LogMsgSpec) # Register message specs. self.MsgEx.RegisterMessageType(self.TempMsgSpec) self.MsgEx.RegisterMessageType(self.MoistMsgSpec) self.MsgEx.RegisterMessageType(self.LogMsgSpec) # Create observers for the sensor data. self.TempObserver = self.TempAdapt.CreateObserver( SensorReportTemp.DATA_KEY_SENSOR_REPORT_ARRAY, self.SamplesPerMessage) self.MoistObserver = self.MoistAdapt.CreateObserver( SensorReportMoist.DATA_KEY_SENSOR_REPORT_ARRAY, self.SamplesPerMessage) # Link the observers to the sensors. self.TempSensor.ObserverAttachNewSample(self.TempObserver) self.MoistSensor.ObserverAttachNewSample(self.MoistObserver) # Create a stream for the log messages. self.LogStream = self.LogAdapt.CreateStream( LogMessage.DATA_KEY_LOG_MSG, ExtLogging.WRITES_PER_LOG) # Configure the ExtLogging class. ExtLogging.ConfigGlobal(level=ExtLogging.INFO, stream=self.LogStream) # Configure the station settings to connect to a WLAN AP. self.NetCon.StationSettingsStore(self.ApCfg["ssid"], self.ApCfg["pwd"]) # Declare test variables. self.RecvMsgCount = 0 self.RecvTopic = None self.RecvMsg = None def tearDown(self): self.MsgEx.Reset() self.TempSensor.SamplesDelete() self.MoistSensor.SamplesDelete() self.NetCon.StationSettingsReset() self.Scheduler.Memory.Delete() @staticmethod def MqttMsgRecvCallback(topic, msg): test_ComponentIntegration.RecvTopic = topic test_ComponentIntegration.RecvMsg = msg test_ComponentIntegration.RecvMsgCount = test_ComponentIntegration.RecvMsgCount + 1 def test_RunComponentIntegration(self): self.MsgEx.SvcIntervalSet(self.MsgExInterval) self.MoistSensor.SvcIntervalSet(self.SensorReadInterval) self.TempSensor.SvcIntervalSet(self.SensorReadInterval) n_deepsleep = 0 deepsleep = True n = 10 while deepsleep is True: deepsleep = False try: self.Scheduler.Run(n) except DeepSleepExceptionInitiated: n = self.Scheduler.Cycles deepsleep = True n_deepsleep += 1 self.assertNotEqual(self.MsgEx.SvcLastRun, -1) self.assertNotEqual(self.NetCon.SvcLastRun, -1) self.assertNotEqual(self.Time.SvcLastRun, -1) self.assertNotEqual(self.TempSensor.SvcLastRun, -1) self.assertNotEqual(self.MoistSensor.SvcLastRun, -1) self.assertNotEqual(n_deepsleep, 0)
def setUp(self): # Configure the URL fields. MessageSpecification.Config(self.UrlFields) # Create objects. filter_depth = len(self.TempSamples) / 2 dummy_temp_sensor = DummySensor.DummySensor(self.TempSamples) dummy_moist_sensor = DummySensor.DummySensor(self.MoistSamples) wlan_ap = WLAN() self.Time = SystemTime.InstanceGet() self.NetCon = NetCon(self.DIR, self.ApCfg, NetCon.MODE_STATION, wlan_ap) self.TempSensor = Sensor.Sensor(self.DIR, SensorReportTemp.NAME_TEMP, filter_depth, dummy_temp_sensor) self.MoistSensor = Sensor.Sensor(self.DIR, SensorReportMoist.NAME_MOIST, filter_depth, dummy_moist_sensor) self.MqttClient = MQTTClient(self.ID, self.BROKER, self.PORT) self.MsgEx = MessageExchange(self.DIR, self.MqttClient, self.ID, self.RETRIES) self.MsgEp = Endpoint() self.Scheduler = ServiceScheduler() # Set service dependencies. self.Time.SvcDependencies( {self.NetCon: Service.DEP_TYPE_RUN_ALWAYS_BEFORE_RUN}) self.MsgEx.SvcDependencies({ self.Time: Service.DEP_TYPE_RUN_ONCE_BEFORE_RUN, self.NetCon: Service.DEP_TYPE_RUN_ALWAYS_BEFORE_INIT }) self.TempSensor.SvcDependencies( {self.Time: Service.DEP_TYPE_RUN_ONCE_BEFORE_RUN}) self.MoistSensor.SvcDependencies( {self.Time: Service.DEP_TYPE_RUN_ONCE_BEFORE_RUN}) # Register all services to the scheduler. self.Scheduler.ServiceRegister(self.Time) self.Scheduler.ServiceRegister(self.NetCon) self.Scheduler.ServiceRegister(self.MsgEx) self.Scheduler.ServiceRegister(self.TempSensor) self.Scheduler.ServiceRegister(self.MoistSensor) # Create message specifications. self.TempMsgSpec = SensorReportTemp() self.MoistMsgSpec = SensorReportMoist() self.LogMsgSpec = LogMessage() # Create a Messaging Endpoint and MessageFormatAdapters. self.TempAdapt = MessageFormatAdapter( self.MsgEp, MessageFormatAdapter.SEND_ON_COMPLETE, self.TempMsgSpec) self.MoistAdapt = MessageFormatAdapter( self.MsgEp, MessageFormatAdapter.SEND_ON_COMPLETE, self.MoistMsgSpec) self.LogAdapt = MessageFormatAdapter( self.MsgEp, MessageFormatAdapter.SEND_ON_COMPLETE, self.LogMsgSpec) # Register message specs. self.MsgEx.RegisterMessageType(self.TempMsgSpec) self.MsgEx.RegisterMessageType(self.MoistMsgSpec) self.MsgEx.RegisterMessageType(self.LogMsgSpec) # Create observers for the sensor data. self.TempObserver = self.TempAdapt.CreateObserver( SensorReportTemp.DATA_KEY_SENSOR_REPORT_ARRAY, self.SamplesPerMessage) self.MoistObserver = self.MoistAdapt.CreateObserver( SensorReportMoist.DATA_KEY_SENSOR_REPORT_ARRAY, self.SamplesPerMessage) # Link the observers to the sensors. self.TempSensor.ObserverAttachNewSample(self.TempObserver) self.MoistSensor.ObserverAttachNewSample(self.MoistObserver) # Create a stream for the log messages. self.LogStream = self.LogAdapt.CreateStream( LogMessage.DATA_KEY_LOG_MSG, ExtLogging.WRITES_PER_LOG) # Configure the ExtLogging class. ExtLogging.ConfigGlobal(level=ExtLogging.INFO, stream=self.LogStream) # Configure the station settings to connect to a WLAN AP. self.NetCon.StationSettingsStore(self.ApCfg["ssid"], self.ApCfg["pwd"]) # Declare test variables. self.RecvMsgCount = 0 self.RecvTopic = None self.RecvMsg = None
def Setup(self): # Create driver instances. self.CapMoist = CapMoisture(Pins.CFG_HW_PIN_MOIST, Pins.CFG_HW_PIN_MOIST_EN) self.Mcp9700Temp = Mcp9700Temp(Pins.CFG_HW_PIN_TEMP, Pins.CFG_HW_PIN_TEMP_EN) self.Ldr = PhTLight(Pins.CFG_HW_PIN_LDR, Pins.CFG_HW_PIN_LDR_EN) # self.VBat = BatteryLevel(1, Pins.CFG_HW_PIN_VBAT_MEAS, Pins.CFG_HW_PIN_VBAT_MEAS_EN) self.RgbLed = RgbLed(Pins.CFG_HW_PIN_LED_RED, Pins.CFG_HW_PIN_LED_GREEN, Pins.CFG_HW_PIN_LED_BLUE) self.Button = UserButton(Pins.CFG_HW_PIN_BTN_0) # Create the WLAN station interface. wlan_ap = WLAN(network.STA_IF) self.Time = SystemTime.InstanceGet() self.NetCon.WlanInterface(wlan_ap, NetCon.MODE_STATION) self.TempSensor = Sensor.Sensor(self.DIR, SensorReportTemp.NAME_TEMP, self.FILTER_DEPTH, self.Mcp9700Temp, self.FILTER_DEPTH) self.MoistSensor = Sensor.Sensor(self.DIR, SensorReportMoist.NAME_MOIST, self.FILTER_DEPTH, self.CapMoist, self.FILTER_DEPTH) self.LightSensor = Sensor.Sensor(self.DIR, SensorReportLight.NAME_LIGHT, self.FILTER_DEPTH, self.PhTLight, self.FILTER_DEPTH) self.MqttClient = MQTTClient(self.ID, self.BROKER, self.PORT) self.MsgEx = MessageExchange(self.DIR, self.MqttClient, self.ID, self.RETRIES) self.Notifyer = Notifyer(self.RgbLed) self.MsgEp = Endpoint() self.Scheduler = ServiceScheduler(self.DEEPSLEEP_THRESHOLD_SEC) # Set service dependencies. self.Time.SvcDependencies( {self.NetCon: Service.DEP_TYPE_RUN_ALWAYS_BEFORE_RUN}) self.MsgEx.SvcDependencies({ self.Time: Service.DEP_TYPE_RUN_ONCE_BEFORE_RUN, self.NetCon: Service.DEP_TYPE_RUN_ALWAYS_BEFORE_INIT }) self.TempSensor.SvcDependencies( {self.Time: Service.DEP_TYPE_RUN_ONCE_BEFORE_RUN}) self.MoistSensor.SvcDependencies( {self.Time: Service.DEP_TYPE_RUN_ONCE_BEFORE_RUN}) self.LightSensor.SvcDependencies( {self.Time: Service.DEP_TYPE_RUN_ONCE_BEFORE_RUN}) self.Notifyer.SvcDependencies( {self.MoistSensor: Service.DEP_TYPE_RUN_ALWAYS_BEFORE_RUN}) # Register all services to the scheduler. self.Scheduler.ServiceRegister(self.Time) self.Scheduler.ServiceRegister(self.NetCon) self.Scheduler.ServiceRegister(self.MsgEx) self.Scheduler.ServiceRegister(self.TempSensor) self.Scheduler.ServiceRegister(self.MoistSensor) self.Scheduler.ServiceRegister(self.LightSensor) self.Scheduler.ServiceRegister(self.Notifyer) # Create message specifications. self.TempMsgSpec = SensorReportTemp() self.MoistMsgSpec = SensorReportMoist() self.LightMsgSpec = SensorReportLight() self.LogMsgSpec = LogMessage() # Create MessageFormatAdapters and couple them with their message specs. # self.TempAdapt = MessageFormatAdapter(self.MsgEp, # MessageFormatAdapter.SEND_ON_COMPLETE, # self.TempMsgSpec) self.MoistAdapt = MessageFormatAdapter( self.MsgEp, MessageFormatAdapter.SEND_ON_COMPLETE, self.MoistMsgSpec) self.LightAdapt = MessageFormatAdapter( self.MsgEp, MessageFormatAdapter.SEND_ON_COMPLETE, self.LightMsgSpec) self.LogAdapt = MessageFormatAdapter( self.MsgEp, MessageFormatAdapter.SEND_ON_COMPLETE, self.LogMsgSpec) # Register message specs for exchange. # self.MsgEx.RegisterMessageType(self.TempMsgSpec) self.MsgEx.RegisterMessageType(self.MoistMsgSpec) self.MsgEx.RegisterMessageType(self.LightMsgSpec) self.MsgEx.RegisterMessageType(self.LogMsgSpec) # Create observers for the sensor data. self.TempObserver = self.TempAdapt.CreateObserver( SensorReportTemp.DATA_KEY_SENSOR_REPORT_SAMPLES, self.SamplesPerMessage) self.MoistObserver = self.MoistAdapt.CreateObserver( SensorReportMoist.DATA_KEY_SENSOR_REPORT_SAMPLES, self.SamplesPerMessage) self.LightObserver = self.LightAdapt.CreateObserver( SensorReportLight.DATA_KEY_SENSOR_REPORT_SAMPLES, self.SamplesPerMessage) # Set the notification ranges and colors. moist_th_range = NotificationRange(self.MOIST_RANGE_MIN, self.MOIST_RANGE_MAX) moist_color_map = { RgbLed.RGB_COLOR_RED: NotificationRange(self.MOIST_RANGE_MAX, self.MOIST_RANGE_MIN), RgbLed.RGB_COLOR_BLUE: NotificationRange(self.MOIST_RANGE_MIN, self.MOIST_RANGE_MAX) } self.MoistNotif = Notification(moist_th_range, moist_color_map, self.MOIST_NOTIF_PRIO, self.MOIST_NOTIF_TIME) self.Notifyer.NotificationRegister(self.MoistNotif) # Link the observers to the sensors. self.TempSensor.ObserverAttachNewSample(self.TempObserver) self.MoistSensor.ObserverAttachNewSample(self.MoistObserver) self.MoistSensor.ObserverAttachNewSample(self.MoistNotif) self.LightSensor.ObserverAttachNewSample(self.LightObserver) # Create a stream for the log messages. self.LogStream = self.LogAdapt.CreateStream( LogMessage.DATA_KEY_LOG_MSG, ExtLogging.WRITES_PER_LOG) # Configure the ExtLogging class. ExtLogging.ConfigGlobal(level=ExtLogging.INFO, stream=self.LogStream) # Set intervals for all services. self.MsgEx.SvcIntervalSet(self.MsgExInterval) self.MoistSensor.SvcIntervalSet(self.EnvSensorReadInterval) self.TempSensor.SvcIntervalSet(self.EnvSensorReadInterval) self.LightSensor.SvcIntervalSet(self.EnvSensorReadInterval) self.Notifyer.SvcIntervalSet(self.NotificationInterval)
class MainApp: PRODUCT_NAME = "smartsensor" DIR = "./" ID = str(ubinascii.hexlify(machine.unique_id()).decode('utf-8')) RETRIES = 3 BROKER = '192.168.0.111' # '192.168.0.103' PORT = 1883 FILTER_DEPTH = const(20) DEEPSLEEP_THRESHOLD_SEC = const(5) MOIST_RANGE_MIN = const(1000) MOIST_RANGE_MAX = const(10000) MOIST_NOTIF_TIME = const(3) MOIST_NOTIF_PRIO = const(5) NetCon = None UrlFields = { MessageSpecification.URL_FIELD_DEVICE_ID: ID, MessageSpecification.URL_FIELD_PRODUCT_NAME: PRODUCT_NAME } SamplesPerMessage = const(1) # Service intervals in seconds. MsgExInterval = const(35) EnvSensorReadInterval = const(7) NotificationInterval = const(7) def __init__(self, netcon_obj): # Configure the URL fields. MessageSpecification.Config(self.UrlFields) MainApp.NetCon = netcon_obj def Setup(self): # Create driver instances. self.CapMoist = CapMoisture(Pins.CFG_HW_PIN_MOIST, Pins.CFG_HW_PIN_MOIST_EN) self.Mcp9700Temp = Mcp9700Temp(Pins.CFG_HW_PIN_TEMP, Pins.CFG_HW_PIN_TEMP_EN) self.Ldr = PhTLight(Pins.CFG_HW_PIN_LDR, Pins.CFG_HW_PIN_LDR_EN) # self.VBat = BatteryLevel(1, Pins.CFG_HW_PIN_VBAT_MEAS, Pins.CFG_HW_PIN_VBAT_MEAS_EN) self.RgbLed = RgbLed(Pins.CFG_HW_PIN_LED_RED, Pins.CFG_HW_PIN_LED_GREEN, Pins.CFG_HW_PIN_LED_BLUE) self.Button = UserButton(Pins.CFG_HW_PIN_BTN_0) # Create the WLAN station interface. wlan_ap = WLAN(network.STA_IF) self.Time = SystemTime.InstanceGet() self.NetCon.WlanInterface(wlan_ap, NetCon.MODE_STATION) self.TempSensor = Sensor.Sensor(self.DIR, SensorReportTemp.NAME_TEMP, self.FILTER_DEPTH, self.Mcp9700Temp, self.FILTER_DEPTH) self.MoistSensor = Sensor.Sensor(self.DIR, SensorReportMoist.NAME_MOIST, self.FILTER_DEPTH, self.CapMoist, self.FILTER_DEPTH) self.LightSensor = Sensor.Sensor(self.DIR, SensorReportLight.NAME_LIGHT, self.FILTER_DEPTH, self.PhTLight, self.FILTER_DEPTH) self.MqttClient = MQTTClient(self.ID, self.BROKER, self.PORT) self.MsgEx = MessageExchange(self.DIR, self.MqttClient, self.ID, self.RETRIES) self.Notifyer = Notifyer(self.RgbLed) self.MsgEp = Endpoint() self.Scheduler = ServiceScheduler(self.DEEPSLEEP_THRESHOLD_SEC) # Set service dependencies. self.Time.SvcDependencies( {self.NetCon: Service.DEP_TYPE_RUN_ALWAYS_BEFORE_RUN}) self.MsgEx.SvcDependencies({ self.Time: Service.DEP_TYPE_RUN_ONCE_BEFORE_RUN, self.NetCon: Service.DEP_TYPE_RUN_ALWAYS_BEFORE_INIT }) self.TempSensor.SvcDependencies( {self.Time: Service.DEP_TYPE_RUN_ONCE_BEFORE_RUN}) self.MoistSensor.SvcDependencies( {self.Time: Service.DEP_TYPE_RUN_ONCE_BEFORE_RUN}) self.LightSensor.SvcDependencies( {self.Time: Service.DEP_TYPE_RUN_ONCE_BEFORE_RUN}) self.Notifyer.SvcDependencies( {self.MoistSensor: Service.DEP_TYPE_RUN_ALWAYS_BEFORE_RUN}) # Register all services to the scheduler. self.Scheduler.ServiceRegister(self.Time) self.Scheduler.ServiceRegister(self.NetCon) self.Scheduler.ServiceRegister(self.MsgEx) self.Scheduler.ServiceRegister(self.TempSensor) self.Scheduler.ServiceRegister(self.MoistSensor) self.Scheduler.ServiceRegister(self.LightSensor) self.Scheduler.ServiceRegister(self.Notifyer) # Create message specifications. self.TempMsgSpec = SensorReportTemp() self.MoistMsgSpec = SensorReportMoist() self.LightMsgSpec = SensorReportLight() self.LogMsgSpec = LogMessage() # Create MessageFormatAdapters and couple them with their message specs. # self.TempAdapt = MessageFormatAdapter(self.MsgEp, # MessageFormatAdapter.SEND_ON_COMPLETE, # self.TempMsgSpec) self.MoistAdapt = MessageFormatAdapter( self.MsgEp, MessageFormatAdapter.SEND_ON_COMPLETE, self.MoistMsgSpec) self.LightAdapt = MessageFormatAdapter( self.MsgEp, MessageFormatAdapter.SEND_ON_COMPLETE, self.LightMsgSpec) self.LogAdapt = MessageFormatAdapter( self.MsgEp, MessageFormatAdapter.SEND_ON_COMPLETE, self.LogMsgSpec) # Register message specs for exchange. # self.MsgEx.RegisterMessageType(self.TempMsgSpec) self.MsgEx.RegisterMessageType(self.MoistMsgSpec) self.MsgEx.RegisterMessageType(self.LightMsgSpec) self.MsgEx.RegisterMessageType(self.LogMsgSpec) # Create observers for the sensor data. self.TempObserver = self.TempAdapt.CreateObserver( SensorReportTemp.DATA_KEY_SENSOR_REPORT_SAMPLES, self.SamplesPerMessage) self.MoistObserver = self.MoistAdapt.CreateObserver( SensorReportMoist.DATA_KEY_SENSOR_REPORT_SAMPLES, self.SamplesPerMessage) self.LightObserver = self.LightAdapt.CreateObserver( SensorReportLight.DATA_KEY_SENSOR_REPORT_SAMPLES, self.SamplesPerMessage) # Set the notification ranges and colors. moist_th_range = NotificationRange(self.MOIST_RANGE_MIN, self.MOIST_RANGE_MAX) moist_color_map = { RgbLed.RGB_COLOR_RED: NotificationRange(self.MOIST_RANGE_MAX, self.MOIST_RANGE_MIN), RgbLed.RGB_COLOR_BLUE: NotificationRange(self.MOIST_RANGE_MIN, self.MOIST_RANGE_MAX) } self.MoistNotif = Notification(moist_th_range, moist_color_map, self.MOIST_NOTIF_PRIO, self.MOIST_NOTIF_TIME) self.Notifyer.NotificationRegister(self.MoistNotif) # Link the observers to the sensors. self.TempSensor.ObserverAttachNewSample(self.TempObserver) self.MoistSensor.ObserverAttachNewSample(self.MoistObserver) self.MoistSensor.ObserverAttachNewSample(self.MoistNotif) self.LightSensor.ObserverAttachNewSample(self.LightObserver) # Create a stream for the log messages. self.LogStream = self.LogAdapt.CreateStream( LogMessage.DATA_KEY_LOG_MSG, ExtLogging.WRITES_PER_LOG) # Configure the ExtLogging class. ExtLogging.ConfigGlobal(level=ExtLogging.INFO, stream=self.LogStream) # Set intervals for all services. self.MsgEx.SvcIntervalSet(self.MsgExInterval) self.MoistSensor.SvcIntervalSet(self.EnvSensorReadInterval) self.TempSensor.SvcIntervalSet(self.EnvSensorReadInterval) self.LightSensor.SvcIntervalSet(self.EnvSensorReadInterval) self.Notifyer.SvcIntervalSet(self.NotificationInterval) def Reset(self): self.MsgEx.Reset() self.TempSensor.SamplesDelete() self.MoistSensor.SamplesDelete() self.LightSensor.SamplesDelete() self.NetCon.StationSettingsReset() def Run(self): self.Scheduler.Run()
def setUp(self): self.Scheduler = ServiceScheduler(deepsleep_threshold_sec=self.MIN_DEEPSLEEP_TIME) return
class test_ServiceScheduler(unittest.TestCase): MIN_DEEPSLEEP_TIME = 5 def setUp(self): self.Scheduler = ServiceScheduler(deepsleep_threshold_sec=self.MIN_DEEPSLEEP_TIME) return def tearDown(self): self.Scheduler.Memory.Sfile.Delete() return # def test_ServiceRegisterAndInitializeSuccessful(self): # svc = TestService(Service.MODE_RUN_ONCE, {}) # # res = self.Scheduler.ServiceRegister(svc) # # self.assertEqual(res, 0) # self.assertEqual(svc.SvcInit.CallCount, 1) # self.assertEqual(svc.SvcStateGet(), Service.STATE_SUSPENDED) # self.assertEqual(len(self.Scheduler.Services), 1) # # def test_ServiceRegisterNoInitDueToDependency(self): # svc_dep = TestService(Service.MODE_RUN_ONCE, {}) # svc = TestService(Service.MODE_RUN_ONCE, {svc_dep: Service.DEP_TYPE_RUN_ONCE_BEFORE_INIT}) # # res = self.Scheduler.ServiceRegister(svc_dep) # self.assertEqual(res, 0) # # res = self.Scheduler.ServiceRegister(svc) # # self.assertEqual(res, 0) # self.assertEqual(svc.SvcInit.CallCount, 0) # self.assertEqual(svc.SvcStateGet(), Service.STATE_UNINITIALIZED) # self.assertEqual(svc_dep.SvcStateGet(), Service.STATE_SUSPENDED) # self.assertEqual(len(self.Scheduler.Services), 2) # def test_ServiceRegisterException(self): # svc = TestService(Service.MODE_RUN_ONCE, {}) # svc.SvcInit.RaiseExcSet() # # res = self.Scheduler.ServiceRegister(svc) # # self.assertEqual(res, -1) # self.assertEqual(svc.SvcStateGet(), Service.STATE_DISABLED) def test_ServiceDeregisterSuccessful(self): svc = TestService(Service.MODE_RUN_ONCE, {}) self.Scheduler.ServiceRegister(svc) svc.SvcStateSet(Service.STATE_SUSPENDED) res = self.Scheduler.ServiceDeregister(svc) self.assertEqual(res, 0) self.assertEqual(svc.SvcStateGet(), Service.STATE_UNINITIALIZED) self.assertEqual(svc.SvcDeinit.CallCount, 1) self.assertEqual(len(self.Scheduler.Services), 0) def test_ServiceDeregisterException(self): svc = TestService(Service.MODE_RUN_ONCE, {}) self.Scheduler.ServiceRegister(svc) svc.SvcDeinit.RaiseExcSet() svc.SvcStateSet(Service.STATE_SUSPENDED) res = self.Scheduler.ServiceDeregister(svc) self.assertEqual(res, -1) self.assertEqual(svc.SvcStateGet(), Service.STATE_DISABLED) def test_RunOnceNoServices(self): self.Scheduler.Run(1) @staticmethod def PeriodicServiceRun(stub_func_obj): print("[PeriodicService] Called") @staticmethod def OneShotServiceRun(stub_func_obj): print("[OneShotService] Called") utime.sleep(TestService.TEST_SERVICE_DURATION) def test_RunServicePeriodic(self): run_count = 2 interval = 2 svc = TestService(Service.MODE_RUN_PERIODIC, {}, interval, test_ServiceScheduler.PeriodicServiceRun) self.Scheduler.ServiceRegister(svc) self.Scheduler.Run(run_count * 2) self.assertEqual(svc.SvcRun.CallCount, run_count) def test_RunServiceOnce(self): svc = TestService(Service.MODE_RUN_ONCE, {}, run_func=test_ServiceScheduler.PeriodicServiceRun) self.Scheduler.ServiceRegister(svc) svc.SvcActivate() self.Scheduler.Run(1) self.assertEqual(svc.SvcRun.CallCount, 1) def test_RunServiceMixed(self): svc_periodic = TestService(Service.MODE_RUN_PERIODIC, {}, 2, test_ServiceScheduler.PeriodicServiceRun) svc_once = TestService(Service.MODE_RUN_ONCE, {}, run_func=test_ServiceScheduler.OneShotServiceRun) self.Scheduler.ServiceRegister(svc_periodic) self.Scheduler.ServiceRegister(svc_once) svc_once.SvcActivate() self.Scheduler.Run(4) self.assertEqual(svc_once.SvcRun.CallCount, 1) self.assertEqual(svc_periodic.SvcRun.CallCount, 1) def test_RunServiceFromRunDependency(self): svc_once = TestService(Service.MODE_RUN_ONCE, {}, run_func=test_ServiceScheduler.OneShotServiceRun) svc_deps = {svc_once: Service.DEP_TYPE_RUN_ALWAYS_BEFORE_RUN} svc_periodic = TestService(Service.MODE_RUN_PERIODIC, svc_deps, 2, test_ServiceScheduler.PeriodicServiceRun) self.Scheduler.ServiceRegister(svc_periodic) self.Scheduler.ServiceRegister(svc_once) self.Scheduler.Run(4) self.assertEqual(svc_once.SvcRun.CallCount, 1) self.assertEqual(svc_periodic.SvcRun.CallCount, 1) def test_RunServiceFromInitDependency(self): svc_once = TestService(Service.MODE_RUN_ONCE, {}, run_func=test_ServiceScheduler.OneShotServiceRun) svc_deps = {svc_once: Service.DEP_TYPE_RUN_ALWAYS_BEFORE_INIT} svc_periodic = TestService(Service.MODE_RUN_PERIODIC, svc_deps, 2, test_ServiceScheduler.PeriodicServiceRun) self.Scheduler.ServiceRegister(svc_periodic) self.Scheduler.ServiceRegister(svc_once) self.assertFalse(svc_periodic.SvcIsInitialized()) self.Scheduler.Run(4) self.assertEqual(svc_once.SvcRun.CallCount, 1) self.assertEqual(svc_periodic.SvcRun.CallCount, 1) self.assertTrue(svc_periodic.SvcIsInitialized()) def test_RunDisableServiceOnException(self): svc = TestService(Service.MODE_RUN_PERIODIC, {}, 2, test_ServiceScheduler.PeriodicServiceRun) self.Scheduler.ServiceRegister(svc) print(svc) svc.SvcRun.RaiseExcSet() self.Scheduler.Run(3) self.assertEqual(svc.SvcStateGet(), Service.STATE_DISABLED) def test_RunServiceSuspend(self): svc = TestService(Service.MODE_RUN_PERIODIC, {}, 2, test_ServiceScheduler.PeriodicServiceRun) self.Scheduler.ServiceRegister(svc) print(svc) svc.SvcRun.Exc = ServiceExceptionSuspend svc.SvcRun.RaiseExcSet() self.Scheduler.Run(3) self.assertEqual(svc.SvcStateGet(), Service.STATE_SUSPENDED) def test_RunServiceLongDuration(self): svc = TestService(Service.MODE_RUN_ONCE, {}, run_func=test_ServiceScheduler.OneShotServiceRun) self.Scheduler.ServiceRegister(svc) svc.SvcActivate() self.Scheduler.Run(1) self.assertEqual(svc.SvcRun.CallCount, 1) self.assertEqual(self.Scheduler.RunTimeSec, TestService.TEST_SERVICE_DURATION) def test_RunServiceAndDeepSleep(self): svc = TestService(Service.MODE_RUN_PERIODIC, {}, 20, test_ServiceScheduler.PeriodicServiceRun) self.Scheduler.ServiceRegister(svc) svc.SvcActivate() exc_occurred = False try: self.Scheduler.Run() except DeepSleepExceptionFailed: exc_occurred = True self.assertTrue(exc_occurred) self.assertEqual(svc.SvcRun.CallCount, 1) self.assertEqual(svc.SvcInterval * 1000, machine.asleep_for()) def test_RunServiceAndSelectShortedSleep(self): svc = TestService(Service.MODE_RUN_PERIODIC, {}, 20, test_ServiceScheduler.PeriodicServiceRun) svc2 = TestService(Service.MODE_RUN_PERIODIC, {}, 5, test_ServiceScheduler.PeriodicServiceRun) # Register services in reverse order (shortest first) to make sure order does not affect selecting # shortest sleep time. self.Scheduler.ServiceRegister(svc2) self.Scheduler.ServiceRegister(svc) svc.SvcActivate() svc2.SvcActivate() exc_occurred = False try: self.Scheduler.Run() except DeepSleepExceptionFailed: exc_occurred = True self.assertTrue(exc_occurred) self.assertEqual(svc.SvcRun.CallCount, 1) self.assertEqual(svc2.SvcRun.CallCount, 1) self.assertEqual(svc2.SvcInterval * 1000, machine.asleep_for()) exc_occurred = False try: self.Scheduler.Run() except DeepSleepExceptionFailed: exc_occurred = True self.assertTrue(exc_occurred) self.assertEqual(svc.SvcRun.CallCount, 1) self.assertEqual(svc2.SvcRun.CallCount, 2) self.assertEqual(svc2.SvcInterval * 1000, machine.asleep_for()) def test_WakeFromDeepSleepAndRunService(self): svc = TestService(Service.MODE_RUN_PERIODIC, {}, 20, test_ServiceScheduler.PeriodicServiceRun) svc_name = svc.SvcName self.Scheduler.ServiceRegister(svc) svc.SvcActivate() exc_occurred = False try: self.Scheduler.Run() except DeepSleepExceptionFailed: exc_occurred = True self.assertTrue(exc_occurred) self.assertTrue(machine.is_asleep()) new_svc = TestService(Service.MODE_RUN_PERIODIC, {}, 20, test_ServiceScheduler.PeriodicServiceRun, svc_name) new_sched = ServiceScheduler() new_sched.ServiceRegister(new_svc) exc_occurred = False try: new_sched.Run() except DeepSleepExceptionFailed: exc_occurred = True self.assertTrue(exc_occurred) self.assertEqual(new_svc.SvcRun.CallCount, 1) self.assertTrue(machine.is_asleep())
class MainApp: VER_MAJOR = const(0) VER_MINOR = const(2) VER_PATCH = const(0) DummySamples = [20, 30, 25, 11, -10, 40, 32] DIR_LOG = const(0) DIR_LORA = const(1) DIR_SENSOR = const(2) DIR_MSG = const(3) DIR_SYS = const(4) DIR_TREE = { DIR_LOG: "/log", DIR_LORA: "/lora", DIR_SENSOR: "/sensor", DIR_MSG: "/msg", DIR_SYS: "/sys" } DIR_ROOT = "/" RETRIES = 1 FILTER_DEPTH = const(5) DEEPSLEEP_THRESHOLD_SEC = const(5) SEND_LIMIT = const(1) SamplesPerMessage = const(1) # Service intervals in seconds. MsgExInterval = const(100) SensorReadInterval = const(50) MoistReadInterval = const(20) # TTN TtnAppEui = [0x70, 0xB3, 0xD5, 0x7E, 0xD0, 0x03, 0x2C, 0xDC] # OTAA Test node 01 # TtnDevEui = [0x00, 0x3C, 0x8D, 0xB2, 0x88, 0x2D, 0xC4, 0x7C] # TtnAppKey = [0x38, 0x34, 0xF5, 0x1F, 0x04, 0xD0, 0x66, 0xF5, # 0xF8, 0x5B, 0x5F, 0xDD, 0xAD, 0x4F, 0xC0, 0xB9] # OTAA Test node 02 # TtnDevEui = [0x00, 0x2B, 0xE3, 0x70, 0x72, 0xA5, 0x9E, 0xF0] # TtnAppKey = [0xD3, 0x07, 0xCF, 0xEC, 0x3E, 0x4B, 0x1D, 0xF4, # 0xE8, 0x70, 0xA7, 0x44, 0xED, 0x26, 0x8C, 0xF1] # OTAA Test node 03 TtnDevEui = [0x00, 0x68, 0xE0, 0x3A, 0xB9, 0xF3, 0x5E, 0x7C] TtnAppKey = [ 0x37, 0xA2, 0x75, 0x26, 0x3C, 0xE8, 0xD6, 0x47, 0x2F, 0x3E, 0xCF, 0xF2, 0x08, 0x47, 0x27, 0x34 ] # ABP Test node 01 DevAddr = [0x26, 0x01, 0x37, 0x47] NwkSKey = [ 0x13, 0x48, 0xA0, 0x44, 0x47, 0xC4, 0x3B, 0xC8, 0x70, 0x9B, 0x2F, 0x5B, 0x5B, 0xAA, 0xE5, 0x7A ] AppSKey = [ 0x5D, 0x5A, 0x38, 0x50, 0x41, 0xD9, 0xD5, 0x0B, 0x14, 0x1D, 0xC5, 0x9A, 0xB4, 0xED, 0xFB, 0x59 ] TtnLoraConfig = { "freq": 868.1, "sf": 7, "ldro": 0, "app_eui": TtnAppEui, "dev_eui": TtnDevEui, "app_key": TtnAppKey } # KPN KpnAppEui = [0x00, 0x59, 0xAC, 0x00, 0x00, 0x01, 0x09, 0xCB] # Node 01 KpnDevEui = [0x00, 0x59, 0xAC, 0x00, 0x00, 0x1B, 0x08, 0x08] KpnAppKey = [ 0x08, 0x9a, 0x03, 0x5f, 0xbe, 0xda, 0xad, 0x6c, 0x96, 0x72, 0xb5, 0x32, 0xb4, 0x11, 0x14, 0xf4 ] # Node 02 # KpnDevEui = [0x00, 0x59, 0xAC, 0x00, 0x00, 0x1B, 0x07, 0xDB] # KpnAppKey = [0xc4, 0x91, 0xbc, 0xe0, 0xd9, 0x21, 0x84, 0x63, # 0x9a, 0x57, 0x63, 0xac, 0x87, 0x6b, 0xe4, 0x05] # Node 03 # KpnDevEui = [0x00, 0x59, 0xAC, 0x00, 0x00, 0x1B, 0x06, 0xD4] # KpnAppKey = [0xe5, 0x14, 0x54, 0x06, 0x19, 0x64, 0xfa, 0x3a, # 0x28, 0xe6, 0xdd, 0xcb, 0x74, 0xec, 0xcb, 0xf2] KpnLoraConfig = { "freq": 868.1, "sf": 12, "ldro": 1, "app_eui": KpnAppEui, "dev_eui": KpnDevEui, "app_key": KpnAppKey } KPN = const(0) TTN = const(1) ABP = const(0) OTAA = const(1) NETWORK = TTN NETWORK_REG = OTAA def __init__(self): return def Setup(self): for dir in self.DIR_TREE.values(): try: uos.mkdir(dir) except OSError: print("Cannot create directory '{}'".format(dir)) # Configure the ExtLogging class. ExtLogging.ConfigGlobal(level=ExtLogging.DEBUG, stream=None, dir=self.DIR_TREE[self.DIR_LOG], file_prefix="log_", line_limit=1000, file_limit=10) StructFile.SetLogger(ExtLogging.Create("SFile")) self.Log = ExtLogging.Create("Main") self.Log.info("Device ID: {}".format(DeviceId.DeviceId())) Version(self.DIR_TREE[self.DIR_SYS], self.VER_MAJOR, self.VER_MINOR, self.VER_PATCH) rst_reason = ResetReason.ResetReason() self.Log.debug("Reset reason: {}".format( ResetReason.ResetReasonToString(rst_reason))) # Create driver instances. self.DummySensorDriver = DummySensor(self.DummySamples) self.InternalTemp = InternalTemp() # TODO: Enable actual sensor drivers. # self.TempSensorDriver = Mcp9700Temp(temp_pin_nr=Pins.CFG_HW_PIN_TEMP, # en_supply_obj=Supply(Pins.CFG_HW_PIN_TEMP_EN, 3.3, 300)) # # self.VBatSensorDriver = VoltageSensor(pin_nr=Pins.CFG_HW_PIN_VBAT_LVL, # en_supply_obj=Supply(Pins.CFG_HW_PIN_VBAT_LVL_EN, 3.3, 300)) if self.NETWORK is self.KPN: self.LoraProtocol = LoraProtocol( self.KpnLoraConfig, directory=self.DIR_TREE[self.DIR_LORA]) elif self.NETWORK is self.TTN: self.LoraProtocol = LoraProtocol( self.TtnLoraConfig, directory=self.DIR_TREE[self.DIR_LORA]) if self.NETWORK_REG is self.ABP: self.LoraProtocol.Params.StoreSession(self.DevAddr, self.AppSKey, self.NwkSKey) else: raise Exception("No valid network LoRa selected.") self.DummySensor = Sensor.Sensor(self.DIR_TREE[self.DIR_SENSOR], "Dummy", self.FILTER_DEPTH, self.DummySensorDriver, samples_per_update=3, dec_round=True, store_data=True) self.TempSensor = Sensor.Sensor( self.DIR_TREE[self.DIR_SENSOR], "Temp", self.FILTER_DEPTH, self. InternalTemp, # TODO: Replace InternalTemp driver with TempSensorDriver samples_per_update=2, dec_round=True, store_data=True) # self.BatteryVoltageSensor = Sensor.Sensor(self.DIR_TREE[self.DIR_SENSOR], # "BatLvl", # self.FILTER_DEPTH, # self.VBatSensorDriver, # samples_per_update=2, # dec_round=False, # store_data=True) self.MsgEx = MessageExchange(directory=self.DIR_TREE[self.DIR_MSG], proto_obj=self.LoraProtocol, send_retries=self.RETRIES, msg_size_max=self.LoraProtocol.Mtu, msg_send_limit=self.SEND_LIMIT) # Create the registration info spec and Registration service. # Link the Registration service to the Message Exchange service. The Message Exchange # service will activate the Registration service when it connects to the LoRa network. self.RegistrationInfo = RegistrationInfo() self.Registration = Registration(self.MsgEx, self.RegistrationInfo) self.MsgEx.AttachConnectionStateObserver(self.Registration) self.Scheduler = ServiceScheduler( deepsleep_threshold_sec=self.DEEPSLEEP_THRESHOLD_SEC, # deep_sleep_obj=PowerManager.PowerManager(), directory=self.DIR_TREE[self.DIR_SYS]) # Set service dependencies. # There are no hard dependencies between the services. # Register all services to the scheduler. self.Scheduler.ServiceRegister(self.DummySensor) self.Scheduler.ServiceRegister(self.TempSensor) # self.Scheduler.ServiceRegister(self.BatteryVoltageSensor) self.Scheduler.ServiceRegister(self.MsgEx) self.Scheduler.ServiceRegister(self.Registration) Message.SetParser(CborParser()) MessageTemplate.SectionsSet(Metadata.MSG_SECTION_META, Metadata.MSG_SECTION_DATA) MessageTemplate.MetadataTemplateSet(Metadata.Metadata, Metadata.MetadataFuncs) # Create message specifications. self.MoistReport = MoistureSensorReport() self.BatteryReport = BatterySensorReport() self.TempReport = TemperatureSensorReport() # Create MessageFormatters and couple them with their message specs. moist_report_meta = { Metadata.MSG_META_TYPE: self.MoistReport.Type, Metadata.MSG_META_SUBTYPE: self.MoistReport.Subtype, } self.MoistFmt = MessageFormatter(self.MsgEx, MessageFormatter.SEND_ON_CHANGE, self.MoistReport, moist_report_meta) battery_report_meta = { Metadata.MSG_META_TYPE: self.BatteryReport.Type, Metadata.MSG_META_SUBTYPE: self.BatteryReport.Subtype, } self.BatteryFmt = MessageFormatter(self.MsgEx, MessageFormatter.SEND_ON_CHANGE, self.BatteryReport, battery_report_meta) temp_report_meta = { Metadata.MSG_META_TYPE: self.TempReport.Type, Metadata.MSG_META_SUBTYPE: self.TempReport.Subtype, } self.TempFmt = MessageFormatter(self.MsgEx, MessageFormatter.SEND_ON_CHANGE, self.TempReport, temp_report_meta) # Register message specs for exchange. self.MsgEx.RegisterMessageType(self.MoistReport) self.MsgEx.RegisterMessageType(self.BatteryReport) self.MsgEx.RegisterMessageType(self.TempReport) self.MsgEx.RegisterMessageType(self.RegistrationInfo) # Create observers for the sensor data. self.MoistObserver = self.MoistFmt.CreateObserver( MoistureSensorReport.DATA_KEY_MEASUREMENTS) self.BatteryObserver = self.BatteryFmt.CreateObserver( BatterySensorReport.DATA_KEY_MEASUREMENTS) self.TempObserver = self.TempFmt.CreateObserver( TemperatureSensorReport.DATA_KEY_MEASUREMENTS) # Link the observers to the sensors. self.DummySensor.ObserverAttachNewSample(self.MoistObserver) self.TempSensor.ObserverAttachNewSample(self.TempObserver) self.Scheduler.RegisterCallbackBeforeDeepSleep(MainApp.BeforeSleep) # Set intervals for all services. self.MsgEx.SvcIntervalSet(self.MsgExInterval) self.MsgEx.DefaultIntervalSet(self.MsgExInterval) self.DummySensor.SvcIntervalSet(self.MoistReadInterval) self.TempSensor.SvcIntervalSet(self.SensorReadInterval) # Activate the Message Exchange to attempt to connect to the LoRa network # if no LoRaWAN session exists yet. if self.LoraProtocol.HasSession() is False: self.MsgEx.SvcActivate() # self.BatteryObserver.Update(100) self.Log.info("Finished initialization.") def Reset(self): self.MsgEx.Reset() self.DummySensor.SamplesDelete() def Run(self): self.Log.info("Starting scheduler") self.Scheduler.Run() @staticmethod def BeforeSleep(): ExtLogging.Stop() StructFile.ResetLogger()
def Setup(self): for dir in self.DIR_TREE.values(): try: uos.mkdir(dir) except OSError: print("Cannot create directory '{}'".format(dir)) # Configure the ExtLogging class. ExtLogging.ConfigGlobal(level=ExtLogging.DEBUG, stream=None, dir=self.DIR_TREE[self.DIR_LOG], file_prefix="log_", line_limit=1000, file_limit=10) StructFile.SetLogger(ExtLogging.Create("SFile")) self.Log = ExtLogging.Create("Main") self.Log.info("Device ID: {}".format(DeviceId.DeviceId())) Version(self.DIR_TREE[self.DIR_SYS], self.VER_MAJOR, self.VER_MINOR, self.VER_PATCH) rst_reason = ResetReason.ResetReason() self.Log.debug("Reset reason: {}".format( ResetReason.ResetReasonToString(rst_reason))) # Create driver instances. self.DummySensorDriver = DummySensor(self.DummySamples) self.InternalTemp = InternalTemp() # TODO: Enable actual sensor drivers. # self.TempSensorDriver = Mcp9700Temp(temp_pin_nr=Pins.CFG_HW_PIN_TEMP, # en_supply_obj=Supply(Pins.CFG_HW_PIN_TEMP_EN, 3.3, 300)) # # self.VBatSensorDriver = VoltageSensor(pin_nr=Pins.CFG_HW_PIN_VBAT_LVL, # en_supply_obj=Supply(Pins.CFG_HW_PIN_VBAT_LVL_EN, 3.3, 300)) if self.NETWORK is self.KPN: self.LoraProtocol = LoraProtocol( self.KpnLoraConfig, directory=self.DIR_TREE[self.DIR_LORA]) elif self.NETWORK is self.TTN: self.LoraProtocol = LoraProtocol( self.TtnLoraConfig, directory=self.DIR_TREE[self.DIR_LORA]) if self.NETWORK_REG is self.ABP: self.LoraProtocol.Params.StoreSession(self.DevAddr, self.AppSKey, self.NwkSKey) else: raise Exception("No valid network LoRa selected.") self.DummySensor = Sensor.Sensor(self.DIR_TREE[self.DIR_SENSOR], "Dummy", self.FILTER_DEPTH, self.DummySensorDriver, samples_per_update=3, dec_round=True, store_data=True) self.TempSensor = Sensor.Sensor( self.DIR_TREE[self.DIR_SENSOR], "Temp", self.FILTER_DEPTH, self. InternalTemp, # TODO: Replace InternalTemp driver with TempSensorDriver samples_per_update=2, dec_round=True, store_data=True) # self.BatteryVoltageSensor = Sensor.Sensor(self.DIR_TREE[self.DIR_SENSOR], # "BatLvl", # self.FILTER_DEPTH, # self.VBatSensorDriver, # samples_per_update=2, # dec_round=False, # store_data=True) self.MsgEx = MessageExchange(directory=self.DIR_TREE[self.DIR_MSG], proto_obj=self.LoraProtocol, send_retries=self.RETRIES, msg_size_max=self.LoraProtocol.Mtu, msg_send_limit=self.SEND_LIMIT) # Create the registration info spec and Registration service. # Link the Registration service to the Message Exchange service. The Message Exchange # service will activate the Registration service when it connects to the LoRa network. self.RegistrationInfo = RegistrationInfo() self.Registration = Registration(self.MsgEx, self.RegistrationInfo) self.MsgEx.AttachConnectionStateObserver(self.Registration) self.Scheduler = ServiceScheduler( deepsleep_threshold_sec=self.DEEPSLEEP_THRESHOLD_SEC, # deep_sleep_obj=PowerManager.PowerManager(), directory=self.DIR_TREE[self.DIR_SYS]) # Set service dependencies. # There are no hard dependencies between the services. # Register all services to the scheduler. self.Scheduler.ServiceRegister(self.DummySensor) self.Scheduler.ServiceRegister(self.TempSensor) # self.Scheduler.ServiceRegister(self.BatteryVoltageSensor) self.Scheduler.ServiceRegister(self.MsgEx) self.Scheduler.ServiceRegister(self.Registration) Message.SetParser(CborParser()) MessageTemplate.SectionsSet(Metadata.MSG_SECTION_META, Metadata.MSG_SECTION_DATA) MessageTemplate.MetadataTemplateSet(Metadata.Metadata, Metadata.MetadataFuncs) # Create message specifications. self.MoistReport = MoistureSensorReport() self.BatteryReport = BatterySensorReport() self.TempReport = TemperatureSensorReport() # Create MessageFormatters and couple them with their message specs. moist_report_meta = { Metadata.MSG_META_TYPE: self.MoistReport.Type, Metadata.MSG_META_SUBTYPE: self.MoistReport.Subtype, } self.MoistFmt = MessageFormatter(self.MsgEx, MessageFormatter.SEND_ON_CHANGE, self.MoistReport, moist_report_meta) battery_report_meta = { Metadata.MSG_META_TYPE: self.BatteryReport.Type, Metadata.MSG_META_SUBTYPE: self.BatteryReport.Subtype, } self.BatteryFmt = MessageFormatter(self.MsgEx, MessageFormatter.SEND_ON_CHANGE, self.BatteryReport, battery_report_meta) temp_report_meta = { Metadata.MSG_META_TYPE: self.TempReport.Type, Metadata.MSG_META_SUBTYPE: self.TempReport.Subtype, } self.TempFmt = MessageFormatter(self.MsgEx, MessageFormatter.SEND_ON_CHANGE, self.TempReport, temp_report_meta) # Register message specs for exchange. self.MsgEx.RegisterMessageType(self.MoistReport) self.MsgEx.RegisterMessageType(self.BatteryReport) self.MsgEx.RegisterMessageType(self.TempReport) self.MsgEx.RegisterMessageType(self.RegistrationInfo) # Create observers for the sensor data. self.MoistObserver = self.MoistFmt.CreateObserver( MoistureSensorReport.DATA_KEY_MEASUREMENTS) self.BatteryObserver = self.BatteryFmt.CreateObserver( BatterySensorReport.DATA_KEY_MEASUREMENTS) self.TempObserver = self.TempFmt.CreateObserver( TemperatureSensorReport.DATA_KEY_MEASUREMENTS) # Link the observers to the sensors. self.DummySensor.ObserverAttachNewSample(self.MoistObserver) self.TempSensor.ObserverAttachNewSample(self.TempObserver) self.Scheduler.RegisterCallbackBeforeDeepSleep(MainApp.BeforeSleep) # Set intervals for all services. self.MsgEx.SvcIntervalSet(self.MsgExInterval) self.MsgEx.DefaultIntervalSet(self.MsgExInterval) self.DummySensor.SvcIntervalSet(self.MoistReadInterval) self.TempSensor.SvcIntervalSet(self.SensorReadInterval) # Activate the Message Exchange to attempt to connect to the LoRa network # if no LoRaWAN session exists yet. if self.LoraProtocol.HasSession() is False: self.MsgEx.SvcActivate() # self.BatteryObserver.Update(100) self.Log.info("Finished initialization.")