I found at one point that I had instances of Insteon door sensors purchased at different times with widely varying battery usage. Scanning logs, I found big variation in the time between sending heartbeat messages. A bit more investigation turned up differences in other parameter settings as well. I wanted a way to set my devices for consistency and max battery life.
- Code: Select all
# Set parameters for hidden motion sensors, including heartbeat interval and LED mode.
# This script is useful to set up Insteon Hidden Motion Sensor (2845-222).
#
# author: D. Duff user dduff617 on forums.indigodomo.com (duff@alum.mit.edu)
#
# Why?
# a) Indigo doesn't currently provide any UI for accessing these settings.
# b) Prolong battery life.
# c) Cut down unnecessary Insteon traffic
#
# What exactly does this do?
# Sets the heartbeat interval. Value can be set from 5 mins to "about a day". I use heartbeat
# for battery monitoring and as such, for me there's really no point in setting it to anything
# other than max value to save batteries and reduce network traffic.
# Turns off LED. Again this is done primarily to save battery - nothing but a waste of battery
# having an LED shine when buried inside a hole in my doorframe.
#
# BEFORE RUNNING THIS SCRIPT
# First, set this to the name of the device you want to configure.
d = indigo.devices["FOY-CLOS Door Open"]
# Next, Put device in linking mode by holding the set button (if device is out of the wall)
# If device is installed in the wall, you can put it in linking mode, by executing the following steps:
# 1. push the plunger
# 2. release
# 3. push the plunger
# 4. release
# 5. push the plunger and hold it until device beeps.
# 6. release the plunger.
# You have to do steps 1-5 in very quick succession. The beep is not very loud, so you have to listen for it.
# The device stays in linking mode for about a minute.
# set heartbeat interval extended command to door sensor, returns a standard ack.
# note that while heartbeat interval can be set, the results must be observed indirectly
# (as the time delta between successive heartbeats). Value can not be read directly from
# the device, which is kind of annoying.
def setHeartbeatInterval (device, value=0) :
setHeartbeatIntervalCmd = [
0x2E,
0x00,
0x00, # unused
0x02, # set hearbeat interval command
value # heartbeat interval value. 0x01->5min, 0x02->10min, 0x03->15min etc. special 0->"about 24 hrs" (emperically, turns out to be roughly in the range of 19:45 to 21:40)
]
indigo.server.log("Attempting to set heartbeat for device {} to {}".format(device.name, value))
# setting calcCrc=True here will cause it to fail - why? i don't know.
reply = indigo.insteon.sendRawExtended(device.address, setHeartbeatIntervalCmd, suppressLogging=True)
if reply.cmdSuccess :
# indigo.server.log("reply success: {:d}, ack value: {:#x}".format(reply.cmdSuccess, reply.ackValue))
indigo.server.log("Heartbeat interval for device {} was successfully set to {} or {}".format(device.name, value, describeSensorHeartbeat(value)))
return True
else:
indigo.server.log("Extended command failed. Device may be offline?", isError=True)
return false
def describeSensorHeartbeat(value) :
if value==0 :
return "about 24 hours"
else:
return "{} minutes".format(5*value)
# read operating flags is a standard (not extended) command.
# should return result in a standard ack (?) with the interesting results packed into a single reply byte.
# note: this does not return the heartbeat interval and afaik, there is no way to do this.
def readOperatingFlags (device):
# indigo.server.log("Attempting to read operating flags 0 for device {}".format(device.name))
reply = indigo.insteon.sendRaw(device.address, [0x1f, 0x00], waitUntilAck=True, suppressLogging=True)
if reply.cmdSuccess:
# indigo.server.log("reply success: %d, ack value: %02X" % (reply.cmdSuccess, reply.ackValue))
# indigo.server.log("ReplyBytes: {}".format(reply.replyBytes))
indigo.server.log("Operating Flags for device {}".format(device.name))
describeOperatingFlags(reply.ackValue)
else:
indigo.server.log("Command failed. Device may be offline?")
def describeOperatingFlags (reply) :
# indigo.server.log("calling descibeOperatingFlags with reply {}".format(reply))
# info from "Developer Notes" for 2845-222 dated October 2013.
# bit 0 = Do Cleanup Report
# bit 1 = 2 Groups
# bit 2 = Repeat Open
# bit 3 = Repeat Closed
# bit 4 = Link to FF Group
# bit 5 = LED Disable
# bit 6 = N/A
# bit 7 = Programming Lock
indigo.server.log("Do Cleanup Report: {}".format((reply & 1<< 0) > 0))
indigo.server.log("2 Groups: {}".format((reply & 1<<1) > 0))
indigo.server.log("Repeat Open: {}".format((reply & 1<<2 ) > 0))
indigo.server.log("Repeat Closed: {}".format((reply & 1>>3) > 0))
indigo.server.log("Link to FF Group: {}".format((reply & 1<<4) > 0))
indigo.server.log("LED Disable: {}".format((reply & 1<<5) > 0))
# indigo.server.log("Unused flag: {}".format((reply & 1<<6) > 0))
indigo.server.log("Programming Lock: {}".format((reply & 1<<7) > 0))
# set LED Mode. mode=True means LED is ON. mode=False means LED is OFF, aka disabled.
def setLEDMode (device, mode=False):
indigo.server.log("Attempting to set LED Mode for device {} to {}".format(device.name, mode))
cmdBytes = [0x20, 0x03 if mode else 0x02]
reply = indigo.insteon.sendRawExtended(device.address, cmdBytes, suppressLogging=True)
if reply.cmdSuccess:
#indigo.server.log("Reply success: {:d}, Ack value: {:02X}, ReplyBytes: {}".format(reply.cmdSuccess, reply.ackValue, reply.replyBytes))
indigo.server.log("LED mode for device {} was successfully set to {}".format(device.name, mode))
return True
else:
indigo.server.log("Command failed. Device may be offline?", isError=True)
return False
# simple ping to test that a device is awake.
def awakeCheck (device):
result = indigo.device.ping(d, suppressLogging=True)
if result["Success"]:
indigo.server.log("Device is awake and listening. %.2f seconds ping for %s" % (result["TimeDelta"]/1000.0, device.name))
return True
else:
indigo.server.log("ping failed for %s" % (d.name), isError=True)
return False
#
# here's where the action happens:
if (not awakeCheck(d)):
indigo.server.log("Device is not awake or not in range. Quitting.", isError=True)
quit()
# set heartbeat interval (to save batteries)
if (not setHeartbeatInterval(d)):
indigo.server.log("Set heartbeat interval failed. Quitting.", isError=True)
quit()
# turn off LED
if not setLEDMode(d):
indigo.server.log("Set LED Mode failed. Quitting.")
quit()
# dump the current operating flags to logs so we can confirm LED status and other settings.
readOperatingFlags(d)