html+="""
"""
return (html.replace('\t', '').replace('\n', '').replace(' ', ''));
}
/********************************************************************************************************************************
*********************************************************************************************************************************
****************************************** END PAGES ********************************************************************************
*********************************************************************************************************************************
*********************************************************************************************************************************/
def getDays(str){
switch (str){
case "1 Day": return 1; break;
case "1 Week": return 7; break;
case "2 Weeks": return 14; break;
case "3 Weeks": return 21; break;
case "1 Month": return 30; break;
case "2 Months": return 60; break;
case "Indefinite": return 0; break;
}
}
def installed() {
initialize()
}
def uninstalled() {
if (state.endpoint) {
try {
revokeAccessToken()
}
catch (e) {
log.warn "Unable to revoke API access token: $e"
}
}
removeChildDevices(getChildDevices());
}
private removeChildDevices(delete) {
delete.each {deleteChildDevice(it.deviceNetworkId)}
}
def updated() {
log.debug("Updating Name to ${app_name}");
app.updateLabel(app_name);
if (install_device == true){
parent.hubiTool_create_tile(this, "tile");
}
if (lts){
switch (lts_update){
case "1:05 am": schedule("0 05 01 * * ?", longTermStorageUpdate); break;
case "2:30 am": schedule("0 30 02 * * ?", longTermStorageUpdate); break;
case "3:45 am": schedule("0 45 04 * * ?", longTermStorageUpdate); break;
case "4:55 am": schedule("0 55 04 * * ?", longTermStorageUpdate); break;
}
}
}
def processCallBack(response, data) {
}
def initialize() {
updated();
}
private getValue(id, attr, val){
def reg = ~/[a-z,A-Z]+/;
orig = val;
val = val.replaceAll("\\s","");
if (settings["attribute_${id}_${attr}_${val}"]!=null){
ret = Double.parseDouble(settings["attribute_${id}_${attr}_${val}"]);
} else {
try {
ret = Double.parseDouble(val - reg);
} catch (e) {
log.debug ("Bad value in Parse: "+orig);
ret = null;
}
}
return ret;
}
private cleanupData(data){
def then = new Date();
use (groovy.time.TimeCategory) {
then -= getDays(lts_time);
}
then_milliseconds = then.getTime();
return data.findAll{ it.date >= then_milliseconds };
}
private getAbbrev(unit){
switch (unit){
case "none": return "";
case "fahrenheit": return "°";
case "celsius": return "°";
case "kelvin": return "K";
case "meters_per_second": return "m/s";
case "miles_per_hour": return "mph";
case "knots": return "kn";
case "millimeters": return "mm";
case "inches": return '"';
case "degrees": return "°";
case "radians": return "rad";
case "cardinal": return "";
case "trend_numeric": return "";
case "trend_text": return "";
case "percent_numeric": return "%";
case "millibars": return "mbar";
case "millimeters_mercury": return "mmHg";
case "inches_mercury": return "inHg";
case "hectopascal": return "hPa";
case "kilometers_per_hour" : return "km/h";
}
return "";
}
private getUnits(unit, value){
if (unit == null) return [name: "unknown", var: "tbd", units: "none"];
try{
switch (unit.toLowerCase()){
case "f":
case "°f":
return [name: "Farenheit (°F)", var: "temperature", units: "fahrenheit"]; break;
case "c":
case "°c":
return [name: "Celsius (°C)", var: "temperature", units: "celcius"]; break;
case "mph":
return [name: "Miles per Hour (mph)", var: "velocity", units: "miles_per_hour"]; break;
case "m/s":
return [name: "Meters per Second (m/s)", var: "velocity", units: "meters_per_second"]; break;
case "in":
case '"':
return [name: 'Inches (")', var: "depth", units: "inches"]; break;
case "mm":
case '"':
return [name: 'Millimeters (mm)', var: "depth", units: "millimeters"]; break;
case "°":
case "deg":
return [name: "Degrees (°)", var: "direction", units: "degrees"]; break;
case "rad":
return [name: "Radians (°)", var: "direction", units: "radians"]; break;
case "inhg":
return [name: "Inches of Mercury (inHg)", var: "pressure", units: "inches_mercury"]; break;
case "mmhg":
return [name: "Millimeters of Mecury mmHg)", var: "pressure", units: "millimeters_mercury"]; break;
case "mbar":
return [name: "Millibars (mbar)", var: "pressure", units: "millibars"]; break;
case "km/h":
return [name: "Kilometers per hour (km/h)", var: "velocity", units: "kilometers_per_hour"]; break;
case "hPa":
return [name: "Hectopascal (hPa)", var:"pressure", units: "hectopascal"]; break;
case "%":
value = Double.parseDouble(value);
if (value > 1.0 && value < 100.0) {
return [name: "Percent (0 to 100)", var:"percent", units: "percent_numeric"];
} else if (value >=0.0 && value < 1.0) {
return [name: "Percent (0.1 to 1.0)", var: "percent", units: "percent_decimal"];
}
break;
default:
return [name: "unknown", var: "tbd", units: "none"]; break;
}
} catch (error) {
log.debug("Unable to find units: "+error);
}
}
def getIconList(){
return [
[name: "None", icon: "alpha-x-circle-outline"],
[name: "Cloudy", icon: "weather-cloudy"],
[name: "Cloudy Alert", icon: "weather-cloudy-alert"],
[name: "Cloudy Right Arrow", icon: "weather-cloudy-arrow-right"],
[name: "Fog", icon: "weather-fog"],
[name: "Hail", icon: "weather-hail"],
[name: "Hazy", icon: "weather-hazy"],
[name: "Hurricane", icon: "weather-hurricane"],
[name: "Lightning", icon: "weather-lightning"],
[name: "Lightning Raining", icon: "weather-lightning-rainy"],
[name: "Night", icon: "weather-night"],
[name: "Night Partly Cloudy", icon: "weather-night-partly-cloudy"],
[name: "Partly Cloudy", icon: "weather-partly-cloudy"],
[name: "Partly Lightning", icon: "weather-partly-lightning"],
[name: "Partly Raining", icon: "weather-partly-rainy"],
[name: "Partly Snowing", icon: "weather-partly-snowy"],
[name: "Partly Snowing Raining",icon: "weather-partly-snowy-rainy"],
[name: "Pouring", icon: "weather-pouring"],
[name: "Raining", icon: "weather-rainy"],
[name: "Snowing", icon: "weather-snowy"],
[name: "Heavy Snow", icon: "weather-snowy-heavy"],
[name: "Snowing Raining", icon: "weather-snowy-rainy"],
[name: "Sunny", icon: "weather-sunny"],
[name: "Sunny Alert", icon: "weather-sunny-alert"],
[name: "Sunny Off", icon: "weather-sunny-off"],
[name: "Sunset", icon: "weather-sunset"],
[name: "Sunset Down", icon: "weather-sunset-down"],
[name: "Sunset Up", icon: "weather-sunset-up"],
[name: "Tornado", icon: "weather-tornado"],
[name: "Windy", icon: "weather-windy"],
[name: "Windy 2", icon: "weather-windy-variant"],
[name: "Home Thermometer", icon: "home-thermometer-outline"],
[name: "Arrow Up", icon: "arrow-up-thick"],
[name: "Arrow Down", icon: "arrow-down-thick"],
[name: "Umbrella", icon: "umbrella-outline"],
[name: "Ruler", icon: "ruler"],
[name: "Cloud Question", icon: "cloud-question"],
[name: "Calendar", icon: "calendar-today"],
[name: "Tail Wind", icon: "tailwind"],
[name: "Compass", icon: "compass-outline"],
[name: "Gauge", icon: "gauge"],
[name: "Thermostat", icon: "thermostat"],
[name: "Water Percent", icon: "water-percent"],
[name: "Wave", icon: "wave"],
[name: "Snow", icon: "snowflake"],
[name: "Water", icon: "water"],];
}
def getWeatherData(){
def options = [
"tile_units": atomicState.unit_type,
"openweather_refresh_rate": openweather_refresh_rate ? openweather_refresh_rate : "300000",
"tiles" : atomicState.tile_settings,
"tile_type" : atomicState.tile_type,
"new_tile_dialog" : atomicState.newTileDialog,
"api_code" : "${state.endpointSecret}",
"url" : "${state.localEndpointURL}",
];
options.out_units = [:];
atomicState.unit_type.each {key, measurement->
options.out_units << [ "${key}" : settings["${key}_units"]];
}
return options;
}
def getMapData(map, loc){
splt = loc.tokenize('.');
cur = map;
splt.each{str->
try{
if (str.isNumber()){
num = str.toInteger();
cur = cur[num];
} else {
cur = cur[str];
}
} catch (e){
//log.debug(loc+": Cannot find data: "+e);
return -1;
}
}
return cur;
}
def applyDecimals(tile, val){
value = val.toString();
if (value.isNumber()){
num_decimals = tile.decimals
value = sprintf("%.${num_decimals}f", value.toFloat());
return value;
}
else return val;
}
def getWindDirection(direction) {
direction = Float.parseFloat(direction.toString());
if (direction > 348.75 || direction < 11.25) return "N";
if (direction >= 11.25 && direction < 33.75) return "NNE";
if (direction >= 33.75 && direction < 56.25) return "NE";
if (direction >= 56.25 && direction < 78.7) return "ENE";
if (direction >= 78.75 && direction < 101.25) return "E";
if (direction >= 101.25 && direction < 123.75) return "ESE";
if (direction >= 123.75 && direction < 146.25) return "SE";
if (direction >= 146.25 && direction < 168.75) return "SSE";
if (direction >= 168.75 && direction < 191.25) return "S";
if (direction >= 191.25 && direction < 213.75) return "SSW";
if (direction >= 213.75 && direction < 236.25) return "SW";
if (direction >= 236.25 && direction < 258.75) return "WSW";
if (direction >= 258.75 && direction < 281.25) return "W";
if (direction >= 281.25 && direction < 303.75) return "WNW";
if (direction >= 303.75 && direction < 326.25) return "NW";
if (direction >= 326.25 && direction < 348.75) return "NNW";
}
def applyConversion(tile, val){
try {
tile_type = atomicState.tile_type."${tile.type}";
out_units = atomicState.unit_type."${tile_type.type}".out;
in_units = tile_type.in_units;
} catch (e){
log.debug("Unable to find units for ${tile.title}:: Input units = "+in_units+" Output units = "+out_units);
}
if (in_units != out_units && out_units != "none")
switch (in_units) {
//Temperature
case "celsius":
switch (out_units) {
case "fahrenheit": val = (val * 9 / 5) + 32; break;
case "kelvin": val = val + 273.15; break;
default: val = "UNSUPPORTED";
}
break;
case "fahrenheit":
switch (out_units) {
case "celsius": val = (val - 32.0) * (5 / 9); break;
case "kelvin": val = ((val - 32) * (5 / 9)) + 273.15; break;
default: val = "UNSUPPORTED";
}
break;
case "kelvin":
switch (out_units) {
case "fahrenheit": val = ((val - 273.15) * (9 / 5)) + 32; break;
case "celsius": val = (val - 273.15); break;
default: val = "UNSUPPORTED";
}
break;
//Precipitation
case "millimeters":
if (out_units == "inches") {
val = (val / 25.4);
} else val = "UNSUPPORTED";
break;
case "inches":
if (out_units == "millimeters") {
val = (val * 25.4);
} else val = "UNSUPPORTED";
break;
//Velocity
case "meters_per_second":
switch (out_units) {
case "miles_per_hour": val = (val * 2.237); break;
case "knots": val = (val * 1.944); break;
case "kilometers_per_hour": val = (val * 3.6); break;
default: val = "UNSUPPORTED";
}
break;
case "miles_per_hour":
switch (out_units) {
case "miles_per_hour": val = (val / 2.237); break;
case "knots": val = (val / 1.151); break;
case "kilometers_per_hour": val = (val * 1.609); break;
default: val = "UNSUPPORTED";
}
break;
case "knots":
switch (out_units) {
case "miles_per_hour": val = (val * 1.151); break;
case "meters_per_second": val = (val / 1.944); break;
case "kilometers_per_hour": val = (val * 1.852); break;
default: val = "UNSUPPORTED";
}
break;
case "kilometers_per_hour":
switch (out_units) {
case "miles_per_hour": val = (val / 1.609); break;
case "meters_per_second": val = (val / 3.6); break;
case "knots": val = (val / 1.852); break;
default: val = "UNSUPPORTED";
}
break;
//Pressure
case "hectopascal":
case "millibars":
switch (out_units) {
case "inches_mercury": val = (val / 33.864); break;
case "millimeters_mercury": val = (val / 1.333); break;
case "hectopascal": break;
default: val = "UNSUPPORTED";
}
break;
case "inches_mercury":
switch (out_units) {
case "hectopascal":
case "millibars": val = (val * 33.864); break;
case "inches_mercury": val = (val / 25.4); break;
default: val = "UNSUPPORTED";
}
break;
case "millimeters_mercury":
switch (out_units) {
case "hectopascal":
case "millibars": val = (val * 1.333); break;
case "millimeters_mercury": val = (val * 25.4); break;
default: val = "UNSUPPORTED";
}
break;
case "degrees":
switch (out_units) {
case "cardinal":
val = getWindDirection(val);
break;
case "radians": val = (val * 3.1415926535) * 180.0; break;
default: val = "UNSUPPORTED";
}
break;
case "radians":
switch (out_units) {
case "cardinal":
val = getWindDirection(((val * 3.1415926535) * 180.0));
break;
case "degrees": val = ((val * 180) / 3.1415926535); break;
default: val = "UNSUPPORTED";
}
break;
case "cardinal":
switch (data.value) {
case "N": val = 0; break;
case "NNE": val = 22.5; break;
case "NE": val = 45; break;
case "ENE": val = 67.5; break;
case "E": val = 90; break;
case "ESE": val = 112.5; break;
case "SE": val = 135; break;
case "SSE": val = 157.5; break;
case "S": val = 180; break;
case "SSW": val = 202.5; break;
case "SW": val = 225; break;
case "WSW": val = 247.5; break;
case "W":val = 270; break;
case "WNW": val = 292.5; break;
case "NW": val = 315; break;
case "NNW": val = 337.5; break;
default: val = -1;
}
if (val != -1) {
switch (out_units) {
case "radians": val = ((val * 3.1415926535) * 180.0); break;
case "degrees": val = val; break;
default: val = "UNSUPPORTED";
}
} else val = "UNSUPPORTED";
break;
\
//TEXT CONVERSIONS
case "time_seconds":
v = val*1000L;
d = new Date(v);
switch (out_units) {
case "time_twelve":
SimpleDateFormat simpDate;
simpDate = new SimpleDateFormat("h:mm");
val = simpDate.format(d);
break;
case "time_two_four":
SimpleDateFormat simpDate;
simpDate = new SimpleDateFormat("kk:mm");
val = simpDate.format(d);
break;
default:
val = "UNSUPPORTED";
}
break;
case "time_milliseconds":
d = new Date(val);
switch (out_units) {
case "time_twelve":
val = d.getTimeString();
break;
case "time_two_four":
val = d.getTimeString();
break;
default:
val = "UNSUPPORTED";
}
break;
case "percent_numeric":
if (out_units == "percent_decimal") val = val / 100.0;
else val = "UNSUPPORTED";
break;
case "percent_decimal":
if (out_units == "percent_numeric") val = val * 100.0;
else val = "UNSUPPORTED";
break;
}
return val;
}
def translateCondition(tile, condition) {
icon = "mdi-weather-sunny-off";
pairings = [
[name: "thunderstorm with light rain", icon: "weather-lightning-rainy"],
[name: "thunderstorm with rain", icon: "weather-lightning-rainy"],
[name: "thunderstorm with heavy rain", icon: "weather-lightning-rainy"],
[name: "light thunderstorm", icon: "weather-lightning"],
[name: "thunderstorm", icon: "weather-lightning"],
[name: "heavy thunderstorm", icon: "weather-lightning"],
[name: "ragged thunderstorm", icon: "weather-lightning"],
[name: "thunderstorm with light drizzle", icon: "weather-lightning-rainy"],
[name: "thunderstorm with drizzle", icon: "weather-lightning-rainy"],
[name: "thunderstorm with heavy drizzle", icon: "weather-lightning-rainy"],
[name: "light intensity drizzle", icon: "weather-partly-rainy"],
[name: "drizzle", icon: "weather-partly-rainy"],
[name: "heavy intensity drizzle", icon: "weather-partly-rainy"],
[name: "light intensity drizzle rain", icon: "weather-partly-rainy"],
[name: "drizzle rain", icon: "weather-partly-rainy"],
[name: "heavy intensity drizzle rain", icon: "weather-rainy"],
[name: "shower rain and drizzle", icon: "weather-rainy"],
[name: "heavy shower rain and drizzle", icon: "weather-pouring"],
[name: "shower drizzle", icon: "weather-rainy"],
[name: "light rain", icon: "weather-rainy"],
[name: "moderate rain", icon: "weather-pouring"],
[name: "heavy intensity rain", icon: "weather-pouring"],
[name: "very heavy rain", icon: "weather-pouring"],
[name: "extreme rain", icon: "weather-pouring"],
[name: "freezing rain", icon: "weather-snowy-rainy"],
[name: "light intensity shower rain", icon: "weather-rainy"],
[name: "shower rain", icon: "weather-rainy"],
[name: "heavy intensity shower rain", icon: "weather-pouring"],
[name: "ragged shower rain", icon: "weather-partly-rainy"],
[name: "light snow", icon: "weather-snowy"],
[name: "snow", icon: "weather-snowy"],
[name: "heavy snow", icon: "weather-snowy-heavy"],
[name: "sleet", icon: "weather-hail"],
[name: "light shower sleet", icon: "weather-hail"],
[name: "shower sleet", icon: "weather-hail"],
[name: "light rain and snow", icon: "weather-snowy-rainy"],
[name: "rain and snow", icon: "weather-snowy-rainy"],
[name: "light shower snow", icon: "weather-partly-snowy"],
[name: "shower snow", icon: "weather-partly-snowy"],
[name: "heavy shower snow", icon: "weather-partly-snowy"],
[name: "mist", icon: "weather-fog"],
[name: "smoke", icon: "weather-fog"],
[name: "haze", icon: "weather-hazy"],
[name: "sand dust whirls", icon: "weather-tornado"],
[name: "fog", icon: "weather-fog"],
[name: "sand", icon: "weather-fog"],
[name: "dust", icon: "weather-fog"],
[name: "volcanic ash", icon: "weather-fog"],
[name: "squalls", icon: "weather-tornado"],
[name: "tornado", icon: "weather-tornado"],
[name: "clear sky night", icon: "weather-night"],
[name: "clear sky", icon: "weather-sunny"],
[name: "few clouds night", icon: "weather-night-partly-cloudy"],
[name: "few clouds", icon: "weather-partly-cloudy"],
[name: "scattered clouds night", icon: "weather-night-partly-cloudy"],
[name: "scattered clouds", icon: "weather-partly-cloudy"],
[name: "broken clouds", icon: "weather-cloudy"],
[name: "overcast clouds", icon: "weather-cloudy"]
];
try {
def now = new Date();
String period = tile.period;
timeframe = period.split("\\.");
def round_hour = false;
if (timeframe[0] == "hourly"){
round_hour = true;
num_hours = timeframe[1].toInteger();
use( groovy.time.TimeCategory ) {
now = now + num_hours.hours;
}
}
check_condition = condition;
if (isNight(now, round_hour)) {
check_condition+=" night";
}
return_val = ["icon", pairings.find{el-> el.name == check_condition}.icon];
} catch (e){
try {
return_val = ["icon", pairings.find{el-> el.name == condition}.icon];
} catch (ex) {
return_val = ["icon", "alert-circle"];
}
}
return return_val;
}
def formatNumericData(tile, val){
if (val == null)
val = 0;
return ["value", applyDecimals(tile, applyConversion(tile, val))];
}
def getMinHour(date){
return (float)(date.getHours())+((float)date.getMinutes()/60.0);
}
def isNight(date, round_hour){
def location = getLocation();
sunrise = getMinHour(location.sunrise);
sunset = getMinHour(location.sunset);
now = round_hour ? (float)date.getHours() : getMinHour(date);
Calendar cal = Calendar.getInstance();
if (now < sunrise || now > sunset) return true
else return false;
}
def formatHourData(tile, val){
def location = getLocation();
val_micro = val*1000L;
Date date = new Date (val_micro);
switch (settings["time_units"]){
case "time_seconds" : return ["value", val];
case "time_milliseconds" : return ["value", val_micro];
case "time_twelve" : return ["value", date.format('h:mm a', location.timeZone)];
case "time_two_four" : return ["value", date.format('HH:mm', location.timeZone)];
}
return ["value", "XXXX"];
}
def formatDayData(tile, val){
def location = getLocation();
val_micro = val*1000L;
Date date = new Date (val_micro);
if (settings["day_units"] == "short") day = date.format('E', location.timeZone);
else day = date.format('EEEE', location.timeZone);
return ["value", day];
}
def formatTextData(tile, val){
switch (settings["text_units"]){
case "plain": return ["value", val];
case "lowercase": return ["value", val.toLowerCase()];
case "uppercase": return ["value", val.toUpperCase()];
case "title": return ["value", val.split(" ").collect{it.capitalize()}.join(" ")];
}
return ["value", val];
}
def formatConditionText(tile, val){
return ["value", val.split(" ").collect{it.capitalize()}.join(" ")];
}
def formatTitle(tile, val){
return["value", ""];
}
def formatPressure(tile, val){
return ["value", "Pressure Trend"];
}
def formatDewPoint(tile, val) {
def text = "";
if (dewPoint < 50) text = "DRY";
else if (dewPoint < 55) text = "NORMAL";
else if (dewPoint < 60) text = "OPTIMAL";
else if (dewPoint < 65) text = "STICKY";
else if (dewPoint < 70) text = "MOIST";
else if (dewPoint < 75) text = "WET";
else text "MISERABLE";
return ["value", text];
}
def getSensorData(measurement){
device_id = measurement.tokenize('.')[1];
attribute = measurement.tokenize('.')[2];
sensor = sensors.find { it.id == device_id };
return sensor.currentState(attribute).getValue();
}
def buildWeatherData(){
def val;
def selections = settings["tile_settings"];
data = parent.getOpenWeatherData();
data = parseJson(data);
temp = atomicState.tile_settings;
temp.eachWithIndex{tile, index->
try {
period = tile.period;
measurement = atomicState.tile_type."${tile.type}".ow;
if (period == "sensor"){
val = getSensorData(measurement);
} else if (measurement == "precipitation"){
rain_val = getMapData(data, period+".rain");
snow_val = getMapData(data, period+".snow");
//Special Case
if (rain_val == null) rain_val = 0;
if (snow_val == null) snow_val = 0;
if (snow_val > rain_val){
tile.icon = "snowflake";
} else {
tile.icon = "water";
}
val = rain_val + snow_val;
} else if (period != "none" && measurement != "none") {
val = getMapData(data, period+"."+measurement);
}
} catch (e){
log.debug(tile.name+": Unable to get data: "+period+", "+measurement);
}
unit_type = atomicState.tile_type."${tile.type}".type;
parse_func = atomicState.unit_type."${unit_type}".parse_func;
try{
if (parse_func!="none"){
returnVal = "${parse_func}"(tile, val);
tile."${returnVal[0]}" = returnVal[1];
} else {
tile.value = "";
}
} catch (error){
log.debug(val+" "+unit_type+" "+parse_func+"::: Issue executing parse function: $parse_func " + error);
}
}
atomicState.tile_settings = temp;
}
def getTileHTML(item, locked){
var = item.var;
fontScale = 4.6;
lineScale = 0.85;
iconScale = 3.5;
header = 0.1;
height = item.h;
html = "";
tile_locked = locked ? "false" : "true";
background = getRGBA(item.background_color, (Float.parseFloat(item.background_opacity)));
font = getRGBA(item.font_color, Float.parseFloat(item.font_opacity));
if (item.display==true){
html += """
${item.title}
${item.font_adjustment}
${item.title}
""";
//Compute Icon and other spacing
//Left Icon
if (item.icon_loc != "right"){
item.icon_space = item.icon_space ? item.icon_space : "";
html+="""${item.icon_space} """;
}
//Text
if (item.text == "null" || item.text == null) item.text="";
html+="""${item.text} """;
//Main Content
html += """${item.value} """
//Units
try{
tile_type = atomicState.tile_type."${item.type}".type;
out_units = atomicState.unit_type."${tile_type}".out;
units = getAbbrev(out_units);
} catch (e){
units = "";
}
if (units == "unknown") units="";
//Unit Spacing
html += """${item.unit_space} """
html += """${units} """;
//Right Icon
if (item.icon_loc == "right"){
html+="""${item.icon_space} """;
html+=""" """;
}
html += """
""";
} //if display
return html;
}
def getDrawType(){
return "google.visualization.LineChart"
}
def removeLastChar(str) {
str.subSequence(0, str.length() - 1)
str
}
def getRGBA(hex, opacity){
def c = hex-"#";
c = c.toUpperCase();
i = Integer.parseInt(c, 16);
r = (i & 0xFF0000) >> 16;
g = (i & 0xFF00) >> 8;
b = (i & 0xFF);
o = opacity/100.0;
s = sprintf("rgba( %d, %d, %d, %.2f)", r, g, b, o);
return s;
}
def defineHTML_Header(){
def html = """
"""
return html;
}
def addColorPicker(Map map){
var = map.var;
title = map.title;
html = """
"""
return html;
}
def addButtonMenu(Map map){
button_var = map.var_name;
default_val = map.default_value;
default_icon = map.default_icon;
item_list = map.list;
tooltip = map.tooltip ? map.tooltip : "";
side = map.side ? map.side : "left";
def html = """
${default_val}
${default_icon}
${tooltip}
"""
html += """
"""
return html;
}
def addMenu(Map map){
button_var = map.var_name;
default_val = map.default_value;
default_icon = map.default_icon;
item_list = map.list;
tooltip = map.tooltip ? map.tooltip : "";
title = map.title;
def html = """
${default_val}
mdi-${default_icon}
${title}
${tooltip}
"""
html += """
"""
return html;
}
def addIconMenu(Map map){
button_var = map.var_name;
default_val = map.default_value;
default_icon = map.default_icon;
item_list = map.list;
tooltip = map.tooltip ? map.tooltip : "";
description = map.description ? map.description : false;
width = map.width;
if (map.tooltip == "Use Icon Name") tooltip = "No Icon Selected";
def html = """
"""
html += """
"""
return html;
}
def addSlider(Map map){
var = map.var;
title = map.title;
min = map.min;
max = map.max;
value = map.value;
html = """
"""
return html;
}
def defineHTML_CSS(){
def html = """
"""
return html;
}
def defineSelectBox(Map map){
title = map.title;
var = map.var;
list = map.list;
visible = map.visible == false ? """style="display: none;" """ : "" ;
function = map.function;
html = """
"""
list.each{key, item->
html+="""${item.name} """
}
html+=
"""
${title}
"""
return html;
}
def defineNewTileDialog(){
typeList = atomicState.newTileDialog;
html = "";
html += """
New Tile Options
"""
html += """
"""
html += """
"""
html+= """
"""
html += """
"""
return html;
}
def defineTileDialog(){
list = [];
atomicState.tile_settings.each{item->
list << [name: item.title, icon: item.icon, var: item.var];
}
def html = """
Options
Save Colors and Opacity to All Tiles
Refresh View This may take some time, depending on the number of tiles
"""
/********************ALIGNMENT****************************************/
html+= """
"""
html += addIconMenu(var_name: "selected_icon", title: "Select Tile Type", default_icon: "alpha-x-circle-outline",
default_value: "center", tooltip: "Use Icon Name", list: getIconList(), width: 4);
html += """
"""
html+= addButtonMenu(var_name: "horizontal_alignment", default_icon: "format-align-center", tooltip: "Horizontal Alignment", default_value: "center", side: "left",
list:[[name: "Left", icon: "format-align-left"],
[name: "Center", icon: "format-align-center"],
[name: "Right", icon: "format-align-right"]]);
html+=
"""
"""
html+= addButtonMenu(var_name: "icon_spacing", default_icon: "keyboard-space", tooltip: "Icon Spacing", default_value: "Single Space", side: "left",
list:[[name: "No Space", icon: "arrow-collapse-horizontal"],
[name: "Single Space", icon: "keyboard-space"],
[name: "Double Space", icon: "arrow-expand-horizontal"]]);
html+=
"""
"""
html+= addButtonMenu(var_name: "decimal_places", default_icon: "decimal", tooltip: "Decimal Places", default_value: "One Decimal", side: "left",
list:[[name: "No Decimal", icon: "hexadecimal"],
[name: "One Decimal", icon: "surround-sound-2-0"],
[name: "Two Decimals", icon: "decimal"]]);
html += """
"""
html+= addButtonMenu(var_name: "font_weight", default_icon: "numeric-4-circle", default_value: "center", tooltip: "Font Weight", side: "right",
list:[[name: "Thin", icon: "numeric-1-circle"],
[name: "Normal", icon: "numeric-4-circle"],
[name: "Bold", icon: "numeric-7-circle"],
[name: "Thick", icon: "numeric-9-circle"]]);
html += """
"""
html+= addButtonMenu(var_name: "units_spacing", default_icon: "keyboard-space", tooltip: "Units Spacing", default_value: "Single Space", side: "right",
list:[[name: "No Space", icon: "arrow-collapse-horizontal"],
[name: "Single Space", icon: "keyboard-space"],
[name: "Double Space", icon: "arrow-expand-horizontal"]]);
html += """
"""
/*****************TEXT COLOR***************************************/
html+= addColorPicker(var: "text", title: "Text");
/****************BACKGROUND COLOR *********************************/
html+= addColorPicker(var: "background", title: "Background");
/****************Font Adjustment *********************************/
html += """
"""
html+= addSlider(var: "font_adjustment", title: "Relative Size", min: -100, value: 0, max:100);
html+="""
""";
return html;
}
def getTileListItem(Map map){
function = map.function;
var: map.name;
menu = map.list;
selections = map.selections.clone();
selections << var;
return "";
if (!menu.list) onclick = """onclick="${map.function}('${selections}')" """
html = """"""
if (menu.list) {
html += """"""
} else {
var = item.name.replaceAll(" ","");
var = parent_+var;
select = selections.clone();
select << [item.name];
func = """onclick="${function_name}('${select}')" """;
if (item.list){
html += getTileListItem(name: item.name, parent: var, function: function, list: item.list, selections: select);
}
else {
html += """
${item.name}
"""
}
}
html += """"""
return html;
}
def defineHTML_Tile(locked){
def temp_units = '°';
def rain_units = '"';
def m_time_units = ' am';
def e_time_units = ' pm';
def wind_units = ' mph';
def pressure_units = 'inHg';
if (tile_units == "metric"){
rain_units = 'mm';
m_time_units = '';
e_time_units = '';
wind_units = ' m/sec';
pressure_units = 'mmHg';
}
background = 'black'
if (background_color != null) {
transparent = background_color_transparent ? 0.0 : background_opacity;
background = getRGBA(background_color, transparent);
}
def html = """
"""
//Main Tile Building Code
atomicState.tile_settings.eachWithIndex{item, index->
html += getTileHTML(item, locked);
} //each
html += """
"""
html+= """
"""
return html;
}
def defineHTML_globalVariables(){
def html = """
var sunrise;
var sunset;
let options = [];
let pws_data = [];
let currentTemperature;
"""
}
//tile_settings_HTML
def defineUpdateDataHTML(var){
if (!settings["$var"]){
app.updateSetting("${var}", [value: "", type: "string"]);
}
html = """