def visualizeData(self, sessionId, channellist): """ Uses a session id and a list of channels to display related data in a new window :param sessionId: An int representing the session id to fetch data from :param channellist: a dictionary where the keys are channel ids and the values are lists where the first item should be the display name of the channel Example: {1: ['Temperature Room 1', 20.0, 'Celsius'], 2: ['Weight Room 2', 2.34, 'Kilograms']} :return: """ useRemote = \ self.widgetList.\ widget(self.widgetList.visualizeDatabaseSettingsIndex)\ .useRemote() # Checks the settings from the visualize page to see if local or remote database should be used in the visualization if useRemote: # If remote get remote database settings database = configInterface.readConfig('config.cfg', 'remotevisual') else: # Else, get local database settings database = configInterface.readConfig('config.cfg', 'default') self.dataDisplay = DataDisplay( databaseValues=database, sessionId=sessionId, channelList=channellist, ongoing=False, timeInterval=1 ) # Displays data from the database in a new window, change hard coded timeintervall self.dataDisplay.show()
def test_add_to_database(self): exp = readConfig(file='config.cfg', section='Test') createDatabase(exp) list = {} for i in range(1, 61): list[i] = [i, 'Kg', 'tolerant'] for ii in range(0, 2): res = addToDatabase(databaseValues=exp, listOfItems=list) self.assertEqual(res, True) dropDatabase(exp)
def getSessions(self): """ Retrieves a list of sessions from a database specified on the database settings page for the visualize option :return: A tuple of tuples containing information about sessions Example: ((1, 'session1'), (2, 'session2')) """ useRemote = \ self.widgetList.\ widget(self.widgetList.visualizeDatabaseSettingsIndex).\ useRemote() # Fetch database type if useRemote: # If remote remoteDatabase = configInterface.readConfig( 'config.cfg', 'remotevisual') sessionList = Database.getSessionList( remoteDatabase) # Get session from remote database else: localDatabase = configInterface.readConfig('config.cfg', 'default') sessionList = Database.getSessionList( localDatabase) # Else, get sessions from local database return sessionList
def getSessionChannels(self, sessionId): """ Uses a session id to fetch all channels connected to the id from a database :param sessionId: An int representing the session id to be used in the database search :return: """ useRemoteDatabase = \ self.widgetList.\ widget(self.widgetList.visualizeDatabaseSettingsIndex)\ .useRemote() # Checks if the local or a remote database should be searched if useRemoteDatabase: # If remote, get remote channels remoteDatabase = \ configInterface.readConfig('config.cfg', 'remotevisual') channelList = \ Database.getSessionChannelList(remoteDatabase, sessionId) else: # Else, get local channels localDatabase = \ configInterface.readConfig('config.cfg', 'default') channelList = \ Database.getSessionChannelList(localDatabase, sessionId) self.widgetList.widget(self.widgetList.visualizeSessionSettingsIndex)\ .updateChannelList(channelList) # Use the channels to update the channel list on the session settings for the visualize page
def test_reset_channel(self): exp = readConfig(file='config.cfg', section='Test') createDatabase(exp) list = {} for i in range(1,61): list[i] = [20 + i, 'Placeholder', 'Placeholder'] fromtime = time.strftime('%H:%M:%S') fromdate = time.strftime('%Y-%m-%d') addToDatabase(databaseValues=exp, listOfItems=list) totime = time.strftime('%H:%M:%S') todate = time.strftime('%Y-%m-%d') id = 5 resetChannel(databaseValues=exp, id=id) readparam = {'id': id, 'fromdate': fromdate, 'fromtime': fromtime, 'todate': todate, 'totime': totime} self.assertTupleEqual(readFromDatabase(databaseValues=exp, readParameters=readparam), ())
def test_read_from_database(self): exp = readConfig(file='config.cfg', section='Test') createDatabase(exp) list = {} fromtime = time.strftime('%H:%M:%S') fromdate = time.strftime('%Y-%m-%d') for i in range(1, 61): list[i] = [i, 'Kg', 'tolerant'] for ii in range(0, 2): addToDatabase(listOfItems=list, databaseValues=exp) totime = time.strftime('%H:%M:%S') todate = time.strftime('%Y-%m-%d') parameterlist = {'fromtime': fromtime, 'fromdate': fromdate, 'totime': totime, 'todate': todate} for index in range(1, 61): parameterlist['id'] = index res = readFromDatabase(databaseValues=exp, readParameters=parameterlist) self.assertEqual(len(res), 2) dropDatabase(exp)
def test_change_channel_name(self): exp = readConfig(file='config.cfg', section='Test') createDatabase(exp) res = changeChannelName(exp, 'Newname', 59) self.assertEqual(res, True) dropDatabase(exp)
def test_create_database(self): exp = readConfig(file='config.cfg', section='Test') res1 = createDatabase(exp) self.assertEqual(res1, True) self.assertRaises(TypeError, lambda: createDatabase, 'Wrong type') dropDatabase(exp)
def __init__(self, parent=None): """ Creates a new instance of a Databaseform page :param parent: """ QtWidgets.QWidget.__init__(self, parent) font = self.createFormFont() self.host = QtWidgets.QLineEdit() self.host.setMinimumSize(200, 50) # Creates the host input field self.host.setFont(font) self.hosttext = "" self.hostlabel = QtWidgets.QLabel("Host") self.hostlabel.setFont(font) self.hostlabel.setMinimumSize(50, 50) self.port = QtWidgets.QLineEdit() self.port.setMinimumSize(200, 50) self.port.setFont(font) self.porttext = "" self.portlabel = QtWidgets.QLabel("Port") self.portlabel.setFont(font) self.portlabel.setMinimumSize(50, 50) self.database = QtWidgets.QLineEdit() self.database.setMinimumSize(200, 50) self.database.setFont(font) self.databasetext = "" self.databaselabel = QtWidgets.QLabel("Database name") self.databaselabel.setFont(font) self.databaselabel.setMinimumSize(50, 50) self.user = QtWidgets.QLineEdit() self.user.setMinimumSize(200, 50) self.user.setFont(font) self.usertext = "" self.userlabel = QtWidgets.QLabel("User") self.userlabel.setFont(font) self.userlabel.setMinimumSize(50, 50) self.password = QtWidgets.QLineEdit() self.password.setMinimumSize(200, 50) self.password.setFont(font) self.passwordtext = "" self.password.setEchoMode(self.password.Password) self.passwordlabel = QtWidgets.QLabel("Password") self.passwordlabel.setFont(font) self.passwordlabel.setMinimumSize(50, 50) hasprevious = configInterface.hasSection('config.cfg', 'remote') if hasprevious: previous_remote_database = \ configInterface.readConfig('config.cfg', 'remote') # Reads previously used database configs self.hosttext = previous_remote_database['host'] self.porttext = previous_remote_database['port'] self.usertext = previous_remote_database['user'] self.databasetext = previous_remote_database['name'] self.passwordtext = previous_remote_database['password'] form = QtWidgets.QFormLayout() form.addRow(self.hostlabel, self.host) form.addRow(self.portlabel, self.port) form.addRow(self.databaselabel, self.database) form.addRow(self.userlabel, self.user) form.addRow(self.passwordlabel, self.password) form.setVerticalSpacing(10) self.setLayout(form)
curs.execute(sql) conn.commit() conn.close() return True except TypeError as T: print('add_to_database Typerror: ') print(T) return False except pymysql.err.Error as E: print('add_to_database MySQL error: ') print(E) raise E except pymysql.err.IntegrityError as E2: print('add_to_database MySQL IntegrityError: ') print(E2) raise E2 def convertToRemoteInsert(values, newsession, piid): for row in values: row['fk_sessions_measurements'] = newsession row['fk_channels_measurements'] = row[ 'fk_channels_measurements'] + 60 * (piid - 1) return values if __name__ == '__main__': db = configInterface.readConfig('config.cfg', 'default') createLocalDatabase(db)
def run(self): """ Fetches values from a local database and adds them to a remote database :return: """ pid = configInterface.readConfig('config.cfg', 'piid') piid = int( pid['piid']) # Gets the id of the Raspberry pi running the program while not self.addedAllData: try: if self.programQuit.wait( 0): # If signaled that the program wants to terminate self.timeInterval = 0 # Do additions immediately if not self.shouldEnd.wait( self.timeInterval * 10): # Wait for timeintervall seconds sessionSettings = configInterface.readConfig( 'config.cfg', 'latestsession') start = sessionSettings['start'] end = sessionSettings[ 'end'] # Get previous previous search parameters if not end == '': # If the session has been ended checkEnd = datetime.datetime.strptime( end, '%Y-%m-%d %H:%M:%S') checkStart = datetime.datetime.strptime( start, '%Y-%m-%d %H:%M:%S') if checkEnd > checkStart: # Check if the last search parameter is greater than the end value fo the session self.addedAllData = True end = datetime.datetime.now( ) # Get new end value to use in local database search valueList = Database.getMeasurements( databaseValues=self.localDatabase, sessionId=self.sessionId, channelId=None, startTime=start, endTime=end ) # Get measurements from the local database templatestAddTime = None templatestAddFractions = None new = [] for row in valueList: # For each row in the result timestamp = row[2].strftime('%Y-%m-%d %H:%M:%S') timestampFractions = row[3] templatestAddTime = row[2].strftime( '%Y-%m-%d %H:%M:%S') templatestAddFractions = row[3] data = row[4] # Add measurementvalues to a new list remoteChannel = row[1] + 60 * ( piid - 1) # Convert local id to remoteid if not (timestamp == self.latestAddTime and timestampFractions == self.latestAddFractions): new.append( (self.remoteSessionId, remoteChannel, timestamp, timestampFractions, data) ) # If the timestamp in this result matches the last timestamp in the previous result # dont add it to the new list if not new == []: Database.remoteAddToDatabase( self.remoteDatabase, new ) # If the list is not empty, add values to the remote database self.latestAddTime = templatestAddTime self.latestAddFractions = templatestAddFractions # Set latest add timestamp if self.databaseIsDown: # If the database was down, the database is now up since the addition was succesful self.connectionEstablished.emit( ) # Signals main thread that the database is connected self.databaseIsDown = False newStart = end.strftime( '%Y-%m-%d %H:%M:%S' ) # Write the end time used in the search to the configfile # To be used as start time in the next search configInterface.setConfig('config.cfg', 'latestsession', {'start': newStart}) else: self.shouldEnd.clear() except pymysql.err.Error as E: # If the database raises an exception if not self.databaseIsDown: self.noConnection.emit( ) # Signal the main thread that the database is down self.databaseIsDown = True print(E) self.programQuit.clear()
def startSession(self): """ Starts a new session :return: """ try: w = self.widgetList.widget settings = self.widgetList.channelSettingsIndex self.useRemote = w( self.widgetList.databaseSettingsIndex).useRemote( ) # Checks if a remote database should be used self.localDatabase = configInterface.readConfig( 'config.cfg', 'default') # Gets configuration for the local database sessionName = w(settings).sessionname # Gets the sessionname channelList = w( settings ).channellist # Gets a list of channels to use in the session timeInterval = w(settings).sessionintervall localChannels = copy.deepcopy( channelList) # Gets the time intervall for the session if self.useRemote: # If a remote should be used self.remoteDatabase = \ configInterface.readConfig('config.cfg', 'remote') # Get remote database configurations if configInterface.hasSection('config.cfg', 'piid'): identifiers = configInterface.readConfig( 'config.cfg', 'piid') self.uuid = identifiers['uuid'] if not Database.remotePiExists(self.remoteDatabase, identifiers['uuid']): newIdentifiers = Database.remoteAddNewPi( self.remoteDatabase) print(newIdentifiers) configInterface.setConfig('config.cfg', 'piid', {'piid': str(self.piid)}) else: self.piid = Database.remoteGetPiid( self.remoteDatabase, self.uuid) configInterface.setConfig('config.cfg', 'piid', {'piid': str(self.piid)}) else: newIdentifiers = Database.remoteAddNewPi( self.remoteDatabase) print(newIdentifiers) self.uuid = newIdentifiers['uuid'] self.piid = int(newIdentifiers['piid']) configInterface.setConfig('config.cfg', 'piid', { 'uuid': self.uuid, 'piid': str(self.piid) }) remoteChannels = self.convertToRemoteChannels(channelList) self.remoteSessionId = \ Database.remoteStartNewSession(databaseValues=self.remoteDatabase, name=sessionName, channels=remoteChannels, piid=self.uuid) # Make a new session entry to the remote database self.localSessionId = \ Database.startNewSession(databaseValues=self.localDatabase, name=sessionName, channels=localChannels) # Make a new session entry to the local database currentTime = datetime.datetime.now() startSearchValue = currentTime.strftime('%Y-%m-%d %H:%M:%S') startFractions = str( currentTime.microsecond) # Get timestamp for session start writeItem = { 'start': startSearchValue, 'startfractions': startFractions, 'localdatabase': str(self.localDatabase), 'localsessionid': str(self.localSessionId), 'timeintervall': str(timeInterval), 'end': '' } # Add session information to configfile if self.useRemote: # If a remote is used writeItem['remotedatabase'] = str(self.remoteDatabase) writeItem['remotesessionid'] = str( self.remoteSessionId ) # Add information about the remote session parser = configparser.ConfigParser() with open('config.cfg', 'r') as r: parser.read_file(r) parser.remove_section( 'latestsession' ) # Remove previous information from the configfile with open('config.cfg', 'w') as w: parser.write(w) configInterface.setConfig( 'config.cfg', 'latestsession', writeItem) # Write the new information to the configfile addThread = Addthread(localDatabase=self.localDatabase, sessionId=self.localSessionId, shouldEnd=self.shouldEnd, channelList=localChannels, timeInterval=timeInterval) addThread.start( ) # Create a thread for adding to the local database and start it if self.useRemote: # If a remote database is used remoteAddThread = AddRemoteThread( remoteDatabase=self.remoteDatabase, localDatabase=self.localDatabase, remoteSessionId=self.remoteSessionId, sessionId=self.localSessionId, shouldEnd=self.shouldEndRemote, programQuit=self.programQuit, timeInterval=timeInterval) remoteAddThread.connectionEstablished.connect( self.stopWarningUser) remoteAddThread.noConnection.connect(self.warnUser) remoteAddThread.start( ) # Create a thread for adding to the remote database and start it self.dataDisplay = DataDisplay( databaseValues=self.localDatabase, sessionId=self.localSessionId, channelList=localChannels, ongoing=True, timeInterval=timeInterval ) # Create a new window for displaying data self.dataDisplay.show() # Show the window self.widgetList.mainMenu.sessionStarted( ) # Change appearance of mainmenu self.showMainMenu() # Display the mainmeny self.sessionRunning = True except pymysql.err.Error as E: if E.args[0] == 1045: # If mysql connection denied message = "Anslutning nekad, se över port, användare och lösenord" self.messageToUser(messageText=message, closeButtonText="Stäng") if E.args[0] == 2003: # If mysql connection cant be found message = "Kunde inte anluta till host: '%s'" % ( self.remoteDatabase['host']) self.messageToUser(messageText=message, closeButtonText="Stäng") if E.args[0] == 1049: # If the database wasnt found message = "Hittade ingen database med namnet '%s'" % ( self.remoteDatabase['name']) self.messageToUser(messageText=message, closeButtonText="Stäng") if E.args[0] == 1062: # If mysql integrity error message = "Minst två kanaler har samma namn. Kanalnamn måste vara unika" self.messageToUser(messageText=message, closeButtonText="Stäng") except ValueError as V: # If wrong value in port field print(V) wrongPortType = "Fel typ för 'Port', ett heltal förväntas" self.messageToUser(messageText=wrongPortType, closeButtonText="Stäng")
def checkForAbortedSession(self): """ Continues a started session if the program was terminated without ending the session :return: """ with open( 'config.cfg', 'r' ) as configfile: # Check if the configfile has a latestsession section parser = configparser.ConfigParser() parser.read_file(configfile) abortedSession = parser.has_section('latestsession') if abortedSession: # If the configfile has the section #Reads config file for the aborted session options hasRemote = parser.has_option( 'latestsession', 'remotedatabase') # Check for remote option channels = configInterface.readConfig('config.cfg', 'channels') # Fetch channels sessionSettings = configInterface.readConfig( 'config.cfg', 'latestsession') start = sessionSettings['start'] end = sessionSettings['end'] self.localDatabase = ast.literal_eval( sessionSettings['localdatabase']) self.localSessionId = int(sessionSettings['localsessionid']) timeInterval = float(sessionSettings['timeintervall']) channelDictionary = {} for index in channels: channelDictionary[index] = ast.literal_eval( channels[index]) # Formats the channel if not end: # If the session was not ended addThread = Addthread(localDatabase=self.localDatabase, sessionId=self.localSessionId, channelList=channelDictionary, shouldEnd=self.shouldEnd, timeInterval=timeInterval) addThread.start( ) # Start a thread for adding values to local database if hasRemote: # If a remote database is used in the session self.useRemote = True self.remoteDatabase = ast.literal_eval( sessionSettings['remotedatabase']) self.remoteSessionId = int( sessionSettings['remotesessionid']) remoteAddThread = AddRemoteThread( remoteDatabase=self.remoteDatabase, remoteSessionId=self.remoteSessionId, localDatabase=self.localDatabase, sessionId=self.localSessionId, shouldEnd=self.shouldEndRemote, programQuit=self.programQuit, timeInterval=timeInterval) remoteAddThread.noConnection.connect(self.warnUser) remoteAddThread.connectionEstablished.connect( self.stopWarningUser) remoteAddThread.start( ) # Start a thread for adding values to the remote database else: self.useRemote = False self.sessionRunning = True # Used by other functions to check if a session is running self.widgetList.mainMenu.sessionStarted( ) # Change appearance of the mainmeny self.dataDisplay = DataDisplay( databaseValues=self.localDatabase, sessionId=self.localSessionId, channelList=channelDictionary, ongoing=True, timeInterval=timeInterval) self.dataDisplay.show() # Open new window displaying data