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())
Beispiel #2
0
    def __init__(self, netcon_obj):

        # Create objects.
        self.Time = SystemTime.InstanceGet()
        WebApp.NetCon = netcon_obj
        self.Scheduler = ServiceScheduler()
Beispiel #3
0
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()
Beispiel #4
0
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
Beispiel #5
0
    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
Beispiel #8
0
    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)
Beispiel #9
0
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())
Beispiel #12
0
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()
Beispiel #13
0
    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.")