def __init__(self, dir: str, dev_eui: str): # The session file is written once when a the device registers successfully. self.SessionSFile = StructFile.StructFile(dir + '/session_' + dev_eui, self.SESSION_DATA_FMT) # The frame count file is written whenever an uplink message is sent. self.FrameCountSFile = StructFile.StructFile(dir + '/fcnt_' + dev_eui, self.FCNT_DATA_FMT) try: self.FrameCounter = self.FrameCountSFile.ReadData(0)[0] Log.info("FrameCounter: {}".format(self.FrameCounter)) except TypeError: Log.info("No LoRaWAN framecounter present.") self.FrameCounter = 0 try: self.DevAddr, self.AppSKey, self.NwkSKey = self.SessionSFile.ReadData(0) self.DevAddr = list(self.DevAddr) self.AppSKey = list(self.AppSKey) self.NwkSKey = list(self.NwkSKey) Log.info("LoRaWAN session info loaded.") Log.debug("NwSKey: {} | AppSKey: {} | DevAddr: {}".format( self.NwkSKey, self.AppSKey, self.DevAddr)) except TypeError: self.FrameCounter = 0 self.DevAddr = None self.AppSKey = None self.NwkSKey = None Log.info("No LoRaWAN session present.")
def __init__(self, file, data_fmt, capacity): Log.info( "Creating NvQueue with path: {}, capacity: {}, format: {}".format( file, capacity, data_fmt)) self.Queue = StructFile.StructFile(file, data_fmt, NvQueue.META_FMT) meta = self.Queue.ReadMeta() # If no metadata is present in the queue file, reset the metadata and write # it to the file. if meta is None: Log.info("No metadata present, initializing queue.") self.Capacity = capacity self._MetaReset() self._MetaUpdate() else: Log.info("Existing metadata found.") Log.debug(str(meta)) self.Capacity = meta[NvQueue.META_STRUCT_CAP] self.Count = meta[NvQueue.META_STRUCT_CNT] self.ReadOffset = meta[NvQueue.META_STRUCT_R_OFF] self.WriteOffset = meta[NvQueue.META_STRUCT_W_OFF] # If the read capacity differs from the capacity argument, update it. if self.Capacity is not capacity: Log.info("Capacity changed, updating metadata.") self.Capacity = capacity self._MetaUpdate()
def test_ConstructorWithUserMeta(self): user_meta_fmt = "<II" os.remove(test_StructFile.TEST_FILE) sf = StructFile.StructFile(test_StructFile.TEST_FILE, test_StructFile.TEST_FMT, user_meta_fmt) self.assertEqual(sf.DataSize, ustruct.calcsize(test_StructFile.TEST_FMT)) file_exists = TestUtil.FileExists(test_StructFile.TEST_FILE) self.assertTrue(file_exists)
def test_WriteReadMeta(self): user_meta_fmt = "<HH" os.remove(test_StructFile.TEST_FILE) sf = StructFile.StructFile(test_StructFile.TEST_FILE, test_StructFile.TEST_FMT, user_meta_fmt) w_meta = (3, 4) sf.WriteMeta(*w_meta) r_meta = sf.ReadMeta() self.assertEqual(r_meta, w_meta)
def __init__(self, dir: str, prefix: str, file_limit: int): file_path = dir + self.COUNT_FILE_NAME self.SFile = StructFile.StructFile(file_path, self.COUNT_FILE_FMT) self.Last = 0 self.First = 0 self.LineCount = 0 self.Max = file_limit self.Dir = dir self.Prefix = prefix self.File = None count_data = self.SFile.ReadData(0) if count_data is not None: self.Last = count_data[self.COUNT_DATA_LAST] self.First = count_data[self.COUNT_DATA_FIRST] self.LineCount = count_data[self.COUNT_DATA_LINES] print("[LogFileMngr] First: {} | Last: {} | LineCount: {}".format( self.Last, self.First, self.LineCount))
def test_ReadMetaNotAvailable(self): user_meta_fmt = "<HH" os.remove(test_StructFile.TEST_FILE) sf = StructFile.StructFile(test_StructFile.TEST_FILE, test_StructFile.TEST_FMT, user_meta_fmt) self.assertEqual(sf.ReadMeta(), None)
def test_ReloadExistingFileAtConstruction(self): w_data = (1, 2) self.Sf.WriteData(0, *w_data) sf_copy = StructFile.StructFile(test_StructFile.TEST_FILE, test_StructFile.TEST_FMT)
def setUp(arg): test_StructFile.Sf = StructFile.StructFile(test_StructFile.TEST_FILE, test_StructFile.TEST_FMT)
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.")