/*
* Notify Tile Device
*
* Licensed Virtual 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.
*
* Change History:
*
* Date Who What
* ---- --- ----
* 2021-01-06 thebearmay Original version 0.1.0
* 2021-01-07 thebearmay Fix condition causing a loss notifications if they come in rapidly
* 2021-01-07 thebearmay Add alternative date format
* 2021-01-07 thebearmay Add last5H for horizontal display
* 2021-01-07 thebearmay Add leading date option
* 2021-03-10 thebearmay Lost span tag with class=last5
* 2021-11-14 ArnB 2.0.0 Add capability Momentary an routine Push allowing a Dashboard switch to clear all messages.
* 2021-11-15 ArnB 2.0.0 Revise logic minimizing attributes and sendevents. Allow for 5 to 20 messages in tile. Insure tile is less than 1024
* 2021-11-16 ArnB 2.0.1 Fix: storing one less message than requested.
* correct
to
* Restore: attribute last5H as an optional preference.
* 2021-11-17 ArnB 2.0.2 Add conversion logic from original version in Update routine
* 2021-11-17 ArnB 2.0.3 Add logic when message count shinks rather than reconfigure
* 2021-11-18 ArnB 2.0.4 Add singleThreaded true
* 2021-11-18 thebearmay 2.0.5 Remove unused attributes from v1.x.x
* 2021-11-20 thebearmay Add option to only display time
* 2021-11-22 thebearmay make date time format a selectable option
* 2021-12-07 thebearmay add "none" as a date time format
* 2022-04-06 thebearmay fix max message state coming back as string
* 2022-09-15 thebearmay issue with clean install
* 2022-12-06 thebearmay additional date/time format
*/
import java.text.SimpleDateFormat
import groovy.transform.Field
static String version() { return '2.0.11' }
@Field sdfList = ["ddMMMyyyy HH:mm","ddMMMyyyy HH:mm:ss","ddMMMyyyy hh:mma", "dd/MM/yyyy HH:mm:ss", "MM/dd/yyyy HH:mm:ss", "dd/MM/yyyy hh:mma", "MM/dd/yyyy hh:mma", "MM/dd HH:mm", "MM/dd h:mma", "HH:mm", "H:mm","h:mma", "None"]
metadata {
definition (
name: "Notification Tile",
namespace: "thebearmay",
description: "Simple driver to act as a destination for notifications, and provide an attribute to display the last 5 on a tile.",
author: "Jean P. May, Jr.",
importUrl:"https://raw.githubusercontent.com/thebearmay/hubitat/main/notifyTile.groovy",
singleThreaded: true
) {
capability "Notification"
capability "Momentary"
capability "Configuration"
attribute "last5", "STRING"
attribute "last5H", "STRING"
}
}
preferences {
input("debugEnable", "bool", title: "Enable debug logging?")
input("sdfPref", "enum", title: "Date/Time Format", options:sdfList, defaultValue:"ddMMMyyyy HH:mm")
input("leadingDate", "bool", title:"Use leading date instead of trailing")
input("msgLimit", "number", title:"Number of messages from 5 to 20",defaultValue:5, range:5..20)
input("create5H", "bool", title: "Create horizontal message tile?")
}
void installed() {
if (debugEnable) log.trace "installed()"
state.lastLimit=0
configure()
}
void updated(){
if (debugEnable) log.trace "updated()"
if(debugEnable) runIn(1800,logsOff)
// V2.0.2 When converting from original version set state variables, adjust html in last5 to make it work with V2.0.0+
if (state?.msgCount == null)
{
state.lastLimit=5
wkTile=device.currentValue("last5")
int x = wkTile.lastIndexOf('');
if (x>0) //if there is anything in tile, adjust for v2.0.0
{
msgFilled=5
int i = wkTile.lastIndexOf('
');
if (debugEnable) log.debug "at While i: ${i} ${msgFilled}"
while (i>0 && msgFilled>0)
{
if (debugEnable) log.debug "in loop i: ${i} ${msgFilled}"
msgFilled--
wkTile = wkTile.substring(0, i) + ''
i = wkTile.lastIndexOf('
');
if (debugEnable) log.debug "out loop i: ${i} ${msgFilled}"
}
if (debugEnable) log.debug "done While i: ${i} ${msgFilled}"
sendEvent(name:"last5", value:wkTile)
state.msgCount=msgFilled
}
else
{ //process empty tile
if (debugEnable) log.debug "Initialize an empty tile"
state.msgCount=0
configure()
}
}
if(msgLimit == null) device.updateSetting("msgLimit",[value:5,type:"number"])
// V2.0.3 When new msgLimit less than prior(state) msgLimit adjust message and state values
if (state?.lastLimit.toInteger()>settings.msgLimit.toInteger())
{
wkTile=device.currentValue("last5")
msgFilled=state.msgCount.toInteger()
if (debugEnable) log.debug "Shinking tile count lastLimit ${state.lastLimit} newLimit ${settings.msgLimit} msgCount ${msgFilled}"
int i = wkTile.lastIndexOf('
');
while (i != -1 && msgFilled > settings.msgLimit.toInteger())
{
wkTile = wkTile.substring(0, i) + '';
msgFilled--
i = wkTile.lastIndexOf('
');
if (debugEnable) log.debug "looping on shrink msgCount ${msgFilled}"
}
state.msgCount=msgFilled
sendEvent(name:"last5", value:wkTile)
}
if (!settings.create5H)
sendEvent(name:"last5H", value:'')
state.lastLimit=settings.msgLimit
}
void configure() {
log.trace "configure()"
if(msgLimit == null) device.updateSetting("msgLimit",[value:5,type:"number"])
sendEvent(name:"last5", value:'')
sendEvent(name:"last5H", value:'')
state.msgCount=0
if(location.hub.firmwareVersionString >= "2.2.8.0") {
if(notify1){
device.deleteCurrentState("notify1")
device.deleteCurrentState("notify2")
device.deleteCurrentState("notify3")
device.deleteCurrentState("notify4")
device.deleteCurrentState("notify5")
}
}
}
void deviceNotification(notification){
if (debugEnable) log.debug "deviceNotification entered: ${notification}"
dateNow = new Date()
if(sdfPref == null) device.updateSetting("sdfPref",[value:"ddMMMyyyy HH:mm",type:"enum"])
if(sdfPref != "None") {
SimpleDateFormat sdf = new SimpleDateFormat(sdfPref)
if (leadingDate)
notification = sdf.format(dateNow) + " " + notification
else
notification += " " + sdf.format(dateNow)
}
// insert new message at beginning of last5 string
msgFilled = state.msgCount.toInteger()
if (msgFilled>0)
wkTile=device.currentValue("last5").replace('','' + notification + '
')
else
wkTile=device.currentValue("last5").replace('','' + notification)
// when msg count exceeds limit, purge last message
if (debugEnable) log.debug "deviceNotification2 msgFilled: ${msgFilled} msgLimit: ${settings.msgLimit}"
if (msgFilled < settings.msgLimit.toInteger())
msgFilled++
else
{
int i = wkTile.lastIndexOf('
');
if (i != -1)
wkTile = wkTile.substring(0, i) + '';
}
// Ensure tile length is less than 1024 and hopefully stop loops
int wkLen=wkTile.length()
while (wkLen > 1024 && msgFilled > 0)
{
if (debugEnable) log.debug "wkTile length ${wkLen}> 1024 truncating msgCount: ${msgFilled}"
int i = wkTile.lastIndexOf('
');
if (i != -1)
{
wkTile = wkTile.substring(0, i) + '';
msgFilled--
}
else
{
wkTile=''
msgFilled=0
}
wkLen=wkTile.length()
if (debugEnable) log.debug "Truncated wkTile length ${wkLen}, msgCount: ${msgFilled}"
}
// Update attributes and state
sendEvent(name:"last5", value: wkTile)
state.msgCount = msgFilled
if (settings.create5H)
sendEvent(name:"last5H", value: " ** "+wkTile.replaceAll("
"," ** ")+" ** ")
}
void logsOff(){
device.updateSetting("debugEnable",[value:"false",type:"bool"])
}
void push() {
configure()
}