Starting out with Python

Posted on
Fri Apr 21, 2017 9:47 am
jay (support) offline
Site Admin
User avatar
Posts: 18220
Joined: Mar 19, 2008
Location: Austin, Texas

Re: Starting out with Python

Inspecting devices in a Scripting Shell is really going to help you here - it's much more interactive than trying to write stuff to the log. You can print a device in the shell and it will show you everything there is to know about a device.

For instance, once you have a shell window open (this is a WeatherSnoop device which is quite involved):

Code: Select all
>>> dev = indigo.devices[1234567890] # "KATT Agent in WeatherSnoop"
>>> print unicode(dev)
address : FatBook.local.:7999
batteryLevel : None
buttonGroupCount : 0
configured : True
description :
deviceTypeId : ws3station
displayStateId : temperature_F
displayStateImageSel : TemperatureSensor
displayStateValRaw : 88.0
displayStateValUi : 88.0 °F
enabled : True
energyAccumBaseTime : None
energyAccumTimeDelta : None
energyAccumTotal : None
energyCurLevel : None
errorState :
folderId : 1605027967
globalProps : MetaProps : (dict)
     com.perceptiveautomation.indigoplugin.weathersnoop : (dict)
          address : FatBook.local.:7999 (string)
          displayState : temperature_F (string)
          dynamicStates : (list)
               [SNIP for brevity]
          host : localhost (string)
          manual : false (bool)
          port : 8000 (string)
          siteName :  (string)
          wsAgent : http://FatBook.local.:7999/2DFAB35B-B074-4F7F-835A-B4EB2BEDAF6F.json (string)
          wsInstance : WeatherSnoop 3 - FatBook@FatBook.local.:7999 (string)
     emptyDict : (dict)
id : 1250026703
lastChanged : 2017-02-02 16:32:26
lastSuccessfulComm : 2017-02-02 16:32:26
model : WeatherSnoop 3 Agent
name : KATT Agent in WeatherSnoop
ownerProps : com.perceptiveautomation.indigoplugin.weathersnoop : (dict)
     address : FatBook.local.:7999 (string)
     displayState : temperature_F (string)
     dynamicStates : (list)
          [SNIP for brevity]
     host : localhost (string)
     manual : false (bool)
     port : 8000 (string)
     siteName :  (string)
     wsAgent : http://FatBook.local.:7999/2DFAB35B-B074-4F7F-835A-B4EB2BEDAF6F.json (string)
     wsInstance : WeatherSnoop 3 - FatBook@FatBook.local.:7999 (string)
pluginId : com.perceptiveautomation.indigoplugin.weathersnoop
pluginProps : emptyDict : (dict)
protocol : Plugin
remoteDisplay : True
states : States : (dict)
     agent : Weather Underground (string)
     agent.ui : Weather Underground (string)
     barometricTrend : Steady (string)
     barometricTrend.ui : Steady (string)
     dayRain_cm : -9999.00 (real)
     dayRain_cm.ui : -9999.0 cm (string)
     dayRain_in : -9999.00 (real)
     dayRain_in.ui : -9999.0 in (string)
     dayRain_km : -9999.00 (real)
     dayRain_km.ui : -9999.0 km (string)
     dayRain_mi : -9999.00 (real)
     dayRain_mi.ui : -9999.0 mi (string)
     dayRain_mm : -9999.00 (real)
     dayRain_mm.ui : -9999.0 mm (string)
     dewPoint_C : 22.20 (real)
     dewPoint_C.ui : 22.2 °C (string)
     dewPoint_F : 72.00 (real)
     dewPoint_F.ui : 72.0 °F (string)
     elevation : -9999 ft (string)
     elevation.ui : -9999 ft (string)
     heatIndex_C : 34.40 (real)
     heatIndex_C.ui : 34.4 °C (string)
     heatIndex_F : 94.00 (real)
     heatIndex_F.ui : 94.0 °F (string)
     humidity : 59 (integer)
     humidity.ui : 59% (string)
     latitude : 30.507950 (string)
     latitude.ui : 30.507950 (string)
     location : Somewhere else (string)
     location.ui : Somewhere else (string)
     longitude : -97.887871 (string)
     longitude.ui : -97.887871 (string)
     name : Station KOPEL (string)
     name.ui : Station KOPEL (string)
     rainOneHour_cm : 0.00 (real)
     rainOneHour_cm.ui : 0.0 cm (string)
     rainOneHour_in : 0.00 (real)
     rainOneHour_in.ui : 0.0 in (string)
     rainOneHour_km : 0.00 (real)
     rainOneHour_km.ui : 0.0 km (string)
     rainOneHour_mi : 0.00 (real)
     rainOneHour_mi.ui : 0.0 mi (string)
     rainOneHour_mm : 0.00 (real)
     rainOneHour_mm.ui : 0.0 mm (string)
     relativeBarometricPressure_cb : 102 (integer)
     relativeBarometricPressure_cb.ui : 102 cb (string)
     relativeBarometricPressure_inHg : 30.10 (real)
     relativeBarometricPressure_inHg.ui : 30.1 inHg (string)
     relativeBarometricPressure_mb : 1019 (integer)
     relativeBarometricPressure_mb.ui : 1019 mb (string)
     solarRadiation : 455 (integer)
     solarRadiation.ui : 455 wm2 (string)
     temperature_C : 31.10 (real)
     temperature_C.ui : 31.1 °C (string)
     temperature_F : 88.00 (real)
     temperature_F.ui : 88.0 °F (string)
     uri : /2DFAB35B-B074-4F7F-835A-B4EB2BEDAF6F.json (string)
     uri.ui : /2DFAB35B-B074-4F7F-835A-B4EB2BEDAF6F.json (string)
     uvIndex : 3.00 (real)
     uvIndex.ui : 3.0 (string)
     version : 3.1.7 (1116) (string)
     version.ui : 3.1.7 (1116) (string)
     visibility_cm : 1609337.10 (real)
     visibility_cm.ui : 1609337.1 cm (string)
     visibility_in : 633598.86 (real)
     visibility_in.ui : 633598.86 in (string)
     visibility_km : 16.10 (real)
     visibility_km.ui : 16.1 km (string)
     visibility_mi : 10.00 (real)
     visibility_mi.ui : 10.0 mi (string)
     visibility_mm : 16093411.10 (real)
     visibility_mm.ui : 16093411.1 mm (string)
     weather : Mostly Cloudy (string)
     weather.ui : Mostly Cloudy (string)
     windChill_C : 6.70 (real)
     windChill_C.ui : 6.7 °C (string)
     windChill_F : 44.00 (real)
     windChill_F.ui : 44.0 °F (string)
     windDirection : 80 (integer)
     windDirection.ui : 80° (E) (string)
     windGust_kn : 0.00 (real)
     windGust_kn.ui : 0.0 kn (string)
     windGust_kph : 0.00 (real)
     windGust_kph.ui : 0.0 kph (string)
     windGust_mph : 0.00 (real)
     windGust_mph.ui : 0.0 mph (string)
     windGust_mps : 0.00 (real)
     windGust_mps.ui : 0.0 mps (string)
     windSpeed_kn : 3.50 (real)
     windSpeed_kn.ui : 3.5 kn (string)
     windSpeed_kph : 6.40 (real)
     windSpeed_kph.ui : 6.4 kph (string)
     windSpeed_mph : 4.00 (real)
     windSpeed_mph.ui : 4.0 mph (string)
     windSpeed_mps : 1.80 (real)
     windSpeed_mps.ui : 1.8 mps (string)
subModel :
supportsAllLightsOnOff : False
supportsAllOff : False
supportsStatusRequest : False
version : None
>>>

Jay (Indigo Support)
Twitter | Facebook | LinkedIn

Posted on
Fri Apr 21, 2017 10:11 am
BlaineM offline
Posts: 36
Joined: Jan 13, 2012

Re: Starting out with Python

jay (support) wrote:
Inspecting devices in a Scripting Shell is really going to help you here - it's much more interactive than trying to write stuff to the log. You can print a device in the shell and it will show you everything there is to know about a device.

Indeed, much easier. Thank you.

--Blaine

Posted on
Sun Aug 05, 2018 3:36 pm
hamw offline
Posts: 1212
Joined: Mar 31, 2008

Re: Starting out with Python

Could someone help me convert this snippet to Python? I use it to check the state of my garage door autoclose to make sure it did in fact close. It checks to see if the garage door is open (I/O Linc binary outputs are true) and the variable GarageAutoClose is also true, and if both true then activates the I/O linc named "aGarageDoor1." Note that I set GarageAutoClose true or false to prevent the autoclose from happening if working in the garage, for instance.
Code: Select all
   tell application "IndigoServer"
      if ((value of variable "Garage1" is "true") and (value of variable "GarageAutoClose" is "true")) then
         set binary outputs of device "aGarage Door 1" to {true}
      end if
   end tell
   
   delay 60
   
   tell application "IndigoServer"
      if ((value of variable "Garage1" is "true") and (value of variable "GarageAutoClose" is "true")) then
         set binary outputs of device "aGarage Door 1" to {true}
      end if
   end tell


I think it would begin with something like this, but don't know how to assemble the state query and then the if/then statement:

Code: Select all
GarageDoor1 = indigo.devices["GarageDoor1"]
if hasattr(iolinc, 'onState'):
   isOn = iolinc.onState   

GarageAutocloseVar = indigo.variables[123]


then what??

Thanks!

Posted on
Mon Aug 06, 2018 4:41 am
DaveL17 offline
User avatar
Posts: 6755
Joined: Aug 20, 2013
Location: Chicago, IL, USA

Re: Starting out with Python

I think this is a literal conversion of your AppleScript:

Code: Select all
from time import sleep


Garage1 = indigo.variables['Garage1'].value  # It's recommended to use Indigo ID numbers instead of names, but names will work.
GarageAutoClose = indigo.variables['GarageAutoClose'].value

if Garage1 == 'true' and GarageAutoClose == 'true':
    indigo.iodevice.setBinaryOutput('Garage1', 0, True)
   
sleep(60)

if Garage1 == 'true' and GarageAutoClose == 'true':
    indigo.iodevice.setBinaryOutput('Garage1', 0, True)

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

[My Plugins] - [My Forums]

Posted on
Mon Aug 13, 2018 8:53 pm
hamw offline
Posts: 1212
Joined: Mar 31, 2008

Re: Starting out with Python

Dave,

First, thanks so much for your assistance. i read over the prior posts and your explanations are very helpful and appreciated. I gave your script a try, incorporating the device attributes query so that I could get the list available on an IOLinc. I used binary.input to get the current state of open/closed, but it won't log, and thus I think it may not run. Ideas?

Code: Select all
from time import sleep

device_id = 308749424
dev = indigo.devices[device_id]
#dev = indigo.devices[308749424]
#indigo.server.log(unicode(dev)) #gets all possible states of device

Garage1 = indigo.devices[308749424].binaryInputs  <<<<<<<<<<<<< gets past this part
# It's recommended to use Indigo ID numbers instead of names, but names will work.
GarageAutoClose = indigo.variables[1770515678].value
indigo.server.log(GarageAutoClose)
indigo.server.log(Garage1)   <<<<<<<<<< won't log and fails here.


if Garage1 == 'true' and GarageAutoClose == 'true':
    indigo.iodevice.setBinaryOutput('Garage1', 0, True)

Posted on
Tue Aug 14, 2018 5:53 am
DaveL17 offline
User avatar
Posts: 6755
Joined: Aug 20, 2013
Location: Chicago, IL, USA

Re: Starting out with Python

You are very close! Indigo will only log strings, so any value that's not a string will need to be converted. I've simplified the script a bit to make it easier to see what's going on. In addition to changing the log command which results in the error, I've also changed the script slightly because I think the 'binaryInputs' property of the device is likely already a boolean value (True, False). I can't test this, so you'll have to let me know if it works the way you want.

Code: Select all
Garage1 = indigo.devices[308749424].binaryInputs  # <<<<< This value is likely not a string.
GarageAutoClose = indigo.variables[1770515678].value

indigo.server.log(u"{0}".format(Garage1))  # <<<<< I prefer the format() command for logging which handles the conversion.
indigo.server.log(u"{0}".format(GarageAutoClose)) 

if Garage1 and GarageAutoClose == 'true':
    indigo.iodevice.setBinaryOutput(308749424, 0, True)

I'm a bit unsure about the last line, which appears to set the binary input of device 308749424 (Garage1) to True when its value is already True (and the value of GarageAutoClose is 'true'). Let's make sure this runs without error and then we can change the logic if we need to.

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

[My Plugins] - [My Forums]

Posted on
Tue Aug 14, 2018 8:51 pm
hamw offline
Posts: 1212
Joined: Mar 31, 2008

Re: Starting out with Python

Success! That single script incorporates a lot of what I need in my system... comparing values, executing an action and logging to be sure the action s actually done. That will make it a lot easier to transition to Python. Thanks very much for your help!

Posted on
Wed Aug 15, 2018 6:06 am
DaveL17 offline
User avatar
Posts: 6755
Joined: Aug 20, 2013
Location: Chicago, IL, USA

Re: Starting out with Python

hamw wrote:
Success! That single script incorporates a lot of what I need in my system... comparing values, executing an action and logging to be sure the action s actually done. That will make it a lot easier to transition to Python. Thanks very much for your help!

Glad to hear that worked for you. A note about the 'if' statement and boolean testing. The first bit:
Code: Select all
if Garage1...

Garage1 is either True or False and Python will only evaluate the second bit if the first bit is True. Note that True (a boolean) is not the same as 'true' (a string) even though they both evaluate to True.

It's easiest to see with this example:
Code: Select all
>>> if 'false':
...     print('True')
...
True 

In other words, the string 'false' evaluates to True. Examples of things that are False:
  • False
  • ""
  • ()
  • []
  • {}
  • 0 (zero)
You may understand all this already, but it starts to get tricky when we get creative:
Code: Select all
if a != 'true' and (b or c) not d and e:

Feel free to ping back with any questions!

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

[My Plugins] - [My Forums]

Posted on
Wed Aug 15, 2018 8:53 am
jay (support) offline
Site Admin
User avatar
Posts: 18220
Joined: Mar 19, 2008
Location: Austin, Texas

Re: Starting out with Python

DaveL17 wrote:
In other words, the string 'false' evaluates to True. Examples of things that are False:
  • False
  • ""
  • ()
  • []
  • {}
  • 0 (zero)


And in most circumstances, None (I'm ignoring the esoterica of the None object).

One other trick: if you have an Indigo variable that's a boolean, then you can explicitly get the value as a boolean, which makes those kinds of comparisons even easier. Here's a slightly altered version of the script:

Code: Select all
Garage1 = indigo.devices[308749424].binaryInputs  # <<<<< This value is likely not a string.
GarageAutoClose = indigo.variables[1770515678].getValue(bool)

indigo.server.log(u"{0}".format(Garage1))  # <<<<< I prefer the format() command for logging which handles the conversion.
indigo.server.log(u"{0}".format(GarageAutoClose)) 

if Garage1 and GarageAutoClose:
    indigo.iodevice.setBinaryOutput(308749424, 0, True)


So you use the getValue() method on the variable object and specify the type of the value you want returned. You can also use int and float.

Jay (Indigo Support)
Twitter | Facebook | LinkedIn

Posted on
Sun Aug 19, 2018 9:07 pm
hamw offline
Posts: 1212
Joined: Mar 31, 2008

Re: Starting out with Python

This seems like it should work... but instead of bypassing the action when the script is not true, it executes anyway. I tried adding a variable as a test, thinking that the IO Linc might not be responding fast enough, but same result.It keeps executing the IO Linc and will open the garage door if closed. Thoughts?


Code: Select all
Schedule                        Garage Door 1 Auto Close (delayed action)
   Script                          [False]
   Script                          false
   Script                          true
   Sent INSTEON                    "aGarage Door 1" on
   Received INSTEON                "aGarage Door 1" on
 
   Sent INSTEON                    "aGarage Door 1" status request (received input sensor: open)
   Sent INSTEON                    "aGarage Door 1" status request (received output relay: off)


The current script:

Code: Select all
Garage1 = indigo.devices[308749424].binaryInputs  # <<<<< This value is likely not a string.
Garage1_State = indigo.variables[552843942].value

GarageAutoClose = indigo.variables[1770515678].value

indigo.server.log(u"{0}".format(Garage1))  # <<<<< I prefer the format() command for logging which handles the conversion.
indigo.server.log(u"{0}".format(Garage1_State))
indigo.server.log(u"{0}".format(GarageAutoClose))

if Garage1_State and GarageAutoClose == 'true':
    indigo.iodevice.setBinaryOutput(308749424, 0, True)

Posted on
Mon Aug 20, 2018 5:36 am
DaveL17 offline
User avatar
Posts: 6755
Joined: Aug 20, 2013
Location: Chicago, IL, USA

Re: Starting out with Python

hamw wrote:
This seems like it should work... but instead of bypassing the action when the script is not true, it executes anyway. I tried adding a variable as a test, thinking that the IO Linc might not be responding fast enough, but same result.It keeps executing the IO Linc and will open the garage door if closed. Thoughts?


Code: Select all
Schedule                        Garage Door 1 Auto Close (delayed action)
   Script                          [False]
   Script                          false
   Script                          true
   Sent INSTEON                    "aGarage Door 1" on
   Received INSTEON                "aGarage Door 1" on
 
   Sent INSTEON                    "aGarage Door 1" status request (received input sensor: open)
   Sent INSTEON                    "aGarage Door 1" status request (received output relay: off)


The current script:

Code: Select all
Garage1 = indigo.devices[308749424].binaryInputs  # <<<<< This value is likely not a string.
Garage1_State = indigo.variables[552843942].value

GarageAutoClose = indigo.variables[1770515678].value

indigo.server.log(u"{0}".format(Garage1))  # <<<<< I prefer the format() command for logging which handles the conversion.
indigo.server.log(u"{0}".format(Garage1_State))
indigo.server.log(u"{0}".format(GarageAutoClose))

if Garage1_State and GarageAutoClose == 'true':
    indigo.iodevice.setBinaryOutput(308749424, 0, True)

Based on your output, it looks like the value of Garage1 is a list (and not a binary value), so it seems that we'll need to access the list element instead. This is untested, but I think it just might work:
Code: Select all
Garage1 = indigo.devices[308749424].binaryInputs[0]  # <<<<< We are attempting to access the 'zeroth' element of the list (the index of the first item is zero).
Garage1_State = indigo.variables[552843942].value

GarageAutoClose = indigo.variables[1770515678].value

indigo.server.log(u"{0}".format(Garage1))
indigo.server.log(u"{0}".format(Garage1_State))
indigo.server.log(u"{0}".format(GarageAutoClose))

if Garage1_State and GarageAutoClose == 'true':
    indigo.iodevice.setBinaryOutput(308749424, 0, True)


EDIT: Only an empty list would evaluate to False.

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

[My Plugins] - [My Forums]

Posted on
Mon Aug 20, 2018 6:13 am
hamw offline
Posts: 1212
Joined: Mar 31, 2008

Re: Starting out with Python

I tried to take the IO link out of the process completely by referencing the variable “garage1”. That variable is set by an indigo action according to the current state of the IOLinc before the script is executed and so represents the current state of the garage IOLinc input. Thus the comparison is currently between the variable “garage1” and the variable “garage auto close.” I would have thought that if the syntax was correct in the comparison it would have resolved to “false, true “ . Since both are not true I would have thought it would pass through the comparison without executing the action.

So could there be a syntax problem in the comparison statement?

Posted on
Mon Aug 20, 2018 8:07 am
FlyingDiver offline
User avatar
Posts: 7220
Joined: Jun 07, 2014
Location: Southwest Florida, USA

Re: Starting out with Python

hamw wrote:
So could there be a syntax problem in the comparison statement?


Maybe. I can never remember the precedence order. Try this:

Code: Select all
Garage1_State = indigo.variables[552843942].value
GarageAutoClose = indigo.variables[1770515678].value

indigo.server.log(u"{0}".format(Garage1_State))
indigo.server.log(u"{0}".format(GarageAutoClose))

if Garage1_State and (GarageAutoClose == 'true'):
    indigo.iodevice.setBinaryOutput(308749424, 0, True)

joe (aka FlyingDiver)
my plugins: http://forums.indigodomo.com/viewforum.php?f=177

Posted on
Mon Aug 20, 2018 8:52 am
DaveL17 offline
User avatar
Posts: 6755
Joined: Aug 20, 2013
Location: Chicago, IL, USA

Re: Starting out with Python

If I'm understanding your example, any non-empty Indigo variable would evaluate to True regardless of its contents unless you use Jay's suggestion to 'getValue()'. In other words, a variable value of 'false' or 'False' would evaluate as True. A variable set to 'false' yields:

Code: Select all
val = indigo.variables[60344867]
if val:
    indigo.server.log('True')
else:
    indigo.server.log('False')

# Yields 'True'

Code: Select all
val = indigo.variables[60344867].getValue(bool)
if val:
    indigo.server.log('True')
else:
    indigo.server.log('False')

# Yields 'False'

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

[My Plugins] - [My Forums]

Posted on
Tue Aug 21, 2018 2:32 pm
matt (support) offline
Site Admin
User avatar
Posts: 21417
Joined: Jan 27, 2003
Location: Texas

Re: Starting out with Python

This:

Code: Select all
val = indigo.variables[60344867]

will always have "if val:" evaluate as True because it isn't the value of the variable. It is the python instance object that represents the entire variable object in Indigo (including the name, value, and other properties). You can use either val.value to extract the value as a string (which will evaluate to True if the string length is > 0; that is, not empty) or you can extract out a specific type of value using the var.getValue(_some_type_) method.

Image

Who is online

Users browsing this forum: No registered users and 3 guests