10 Replies Latest reply on May 14, 2015 5:11 PM by CMata_Intel

    Edison Interrupt Service Routine In Python Daemon

    LightBulb

      Further extending the IO event handling framework in python question I would like my code to run in a daemon mode.

       

      This seems to be a suitable daemon framework and it works as it is:

      A simple unix/linux daemon in Python - Lone Wolves - Web, game, and open source development

       

      Now here is my code where I am basically just copied stuff from the earlier post to the overriden run method. Unfortunately it does not work at all. The daemon crashes.

       

      
       #!/usr/bin/env python 
      
      import sys, time  
      from daemon import Daemon  
      
      import mraa  
      
      class Toggle:  
        state = 0  
      
      class MyDaemon(Daemon):  
        def run(self):  
       mraa.Gpio(8).dir(mraa.DIR_OUT) 
       mraa.Gpio(4).dir(mraa.DIR_IN) 
        t=Toggle()  
      
        def pressed(args):  
        if t.state==0:  
       mraa.Gpio(8).write(1) 
        t.state = 1  
        else:  
       mraa.Gpio(8).write(0) 
        t.state = 0  
      
      
       mraa.Gpio(4).isr(mraa.EDGE_RISING, pressed, pressed) 
      
        while True:  
       time.sleep(60) 
      
      
      if __name__ == "__main__":  
       daemon = MyDaemon('/tmp/daemon-example.pid') 
        if len(sys.argv) == 2:  
        if 'start' == sys.argv[1]: 
        daemon.start()  
        elif 'stop' == sys.argv[1]: 
        daemon.stop()  
        elif 'restart' == sys.argv[1]: 
       daemon.restart() 
        else:  
        print "Unknown command" 
        sys.exit(2)  
        sys.exit(0)  
        else:  
        print "usage: %s start|stop|restart" % sys.argv[0] 
        sys.exit(2) 
      
      
        • 1. Re: Edison Interrupt Service Routine In Python Daemon
          LightBulb

          The forum syntax highlighter is a disaster. It is impossible just to copy-paste from vi window. The code loses the formatting and goes into a table form (huh?). I have to spend half an hour shaping the code again. I wonder if this happens to me only.

          #!/usr/bin/env python

           

          import sys, time

          from daemon import Daemon

           

          import mraa

           

          class Toggle:

            state = 0

           

          class MyDaemon(Daemon):

              t=Toggle()

           

              def pressed(args):

                if t.state==0:

                  mraa.Gpio(8).write(1)

                  t.state = 1

                else:

                  mraa.Gpio(8).write(0)

                  t.state = 0    

           

              def run(self):

                  mraa.Gpio(8).dir(mraa.DIR_OUT)

                  mraa.Gpio(4).dir(mraa.DIR_IN)

                  mraa.Gpio(4).isr(mraa.EDGE_RISING, pressed, pressed)

                  while True:

                                  time.sleep(60)

           

                        

           

           

           

          if __name__ == "__main__":

              daemon = MyDaemon('/tmp/daemon-example.pid')

              if len(sys.argv) == 2:

                  if 'start' == sys.argv[1]:

                      daemon.start()

                  elif 'stop' == sys.argv[1]:

                      daemon.stop()

                  elif 'restart' == sys.argv[1]:

                      daemon.restart()

                  else:

                      print "Unknown command"

                      sys.exit(2)

                  sys.exit(0)

              else:

                  print "usage: %s start|stop|restart" % sys.argv[0]

                  sys.exit(2)

           

          • 2. Re: Edison Interrupt Service Routine In Python Daemon
            CMata_Intel

            Hi LightBulb ;

             

            What do you mean when you say the daemon crashes? Does the board stop working? Is there an error message on the Terminal Console? Or doesn't work at all?

            How are you running the daemon?

             

            Regards;

            CMata

            • 3. Re: Edison Interrupt Service Routine In Python Daemon
              LightBulb

              Hi CMata_Intel,

               

              I start my daemon daemon-example.py as it is supposed to be started

              ./daemon-example.py start

              And if I have commented out the line

                 
              mraa.Gpio(4).isr(mraa.EDGE_RISING, pressed, pressed)

              then the daemon is listed the list of processes shown by the ps command.

               

              I have done some experiments with the code and the "if mraa.Gpio(4).read() ==1  mraa.Gpio(8).write(1)" type of logic works fine.

               

              When the line interrupt line is there the daemon process is not appearing in the process list. Edison board keeps running. I do not get an error message because all the streams of the daemon are redirected to /dev/null.

               

              I wonder if there is something obvious that I am missing about interrupts?

              Otherwise I guess I'd need to see how I get the error messages, set up logging etc.

              • 4. Re: Edison Interrupt Service Routine In Python Daemon
                LightBulb

                I have added tests and enabled the stdout and stderr in the daemon wrapper.

                So now I can see that mraa.Gpio(4).isr(mraa.EDGE_RISING, pressed, pressed)  is working as supposed the first time it is called.

                The second time inside the run(self) method of the class MyDaemon(Daemon) it has no effect. Does not produce an error either.

                [Python] daemon2.py - Pastebin.com - this is my code (chmod u+x)

                [Python] daemon.py - Pastebin.com  - this is the daemon boilerplate, it has to be in the same folder

                 

                #!/usr/bin/env python

                 

                import sys, time

                from daemon import Daemon

                 

                import mraa

                 

                mraa.Gpio(8).dir(mraa.DIR_OUT)

                mraa.Gpio(4).dir(mraa.DIR_IN)

                 

                def pressed(args):

                    print("called the pressed method")

                    mraa.Gpio(8).write(1)

                 

                mraa.Gpio(4).isr(mraa.EDGE_RISING, pressed, pressed) # first time

                time.sleep(5)

                 

                 

                class MyDaemon(Daemon):

                    def run(self):

                        print("first blink")

                        mraa.Gpio(8).write(0)

                            time.sleep(1)

                        mraa.Gpio(8).write(1)

                            time.sleep(1)

                        mraa.Gpio(8).write(0)

                     

                        print("in the loop")

                        light=False

                        while not light:

                            if mraa.Gpio(4).read():

                                mraa.Gpio(8).write(1)

                                light=True

                                print("turn the light on and exit the loop")

                            time.sleep(.5)         

                 

                        print("exited the loop")

                        time.sleep(1)

                        mraa.Gpio(8).write(0)

                        print("turned the light off")

                 

                        print("just before the isr call")

                        mraa.Gpio(4).isr(mraa.EDGE_RISING, pressed, pressed) # second time

                        print("past the isr call, sleep for 5 sec")

                            time.sleep(5)

                 

                        print("second blink")

                        mraa.Gpio(8).write(0)

                            time.sleep(1)

                        mraa.Gpio(8).write(1)

                            time.sleep(1)

                        mraa.Gpio(8).write(0)

                        print("daemon exits")

                 

                 

                if __name__ == "__main__":

                    daemon = MyDaemon('/tmp/daemon2.pid')

                    if len(sys.argv) == 2:

                        if 'start' == sys.argv[1]:

                            daemon.start()

                        elif 'stop' == sys.argv[1]:

                            daemon.stop()

                        elif 'restart' == sys.argv[1]:

                            daemon.restart()

                        else:

                            print "Unknown command"

                            sys.exit(2)

                        sys.exit(0)

                    else:

                        print "usage: %s start|stop|restart" % sys.argv[0]

                        sys.exit(2)

                 

                 

                P.S. to enable printing and errors just put the proper strings into the daemon.py where there was /dev/null before

                def __init__(self, pidfile, stdin='/dev/null', stdout='/dev/null', stderr='/dev/null'):

                def __init__(self, pidfile, stdin='/dev/null', stdout='/dev/stdout', stderr='/dev/stderr'):
                • 5. Re: Edison Interrupt Service Routine In Python Daemon
                  CMata_Intel

                  Hi LightBulb

                   

                  I'm sorry for the delay in my response, do you have updates in this? Have you tried to debug what is happening in the service? Have you tried to chmod 777 the service in order to assign permissions to the driver?

                  When you say "'...is working as supposed the first time it is called", what happens next that stops working(unplug/plug the board, rebooting, run another service, ....)

                   

                  Regards;

                  CMata

                  • 6. Re: Edison Interrupt Service Routine In Python Daemon
                    LightBulb

                    I have edited the code preceding your comment so you can see what am referring to first and second time (in bold).

                    My experience with Python Classes is virtually zero so I might have done a silly error there. Anyway the second time the method "pressed" is obviously not called when I push the button. Apart from that everything works. When I restart the daemon it does listen for the interrupt the "first time" again.

                    Changing the permissions to 777 did not help.

                    • 7. Re: Edison Interrupt Service Routine In Python Daemon
                      LightBulb

                      A more refined version

                       

                      #!/usr/bin/env python

                       

                      import sys, time

                      from daemon import Daemon

                       

                      import mraa

                       

                      mraa.Gpio(8).dir(mraa.DIR_OUT)

                      mraa.Gpio(4).dir(mraa.DIR_IN)

                       

                      def turn_light_on(args):

                          print("called the turn_light_on method")

                          mraa.Gpio(8).write(1)

                       

                      def turn_light_off(args):

                          print("called the turn_light_off method")

                          mraa.Gpio(8).write(0)

                       

                      def blink():

                          turn_light_off(turn_light_on)

                              time.sleep(1)              

                              turn_light_on(turn_light_on)

                              time.sleep(1)                 

                              turn_light_off(turn_light_off)

                       

                      class MyDaemon(Daemon):

                          def run(self):

                       

                              print("first blink")

                              blink()

                       

                              print("just before the isr call")

                              mraa.Gpio(4).isr(mraa.EDGE_RISING, turn_light_on, turn_light_on)

                              print("past the isr call, sleep for 15 sec")

                              time.sleep(15)

                      # here a button press (Gpio(4)) should fire an interrupt and a call to turn_light_on but it has no effect, why?

                       

                              print("second blink")

                              blink()

                       

                              print("daemon exits")

                       

                      if __name__ == "__main__":

                          daemon = MyDaemon('/tmp/daemon2.pid')

                          if len(sys.argv) == 2:

                              if 'start' == sys.argv[1]:

                                  daemon.start()

                              elif 'stop' == sys.argv[1]:

                                  daemon.stop()

                              elif 'restart' == sys.argv[1]:

                                  daemon.restart()

                              else:

                                  print "Unknown command"

                                  sys.exit(2)

                              sys.exit(0)

                          else:

                              print "usage: %s start|stop|restart" % sys.argv[0]

                              sys.exit(2)

                      • 8. Re: Edison Interrupt Service Routine In Python Daemon
                        LightBulb

                        I still do not know why but below code works. The part in bold is what has made a difference. Thanks for your great support everybody.

                        #!/usr/bin/env python

                         

                        import sys, time

                        from daemon import Daemon

                        import mraa

                        class Toggle:

                          state = 0

                        class MyDaemon(Daemon):

                            def run(self):

                                t=Toggle()

                                mraa.Gpio(8).dir(mraa.DIR_OUT) # connect Relay to the D8

                                def pressed(args):

                                    if t.state==0:

                                        mraa.Gpio(8).write(1)

                                        t.state = 1

                                    else:

                                        mraa.Gpio(8).write(0)

                                        t.state = 0 

                                x = mraa.Gpio(4) # connect button to the D4

                                x.dir(mraa.DIR_IN)

                                x.isr(mraa.EDGE_RISING, pressed, pressed)

                                while True:

                                    time.sleep(15)

                         

                        if __name__ == "__main__":

                            daemon = MyDaemon('/tmp/daemon5.pid')

                            if len(sys.argv) == 2:

                                if 'start' == sys.argv[1]:

                                    daemon.start()

                                elif 'stop' == sys.argv[1]:

                                    daemon.stop()

                                elif 'restart' == sys.argv[1]:

                                    daemon.restart()

                                else:

                                    print "Unknown command"

                                    sys.exit(2)

                                sys.exit(0)

                            else:

                                print "usage: %s start|stop|restart" % sys.argv[0]

                                sys.exit(2)

                        1 of 1 people found this helpful
                        • 9. Re: Edison Interrupt Service Routine In Python Daemon
                          CMata_Intel

                          Hi LightBulb

                           

                          I'm really glad that now you are able to use the service as you wanted. I encourage you to keep posting all your doubts/questions and also your results or project.

                           

                          Kind Regards

                          -CMata