Nth device in an device.iter? [Solved!]

Posted on
Thu Dec 24, 2020 11:25 pm
whmoorejr offline
User avatar
Posts: 522
Joined: Jan 15, 2013
Location: Houston, TX

Nth device in an device.iter? [Solved!]

So, I did figure out how to run through all the devices in a plugin.... what if there are 10 devices and I want the 6th one?

This is the half-ass script I have so far....
Code: Select all
thisRecord = "6"
thisRecordInt = int(thisRecord)
allDevices = indigo.devices.iter(filter="com.whmoorejr.my-people")

if thisDevice = item thisRecordInt of allDevices:
   friendlyName = thisDevice.states["friendlyName"]
   indigo.server.log("This is the device for: " + friendlyName)


It's the 4th line that I know is not right, but I'm not sure what it is supposed to be. I know the 1st and 2nd line could be one line... I'm switching to a VariableID once sorted out.
Last edited by whmoorejr on Fri Dec 25, 2020 6:31 pm, edited 1 time in total.

Bill
My Plugin: My People

Posted on
Fri Dec 25, 2020 2:18 am
howartp offline
Posts: 4267
Joined: Jan 09, 2014
Location: West Yorkshire, UK

Re: Nth device in an device.iter?

What’s the purpose of the script?

You won’t normally index Indigo devices by their order. I’m not even sure if indigo devices returns a fixed sort order each time, it might.

You’d be best using the dev ID to identify a device.


Sent from my iPhone using Tapatalk Pro

Posted on
Fri Dec 25, 2020 10:55 am
whmoorejr offline
User avatar
Posts: 522
Joined: Jan 15, 2013
Location: Houston, TX

Re: Nth device in an device.iter?

howartp wrote:
What’s the purpose of the script?

This is another part of it....
Code: Select all
nextRecord = thisRecordInt + 1 # to go forward
prevRecord = thisRecordInt - 1 # to go backward

if nextRecord > totalRecords:
   nextRecord = 0

elif prevRecord <= 0
   prevRecord = totalRecords


My thought is a control page implementation.... a script could go through the devices of a plugin and when that action (script) is run, the device states are saved to a set of variables. A "go forward" action would move to the next device, overwrite the variables. A "go backward" action would go to the previous device. On a control page, instead of showing device states, you would use the temp variables and one page could dynamically move through all the devices.

For my current my people plugin, a control page could flip through all the different "people" devices... without having to create a page for each device.

Similarly for my next project, a room plugin, you could rotate through rooms on one page. <-- I'm waiting for more feedback on the my people plugin before I make something else.

If my plugin skills improve, ideally I would find a way to do this from within the plugin.... like have the plugin create a template device and when you do a "Next" or "Previous" action, it would populate the template device with actual devices created by the user.

On a side-note, I wrote a script that will pull a PIN number from a variable and compare it against all the People Devices in my plugin. Might not sound like much, but if I write a script that works... that's huge!

Bill
My Plugin: My People

Posted on
Fri Dec 25, 2020 6:31 pm
whmoorejr offline
User avatar
Posts: 522
Joined: Jan 15, 2013
Location: Houston, TX

Re: Nth device in an device.iter?

This worked. As you increase or decrease the variable (+1 / -1) the variables with state values change and it scrolls through the devices. If you get to the last item in the list, it corrects the variable to be back within range.
Code: Select all
recordRequestedString = indigo.variables[1728724637].value # "recordRequest"
recordRequested = int(recordRequestedString)

personCount = indigo.devices.len(filter="com.whmoorejr.my-people")-1

### Verify Requested Record is within range, modify variable if necessary

if recordRequested > personCount:
   recordRequested = 0
   indigo.variable.updateValue(1728724637, value=str(recordRequested))
   
elif recordRequested < 0:
   recordRequested = personCount
   indigo.variable.updateValue(1728724637, value=str(recordRequested))
   
personList = []
iterator=indigo.devices.iter(filter="com.whmoorejr.my-people")
for dev in iterator:
   personList.append(dev.name)
   
nowShowing = personList[recordRequested]

for dev in indigo.devices.iter(filter="com.whmoorejr.my-people"):
   if dev.name == nowShowing:
      indigo.variable.updateValue(1633370587, value=dev.states["firstName"])
      indigo.variable.updateValue(773860353, value=dev.states["lastName"])
      indigo.variable.updateValue(472428140, value=dev.states["friendlyName"])
      

Bill
My Plugin: My People

Posted on
Sat Dec 26, 2020 2:56 pm
matt (support) offline
Site Admin
User avatar
Posts: 20568
Joined: Jan 27, 2003
Location: Texas

Re: Nth device in an device.iter? [Solved!]

Novel idea to get around some of the Control Page dynamic limitations. 8)

A slightly optimized (but untested) version of your script that avoids needing 2 device iter() loops, and breaks out of the loop once it hits the recordRequested-th iteration.

Code: Select all
recordRequestedString = indigo.variables[1728724637].value # "recordRequest"
recordRequested = int(recordRequestedString)

personCount = indigo.devices.len(filter="com.whmoorejr.my-people")-1

### Verify Requested Record is within range, modify variable if necessary

if recordRequested > personCount:
   recordRequested = 0
   indigo.variable.updateValue(1728724637, value=str(recordRequested))
elif recordRequested < 0:
   recordRequested = personCount
   indigo.variable.updateValue(1728724637, value=str(recordRequested))

recordCount = 0
for dev in indigo.devices.iter(filter="com.whmoorejr.my-people"):
   if recordCount == recordRequested:
      indigo.variable.updateValue(1633370587, value=dev.states["firstName"])
      indigo.variable.updateValue(773860353, value=dev.states["lastName"])
      indigo.variable.updateValue(472428140, value=dev.states["friendlyName"])
      break
   recordCount += 1

Image

Posted on
Sat Dec 26, 2020 4:39 pm
whmoorejr offline
User avatar
Posts: 522
Joined: Jan 15, 2013
Location: Houston, TX

Re: Nth device in an device.iter? [Solved!]

matt (support) wrote:
A slightly optimized (but untested) version of your script that avoids needing 2 device iter() loops, and breaks out of the loop once it hits the recordRequested-th iteration.

Tested and it worked. I tried a bunch of stuff first, and eventually figured I need to build a list within brackets [] which was my first iter loop. I wish I had a saved version of every script I ran previously to see if anything was close. I tried stuff like, if dev [:3] and all kinds of wonky stuff.

As far as incorporating it into a plugin... my though is to follow the custom device example and create a "Now Showing" device. I was thinking that the firmware prop would be a good place to store the integer. So it would create the device as set the firmware to "0". Then an "Go Forward" or "Go Backward" action would +1 or -1 to that and then use the python scrip to save the state values of the recordRequeted device to the "Now Showing" device......

But I'm already stuck on creating the device....
Code: Select all
   def startup(self):
      self.debugLog(u"startup called")
      

        #### Create Now Showing Device for Control Pages ####
      if "Now Showing" in indigo.devices:
         self.aPersonDev = indigo.devices["Now Showing"]
      else:
         indigo.server.log(u"Creating Now Showing Device for Control Pages")
         self.aPersonDev = indigo.device.create(indigo.kProtocol.Plugin, "Now Showing", "An template for control pages, do not delete" ,  deviceTypeID="aPerson")
   #      self.aPersonDev.updateStateImageOnServer(indigo.KStateImageSel.SensorTripped)
   #      self.aPersonDev.updateStateOnServer(key="homeState", value="Unsure")
   #      newProps["Firmware"] = 0 # This will be used as the record locatator digit.
         
   def shutdown(self):
      self.debugLog(u"shutdown called")
Which results in:
Started plugin "My People 1.2.7"
My People Debug startup called
My People Creating Now Showing Device for Control Pages
My People Error Error in plugin execution startup:

Traceback (most recent call last):
File "plugin.py", line 30, in startup
ArgumentError: Python argument types in
DeviceCmds.create(DeviceCmds, kProtocol, str, str)
did not match C++ signature:
create(CDeviceBase::_DeviceCmds {lvalue}, TDevProto protocol, CCString name='', CCString description='', boost::python::api::object folder=None, boost::python::api::object address=None, CCString deviceTypeId='', CCString pluginId='', boost::python::api::object props=None, bool configured=True, boost::python::api::object groupWithDevice=None)

Bill
My Plugin: My People

Posted on
Sun Dec 27, 2020 11:21 am
matt (support) offline
Site Admin
User avatar
Posts: 20568
Joined: Jan 27, 2003
Location: Texas

Re: Nth device in an device.iter? [Solved!]

In your args to the create() method use deviceTypeId instead of deviceTypeID. 8)

Image

Posted on
Sun Dec 27, 2020 6:02 pm
whmoorejr offline
User avatar
Posts: 522
Joined: Jan 15, 2013
Location: Houston, TX

Re: Nth device in an device.iter? [Solved!]

matt (support) wrote:
In your args to the create() method use deviceTypeId instead of deviceTypeID. 8)


Thank you again Matt.

Bill
My Plugin: My People

Posted on
Mon Dec 28, 2020 12:14 am
whmoorejr offline
User avatar
Posts: 522
Joined: Jan 15, 2013
Location: Houston, TX

Re: Nth device in an device.iter? [Solved!]

Thank you all for your help. I just released version 1.2.6 of my plugin https://forums.indigodomo.com/viewforum.php?f=351which added a couple cool things....
Now on startup, the plugin creates a "Now Showing" device that can be used on a control page to display all of your "People"
There are four new actions...
    Now Showing First
    Now Showing Previous
    Now Showing Next
    Now Showing Last
Those actions overwrite the "Now Showing" device with the device states from your other "People" devices.

Bill
My Plugin: My People

Posted on
Mon Dec 28, 2020 10:53 am
jay (support) offline
Site Admin
User avatar
Posts: 16815
Joined: Mar 19, 2008
Location: Austin, Texas

Re: Nth device in an device.iter? [Solved!]

If you're storing the index of the person device in the indigo.devices() filtered list, how do you guarantee that index #5 is always going to be the same person? Shouldn't you be using device IDs instead since they never change?

Jay (Indigo Support)
Twitter | Facebook | LinkedIn

Posted on
Mon Dec 28, 2020 12:10 pm
whmoorejr offline
User avatar
Posts: 522
Joined: Jan 15, 2013
Location: Houston, TX

Re: Nth device in an device.iter? [Solved!]

jay (support) wrote:
If you're storing the index of the person device in the indigo.devices() filtered list, how do you guarantee that index #5 is always going to be the same person? Shouldn't you be using device IDs instead since they never change?


I couldn't figure out a good way to store the Record Locator number with the "Now Showing" device without creating a separate state.... which would show up on all the other devices (which I didn't want)....
So, I ended up storing the variable in the PluginConfig.xml as a pluginpref. (which seems to work)

It seems that the devices in the list always end up in the order that they were created, so if that's correct, then they should stay in the same order? Although it would be cool to be able to sort the list in a user defined way.... alphabetical ascending, descending, etc. But adding that level of implementation is way beyond my skill level.... I'm actually surprised it works as well as it does. With the double iter I had originally, it built the list using device name.... Should I go back to that and add the "dev.name is not"?
Code: Select all
personList = []
iterator=indigo.devices.iter(filter="com.whmoorejr.my-people")
for dev in iterator:
   if  dev.name is not "Now Showing":
        personList.append(dev.name)
   
nowShowing = personList[recordRequested]

I think that would put the list in alphabetical order and exclude the "Now Showing" device from the the list? When scrolling up or down through the devices, when you get to the "Now Showing" device, on a control page it looks like a duplicate record.... if your control page is set to show the states of "Now Showing" which is device #9 in your list and you are looking at device #8 "Bob", when you select Next advance to device 9 (Now Showing), the action will overwrite device 9 with device 9 and it's Bob again.

(FYI: The code I posted above looks different now that's it's in a plugin.... no external variables, etc.)

Bill
My Plugin: My People

Posted on
Mon Dec 28, 2020 2:25 pm
jay (support) offline
Site Admin
User avatar
Posts: 16815
Joined: Mar 19, 2008
Location: Austin, Texas

Re: Nth device in an device.iter? [Solved!]

whmoorejr wrote:
It seems that the devices in the list always end up in the order that they were created, so if that's correct, then they should stay in the same order? )


What if you delete one? Say, #2 out of 5 total. Now #3 becomes #2, #4 becomes #3, etc.

whmoorejr wrote:
Although it would be cool to be able to sort the list in a user defined way.... alphabetical ascending, descending, etc. But adding that level of implementation is way beyond my skill level.... I'm actually surprised it works as well as it does. With the double iter I had originally, it built the list using device name.... Should I go back to that and add the "dev.name is not"?
Code: Select all
personList = []
iterator=indigo.devices.iter(filter="com.whmoorejr.my-people")
for dev in iterator:
   if  dev.name is not "Now Showing":
        personList.append(dev.name)
   
nowShowing = personList[recordRequested]

I think that would put the list in alphabetical order and exclude the "Now Showing" device from the the list? When scrolling up or down through the devices, when you get to the "Now Showing" device, on a control page it looks like a duplicate record.... if your control page is set to show the states of "Now Showing" which is device #9 in your list and you are looking at device #8 "Bob", when you select Next advance to device 9 (Now Showing), the action will overwrite device 9 with device 9 and it's Bob again.

(FYI: The code I posted above looks different now that's it's in a plugin.... no external variables, etc.)


For your use case, it's probably fine. If I were doing it I think I'd do something like this:

  1. implement the deviceStartComm method which will get called every time one of your person devices starts up (either at plugin start or when one is created). Inside that method I'd add it to a list maintained in the plugin (which you could then sort on any of the device states).
  2. implement the deviceStopComm method and remove the device from the list being maintained above
  3. implement actions for next/previous which would cycle through the list

If you want to learn more about writing plugins, that might be a useful exercise because you'll definitely want to be familiar with those two methods. And it'll give you some experience with arrays and sorting, not to mention implementing actions. Just a thought if you're interested in expanding your understanding of plugin development. You've already come a long way though, so congrats.

Jay (Indigo Support)
Twitter | Facebook | LinkedIn

Posted on
Mon Dec 28, 2020 2:57 pm
whmoorejr offline
User avatar
Posts: 522
Joined: Jan 15, 2013
Location: Houston, TX

Re: Nth device in an device.iter? [Solved!]

jay (support) wrote:
What if you delete one? Say, #2 out of 5 total. Now #3 becomes #2, #4 becomes #3, etc.
I don't think that's a big problem if your just scrolling through a small list (10 or so... good for a household).... I think it would need to be more specific if this were to be used in a business setting with tracking 30 or 100 users. That's when you would want sorting abilities, maybe a name lookup action to go to a specific record (device), etc.

jay (support) wrote:
  1. implement the deviceStartComm method which will get called every time one of your person devices starts up (either at plugin start or when one is created). Inside that method I'd add it to a list maintained in the plugin (which you could then sort on any of the device states).
  2. implement the deviceStopComm method and remove the device from the list being maintained above
  3. implement actions for next/previous which would cycle through the list
that and I need to get my head wrapped around the run concurrent stuff. I'm playing with another plugin where I might need that too, but I'm not sure yet. Hopefully when the kids get a little older, I'll have time to go to the local junior college and take a python class or something just to give me a solid base of understanding.

In the meantime, I really do appreciate everyone's patience and understanding.

Bill
My Plugin: My People

Page 1 of 1

Who is online

Users browsing this forum: No registered users and 9 guests