We have moved at community.getvera.com

Author Topic: Device Dashboard for Dummies  (Read 9971 times)

Offline amg0

  • Moderator
  • Master Member
  • *****
  • Posts: 3174
  • Karma: +209/-8
Re: Device Dashboard for Dummies
« Reply #15 on: September 09, 2015, 07:39:21 am »
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:
Code: [Select]
"urn:schemas-micasaverde-com:device:Sonos:1":{"DeviceDrawFunc":"ALTUI_PluginDisplays.drawSonos","ScriptFile":"J_ALTUI_plugins.js"}
Object Mapping:
Code: [Select]
drawSonos      : _drawSonos,
Dashboard Method:
Code: [Select]
    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

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
Code: [Select]
var myGlyph = glyphTemplate.format( name, title, color  );where
- name is the name from the examples of glyphs in http://getbootstrap.com/components/ 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
Code: [Select]
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:
Code: [Select]
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
Code: [Select]
$("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: [Select]
$("btn.your_class).on('click',function() {
    var id = $(this).prop('id');
    switch(id) {
        case  etc ...
   }

}
)

I attached a screen shot of potentially interesting glyphs

Offline amg0

  • Moderator
  • Master Member
  • *****
  • Posts: 3174
  • Karma: +209/-8
Re: Device Dashboard for Dummies
« Reply #16 on: September 09, 2015, 04:14:46 pm »
integrated your sonos version in v671

Offline dklinkman

  • Full Member
  • ***
  • Posts: 129
  • Karma: +1/-0
Re: Device Dashboard for Dummies
« Reply #17 on: September 09, 2015, 10:24:02 pm »
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.
Code: [Select]
style += ".altui-sonos-text, .altui-combsw-text, .altui-sysmon-text {font-size: 11px;}";
Now for the new plugin.  All the usual here:
Code: [Select]
"urn:schemas-cd-jackson-com:device:SystemMonitor:1":{"DeviceDrawFunc":"ALTUI_PluginDisplays.drawSysMonitor","ScriptFile":"J_ALTUI_plugins.js"}
Code: [Select]
drawSysMonitor  : _drawSysMonitor,
Code: [Select]
    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: [Select]
    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: [Select]
    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
VeraPlus, UI7, ALTUI on Chrome, Lots of devices and plugins including MQTT and MySensors.  Also playing around with openLuup

Offline dklinkman

  • Full Member
  • ***
  • Posts: 129
  • Karma: +1/-0
Re: Device Dashboard for Dummies
« Reply #18 on: September 09, 2015, 11:23:00 pm »
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:
Code: [Select]
style += ".altui-sonos-text, .altui-combsw-text, .altui-sysmon-text, .altui-veraalerts-text {font-size: 11px;}";
Plus the usual:
Code: [Select]
"urn:richardgreen:device:VeraAlert:1":{"DeviceDrawFunc":"ALTUI_PluginDisplays.drawVeraAlerts","ScriptFile":"J_ALTUI_plugins.js"},
Code: [Select]
    drawVeraAlerts  : _drawVeraAlerts,
Code: [Select]
    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
VeraPlus, UI7, ALTUI on Chrome, Lots of devices and plugins including MQTT and MySensors.  Also playing around with openLuup

Offline dklinkman

  • Full Member
  • ***
  • Posts: 129
  • Karma: +1/-0
Re: Device Dashboard for Dummies
« Reply #19 on: September 09, 2015, 11:49:23 pm »
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:
Code: [Select]
"urn:schemas-micasaverde-com:device:TempLeakSensor:1":{"DeviceDrawFunc":"ALTUI_PluginDisplays.drawTempLeak","ScriptFile":"J_ALTUI_plugins.js"},
Code: [Select]
    drawTempLeak    : _drawTempLeak,
Code: [Select]
    function _drawTempLeak( device ) {
        return _drawTempSensor(device);
    }

Thanks!!!     --David
VeraPlus, UI7, ALTUI on Chrome, Lots of devices and plugins including MQTT and MySensors.  Also playing around with openLuup

Offline dklinkman

  • Full Member
  • ***
  • Posts: 129
  • Karma: +1/-0
Re: Device Dashboard for Dummies
« Reply #20 on: September 10, 2015, 12:50:03 am »
Sorry.  Realized after the fact that this is not just a water/temp sensor but a security sensor.  So it needs an arm/bypass switch and i also managed to get the last tripped in there without compromising the temperature reading.  Updated and somewhat more complicated method attached.

Code: [Select]
    function _drawTempLeak( device ) {
        var html = "";
        var armed = parseInt(MultiBox.getStatus( device, 'urn:micasaverde-com:serviceId:SecuritySensor1', 'Armed' ));
html += _createOnOffButton( armed,"altui-onoffbtn-"+device.altuiid, _T("Bypass,Arm"), "pull-right" );
        html += _drawTempSensor(device);
        var lasttrip = MultiBox.getStatus( device, 'urn:micasaverde-com:serviceId:SecuritySensor1', 'LastTrip' );
if (lasttrip != null) {
var lasttripdate = _toIso(new Date(lasttrip*1000),' ');
html+= "<div class='altui-lasttrip-text text-muted'>{0} {1} </div>".format( timeGlyph,lasttripdate );
}
html += "<script type='text/javascript'>";
html += " $('div#altui-onoffbtn-{0}').on('click touchend', function() { ALTUI_PluginDisplays.toggleArmed('{0}','div#altui-onoffbtn-{0}'); } );".format(device.altuiid);
html += "</script>";
        return html;
    }
VeraPlus, UI7, ALTUI on Chrome, Lots of devices and plugins including MQTT and MySensors.  Also playing around with openLuup

Offline amg0

  • Moderator
  • Master Member
  • *****
  • Posts: 3174
  • Karma: +209/-8
Re: Device Dashboard for Dummies
« Reply #21 on: September 10, 2015, 11:58:02 am »
Sorry.  Realized after the fact that this is not just a water/temp sensor but a security sensor.  So it needs an arm/bypass switch and i also managed to get the last tripped in there without compromising the temperature reading.  Updated and somewhat more complicated method attached.

Code: [Select]
    function _drawTempLeak( device ) {
        var html = "";
        var armed = parseInt(MultiBox.getStatus( device, 'urn:micasaverde-com:serviceId:SecuritySensor1', 'Armed' ));
html += _createOnOffButton( armed,"altui-onoffbtn-"+device.altuiid, _T("Bypass,Arm"), "pull-right" );
        html += _drawTempSensor(device);
        var lasttrip = MultiBox.getStatus( device, 'urn:micasaverde-com:serviceId:SecuritySensor1', 'LastTrip' );
if (lasttrip != null) {
var lasttripdate = _toIso(new Date(lasttrip*1000),' ');
html+= "<div class='altui-lasttrip-text text-muted'>{0} {1} </div>".format( timeGlyph,lasttripdate );
}
html += "<script type='text/javascript'>";
html += " $('div#altui-onoffbtn-{0}').on('click touchend', function() { ALTUI_PluginDisplays.toggleArmed('{0}','div#altui-onoffbtn-{0}'); } );".format(device.altuiid);
html += "</script>";
        return html;
    }
thanks ! should we have a tripped indicator like the motion sensor with it too ?

Offline dklinkman

  • Full Member
  • ***
  • Posts: 129
  • Karma: +1/-0
Re: Device Dashboard for Dummies
« Reply #22 on: September 10, 2015, 02:58:52 pm »
Quote
thanks ! should we have a tripped indicator like the motion sensor with it too ?

I suppose it should.  I tried putting a small tripped indicator below the date/time but it looked silly so I took it out.

Maybe to the right of the date/time if that can work.  It's not like it's going to appear all that often
VeraPlus, UI7, ALTUI on Chrome, Lots of devices and plugins including MQTT and MySensors.  Also playing around with openLuup

Offline dklinkman

  • Full Member
  • ***
  • Posts: 129
  • Karma: +1/-0
Re: Device Dashboard for Dummies
« Reply #23 on: September 13, 2015, 11:51:46 pm »
amg0, here's yet another dashboard.  This time for the beloved multi string container.  This one's a little busy.  You can fill in the missing parts I hope.

Code: [Select]
"urn:schemas-upnp-org:device:VContainer:1":{"DeviceDrawFunc":"ALTUI_PluginDisplays.drawMultiString","ScriptFile":"J_ALTUI_plugins.js"},
classes for '_getStyle'
Code: [Select]
style += ".altui-multistring-text-div { margin-top: 2px; height: 48px; overflow: hidden; }"
        style += ".altui-multistring-text-some { font-size: 11px; }";
        style += ".altui-multistring-text-all { font-size: 7px; }";
style += ".altui-multistring-text-1, .altui-multistring-text-2 { }";

And the method:
Code: [Select]
// return the html string inside the .panel-body of the .altui-device#id panel
    function _drawMultiString( device ) {
        var html = "";
        html += "<div class='btn-group pull-right'>";
        html += " <button id='altui-allbtn-{0}' type='button' class='altui-window-btn btn btn-default btn-xs'>{1}</button>".format( device.altuiid,_T("All"));
        html += " <button id='altui-morebtn-{0}' type='button' class='altui-window-btn btn btn-default btn-xs'>{1}</button>".format( device.altuiid,_T("More"));
        html += "</div>";
        html += "<div class='altui-multistring-text-div'>";
        for (var v = 1; v <= 5 ; v++) {
            var label = MultiBox.getStatus( device, 'urn:upnp-org:serviceId:VContainer1', "VariableName" + v );
            var value = MultiBox.getStatus( device, 'urn:upnp-org:serviceId:VContainer1', "Variable" + v );
            var style = "class='altui-multistring-text-some altui-multistring-text-1 text-muted'";
            if (v > 3) { style = "class='altui-multistring-text-some altui-multistring-text-2 text-muted' style='display: none;'"; }
            if (label != null && value != null) {
                html += $(" <div " + style + "></div>").text(label + ": " + value).wrap( "<div></div>" ).parent().html()
            }
        }
        html += "</div>";
        html += "<script type='text/javascript'>";           
        html += " $('button#altui-allbtn-{0}').on('click', function() { $('.altui-multistring-text-some').removeClass('altui-multistring-text-some').addClass('altui-multistring-text-all').show(); $('#altui-morebtn-{0}').html('Less'); });".format(device.altuiid);           
        html += " $('button#altui-morebtn-{0}').on('click', function() { var ml = $(this).html(); if (ml == 'Less') { $('.altui-multistring-text-all').removeClass('altui-multistring-text-all').addClass('altui-multistring-text-some'); $('.altui-multistring-text-2').hide(); $('#altui-morebtn-{0}').html('More'); } else { $('.altui-multistring-text-1').toggle(); $('.altui-multistring-text-2').toggle(); } });".format(device.altuiid);           
        html += "</script>";
        return html;
    }

Basically the MultiString plugin supports 5 labels and variables and the dashboard initially displays the first 3.  If they are not too wordy they should display ok.  The buttons can display all 5 with reduced font, or can toggle between the first 3, or last 2.  An altui refresh which happens occasionally will reset the presentation.  But that's life.

Thanks!!!   --David
VeraPlus, UI7, ALTUI on Chrome, Lots of devices and plugins including MQTT and MySensors.  Also playing around with openLuup

Offline amg0

  • Moderator
  • Master Member
  • *****
  • Posts: 3174
  • Karma: +209/-8
Re: Device Dashboard for Dummies
« Reply #24 on: September 14, 2015, 02:13:42 am »
amg0, here's yet another dashboard.  This time for the beloved multi string container.  This one's a little busy.  You can fill in the missing parts I hope.

Code: [Select]
"urn:schemas-upnp-org:device:VContainer:1":{"DeviceDrawFunc":"ALTUI_PluginDisplays.drawMultiString","ScriptFile":"J_ALTUI_plugins.js"},
classes for '_getStyle'
Code: [Select]
style += ".altui-multistring-text-div { margin-top: 2px; height: 48px; overflow: hidden; }"
        style += ".altui-multistring-text-some { font-size: 11px; }";
        style += ".altui-multistring-text-all { font-size: 7px; }";
style += ".altui-multistring-text-1, .altui-multistring-text-2 { }";

And the method:
Code: [Select]
// return the html string inside the .panel-body of the .altui-device#id panel
    function _drawMultiString( device ) {
        var html = "";
        html += "<div class='btn-group pull-right'>";
        html += " <button id='altui-allbtn-{0}' type='button' class='altui-window-btn btn btn-default btn-xs'>{1}</button>".format( device.altuiid,_T("All"));
        html += " <button id='altui-morebtn-{0}' type='button' class='altui-window-btn btn btn-default btn-xs'>{1}</button>".format( device.altuiid,_T("More"));
        html += "</div>";
        html += "<div class='altui-multistring-text-div'>";
        for (var v = 1; v <= 5 ; v++) {
            var label = MultiBox.getStatus( device, 'urn:upnp-org:serviceId:VContainer1', "VariableName" + v );
            var value = MultiBox.getStatus( device, 'urn:upnp-org:serviceId:VContainer1', "Variable" + v );
            var style = "class='altui-multistring-text-some altui-multistring-text-1 text-muted'";
            if (v > 3) { style = "class='altui-multistring-text-some altui-multistring-text-2 text-muted' style='display: none;'"; }
            if (label != null && value != null) {
                html += $(" <div " + style + "></div>").text(label + ": " + value).wrap( "<div></div>" ).parent().html()
            }
        }
        html += "</div>";
        html += "<script type='text/javascript'>";           
        html += " $('button#altui-allbtn-{0}').on('click', function() { $('.altui-multistring-text-some').removeClass('altui-multistring-text-some').addClass('altui-multistring-text-all').show(); $('#altui-morebtn-{0}').html('Less'); });".format(device.altuiid);           
        html += " $('button#altui-morebtn-{0}').on('click', function() { var ml = $(this).html(); if (ml == 'Less') { $('.altui-multistring-text-all').removeClass('altui-multistring-text-all').addClass('altui-multistring-text-some'); $('.altui-multistring-text-2').hide(); $('#altui-morebtn-{0}').html('More'); } else { $('.altui-multistring-text-1').toggle(); $('.altui-multistring-text-2').toggle(); } });".format(device.altuiid);           
        html += "</script>";
        return html;
    }

Basically the MultiString plugin supports 5 labels and variables and the dashboard initially displays the first 3.  If they are not too wordy they should display ok.  The buttons can display all 5 with reduced font, or can toggle between the first 3, or last 2.  An altui refresh which happens occasionally will reset the presentation.  But that's life.

Thanks!!!   --David

thank you. I integrated as is for now.

ALTUI has an object for persistent settings.

to read from it
Code: [Select]
var value = MyLocalStorage.getSettings('MYSETTINGSNAME');
to save into it
Code: [Select]
MyLocalStorage.setSettings("MYSETTINGSNAME",value);

Offline dklinkman

  • Full Member
  • ***
  • Posts: 129
  • Karma: +1/-0
Re: Device Dashboard for Dummies
« Reply #25 on: September 14, 2015, 04:05:57 pm »
Here's another update for the MultiSwitch dashboard that incorporates your suggestions regarding localized strings and using the object persistence.

So the device will always show a default view when first displayed or when altui is reloaded or refreshed in the browser.  If any other view is selected it will persist through presentation updates, like after a variable is changed.  The javascript is a little crazy but it seems to work well.
Code: [Select]
    // return the html string inside the .panel-body of the .altui-device#id panel
    function _drawMultiString( device ) {
        var html = ""; var sAll = _T("All"); var sMore = _T("More"); var sLess = _T("Less");
        if ($('button#altui-morebtn-'+device.altuiid).html() == undefined) {
            var initstate = {}; initstate['devicestate'] = 0;
            MyLocalStorage.setSettings("MULTISTRINGUISTATE"+device.altuiid, initstate);
        }       
        var state = MyLocalStorage.getSettings("MULTISTRINGUISTATE"+device.altuiid);
        var display = state != null ? state['devicestate'] : 0;
        html += "<div class='btn-group pull-right'>";
        html += " <button id='altui-allbtn-{0}' type='button' class='altui-window-btn btn btn-default btn-xs'>{1}</button>".format( device.altuiid,sAll);
        html += " <button id='altui-morebtn-{0}' type='button' class='altui-window-btn btn btn-default btn-xs'>{1}</button>".format( device.altuiid,(display != 2 ? sMore : sLess));
        html += "</div>";
        html += "<div class='altui-multistring-text-div'>";
        for (var v = 1; v <= 5 ; v++) {
            var label = MultiBox.getStatus( device, 'urn:upnp-org:serviceId:VContainer1', "VariableName" + v );
            var value = MultiBox.getStatus( device, 'urn:upnp-org:serviceId:VContainer1', "Variable" + v );
            var style = "";
            if (v <= 3) { style = "class='" + (display != 2 ? "altui-multistring-text-some" : "altui-multistring-text-all") + " altui-multistring-text-1 text-muted'"; }
            else {
                style = "class='" + (display != 2 ? "altui-multistring-text-some" : "altui-multistring-text-all") + " altui-multistring-text-2 text-muted'";
                if (display != 2) { style += " style='display: none;'"; }
            }           
            if (label != null && value != null) {
                html += $(" <div " + style + "></div>").text(label + ": " + value).wrap( "<div></div>" ).parent().html();
            }
        }
        html += "</div>";
        html += "<script type='text/javascript'>";
        html += " var state = MyLocalStorage.getSettings('MULTISTRINGUISTATE{0}');".format(device.altuiid);
        html += " if (state['devicestate'] == 1) { $('.altui-multistring-text-1').toggle(); $('.altui-multistring-text-2').toggle(); }";
        html += " $('button#altui-allbtn-{0}').on('click', function() { $('.altui-multistring-text-some').removeClass('altui-multistring-text-some').addClass('altui-multistring-text-all').show(); $('#altui-morebtn-{0}').html('{1}'); state['devicestate'] = 2; MyLocalStorage.setSettings('MULTISTRINGUISTATE{0}', state); });".format(device.altuiid,sLess);           
        html += " $('button#altui-morebtn-{0}').on('click', function() { if ($(this).html() == '{1}') { $('.altui-multistring-text-all').removeClass('altui-multistring-text-all').addClass('altui-multistring-text-some'); $('.altui-multistring-text-2').hide(); $('#altui-morebtn-{0}').html('{2}'); state['devicestate'] = 0; MyLocalStorage.setSettings('MULTISTRINGUISTATE{0}', state); } else { $('.altui-multistring-text-1').toggle(); $('.altui-multistring-text-2').toggle(); state['devicestate'] = state['devicestate'] == 0 ? 1 : 0; MyLocalStorage.setSettings('MULTISTRINGUISTATE{0}', state); } });".format(device.altuiid,sLess,sMore);           
        html += "</script>";
        return html;
    }

Thanks!!!    --David
VeraPlus, UI7, ALTUI on Chrome, Lots of devices and plugins including MQTT and MySensors.  Also playing around with openLuup

Offline amg0

  • Moderator
  • Master Member
  • *****
  • Posts: 3174
  • Karma: +209/-8
Re: Device Dashboard for Dummies
« Reply #26 on: September 14, 2015, 04:54:55 pm »
Here's another update for the MultiSwitch dashboard that incorporates your suggestions regarding localized strings and using the object persistence.

So the device will always show a default view when first displayed or when altui is reloaded or refreshed in the browser.  If any other view is selected it will persist through presentation updates, like after a variable is changed.  The javascript is a little crazy but it seems to work well.
Code: [Select]
    // return the html string inside the .panel-body of the .altui-device#id panel
    function _drawMultiString( device ) {
        var html = ""; var sAll = _T("All"); var sMore = _T("More"); var sLess = _T("Less");
        if ($('button#altui-morebtn-'+device.altuiid).html() == undefined) {
            var initstate = {}; initstate['devicestate'] = 0;
            MyLocalStorage.setSettings("MULTISTRINGUISTATE"+device.altuiid, initstate);
        }       
        var state = MyLocalStorage.getSettings("MULTISTRINGUISTATE"+device.altuiid);
        var display = state != null ? state['devicestate'] : 0;
        html += "<div class='btn-group pull-right'>";
        html += " <button id='altui-allbtn-{0}' type='button' class='altui-window-btn btn btn-default btn-xs'>{1}</button>".format( device.altuiid,sAll);
        html += " <button id='altui-morebtn-{0}' type='button' class='altui-window-btn btn btn-default btn-xs'>{1}</button>".format( device.altuiid,(display != 2 ? sMore : sLess));
        html += "</div>";
        html += "<div class='altui-multistring-text-div'>";
        for (var v = 1; v <= 5 ; v++) {
            var label = MultiBox.getStatus( device, 'urn:upnp-org:serviceId:VContainer1', "VariableName" + v );
            var value = MultiBox.getStatus( device, 'urn:upnp-org:serviceId:VContainer1', "Variable" + v );
            var style = "";
            if (v <= 3) { style = "class='" + (display != 2 ? "altui-multistring-text-some" : "altui-multistring-text-all") + " altui-multistring-text-1 text-muted'"; }
            else {
                style = "class='" + (display != 2 ? "altui-multistring-text-some" : "altui-multistring-text-all") + " altui-multistring-text-2 text-muted'";
                if (display != 2) { style += " style='display: none;'"; }
            }           
            if (label != null && value != null) {
                html += $(" <div " + style + "></div>").text(label + ": " + value).wrap( "<div></div>" ).parent().html();
            }
        }
        html += "</div>";
        html += "<script type='text/javascript'>";
        html += " var state = MyLocalStorage.getSettings('MULTISTRINGUISTATE{0}');".format(device.altuiid);
        html += " if (state['devicestate'] == 1) { $('.altui-multistring-text-1').toggle(); $('.altui-multistring-text-2').toggle(); }";
        html += " $('button#altui-allbtn-{0}').on('click', function() { $('.altui-multistring-text-some').removeClass('altui-multistring-text-some').addClass('altui-multistring-text-all').show(); $('#altui-morebtn-{0}').html('{1}'); state['devicestate'] = 2; MyLocalStorage.setSettings('MULTISTRINGUISTATE{0}', state); });".format(device.altuiid,sLess);           
        html += " $('button#altui-morebtn-{0}').on('click', function() { if ($(this).html() == '{1}') { $('.altui-multistring-text-all').removeClass('altui-multistring-text-all').addClass('altui-multistring-text-some'); $('.altui-multistring-text-2').hide(); $('#altui-morebtn-{0}').html('{2}'); state['devicestate'] = 0; MyLocalStorage.setSettings('MULTISTRINGUISTATE{0}', state); } else { $('.altui-multistring-text-1').toggle(); $('.altui-multistring-text-2').toggle(); state['devicestate'] = state['devicestate'] == 0 ? 1 : 0; MyLocalStorage.setSettings('MULTISTRINGUISTATE{0}', state); } });".format(device.altuiid,sLess,sMore);           
        html += "</script>";
        return html;
    }

Thanks!!!    --David
ok integrated for next release

Offline dklinkman

  • Full Member
  • ***
  • Posts: 129
  • Karma: +1/-0
Re: Device Dashboard for Dummies
« Reply #27 on: September 14, 2015, 08:43:19 pm »
Here's a little/simple one for a change.  For the UPnP Proxy device.  All it does really is display the status text.

Code: [Select]
"urn:schemas-futzle-com:device:UPnPProxy:1":{"DeviceDrawFunc":"ALTUI_PluginDisplays.drawPnPProxy","ScriptFile":"J_ALTUI_plugins.js"},
Code: [Select]
style += ".altui-upnpproxy-text { font-size: 11px; margin-left: 2px; margin-top: 22px; }";
Code: [Select]
    // return the html string inside the .panel-body of the .altui-device#id panel
    function _drawPnPProxy( device ) {
        var html = "";
        var status = MultiBox.getStatus( device, 'urn:futzle-com:serviceId:UPnPProxy1', 'StatusText' );
        if (status != null) {
            html += "<div class='altui-upnpproxy-text text-muted'>Status: {0}</div>".format(status);
        }
        return html;
    }

Thanks!!!      --David
« Last Edit: September 14, 2015, 08:47:24 pm by dklinkman »
VeraPlus, UI7, ALTUI on Chrome, Lots of devices and plugins including MQTT and MySensors.  Also playing around with openLuup

Offline dklinkman

  • Full Member
  • ***
  • Posts: 129
  • Karma: +1/-0
Re: Device Dashboard for Dummies
« Reply #28 on: September 20, 2015, 09:24:34 pm »
Hey amg0,  Here's another dashboard for you.  I think the last one I might do for awhile, since I have covered everything I install and use that you haven't already done.  7 buttons on the dashboard.  Plus a countdown timer.  This time for the Program Logic Timer Switch device.  And it's a busy one.  But it seems to work well enough.

param:
Code: [Select]
"urn:schemas-rts-services-com:device:ProgramLogicTS:1":{"ScriptFile":"J_ALTUI_plugins.js","DeviceDrawFunc":"ALTUI_PluginDisplays.drawProgLogicTimerSwitch"},
mapping:
Code: [Select]
drawProgLogicTimerSwitch: _drawProgLogicTimerSwitch,
styles:
Code: [Select]
style += ".altui-plts-btn-div { margin-top: 4px; height: 48px; overflow:hidden; } .altui-plts-btn { width: 50px; font-size: 11px; line-height: 1.5; } .altui-plts-btn-on { color: white; background-color: #006C44; } .altui-plts-btn-on:hover, .altui-plts-btn-on:focus, .altui-plts-btn-on:active, .altui-plts-btn-on:active:focus, .altui-plts-btn-on.active:focus { color: white; background-color: #006C44; outline: 0 none; box-shadow: none; } .altui-plts-time-text-div { float: left; margin-left: 6px; margin-top: 5px; font-size: 9px; overflow: hidden; }";
the method
Code: [Select]
    function _drawProgLogicTimerSwitch( device ) {
        var html = "";
        var onoff = MultiBox.getStatus(device, 'urn:rts-services-com:serviceId:ProgramLogicTS', 'Status');
        var armed = MultiBox.getStatus(device, 'urn:rts-services-com:serviceId:ProgramLogicTS', 'Armed');
        var state = MultiBox.getStatus(device, 'urn:rts-services-com:serviceId:ProgramLogicTS', 'State');
        var rtime = MultiBox.getStatus(device, 'urn:rts-services-com:serviceId:ProgramLogicTS', 'TimeRemaining');
        html += "<div class='pull-right altui-plts-btn-div'>";
        html += " <div class='btn-group'>";
        html += "  <button id='altui-armbtn-{0}' type='button' class='altui-plts-btn btn btn-default btn-xs {2}'>{1}</button>".format(device.altuiid, _T("Arm"), armed==1?'altui-plts-btn-on':'');
        html += "  <button id='altui-bypassbtn-{0}' type='button' class='altui-plts-btn btn btn-default btn-xs {2}'>{1}</button>".format(device.altuiid, _T("Bypass"), armed==0?'altui-plts-btn-on':'');
        html += "  <button id='altui-triggerbtn-{0}' type='button' class='altui-plts-btn btn btn-default btn-xs'>{1}</button>".format(device.altuiid, _T("Trigger"));
        html += "  <button id='altui-restartbtn-{0}' type='button' class='altui-plts-btn btn btn-default btn-xs'>{1}</button>".format(device.altuiid, _T("Restart"));
        html += " </div><br>";
        html += " <div class='btn-group'>";
        html += "  <button id='altui-onbtn-{0}' type='button' class='altui-plts-btn btn btn-default btn-xs {2}'>{1}</button>".format(device.altuiid, _T("On"), onoff==1?'altui-plts-btn-on':'');
        html += "  <button id='altui-offbtn-{0}' type='button' class='altui-plts-btn btn btn-default btn-xs {2}'>{1}</button>".format(device.altuiid, _T("Off"), onoff==0?'altui-plts-btn-on':'');
        html += "  <button id='altui-resetbtn-{0}' type='button' class='altui-plts-btn btn btn-default btn-xs {2}'>{1}</button>".format(device.altuiid, _T("Reset"), state==0?'altui-plts-btn-on':'');
        if (state == 3 && rtime != null) {
            var h = '00'; var m = '00'; var s = '00'; var hms = rtime.split(':');
            if ( hms.length == 3) { h = hms[0]; m = hms[1]; s = hms[2] } else if ( hms.length == 2) { m = hms[0]; s = hms[1] } else { s = hms[0] }
            html += "<div id='altui-plts-rtime' class='altui-plts-time-text-div text-muted'>" + "{0}:{1}:{2}".format(h,m,s) + "</div>";           
        }
        html += " </div>";
        html += "</div>";
        html += "<script type='text/javascript'>";
        html += " function resizepltbtn() { var w = $('div.altui-device-body').width(); w=w<250?(w-50)/4:50; $('button.altui-plts-btn').css('width', w); $('#altui-plts-rtime').css('width', w-8).css('overflow', 'hidden'); }; resizepltbtn();";
        html += " $(window).resize(function(){ resizepltbtn(); });"
        html += " $('button#altui-restartbtn-{0}').on('click', function() { var device = MultiBox.getDeviceByAltuiID('{0}'); var state = MultiBox.getStatus(device, 'urn:rts-services-com:serviceId:ProgramLogicTS', 'State'); if (state==3) { MultiBox.runActionByAltuiID('{0}','urn:rts-services-com:serviceId:ProgramLogicTS','SetState',{'newStateValue':'2'}); $('button#altui-restartbtn-{0}').addClass('altui-plts-btn-on'); } });".format(device.altuiid);
        html += " $('button#altui-triggerbtn-{0}').on('click', function() { MultiBox.runActionByAltuiID('{0}','urn:rts-services-com:serviceId:ProgramLogicTS','SetState',{'newStateValue':'1'}); $('button#altui-triggerbtn-{0}').addClass('altui-plts-btn-on'); });".format(device.altuiid);
        html += " $('button#altui-bypassbtn-{0}').on('click', function() { MultiBox.runActionByAltuiID('{0}','urn:rts-services-com:serviceId:ProgramLogicTS','SetArmed',{'newArmedValue':'0'}); $('button#altui-bypassbtn-{0}').addClass('altui-plts-btn-on'); $('button#altui-armbtn-{0}').removeClass('altui-plts-btn-on'); });".format(device.altuiid);
        html += " $('button#altui-armbtn-{0}').on('click', function() { MultiBox.runActionByAltuiID('{0}','urn:rts-services-com:serviceId:ProgramLogicTS','SetArmed',{'newArmedValue':'1'}); $('button#altui-armbtn-{0}').addClass('altui-plts-btn-on'); $('button#altui-bypassbtn-{0}').removeClass('altui-plts-btn-on'); });".format(device.altuiid);
        html += " $('button#altui-resetbtn-{0}').on('click', function() { MultiBox.runActionByAltuiID('{0}','urn:rts-services-com:serviceId:ProgramLogicTS','SetState',{'newStateValue':'0'}); $('button#altui-resetbtn-{0}').addClass('altui-plts-btn-on'); });".format(device.altuiid);
        html += " $('button#altui-offbtn-{0}').on('click', function() { MultiBox.runActionByAltuiID('{0}','urn:rts-services-com:serviceId:ProgramLogicTS','SetTarget',{'newTargetValue':'0'}); $('button#altui-offbtn-{0}').addClass('altui-plts-btn-on'); $('button#altui-onbtn-{0}').removeClass('altui-plts-btn-on'); });".format(device.altuiid);
        html += " $('button#altui-onbtn-{0}').on('click', function() { MultiBox.runActionByAltuiID('{0}','urn:rts-services-com:serviceId:ProgramLogicTS','SetTarget',{'newTargetValue':'1'}); $('button#altui-onbtn-{0}').addClass('altui-plts-btn-on'); $('button#altui-offbtn-{0}').removeClass('altui-plts-btn-on'); });".format(device.altuiid);
        html += "</script>";
        return html;
    }

Enjoy.  Thanks!!!    --David
VeraPlus, UI7, ALTUI on Chrome, Lots of devices and plugins including MQTT and MySensors.  Also playing around with openLuup

Offline a-lurker

  • Hero Member
  • *****
  • Posts: 872
  • Karma: +66/-8
Re: Device Dashboard for Dummies
« Reply #29 on: September 28, 2015, 09:29:25 pm »
Thought I have ago. This is for the Arduino MySensors plugin:

Code: [Select]
    "urn:schemas-arduino-cc:device:arduino:1": {
        "DeviceDrawFunc": "ALTUI_PluginDisplays.drawMySensors",
        "ScriptFile": "J_ALTUI_plugins.js"
    },

Code: [Select]
drawMySensors   : _drawMySensors,

Code: [Select]
    function _drawMySensors( device) {
        var including = MultiBox.getStatus(device, 'urn:upnp-arduino-cc:serviceId:arduino1', 'InclusionMode');

        var html = "";
        html += "<div class='text-muted'>Press Start to include"

        html += "<div class='pull-right'>";
        html += ("<button id ='altui-arduino-include-start-{0}' type='button' class='altui-window-btn btn btn-default btn-sm {1}'>"+_T("Start")+"</button>").format(device.altuiid, (including==1) ? 'active' : '' );
        html += ("<button id ='altui-arduino-include-stop-{0}'  type='button' class='altui-window-btn btn btn-default btn-sm {1}'>"+_T("Stop") +"</button>").format(device.altuiid, (including==0) ? 'active' : '' );
        html += "</div></div>";

        html += "<script type='text/javascript'>";
        html += "$('button#altui-arduino-include-start-{0}').on('click', function() { MultiBox.runActionByAltuiID('{0}', 'urn:upnp-arduino-cc:serviceId:arduino1', 'StartInclusion', {}); } );".format(device.altuiid);
        html += "$('button#altui-arduino-include-stop-{0}').on ('click', function() { MultiBox.runActionByAltuiID('{0}', 'urn:upnp-arduino-cc:serviceId:arduino1', 'StopInclusion',  {}); } );".format(device.altuiid);
        html += "</script>";

        return html;
    };

Feel free to rehash this, if needed, as I'm not really too sure of the syntax of all of this stuff but is seems to work.
« Last Edit: September 29, 2015, 12:03:55 am by a-lurker »