Search code examples
pythonpython-3.xkivykivy-language

Kivy Label Unable to refresh when validating the Ip address


I'm building a Kivy interface with raspberry pi module.In the user interface I have status screen which shows the Ip address.If I disconnect the Ethernet cable,screen suppose to give me error label(kivy screenone label:IpAddress) and when I reconnect the Ethernet cable, label should be update back to Ip address. Unfortunately when I disconnect the Ethernet cable app shows the "Error" but when I Reconnect the Ethernet it not showing back my Ip Address. Ipaddress label stays as "Error"..

##this is the root widget
class Menu(BoxLayout):
    manager = ObjectProperty(None)

    def __init__(self, **kwargs):
        super(Menu, self).__init__(**kwargs)
        Window.bind(on_keyboard=self._key_handler)
        #btn1 = ActionButton(text='',icon='./assest/usb.jpg')

    def _key_handler(self, instance, key, *args):
        if key is 27:
            self.set_previous_screen()
            return True

    def set_previous_screen(self):
        if self.manager.current != 'home':
            #self.manager.transition.direction = 'left'
            self.manager.transition = SwapTransition()


class ScreenOne(Screen,BoxLayout):

    stringIP=subprocess.check_output(["hostname", "-I"]).split()[0]
    print_ip = StringProperty(str(stringIP).strip("b'"))

    def __init__(self, **kwargs):
        super(ScreenEnergy, self).__init__(**kwargs)
        #Clock.schedule_interval(self.update_ip, 1)
        scheduler1 = BackgroundScheduler()
        scheduler1.add_job(self.update_ip, 'interval', seconds=1)
        scheduler1.start()
        # #self.update_ip()
        print("status window")


    def update_ip(self,*args):     
        try:
            # connect to the host -- tells us if the host is actually
            # reachable
            socket.create_connection(("www.google.com", 80))
            self.print_ip
            print("ip")
            #print("connected")
            return True
        except OSError:
            self.ids.ipAddress.text="[b][color=ff0000]Error[/color][/b]"
            print("not Ip ")
        return False

        # try:
        #     #socket.inet_aton(self.print_ip)
        #     #socket.inet_pton(socket.AF_INET6, self.print_ip)
        #     self.print_ip='\b(([1-9][0-9]?|1[0-9][0-9]|2[0-4][0-9]|25[0-5])\.){3}'
        #     self.ids.ipLabel.text="faffxga"
        #         # legal
        # except socket.error:
        #     self.ids.ipLabel.text="adadadsadsa"
        # return False

        #         # Not legal

       class MenuApp(FlatApp):


    def build(self):
        my_callback=Menu()
        #ip_call =ScreenEnergy()
        scheduler = BackgroundScheduler()
        scheduler.add_job(my_callback.is_connected, 'interval', seconds=1)
        #scheduler.add_job(ip_call.update_ip, 'interval', seconds=1)
        scheduler.start()
        return my_callback



if __name__ == '__main__':

    MenuApp().run()
#:kivy 1.10.0
#:import hex kivy.utils.get_color_from_hex
#:import Factory kivy.factory.Factory

<Menu>:
    canvas.before:
        Rectangle:
            pos: self.pos
            size: self.size

    manager: screen_manager
    orientation: "vertical"
    ActionBar:

        size_hint_y: 0.15
        background_image: ''
        background_color: 0.349, 0.584, 0.917, 1
        ActionView:
            ActionPrevious:

            ActionButton:
                id:motorBtn
                text:''
                icon:'./assest/Ethernet.jpg'

    Manager:
        id: screen_manager

<ScreenOne>:
    BoxLayout:
        orientation: 'vertical'
        WrappedLabel:
            id:welcomeStatus
            text: "[b]Status[/b]"
            font_size:min(root.width,root.height)/15
        GridLayout:
            cols:2
            row: 3
            padding:root.width*.02,root.height*.03
            spacing:min(root.width,root.height)*.02
            Label:   
                id:ipLabel
                size_hint_x: .15
                color: 0, 0, 0, 1
                text: '[b]IP Address :[/b]'
                markup:True 
            Label:
                id:ipAddress
                size_hint_x: .15
                color: 0, 0, 0, 1
                text: root.print_ip
                color: 1, 0, 0, 1
                bold:True
                markup:True  

<Screen 2>:

<Manager>:

    id: screen_manager

UPDATE TWO: After required modification to the code no more errors on terminal .. at least it's good sign!

class ScreenOne(Screen,BoxLayout):
    print_ip = StringProperty('')
       
    def __init__(self, **kwargs):
        super(ScreenEnergy, self).__init__(**kwargs)
        Clock.schedule_interval(self.update_ip, 1)
        print("status window")
        
    
    def update_ip(self,*args):     
        try:
            # connect to the host -- tells us if the host is actually
            # reachable
            socket.create_connection(("www.google.com", 80))
            stringIP = subprocess.check_output(["hostname", "-I"]).split()[0]
            self.print_ip = str(stringIP).strip("b'")
            print("ip={self.print_ip}")
            return True
        except OSError:
            self.ids.ipAddress.text="[b][color=ff0000]Error[/color][/b]"
            print("not Ip ")
        return False

before disconnecting the Ethernet cable(looks Good) enter image description here

after disconnecting the cable(looks good) enter image description here

after reconnecting the Ethernet cable(not good) enter image description here

looks like code stuck in except OSError: because it's not changing back to Ethernet address.


Solution

  • Problem

    Not resetting of attribute, print_ip inside the try block after socket.create_connection() call.

    Solution

    At class ScreenOne, do the following:

    • Move stringIP=subprocess.check_output(["hostname", "-I"]).split()[0] to after socket.create_connection() call
    • Replace class attribute, print_ip = StringProperty(str(stringIP).strip("b'")) with print_ip = StringProperty('')
    • Add self.print_ip = str(stringIP).strip("b'") after stringIP = subprocess.check() call
    • Replace self.ids.ipAddress.text with self.print_ip

    Snippets

    class ScreenOne(Screen):
    
        print_ip = StringProperty('')
        ...
    
        def update_ip(self,*args):     
            try:
                # connect to the host -- tells us if the host is actually
                # reachable
                socket.create_connection(("www.google.com", 80))
                stringIP = subprocess.check_output(["hostname", "-I"]).split()[0]
                self.print_ip = str(stringIP).strip("b'")
                print(f"ip={self.print_ip}")
            except OSError:
                self.print_ip = "[b][color=ff0000]Error[/color][/b]"
                print("not Ip ")