Need to set the timer in ignition when table has fetched the data

I need to set the timer count when the table filed is entered.
I have a start button, which will open one popup, in that popup, there is some text input component, when I enter those details, all details will go into table, once table is fetched the data, the timer should start counting down, 00:00:00(HH:MM:SS) for 30 mins. in start button component itself.
start
add
How can I achieve this? Kindly help me!

  • On the primary view create custom.tableTimer.
  • In the script that fetches the table data add the lines,
	future = system.date.addMinutes(system.date.now(), 30)
	self.view.custom.tableTimer = future
  • On the button text property add an expression binding:
if(now(1000) > {view.custom.tableTimer},
	"--:--:--",
	dateFormat(
		{view.custom.tableTimer} - now(1000),
		"HH:mm:ss"
	)
)
1 Like

Thank you for your reply. My popup is configured in another view. How can I pass the custom.tabletimer to main view where the timer starts. I tired to system.navigate function by passing the parameter , but it is opening one view,Kindly help me!

It is not clear,

  1. Where is this button? On the main view or on the popup?
  2. Where is the table? On the main view?
  3. When data is entered in the popup how is the table updated?
  4. Why are you displaying time on a button? A button should show what the function of the button is. Showing time on a is not standard GUI and will cause operator confusion. Show the time on a label.

You can send messages between Perspective views using system.perspective.sendMessage | Ignition User Manual to send and Component Message Handlers | Ignition User Manual to receive them. (There is an IU video on the second link.)

I think you need to fix your user interface first.

1 Like

Thank you for your reply. Let me explain my UI flow.
I have one View A. This View A is figure 1. When I click start button, View B will open as dock view as figure 2 appear. In view B . I will enter the details, enterted details will poll into the table. Once table data has been polled , The timer should start for 30 mins. View c has many embedded view of View B. The timer should run in start button component. Attached the images.
fig-4




Hope I have explained clearly than before. Kindly guide me.

sendMessage and a message hanlder will do what you require.

General comments

  1. Your Start button is labelled incorrectly because it doesn't actually start the process. It only takes you to the setup screen. It should be labelled as New batch or Setup.
  2. The popup has no indication which machine or process is being edited. If the user gets distracted and returns to the screen they may enter incorrect data. Add the process name to the popup titlebar or a label on the popup. (Pass it in as a parameter.)
  3. The popup should have clearly labelled buttons - typically Proceed Cancel or OK Cancel. These may need to be separate from the Add button which should only add a line to the list.
  4. The Add button should be in the same style as the Reset and Start buttons for consistent user experience.
  5. The Add button appears to be enabled despite no selections having been made on the popup form. This is bad. Use the OK button but only enable it when valid values are selected or input on each of the form controls.
  6. If you insist on displaying the countdown on the button text then at least disable the button and show a disabled style so the user knows they can't press it.
  7. Temperature should have the ° symbol in front of C.
1 Like

Thank you for your valuable input. Will correct it. Also, I was getting the error. Kindly hele me to resolve this.
I have added the code

future = system.date.addMinutes(system.date.now(), 30)
	self.view.custom.tableTimer = future

, and output for this is below
"2024-06-04T11:30:57.187Z."
I am taking this custom component value to another view via system.send message function,
, there I was implementing the below code in the label, but it was throwing expression error

You haven't copied my expression code correctly.

You could consider using a session variable instead. This would be available to all views (but would be shared between all browser tabs as well).

Tips:

  1. Use line breaks and indentations on your expressions to make them easier to read and debug.
  2. When reporting that there is an expression error then please state what the error message is.
1 Like

Yes corrected. Can you please reset the code like, count the time from 0sec to 30 mins in the same HH:MM:SS format, just from when the table polled the data. Kindly help me

I think you need to start working out some of this stuff yourself. You have a good starting point in the solution I gave you.

  • Modify self.view.custom.tableTimer to store the time now.
  • Modify my expression binding on the button's props.text to display the elapsed time.

If you get stuck then paste your formatted code and any error messages.

1 Like

What should happen when the user's browser crashes after they've started the timer? Or when another user simultaneously opens the same process?

Managing state in the session or other UI variables doesn't handle those cases. One or more gateway memory tags or PLC OPC tags should be used to hold the state of the process.

2 Likes

Thank you for your reply. Will check on this

Sure. Thank you

So I have written the python code for timer to run for 2 hrs in hh:mm:ss forward format. Here is the code,

import time

def run_clock():
    for hour in range(3):  # range(3) because we need to include the 2-hour mark
        for minute in range(60):
            for second in range(60):
                if hour == 2 and minute == 0 and second == 0:
                    return
                current_time = f"{hour:02}:{minute:02}:{second:02}"
                print(current_time, end="\r")
                time.sleep(1)

run_clock()

I am thinking to bind this code with one memory tag, is it possible to write the each value to that tag, if yes kindly guide me

Oy! no! Just use a timer event with a bit of state in one or more memory tags.

Ignition is event driven. Any kind of looping to wait for some condition, whether time or signal, is an invitation to disaster. Any kind of .sleep() call is major red flag.

See this topic for similar techniques:

1 Like

There is no need for that.

  • If you want to use a tag you will need one for each machine / process. That means that you should be using a UDT to define all the tags associated with that machine / process.
  • When the process starts write to the startTimeStamp tag (which you will create) using,
    system.tag.writeBlocking(system.date.now())
  • Anywhere you need to display the elapsed time use an expression binding similar to this:
dateFormat(
	now(1000) - {[default]Process03/startTimeStamp},
	"HH:mm:ss"
)

The now(1000) will cause the expression to reevaluate and update every 1000 ms.

If you ever find yourself using sleep() in a script it is likely that you have lost your way. It is a bad idea.

1 Like

Thank you for your input

Thank you !