Skip to content

Commit

Permalink
No commit message
Browse files Browse the repository at this point in the history
  • Loading branch information
krlaframboise committed Dec 29, 2016
1 parent 4b95886 commit b90e57d
Showing 1 changed file with 90 additions and 45 deletions.
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/**
* Simple Event Logger - SmartApp v 1.0.1
* Simple Event Logger - SmartApp v 1.0.2
*
* Author:
* Kevin LaFramboise (krlaframboise)
Expand All @@ -9,6 +9,9 @@
*
* Changelog:
*
* 1.0.2 (12/29/2016)
* - Added additional logging and verification of the Web App Url.
*
* 1.0.1 (12/28/2016)
* - Bug fix for devices with null attributes
*
Expand Down Expand Up @@ -51,7 +54,7 @@ preferences {
page(name: "createTokenPage")
}

def version() { return "01.00.01" }
def version() { return "01.00.02" }
def gsVersion() { return "01.00.00" }

def mainPage() {
Expand Down Expand Up @@ -88,7 +91,7 @@ def mainPage() {
label title: "Assign a name", required: false
mode title: "Set for specific mode(s)", required: false
if (state.installed) {
getPageLink("aboutPageLink", "About Simple Event Logger", "aboutPage", null, "Tap to view documentation, version and additional information.")
getPageLink("aboutPageLink", "About Simple Event Logger", "aboutPage", null, "Tap to view documentation, version and additional information.", "https://raw.githubusercontent.com/krlaframboise/Resources/master/simple-event-logger/[email protected]")
}
}
section(" ") {
Expand Down Expand Up @@ -183,7 +186,7 @@ private getAttributesPageContent() {
paragraph "If there are some events that should't be logged for specific devices, use the corresponding event fields below to exclude them."
paragraph "You can also use the fields below to see which devices support each event."

settings.allowedAttributes.sort().each { attr ->
settings?.allowedAttributes?.sort()?.each { attr ->
def attrDevices = getSelectedDevices()?.findAll{ device ->
device.hasAttribute("${attr}")
}?.collect { it.displayName }?.unique()?.sort()
Expand Down Expand Up @@ -228,10 +231,12 @@ private getOptionsPageContent() {
defaultValue: true,
required: false
}
section("Google Sheets Web App") {
section("${getWebAppName()}") {
input "googleWebAppUrl", "text",
title: "Google Sheets Web App Url:\n\n(A popup box with a URL is shown after Deploying the Google Sheets Script. Copy and paste that entire URL into this field.)",
title: "${getWebAppName()} Url",
required: true
paragraph "The url you enter into this field needs to start with: ${getWebAppBaseUrl()}"
paragraph "If your url does not start like that, go back and copy it from the Script Editor Publish screen in the Google Sheet."
}

if (state.installed) {
Expand Down Expand Up @@ -267,7 +272,7 @@ def createTokenPage() {
}
}

private getPageLink(linkName, linkText, pageName, args=null,desc="") {
private getPageLink(linkName, linkText, pageName, args=null,desc="",image=null) {
def map = [
name: "$linkName",
title: "$linkText",
Expand All @@ -278,6 +283,9 @@ private getPageLink(linkName, linkText, pageName, args=null,desc="") {
if (args) {
map.params = args
}
if (image) {
map.image = image
}
href(map)
}

Expand All @@ -302,7 +310,7 @@ private disposeAppEndpoint() {
revokeAccessToken()
}
catch (e) {
log.warn "Unable to remove access token: $e"
logWarn "Unable to remove access token: $e"
}
state.endpoint = ""
}
Expand All @@ -323,11 +331,12 @@ def updated() {

initializeAppEndpoint()

if (settings?.logFrequency && settings?.maxEvents && settings?.logDesc != null && settings?.googleWebAppUrl) {
if (settings?.logFrequency && settings?.maxEvents && settings?.logDesc != null && verifyWebAppUrl(settings?.googleWebAppUrl)) {
state.optionsConfigured = true
}
else {
logDebug "Unconfigured - Options"
state.optionsConfigured = false
}

if (settings?.allowedAttributes) {
Expand Down Expand Up @@ -358,28 +367,47 @@ def updated() {
}
}

private verifyWebAppUrl(url) {
if (!url) {
logDebug "The ${getWebAppName()} Url field is required"
return false
}
else if ("$url"?.toLowerCase()?.startsWith(getWebAppBaseUrl())) {
return true
}
else {
logWarn "The ${getWebAppName()} Url is not valid. Go back and copy the url from the Google Sheets Script Editor Publish page."
return false
}
}

// Requests the version from the Google Script and displays a warning if it's not the expected version.
private verifyGSVersion() {
def actualGSVersion = ""

logTrace "Retrieving Google Script Code version of the Google Sheets Web App."
logTrace "Retrieving Google Script Code version of the ${getWebAppName()}"
try {
def params = [
uri: settings?.googleWebAppUrl
]

def params = [
uri: settings?.googleWebAppUrl
]
httpGet(params) { objResponse ->
if (objResponse?.status == 200) {
if ("${objResponse.data}" == "Version ${gsVersion()}") {
logTrace "The Google Web App is using the correct version of the Google Script code."
httpGet(params) { objResponse ->
if (objResponse?.status == 200) {
if ("${objResponse.data}" == "Version ${gsVersion()}") {
logTrace "The ${getWebAppName()} is using the correct version of the Google Script code."
}
else {
logWarn "The ${getWebAppName()} is not using version ${gsVersion()} of the Google Script code which is required by version ${version()} of the Simple Event Logger SmartApp.\n\nPlease update to the latest version of this SmartApp and the Google Script code to ensure that everything works properly.\n\nWhen deploying a new version of the Google Script Code in the Google Sheet, make sure you change the 'Product Version' field to 'New'."
}
}
else {
log.warn "The Google Sheet's Web App is not using version ${gsVersion()} of the Google Script code which is required by version ${version()} of the Simple Event Logger SmartApp.\n\nPlease update to the latest version of this SmartApp and the Google Script code to ensure that everything works properly.\n\nWhen deploying a new version of the Google Script Code in the Google Sheet, make sure you change the 'Product Version' field to 'New'."
logWarn "Unable to connect to the ${getWebAppName()}. Make sure you followed the instructions for setting up and testing it."
}
}
else {
log.warn "Unable to connect to the Google Sheets Web App. Make sure you followed the instructions for setting up and testing it."
}
}
}
catch(e) {
logWarn "Failed to retrieve Google Script Version. Error: ${e.message}"
}
}

def logNewEvents() {
Expand All @@ -404,9 +432,9 @@ def logNewEvents() {

def events = getNewEvents(startDate, endDate)
def eventCount = events?.size ?: 0
def actionMsg = eventCount > 0 ? ", posting them to Google Web App" : ""
def actionMsg = eventCount > 0 ? ", posting them to ${getWebAppName()}" : ""

logDebug "Found ${String.format('%,d', eventCount)} events between ${getFormattedLocalTime(startDate.time)} and ${getFormattedLocalTime(endDate.time)}${actionMsg}"
logDebug "SmartThings found ${String.format('%,d', eventCount)} events between ${getFormattedLocalTime(startDate.time)} and ${getFormattedLocalTime(endDate.time)}${actionMsg}"

if (events) {
postEventsToGoogleSheets(events)
Expand Down Expand Up @@ -436,7 +464,12 @@ private postEventsToGoogleSheets(events) {

// Google Sheets redirects the post to a temporary url so the response is usually 302 which is page moved.
def processLogEventsResponse(response, data) {
logTrace "Google Sheets Logging Response: ${response?.status}"
if (response?.status == 302) {
logTrace "${getWebAppName()} Response: ${response.status}"
}
else {
logWarn "Unexpected response from ${getWebAppName()}: ${response?.errorMessage}"
}
}

private initializeAppEndpoint() {
Expand All @@ -450,7 +483,7 @@ private initializeAppEndpoint() {
}
}
catch(e) {
log.warn "${getInitializeEndpointErrorMessage()}"
logWarn "${getInitializeEndpointErrorMessage()}"
state.endpoint = null
}
}
Expand Down Expand Up @@ -479,12 +512,12 @@ def api_updateLoggingStatus() {
status.freeSpace = data.freeSpace

if (data.error) {
logDebug "Google Sheets Reported: ${data.error}"
logDebug "${getWebAppName()} Reported: ${data.error}"
}
}
else {
status.success = false
logDebug "Logging Postback was empty."
logDebug "The ${getWebAppName()} postback has no data."
}
state.loggingStatus = status
logLoggingStatus()
Expand All @@ -493,10 +526,10 @@ def api_updateLoggingStatus() {
private logLoggingStatus() {
def status = getFormattedLoggingStatus()
if (state.loggingStatus?.success) {
logDebug "Logged ${status.eventsLogged} events between ${status.start} and ${status.end} in ${status.runTime}."
logDebug "${getWebAppName()} logged ${status.eventsLogged} events between ${status.start} and ${status.end} in ${status.runTime}."
}
else {
logDebug "Failed to log events between ${status.start} and ${status.end}."
logWarn "${getWebAppName()} failed to log events between ${status.start} and ${status.end}."
}

logTrace "Google Script Version: ${state.loggingStatus?.gsVersion}, Total Events Logged: ${status.totalEventsLogged}, Remaining Space Available: ${status.freeSpace}"
Expand All @@ -521,15 +554,15 @@ private getNewEvents(startDate, endDate) {

logTrace "Retrieving Events from ${startDate} to ${endDate}"

getSelectedDevices().each { device ->
getSelectedDevices()?.each { device ->

def deviceAllowedAttrs = getDeviceAllowedAttrs(device.displayName)
def deviceAllowedAttrs = getDeviceAllowedAttrs(device?.displayName)

device.eventsBetween(startDate, endDate, [max: maxEvents])?.flatten().each { event ->
device?.eventsBetween(startDate, endDate, [max: maxEvents])?.flatten()?.each { event ->

if ("${event?.source}" == "DEVICE" && deviceAllowedAttrs?.find { attr -> attr?.toLowerCase() == event?.name?.toLowerCase() }) {
events << [
time: getFormattedLocalTime(event.date.time),
time: getFormattedLocalTime(event.date?.time),
device: event.displayName,
name: event.name,
value: event.value,
Expand All @@ -539,7 +572,7 @@ private getNewEvents(startDate, endDate) {
}
}

return events.unique().sort { it.time }
return events?.unique()?.sort { it.time }
}

private getFormattedLocalTime(utcTime) {
Expand All @@ -554,7 +587,7 @@ private getFormattedLocalTime(utcTime) {
}

private getEventDesc(desc) {
if (settings?.logDesc && !desc.contains("device.displayName")) {
if (settings?.logDesc && !desc?.contains("device.displayName")) {
return desc
}
else {
Expand All @@ -566,9 +599,9 @@ private getDeviceAllowedAttrs(deviceName) {
def deviceAllowedAttrs = []

settings?.allowedAttributes?.each { attr ->
def attrExcludedDevices = settings."${attr}Exclusions"
def attrExcludedDevices = settings?."${attr}Exclusions"

if (!attrExcludedDevices.find { it.toLowerCase() == deviceName.toLowerCase() }) {
if (!attrExcludedDevices.find { it?.toLowerCase() == deviceName?.toLowerCase() }) {
deviceAllowedAttrs << "${attr}"
}
}
Expand All @@ -580,40 +613,40 @@ private getSupportedAttributes() {
def devices = getSelectedDevices()

if (devices) {
getAllAttributes().each { attr ->
if (devices?.find { it.hasAttribute("${attr}") }) {
getAllAttributes()?.each { attr ->
if (devices?.find { it?.hasAttribute("${attr}") }) {
supportedAttributes << "${attr}"
}
}
}

return supportedAttributes.unique().sort()
return supportedAttributes?.unique()?.sort()
}

private getAllAttributes() {
def attributes = []
getCapabilities().each { cap ->
if (cap.attr) {
if (cap?.attr) {
if (cap.attr instanceof Collection) {
cap.attr.each { attr ->
attributes << "${attr}"
}
}
else {
attributes << "${cap.attr}"
attributes << "${cap?.attr}"
}
}
}
return attributes
}

private getSelectedDeviceNames() {
return getSelectedDevices()?.collect { it.displayName}?.sort()
return getSelectedDevices()?.collect { it?.displayName }?.sort()
}

private getSelectedDevices() {
def devices = []
getCapabilities().each {
getCapabilities()?.each {
if (settings?."${it.cap}Pref") {
devices << settings?."${it.cap}Pref"
}
Expand Down Expand Up @@ -700,6 +733,14 @@ private averageSupportedAttributes() {
]
}

private getWebAppName() {
return "Google Sheets Web App"
}

private getWebAppBaseUrl() {
return "https://script.google.com/macros/s/"
}

long safeToLong(val, defaultVal=0) {
try {
if (val && (val instanceof Long || "${val}".isLong())) {
Expand Down Expand Up @@ -732,6 +773,10 @@ private logInfo(msg) {
}
}

private logWarn(msg) {
log.warn msg
}

private loggingTypeEnabled(loggingType) {
return (!settings?.logging || settings?.logging?.contains(loggingType))
}

0 comments on commit b90e57d

Please sign in to comment.