Help with Smart App


(Greg) #1

Really would appreciate if anyone could give me some help or guidance. I’m trying to write an app so that I will get a notification ONLY if acceleration happens twice in a user defined period of time. I’ve pieced the following together from other smart apps.

preferences {
    section("Which Accelerometer?"){
        input "accelerometers", "capability.accelerationSensor", title: "Which", multiple: true  
    }
    section ("What Period of Time?"){
        input "frequency", "decimal", title: "Minutes", required: true
    }
    section("Send this message (optional, sends standard status message if not specified)"){
        input "messageText", "text", title: "Message Text", required: false
    }
    section("Via a push notification and/or an SMS message"){
        input "phone", "phone", title: "Phone Number (for SMS, optional)", required: false
        input "pushAndPhone", "enum", title: "Both Push and SMS?", required: false, metadata: [values: ["Yes","No"]]
    }
}

def installed()
{
    subscribe(accelerometers, "accelerometer.active", accelerometerActiveHandler)
}

def updated()
{
    unsubscribe()
    subscribe(accelerometer, "accerlometer.active", accelerometerActiveHandler)
}

def accelerationActiveHandler(evt) {
    def deltaMinues = "frequency"
    def timeAgo = new Date(now() - (60 * deltaMinutes))
    def recentEvents = accelerationSensor.eventsSince(timeAgo)
    log.trace "Found ${recentEvents?.size() ?: 0} events in the last $deltaMinutes minutes"
    def alreadySentSms = recentEvents.count { it.value && it.value == "active" } > 1

    if (alreadySentSms) {
        sendMessage
    } else {
        log.debug "did not happen twice"
    }
}

private sendMessage(evt) {
    def msg = messageText ?: defaultText(evt)
    log.debug "$evt.name:$evt.value, pushAndPhone:$pushAndPhone, '$msg'"

    if (!phone || pushAndPhone != "No") {
        log.debug "sending push"
        sendPush(msg)
    }
    if (phone) {
        log.debug "sending SMS"
        sendSms(phone, msg)
    }
}

I have FINALLY stopped getting errors while trying to just save the app. However now when I run it in the simulator I get the following error

(groovy.lang.GroovyRuntimeException: Ambiguous method overloading for method script14063079272841487926851#subscribe.
Cannot resolve which method to invoke for [null, class java.lang.String, null] due to overlapping prototypes between:
[interface java.util.Collection, class java.lang.String, class java.lang.String]
[class physicalgraph.app.InstalledSmartAppWrapper, class java.lang.String, interface java.util.Map]
[class physicalgraph.app.LocationWrapper, class java.lang.String, interface java.util.Map] @ line 50)

Thanks in advance.


(Geko) #2

Typo in subscribe(accelerometer,. Should be subscribe(accelerometers,


(Greg) #3

thanks geko! I’m not getting any errors now but but my app also isn’t doing anything after I trigger the virtual accelerometer


(Brian) #4

what happens if you log.debug frequency? decimal doesnt seem like the right data type. integer ?
Also log.debug timeAgo to see if you’re getting an expected time value


(Greg) #5

I’m not sure where I am supposed to put those things. I basically just cut and pasted the app together - other than the parts where I made the typo you found.

Really hoping these smart app work shops are what I need


(Brian) #6

Any time you populate a variable you can then debug it out to the console.

First frequency is already a variable declared in the preferences section. You do not need the line def deltaMinues = "frequency" since it is redundant as well as incorrectly formatted. If you kept it you would remove the quotes. As is, your line states that deltaMinutes is equal the literal string frequency.

Once you declare def timeAgo = new Date(now() - (60 * deltaMinutes)) go ahed and put log.debug "Delta Minutes = ${deltaMinutes} in the next line.
When you run the code you should get a value there that represents something useful to you. If it comes back in an oddly formatted number or string you have found your problem. I would also change input "frequency", "decimal", title: "Minutes", required: true to input "frequency", "integer", title: "Minutes", required: true


(Greg) #7

@docwisdom really appreciate you trying to help me.

I made the changes you suggested (or at least I think I did) but I can’t save the app without this error.

org.codehaus.groovy.control.MultipleCompilationErrorsException: startup failed:
script14066747004731989719373.groovy: 56: expecting anything but ‘’\n’’; got it anyway @ line 56, column 48.
lta Minutes = ${deltaMinutes}
^

1 error

I see nothing at column 48 other than } Here is the modified code.

preferences {
    section("Which Accelerometer?"){
        input "accelerometers", "capability.accelerationSensor", title: "Which", multiple: true  
    }
    section ("What Period of Time?"){
        input "frequency", "integer", title: "Minutes", required: true
    }
    section("Send this message (optional, sends standard status message if not specified)"){
        input "messageText", "text", title: "Message Text", required: false
    }
    section("Via a push notification and/or an SMS message"){
        input "phone", "phone", title: "Phone Number (for SMS, optional)", required: false
        input "pushAndPhone", "enum", title: "Both Push and SMS?", required: false, metadata: [values: ["Yes","No"]]
    }
}

def installed()
{
    subscribe(accelerometers, "accelerometer.active", accelerometerActiveHandler)
}

def updated()
{
    unsubscribe()
    subscribe(accelerometers, "accelerometer.active", accelerometerActiveHandler)
}

def accelerationActiveHandler(evt) {
    def timeAgo = new Date(now() - (60 * deltaMinutes))
    log.debug "Delta Minutes = ${deltaMinutes}
    def recentEvents = accelerationSensor.eventsSince(timeAgo)
    log.trace "Found ${recentEvents?.size() ?: 0} events in the last $deltaMinutes minutes"
    def alreadySentSms = recentEvents.count { it.value && it.value == "active" } > 1

    if (alreadySentSms) {
        sendMessage
    } else {
        log.debug "did not happen twice"
    }
}

private sendMessage(evt) {
    def msg = messageText ?: defaultText(evt)
    log.debug "$evt.name:$evt.value, pushAndPhone:$pushAndPhone, '$msg'"

    if (!phone || pushAndPhone != "No") {
        log.debug "sending push"
        sendPush(msg)
    }
    if (phone) {
        log.debug "sending SMS"
        sendSms(phone, msg)
    }
}

(skp19) #8

Are you missing a closing quote here?


(Brian) #9

@eparkerjr is right, you are missing the ending quote at log.debug "Delta Minutes = ${deltaMinutes}"
Sorry if my post had it chopped off.


(Greg) #10

Thanks @eparkerjr and @docwisdom

the quote fixed the save error. I ran through the simulator and only got this in the log, nothing else, tripped the virtual accelerometer several times.

12:44:05 PM:
trace
accelerometer.active from accelerometers was provided with null…creating subscription


(Brian) #11

Dang. I totally steered you in the wrong direction on the input format. integer needs to be replaced with number. I got my programming languages mixed up. Also in your trace line you need brackets around your variable for detalMinutes Thats why you are getting null.

log.trace "Found ${recentEvents?.size() ?: 0} events in the last ${deltaMinutes} minutes"


(Greg) #12

no problem, I just appreciate that you are trying to help me. Here is my updated code. and the logs. still getting null? and no notification.

preferences {
    section(“Which Accelerometer?”){
        input “accelerometers”, “capability.accelerationSensor”, title: “Which”, multiple: true  
    }
    section (“What Period of Time?”){
        input “frequency”, “number”, title: “Minutes”, required: true
    }
    section(“Send this message (optional, sends standard status message if not specified)”){
        input “messageText”, “text”, title: “Message Text”, required: false
    }
    section(“Via a push notification and/or an SMS message”){
        input “phone”, “phone”, title: “Phone Number (for SMS, optional)”, required: false
        input “pushAndPhone”, “enum”, title: “Both Push and SMS?”, required: false, metadata: [values: [“Yes”,“No”]]
    }
}

def installed()
{
    subscribe(accelerometers, “accelerometer.active”, accelerometerActiveHandler)
}

def updated()
{
    unsubscribe()
    subscribe(accelerometers, “accelerometer.active”, accelerometerActiveHandler)
}

def accelerationActiveHandler(evt) {
    def timeAgo = new Date(now() - (60 * deltaMinutes))
    log.debug “Delta Minutes = ${deltaMinutes}”
    def recentEvents = accelerationSensor.eventsSince(timeAgo)
    log.trace “Found ${recentEvents?.size() ?: 0} events in the last ${deltaMinutes} minutes”
    def alreadySentSms = recentEvents.count { it.value && it.value == “active” } > 1

if (alreadySentSms) {
        sendMessage
    } else {
        log.debug “did not happen twice”
    }
}

private sendMessage(evt) {
    def msg = messageText ?: defaultText(evt)
    log.debug “$evt.name:$evt.value, pushAndPhone:$pushAndPhone, ‘$msg’”

if (!phone || pushAndPhone != “No”) {
        log.debug “sending push”
        sendPush(msg)
    }
    if (phone) {
        log.debug “sending SMS”
        sendSms(phone, msg)
    }
}

3:38:39 PM:
trace
accelerometer.active from accelerometers was provided with null…creating subscription

3:38:39 PM:
trace
Tell me if it happens twice is attempting to unsubscribe from all events


3:38:38 PM:
trace
accelerometer.active from accelerometers was provided with null...creating subscription


3:38:38 PM:
trace
Tell me if it happens twice is attempting to unsubscribe from all events


3:38:38 PM:
trace
accelerometer.active from accelerometers was provided with null...creating subscription


3:38:38 PM:
trace
Tell me if it happens twice is attempting to unsubscribe from all events


3:38:38 PM:
trace
accelerometer.active from accelerometers was provided with null...creating subscription


3:38:38 PM:
trace
Tell me if it happens twice is attempting to unsubscribe from all events

(Brian) #13

typo in handler name and in capability

subscribe(accelerometers, "accelerometer.active", accelerometerActiveHandler)
def accelerationActiveHandler(evt) {

should be

subscribe(accelerometers, "acceleration.active", accelerometerActiveHandler)
def accelerometerActiveHandler(evt) {

your time calc also needs work…


(Brian) #14

I got close but its not counting properly, it only sees 1 event all the time. But I gotta head out, so work from here.

/**
 *  tell me if it happens twice
 *
 *  Copyright 2014 Brian Critchlow
 *
 *  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: "tell me if it happens twice",
    namespace: "docwisdom",
    author: "Brian Critchlow",
    description: "test",
    category: "",
    iconUrl: "https://s3.amazonaws.com/smartapp-icons/Convenience/Cat-Convenience.png",
    iconX2Url: "https://s3.amazonaws.com/smartapp-icons/Convenience/Cat-Convenience@2x.png")

preferences {
    section("Which Accelerometer?"){
        input "accelerometers", "capability.accelerationSensor", title: "Which", multiple: true  
    }
    section ("What Period of Time?"){
        input "deltaMinutes", "number", title: "Minutes", required: true
    }
    section("Send this message (optional, sends standard status message if not specified)"){
        input "messageText", "text", title: "Message Text", required: false
    }
    section("Via a push notification and/or an SMS message"){
        input "phone", "phone", title: "Phone Number (for SMS, optional)", required: false
        input "pushAndPhone", "enum", title: "Both Push and SMS?", required: false, metadata: [values: ["Yes","No"]]
    }
}

def installed()
{
    subscribe(accelerometers, "acceleration.active", accelerometerActiveHandler)
}

def updated()
{
    unsubscribe()
    subscribe(accelerometers, "acceleration.active", accelerometerActiveHandler)
}

def accelerometerActiveHandler(evt) { 
	def timeAgo = new Date(now() - (1000 * 60 * deltaMinutes).toLong())
    log.debug timeAgo
	def recentEvents = accelerometers.eventsSince(timeAgo)
	log.trace "Found ${recentEvents?.size() ?: 0} events in the last ${deltaMinutes} minutes"
    def alreadySentSms = recentEvents.count { it.value == "active" } > 1 
   
    if (alreadySentSms) {
        sendMessage
    } else {
        log.debug "did not happen twice"
    }
}

private sendMessage(evt) {
    def msg = messageText ?: defaultText(evt)
    log.debug "$evt.name:$evt.value, pushAndPhone:$pushAndPhone, '$msg'"

    if (!phone || pushAndPhone != "No") {
        log.debug "sending push"
        sendPush(msg)
    }
    if (phone) {
        log.debug "sending SMS"
        sendSms(phone, msg)
    }
}

(Greg) #15

I’ve looked at every other app I could find that has this type of language and I don’t see what’s wrong. Of course I didn’t see my typos earlier either.

the only thing I see is sometimes people used, but I tried it and it still only counts the one event

def alreadySentSms = recentEvents.count { it.value && it.value == “active” } > 1


(Brian) #16

Unfortunately its kinda throwing me too, maybe someone else from the community with more smartapp code experience can chime in.


(Greg) #17

thanks for all your help so far @docwisdom I hope someone else chimes in.


(Greg) #18

Just wanted to post in here to close the issue - this app was solved by @tslagle1