Rule with timeout not acting as expected

The vehiclePresent device is custom hardware with a Zigbee "radio" and custom driver.
I wrote it some time ago and the system seemed to work. Recently I started working on why there was a delay.
The rule "asks" for an update measurement. and vehiclePresent should be forced to "null" after the asked for measurement was sent.

You will see I'm not a good groovy coder, so my code is likely far from optimum.

/**
 *  Garage Ultrasonic Sensor
 *
 * 2020-12-25 - v02b - "saves" in hubitat and can request measurement via device page button.
 *                      able to compare rec'd distance value to threshold
 *              v02c -  add events putting results in db
 *              v02e -  release candidate, still needs testing.
 *                      with v02e everything seems to work.
 *              v02f -  added distance status
 *              v02g -  converted to PresenceSensor due to issues with RM and (bool?) custom attributes
 *              v02h -  Changed the variable echo to echo for clarity.
 *              v02j -  added runin to clear Distance and Presence after 5 minutes (as they could be invalid)
 *                        won't work.  We will have to count #OK.
 *						send  @. to make measurement
 *				v03  -  Add variable to count number of measurements made
 *              v04a  - distance was an integer
 *
 *              todo -  transfer initial configure to Hub instead of Arduino.
 *                   -  add ability to change "ping." in cc2430 and #OK. in Arduino.
 *                   -
 *                   -  clean up some of the log commands etc
 *          Change vehicle present to enum   present, not present, null
 *
 */

import hubitat.device.HubAction
import hubitat.device.HubMultiAction
import hubitat.device.Protocol

metadata {
    definition (name: "Garage Ultrasonic v04a", namespace: "johnrob", author: "various") {
        capability "Actuator"       // our device has commands...
        capability "Sensor"         // our device has attributes...
        capability "PresenceSensor" // ENUM["present", "not present"]
        capability "Configuration"  // capability "Configuration"  commands: configure()

        command "requestMeasRM"

        attribute "vehiclePresent", "enum", ["present", "not present","null"]
        //attribute "someOtherName", "enum", ["light", "dark"]
        attribute "lastActivity", "String"
        attribute "distance", "number"
    }

    preferences {           // see: Hubitat Notes (HTTP, driver and app).docx for more input options (there are lots of them)
        input name: "threshold", type: "num", title: "Presence Threshold (cm)", defaultValue: 200, range: "50..250", required: false
        input name: "logEnable", type: "bool", title: "Enable debug logging", defaultValue: true
        input name: "txtEnable", type: "bool", title: "Enable descriptionecho logging", defaultValue: true
    }
}

// Parse incoming device messages to generate events
def parse(String description) {
    if (logEnable) log.debug " description is $description"
    state.lastRan = now()
//    runIn(300, clearOldData)   //seconds, watchdogAlarm,[overwrite: true])  // [] because overwrite is a map

    Map map = [:]

    def event = zigbee.getEvent(description)
    if (event) {
        if (txtEnable) log.debug " parsed zigbee event = '${event}"
        sendEvent(event)
    }

    else if (description?.startsWith("catchall:")) {
        if (logEnable) log.debug " catchall is $description"
    }


    else if (description?.startsWith("read attr -")) {          // our returned measurement is in this Map
        def descMap = zigbee.parseDescriptionAsMap(description)
        if (logEnable) log.debug " Desc Map: $descMap"
        if (descMap.clusterInt == 0) {
            def echo = descMap.value            // def = define untyped variable
            if (txtEnable) log.info " parsing '${echo}'"
            echo = echo.replace(".","").trim()
            if (echo.startsWith("!")) {
                echo = echo.replace("!","")
                sendEvent(name: "distance", value: echo, isStateChange: true, unit: "cm")

                int echoValue = Integer.parseInt(echo)
                int threshold = Integer.parseInt(threshold)

                if (txtEnable) log.info "echo=${echoValue}"

                if (echoValue > threshold) {
                    vehState = "not present"
                    log.info " > threshold}"
                }
                else{
                    vehState = "present"
                    if (txtEnable) log.info "${echo} < threshold}"
                }

                return sendEvent(name: "vehiclePresent", value: vehState, isStateChange: true)
            }
            if (echo.startsWith("ping")) return    // trailing . removed above
            else if (echo.startsWith("#OK")){
                clearOldData()        // by the time we get the next OK, the data will be obsolete.
                return
            }

            else log.warn "Not an attribute we can decode"
        }

    } // --- 2nd else if ---


    else {
        log.warn "DID NOT PARSE MESSAGE for description : $description"
        if (logEnable) log.debug zigbee.parseDescriptionAsMap(description)
    }

}   // --- parse ---

//def getecho(){ // read some attribute string from the device
//  if (txtEnable) log.info "gettext"
//    //zigbee.readAttribute(0x000, 0x0006) // gets the last thing the device tried to send to us
//    zigbee.readAttribute(0x000, 0x0010) // gets the last command the device heard us send
//}

def requestMeasRM() {
    sendHubCommand(new HubAction(sendtodevice("@."), Protocol.ZIGBEE))
}

def sendtodevice(String mystr){
    if (txtEnable) log.info "sending '${mystr}'"
    mystr=mystr.padRight(16,".") // mystr should be 16 bytes!
    def packed = hubitat.helper.HexUtils.byteArrayToHexString(mystr.getBytes())
    if (logEnable) log.info "sending '${mystr}', packed is ${packed}"

    def commandtosend = "he wattr 0x${device.deviceNetworkId} 8 0x000 0x010 0x42 {10"+packed+"}" // SAMPLELIGHT_ENDPOINT is defined as 8 in device code // the 10 on the end means 16 bytes length
    if (logEnable) log.debug "$commandtosend"
    return commandtosend
}

def sendCommand(String msg) {
    if (txtEnable) log.info "sendCommand - ${msg}"
    sendHubCommand(new HubAction(sendtodevice(msg), Protocol.ZIGBEE))  // "new" Creates a new HubAction object
}

def configure() {
    if (txtEnable) log.info "Configuring Reporting and Bindings."
    zigbee.onOffRefresh() + zigbee.onOffConfig()
}

def installed() {
    if (txtEnable) log.info "Executing 'installed()'"
    updated()
}

def initialize() {
    if (txtEnable) log.info "Executing 'initialize()'"
}

def updated() {
    if (txtEnable) log.info "Executing 'updated()'"

    if (logEnable) {
        log.info "Enabling Debug Logging for 30 minutes"
        runIn(1800,logsOff)
    } else {
        unschedule(logsoff)
    }
}

def now() {
    if(location.timeZone)
    now = new Date().format("yyyy MMM dd EEE h:mm:ss a", location.timeZone)
    else
    now = new Date().format("yyyy MMM dd EEE h:mm:ss a")
    sendEvent(name: "lastActivity", value: now, displayed:false)
    result
}

def clearOldData() {
     sendEvent(name: "distance", value: "null", isStateChange: true, unit: "cm")
     sendEvent(name: "vehiclePresent", value: "null", isStateChange: true)
}

//  --- eof ---