Exemplo n.º 1
0
class DeviceManager():
    
    INSTANCE = None
    
    # Singleton pattern
    def __new__(cls, *args, **kwargs):
        if not cls.INSTANCE:
            cls.INSTANCE = super(DeviceManager, cls).__new__(
                                cls, *args, **kwargs)
        
        return cls.INSTANCE
    
    def __init__(self):
        # Instantiate Logger
        self.LOGGER = Debug.getLogger("energyathome.datalogger.serialcomm")

        self.COMM = serial.Serial()
        
        # Create Config manager
        self.CONFIG = ConfigManager()

    # Open serial connection
    def open(self):
        '''Open connection to USB to serial port'''       
        
        self.COMM.port = self.CONFIG.getConfig("SerialConnection", "serialport")
        self.COMM.baudrate = self.CONFIG.getIntConfig("SerialConnection", "baudrate")
        self.COMM.parity = self.CONFIG.getConfig("SerialConnection", "parity")
        self.COMM.timeout = None
        self.COMM.bytesize = self.CONFIG.getIntConfig("SerialConnection", "bytesize")
        
        if(self.COMM.isOpen() == False):
            self.LOGGER.info('Establishing connection to device')
            self.COMM.open()
        else:
            self.LOGGER.info('Connection already opened')
            
        self.LOGGER.info('Device connected:' + str(self.COMM.isOpen()))

    # Close serial connection
    def close(self):
        '''Close connection to USB to Serial port'''
        
        if(self.COMM.isOpen):
            self.LOGGER.info('Closing device connection')
            self.COMM.close()
            
        self.LOGGER.info('Device connection closed')

    # Get data from serial connection
    def read(self):
        '''Read data from USB to Serial device. Connection must be established.'''
        
        data = self.COMM.readline()
        if(len(data) > 0):
            self.LOGGER.debug('serial data: ' + data)
            return data
Exemplo n.º 2
0
class BackupRestore:
    
    def __init__(self):
        # Instantiate Logger
        self.LOGGER = Debug.getLogger("energyathome.datalogger.offlinehandler")
        # Configuration Manager
        self.CONFIG = ConfigManager()
        # Data validation class
        self.VALIDATOR = CheckLiveData()
        # Data trigger class
        self.TRIGGER = CheckLiveTriggers()
        
    def backup(self, historicalData):
        '''Writes historical data to file'''
        
        #If true exit due to exception
        exit = False
        # Get file path from config
        location = self.CONFIG.getConfig("Application", "offlineFile")
        #Check if config is empty
        if len(location) == 0:
            # Use current directory
            location = os.path.join(os.getcwd(), "backup.p")
            self.LOGGER.warning("offlineFile is empty. Using default: '" + location + "'")
        
        try:
            # Append to file
            path = file(location, "a")

            # Ensure object has data
            if historicalData is not None:
                self.LOGGER.info("Writing data to file:" + str(historicalData.__dict__))
                pickle.dump(historicalData, path)
        except IOError:
            #Debug.writeOut("Unable to write to backup file: '" + location + "'")
            # No point running program if it's unable to write to file
            exit = True
        finally:
            # Close file
            try:
                path.close()
            except UnboundLocalError:
                # File was not opened
                pass
        # Check to exit
        if exit:
            Core.shutdown()

    def restore(self):
        '''Starts the restore process from a file.'''
        
        backup = self.restoreFromFile()
        recordCount = len(backup)
        
        if(recordCount > 0):
            self.LOGGER.info(str(recordCount) + " record(s) found. Saving to DB")
            for record in backup:
                # Set data as valid by default
                hDataValid = True
                # Get backup record
                hData = record
                
                if self.VALIDATOR is not None and self.CONFIG.getBooleanConfig("Tolerence", "enabled"):
                    try:
                        validatedData = self.VALIDATOR.validateData(hData)
                    except Exception as e:
                        raise e
                    
                    hDataValid = validatedData[0]
                    if hDataValid is True:
                        hData = validatedData[1]
                
                if hDataValid and self.CONFIG.getBooleanConfig("Trigger", "enabled"):
                    # Check trigger conditions which return true or false if it's valid
                    try:
                        hDataValid = self.TRIGGER.checkTriggers(hData)
                    except Exception as e:
                        raise e
                
                # Insert the first element in list and remove it
                if hDataValid:
                    self.LOGGER.info("Inserting: " + str(record.__dict__))
                    #HistoricalData.insertData(record)
                    HistoricalData.insertData(hData)
                else:
                    self.LOGGER.info("Skipped backup record")
                
            # Remove backup file to prevent duplicate data from being restored.
            self.LOGGER.info("Restore from backup complete.")
            self.LOGGER.info("Removing backup file.")
            self.LOGGER.info("File deleted? " + str(self.deleteBackupFile()))

    def restoreFromFile(self):
        '''Reads a file and returns an array of objects.'''
        
        # List to store restored objects
        list = []
        # Get file path from config
        location = self.CONFIG.getConfig("Application", "offlineFile")
        #Check if config is empty
        if len(location) == 0:
            # Use current directory
            location = os.path.join(os.getcwd(), "backup.p")
            self.LOGGER.info("offlineFile is empty. Using default: '" + location + "'")
        # Check file exists before deleting
        if os.path.exists(location):
            # Create file object
            path = file(location, "r")
            # Read file till end of file
            try:
                while True:
                    list.append(pickle.load(path))
            except EOFError:
                # Ignore end of file error
                pass
            finally:
                # Close file
                path.close()
                
        self.LOGGER.info("Found " + str(len(list)) + " record(s) in '" + location + "'")
        return list

    def deleteBackupFile(self):
        '''Removed backup file if it exists.'''
        
        success = False;
        
        # Get file path from config
        location = self.CONFIG.getConfig("Application", "offlineFile")
        #Check if config is empty
        if len(location) == 0:
            # Use current directory
            location = os.path.join(os.getcwd(), "backup.p")
            self.LOGGER.info("offlineFile is empty. Using default: '" + location + "'")
        # Check file exists before deleting
        if os.path.exists(location):
            # Delete file
            try:
                os.remove(location)
                success = True;
            except OSError:
                self.LOGGER.error("Unable to remove file: '" + location + "'")
        
        return success;
Exemplo n.º 3
0
class CheckLiveData:
    
    def __init__(self):
        # Instantiate config manager
        self.CONFIG = ConfigManager()
        # Get logger instance
        self.LOGGER = Debug.getLogger("energyathome.datalogger.datavalidation")
        
    # Validate data captured from device
    def validateData(self, historicalData):
        '''Checks historical data fall within parameter which is customised in the config file.
        Returns results in a tuple size of 2.
        [0] = True or False depending if validation was successful or not
        [1] = HistoricalData.HistoricalData class of sanitised data'''
        
        valid = True
        
        # Get maximum appliance Id value
        maxAppId = self.CONFIG.getIntConfig("Tolerence", "maxApplianceId")
        
        try:
            # If max app id is greater than 0 then checking for app id is enabled
            if maxAppId is not None and maxAppId >= 0:
                if self.checkApplianceId(historicalData) is False:
                    valid = False
            
            # Check device name matches in the config
            deviceNames = self.CONFIG.getConfig("Tolerence", "allowedDeviceNames")
            # If device names are defined then perform a match
            if deviceNames is not None and deviceNames != "":
                if self.checkDeviceName(historicalData) is False:
                    valid = False
            
            if self.CONFIG.getBooleanConfig("Tolerence", "allowNewAppliances") is False:
                # If it returns true then it's a new appliance and should be ignored
                if self.checkNewAppliance(historicalData) is True:
                    valid = False
                    self.LOGGER.info("Appliance ID " + str(historicalData.applianceId) + " was not stored due to allowNewAppliances = False")
                    
            # Check channel names
            if self.CONFIG.getBooleanConfig("Tolerence", "allowBlankChannelNames") is False:
                test = self.checkChannelNames(historicalData)
                # If test returned None then it failed validation.
                # Otherwise assign returned Historical Data because it may have changed some attributes
                if test is None:
                    valid = False
                    
                else:
                    historicalData = test
            
            # Check channels
            if self.CONFIG.getBooleanConfig("Tolerence", "checkChannels") is True and historicalData.applianceId is not None:
                test = self.checkChannels(historicalData)
                # If test returned None then it failed validation.
                # Otherwise assign returned Historical Data because it may have changed some attributes
                if test is None:
                    valid = False
                else:
                    historicalData = test
        except ConnectionException as ce:
            raise ce
        
        return (valid, historicalData)
    
    def checkApplianceId(self, historicalData):
        '''Checks if appliance ID falls within a set range'''
        
        # Get maximum appliance Id value
        maxAppId = self.CONFIG.getIntConfig("Tolerence", "maxApplianceId")
        
        try:
            # Check if appliance number exceeds maximum
            if int(historicalData.applianceId) > maxAppId:
                self.LOGGER.info("Appliance ID " + str(historicalData.applianceId) + " > " + str(maxAppId))
                return False
            
            else:
                return True
            
        except ValueError, ve:
            self.LOGGER.info("Check max App ID failed: " + str(historicalData.applianceId) + " > " + str(maxAppId))
            return False
            
        except AttributeError as ae:
            self.LOGGER.info("Check max App ID failed: No attribute Error:" + str(ae))
            return False