Page 1 of 2

How to use 'refreshCallbackMethod' in Devices.xml

PostPosted: Sun Jul 05, 2020 9:55 am
by hannt
Trying to implement 'refreshCallbackMethod' for a custom device plugin. I read the post how to use : valuesDict['refreshCallbackMethod'] documenting how to use it, but it isn't working for me. I've implemented the callback method similar to the sample provided, which also writes a log entry so I know when it is called. However, I'm having trouble defining it in the config UI XML. I though it would look something like this:

Code: Select all
<ConfigUI refreshCallbackMethod='refreshDeviceConfigUi'>
    ...
</ConfigUI>
I also tried:

Code: Select all
<ConfigUI>
    <refreshCallbackMethod>refreshDeviceConfigUi</refreshCallbackMethod>
    ...
</ConfigUI>
What is the correct way to define this in Devices.xml?

Re: How to use 'refreshCallbackMethod' in Devices.xml

PostPosted: Tue Jul 07, 2020 5:25 pm
by matt (support)
It wasn't very clear on that other forum thread so here is an example. Although it might be possible to do via XML, it is easier to just handle by overriding one of these methods (use the first one unless you are using the device factory UI option): And note you can conditionalize it based on the passed in device typeId if you need.

Code: Select all
   def getDeviceConfigUiValues(self, pluginProps, typeId, devId):
      valuesDict = pluginProps
      errorMsgDict = indigo.Dict()
      valuesDict['refreshCallbackMethod'] = 'nameOfYourRfreshMethod'
      return (valuesDict, errorMsgDict)

   def getDeviceFactoryUiValues(self, devIdList):
      valuesDict = indigo.Dict()
      valuesDict['refreshCallbackMethod'] = 'nameOfYourRfreshMethod'
      errorMsgDict = indigo.Dict()
      return (valuesDict, errorMsgDict)

Re: How to use 'refreshCallbackMethod' in Devices.xml

PostPosted: Wed Jul 08, 2020 6:50 pm
by hannt
matt (support) wrote:
It wasn't very clear on that other forum thread so here is an example. Although it might be possible to do via XML, it is easier to just handle by overriding one of these methods (use the first one unless you are using the device factory UI option): And note you can conditionalize it based on the passed in device typeId if you need.


Thanks, Matt! This is very useful information - I didn't know about 'getDeviceConfigUiValues'. For what I'm doing, that should work even without 'refreshCallbackMethod'.

Re: How to use 'refreshCallbackMethod' in Devices.xml

PostPosted: Thu Jul 09, 2020 6:57 am
by hannt
As a followup, I was able to get t refreshCallbackMethod working in Devices.xml without using getDeviceConfigUiValues. Not sure if 'textfield' is the correct type to define this, but it seems to work.

Code: Select all
<ConfigUI>
    <Field id="refreshCallbackMethod" type="textfield" hidden="true" defaultValue="refreshDeviceConfigUi"/>
    ....
</ConfigUI>

Re: How to use 'refreshCallbackMethod' in Devices.xml

PostPosted: Thu Jul 09, 2020 3:09 pm
by matt (support)
Yep, that (using textfield) look correct for the XML definition.

Re: How to use 'refreshCallbackMethod' in Devices.xml

PostPosted: Sun Jan 24, 2021 11:43 pm
by kw123
I would like to use this feature, Q:

I am using:
in .. .
Code: Select all
def getPrefsConfigUiValues(self):
   valuesDict, errDict =  super(Plugin, self).getPrefsConfigUiValues()
   valuesDict[u"refreshCallbackMethod"]   = "setabc"
   return valuesDict

in
Code: Select all
def setabc(self,valuesDict=None):

valuesDict is None, never anything in there,

is this correct?
Code: Select all
def setabc(self, valuesDict=None):
   valuesDict = indigo.Dict()
   valuesDict ["myParamter"] = "abc"
   return valuesDict


Karl

Re: How to use 'refreshCallbackMethod' in Devices.xml

PostPosted: Mon Jan 25, 2021 11:30 am
by matt (support)
I just tried an example and it passed a populated valuesDict. I think the problem is might be in your getPrefsConfigUiValues() implementation. Try this:

Code: Select all
def getPrefsConfigUiValues(self):
   (valuesDict, errorsDict) = super(Plugin, self).getPrefsConfigUiValues()
   valuesDict[u"refreshCallbackMethod"] = "setabc"
   return (valuesDict, errorsDict)


FYI, here is my complete example which worked:

Code: Select all
   def getPrefsConfigUiValues(self):
      (valuesDict, errorsDict) = super(Plugin, self).getPrefsConfigUiValues()
      valuesDict[u"refreshCallbackMethod"] = "prefsRefreshCallback"
      return (valuesDict, errorsDict)

   def prefsRefreshCallback(self, valuesDict):
      indigo.server.log(u"prefsRefreshCallback called")
      indigo.server.log(u"valuesDict: {}".format(valuesDict))
      return valuesDict

Re: How to use 'refreshCallbackMethod' in Devices.xml

PostPosted: Tue Jan 26, 2021 12:11 pm
by kw123
my mistake ..

I copied the def from
Code: Select all
   def filterWiFiDevice(self, filter="", valuesDict=None):
and valuesDict is the 2. argument, should be the first
so
Code: Select all
def theCallbackmethod(self,valuesDict=None):
works fine

Code: Select all
def theCallbackmethod(self, filter="", valuesDict=None):
does not work valuesDict is always None,
The valuesDict data is in "filters"

.. and I thought that using valuesDict=xxx would always work no matter where in the sequence is it in def xx(....):
So I guess valuesDict is not an optional parameter and the first one listed in def() will get the data

thanks for being patient

Karl

Re: How to use 'refreshCallbackMethod' in Devices.xml

PostPosted: Tue Jan 26, 2021 12:24 pm
by DaveL17
kw123 wrote:
.. and I thought that using valuesDict=xxx would always work no matter where in the sequence is it in def xx(....):

That's true if the sender is using the attribute names explicitly.

This works:
Code: Select all
#! /usr/bin/env python
# -*- coding: utf-8 -*-

def foo(a=1, b=None):
   print(u"{} {}".format(a, b))
   
foo(b=2, a=3)

>>>3 2

Re: How to use 'refreshCallbackMethod' in Devices.xml

PostPosted: Tue Jan 26, 2021 12:25 pm
by matt (support)
kw123 wrote:
... and I thought that using valuesDict=xxx would always work no matter where in the sequence is it in def xx(....): So I guess valuesDict is not an optional parameter and the first one listed in def() will get the data

Yeah, all of the API callbacks Indigo makes into plugins are positional (not named) arguments, so the order matters for those.

Re: How to use 'refreshCallbackMethod' in Devices.xml

PostPosted: Tue Jan 26, 2021 10:08 pm
by RogueProeliator
This works:
Code: Select all
def foo(a=1, b=None):
   print(u"{} {}".format(a, b))
   
foo(b=2, a=3)


And should be kicked back in code review by any competent engineering manager... :-)

Re: How to use 'refreshCallbackMethod' in Devices.xml

PostPosted: Wed Jan 27, 2021 6:36 am
by DaveL17
RogueProeliator wrote:
And should be kicked back in code review by any competent engineering manager... :-)

It must be so boring to have such a linear view of the universe. :D

Re: How to use 'refreshCallbackMethod' in Devices.xml

PostPosted: Wed Jan 27, 2021 9:48 pm
by RogueProeliator
It must be so boring to have such a linear view of the universe. :D

Yes, but it is very ordered! (See what I did there!?!? Sigh, I need more sleep.)

Re: How to use 'refreshCallbackMethod' in Devices.xml

PostPosted: Thu Jan 28, 2021 5:43 am
by DaveL17
If I said that I thought that was funny, I'd be line. :roll:

Re: How to use 'refreshCallbackMethod' in Devices.xml

PostPosted: Thu Feb 18, 2021 6:20 am
by DaveL17
kw123 wrote:
.. and I thought that using valuesDict=xxx would always work no matter where in the sequence is it in def xx(....):
So I guess valuesDict is not an optional parameter and the first one listed in def() will get the data

I've recently learned something else that seems tangentially relevant to this point.

Apparently, Python only evaluates the default method attributes once. I've seen warnings from my IDE about using something mutable as a method attribute:

Code: Select all
def foo(bar={}):
will work if you're careful, but it can be perilous.

Code: Select all
def foo(bar=[]):
   print(bar)
   bar.append('x')

foo()

foo()  # you might think you're getting an empty list here, but you're not.

>>> []
>>> ['x']