how to call a method in the plugin class

Posted on
Thu Oct 05, 2017 6:26 pm
kw123 offline
User avatar
Posts: 8360
Joined: May 12, 2013
Location: Dallas, TX

how to call a method in the plugin class

assume
pluginId = "aa.bb.zz"
pluginDisplayName = "aaa"

Code: Select all
class Plugin(indigo.PluginBase)
....
....
  def test(text):
    indigo.server.log(text)
in a class outside class Plugin(indigo.PluginBase)

question: how do I call the method test, tried
Code: Select all
class abc():
  test("0")
  aaa.test("1")
  indigo.aaa.test("2")
  indigo.aa.bb.zz.test("3")
  aa.bb.zz.test("4")
 ### this works:
  indigo.server.log("hello")
and many more none works
class abc() is in the same file as the plugin at the end .


in other words what is the name of the plugin class

any pointer from the real expert appreciated..


Karl

Posted on
Thu Oct 05, 2017 7:02 pm
kw123 offline
User avatar
Posts: 8360
Joined: May 12, 2013
Location: Dallas, TX

Re: how to call a method in the plugin class

got one step further the class name is "Plugin"

now it requires
error='unbound method test() must be called with Plugin " instance" as first argument

now what is the plugin "instance"... tried, Plugin, plugin.xxx, indigo.xxx etc..

Posted on
Thu Oct 05, 2017 7:39 pm
RogueProeliator offline
User avatar
Posts: 2501
Joined: Nov 13, 2012
Location: Baton Rouge, LA

Re: how to call a method in the plugin class

I'm not positive what you are trying to accomplish, but if you are trying to call the function without an instance of the class (i.e. you won't have access to the instance members), you will want to decorate the function with @staticmethod... something like:

Code: Select all
class Plugin(indigo.PluginBase)
   ....
   ....
     @staticmethod
     def test(text):
       indigo.server.log(text)

Posted on
Thu Oct 05, 2017 7:48 pm
kw123 offline
User avatar
Posts: 8360
Joined: May 12, 2013
Location: Dallas, TX

Re: how to call a method in the plugin class

thanks ,

here is want I want to dow.
set up a tcp/ip listener class/instance
then when it gets data call the plugin test method and handover the data to change dev.states ..

Code: Select all
### in plugin class
        server = tcpipServer(("192.168.1.15",12345), ThreadedEchoRequestHandler)
        t = threading.Thread(target=server.serve_forever)
        t.start()
        indigo.server.log( 'Server loop running in thread:', t.getName() )

    def test2(self,textIn):
        indigo.server.log(" test2 called with:")
        indigo.server.log(textIn)
        indigo.server.log(" test2 end")
      #  and then dev.updatestatesonserv etc ..


class ThreadedEchoRequestHandler(SocketServer.BaseRequestHandler):
    def handle(self):
        # Echo back to the client
        data = self.request.recv(1024)
        cur_thread = threading.currentThread()
        response = '%s: %s' % (cur_thread.getName(), data)
        self.request.send("ok")
        indigo.server.log(response)

        try: Plugin.test2(>> what goes here  <<< ,response)
        except  Exception, e:
                indigo.server.log(u"in Line '%s' has error='%s'" % (sys.exc_traceback.tb_lineno, e))
        indigo.server.log("end")

        return

class tcpipServer(SocketServer.ThreadingMixIn, SocketServer.TCPServer):
    pass


so I would like to know: >> what goes here <<<

Posted on
Thu Oct 05, 2017 8:52 pm
kw123 offline
User avatar
Posts: 8360
Joined: May 12, 2013
Location: Dallas, TX

Re: how to call a method in the plugin class

I guess this is the problem:
indigo creates the instance and it is known to INDIGO but not to the other class as IT does not instantiate the plugin class...

have tried to figure out inside the plugin " what is my instance" but that is just a pointer to a memory location I guess...

.. ???

Posted on
Thu Oct 05, 2017 9:04 pm
RogueProeliator offline
User avatar
Posts: 2501
Joined: Nov 13, 2012
Location: Baton Rouge, LA

Re: how to call a method in the plugin class

I think I see what you are trying to do there... I do something similar in Domotics Pad plugin (pared down for readability):

Code: Select all
class Plugin(RPFramework.RPFrameworkPlugin.RPFrameworkPlugin):
   ...
   #-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
   # This routine will send the Update Device Status request notification in order to ask
   # the device to update its status immediately (instead of waiting for its normal 15
   # minute update interval)
   #-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
   def requestDeviceStatusNotification(self, deviceId):
       ...

class ThreadedTCPRequestHandler(SocketServer.BaseRequestHandler):
   def handle(self):
      ...
      indigoPlugin = indigo.activePlugin
      indigoPlugin.requestDeviceStatusNotification(int(deviceId))
     ...

If I've mucked something up in trying to be concise, feel free to download the Domotics Pad Mobile Client plugin and look at the full code.

Adam

Posted on
Thu Oct 05, 2017 9:14 pm
DaveL17 offline
User avatar
Posts: 6751
Joined: Aug 20, 2013
Location: Chicago, IL, USA

Re: how to call a method in the plugin class

No Adam, you got it right.

Code: Select all
        plugin = indigo.activePlugin
        plugin.test('foo')

will pass the text 'foo' to the method test(self, text) within the main plugin class.

I just tested it. :)

I came here to drink milk and kick ass....and I've just finished my milk.

[My Plugins] - [My Forums]

Posted on
Thu Oct 05, 2017 9:16 pm
kw123 offline
User avatar
Posts: 8360
Joined: May 12, 2013
Location: Dallas, TX

Re: how to call a method in the plugin class

ok that works. so help me understand:

indigo.activePlugin gets the instance for the call to test(response) (in my case.)


Karl

Posted on
Thu Oct 05, 2017 9:32 pm
RogueProeliator offline
User avatar
Posts: 2501
Joined: Nov 13, 2012
Location: Baton Rouge, LA

Re: how to call a method in the plugin class

indigo.activePlugin gets the instance for the call to test(response) (in my case.)

Yes, this was a suggestion that I got from Matt a while back for getting a reference to the current plugin (current being current within that process, I assume... probably a null reference outside of the plugin host).

Posted on
Thu Oct 05, 2017 11:19 pm
kw123 offline
User avatar
Posts: 8360
Joined: May 12, 2013
Location: Dallas, TX

Re: how to call a method in the plugin class

this is cool ... actually already works.

Now some error management and logging and testing ..

that was FAST

thanks

Karl

Posted on
Mon Oct 09, 2017 10:13 am
kw123 offline
User avatar
Posts: 8360
Joined: May 12, 2013
Location: Dallas, TX

Re: how to call a method in the plugin class

Think this is for Matt/ Jay/ RogueProeliator

I believe there is an opportunity to improve how indigo shuts down the plugins:

Asume:
A tcp/ip listener stack is running in its own class and calls the plugin methods ( indigo.activePlugin.someMethod() ) every time when receiving data i.e. to update dev/states etc ( that works nicely)

Then when indigo is starting the shutdown process for the plugin:

It looks to me that the access to the plugin methods are stopped a little bit too early: the tcp/ip listener stack is still receiving data and tries to call the plugin methods , but they are not reachable, the console then shows "HandlerError -- all command handlers are disabled for that plugin" -- many times

So it would be nice if the methods are still available until the main thread (runConcurrentThread ..) is finished.

When the plugin stops internally (just exit the "while True" loop in runConcurrentThread) and the tcp/ip stack does a socket.close() before ending "runConcurrentThread" everything shuts down nicely
It also shuts down nicely when there is no data coming into tcp/ip socket = the tcp/ip stack is NOT calling any indigo.activePlugin methods.

At least that is my simplistic view of the world.

Karl

Posted on
Mon Oct 09, 2017 11:48 am
matt (support) offline
Site Admin
User avatar
Posts: 21416
Joined: Jan 27, 2003
Location: Texas

Re: how to call a method in the plugin class

I think something slightly different is occurring. Can you copy/paste the Event Log showing the complete shutdown sequence in the case where the error occurs?

Image

Posted on
Mon Oct 09, 2017 2:31 pm
kw123 offline
User avatar
Posts: 8360
Joined: May 12, 2013
Location: Dallas, TX

Re: how to call a method in the plugin class

Code: Select all
         if self.indigoInputPORT > 0 and self.IndigoOrSocket == "socket":
            self.currentlyBooting   = time.time() + 40
            self.startTcpipListening()
            self.currentlyBooting   = time.time() + 20
            if self.socketServer is not None: self.stackReady = True


#########
        else:
            indigo.variables.subscribeToChanges()
            self.currentlyBooting   = time.time() + 20
            self.stackReady         = True

        if self.quitNow =="":
            if self.logFileActive:
                indigo.server.log(" .. initalized, log info in : "+self.logFile)
                self.ML.myLog("all"," .. initalized, starting loop" )
            else:   
                indigo.server.log(" .. initalized, starting loop ")
        ########   ------- here the loop starts    --------------
        #self.ML.myLog("special","memory used: "+str(resource.getrusage(resource.RUSAGE_SELF).ru_maxrss / (1024.*1024.))[:6]+"[MB] BeginningOfLoop   ")
        while self.quitNow == "":
                self.countLoop += 1
                self.sleep(5.)

                if self.countLoop > 5:
                    anyChange= self.periodCheck()
                if self.statusChanged ==1:  self.setGroupStatus()
                if self.statusChanged ==2:  self.setGroupStatus(init=True)

                if self.enableFING == "1":
                    if self.updateFING("loop ") == "break": break
                #if self.countLoop%700 ==0: # once an hour
                    #self.ML.myLog("special","memory used: "+str(resource.getrusage(resource.RUSAGE_SELF).ru_maxrss / (1024.*1024.))[:6]+"[MB] @LoopSnapshot  ")
        self.messageON = False
       
        try: 
           if self.socketServer is not None: 
                self.socketServer.shutdown()
        except:  pass

        try:
            if self.quitNow != "":
                indigo.server.log( u" stopping plugin due to:  ::::: " + self.quitNow + " :::::")
                serverPlugin = indigo.server.getPlugin(self.pluginId)
                serverPlugin.restart(waitUntilDone=False)
        except: pass

        return

#### this starts the listener
    def startTcpipListening(self):
            TCPserverHandle=""
            self.ML.myLog("socket",u"starting tcpip socket listener, for RPI data, might take some time")
            tcpStart = time.time() 
            lsofCMD ="/usr/sbin/lsof -i tcp:"+str(self.indigoInputPORT)
            for ii in range(40):  #  gives port busy for ~ 20 secs if restart, new start it is fine, error message continues even if it works -- indicator =ok: if lsof gives port number 
                try:    self.socketServer = ThreadedTCPServer((self.myIpNumber,self.indigoInputPORT), ThreadedTCPRequestHandler)
                except  Exception, e:
                    self.ML.myLog("socket",u"in Line '%s' :'%s'" % (sys.exc_traceback.tb_lineno, e)+ " try:"+ str(ii)+"  time elapsed:"+ str(time.time()-tcpStart) )
                try:
                    ret = subprocess.Popen(lsofCMD, shell=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE).communicate()
                    if len(ret[0]) >0: #  if lsof gives port number it works..
                        self.ML.myLog("socket",lsofCMD+"\n"+ ret[0].strip("\n"))
                        TCPserverHandle = threading.Thread(target=self.socketServer.serve_forever)
                        TCPserverHandle.daemon =True # don't hang on exit
                        TCPserverHandle.start()
                        break
                except  Exception, e:
                    indigo.server.log(u"in Line '%s' has error='%s'" % (sys.exc_traceback.tb_lineno, e))
                       
                if ii <=1: tcpWaitTime = 5
                else:      tcpWaitTime = 1
                self.sleep(tcpWaitTime)
            try:   
                self.ML.myLog("socket",'tcpip socket listener running; thread:#'+ TCPserverHandle.getName() )#  + " try:"+ str(ii)+"  time elapsed:"+ str(time.time()-tcpStart) )
                self.stackReady = True
            except: self.quitNow=" tcpip stack did not load, restart"
            return

##################
##################       
class ThreadedTCPRequestHandler(SocketServer.BaseRequestHandler):

    def handle(self):
        try:
            data0 =""
            tStart=time.time()

            if  not indigo.activePlugin.ipNumberOK(self.client_address[0]) :
                indigo.activePlugin.ML.myLog("socket","TCPIP socket data receiving from "+ unicode(self.client_address) +" not in accepted ip number list"  )
                indigo.activePlugin.handlesockErrorreporting(self.client_address[0],0,"unknown","errIP" )
                return
           
            while True:
                buffer = self.request.recv(1024)#  max observed is ~ 2200 bytes
                data0 += buffer
                if not buffer or len(buffer) ==0 or len(buffer) < 1024:
                    break
                if time.time() - tStart > 2: break
                if  len(data0) > 13000:       return
           
            try:
                ## look for length tag dataS =split data
                dataS = data0.split("x-6-a")
                if len(dataS) !=3: # tag not found
                    indigo.activePlugin.ML.myLog("socket","TCPIP socket  x-6-a  tag not found: "+data0[0:50] +"  ..  "+data0[-10:])
                    try: self.request.send("error-tag missing")
                    except: pass
                    indigo.activePlugin.handlesockReporting(self.client_address[0],expLength,name,"errTag" )
                    return
                expLength = int(dataS[0])
                name      = dataS[1]
                lenData   = len(dataS[2])
                if expLength != lenData: # expected # of bytes not received
                    indigo.activePlugin.ML.myLog("socket","TCPIP socket length of data wrong, exp:"+dataS[0]+";  actual:"+ str(lenData)+";  name:"+name+"; "+dataS[2][0:50] +"    ..    "+data0[-10:])
                    try: self.request.send("error-lenDatawrong-"+str(lenData) )
                    except: pass
                    indigo.activePlugin.handlesockReporting(self.client_address[0],expLength,name,"errLength" )
                    return
                   
                dataJ = json.loads(dataS[2])  # dataJ = json object for data
                try:    self.request.send("ok-"+str(lenData) )
                except: pass
            except  Exception, e:
                indigo.activePlugin.ML.myLog("socket",u"TCPIP socket  in Line '%s' has error='%s'" % (sys.exc_traceback.tb_lineno, e))
                indigo.activePlugin.ML.myLog("socket","TCPIP socket  bad data received; len of data:"+str(len(data0))+"  "+ unicode(threading.currentThread())+"    time used:"+str(time.time()-tStart) )
                indigo.activePlugin.ML.myLog("socket",data0[0:50]+"   ..   "+data0[-10:] )
                try: self.request.send("error-unknown-"+str(lenData) )
                except: pass
                indigo.activePlugin.handlesockReporting(self.client_address[0],expLength,name,"errUnknown" )
                return
           
            if name.find(u"pi_IN_") != 0 :
                indigo.activePlugin.ML.myLog("socket","TCPIP socket  listener bad name "+name )
                indigo.activePlugin.handlesockReporting(self.client_address[0],expLength,name,"badName" )
                return

            indigo.activePlugin.addToDataQueue( name, dataJ,dataS[2] )
            indigo.activePlugin.handlesockReporting(self.client_address[0],expLength,name,"ok" )

        except  Exception, e:
            indigo.activePlugin.ML.myLog("socket",u"in Line '%s' has error='%s'" % (sys.exc_traceback.tb_lineno, e))
            indigo.activePlugin.ML.myLog("socket","TCPIP socket "+ data0[0:50] )
            indigo.activePlugin.handlesockReporting(self.client_address[0],name,"errJson" )
        return
##################
class ThreadedTCPServer(SocketServer.ThreadingMixIn, SocketServer.TCPServer):
    pass
###################  TCPIP listen section  receive data from RPI via socket comm  end            #################



other error messages in indigo log file .. only in console and sometimes indigo plugin has a crash (will send in email)
THIS: self.messageON = False
suppresses any logging in the plugin


Karl

Posted on
Mon Oct 09, 2017 4:01 pm
matt (support) offline
Site Admin
User avatar
Posts: 21416
Joined: Jan 27, 2003
Location: Texas

Re: how to call a method in the plugin class

I want to see the Event Log window results (from Indigo) when the plugin is shutting down and showing errors.

Image

Posted on
Mon Oct 09, 2017 4:28 pm
kw123 offline
User avatar
Posts: 8360
Joined: May 12, 2013
Location: Dallas, TX

Re: how to call a method in the plugin class

when I switch login on: i.e. do not suppress login I get

some of these - between 0 and 3 in indigo log
17:15:37 -in Line '756' has error='UnexpectedNullError'
17:26:29 -in Line '9567' has error='UnexpectedNullError -- CClientMgr not created'
17:26:29 -in Line '756' has error='UnexpectedNullError'
17:26:29 -in Line '8062' has error='UnexpectedNullError -- CClientMgr not created'

using:
Code: Select all
 except  Exception, e:
   self.toLog(u"in Line '%s' has error='%s'" % (sys.exc_traceback.tb_lineno, e))

and between 0 and 15 in console of these;" HandlerError -- all command handlers are disabled for that plugin"

where line 756 can be something like this:
indigo.variable.create(varName, self.iBeaconFolderNameVariables)
or anything with get or update indigo. xxx in the plugin itself.

Karl

ps
I have suppressed logging with:

Code: Select all
if  unicode(e).find("UnexpectedNullError") ==-1: and  self.messageON:
     self.toLog(...)

Who is online

Users browsing this forum: No registered users and 4 guests