Read integer and transform in time

I read a value from a PLC tag that is integer (seconds), and save this data in an SQL table. I would like to show this value in a powertable but in hh:mm:ss format, and this cell must be editable ( in the powertable) in that format, but write in integer format in plc.
Example: PLC 60 seconds / Ignition 00:01:00

Thanks so much

I would adjust the query to return the time in hh:mm:ss format.

In the onCellEdited, your script might look something like:

if colName == 'timeColumn':
	seconds = sum(int(x) * 60 ** i for i, x in enumerate(reversed(newValue.split(':'))))
	ndx = self.data.getValueAt(rowIndex, 0) # Or however you are discerning one row from another

	query = 'UPDATE myTable SET timeColumn = ? where ndx = ?'
	system.db.runPrepUpdate(query, [seconds, ndx], myDbConnectionName)
	# Refresh the table after writing to the db.
	system.db.refresh(self.data)
1 Like

That one-liner for getting seconds from "hh:mm:ss" is excellent. :+1:

Do you also happen to have a one-liner for reverse operation: getting the time string ("HH:mm:ss") from seconds?

This function isn't quite what you asked for but you can certainly call it with a one-liner.

def format_seconds_to_hhmmss(seconds):
	minutes, seconds = divmod(seconds, 60)
	hours, minutes = divmod(minutes, 60)

    # For maximum readability don't return leading zeros.
	if hours:
		return "%1i:%02i:%02i" % (hours, minutes, seconds)
	elif minutes:
		return "%02i:%02i" % (minutes, seconds)
	else:
		return "%02i" % (seconds)

I created it for machine uptime / downtime (where the colour changes from green to red) and it can display > 24 hours.

I call the function from a binding script transform:
return (timeFunctions.format_seconds_to_hhmmss(value))

3 Likes

Almost.

from datetime import timedelta
hms = str(datetime.timedelta(seconds=inputValue))
2 Likes

Yes! this worked when I write on cell ( like you mentioned on CellEdited), but…

I have a button, with some scripts to read the value of tag on PLC and refresh the PowerTable with this values), I put the same line (seconds = sum(int(x) * 60 ** i for i, x in enumerate(reversed(newValue.split(':')))) ) in the script button, but continue writing the integer number and not in format “HH:mm:ss”.

Thanks for all help.

Maybe if you show your code. My mind reading skills are not what they used to be. :wink:

I used float and not int, because some numbers can be float. Thanks!!!

***onCellEdited - work, I can write in the table's cell and in the PLC tag OPC**


if colIndex == 5: # write  new value JUST INTO the table
			for row in py_TableData:
				
				
					tPath = self.data.getValueAt(rowIndex,1) # copy tagpath from column 1
					vlr = self.data.getValueAt(rowIndex,5)
					print vlr , "vlr"
					
					#convert time in integer
					import datetime
					from datetime import timedelta

					seconds = sum(int(x) * 60 ** i for i, x in enumerate(reversed(newValue.split(':'))))
					print seconds
					
					system.tag.write(tPath,seconds) # write tagpath with new value in PLC and table
					id = self.data.getValueAt(rowIndex, 0) # Or however you are discerning one row from another
						
					query = "UPDATE IgnitionDB.dbo.ParamTimer SET ValuePLC = ? WHERE TagName = ?" % (colName)
					system.db.runPrepUpdate(query, [seconds, TagName])
			# Refresh the table after writing to the db.
					system.db.refresh(self, "data")  

#********************************button - actionPerformed  - don't work - used to refresh the power table with int or float values from PLC  ************

import system

TableData2 = system.gui.getParentWindow(event).getComponentForPath('Root Container.PowerTable2').data

ltable = [TableData2]
for TableData in ltable :

#Convert to PyDataset (easier to loop through)
	py_TableData = system.dataset.toPyDataSet(TableData)
	
#Start the transaction
	txID = system.db.beginTransaction(timeout=5000)
	columnDB = system.db.runQuery('SELECT id FROM IgnitionDB.dbo.ParamTimer').getColumnAsList(0)
#column ID from table and ID from DB and compare returning a list
	columnDB  = str(tuple(columnDB ))
	columnDB  = columnDB.replace("(", '')
	columnDB  = columnDB.replace(")", '')
	columnDB  = columnDB.replace(",", '')
	columnDB = columnDB.replace("u'", '')
	columnDB = columnDB.replace("'", '')
#Loop through the rows in the dataset, and insert them into the database.
	
	for row in py_TableData:
		
		if str(row['id']) in columnDB:
		
			column1 = row['id']
			column2 = row['TagPath']
			column3 = row['Descr']
			column4 = row['ValueDB']
			column6 = row['ValuePLC']
			column7 = row['TagName']
			
			print column7 , "tag"
			vlr = system.tag.read(row['TagPath']).value  # READ tagpath with new value in PLC 
			print vlr , "vlr"
			
			colName = "ValuePLC"
	
			query = "UPDATE IgnitionDB.dbo.ParamTimer SET %s = ? WHERE id = ?" % (colName)
			args = [vlr, column1]
			
# HERE ------Convert to HH:mm:ss  ************************************************************************
			import datetime
			from datetime import timedelta
			
			newValue = str(vlr)
			print newValue
			
			seconds = sum(float(x) * 60 ** i for i, x in enumerate(reversed(newValue.split(':'))))
			print seconds , "sec"
			
			if  "TIME" in column7:  **# JUST FROM TAG WITH "TIME" IN THE NAME**
				vlr = vlr/60
				vlr= str(vlr)  # because I have errors with int and string

				seconds = sum(float(x) * 60 ** i for i, x in enumerate(vlr.split(':')))
				print seconds , "secif"
				
				query = "UPDATE IgnitionDB.dbo.ParamTimer SET %s = ? WHERE id = ?" % (colName)
				
				args = [seconds, column1]
				print "if"
		
			
		    # Run the query with the specified arguments.
			system.db.runPrepUpdate(query, args)
			#system.db.refresh(self, "data")

If you're talking about this bit:

seconds = sum(float(x) * 60 ** i for i, x in enumerate(reversed(newValue.split(':'))))

Then it makes no sense.
We're talking about time here, the 3 parts separated by : in 03:14:53, which are hours, minutes and seconds. Those can't be float.

what's vlr when you first get it ? Right here:

vlr = system.tag.read(row['TagPath']).value  # READ tagpath with new value in PLC 

what are its type and value ?

Hiii
I read just one value from PLC, this tagPath: vlr = system.tag.read(row['TagPath']).value and it is float ( but is a number that represent seconds for example 60,120,3600,7200), and I want convert to this format HH:mm:ss. I don't have a number for each HH, mm, ss.
The problem isn't in the "read" the number, but convert it.
Thank you.

Well you can’t expect this newValue.split(':') to work on a float.
You need to format your timestamp to a date with system.date.format() or whatever formatting function you prefer. Maybe not this one actually, I think it takes an int, a float won’t work.

Or, from post 5...

example:

from datetime import timedelta

inputValue = 1234.5
hms = str(timedelta(seconds=inputValue))

print hms

Output:

0:20:34.500000
>>> 
1 Like

Thank you so much, worked! I’ve tried before but I was missing a line of code and it didn’t work, now I tried again and it worked :slight_smile:


from datetime import timedelta
**inputValue = 1234.5**
hms = str(timedelta(seconds=inputValue))

Note the nice code formatting blocks in the answers. Use the </> code formatting button to do this. It preserves indentation and applies syntax highlighting. If you want a bit of inline code then put it between two backticks `like this`.

1 Like