/**
* Nest Camera
* Copyright (C) 2018, 2019 Anthony S..
* Author: Anthony Santilli (@tonesto7)
* Modified: 05/10/2020
*/
import java.text.SimpleDateFormat
import groovy.time.TimeCategory
preferences { }
String devVer() { return "2.0.5" }
metadata {
definition (name: "Nest Camera", author: "Anthony S.", namespace: "tonesto7", importUrl: "https://raw.githubusercontent.com/tonesto7/nst-manager-he/master/drivers/nstCamera.groovy") {
capability "Actuator"
capability "Sensor"
capability "Switch"
capability "Motion Sensor"
capability "Sound Sensor"
capability "Refresh"
//capability "Image Capture"
//capability "Video Camera"
//capability "Video Capture"
command "refresh"
command "poll"
//command "streamingOn"
//command "streamingOff"
command "toggleStreaming"
attribute "softwareVer", "string"
attribute "lastConnection", "string"
attribute "lastOnlineChange", "string"
// attribute "lastUpdateDt", "string"
attribute "isStreaming", "string"
attribute "audioInputEnabled", "string"
attribute "videoHistoryEnabled", "string"
attribute "motionPerson", "string"
attribute "publicShareEnabled", "string"
attribute "publicShareUrl", "string"
attribute "imageUrl", "string"
attribute "imageUrlHtml", "string"
attribute "animatedImageUrl", "string"
attribute "animatedImageUrlHtml", "string"
attribute "lastEventStart", "string"
attribute "lastEventEnd", "string"
attribute "lastEventType", "string"
attribute "lastEventZones", "string"
attribute "urlsexpire", "string"
attribute "apiStatus", "string"
attribute "onlineStatus", "string"
attribute "securityState", "string"
}
preferences {
input name: "motionOnPersonOnly", type: "bool", title: "Only Trigger Motion Events When Person is Detected?", defaultValue: false, displayDuringSetup: false
input name: "logEnable", type: "bool", title: "Enable debug logging", defaultValue: true
input name: "txtEnable", type: "bool", title: "Enable descriptionText logging", defaultValue: false
}
}
void logsOff(){
log.warn "${device?.displayName} debug logging disabled..."
device.updateSetting("logEnable",[value:"false",type:"bool"])
}
void initialize() {
log.trace "Device Initialized: (${device?.displayName})..."
if (!state.updatedLastRanAt || now() >= state.updatedLastRanAt + 2000) {
state.updatedLastRanAt = now()
state?.isInstalled = true
log.warn "debug logging is: ${logEnable} | description logging is: ${txtEnable}"
if (logEnable) { runIn(1800,logsOff) }
} else {
Logger("initialize(): Ran within last 2 seconds - SKIPPING", "trace", true)
}
state.remove("enRemDiagLogging")
}
void installed() {
log.trace "Device Installed: (${device?.displayName})..."
verifyDataAttr()
runIn(5, "initialize", [overwrite: true] )
}
void updated() {
log.trace "Device Updated: (${device?.displayName})..."
runIn(5, "initialize", [overwrite: true] )
}
void uninstalled() {
log.trace "Device Removed: (${device?.displayName})..."
}
void verifyDataAttr() {
if(!device?.getDataValue("manufacturer")) {
updateDataValue("manufacturer", "Nest")
}
if(!device?.getDataValue("model")) {
updateDataValue("model", device?.name as String)
}
}
def stateRemove(key) {
state.remove(key?.toString())
return true
}
def parse(String description) {
if (txtEnable) { log.debug "parse: ${description}" }
}
void poll() {
//log.trace "polling parent..."
parent?.refresh(this)
}
void refresh() {
poll()
}
void generateEvent(eventData) {
String dtNow = getDtNow()
//log.trace("processEvent Parsing data ${eventData}")
try {
// Logger("------------START OF API RESULTS DATA------------", "warn")
if(eventData) {
def results = eventData?.data
//log.debug "results: $results"
state?.restStreaming = true
state.motionSndChgWaitVal = eventData?.motionSndChgWaitVal ? eventData?.motionSndChgWaitVal.toInteger() : 60
state.nestTimeZone = eventData?.tz ?: null
publicShareUrlEvent(results?.public_share_url)
onlineStatusEvent(results?.is_online?.toString())
isStreamingEvent(results?.is_streaming)
securityStateEvent(eventData?.secState)
publicShareEnabledEvent(results?.is_public_share_enabled?.toString())
videoHistEnabledEvent(results?.is_video_history_enabled?.toString())
if(results?.last_is_online_change) { lastOnlineEvent(results?.last_is_online_change?.toString()) }
apiStatusEvent(eventData?.apiIssues)
audioInputEnabledEvent(results?.is_audio_input_enabled?.toString())
softwareVerEvent(results?.software_version?.toString())
def cur = device?.currentState("isStreaming")?.value.toString()
if(cur == "on") {
if(results?.snapshot_url) {
if(isStateChange(device, "imageUrl", results?.snapshot_url?.toString()) ) { // || isStateChange(device, "imageUrlHtml", results?.snapshot_url?.toString())) {
sendEvent(name: "imageUrl", value: results?.snapshot_url?.toString(), displayed: false)
sendEvent(name: 'imageUrlHtml', value: '', displayed: false)
}
}
if(results?.last_event) {
if(results?.last_event?.animated_image_url) {
if(isStateChange(device, "animatedImageUrl", results?.last_event?.animated_image_url?.toString()) ) { //|| isStateChange(device, "animatedImageUrlHtml", results?.last_event?.animated_image_url?.toString())) {
sendEvent(name: "animatedImageUrl", value: results?.last_event?.animated_image_url?.toString(), displayed: false)
sendEvent(name: "animatedImageUrlHtml", value: '', displayed: false)
sendEvent(name: "urlsexpire", value: results?.last_event?.urls_expire_time , displayed: false)
}
}
if(results?.last_event.start_time && results?.last_event.end_time) { lastEventDataEvent(results?.last_event, results?.activity_zones) }
}
}
lastUpdatedEvent(false)
lastCheckinEvent(dtNow)
}
return
}
catch (ex) {
log.error "generateEvent Exception: ${ex?.message}"
}
}
Integer getStateSize() { return state?.toString().length() }
Integer getStateSizePerc() { return (Integer)Math.round((stateSize/100000)*100) }
def getDevTypeId() { return device?.getDevTypeId() }
def getDataByName(String name) {
state[name] ?: device.getDataValue(name)
}
def getDeviceStateData() {
return getState()
}
def getTimeZone() {
def tz = null
if (location?.timeZone) { tz = location?.timeZone }
else { tz = state?.nestTimeZone ? TimeZone.getTimeZone(state?.nestTimeZone) : null }
return tz
}
void lastCheckinEvent(String checkin, sendEvt=false) {
def tf = new SimpleDateFormat("MMM d, yyyy - h:mm:ss a")
tf.setTimeZone(getTimeZone())
//Logger("lastCheckin: checkin: ${checkin}", "debug")
def regex1 = /Z/
String t0 = checkin.replaceAll(regex1, "-0000")
String lastConn = t0 ? tf?.format(Date.parse("E MMM dd HH:mm:ss z yyyy", t0)) : "Not Available"
state.lastConnection = lastConn
if(sendEvt) {
def lastChk = device.currentState("lastConnection")?.value
if(isStateChange(device, "lastConnection", lastConn)) {
// Logger("Last Nest Check-in was: (${lastConn}) | Previous State: (${lastChk})")
sendEvent(name: 'lastConnection', value: lastConn?.toString(), displayed: false)
}
}
}
void lastOnlineEvent(String dt) {
String lastOnlVal = device.currentState("lastOnlineChange")?.value
def tf = new SimpleDateFormat("MMM d, yyyy - h:mm:ss a")
tf.setTimeZone(getTimeZone())
//Logger("lastOnlineEvent: dt: ${dt}", "debug")
def regex1 = /Z/
String t0 = dt.replaceAll(regex1, "-0000")
String lastOnl = !t0 ? "Nothing To Show..." : tf?.format(Date.parse("yyyy-MM-dd'T'HH:mm:ss.SSSZ", t0))
if(isStateChange(device, "lastOnlineChange", lastOnl)) {
Logger("Last Online Change was: (${lastOnl}) | Previous State: (${lastOnlVal})")
sendEvent(name: 'lastOnlineChange', value: lastOnl, displayed: true, isStateChange: true)
}
}
void onlineStatusEvent(String isOnline) {
//Logger("onlineStatusEvent($isOnline)")
String prevOnlineStat = device.currentState("onlineStatus")?.value
String onlineStat = isOnline == "true" ? "online" : "offline"
if(isStateChange(device, "onlineStatus", onlineStat)) {
Logger("Online Status is: (${onlineStat}) | Previous State: (${prevOnlineStat})")
sendEvent(name: "onlineStatus", value: onlineStat.toString(), descriptionText: "Online Status is: ${onlineStat}", displayed: true, isStateChange: true, state: onlineStat)
}
}
void securityStateEvent(String sec) {
String val = ""
String oldState = device.currentState("securityState")?.value
if(sec) { val = sec }
if(isStateChange(device, "securityState", val)) {
Logger("Security State is (${val}) | Previous State: (${oldState})")
sendEvent(name: "securityState", value: val, descriptionText: "Location Security State is: ${val}", displayed: true, isStateChange: true, state: val)
}
}
void isStreamingEvent(isStreaming, override=false) {
//log.trace "isStreamingEvent($isStreaming)..."
String isOn = device.currentState("isStreaming")?.value
String isOnline = device.currentState("onlineStatus")?.value
String val = (isStreaming.toString() == "true") ? "on" : (isOnline.toString() != "online" ? "offline" : "off")
if(isStateChange(device, "isStreaming", val)) {
Logger("Camera Live Video Streaming is: (${val}) | Previous State: (${isOn})")
sendEvent(name: "isStreaming", value: val, descriptionText: "Camera Video Streaming is: ${val}", displayed: true, isStateChange: true, state: val)
sendEvent(name: "switch", value: (val == "on" ? val : "off"), displayed: false)
}
}
void audioInputEnabledEvent(on) {
String isOn = device.currentState("audioInputEnabled")?.value
String val = (on.toString() == "true") ? "Enabled" : "Disabled"
if(isStateChange(device, "audioInputEnabled", val)) {
Logger("Audio Input Status is: (${val}) | Previous State: (${isOn})")
sendEvent(name: "audioInputEnabled", value: val, descriptionText: "Audio Input Status is: ${val}", displayed: true, isStateChange: true, state: val)
}
}
void videoHistEnabledEvent(on) {
String isOn = device.currentState("videoHistoryEnabled")?.value
String val = (on.toString() == "true") ? "Enabled" : "Disabled"
if(isStateChange(device, "videoHistoryEnabled", val)) {
Logger("Video History Status is: (${val}) | Previous State: (${isOn})")
sendEvent(name: "videoHistoryEnabled", value: val, descriptionText: "Video History Status is: ${val}", displayed: true, isStateChange: true, state: val)
}
}
void publicShareEnabledEvent(on) {
String isOn = device.currentState("publicShareEnabled")?.value
String val = on ? "Enabled" : "Disabled"
if(isStateChange(device, "publicShareEnabled", val)) {
Logger("Public Sharing Status is: (${val}) | Previous State: (${isOn})")
sendEvent(name: "publicShareEnabled", value: val, descriptionText: "Public Sharing Status is: ${val}", displayed: true, isStateChange: true, state: val)
}
}
void softwareVerEvent(String ver) {
String verVal = device.currentState("softwareVer")?.value
if(isStateChange(device, "softwareVer", ver)) {
Logger("Firmware Version: (${ver}) | Previous State: (${verVal})")
sendEvent(name: 'softwareVer', value: ver, descriptionText: "Firmware Version is now v${ver}", displayed: false)
}
}
void lastEventDataEvent(data, actZones) {
// log.trace "lastEventDataEvent($data)"
def tf = new SimpleDateFormat("E MMM dd HH:mm:ss z yyyy")
tf.setTimeZone(getTimeZone())
//Logger("lastEventDataEvent 1", "debug")
String curStartDt = device?.currentState("lastEventStart")?.value ? tf?.format(Date.parse("E MMM dd HH:mm:ss z yyyy", device?.currentState("lastEventStart")?.value.toString())) : null
//Logger("lastEventDataEvent 2 curStartDt: ${curStartDt}", "debug")
String curEndDt = device?.currentState("lastEventEnd")?.value ? tf?.format(Date.parse("E MMM dd HH:mm:ss z yyyy", device?.currentState("lastEventEnd")?.value.toString())) : null
//Logger("lastEventDataEvent 2 curEndDt: ${curEndDt}", "debug")
def regex1 = /Z/
//Logger("lastEventData 3 data.start: ${data?.start_time}")
String t0 = data?.start_time ? data?.start_time.replaceAll(regex1, "-0000") : data?.start_time
String newStartDt = data?.start_time ? tf.format(Date.parse("yyyy-MM-dd'T'HH:mm:ss.SSSZ", t0)) : "Not Available"
//Logger("lastEventDataEvent 3 newStartDt: ${newStartDt}", "debug")
//Logger("lastEventData 3 data.end_time: ${data?.end_time}")
String t1 = data?.end_time ? data?.end_time.replaceAll(regex1, "-0000") : data?.end_time
String newEndDt = data?.end_time ? tf.format(Date.parse("yyyy-MM-dd'T'HH:mm:ss.SSSZ", t1)) : "Not Available"
//Logger("lastEventDataEvent 3 newEndDt: ${newEndDt}", "debug")
Boolean hasPerson = data?.has_person ? data?.has_person?.toBoolean() : false
Boolean hasMotion = data?.has_motion ? data?.has_motion?.toBoolean() : false
Boolean hasSound = data?.has_sound ? data?.has_sound?.toBoolean() : false
def evtZoneIds = data?.activity_zone_ids
String evtZoneNames = (String)null
String evtType = (!hasMotion ? "Sound Event" : "Motion Event") + "${hasPerson ? " (Person)" : ""}" + "${hasSound ? " (Sound)" : ""}"
if(actZones && evtZoneIds) {
state?.activityZones = actZones?.collect { it?.name }
evtZoneNames = actZones.findAll { it?.id.toString() in evtZoneIds }.collect { it?.name }
String zstr = ""
Integer i = 1
evtZoneNames?.sort()?.each {
zstr += "${(i > 1 && i <= evtZoneNames?.size()) ? "
" : ""}${it}"
i = i+1
}
}
state.lastEventDate = formatDt2(Date.parse("yyyy-MM-dd'T'HH:mm:ss.SSSZ", t0), "MMMMM d, yyyy")
state.lastEventTime = "${formatDt2(Date.parse("yyyy-MM-dd'T'HH:mm:ss.SSSZ", t0), "h:mm:ssa")} to ${formatDt2(Date.parse("yyyy-MM-dd'T'HH:mm:ss.SSSZ", t1), "h:mm:ssa")}"
if(state?.lastEventData) { state.lastEventData == null }
Boolean tryPic = false
if(!evtZoneNames) evtZoneNames = "not set"
if(!state?.lastCamEvtData || (curStartDt != newStartDt || curEndDt != newEndDt) || isStateChange(device, "lastEventType", evtType) || isStateChange(device, "lastEventZones", evtZoneNames)) {
if(hasPerson || hasMotion || hasSound) {
//log.debug "curStartDt: $curStartDt | curEndDt: $curEndDt || newStartDt: $newStartDt | newEndDt: $newEndDt"
//log.debug "lastEventType: $evtType | lastEventZones: ${evtZoneNames.toString()}"
sendEvent(name: 'lastEventStart', value: newStartDt, descriptionText: "Last Event Start is ${newStartDt}", displayed: false)
sendEvent(name: 'lastEventEnd', value: newEndDt, descriptionText: "Last Event End is ${newEndDt}", displayed: false)
sendEvent(name: 'lastEventType', value: evtType, descriptionText: "Last Event Type was ${evtType}", displayed: false)
sendEvent(name: 'lastEventZones', value: evtZoneNames.toString(), descriptionText: "Last Event Zones: ${evtZoneNames}", displayed: false)
state.lastCamEvtData = ["startDt":newStartDt, "endDt":newEndDt, "hasMotion":hasMotion, "hasSound":hasSound, "hasPerson":hasPerson, "motionOnPersonOnly":(settings?.motionOnPersonOnly == true), "actZones":(data?.activity_zone_ids ?: null)]
if(data?.start_time && GetTimeDiffSeconds(newStartDt) < 180L) {
Logger("└────────────────────────────")
Logger("│ HasSound: (${hasSound})")
Logger("│ HasPerson: (${hasPerson})")
//Logger("│ Took Snapshot: (${tryPic})")
Logger("│ Zones: ${evtZoneNames ?: "None"}")
Logger("│ End Time: (${newEndDt})")
Logger("│ Start Time: (${newStartDt})")
Logger("│ Type: ${evtType}")
Logger("┌────────New Camera Event────────")
} else {
Logger("Start Time out of time range: (${newStartDt})")
}
}
}
motionSoundEvtHandler()
}
void motionSoundEvtHandler() {
def data = state?.lastCamEvtData
if(data) {
motionEvtHandler(data)
data = state?.lastCamEvtData
soundEvtHandler(data)
}
}
void motionEvtHandler(data) {
def tf = new SimpleDateFormat("E MMM dd HH:mm:ss z yyyy")
tf.setTimeZone(getTimeZone())
Date dtNow = new Date()
String curMotion = device.currentState("motion")?.value?.toString()
String motionStat = "inactive"
String motionPerStat = "inactive"
if(state?.restStreaming == true && data) {
if(data?.endDt && data?.hasMotion && !data?.sentMUpd) {
Long t0 = GetTimeDiffSeconds(data?.startDt, data?.endDt)
Integer t1 = state?.motionSndChgWaitVal ?: 4
Integer newDur = Math.min( Math.max(3, t0.toInteger()) , t1)
t0 = GetTimeDiffSeconds(data?.endDt)
Long howRecent = Math.max(1L, t0)
//Logger("MOTION NewDur: ${newDur} howRecent: ${howRecent}")
def tt0 = state?.lastCamEvtData
tt0.sentMUpd = true
state.lastCamEvtData = tt0
if(howRecent <= 60L) {
Boolean motGo = (data?.motionOnPersonOnly == true && data?.hasPerson != true) ? false : true
if(motGo) {
motionStat = "active"
if(data?.hasPerson) { motionPerStat = "active" }
runIn(newDur, "motionSoundEvtHandler", [overwrite: true])
}
}
/*
def newEndDt = null
use( TimeCategory ) {
newEndDt = Date.parse("E MMM dd HH:mm:ss z yyyy", data?.endDt.toString())+1.minutes
}
if(newEndDt) {
def motGo = (data?.motionOnPersonOnly == true && data?.hasPerson != true) ? false : true
if(newEndDt > dtNow && motGo) {
motionStat = "active"
if(data?.hasPerson) { motionPerStat = "active" }
runIn(state?.motionSndChgWaitVal.toInteger()+6, "motionSoundEvtHandler", [overwrite: true])
}
}
*/
}
}
if(isStateChange(device, "motion", motionStat) ) {
Logger("Motion Sensor is: (${motionStat}) | Person: (${motionPerStat}) | Previous State: (${curMotion})")
sendEvent(name: "motion", value: motionStat, descriptionText: "Motion Sensor is: ${motionStat}", displayed: true, isStateChange: true, state: motionStat)
}
if(isStateChange(device, "motionPerson", motionPerStat)) {
sendEvent(name: "motionPerson", value: motionPerStat, descriptionText: "Motion Person is: ${motionPerStat}", displayed: true, isStateChange: true, state: motionPerStat)
}
}
void soundEvtHandler(data) {
def tf = new SimpleDateFormat("E MMM dd HH:mm:ss z yyyy")
tf.setTimeZone(getTimeZone())
Date dtNow = new Date()
String curSound = device.currentState("sound")?.value?.toString()
String sndStat = "not detected"
if(state?.restStreaming == true && data) {
if(data?.endDt && data?.hasSound && !data?.sentSUpd) {
Long t0 = GetTimeDiffSeconds(data?.startDt, data?.endDt)
Integer t1 = state?.motionSndChgWaitVal ?: 4
Integer newDur = Math.min( Math.max(3, t0.toInteger()) , state?.motionSndChgWaitVal)
t0 = GetTimeDiffSeconds(data?.endDt)
Long howRecent = Math.max(1L, t0)
//Logger("SOUND NewDur: ${newDur} howRecent: ${howRecent}")
def tt0 = state?.lastCamEvtData
tt0.sentSUpd = true
state.lastCamEvtData = tt0
if(howRecent <= 60L) {
sndStat = "detected"
runIn(newDur, "motionSoundEvtHandler", [overwrite: true])
}
/*
def newEndDt = null
use( TimeCategory ) {
newEndDt = Date.parse("E MMM dd HH:mm:ss z yyyy", data?.endDt.toString())+1.minutes
}
if(newEndDt) {
if(newEndDt > dtNow) {
sndStat = "detected"
runIn(state?.motionSndChgWaitVal.toInteger()+6, "motionSoundEvtHandler", [overwrite: true])
}
}
*/
}
}
if(isStateChange(device, "sound", sndStat)) {
Logger("Sound Detector: (${sndStat}) | Previous State: (${curSound})")
sendEvent(name: "sound", value: sndStat, descriptionText: "Sound Sensor is: ${sndStat}", displayed: true, isStateChange: true, state: sndStat)
}
}
void apiStatusEvent(String issueDesc) {
String curStat = device.currentState("apiStatus")?.value
String newStat = issueDesc
if(isStateChange(device, "apiStatus", newStat)) {
Logger("API Status is: (${newStat.capitalize()}) | Previous State: (${curStat.toString().capitalize()})")
sendEvent(name: "apiStatus", value: newStat, descriptionText: "API Status is: ${newStat}", displayed: true, isStateChange: true, state: newStat)
}
}
void lastUpdatedEvent(Boolean sendEvt=false) {
Date now = new Date()
def tf = new SimpleDateFormat("MMM d, yyyy - h:mm:ss a")
tf.setTimeZone(getTimeZone())
String lastDt = tf.format(now)
state.lastUpdatedDt = lastDt
// state?.lastUpdatedDtFmt = formatDt(now)
if(sendEvt) {
String lastUpd = device.currentState("lastUpdatedDt")?.value
sendEvent(name: 'lastUpdatedDt', value: lastDt, displayed: false, isStateChange: true)
}
}
void publicShareUrlEvent(String url) {
//log.trace "publicShareUrlEvent($url)"
if(isStateChange(device, "publicShareUrl", url)) {
sendEvent(name: "publicShareUrl", value: url)
}
}
def getPublicVidID() {
def id = null
if(!state?.pubVidId && state?.public_share_url) {
id = state?.public_share_url.tokenize('/')[3].toString()
state?.pubVidId = id
} else {
id = state?.pubVidId
}
return id
}
String getRecTimeDesc(val) {
String result = null
if(val && val instanceof Integer) {
if(val.toInteger() > 24) {
def nVal = (val/24).toDouble().round(0) //
result = "${nVal.toInteger()} days"
} else {
result = "${val} hours"
}
}
return result
}
/************************************************************************************************
| DEVICE COMMANDS |
*************************************************************************************************/
void toggleStreaming() {
String cur = device?.currentState("isStreaming")?.value.toString()
if(cur == "on" || cur == "unavailable" || !cur) {
streamingOff(true)
} else {
streamingOn(true)
}
}
void streamingOn(Boolean manChg=false) {
try {
Logger("Sending Camera Stream ON Command...")
parent?.setCamStreaming(this, "true")
} catch (ex) {
log.error "streamingOn Exception: ${ex?.message}"
}
}
void streamingOff(Boolean manChg=false) {
try {
Logger("Sending Camera Stream OFF Command...")
parent?.setCamStreaming(this, "false")
} catch (ex) {
log.error "streamingOff Exception: ${ex?.message}"
}
}
void on() {
streamingOn()
}
void off() {
streamingOff()
}
void flip() {
Logger("Nest API Doesn't support the FLIP command...", "warn")
}
void mute() {
Logger("Nest API Doesn't support the MUTE command...", "warn")
}
void unmute() {
Logger("Nest API Doesn't support the UNMUTE command...", "warn")
}
/*******************************************************************************
| LOGGING FUNCTIONS |
********************************************************************************/
String lastN(String input, n) {
return n > input?.size() ? input : input[-n..-1]
}
void Logger(String msg, String logType = "debug") {
if(!logEnable || !msg) { return }
String smsg = "${device.displayName} (v${devVer()}) | ${msg}"
if(state?.enRemDiagLogging == null) {
state?.enRemDiagLogging = parent?.getStateVal("enRemDiagLogging")
if(state?.enRemDiagLogging == null) {
state?.enRemDiagLogging = false
}
//log.debug "set enRemDiagLogging to ${state?.enRemDiagLogging}"
}
if(state?.enRemDiagLogging) {
String theId = lastN(device.getId().toString(),5)
parent.saveLogtoRemDiagStore(smsg, logType, "Camera-${theId}")
} else {
switch (logType) {
case "trace":
log.trace "${msg}"
break
case "debug":
log.debug "${msg}"
break
case "info":
log.info "${msg}"
break
case "warn":
log.warn "${msg}"
break
case "error":
log.error "${msg}"
break
default:
log.debug "${msg}"
break
}
}
}
//This will Print logs from the parent app when added to parent method that the child calls
def log(message, level = "trace") {
Logger("PARENT_Log>> " + message, level)
return null // always child interface call with a return value
}
String getDtNow() {
Date now = new Date()
return formatDt(now)
}
def getSettingVal(var) {
if(var == null) { return settings }
return settings[var] ?: null
}
String formatDt(Date dt, Boolean mdy=false) {
//log.trace "formatDt($dt, $mdy)..."
String formatVal = mdy ? "MMM d, yyyy - h:mm:ss a" : "E MMM dd HH:mm:ss z yyyy"
def tf = new SimpleDateFormat(formatVal)
if(getTimeZone()) { tf.setTimeZone(getTimeZone()) }
return tf.format(dt)
}
String formatDt2(Date dt, String fmt=null) {
//log.trace "formatDt($dt, $mdy)..."
def tf = new SimpleDateFormat(fmt)
if(getTimeZone()) { tf.setTimeZone(getTimeZone()) }
return tf.format(dt)
}
Long GetTimeDiffSeconds(String strtDate, String stpDate=(String)null, String methName=null) {
//LogTrace("[GetTimeDiffSeconds] StartDate: $strtDate | StopDate: ${stpDate ?: "Not Sent"} | MethodName: ${methName ?: "Not Sent"})")
if((strtDate && !stpDate) || (strtDate && stpDate)) {
Date now = new Date()
String stopVal = stpDate ? stpDate : formatDt(now)
Long start = Date.parse("E MMM dd HH:mm:ss z yyyy", strtDate).getTime()
Long stop = Date.parse("E MMM dd HH:mm:ss z yyyy", stopVal).getTime()
Long diff = (stop - start) / 1000L //
//LogTrace("[GetTimeDiffSeconds] Results for '$methName': ($diff seconds)")
return diff
} else { return null }
}
/*
def epochToTime(tm) {
def tf = new SimpleDateFormat("h:mm a")
tf?.setTimeZone(getTimeZone())
return tf.format(tm)
}
def isTimeBetween(start, end, now, tz) {
def startDt = Date.parse("E MMM dd HH:mm:ss z yyyy", start).getTime()
def endDt = Date.parse("E MMM dd HH:mm:ss z yyyy", end).getTime()
def nowDt = Date.parse("E MMM dd HH:mm:ss z yyyy", now).getTime()
def result = false
if(nowDt > startDt && nowDt < endDt) {
result = true
}
return result
}
*/