Device Dashboard for Dummies

amg0, Thanks for adding the dashboard for the VSwitch. I use that one a lot.

I’ve tried deciphering where and how the dashboards are created in the code. Not much success. I’m more of a classic coder–Java, C++, etc. I can do some lua and javascript is no big deal. But the key to it all I believe is how to use the libraries and tools.

If you’re willing I’d love it if you could show where and how you added the dashboard for the VSwitch. Kind of a adding a device dashboard for dummies if you will.

I have a custom device of my own that I would like to add two dashboard switches and a few status variables. I think I can find where to start, but I don’t know how to finish

Thanks!! --David

[quote=“dklinkman, post:1, topic:188672”]amg0, Thanks for adding the dashboard for the VSwitch. I use that one a lot.

I’ve tried deciphering where and how the dashboards are created in the code. Not much success. I’m more of a classic coder–Java, C++, etc. I can do some lua and javascript is no big deal. But the key to it all I believe is how to use the libraries and tools.

If you’re willing I’d love it if you could show where and how you added the dashboard for the VSwitch. Kind of a adding a device dashboard for dummies if you will.

I have a custom device of my own that I would like to add two dashboard switches and a few status variables. I think I can find where to start, but I don’t know how to finish

Thanks!! --David[/quote]

Yes,I ll post something later but for now these could be useful to start
http://forum.micasaverde.com/index.php/topic,33307.0.html

J_altui_plugins.js or j_altui_iphone.js are example of device dashboard and control panel plugins
Plugins are declared in the config variable of altUI device or in l_altui.lua code for the default config. I do force config to be reset to default whenever Lua code version increases so it could be good you give me your config and module and code once done, up to you.

I have attached a tutorial document in English into the msg1 of the plugin development thread here
[url=http://forum.micasaverde.com/index.php/topic,33307.msg244107.html#msg244107]http://forum.micasaverde.com/index.php/topic,33307.msg244107.html#msg244107[/url]

Very, very helpful. Thanks for doing that. From the document I was able to (finally) understand how the dashboards are declared, and see how they are implemented. I was able to add a dashboard to my own plugin which is basically the old ping sensor rewritten and extended somewhat. I attached the result. Now I have about 8 more to make for devices that I use that don’t currently have one. I’ll share those once I’m done.

Thanks!!! --David

[quote=“dklinkman, post:4, topic:188672”]Very, very helpful. Thanks for doing that. From the document I was able to (finally) understand how the dashboards are declared, and see how they are implemented. I was able to add a dashboard to my own plugin which is basically the old ping sensor rewritten and extended somewhat. I attached the result. Now I have about 8 more to make for devices that I use that don’t currently have one. I’ll share those once I’m done.

Thanks!!! --David[/quote]

looks great !

This appears to work well for the GCal device since it is really just another sensor. Easy since it just uses the existing motion sensor implementation.

PluginConfig variable:

“urn:schemas-utz-com:device:GCal:1”: {“DeviceDrawFunc”: “ALTUI_PluginDisplays.drawGCal”,“ScriptFile”: “J_ALTUI_plugins.js”}

mapping in J_ALTUI_plugins.js

drawGCal : _drawGCal,

method in J_ALTUI_plugins.js

function _drawGCal( device ) {
return _drawMotion( device );
}

Edit: I just noticed the dashboard image doesn’t have the last tripped date/time. That’s only because this particular device has never been tripped!

[quote=“dklinkman, post:6, topic:188672”]This appears to work well for the GCal device since it is really just another sensor. Easy since it just uses the existing motion sensor implementation.

PluginConfig variable:

“urn:schemas-utz-com:device:GCal:1”: {“DeviceDrawFunc”: “ALTUI_PluginDisplays.drawGCal”,“ScriptFile”: “J_ALTUI_plugins.js”}

mapping in J_ALTUI_plugins.js

drawGCal : _drawGCal,

method in J_ALTUI_plugins.js

function _drawGCal( device ) {
return _drawMotion( device );
}

Edit: I just noticed the dashboard image doesn’t have the last tripped date/time. That’s only because this particular device has never been tripped![/quote]

ok thank you very much ! saves me time … included in next version

Sweet! I was able to get my sensor device type to dynamically register with altui using @reneboer’s pattern.

Now your [very welcome and] frequent altui updates won’t overwrite my dashboard :slight_smile:

–David

amg0 Here’s another one for you. This is a dashboard for the Combination Switch. Another device I use a lot.

PluginConfig variable:

{"urn:schemas-futzle-com:device:CombinationSwitch:1": {"DeviceDrawFunc": "ALTUI_PluginDisplays.drawCombinationSwitch","ScriptFile": "J_ALTUI_plugins.js"}

Object Mapping:

drawCombinationSwitch : _drawCombinationSwitch,

JS Method:

[code] function _drawCombinationSwitch( device ) {
var html = “”;

    var poke = 0;
    html += _createOnOffButton( poke,"altui-pokebtn-"+device.altuiid, _T("Poke,Poke") , "pull-right" );

    var label = MultiBox.getStatus( device, 'urn:futzle-com:serviceId:CombinationSwitch1', 'Label' );
    if (label != null) {
        html += "<div class='altui-temperature'><br>Watched Items: {0}</div>".format(label);
    }

    html += "<script type='text/javascript'>";
    html += " $('div#altui-pokebtn-{0}').on('click touchend', function() { MultiBox.runActionByAltuiID('{0}', 'urn:futzle-com:serviceId:CombinationSwitch1', 'Trigger', {}); } );".format(device.altuiid);
    html += "</script>";

    return html;
};[/code]

But I need your help a little bit with this one. The “poke” button should be a momentary type, literally a pushbutton, not a toggle or an on/off type. I used your on/off button only because I don’t know how to create a different one. The button works. If you click it the javascript runs and the device gets “poked” as it should. But the button has no feedback or animation. For what it’s worth the button under UI7 doesn’t animate either.

In any case the dashboard works just fine. I couldn’t find an example of ‘just a button’ in any of your works. At least nothing that fits the motif. The thermostat device had some interesting code that I want to study some more. Nice work there.

Thanks!!! --David

amg0, Here’s one more. This time for the DayTime plugin which I also use. This one loosely follows your VSwitch pattern.

This one simply displays a Night/Day toggle switch on the dashboard. This device allows you to temporarily force night and day states via the toggle switch. Which is handy when testing a scene, for example.

PluginConfig:

"urn:schemas-rts-services-com:device:DayTime:1": {"DeviceDrawFunc": "ALTUI_PluginDisplays.drawDayTime","ScriptFile": "J_ALTUI_plugins.js"}

Object Mapping:

drawDayTime    : _drawDayTime,

An Object Mapping of a new method - hopefully you know where this goes:

toggleDayTimeButton : function (altuiid,htmlid) { ALTUI_PluginDisplays.toggleButton(altuiid, htmlid, 'urn:rts-services-com:serviceId:DayTime', 'Status', function(id,newval) { MultiBox.runActionByAltuiID( altuiid, 'urn:rts-services-com:serviceId:DayTime', 'SetTarget', {newTargetValue:newval} ); }); },

And the new dashboard method:

[code] function _drawDayTime( device ) {
var html = “”;

	var status = parseInt(MultiBox.getStatus( device, 'urn:rts-services-com:serviceId:DayTime', 'Status' )); 
	html += _createOnOffButton( status,"altui-onoffbtn-"+device.altuiid, _T("Night,Day") , "pull-right");
	
	html += "<script type='text/javascript'>";
	html += " $('div#altui-onoffbtn-{0}').on('click touchend', function() { ALTUI_PluginDisplays.toggleDayTimeButton('{0}','div#altui-onoffbtn-{0}'); } );".format(device.altuiid);
	html += "</script>";
	return html;
}[/code]

fantastic, thx !
I added it in the next revision ( not yet published ) but the source code is here
http://code.mios.com/trac/mios_alternate_ui/browser

regarding the poke button, would not a simple push button work ? we have example in infoviewer dashboard for instance of a classic push button for instance

regarding the poke button, would not a simple push button work ? we have example in infoviewer dashboard for instance of a classic push button for instance
I suppose it would! When scanning for examples unfortunately I'm only looking at devices I have. But I'll check out Infoviewer.

Thanks!

amg0, That worked well. Classic pushbutton it is. I also toned down the text label. Here’s the updated method.

[code] function _drawCombinationSwitch( device ) {
var html = “”;

    html += ("<button id='altui-pokebtn-{0}' type='button' class='pull-right altui-window-btn btn btn-default btn-sm '>{1}</button>" .format( device.altuiid,_T("Poke") )) ;

    var label = MultiBox.getStatus( device, 'urn:futzle-com:serviceId:CombinationSwitch1', 'Label' );
    if (label != null) {
        html += "<div class='altui-vswitch-text text-muted'><br>Watched Items: {0}</div>".format(label);
    }

    html += "<script type='text/javascript'>";
    html += " $('button#altui-pokebtn-{0}').on('click', function() { console.log('clicked'); MultiBox.runActionByAltuiID('{0}', 'urn:futzle-com:serviceId:CombinationSwitch1', 'Trigger', {}); } );".format(device.altuiid);
    html += "</script>";

    return html;
};[/code]

[quote=“dklinkman, post:13, topic:188672”]amg0, That worked well. Classic pushbutton it is. I also toned down the text label. Here’s the updated method.

[code] function _drawCombinationSwitch( device ) {
var html = “”;

    html += ("<button id='altui-pokebtn-{0}' type='button' class='pull-right altui-window-btn btn btn-default btn-sm '>{1}</button>" .format( device.altuiid,_T("Poke") )) ;

    var label = MultiBox.getStatus( device, 'urn:futzle-com:serviceId:CombinationSwitch1', 'Label' );
    if (label != null) {
        html += "<div class='altui-vswitch-text text-muted'><br>Watched Items: {0}</div>".format(label);
    }

    html += "<script type='text/javascript'>";
    html += " $('button#altui-pokebtn-{0}').on('click', function() { console.log('clicked'); MultiBox.runActionByAltuiID('{0}', 'urn:futzle-com:serviceId:CombinationSwitch1', 'Trigger', {}); } );".format(device.altuiid);
    html += "</script>";

    return html;
};[/code][/quote]

thx, integrated and published in v0.70.667

Awesome. Thank you. Here’s yet another one. A dashboard for the Sonos plugin this time. Implementation is a little more complicated. The presentation lags a bit but that’s just the updating of the UI I think. But it’s functional.

PluginConfig:"urn:schemas-micasaverde-com:device:Sonos:1":{"DeviceDrawFunc":"ALTUI_PluginDisplays.drawSonos","ScriptFile":"J_ALTUI_plugins.js"}

Object Mapping:drawSonos : _drawSonos,

Dashboard Method: function _drawSonos( device ) { var html = ""; var status = MultiBox.getStatus(device, 'urn:upnp-org:serviceId:AVTransport', 'TransportState'); // may return: PLAYING, PAUSED_PLAYBACK, STOPPED var title = MultiBox.getStatus(device, 'urn:upnp-org:serviceId:AVTransport', 'CurrentTitle'); // could also get CurrentAlbum, CurrentArtist, CurrentStatus var playstatus = ""; var playtitle = ""; var playbtn = "Play"; var stopbtn = "Stop"; var playbtnstyle = ""; var stopbtnstyle = ""; if (title != null) { if (status == "PLAYING") { playstatus = "Playing..."; playtitle = title; playbtn = "Pause"; } else { if (status == "PAUSED_PLAYBACK") { playstatus = "<br>Paused...<br>Press Play to continue"; } else if (status == "STOPPED") { playstatus = "<br>Stopped"; } else { playstatus = ""; } } } html += "<button id='altui-Stopbtn-{0}' type='button' class='pull-right altui-window-btn btn btn-default btn-sm {1}'>{2}</button>" .format(device.altuiid, stopbtnstyle, _T(stopbtn)) ; html += "<button id='altui-{2}btn-{0}' type='button' class='pull-right altui-window-btn btn btn-default btn-sm {1}'>{2}</button>" .format(device.altuiid, playbtnstyle, _T(playbtn)) ; if (title != null) { html += "<div class='altui-vswitch-text text-muted' style='height: 50px; overflow: hidden'>{0}<br>{1}</div>".format(playstatus, playtitle); } html += "<script type='text/javascript'>"; html += " $('button#altui-Playbtn-{0}').on('click', function() { MultiBox.runActionByAltuiID('{0}', 'urn:micasaverde-com:serviceId:MediaNavigation1', 'Play', {}); } );".format(device.altuiid); html += " $('button#altui-Pausebtn-{0}').on('click', function() { MultiBox.runActionByAltuiID('{0}', 'urn:micasaverde-com:serviceId:MediaNavigation1', 'Pause', {}); } );".format(device.altuiid); html += " $('button#altui-Stopbtn-{0}').on('click', function() { MultiBox.runActionByAltuiID('{0}', 'urn:micasaverde-com:serviceId:MediaNavigation1', 'Stop', {}); } );".format(device.altuiid); html += "</script>"; return html; }

This simple dashboard doesn’t even begin to scratch the functionality of the control panel tabs which are all fully functional under altui. But it’s something.

I played with colors for the buttons but backed that off because the UI refresh seemed to interfere with it. I might need to figure out how to use the spinner like you do with the onoff button. More code to study.

One question for you. I tend to reuse CSS classes from other dashboards rather than define new ones. Is that ok or maybe a no-no? I know you’ve put a lot of work into CSS and skinning.

Only 4 more device types to ‘dashboard’ on my short list!!

Thanks!!! --David

[quote=“dklinkman, post:15, topic:188672”]Awesome. Thank you. Here’s yet another one. A dashboard for the Sonos plugin this time. Implementation is a little more complicated. The presentation lags a bit but that’s just the updating of the UI I think. But it’s functional.

PluginConfig:"urn:schemas-micasaverde-com:device:Sonos:1":{"DeviceDrawFunc":"ALTUI_PluginDisplays.drawSonos","ScriptFile":"J_ALTUI_plugins.js"}

Object Mapping:drawSonos : _drawSonos,

Dashboard Method: function _drawSonos( device ) { var html = ""; var status = MultiBox.getStatus(device, 'urn:upnp-org:serviceId:AVTransport', 'TransportState'); // may return: PLAYING, PAUSED_PLAYBACK, STOPPED var title = MultiBox.getStatus(device, 'urn:upnp-org:serviceId:AVTransport', 'CurrentTitle'); // could also get CurrentAlbum, CurrentArtist, CurrentStatus var playstatus = ""; var playtitle = ""; var playbtn = "Play"; var stopbtn = "Stop"; var playbtnstyle = ""; var stopbtnstyle = ""; if (title != null) { if (status == "PLAYING") { playstatus = "Playing..."; playtitle = title; playbtn = "Pause"; } else { if (status == "PAUSED_PLAYBACK") { playstatus = "<br>Paused...<br>Press Play to continue"; } else if (status == "STOPPED") { playstatus = "<br>Stopped"; } else { playstatus = ""; } } } html += "<button id='altui-Stopbtn-{0}' type='button' class='pull-right altui-window-btn btn btn-default btn-sm {1}'>{2}</button>" .format(device.altuiid, stopbtnstyle, _T(stopbtn)) ; html += "<button id='altui-{2}btn-{0}' type='button' class='pull-right altui-window-btn btn btn-default btn-sm {1}'>{2}</button>" .format(device.altuiid, playbtnstyle, _T(playbtn)) ; if (title != null) { html += "<div class='altui-vswitch-text text-muted' style='height: 50px; overflow: hidden'>{0}<br>{1}</div>".format(playstatus, playtitle); } html += "<script type='text/javascript'>"; html += " $('button#altui-Playbtn-{0}').on('click', function() { MultiBox.runActionByAltuiID('{0}', 'urn:micasaverde-com:serviceId:MediaNavigation1', 'Play', {}); } );".format(device.altuiid); html += " $('button#altui-Pausebtn-{0}').on('click', function() { MultiBox.runActionByAltuiID('{0}', 'urn:micasaverde-com:serviceId:MediaNavigation1', 'Pause', {}); } );".format(device.altuiid); html += " $('button#altui-Stopbtn-{0}').on('click', function() { MultiBox.runActionByAltuiID('{0}', 'urn:micasaverde-com:serviceId:MediaNavigation1', 'Stop', {}); } );".format(device.altuiid); html += "</script>"; return html; }

This simple dashboard doesn’t even begin to scratch the functionality of the control panel tabs which are all fully functional under altui. But it’s something.

I played with colors for the buttons but backed that off because the UI refresh seemed to interfere with it. I might need to figure out how to use the spinner like you do with the onoff button. More code to study.

One question for you. I tend to reuse CSS classes from other dashboards rather than define new ones. Is that ok or maybe a no-no? I know you’ve put a lot of work into CSS and skinning.

Only 4 more device types to ‘dashboard’ on my short list!!

Thanks!!! --David[/quote]

greats, it is really good to see people contributing to improving this UI. it is really appreciated.

regarding reusing CSS classes, I think it is better not to reuse too much in case you anticipate someone may want to reskin that to something else. button is unlikely to be skinned too much but text lines could , some people may prefer bigger or smaller fonts so I would recommend not reusing classes for text lines for instance while it is probably acceptable for some of the dashboards buttons for which , some consistency accross dashboards is probably desirable. Plus creating too many unused css class is not that great either, so it is a balance.

Regarding buttons, you could take advantage of bootstrap glyphs and create really small button with just the icons inside for play pause stop fast forward etc…
see glyphTemplate in J_ALTUI_uimgr.js, you can use it this way

var myGlyph = glyphTemplate.format( name, title, color  );

where

  • name is the name from the examples of glyphs in https://getbootstrap.com/docs/5.3/components/accordion/ minus the prefix ‘glyphicon glyphicon-’ part. so the play glyph name to use would be “play”
  • title : popup title text when hovering the mouse, also used for accessibility user interface
  • color : can be ‘’ for default or one of the standard typography color of bootstrap ( text-danger, text-warning text-muted, text-info etc )

then you compose your HTML button. example

var infobutton = smallbuttonTemplate.format( plugin.altuiid, 'altui-plugin-icon altui-plugin-info-sign',  glyphTemplate.format("info-sign","Information",""), "Info");

that smallbuttonTemplate is defined in J_ALTUI_uimgr.js like that:

smallbuttonTemplate = "<button id='{0}' type='button' class='{1} btn btn-default btn-sm' aria-label='tbd' title='{3}'>{2}</button>";

so you will get the jquery click event this way

$("btn.your_class#your_id").on('click',function()... )

where your_class was passed as one of the words in parameter 2 of the smallbuttonTemplate.format() ( you can pass several classes )
and your_id was passed in parameter 1 of the smallbuttonTemplate.format()

you could also have only one callback for the class, then internally switch by ID

[code]$("btn.your_class).on(‘click’,function() {
var id = $(this).prop(‘id’);
switch(id) {
case etc …
}

}
)[/code]

I attached a screen shot of potentially interesting glyphs

integrated your sonos version in v671

That’s all really useful information. Thanks.

I have yet another dashboard for you. This time for the System Monitor app. Super simple. Screenshot attached below

But first things first. I created text classes for the dashboards that I made earlier that use text to display information. This is the code to be added to _getStyle(). Nothing fancy. Just mimics the vswitch text class.

style += ".altui-sonos-text, .altui-combsw-text, .altui-sysmon-text {font-size: 11px;}";

Now for the new plugin. All the usual here:

"urn:schemas-cd-jackson-com:device:SystemMonitor:1":{"DeviceDrawFunc":"ALTUI_PluginDisplays.drawSysMonitor","ScriptFile":"J_ALTUI_plugins.js"}
drawSysMonitor  : _drawSysMonitor,

function _drawSysMonitor( device ) { var html = ""; var memoryavail = MultiBox.getStatus(device, 'urn:cd-jackson-com:serviceId:SystemMonitor', 'memoryAvailable'); var cpuload = MultiBox.getStatus(device, 'urn:cd-jackson-com:serviceId:SystemMonitor', 'cpuLoad5'); if (memoryavail != null && cpuload != null) { html += "<div class='altui-sysmon-text text-muted'><br>Memory Available: {0}<br>CPU Load (5 minute): {1}</div>".format(memoryavail, cpuload); } return html; }

And now the updated draw methods for the combination switch and for sonos that use the new text classes:

[code] function _drawCombinationSwitch( device ) {
var html = “”;

    html += ("<button id='altui-pokebtn-{0}' type='button' class='pull-right altui-window-btn btn btn-default btn-sm '>{1}</button>" .format( device.altuiid,_T("Poke") )) ;

    var label = MultiBox.getStatus( device, 'urn:futzle-com:serviceId:CombinationSwitch1', 'Label' );
    if (label != null) {
        html += "<div class='altui-combsw-text text-muted'><br>Watched Items: {0}</div>".format(label);
    }

    html += "<script type='text/javascript'>";
    html += " $('button#altui-pokebtn-{0}').on('click', function() { MultiBox.runActionByAltuiID('{0}', 'urn:futzle-com:serviceId:CombinationSwitch1', 'Trigger', {}); } );".format(device.altuiid);
    html += "</script>";

    return html;
};[/code]

function _drawSonos( device ) { var html = ""; var status = MultiBox.getStatus(device, 'urn:upnp-org:serviceId:AVTransport', 'TransportState'); // may return: PLAYING, PAUSED_PLAYBACK, STOPPED var title = MultiBox.getStatus(device, 'urn:upnp-org:serviceId:AVTransport', 'CurrentTitle'); // could also get CurrentAlbum, CurrentArtist, CurrentStatus var playstatus = ""; var playtitle = ""; var playbtn = "Play"; var stopbtn = "Stop"; var playbtnstyle = ""; var stopbtnstyle = ""; if (title != null) { if (status == "PLAYING") { playstatus = "Playing..."; playtitle = title; playbtn = "Pause"; } else { if (status == "PAUSED_PLAYBACK") { playstatus = "<br>Paused...<br>Press Play to continue"; } else if (status == "STOPPED") { playstatus = "<br>Stopped"; } else { playstatus = ""; } } } html += "<button id='altui-Stopbtn-{0}' type='button' class='pull-right altui-window-btn btn btn-default btn-sm {1}'>{2}</button>" .format(device.altuiid, stopbtnstyle, _T(stopbtn)) ; html += "<button id='altui-{2}btn-{0}' type='button' class='pull-right altui-window-btn btn btn-default btn-sm {1}'>{2}</button>" .format(device.altuiid, playbtnstyle, _T(playbtn)) ; if (title != null) { html += "<div class='altui-sonos-text text-muted' style='height: 48px; overflow: hidden'>{0}<br>{1}</div>".format(playstatus, playtitle); } html += "<script type='text/javascript'>"; html += " $('button#altui-Playbtn-{0}').on('click', function() { MultiBox.runActionByAltuiID('{0}', 'urn:micasaverde-com:serviceId:MediaNavigation1', 'Play', {}); } );".format(device.altuiid); html += " $('button#altui-Pausebtn-{0}').on('click', function() { MultiBox.runActionByAltuiID('{0}', 'urn:micasaverde-com:serviceId:MediaNavigation1', 'Pause', {}); } );".format(device.altuiid); html += " $('button#altui-Stopbtn-{0}').on('click', function() { MultiBox.runActionByAltuiID('{0}', 'urn:micasaverde-com:serviceId:MediaNavigation1', 'Stop', {}); } );".format(device.altuiid); html += "</script>"; return html; }

Hopefully it all makes sense.

Thanks!!! --David

Another one for you. A simple one again. This time for the Vera Alerts app. Basically just mimicking what it does on UI7

An update to the text styles I sent before:

style += ".altui-sonos-text, .altui-combsw-text, .altui-sysmon-text, .altui-veraalerts-text {font-size: 11px;}";

Plus the usual:

"urn:richardgreen:device:VeraAlert:1":{"DeviceDrawFunc":"ALTUI_PluginDisplays.drawVeraAlerts","ScriptFile":"J_ALTUI_plugins.js"},
    drawVeraAlerts  : _drawVeraAlerts,

function _drawVeraAlerts( device ) { var html = ""; var lastmsgsent = MultiBox.getStatus(device, 'urn:richardgreen:serviceId:VeraAlert1', 'LastMsgSent'); var lastrecipient = MultiBox.getStatus(device, 'urn:richardgreen:serviceId:VeraAlert1', 'LastRecipient'); if (lastmsgsent != null && lastrecipient != null) { html += "<div class='altui-sysmon-text text-muted' style='padding-left: 52px'><br>Last Msg Sent: {0}<br>Profile Used: {1}</div>".format(lastmsgsent, lastrecipient); } return html; }

Short and sweet. Only a few left on my list.

Thanks!!! --David

Ok last one for today I promise. Another super simple one. This is for a water leak/freeze sensor. An actual z-wave device this time. The sensor icon looks ok. This dashboard simply adds the temperature reading. See the attached image. The actual device is a Fortezza water and freeze detector. Mine sits in a drawer because I haven’t yet figured out how to untrip the thing. Probably something with the temperature alarm settings.

In any case here is the usual:

"urn:schemas-micasaverde-com:device:TempLeakSensor:1":{"DeviceDrawFunc":"ALTUI_PluginDisplays.drawTempLeak","ScriptFile":"J_ALTUI_plugins.js"},
    drawTempLeak    : _drawTempLeak,

function _drawTempLeak( device ) { return _drawTempSensor(device); }

Thanks!!! --David