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. 
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. 
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 
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`
.
2 Likes