diff --git a/apps/echo-speaks.groovy b/apps/echo-speaks.groovy index 12985b1c..a92cece2 100644 --- a/apps/echo-speaks.groovy +++ b/apps/echo-speaks.groovy @@ -18,6 +18,8 @@ //file:noinspection unused //file:noinspection GroovySillyAssignment //file:noinspection GrMethodMayBeStatic +//file:noinspection GrUnnecessaryPublicModifier +//file:noinspection SpellCheckingInspection import groovy.json.JsonOutput @@ -29,8 +31,8 @@ import java.util.concurrent.Semaphore //************************************************ //* STATIC VARIABLES * //************************************************ -@Field static final String appVersionFLD = '4.2.2.0' -@Field static final String appModifiedFLD = '2022-12-22' +@Field static final String appVersionFLD = '4.2.2.1' +@Field static final String appModifiedFLD = '2023-07-16' @Field static final String gitBranchFLD = 'master' @Field static final String platformFLD = 'Hubitat' @Field static final Boolean devModeFLD = false @@ -84,6 +86,8 @@ import java.util.concurrent.Semaphore @Field static final String sASTR = 'a' @Field static final String sTSTR = 't' @Field static final List lSUNRISESET = ['sunrise', 'sunset'] +@Field static final Integer iZ = 0 +@Field static final Integer i1 = 1 //************************************************ //* IN-MEMORY ONLY VARIABLES * @@ -220,8 +224,8 @@ def mainPage() { section(sectHead("Companion Apps:")) { List zones = getZoneApps() List acts = getActionApps() - href "zonesPage", title: inTS1("Manage Zones${zones?.size() ? " (${zones?.size()} ${zones?.size() > 1 ? "Zones" : "Zone"})" : sBLANK}", "es_groups"), description: getZoneDesc() - href "actionsPage", title: inTS1("Manage Actions${acts?.size() ? " (${acts?.size()} ${acts?.size() > 1 ? "Actions" : "Action"})" : sBLANK}", "es_actions"), description: getActionsDesc() + href "zonesPage", title: inTS1("Manage Zones${zones?.size() ? " (${zones?.size()} ${zones?.size() > i1 ? "Zones" : "Zone"})" : sBLANK}", "es_groups"), description: getZoneDesc() + href "actionsPage", title: inTS1("Manage Actions${acts?.size() ? " (${acts?.size()} ${acts?.size() > i1 ? "Actions" : "Action"})" : sBLANK}", "es_actions"), description: getActionsDesc() } section(sectHead("Alexa Login Service:")) { @@ -296,7 +300,7 @@ def authStatusPage() { section(sectHead("Cookie Tools: (Tap to show)", getAppImg("cookie")), hideable: true, hidden: true) { String ckDesc = pastDayChkOk ? "This will Refresh your Amazon Cookie." : "It's too soon to refresh your cookie.\nMinimum wait is 24 hours!!" input "refreshCookieDays", "number", title: inTS1("Auto refresh cookie every?\n(in days)", "day_calendar"), description: "in Days (1-5 max)", required: true, range: '1..5', defaultValue: 5, submitOnChange: true - if(refreshCookieDays != null && refreshCookieDays < 1) { settingUpdate("refreshCookieDays", 1, "number") } + if(refreshCookieDays != null && refreshCookieDays < i1) { settingUpdate("refreshCookieDays", i1, "number") } if(refreshCookieDays != null && refreshCookieDays > 5) { settingUpdate("refreshCookieDays", 5, "number") } // Refreshes the cookie @@ -481,7 +485,7 @@ Boolean guardAutoConfigured() { } String guardAutoDesc() { - String str = sBLANK + String str; str = sBLANK if(guardAutoConfigured()) { str += spanSmBldBr("Guard Triggers:") str += (settings.guardAwayAlarm && settings.guardHomeAlarm) ? spanSmBr(" ${sBULLET} Using ${getAlarmSystemName()}") : sBLANK @@ -1174,9 +1178,9 @@ void appButtonHandler(String btn) { default: if(btn.contains("::")) { List items = btn.tokenize("::") - if(items && items.size() > 1 && items[1]) { - String k = (String)items[0] - String v = (String)items[1] + if(items && items.size() > i1 && items[i1]) { + String k = (String)items[iZ] + String v = (String)items[i1] switch(k) { case "executeRoutine": // log.debug "routine: ${rt[1]}" @@ -1267,7 +1271,7 @@ public Map seqItemsAvail() { def sequencePage() { return dynamicPage(name: "sequencePage", uninstall: false, install: false) { section(sectHead("Command Legend:"), hideable: true, hidden: true) { - String str1 = "Sequence Options:" + String str1; str1 = "Sequence Options:" ((Map)seqItemsAvailFLD.other).sort()?.each { String k, String v-> str1 += "${bulletItem(str1, "${k}${v != sNULL ? "::${v}" : sBLANK}")}" } @@ -1275,11 +1279,11 @@ def sequencePage() { // seqItemsAvailFLD.dnd?.sort()?.each { String k, String v-> // str4 += "${bulletItem(str4, "${k}${v != sNULL ? "::${v}" : sBLANK}")}" // } - String str2 = "Music Options:" + String str2; str2 = "Music Options:" ((Map)seqItemsAvailFLD.music).sort()?.each { String k, String v-> str2 += "${bulletItem(str2, "${k}${v != sNULL ? "::${v}" : sBLANK}")}" } - String str3 = "Canned TTS Options:" + String str3; str3 = "Canned TTS Options:" ((Map)seqItemsAvailFLD.speech).sort()?.each { String k, v-> String newV if(v instanceof List) { newV = sBLANK; v?.sort()?.each { newV += " ${dashItem(newV, "${it}", true)}" } } @@ -1324,14 +1328,14 @@ void executeAnnouncement() { String testMsg = (String)settings.test_announceMessage List sDevs = (Boolean)settings.test_announceAllDevices ? getChildDevicesByCap("announce") : getDevicesFromList((List)settings.test_announceDevices) if(sDevs?.size()) { - if(sDevs.size() > 1) { + if(sDevs.size() > i1) { List devObj = [] sDevs.each { devObj.push([deviceTypeId: (String)it?.getEchoDeviceType(), deviceSerialNumber: (String)it?.getEchoSerial()]) } // String devJson = new groovy.json.JsonOutput().toJson(devObj) // send to first one which will have Amazon fan it out - sDevs[0]?.sendAnnouncementToDevices(testMsg, "Echo Speaks Test", devObj, settings.test_announceVolume ?: null, settings.test_announceRestVolume ?: null) + sDevs[iZ]?.sendAnnouncementToDevices(testMsg, "Echo Speaks Test", devObj, settings.test_announceVolume ?: null, settings.test_announceRestVolume ?: null) } else { - sDevs[0]?.playAnnouncement(testMsg, "Echo Speaks Test", settings.test_announceVolume ?: null, settings.test_announceRestVolume ?: null) + sDevs[iZ]?.playAnnouncement(testMsg, "Echo Speaks Test", settings.test_announceVolume ?: null, settings.test_announceRestVolume ?: null) } } } @@ -1357,7 +1361,7 @@ Map executeTuneInSearch(String query) { contentType: sAPPJSON, timeout: 20 ] - Map results = [:] + Map results; results = [:] try { httpGet(params) { resp -> if(resp?.status != 200) logWarn("${resp?.status} $params") @@ -1500,7 +1504,7 @@ def updated() { if(!(Boolean)state.isInstalled) { state.isInstalled = true } if(!state.installData) { state.installData = [initVer: appVersionFLD, dt: getDtNow(), updatedDt: getDtNow(), shownDonation: false, sentMetrics: false] } unsubscribe() - state.clearCnt = 0 + state.clearCnt = iZ state.zoneEvtsActive = false unschedule() stateMigrationChk() @@ -1623,7 +1627,7 @@ void wsEvtHandler(Map evt) { List trigs = (List)evt.triggers Map atts = (Map)evt.attributes if("bluetooth" in trigs) { runIn(2, "getBluetoothRunIn") } // getBluetoothDevices(true) - if("activity" in trigs) { runIn(1, "getDeviceActivityRunIn") } // Map a=getDeviceActivity(sNULL, true) + if("activity" in trigs) { runIn(i1, "getDeviceActivityRunIn") } // Map a=getDeviceActivity(sNULL, true) if("notification" in trigs) { runIn(2, "getNotificationsRunIn") } if((Boolean)evt.all) { getEsDevices()?.each { eDev-> @@ -1880,7 +1884,7 @@ Boolean checkIfCodeUpdated() { } List cDevs = getEsDevices() if(cDevs?.size()) { - String ver = (String)cDevs[0]?.devVersion() + String ver = (String)cDevs[iZ]?.devVersion() if((String)codeVerMap.echoDevice != ver) { chgs.push("echoDevice") state.pollBlocked = true @@ -1899,7 +1903,7 @@ Boolean checkIfCodeUpdated() { // } List cApps = getActionApps() if(cApps?.size()) { - String ver = (String)cApps[0]?.appVersion() + String ver = (String)cApps[iZ]?.appVersion() if((String)codeVerMap.actionApp != ver) { chgs.push("actionApp") state.pollBlocked = true @@ -1909,7 +1913,7 @@ Boolean checkIfCodeUpdated() { } List zApps = getZoneApps() if(zApps?.size()) { - String ver; ver = (String)zApps[0]?.appVersion() + String ver; ver = (String)zApps[iZ]?.appVersion() if((String)codeVerMap.zoneApp != ver) { chgs.push("zoneApp") state.pollBlocked = true @@ -2044,7 +2048,7 @@ def storeCookieData() { String myId=app.getId() cookieDataFLD[myId] = cookieItems cookieDataFLD = cookieDataFLD - state.clearCnt = 0 + state.clearCnt = iZ } updServerItem("isLocal", (data.isLocal == true)) @@ -2074,8 +2078,8 @@ def storeCookieData() { def clearCookieD() { // deal with temporary problems Integer a; a = (Integer)state.clearCnt - a = a!= null ? a : 0 - a = a+1 + a = a!= null ? a : iZ + a = a+i1 state.clearCnt = a if(a > 5) clearCookieData('webCall', false) else logTrace("skipping server call to clearCookieData()") @@ -2092,7 +2096,7 @@ def clearCookieData(String src=sNULL, Boolean callSelf=false) { String myId=app.getId() cookieDataFLD[myId] = [:] cookieDataFLD = cookieDataFLD - state.clearCnt = 0 + state.clearCnt = iZ remTsVal(["lastCookieChkDt", "lastCookieRrshDt"]) unschedule("getEchoDevices") // unschedule("getOtherData") @@ -2196,7 +2200,7 @@ void clearServerAuth() { // log.debug "resp: ${resp.status} | data: ${resp?.data}" if(resp?.status != 200) logWarn("clearServerAuth: ${resp?.status} $params") if (resp?.status == 200) { - logInfo("Clear Server Auth Completed... | Process Time: (${execDt ? (wnow()-execDt) : 0}ms)") + logInfo("Clear Server Auth Completed... | Process Time: (${execDt ? (wnow()-execDt) : iZ}ms)") } } } @@ -2229,7 +2233,7 @@ def wakeupServerResp(response, data) { if(response?.status == 200) { updTsVal("lastServerWakeDt") if (rData && rData == "OK") { - logDebug("$rData wakeupServer Completed... | Process Time: (${data?.execDt ? (wnow()-data?.execDt) : 0}ms) | Source: (${data?.wakesrc}) ${data}") + logDebug("$rData wakeupServer Completed... | Process Time: (${data?.execDt ? (wnow()-data?.execDt) : iZ}ms) | Source: (${data?.wakesrc}) ${data}") if(data?.refreshCookie == true) { runIn(2, "cookieRefresh") } if(data?.updateGuard == true) { runIn(2, "checkGuardSupportFromServer") } } else { @@ -2268,11 +2272,11 @@ def cookieRefreshResp(response, data) { Map rData = response?.data ? parseJson(response?.data?.toString()) : null // log.debug "rData: $rData" if (rData && rData?.result && rData?.result?.size()) { - logInfo("Amazon Cookie Refresh Completed | Process Time: (${data?.execDt ? (wnow()-data?.execDt) : 0}ms)") + logInfo("Amazon Cookie Refresh Completed | Process Time: (${data?.execDt ? (wnow()-data?.execDt) : iZ}ms)") cMsg = "Amazon Cookie was Refreshed Successfully!!!" // log.debug "refreshAlexaCookie Response: ${rData?.result}" } else { - logWarn("Amazon Cookie Refresh Completed with NO DATA ${rData} | Process Time: (${data?.execDt ? (wnow()-data?.execDt) : 0}ms)") + logWarn("Amazon Cookie Refresh Completed with NO DATA ${rData} | Process Time: (${data?.execDt ? (wnow()-data?.execDt) : iZ}ms)") cMsg = "Amazon Cookie was Completed with NO DATA" } } @@ -2306,7 +2310,7 @@ Boolean validateCookie(Boolean frc=false) { Map params = [ uri: getAmazonUrl(), path: "/api/bootstrap", - query: ["version": 0], + query: ["version": iZ], headers: getReqHeaderMap(true), contentType: sAPPJSON, timeout: 20, @@ -2562,9 +2566,9 @@ public updChildVers() { List cApps = getActionApps() List zApps = getZoneApps() List eDevs = getEsDevices() - updCodeVerMap("actionApp", cApps?.size() ? cApps[0]?.appVersion() : null) - updCodeVerMap("zoneApp", zApps?.size() ? zApps[0]?.appVersion() : null) - updCodeVerMap("echoDevice", eDevs?.size() ? eDevs[0]?.devVersion() : null) + updCodeVerMap("actionApp", cApps?.size() ? cApps[iZ]?.appVersion() : null) + updCodeVerMap("zoneApp", zApps?.size() ? zApps[iZ]?.appVersion() : null) + updCodeVerMap("echoDevice", eDevs?.size() ? eDevs[iZ]?.devVersion() : null) String verZD zApps.each { if(!verZD) verZD= it?.relayDevVersion() } updCodeVerMap('zoneEchoDevice', verZD ?: sNULL) @@ -2643,7 +2647,7 @@ private void getNotifications(Boolean frc = false) { ] try { logTrace('getNotifications') - Map sData = null + Map sData; sData = null List newList = [] httpGet(params) { response-> sData = response?.data ?: null @@ -2730,10 +2734,10 @@ Map getBluetoothData(String serialNumber) { if(!isAuthValid("getBluetoothData")) { return [btObjs: [:], pairedNames: [], curConnName: sBLANK] } String myId=app.getId() // logTrace("getBluetoothData: ${serialNumber}") - String curConnName = sNULL + String curConnName; curConnName= sNULL Map btObjs = [:] getBluetoothDevices(true) - Map btData = bluetoothDataFLD[myId] + Map btData; btData = bluetoothDataFLD[myId] if(btData == null) { bluetoothDataFLD[myId] = [:] bluetoothDataFLD=bluetoothDataFLD @@ -2784,7 +2788,7 @@ Map getDeviceActivity(String serialNum, Boolean frc=false) { } else if (!serialNum) runIn(3, "getDeviceActivityRunIn") if(serialNum) { String appId=app.getId() - Map lastActData = devActivityMapFLD[appId] + Map lastActData; lastActData = devActivityMapFLD[appId] lastActData = lastActData ?: null // log.debug "activityData(IN): $lastActData" if(lastActData && (String)lastActData.serialNumber == serialNum) { @@ -2885,7 +2889,7 @@ void DnDResp(resp, data){ Boolean getDndEnabled(String serialNumber) { if(!isAuthValid("getDndEnabled")) { return false } String myId=app.getId() - Map sData = dndDataFLD[myId] + Map sData; sData= dndDataFLD[myId] if(sData == null) { getDoNotDisturb() sData = dndDataFLD[myId] @@ -2904,8 +2908,8 @@ public Map getAlexaRoutines(String autoId=sNULL) { String myId=app.getId() Integer lastU = getLastTsValSecs("alexaRoutinesUpdDt") - List rtList = [] - Map rtResp = [:] + List rtList; rtList = [] + Map rtResp; rtResp = [:] if(alexaRoutinesDataFLD[myId] && ( (autoId && lastU < 90) || (!autoId && lastU < 180) )) { rtList = alexaRoutinesDataFLD[myId] } else { @@ -2939,7 +2943,7 @@ public Map getAlexaRoutines(String autoId=sNULL) { // log.debug "alexaRoutines: $rtList" Map items = [:] - Integer cnt = 1 + Integer cnt; cnt = i1 if(rtList.size()) { if(autoId) { rtResp = ((List)rtList).find { it?.automationId?.toString() == autoId } ?: [:] @@ -3031,7 +3035,7 @@ void checkGuardSupport() { void checkGuardSupportResponse(response, data) { // log.debug "checkGuardSupportResponse Resp Size(${response?.data?.toString()?.size()})" - Boolean guardSupported = false + Boolean guardSupported; guardSupported = false try { if(response?.status != 200) logWarn("${response?.status} checkGuardSupportResponse") if(response?.status == 200) { @@ -3083,7 +3087,7 @@ void checkGuardSupportFromServer() { } void checkGuardSupportServerResponse(response, data) { - Boolean guardSupported = false + Boolean guardSupported; guardSupported = false try { if(response?.status != 200) { logWarn("checkGuardSupportServerResp: ${response?.status}") @@ -3147,11 +3151,12 @@ void getGuardState() { } } -void setGuardState(String guardState) { +void setGuardState(String iguardState) { Long execTime = wnow() String meth = "setGuardState" if(!isAuthValid("setGuardState")) { return } if(!(Boolean)state.alexaGuardSupported) { logError("Alexa Guard is either not enabled. or not supported by any of your devices"); return } + String guardState; guardState = iguardState guardState = guardStateConv(guardState) logDebug("setAlexaGuard($guardState)") try { @@ -3217,7 +3222,7 @@ void setGuardState(String guardState) { // } void respExceptionHandler(ex, String mName, Boolean ignOn401=false, Boolean toAmazon=true, Boolean ignNullMsg=false) { - String toMsg = "Amazon" + String toMsg; toMsg = "Amazon" if(!toAmazon) { toMsg = "Echo Speaks Server" } if(ex) { String stackTr @@ -3418,7 +3423,7 @@ void receiveEventData(Map evtData, String src) { String myId=app.getId() //String wsChildHandlerName = "Echo Speaks WS" - String nmS = 'echoSpeaks_websocket' + String nmS; nmS = 'echoSpeaks_websocket' // def oldWsDev = getChildDevice(nmS) // if(oldWsDev) { deleteChildDevice(nmS) } nmS = myId+'|'+nmS @@ -3434,8 +3439,8 @@ void receiveEventData(Map evtData, String src) { Map skippedDevices = [:] List unknownDevices = [] List curDevFamily = [] -// Integer cnt = 0 - String devAcctId = sNULL +// Integer cnt = iZ + String devAcctId; devAcctId = sNULL evtData?.echoDevices?.each { String echoKey, echoValue-> devAcctId = echoValue?.deviceAccountId logTrace("echoDevice | $echoKey | ${echoValue}") @@ -3502,8 +3507,8 @@ void receiveEventData(Map evtData, String src) { permissions["siriusXm"] = (((Map)evtData.musicProviders).containsKey("SIRIUSXM")) // permissions["tidal"] = true permissions["spotify"] = true //(echoValue?.capabilities.contains("SPOTIFY")) // Temporarily removed restriction check - permissions["isMultiroomDevice"] = (echoValue.clusterMembers && echoValue.clusterMembers?.size() > 0) ?: false - permissions["isMultiroomMember"] = (echoValue.parentClusters && echoValue.parentClusters?.size() > 0) ?: false + permissions["isMultiroomDevice"] = (echoValue.clusterMembers && echoValue.clusterMembers?.size() > iZ) ?: false + permissions["isMultiroomMember"] = (echoValue.parentClusters && echoValue.parentClusters?.size() > iZ) ?: false permissions["alarms"] = (echoValue.capabilities?.contains("TIMERS_AND_ALARMS")) permissions["reminders"] = (echoValue.capabilities?.contains("REMINDERS")) permissions["doNotDisturb"] = (echoValue.capabilities?.contains("SLEEP")) @@ -3518,7 +3523,7 @@ void receiveEventData(Map evtData, String src) { echoValue["guardStatus"] = ((Boolean)state.alexaGuardSupported && (String)state.alexaGuardState) ? (String)state.alexaGuardState : ((Boolean)permissions.guardSupported ? sUnknown : "Not Supported") echoValue["musicProviders"] = (Map)evtData.musicProviders echoValue["permissionMap"] = permissions - echoValue["hasClusterMembers"] = (echoValue.clusterMembers && echoValue.clusterMembers?.size() > 0) ?: false + echoValue["hasClusterMembers"] = (echoValue.clusterMembers && echoValue.clusterMembers?.size() > iZ) ?: false if(deviceStyleData?.n?.toString()?.toLowerCase()?.contains(sUNKNOWN)) { unknownDevices.push([ @@ -3547,7 +3552,7 @@ void receiveEventData(Map evtData, String src) { ] String dni = [app?.id, "echoSpeaks", echoKey].join("|") - def childDevice = getChildDevice(dni) + def childDevice; childDevice = getChildDevice(dni) String devLabel = "${(Boolean)settings.addEchoNamePrefix ? "Echo - " : sBLANK}${echoValue?.accountName}${echoValue?.deviceFamily == "WHA" ? " (WHA)" : sBLANK}" String childHandlerName = "Echo Speaks Device" Boolean autoRename = ((Boolean)settings.autoRenameDevices) @@ -3619,7 +3624,7 @@ public static Map minVersions() { } private Map getMinVerUpdsRequired() { - Boolean updRequired = false + Boolean updRequired; updRequired = false List updItems = [] Map codeItems = [server: "Echo Speaks Server", echoDevice: "Echo Speaks Device", wsDevice: "Echo Speaks Websocket", actionApp: "Echo Speaks Actions", zoneApp: "Echo Speaks Zones", zoneEchoDevice: "Echo Speaks Zone Device"] Map codeVers = (Map)state.codeVersions ?: [:] @@ -3683,8 +3688,8 @@ void removeDevices(Boolean all=false) { settingUpdate("cleanUpDevices", sFALSE, sBOOL) List devList = getDeviceList(true)?.collect { (String)[app?.id, "echoSpeaks", it?.key].join("|") } List items = ((List)app.getChildDevices())?.findResults { (all || (!all && !devList?.contains(it?.deviceNetworkId as String))) ? it?.deviceNetworkId as String : sNULL } - logWarn("removeDevices(${all ? "all" : sBLANK}) | In Use: (${all ? 0 : devList.size()}) | Removing: (${items.size()})", true) - if(items.size() > 0) { + logWarn("removeDevices(${all ? "all" : sBLANK}) | In Use: (${all ? iZ : devList.size()}) | Removing: (${items.size()})", true) + if(items.size() > iZ) { items.each { String it -> deleteChildDevice(it) } } } catch (ex) { logError("Device Removal Failed: ${ex}", false, ex) } @@ -3697,11 +3702,13 @@ void execAsyncCmd(String method, String callbackHandler, Map params, Map otherDa } else { logError("execAsyncCmd Error | Missing a required parameter") } } +@SuppressWarnings('GrReassignedInClosureLocalVar') void sendAmazonCommand(String method, Map params, Map otherData=null) { String meth = "sendAmazonCommand ${method} ${params} ${otherData?.cmdDesc}" try { - def rData = null - def rStatus = null + def rData, rStatus + rData = null + rStatus = null logTrace(meth) switch(method) { case "POST": @@ -3798,7 +3805,7 @@ void sendZoneCmd(Map cmdData) { if(myCmd && znList && znList.size()) { List devObj = getZoneDevices(znList, myCmd in ['speak', 'speak_parallel'] ? "TTS" : "announce") - String newmsg = (String)cmdData.message + String newmsg; newmsg = (String)cmdData.message String title = (String)cmdData.title Integer volume = (Integer)cmdData.changeVol Integer restoreVolume = (Integer)cmdData.restoreVol @@ -3827,12 +3834,12 @@ void sendZoneCmd(Map cmdData) { */ void sendDevObjCmd(List odevObj, String myCmd, String title, String imsg, Integer volume, Integer restoreVolume){ List devObj = odevObj.unique() // remove any duplicate devices - String newmsg=imsg - String origMsg = newmsg - if(devObj.size() == 0) { - logWarn("sendDevObjCmd NO DEVICES | cmd: $myCmd | devObj: $devObj | msg: ${newmsg} title: $title | volume: $volume | restoreVolume: $restoreVolume") - return - } + String newmsg; newmsg=imsg + String origMsg = newmsg + if(devObj.size() == iZ) { + logWarn("sendDevObjCmd NO DEVICES | cmd: $myCmd | devObj: $devObj | msg: ${newmsg} title: $title | volume: $volume | restoreVolume: $restoreVolume") + return + } //noinspection GroovyFallthrough switch(myCmd) { case "announcement": @@ -3966,7 +3973,7 @@ void sendSpeak(Map cmdMap, Map deviceData, String device, String callback, Boole account: cmdMap.account ] */ // Map st = [serialNumber: cmdMap.serialNumber, deviceType: cmdMap.deviceType] - List seqCmds = [] + List seqCmds; seqCmds = [] if(cmdMap.newVolume) { seqCmds.push([command: "volume", value: cmdMap.newVolume, deviceData: deviceData]) } seqCmds.push([command: 'sendspeak', value:cmdMap.message, deviceData:deviceData]) @@ -4008,7 +4015,7 @@ void queueSequenceCommand(String type, String command, value, Map deviceData=[:] void queueMultiSequenceCommand(List commands, String srcDesc, Boolean parallel=false, Map cmdMap=[:], String device=sNULL, String callback=sNULL) { //log.warn "commands: $commands srcDesc: $srcDesc parallel: $parallel cmdMap: $cmdMap device: $device" // expand speak commands and handle ssml - List newCmds = [] + List newCmds; newCmds = [] List seqCmds = commands seqCmds?.each { cmdItem-> // log.debug "cmdItem: $cmdItem" @@ -4048,12 +4055,12 @@ void addToQ(Map item) { releaseTheLock(sHMLF) - if(qsiz == 1) runInMillis(300L, "workQ") + if(qsiz == i1) runInMillis(300L, "workQ") else runIn(24, "workQB") List lmsg = [] String t = item.t - Boolean fir=true + Boolean fir; fir=true ['cmdMap', 'time', 'deviceData', 'device', 'callback', 'parallel', 'command', 'value', 'srcDesc', 'type'].each { String s -> def ss = item."${s}" if(ss) { @@ -4063,7 +4070,7 @@ void addToQ(Map item) { } } if(item.commands?.size()) { - Integer cnt = 1 + Integer cnt; cnt = i1 item.commands.each { cmd -> lmsg.push("addToQ (${item.t}) | Command(${cnt}): ${cmd}".toString()) cnt++ @@ -4082,37 +4089,38 @@ void workQ() { String appId=app.getId() Boolean aa = getTheLock(sHMLF, "addToQ(${item})") // log.trace "lock wait: ${aa}" - Boolean locked = true + Boolean locked; locked = true Map myMap = workQMapFLD[appId] ?: [:] - Boolean active = (Boolean)myMap.active + Boolean active; active = (Boolean)myMap.active if(active==null) { active = false; myMap.active=active; workQMapFLD[appId]=myMap; workQMapFLD=workQMapFLD } // log.debug "active: $active myMap: $myMap" - Long nextOk = (Long)myMap.nextOk ?: 0L + Long nextOk; nextOk = (Long)myMap.nextOk ?: 0L if(nextOk < wnow()) nextOk = 0L Map memStore = historyMapFLD[appId] ?: [:] String k = 'cmdQ' List eData = (List)memStore[k] ?: [] - Boolean fnd = (eData.size() > 0) + Boolean fnd = (eData.size() > iZ) // if we are not doing anything grab next item off queue and start it; if(!active && wnow() > nextOk && fnd) { List lmsg = [] - Double msSum = 0.0D - List seqList = [] + Double msSum; msSum = 0.0D + List seqList; seqList = [] List activeD = [] - Map extData=[:] + Map extData; extData=[:] List extList = [] - Boolean oldParallel = null - Boolean parallel = false + Boolean oldParallel,parallel + oldParallel = null + parallel = false String srcDesc - Map seqObj=null - Integer mdelay = 0 + Map seqObj; seqObj=null + Integer mdelay; mdelay = iZ // lets try to join commands in single request to Alexa while(eData.size()>0){ @@ -4121,7 +4129,7 @@ void workQ() { String t=(String)item.t // Long tLong=(Long)item.time - Map cmdMap=[:] + Map cmdMap; cmdMap=[:] String device = (String)item.device String callback = (String)item.callback srcDesc = sNULL @@ -4132,8 +4140,8 @@ void workQ() { List seqCmds = (List)item.commands if(srcDesc == 'ExecuteRoutine'){ - if(seqList.size() > 0) break // execute runs by itself - Map seqMap = (Map)seqCmds[0].command // already have a sequence map + if(seqList.size() > iZ) break // execute runs by itself + Map seqMap = (Map)seqCmds[iZ].command // already have a sequence map seqObj = sequenceBuilder(seqMap, null, null) if(oldParallel == null) oldParallel = parallel } else { @@ -4147,7 +4155,7 @@ void workQ() { //log.debug "seqCmds: $seqCmds" seqList = seqList + multiSequenceListBuilder(seqCmds) - if(!parallel) mdelay = 0 + if(!parallel) mdelay = iZ seqCmds?.each { cmdItem-> //log.debug "cmdItem: $cmdItem" if(cmdItem.command instanceof String){ @@ -4181,7 +4189,7 @@ void workQ() { def value = item.value if(command in ['announcement_devices'] ) { - if(seqList.size() > 0) break // this command runs alone so finish off what we are planning to do + if(seqList.size() > iZ) break // this command runs alone so finish off what we are planning to do seqObj = sequenceBuilder(command, value, deviceData) } else { seqList = seqList + [createSequenceNode(command, value, deviceData)] @@ -4199,7 +4207,7 @@ void workQ() { updMemStoreItem(k, eData) if(t=='nop') { - if(seqList.size() > 0) { + if(seqList.size() > iZ) { lmsg.push("workQ found nop, processing current list") break // finish off what we are planning to do } @@ -4213,7 +4221,7 @@ void workQ() { Map t_extData =[:] if(device && callback) { - String nstr = cmdMap?.message?.toString() + String nstr; nstr = cmdMap?.message?.toString() nstr = nstr?.trim() Boolean isSSML = (nstr?.toString()?.startsWith("") && nstr?.endsWith("")) //if(isSSML) nstr = nstr[7..-9] @@ -4235,8 +4243,8 @@ void workQ() { extList.push(t_extData) extData.extList = extList - Double ms = ((cmdMap?.msgDelay ?: 0.5D) * 1000.0D) - ms = Math.min(240000, Math.max(ms, 0)) // at least 0, max 240 seconds + Double ms; ms = ((cmdMap?.msgDelay ?: 0.5D) * 1000.0D) + ms = Math.min(240000, Math.max(ms, iZ)) // at least 0, max 240 seconds msSum = parallel ? ms : msSum + ms lmsg.push("workQ ms delay is $msSum".toString()) @@ -4245,7 +4253,7 @@ void workQ() { } } - if(seqList.size() > 0 || seqObj) { + if(seqList.size() > iZ || seqObj) { Integer mymin = 3000 // min ms between Alexa commands @@ -4289,11 +4297,11 @@ void workQ() { } } - Long t0 = wnow() + Long t0; t0 = wnow() mmsg = "workQ active: ${active} work items fnd: ${fnd} now: ${t0} nextOk: ${nextOk}" if(!active && fnd) { // if we have more work to do t0 = wnow() - Long ms = nextOk+200L - t0 + Long ms; ms = nextOk+200L - t0 if(ms <= 0L) ms = 4000 if(t0 < nextOk) { // if we are waiting between commands due to Alexa limits, schedule wakeup to resume runInMillis(ms, "workQF") @@ -4307,20 +4315,20 @@ void workQ() { // this does not handle SSML break commands // https://developer.amazon.com/en-US/docs/alexa/custom-skills/speech-synthesis-markup-language-ssml-reference.html Integer getMsgDur(String command, String type, String tv){ - Integer del = 0 + Integer del; del = iZ if(command in ['announcement_devices', 'announcement', 'announcementall'] || type in ['sendSpeak']) { String[] valObj = (tv?.contains("::")) ? tv.split("::") : ["Echo Speaks", tv] - String nstr = valObj[1].trim() + String nstr; nstr = valObj[1].trim() nstr = nstr.replaceAll(/\s\s+/, sSPACE) //String nm = nstr.toString().replaceAll('<', '<').replaceAll('>', '>') //log.debug "getMsgDur $nm" - Boolean isSSML = (nstr?.startsWith("") && nstr?.endsWith("")) + Boolean isSSML; isSSML = (nstr?.startsWith("") && nstr?.endsWith("")) if(isSSML) nstr = nstr[7..-9] isSSML = (isSSML || command == 'ssml') String actMsg = isSSML ? nstr?.replaceAll(/<[^>]+>/, sBLANK) : cleanString(nstr) //nm = actMsg.toString().replaceAll('<', '<').replaceAll('>', '>') //log.debug "getMsgDur1 $nm" - Integer msgLen = actMsg?.length() ?: 0 + Integer msgLen = actMsg?.length() ?: iZ del = calcDelay(msgLen) if(devModeFLD) logTrace("getMsgDur res: $del | actMsg: ${actMsg} msgLen: $msgLen origLen: ${tv.length()} isSSML: ${isSSML} ($command, $type, $tv)") } @@ -4333,8 +4341,8 @@ Integer getMsgDur(String command, String type, String tv){ static Integer calcDelay(Integer msgLen=null, Boolean addRandom=false) { if(!msgLen) { return 30 } Integer twd = 2 - Integer v = (Integer)((msgLen <= 14 ? 1 : (msgLen / 14)) * twd) - Integer res=v + Integer v = (Integer)((msgLen <= 14 ? i1 : (msgLen / 14)) * twd) + Integer res; res=v Integer randomInt if(addRandom){ Random random = new Random() @@ -4348,9 +4356,9 @@ static Integer calcDelay(Integer msgLen=null, Boolean addRandom=false) { void finishWorkQ(response, extData){ String meth = 'finishWorkQ' logTrace "running "+meth - Integer statusCode=null + Integer statusCode; statusCode=null def sData - String respMsg=sNULL + String respMsg; respMsg=sNULL try { statusCode = response?.status?.toInteger() if(response.hasError()){ @@ -4360,7 +4368,7 @@ void finishWorkQ(response, extData){ respExceptionHandler(ex, "finishWorkQ", true) } - Boolean retry=false + Boolean retry; retry=false if(statusCode == 200) updTsVal("lastSpokeToAmazon") else { logWarn("$meth | ${statusCode} | $respMsg | $extData") @@ -4387,7 +4395,7 @@ void finishWorkQ(response, extData){ Map memStore = historyMapFLD[appId] ?: [:] String k = 'active' - List activeD = (List)memStore[k] ?: [] + List activeD; activeD = (List)memStore[k] ?: [] if(retry) { log.warn "wanted to retry but did not" // String kk = 'cmdQ' @@ -4465,17 +4473,17 @@ static Map multiSequenceBuilder(List nodeList, Boolean parallel=false) { return seqMap } -static Integer getStringLen(String str) { return str?.length() ?: 0 } +static Integer getStringLen(String str) { return str?.length() ?: iZ } -private static List msgSeqBuilder(String str, Map deviceData, String cmdType) { - //String nm = str.toString().replaceAll('<', '<').replaceAll('>', '>') +private static List msgSeqBuilder(String istr, Map deviceData, String cmdType) { + //String nm = istr.toString().replaceAll('<', '<').replaceAll('>', '>') //log.debug "msgSeqBuilder: $nm" List seqCmds = [] - List strArr = [] - String nstr = str.trim() + List strArr; strArr = [] + String nstr = istr.trim() Boolean isSSML = (nstr.startsWith("") && nstr.endsWith("")) //if(isSSML) nstr = nstr[7..-9] - str = nstr + String str;str = nstr if(str.length() < 450) { seqCmds.push([command: (isSSML ? "ssml": "speak"), value: str, deviceData: deviceData, cmdType: cmdType]) } else { @@ -4495,7 +4503,7 @@ private static List msgSeqBuilder(String str, Map deviceData, String cmdType) { } String cleanString(String istr, Boolean frcTrans=false) { - String str=istr + String str; str=istr if(!str) { return sNULL } //String nm = str.toString().replaceAll('<', '<').replaceAll('>', '>') //log.debug "cleanString1: $nm" @@ -4513,7 +4521,7 @@ String cleanString(String istr, Boolean frcTrans=false) { } private String textTransform(String istr, Boolean force=false) { - String str=istr + String str; str=istr if(!force && (Boolean)settings.disableTextTransform) { return str } // Converts F temp values to readable text "19F" str = str.replaceAll(/([+-]?\d+)\s?([CcFf])/) { return "${it[0]?.toString()?.replaceAll("[-]", "minus ")?.replaceAll("[FfCc]", " degrees")}" } @@ -4541,7 +4549,7 @@ Map createSequenceNode(String command, value, Map deviceData = [:]) { //log.debug "createSequenceNode: value: $nm" //log.debug "createSequenceNode: deviceData: $deviceData " try { - Boolean remDevSpecifics = false + Boolean remDevSpecifics; remDevSpecifics = false String deviceType = deviceData?.deviceType ?: sNULL String serialNumber = deviceData?.serialNumber ?: sNULL String accountId = deviceData?.account ?: sNULL @@ -4851,7 +4859,7 @@ public void logsDisable() { public void activateChildAdvLogs() { String myId=app.getId() - Map myMap = childLogMapFLD[myId] + Map myMap; myMap = childLogMapFLD[myId] myMap = myMap ?: [:] Boolean a @@ -4937,7 +4945,7 @@ private void disableAdvChldLogs() { settingUpdate("childDeviceLogTrace", sFALSE, sBOOL) String myId=app.getId() - Map myMap = childLogMapFLD[myId] + Map myMap; myMap = childLogMapFLD[myId] myMap = myMap ?: [:] Boolean a = false myMap.childAppLogDebug = a @@ -4949,7 +4957,7 @@ private void disableAdvChldLogs() { } void missPollNotify(Boolean ion, Integer wait) { - Boolean on=ion + Boolean on; on=ion Integer lastDataUpd = getLastTsValSecs("lastDevDataUpdDt", 1000000) Integer lastMissPollM = getLastTsValSecs("lastMissedPollMsgDt") //if(devModeFLD) logTrace("missPollNotify() | on: ($on) | wait: ($wait) | getLastDevicePollSec: (${lastDataUpd}) | misPollNotifyWaitVal: (${settings.misPollNotifyWaitVal}) | getLastMisPollMsgSec: (${lastMissPollM})") @@ -4988,19 +4996,19 @@ void appUpdateNotify() { Boolean echoDevUpd = echoDevUpdAvail() // Boolean socketUpd = socketUpdAvail() Boolean servUpd = serverUpdAvail() - Boolean res=false + Boolean res; res=false if(appUpd || actUpd || zoneUpd || zoneChildDevUpd || echoDevUpd || socketUpd || servUpd) res=true Integer secs Integer updW - Boolean on=false + Boolean on; on=false if(res) { on = ((Boolean)settings.sendAppUpdateMsg) updW = settings.updNotifyWaitVal?.toInteger() if(updW == null) { updW = 43200; settingUpdate("updNotifyWaitVal", "43200", sENUM) } secs=getLastTsValSecs("lastUpdMsgDt") if(secs > updW && on) { - String str = sBLANK + String str; str = sBLANK str += !appUpd ? sBLANK : "\nEcho Speaks App: v${state.appData?.versions?.mainApp?.ver?.toString()}" str += !actUpd ? sBLANK : "\nEcho Speaks Actions: v${state.appData?.versions?.actionApp?.ver?.toString()}" str += !zoneUpd ? sBLANK : "\nEcho Speaks Zones: v${state.appData?.versions?.zoneApp?.ver?.toString()}" @@ -5043,7 +5051,7 @@ Boolean getOk2Notify() { Boolean smsOk = false Boolean pushOk = false Boolean pushOver = false - Boolean notifDevsOk = (((List)settings.notif_devs)?.size() > 0) + Boolean notifDevsOk = (((List)settings.notif_devs)?.size() > iZ) Boolean alexaMsg = ((Boolean)settings.notif_alexa_mobile) Boolean daysOk = (List)settings.notif_days ? (isDayOfWeek((List)settings.notif_days)) : true Boolean timeOk = notifTimeOk() @@ -5085,7 +5093,8 @@ Boolean notifTimeOk() { if(startTime && stopTime) { Boolean not = startTime.getTime() > stopTime.getTime() - Boolean isBtwn = !timeOfDayIsBetween((not ? stopTime : startTime), (not ? startTime : stopTime), now, mTZ()) + Boolean isBtwn + isBtwn = !timeOfDayIsBetween((not ? stopTime : startTime), (not ? startTime : stopTime), now, mTZ()) isBtwn = not ? !isBtwn : isBtwn logTrace("NotifTimeOk ${isBtwn} | CurTime: (${now}) is${!isBtwn ? " NOT": sBLANK} between (${not ? stopTime:startTime} and ${not ? startTime:stopTime})") return isBtwn @@ -5095,8 +5104,8 @@ Boolean notifTimeOk() { // Sends the notifications based on app settings public Boolean sendMsg(String msgTitle, String msg, Boolean showEvt=true, Map pushoverMap=null, sms=null, push=null) { logTrace("sendMsg() | msgTitle: ${msgTitle}, msg: ${msg}, showEvt: ${showEvt}") - String sentstr = sBLANK - Boolean sent = false + String sentstr; sentstr = sBLANK + Boolean sent; sent = false try { String newMsg = msgTitle+": "+msg String flatMsg = newMsg.replaceAll("\n", sSPACE) @@ -5134,7 +5143,7 @@ static String getPublicImg(String imgName) { return "https://raw.githubuserconte static String sectH3TS(String t, String st, String i = sNULL, String c=sCLR4D9) { return """

${i ? """ """ : sBLANK} ${t?.replaceAll("\\n", "
")}

${st ?: sBLANK}""" } public static String paraTS(String title = sNULL, String body = sNULL, String img = sNULL, Map tOpts=[s: 'normal', c: 'black', b: true, u:true], Map bOpts = [s:'normal', c: sNULL, b: false]) { - String s = sBLANK + String s; s = sBLANK s += title ? "
${img != sNULL ? """ """ : sBLANK}${title}
" : sBLANK s += body ? "
${body}
" : sBLANK return s @@ -5212,16 +5221,16 @@ String getLocalEndpointUrl(subPath) { return "${getLocalApiServerUrl()}/apps/${a Boolean showDonationOk() { return ((Boolean)state.isInstalled && !(Boolean)getInstData('shownDonation') && getDaysSinceUpdated() >= 30) } Integer getDaysSinceUpdated() { - String updDt = getInstData('updatedDt') + String updDt; updDt = getInstData('updatedDt') updDt = updDt ?: sNULL if(updDt == sNULL || updDt == "Not Set") { updInstData("updatedDt", getDtNow()) - return 0 + return iZ } else { Date start = Date.parse("E MMM dd HH:mm:ss z yyyy", updDt) Date stop = new Date() if(start && stop) { return (stop - start) } - return 0 + return iZ } } @@ -5253,7 +5262,7 @@ Boolean sendFirebaseData(String url, String path, String data, String cmdType=nu Boolean queueFirebaseData(String url, String path, String data, String cmdType=sNULL, String type=sNULL) { // logTrace("queueFirebaseData(${path}, ${data}, $cmdType, $type") - Boolean result = false + Boolean result; result = false String json = new JsonOutput().prettyPrint(data) Map params = [uri: url, path: path, requestContentType: sAPPJSON, contentType: sAPPJSON, timeout: 20, body: json] String typeDesc = type ?: "Data" @@ -5272,7 +5281,7 @@ Boolean queueFirebaseData(String url, String path, String data, String cmdType=s Boolean removeFirebaseData(String pathVal) { logTrace("removeFirebaseData(${pathVal})") - Boolean result = true + Boolean result; result = true try { httpDelete(uri: getFbMetricsUrl(), path: pathVal) { resp -> logDebug("Remove Firebase | resp: ${resp?.status}") @@ -5335,10 +5344,10 @@ private String createMetricsDataJson() { if(obj?.errors?.size()) { obj?.errors?.each { String k, v-> deviceErrorMap[k] = (deviceErrorMap[k] ? deviceErrorMap[k] + v : v) } } } Map actData = [:] - Integer actCnt = 0 + Integer actCnt; actCnt = iZ getActionApps()?.each { a-> actData[actCnt] = a?.getActionMetrics(); actCnt++ } Map zoneData = [:] - Integer zoneCnt = 0 + Integer zoneCnt; zoneCnt = iZ getZoneApps()?.each { a-> zoneData[zoneCnt] = a?.getZoneMetrics(); zoneCnt++ } Map dataObj = [ guid: (String)state.appGuid, @@ -5357,9 +5366,9 @@ private String createMetricsDataJson() { zones: zoneData, counts: [ deviceStyleCnts: (Map)state.deviceStyleCnts ?: [:], - appHeartbeatCnt: state.appHeartbeatCnt ?: 0, - getCookieCnt: state.getCookieCnt ?: 0, - appErrorCnt: state.appErrorCnt ?: 0, + appHeartbeatCnt: state.appHeartbeatCnt ?: iZ, + getCookieCnt: state.getCookieCnt ?: iZ, + appErrorCnt: state.appErrorCnt ?: iZ, deviceErrors: deviceErrorMap ?: [:], deviceUsage: deviceUsageMap ?: [:] ] @@ -5375,7 +5384,7 @@ private String createMetricsDataJson() { } void incrementCntByKey(String key) { - Long evtCnt = (Long)state."${key}" + Long evtCnt; evtCnt = (Long)state."${key}" evtCnt = evtCnt != null ? evtCnt : 0L evtCnt++ // logTrace("${key?.toString()?.capitalize()}: $evtCnt", true) @@ -5386,14 +5395,14 @@ void incrementCntByKey(String key) { // APP/DEVICE Version Functions // ****************************************** static Boolean codeUpdIsAvail(String newVer, String curVer, String type) { - Boolean result = false + Boolean result; result = false def latestVer if(newVer && curVer) { List versions = [newVer, curVer] if(newVer != curVer) { latestVer = versions?.max { a, b -> List verA = a?.tokenize('.'); List verB = b?.tokenize('.'); Integer commonIndices = Math.min(verA?.size(), verB?.size()) - for (Integer i = 0; i < commonIndices; ++i) { if(verA[i]?.toInteger() != verB[i]?.toInteger()) { return verA[i]?.toInteger() <=> verB[i]?.toInteger() } } + for (Integer i = iZ; i < commonIndices; ++i) { if(verA[i]?.toInteger() != verB[i]?.toInteger()) { return verA[i]?.toInteger() <=> verB[i]?.toInteger() } } verA?.size() <=> verB?.size() } result = (latestVer == newVer) @@ -5468,14 +5477,14 @@ private getWebData(Map params, String desc, Boolean text=true) { } -static Map getAvailableSounds() { +static Map getAvailableSounds() { return getAvailableSoundsFLD } // https://developer.amazon.com/en-US/docs/alexa/custom-skills/ask-soundlibrary.html // TODO: https://m.media-amazon.com/images/G/01/mobile-apps/dex/ask-tech-docs/ask-soundlibrary._TTH_.json // send this to speak command: