Uplink function - how to change data label and icon using data bindings?

Hi there!
I am building an automatic chicken coop and have a question about data binding.

I want to modify a text label using data binding. I tried to create a data table in my anvil server that is modified with the door_status variable.
1- how can i modify the door_status value in my table? do i need to add a row each time?
2- how to have the door_status value displayed as my text label (text label will change depending on door_status value)? Also, how can i modify an icon (door opened and door closed) depending on that status?

Here is the open_door function

#open coop door
@anvil.server.callable
def open_coop_door():
    for i in range(0, max_time_coop_motor, 1):
        motor.forward()
        time.sleep(1)
        i = i + 1
        print(i)
        if GPIO.input(LS001):
            motor.stop
            print('Door Opened')
            door_status= 'Opened'
            return
        elif i == max_time_coop_motor:
            print('Alarm LS001')
            door_status= 'Alarm LS001'
            #cleanup
            return
        else:
            pass

Here’s one idea - you could add a timer component on your client code with a timer_tick event handler.

You then silently check the status of the door at regular intervals

def timer_tick(self, **event_args):
    door_status = anvil.server.call_s('check_door_status') 
    # call_s is a slient call - i.e. no loading indicator
    self.door_status_label.text = door_status

Then on the server you could check your global flag DOOR_STATUS


# Server code
DOOR_STATUS = 'closed'

@anvil.server.callable
check_door_status():
    return DOOR_STATUS 
    # similar to the AUTO_MODE variable, set this in the open_coop_door function

@anvil.server.callable
def open_coop_door():
    global DOOR_STATUS
    # logic as before

You could also look to do it with an http endpoint, or as you suggest - checking a datatable row.

This is no help to you, but I think more posts should start with sentences like that.

2 Likes

Again, you are right, it is working!!! i am learning so much.

I am now trying to change the icon depending on door_status value. It is working fine if the icons are already integrated in Anvil. Although, when trying to upload icons that are located in my computer, it is not working (i am using the link that anvil gives me when uploading an icon).

Is it possible to use external icons?

 def timer_tick(self, **event_args):
      door_status = anvil.server.call_s('check_door_status') 
      # call_s is a slient call - i.e. no loading indicator
      self.door_status_label.text = door_status
      if door_status == 'Fermée':
        self.door_icon_label.icon('')
      elif door_status == 'Ouverte':
        self.door_icon_label.icon('')
      elif door_status == 'Alarme LS001' or door_status == 'Alarme LS002':
        self.door_icon_label.icon('fa:exclamation')

if you have a small number of icons you can add these images to the assets folder

then you can reference the icons like: _/theme/{your_icon_filename}

icon isn’t a callable it’s a property so change your code to

      if door_status == 'Fermée':
        self.door_icon_label.icon = ''
      elif door_status == 'Ouverte':
        self.door_icon_label.icon = '' # can also set this to  '_/theme/{your_file}'
      elif door_status == 'Alarme LS001' or door_status == 'Alarme LS002':
        self.door_icon_label.icon = 'fa:exclamation'

i have basic skills of html programing and not sure why my program isn’t working. i created two files (see below for closed_door icon example). the css icons library looks very common and popular.

File

<!DOCTYPE html>
<html>
<head>
<script src="https://kit.fontawesome.com/MY_CODE" crossorigin="anonymous"></script>
</head>
<body>
  
<i class="fas fa-door-closed"></i>
  
</body>
</html>

Code in my form:

  def timer_tick(self, **event_args):
      door_status = anvil.server.call_s('check_door_status') 
      # call_s is a slient call - i.e. no loading indicator
      self.door_status_label.text = door_status
      if door_status == 'Fermée':
        self.door_icon_label.icon = '_/theme/closed_door_icon.html'
      elif door_status == 'Ouverte':
        self.door_icon_label.icon = '_/theme/opened_door_icon.html'
      elif door_status == 'Alarme LS001' or door_status == 'Alarme LS002':
        self.door_icon_label.icon = 'fa:exclamation'

I tested it with an anvil icon and it is working fine.

You can’t set the icon property of a label to be html.
You can set it to a string (e.g. fa:heart) or a url to an image/svg file (e.g. _/theme/img.png).

To use the newer version of fonteawesome include the script tag in your native libraries (see the Theme section of your app).

If you are just using the free version then you should be able to include almost all the icons you need without having to do anything fancy.

e.g. the following code should just work

 def timer_tick(self, **event_args):
      door_status = anvil.server.call_s('check_door_status') 
      # call_s is a slient call - i.e. no loading indicator
      self.door_status_label.text = door_status
      if door_status == 'Fermée':
        self.door_icon_label.icon = 'fa:door-closed'
      elif door_status == 'Ouverte':
        self.door_icon_label.icon = 'fa:door-open'
      elif door_status == 'Alarme LS001' or door_status == 'Alarme LS002':
        self.door_icon_label.icon = 'fa:exclamation'

If you have pro icons then see this thread:

Hello stu,

I finally managed to make it work. It was, as you said, pretty straight forward but I was having difficulties.

I simply added the font awesome library…

I then used the fa code, same structure as the icons in Anvil:
image

It is a simple way to have a lot of icons for free!

Thanks again.

3 Likes