Update textbox content from other thread
Hello, I’m started with gradio with the following simple code example:import gradio as gr
from threading import Timer

time = 1

class RepeatTimer(Timer):
    def run(self):
        while not self.finished.wait(self.interval):
            self.function(*self.args, **self.kwargs)

def timer():
    global time
    time += 1 
    box =  demo.children[0].children[0]
    box.value=str(time)

with gr.Blocks() as demo:
    box = gr.Textbox(value="start", label="timer", interactive=True)    

# create & start timer thread
t = RepeatTimer(2.0, timer)
t.start()

# start web server
demo.launch()Why I get no update of the textbox content ? In the debugger I see that the value is updated.What can I do ?
2022-09-25T20:43:42Z
Hi@Barricade! Thanks for the question.If I understand correctly, you’re trying to periodically run a function to update the UI of your app?There isn’t an api to do that in gradio right now. SeeMake it easier to work with streaming data · Issue #2050 · gradio-app/gradio · GitHub. In general, updates to your app have to be triggered through interacting with the UI.Do you mind sharing a bit more about your use case?
2022-09-25T20:58:36Z
Hi@freddyaboulton,thank you for checking my question. At first, I saw the possibilities from gradio to build very easy web gui applications with python. But my first use case is a web based heating house controllerrunning on a raspberry pi with python in a docker container.  There are different temperatures, different relay actors, i want show the values in the web gui. Next step is to define times for switching on and off the relays and I want do it in home from a  tablet and from outside with a smartphone.“In general, updates to your app have to be triggered through interacting with the UI.”Is it f.e. possible to send post requests (from a thread over localhost) to the web gui ?Or has the gui thread a running hookable function ?Or can I simulate button click events, from an unvisible button ?
2022-09-26T16:02:14Z
Very cool demo@Barricade!To show the latest values of the temperature, you do not need to manually update the config like you did in the demo. The config only reflects the state when the app is created.To read the latest temperature value and display it in the UI you can use theloadevent listener. There is a rest api for all gradio apps. When you create an event listener, you can use theapi_nameparameter and that will automatically document a rest endpoint to trigger that event.So a think a skeleton of your demo can look like this:def get_temperature(...):
    ....

def turn_off_relay(....):
    ....

with gr.Blocks() as demo:
    temperature = gr.Number()
    relay_id = gr.Dropdown(choices=[...])
    off_switch = gr.Button(value="Turn off Relay")
    off_switch.click(turn_off_relay, inputs=relay_id, outputs=None, api_name="turn_off")
    demo.load(get_temperature, inputs=None, outputs=[temperature])

demo.launch()You can then click on the “view api” button at the bottom of your app to the the “turn_off” endpoint.If you plan on turning them on or off on a schedule, you can use the code you have to run the “turn off” logic in a separate thread but you shouldn’t store the state of whether or not a relay is turned on or off in the app itself but rather in an external datasource and have gradio from that instead.Hopefully that helps!
2022-09-27T10:54:08Z
Hi Freddy,thank you for your help, i started with your example, using visual studo code as development environment, view python printf output in the terminal window  from vs code.import gradio as gr

gTemperature = -10

def get_temperature():
    global gTemperature
    gTemperature += 1
    print('temperature:', gTemperature)
    return gTemperature

def turn_off_relay(id):
    print('relay:', id)
    return

with gr.Blocks() as demo:
    temperature = gr.Number()
    relay_id = gr.Dropdown(choices=['Rel 1', 'Rel 2'])
    off_switch = gr.Button(value="Turn off Relay")
    off_switch.click(turn_off_relay, inputs=relay_id, outputs=None, api_name="turn_off")
    demo.load(get_temperature, inputs=None, outputs=[temperature])

demo.launch()The “demo.load” function is working, but not as hoped by meThe function get_temperature() was called only one time at starting the app andthan allways i press the F5 key in the browser (temperature is going higher).I wished, that allways the temperature is changing, the value in the number widget is automatily change, like a thermometer.PS D:\Projects\python-projects\gradio> & python.exe d:/Projects/python-projects/gradio/update-textbox.py
Running on local URL:  http://127.0.0.1:7861

To create a public link, set `share=True` in `launch()`.
temperature: -9
temperature: -8
relay: Rel 1
relay: Rel 2For testing the API I installed in firefox the “RESTClient” plugin, whrere I can fire post and get requests with JSON content, but I’m not family with the syntax.
2022-09-27T16:46:24Z
Hi@Barricade!Barricade:The function get_temperature() was called only one time at starting the appRight now, it’s not possible to automatically update the UI when the backend data changes. I suggested using theloadevent so that you could get the latest temperature whenever you manually refreshed the page.We’re thinking about how to support this use case though!  We filed thisissue(linked above) to track this.
2022-09-28T09:57:09Z
ok, api tests are now working, with:curl -X POSThttp://127.0.0.1:7861/api/turn_off-H ‘Content-Type: application/json’ -d ‘{“data”: [“Rel 1”]}’the above function turn_off_relay(id) was called
2022-09-30T16:45:02Z
Hi@Barricade!We’ve been working on adding an API to gradio apps that lets you run functions forever and not refresh the page.What we have right now is therun_forevermethod. It’s similar to theloadmethod but like it says but it runs indefinitely without refreshing the page. For your temperature use case you can do something likedef get_current_temp():
    .... .....

with gr.Blocks() as demo:
    temperature = gr.Number()
    demo.run_forever(get_current_temp,
                     inputs=None,
                     outputs=temperature,
                     every=1 # units in seconds)
demo.queue().launch()It’s available as a python wheel here:https://gradio-builds.s3.amazonaws.com/run-forever/v1/gradio-3.4-py3-none-any.whlAn example using this feature is here:nvidia-smi - a Hugging Face Space by julien-cThis is an experimental feature - the api might change but we’d love to get your feedback on the current API.
2022-10-01T07:26:30Z
Hi@freddyaboulton,thank you, your example is working, also if i change your example fromevery=1 # units in seconds)toevery=0.1)  # units in secondsThe gui is updating very quickly.(next text removed, found my mistake)
2022-10-06T12:49:23Z
Is there a possibility to have more than one “run_forever” functions ?Yes, i checked is working very well.
2022-10-06T17:35:58Z
Great to hear@Barricade! Will try to release this formally soon. Thank you for testing
2022-10-14T07:38:08Z
Hi, can you inform here please, when the for me very well working feature is gone in the release ?
2022-10-14T16:54:49Z
Absolutely@Barricade! Have not released it yet but planning to do it soon.