Zones 9+

General Discussion

Re: Zones 9+

Postby kevin » Mon May 15, 2017 6:25 pm

device_type.groovy

after line 32:
Code: Select all
 input("zonetracker8zone", "number", title: "ZoneTracker Sensor #8", description: "Zone number to associate with this contact sensor.")

add:
Code: Select all
 input("zonetracker9zone", "number", title: "ZoneTracker Sensor #9", description: "Zone number to associate with this contact sensor.")
 input("zonetracker10zone", "number", title: "ZoneTracker Sensor #10", description: "Zone number to associate with this contact sensor.")


Line 522 - change:
Code: Select all
 for (def i = 1; i <= 8; i++) {

to:
Code: Select all
 for (def i = 1; i <= 10; i++) {




service_manager.groovy

Line 366 - change:
Code: Select all
 for (def i = 0; i < 8; i++)

to:
Code: Select all
 for (def i = 0; i < 10; i++)



This will add 2 more sensors to your list - you can then assign new zone numbers to them in the Smart Things UI after uploading your code.
Not an employee of the company. Just here to help and keep things clean.
kevin
Platinum Nut
Platinum Nut
 
Posts: 994
Joined: Fri Aug 16, 2013 10:10 am

Re: Zones 9+

Postby mgreinke » Thu Jun 15, 2017 7:13 am

I finally got around to trying this. It works mostly however I did find some anomalies. Not sure if they are attributable to the modifications or maybe the firmware I am on.

1) Although I edited the code to support a total of 26 virtual sensors (8 native on panel, 2 on hardwired expander and 16 on wireless expander), I actually ended up with 32 being created in the IDE. Not sure why the additional 6 got created.
2) For some reason, my front door which is a wired contact sensor configured as zone 2 on my panel is now getting reported as zone 29 by the AD2 (webapp and ST). I've confirmed its configured correctly in the ST app. The panel doesn't register a fault on the second sensor. This didn't happen when I only had 8 sensors configured.
3) Occasionally, an open contact sensor (like a door that is propped open for ventilation) will report as open and closed every minute or so in both the webapp and ST. If I power cycle the AD2 it seems to correct the issue temporarily.
4) Occasionally if a sensor is opened and closed quickly, like to open a slider to let a dog out or in, the webapp and ST don't seem to register the fault (or restore). Perhaps polling isn't quick enough to pick up such brief faults. I currently have about 13 connected and active sensors. Perhaps that many sensors is overloading the AD2?
5) If the system is armed and then tripped, the AD2 and ST report the proper sensor that tripped the alarm but also always reports a second sensor being faulted. The same second sensor is being incorrectly reported anytime the alarm is tripped however I know that second sensor has not been tripped.

Anyway, despite these problems I'm still very happy with the AD2!

I only wish the Ademco panel would allow reporting sensor status while the panel is armed but obviously that is an issue with the panel not the AD2.
I'm on firmware version 2.2a.8.2 but am wondering if a newer firmware would address any of these?
mgreinke
Junior Nut
Junior Nut
 
Posts: 23
Joined: Tue May 02, 2017 4:06 pm

Re: Zones 9+

Postby kevin » Thu Jun 15, 2017 9:39 am

Hey if you could submit a ticket about this to ad2usb@support.nutech.com so we can easily add investigation to our work queue that would be great.

We have released a new stable firmware here: https://www.alarmdecoder.com/wiki/index.php/Firmware

I do not think your issues are firmware related, but it is recommended to stay up to date as software will eventually follow firmware with new capabilities.
Not an employee of the company. Just here to help and keep things clean.
kevin
Platinum Nut
Platinum Nut
 
Posts: 994
Joined: Fri Aug 16, 2013 10:10 am

Re: Zones 9+

Postby kevin » Thu Jun 15, 2017 11:01 am

Now that I think about it, maybe fixes to EXP messages in newest firmware might help a bit - but still strange issues nonetheless that a support ticket is warranted.
Not an employee of the company. Just here to help and keep things clean.
kevin
Platinum Nut
Platinum Nut
 
Posts: 994
Joined: Fri Aug 16, 2013 10:10 am

Re: Zones 9+

Postby Jag4666 » Sat Nov 18, 2017 5:49 pm

Hi guys,

anyone encountering this error message when adding additional zones under the service manager after completing all the steps then clicking install?

java.lang.NullPointerException: Cannot invoke method minus() on null object

i am adding a total of 20 zones
Jag4666
newt
newt
 
Posts: 14
Joined: Fri Oct 28, 2016 7:10 pm

Re: Zones 9+

Postby Jag4666 » Sat Nov 18, 2017 6:46 pm

the code from my hub

9d0ba67d-ea9e-4d59-8638-01476432e149 8:46:43 PM: error java.lang.NullPointerException: Cannot invoke method minus() on null object
9d0ba67d-ea9e-4d59-8638-01476432e149 8:46:43 PM: trace addExistingDevices, devices.find=uuid:8430b64a-8c6b-11e7-ad9f-b827ebfe86ab={port=1388, ssdpUSN=uuid:8430b64a-8c6b-11e7-ad9f-b827ebfe86ab, devicetype=04, mac=B827EBFE86AB, hub=33c4f538-470f-496a-8e20-65d1a99c8e77, ssdpTerm=urn:schemas-upnp-org:device:AlarmDecoder:1, ip=C0A8000E}
9d0ba67d-ea9e-4d59-8638-01476432e149 8:46:43 PM: trace devices=[uuid:8430b64a-8c6b-11e7-ad9f-b827ebfe86ab:[port:1388, ssdpUSN:uuid:8430b64a-8c6b-11e7-ad9f-b827ebfe86ab, devicetype:04, mac:B827EBFE86AB, hub:33c4f538-470f-496a-8e20-65d1a99c8e77, ssdpTerm:urn:schemas-upnp-org:device:AlarmDecoder:1, ip:C0A8000E]]
9d0ba67d-ea9e-4d59-8638-01476432e149 8:46:43 PM: trace addExistingDevices, getChildDevice(C0A8000E:1388)
9d0ba67d-ea9e-4d59-8638-01476432e149 8:46:43 PM: trace addExistingDevices: C0A8000E:1388
9d0ba67d-ea9e-4d59-8638-01476432e149 8:46:43 PM: trace initialize
9d0ba67d-ea9e-4d59-8638-01476432e149 8:46:43 PM: debug Installed with settings: [selectedDevices:C0A8000E:1388, shmChangeSHMStatus:true, shmIntegration:true, defaultSensorToClosed:true]
9d0ba67d-ea9e-4d59-8638-01476432e149 8:46:40 PM: trace locationHandler: device already exists.. checking for changed values
Jag4666
newt
newt
 
Posts: 14
Joined: Fri Oct 28, 2016 7:10 pm

Re: Zones 9+

Postby kevin » Mon Nov 20, 2017 3:18 pm

null object means something you added didn't get initialized to anything
Not an employee of the company. Just here to help and keep things clean.
kevin
Platinum Nut
Platinum Nut
 
Posts: 994
Joined: Fri Aug 16, 2013 10:10 am

Re: Zones 9+

Postby Jag4666 » Mon Nov 20, 2017 3:37 pm

I’ve been doing the install as per the instructions on github with the only change being in the number of zones. I’ve followed the instructions in this thread for doing that. Are there any other things I should be changing to increase the number of zones.

What would be causing this initialization error. it is only showing up after I complete the simulation where I identify the alarm decoder IP.

From what I can see the code seems to be correct
Jag4666
newt
newt
 
Posts: 14
Joined: Fri Oct 28, 2016 7:10 pm

Re: Zones 9+

Postby kevin » Mon Nov 20, 2017 3:38 pm

A closer look at the error indicates you perhaps did not uninstall all of the alarmdecoder components before you re-uploaded new code??
Not an employee of the company. Just here to help and keep things clean.
kevin
Platinum Nut
Platinum Nut
 
Posts: 994
Joined: Fri Aug 16, 2013 10:10 am

Re: Zones 9+

Postby Jag4666 » Wed Nov 22, 2017 12:13 pm

Hey Kevin,

Thanks for replying.

I have tried uninstalling multiple times with a reboot prior to installing with no such luck.

Not sure where it seems to be getting locked up.

Below is the Service Manager Code:

/**
* AlarmDecoder Service Manager
*
* Copyright 2016 Nu Tech Software Solutions, Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except
* in compliance with the License. You may obtain a copy of the License at:
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software distributed under the License is distributed
* on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License
* for the specific language governing permissions and limitations under the License.
*
*/

definition(
name: "AlarmDecoder (Service Manager)",
namespace: "alarmdecoder",
author: "Nu Tech Software Solutions, Inc.",
description: "AlarmDecoder (Service Manager)",
category: "My Apps",
iconUrl: "https://s3.amazonaws.com/smartapp-icons/Convenience/Cat-Convenience.png",
iconX2Url: "https://s3.amazonaws.com/smartapp-icons/Convenience/Cat-Convenience@2x.png",
iconX3Url: "https://s3.amazonaws.com/smartapp-icons/Convenience/Cat-Convenience@2x.png",
singleInstance: true) { }

preferences {
page(name: "main", title: "Discover your AlarmDecoder", install: true, uninstall: true) {
section("") {
href(name: "discover", title: "Discover", required: false, page: "discover_devices", description: "Tap to discover")
}
}
page(name: "discover_devices", title: "Discovery started..", content: "discover_devices", refreshTimeout: 5)
}

mappings {
path("/update") {
action: [
GET: "webserviceUpdate"
]
}
}

/*** Handlers ***/

def installed() {
log.debug "Installed with settings: ${settings}"

initialize()
}

def updated() {
log.debug "Updated with settings: ${settings}"

unschedule()
initialize()
}

def uninstalled() {
log.trace "uninstalled"

// HACK: Work around SmartThings wonky uninstall. They claim unsubscribe is uncessary,
// but it is, as is the runIn() since everything is asynchronous. Otherwise events
// don't get correctly unbound and the devices can't be deleted because they're in use.
unschedule()
unsubscribe()
runIn(300, do_uninstall)
}

def initialize() {
log.trace "initialize"

unsubscribe()
state.subscribed = false
state.lastSHMStatus = null
state.lastAlarmDecoderStatus = null

subscribe(location, "alarmSystemStatus", shmAlarmHandler)

unschedule()

if (selectedDevices) {
addExistingDevices()
configureDevices()
}

scheduleRefresh()
}

def locationHandler(evt) {
log.trace "locationHandler"

def description = evt.description
def hub = evt?.hubId

log.trace "locationHandler: description=${description}"

def parsedEvent = parseEventMessage(description)
parsedEvent << ["hub":hub]

// LAN EVENTS
if (parsedEvent?.ssdpTerm?.contains("urn:schemas-upnp-org:device:AlarmDecoder:1")) {
getDevices()

if (!(state.devices."${parsedEvent.ssdpUSN.toString()}")) {
log.trace "locationHandler: Adding device: ${parsedEvent.ssdpUSN}"

devices << ["${parsedEvent.ssdpUSN.toString()}": parsedEvent]
}
else {
def d = state.devices."${parsedEvent.ssdpUSN.toString()}"
boolean deviceChangedValues = false

log.trace "locationHandler: device already exists.. checking for changed values"

if (d.ip != parsedEvent.ip || d.port != parsedEvent.port) {
d.ip = parsedEvent.ip
d.port = parsedEvent.port
deviceChangedValues = true

log.trace "locationHandler: device changed values!"
}

if (deviceChangedValues) {
def children = getChildDevices()
children.each {
if (it.getDeviceDataByName("mac") == parsedEvent.mac) {
it.setDeviceNetworkId((parsedEvent.ip + ":" + parsedEvent.port))
log.trace "Set new network id: " + parsedEvent.ip + ":" + parsedEvent.port
}
}
}
}
}

// HTTP EVENTS
if (parsedEvent?.body && parsedEvent?.headers) {
log.trace "locationHandler: headers=${new String(parsedEvent.headers.decodeBase64())}"
log.trace "locationHandler: body=${new String(parsedEvent.body.decodeBase64())}"
}
}

def refreshHandler() {
log.trace "refreshHandler"

refresh_alarmdecoders()
}

def webserviceUpdate()
{
log.trace "webserviceUpdate"

refresh_alarmdecoders()
return [status: "OK"]
}

/*** Commands ***/

def zoneOn(evt) {
log.trace("zoneOn: desc=${evt.value}")

def d = getChildDevices().find { it.deviceNetworkId.contains("switch${evt.value}") }
if (d)
{
def sensorValue = "closed"
if (settings.defaultSensorToClosed == true)
sensorValue = "open"

d.sendEvent(name: "contact", value: sensorValue, isStateChange: true, filtered: true)
}
}

def zoneOff(evt) {
log.trace("zoneOff: desc=${evt.value}")

def d = getChildDevices().find { it.deviceNetworkId.contains("switch${evt.value}") }
if (d)
{
def sensorValue = "open"
if (settings.defaultSensorToClosed == true)
sensorValue = "closed"

d.sendEvent(name: "contact", value: sensorValue, isStateChange: true, filtered: true)
}
}

def shmAlarmHandler(evt) {
if (settings.shmIntegration == false)
return

log.trace("shmAlarmHandler -- ${evt.value}")

if (state.lastSHMStatus != evt.value && evt.value != state.lastAlarmDecoderStatus)
{
getAllChildDevices().each { device ->
if (!device.deviceNetworkId.contains(":switch"))
{
if (evt.value == "away")
device.lock()
else if (evt.value == "stay")
device.on()
else if (evt.value == "off")
device.off()
else
log.debug "Unknown SHM alarm value: ${evt.value}"
}
}
}

state.lastSHMStatus = evt.value
}

def alarmdecoderAlarmHandler(evt) {
if (settings.shmIntegration == false || settings.shmChangeSHMStatus == false)
return

log.trace("alarmdecoderAlarmHandler: ${evt.value}")

if (state.lastAlarmDecoderStatus != evt.value && evt.value != state.lastSHMStatus)
sendLocationEvent(name: "alarmSystemStatus", value: evt.value)

state.lastAlarmDecoderStatus = evt.value
}

/*** Utility ***/

def discover_devices() {
int refreshInterval = 5
int refreshCount = !state.refreshCount ? 0 : state.refreshCount as int
state.refreshCount = refreshCount += 1

def found_devices = [:]
def options = state.devices.each { k, v ->
log.trace "discover_devices: ${v}"
def ip = convertHexToIP(v.ip)
found_devices["${v.ip}:${v.port}"] = "AlarmDecoder @ ${ip}"
}

def numFound = found_devices.size() ?: 0

if (!state.subscribed) {
log.trace "discover_devices: subscribe to location"

subscribe(location, null, locationHandler, [filterEvents: false])
state.subscribed = true
}

discover_alarmdecoder()

return dynamicPage(name: "discover_devices", title: "Setup", nextPage: "", refreshInterval: refreshInterval, install: true, uninstall: true) {
section("Devices") {
input "selectedDevices", "enum", required: false, title: "Select device(s) (${numFound} found)", multiple: true, options: found_devices
// TEMP: REMOVE THIS?
href(name: "refreshDevices", title: "Refresh", required: false, page: "discover_devices")
}
section("Smart Home Monitor Integration") {
input(name: "shmIntegration", type: "bool", defaultValue: true, title: "Integrate with Smart Home Monitor?")
input(name: "shmChangeSHMStatus", type: "bool", defaultValue: true, title: "Automatically change Smart Home Monitor status when armed or disarmed?")
}
section("Zone Sensors") {
input(name: "defaultSensorToClosed", type: "bool", defaultValue: true, title: "Default zone sensors to closed?")
}
}
}

def discover_alarmdecoder() {
log.trace "discover_alarmdecoder"

if (!state.subscribed) {
log.trace "discover_alarmdecoder: subscribing!"
subscribe(location, null, locationHandler, [filterEvents: false])
state.subscribed = true
}

sendHubCommand(new physicalgraph.device.HubAction("lan discovery urn:schemas-upnp-org:device:AlarmDecoder:1", physicalgraph.device.Protocol.LAN))
}

def do_uninstall() {
def devices = getChildDevices()

devices.each {
try {
log.trace "deleting child device: ${it.deviceNetworkId}"
deleteChildDevice(it.deviceNetworkId)
}
catch(Exception e) {
log.trace("exception while uninstalling: ${e}")
}
}
}

def scheduleRefresh() {
def minutes = 1

def cron = "0 0/${minutes} * * * ?"
schedule(cron, refreshHandler)
}

def refresh_alarmdecoders() {
log.trace("refresh_alarmdecoders-")
getAllChildDevices().each { device ->
// Only refresh the main device.
if (!device.deviceNetworkId.contains(":switch"))
{
log.trace("refresh_alarmdecoders: ${device}")
device.refresh()
}
}
}

def getDevices() {
if(!state.devices) {
state.devices = [:]
}

state.devices
}

def addExistingDevices() {
log.trace "addExistingDevices: ${selectedDevices}"

def selected_devices = selectedDevices
if (selected_devices instanceof java.lang.String) {
selected_devices = [selected_devices]
}

selected_devices.each { dni ->
def d = getChildDevice(dni)
log.trace("addExistingDevices, getChildDevice(${dni})")
if (!d) {
log.trace("devices=${devices}")
def newDevice = state.devices.find { /*k, v -> k == dni*/ k, v -> dni == "${v.ip}:${v.port}" }
log.trace("addExistingDevices, devices.find=${newDevice}")

if (newDevice) {
// Set the device network ID so that hubactions get sent to the device parser.
state.ip = newDevice.value.ip
state.port = newDevice.value.port
state.hub = newDevice.value.hub

// Set URN for the child device
def urn = newDevice.value.ssdpPath
urn -= "http://"
state.urn = urn

// Create device and subscribe to it's zone-on/off events.
d = addChildDevice("alarmdecoder", "AlarmDecoder Network Appliance", "${state.ip}:${state.port}", newDevice?.value.hub, [name: "${state.ip}:${state.port}", label: "AlarmDecoder", completedSetup: true, data:[urn: state.urn]])
}
}
}
}

private def configureDevices() {
def device = getChildDevice("${state.ip}:${state.port}")
if (!device) {
log.trace("configureDevices: Could not find primary device.")
return
}

subscribe(device, "zone-on", zoneOn, [filterEvents: false])
subscribe(device, "zone-off", zoneOff, [filterEvents: false])
subscribe(device, "alarmStatus", alarmdecoderAlarmHandler, [filterEvents: false])

// Add virtual zone contact sensors.
for (def i = 0; i < 20; i++)
{
def newSwitch = state.devices.find { k, v -> k == "${state.ip}:${state.port}:switch${i+1}" }
if (!newSwitch)
{
def zone_switch = addChildDevice("alarmdecoder", "VirtualContactSensor", "${state.ip}:${state.port}:switch${i+1}", state.hub, [name: "${state.ip}:${state.port}:switch${i+1}", label: "AlarmDecoder Zone Sensor #${i+1}", completedSetup: true])

def sensorValue = "open"
if (settings.defaultSensorToClosed == true)
sensorValue = "closed"

// Set default contact state.
zone_switch.sendEvent(name: "contact", value: sensorValue, isStateChange: true, displayed: false)
}
}
}

private def parseEventMessage(String description) {
def event = [:]
def parts = description.split(',')

parts.each { part ->
part = part.trim()
if (part.startsWith('devicetype:')) {
def valueString = part.split(":")[1].trim()
event.devicetype = valueString
}
else if (part.startsWith('mac:')) {
def valueString = part.split(":")[1].trim()
if (valueString) {
event.mac = valueString
}
}
else if (part.startsWith('networkAddress:')) {
def valueString = part.split(":")[1].trim()
if (valueString) {
event.ip = valueString
}
}
else if (part.startsWith('deviceAddress:')) {
def valueString = part.split(":")[1].trim()
if (valueString) {
event.port = valueString
}
}
else if (part.startsWith('ssdpPath:')) {
part -= "ssdpPath:"
def valueString = part.trim()
if (valueString) {
event.ssdpPath = valueString
}
}
else if (part.startsWith('ssdpUSN:')) {
part -= "ssdpUSN:"
def valueString = part.trim()
if (valueString) {
event.ssdpUSN = valueString
}
}
else if (part.startsWith('ssdpTerm:')) {
part -= "ssdpTerm:"
def valueString = part.trim()
if (valueString) {
event.ssdpTerm = valueString
}
}
else if (part.startsWith('headers')) {
part -= "headers:"
def valueString = part.trim()
if (valueString) {
event.headers = valueString
}
}
else if (part.startsWith('body')) {
part -= "body:"
def valueString = part.trim()
if (valueString) {
event.body = valueString
}
}
}

event
}

private String convertHexToIP(hex) {
[convertHexToInt(hex[0..1]),convertHexToInt(hex[2..3]),convertHexToInt(hex[4..5]),convertHexToInt(hex[6..7])].join(".")
}

private Integer convertHexToInt(hex) {
Integer.parseInt(hex,16)
}
Jag4666
newt
newt
 
Posts: 14
Joined: Fri Oct 28, 2016 7:10 pm

PreviousNext

Return to General

Who is online

Users browsing this forum: No registered users and 4 guests

cron