/*
* Hub Information Display
*
*
* 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, WIyTHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License
* for the specific language governing permissions and limitations under the License.
*
* Date Who Description
* ------------- ------------------- ---------------------------------------------------------
* 23Mar2025 thebearmay v0.0.1 - Original code
* 04Apr2025 v0.1.0 - Beta Ready Code
* 05Apr2025 v0.1.1 - Freememory fix for MB
* 07Apr2025 v0.1.2 - Add Memory History
* v0.1.3 - Fix graph sizes
* 08Apr2025 v0.1.4 - Change Windy URL
* 10Apr2025 v0.1.5 - Add CPU Temperature chart
* 12May2025 v0.1.6 - Add Full Screen option
* 25May2025 v0.1.7 - Change capability to device.HubInformationDriverv3
* 19Dec2025 v0.1.8 - Trap the start up error when the Hub Info device hasn't fully populated
*/
static String version() { return '0.1.8' }
import groovy.json.JsonSlurper
import groovy.json.JsonOutput
import groovy.transform.Field
//include thebearmay.uiInputElements
definition (
name: "Hub Detailed Information Display",
namespace: "thebearmay",
author: "Jean P. May, Jr.",
description: "App to combine the Hub Details page with information collected by the Hub Information Driver v3",
category: "Utility",
importUrl: "https://raw.githubusercontent.com/thebearmay/hubitat/main/apps/hubInfoDisp.groovy",
installOnOpen: true,
oauth: false,
iconUrl: "",
iconX2Url: ""
)
preferences {
page name: "pageRender"
page name: "configPage"
}
mappings {
/* path("/refresh") {
action: [POST: "refresh",
GET: "refresh"]
}
*/
}
def installed() {
// log.trace "installed()"
state?.isInstalled = true
initialize()
}
def updated(){
// log.trace "updated()"
if(!state?.isInstalled) { state?.isInstalled = true }
if(debugEnabled) runIn(1800,logsOff)
}
def initialize(){
}
void logsOff(){
app.updateSetting("debugEnabled",[value:"false",type:"bool"])
}
def configPage(){
dynamicPage (name: "configPage", title: "
"
return retVal
}
/*****************************************************************************
* Returns a string that will create an input enum or mode element for an app *
* *
* HashMap fields: *
* name - (required) name to store the input as a setting, no spaces or *
* special characters *
* type - (required) capability type, *
* title - displayed description for the input element *
* width - CSS descriptor for field width *
* background - CSS color descriptor for the input background color *
* color - CSS color descriptor for text color *
* fontSize - CSS text size descriptor *
* multiple - true/ *
* options - list of values for the enum (modes will autofill) *
* defaultValue - default for the field *
* radius - CSS border radius value (rounded corners) *
* hoverText - Text to display as a tool tip *
*****************************************************************************/
String inputEnum(HashMap opt){
String computedStyle = ''
if(opt.type == 'mode') opt.options = location.getModes()
if(opt.width) computedStyle += "width:${opt.width};min-width:${opt.width};"
if(opt.background) computedStyle += "background-color:${opt.background};"
if(opt.color) computedStyle += "color:${opt.color};"
if(opt.fontSize) computedStyle += "font-size:${opt.fontSize};"
if(opt.radius) computedStyle += "border-radius:${opt.radius};"
if(!opt.multiple) {
opt.multiple = false
mult = ' '
} else {
mult = 'multiple'
}
if(opt.hoverText && opt.hoverText != 'null')
opt.title ="${opt.title}
"
return retVal
}
/*****************************************************************************
* Returns a string that will create an input boolean element for an app *
* *
* HashMap fields: *
* name - (required) name to store the input as a setting, no spaces or *
* special characters *
* type - (required) capability type, *
* title - displayed description for the input element *
* width - CSS descriptor for field width *
* background - CSS color descriptor for the input background color *
* color - CSS color descriptor for text color *
* fontSize - CSS text size descriptor *
* defaultValue - default for the field *
* radius - CSS border radius value (rounded corners) *
* trackColor - CSS color descriptor for the switch track *
* switchColor - CSS color descriptor for the switch knob *
* hoverText - Text to display as a tool tip *
*****************************************************************************/
String inputBool(HashMap opt) {
if(!opt.name || !opt.type) return "Error missing name or type"
if(opt.hoverText && opt.hoverText != 'null')
opt.title ="${opt.title}
"
return retVal
}
/*****************************************************************************
* Returns a string that will create an input checkbox element for an app *
* *
* HashMap fields: *
* name - (required) name to store the input as a setting, no spaces or *
* special characters *
* type - (required) capability type, *
* title - displayed description for the input element *
* width - CSS descriptor for field width *
* background - CSS color descriptor for the input background color *
* color - CSS color descriptor for text color *
* fontSize - CSS text size descriptor *
* defaultValue - default for the field *
* radius - CSS border radius value (rounded corners) *
* cBoxColor - CSS color descriptor for the checkbox color *
* hoverText - Text to display as a tool tip *
*****************************************************************************/
String inputCheckbox(HashMap opt) {
if(!opt.name || !opt.type) return "Error missing name or type"
if(opt.hoverText && opt.hoverText != 'null')
opt.title ="${opt.title}
"
return retVal
}
/*****************************************************************************
* Returns a string that will create an button element for an app *
* *
* HashMap fields: *
* name - (required) name to identify the button, no spaces or *
* special characters *
* title - (required) button label *
* width - CSS descriptor for field width *
* background - CSS color descriptor for the input background color *
* color - CSS color descriptor for text color *
* fontSize - CSS text size descriptor *
* radius - CSS border radius descriptor (corner rounding) *
* hoverText - Text to display as a tool tip *
*****************************************************************************/
String buttonLink(HashMap opt) { //modified slightly from jtp10181's code
if(!opt.name || !opt.title )
return "Error missing name or title"
String computedStyle = 'cursor:pointer;text-align:center;box-shadow: 2px 2px 4px #71797E;'
if(opt.width) computedStyle += "width:${opt.width};min-width:${opt.width};"
if(opt.background) computedStyle += "background-color:${opt.background};"
if(opt.color) computedStyle += "color:${opt.color};"
if(opt.fontSize) computedStyle += "font-size:${opt.fontSize};"
if(opt.radius) computedStyle += "border-radius:${opt.radius};"
if(opt.hoverText && opt.hoverText != 'null')
opt.title ="${opt.title}
"
}
/*****************************************************************************
* Returns a string that will create an button element to hide/display a div *
* for an app *
* HashMap fields: *
* name - (required) name to identify the button, no spaces or *
* special characters *
* title - (required) button label *
* divName - (require) name of the division to hide or display *
* hidden - if true will hide the div immediately *
* width - CSS descriptor for field width *
* background - CSS color descriptor for the input background color *
* color - CSS color descriptor for text color *
* fontSize - CSS text size descriptor *
* radius - CSS border radius descriptor (corner rounding) *
*****************************************************************************/
String btnDivHide(HashMap opt) {
if(!opt.name || !opt.title || !opt.divName)
return "Error missing name, title or division"
String computedStyle = 'cursor:pointer;box-shadow: 2px 2px 4px #71797E;'
if(!opt.width) opt.width = '100%'
computedStyle += "width:${opt.width};"
if(opt.background) computedStyle += "background-color:${opt.background};"
if(opt.color) computedStyle += "color:${opt.color};"
if(opt.fontSize) computedStyle += "font-size:${opt.fontSize};"
if(opt.radius) computedStyle += "border-radius:${opt.radius};"
if(opt.destPage) {
inx = appLocation().lastIndexOf("/")
dest = appLocation().substring(0,inx)+"/${opt.destPage}"
} else if(opt.destUrl) {
dest=opt.destUrl
}
String btnElem = ""
String script= ""
if(opt.hidden){
btnElem = ""
script=""
}
opt.title = "${btnElem} ${opt.title}"
if(opt.hoverText && opt.hoverText != 'null')
opt.title ="${opt.title}