[RELEASE] HousePanel Dashboard for SmartThings and Hubitat

Great work, and surprisingly not that complicated to implement. One more bug fix request. Custom frames that were given a new name worked great initially, but would reset to their old names (forecast.html) on the slow_poll, which is rarely called. I tracked the bug down to housepanel.php line 1270. You can replace $fn = $defaultname with:

        // get custom tile name if it was defined in tile editor and stored
        // in the room array - this is a temp fix until I change the architecture
        // to stre custom names in the index of things instead
        $customname= "";
        $rooms = $options["rooms"];
        $thingoptions = $options["things"];
        $tileid = $options["index"]["frame|".$frameid];
        foreach ($rooms as $room => $ridx) {
            if ( array_key_exists($room, $thingoptions) ) {
               $things = $thingoptions[$room];
               foreach ($things as $kindexarr) {
                  // only do this if we have custom names defined in rooms
                  if ( is_array($kindexarr) && count($kindexarr) > 3 ) {
                     $kindex = $kindexarr[0];
                     // if our tile matches and there is a custom name, use it
                     if ( intval($kindex)===intval($tileid) ) {
                        $customname = $kindexarr[4];
                        if ( $customname!=="" ) { break; }
                     }
                  }
               }
            }
            if ( $customname!=="" ) { break; }
        }


        $fn = $defaultname;
        if ( $customname ) {
           $fn = $customname;
        }
1 Like

Brilliant bug catch and fix. Amazed at how quickly you learned how this code works.

This makes me wonder if I left a few other dangling errors in the code.

Many thanks for this.

[edit] sure enough this same error cause the new album art to disappear upon refresh. I have a fix that will get uploaded soon. Same for video tiles.

Still fine tuning this. Turns out there are two ways to provide a custom name. One in the TileEditor and one in the TileCustomizer. So I need code to deal with both cases. The fix above works for the TileEditor but not the TileCustomizer. I posted a TileCustomizer fix that broke the above fix so I withdrew it.

Okay posted update but I have to warn you that I also discovered that trackDescription is no longer returned by ST properly. Not sure why. So this means the album art still won’t show unless you are using Hubitat. [EDIT] Resolved with a Hub reboot so ignore this warning.

The issue with custom names and edited names is also fixed in this update.

Update to implement native Echo Speaks album art in addition to the Sonos album art method. Still have some kinks to work out but its a start. Should work - would love to see some feedback from people with Echo Speaks installed. If anyone has speakers other than Sonos I would love to know if this works with those too.

Here’s a screen shot of the new Album Art generator in action. In honor of Doris Day who passed away this week that is what I was listening to when I took the screen shot. This screen shot also shows a custom tile that shows off this feature too.

1 Like

Release V2.064 tonight.

Minor tweak to enable linked Music Controls, such as what is shown in the custom tile in the example above, to work. Also improved the stability and robustness of the Album Art feature. A number of minor and very obscure bug fixes in this update too.

One more little bug fix to get the slow refresh frames right. housepanel.php line 2356 should be

$customname = getCustomName($thing["name"], $thing["id"], $thingtype, $options);

because you were using $swid in a different way here. I pulled the latest (yesterday’s latest) and confirmed the echo speaks album art works great out of the box.

Finally - I’m thinking of adding support for more custom frames later. I already have 4, so when I find one more thing I want to do I’ll probably get around to it. The easy way of just bumping the counter should work, but I’ll think about a better approach.

Thanks for finding this bug. Good catch as always.

Take a look at the code in the Options page creator that enables any number of custom tiles to be created (search for ā€œcustomcntā€). We could add this same logic for frames so that the user can select how many frames to generate. For that matter while we’re at it we should probably enable that for video tiles too. Unfortunately Image and Blank tiles are done in the groovy code - although they could be moved over to PHP too for similar functionality.

I suppose a fast and lazy fix would involve using customcnt to control how many frame, video, and custom tiles to use.

Speaking of images! I just figured out how to take periodic snapshots from my ring doorbells and run them through ffmpeg to extract an image frame. I set that as the background-image in one of my imgX.jpg tiles. All good so far. Two follow ups from here though.

  1. How can I get the background-image to refresh when the content changes on the server? I think the only way to do this reliably is to update the housepanel.js to append some random noise on the end of the imgX.jpg path on every fast refresh. I guess updateTile could look for key===ā€œurlā€ and then check if the div has a background-image, and if so, append ? so that it busts the local cache. Seems pretty ugly. Do you have any better ideas or am I missing something obvious?

  2. I would love it so that if I click on this tile it pops up the full video (which is available in the video1 tile, but I don’t want that looping all the time). What’s the right way to set an onclick handler for a tile that does something (creates a new window with a specific URL)?

Thanks.

1 Like

Please do share how you did this.

As for refreshing the background image I think the best way is to just restate the name of the background in the .js file.

Make an on.click jQuery function that opens a new window via JavaScript. I do this in the tileeditor in several places. Also in the main housepanel.js code for opening confirmation dialog boxes.

I had another thought. You could link the video to the image tile using the customizer and then hide the video normally. Then when you click the image the code would check for a sibling video subid- and if found a window opens and it plays. The code to link and hide are there but to show a sibling in a window isn’t. Don’t think it would be hard. Another idea is code could look for a user added text field called something like ā€œonclickā€ with the value being the name of the video file to play. I actually like this idea better as it is more flexible.

As I am working on user configurable number of frame tiles and video tiles — just like custom tiles, I am realizing that I should have implemented blanks and images on the PHP web app side and not on the groovy Hub side. Swapping it is relatively easy and will give users the flexibility to change the content of images and the number of blanks and images in the app just like custom today.

The only down side is it will break any prior setups that use groovy generated blanks or images. So I’m wondering how many people really use this. Blanks aren’t that useful anymore now that HP has random positioning support and custom tiles are better blanks, and image tiles are clunky with a required CSS hack. The new one will be much better with any file name supported and image size control. While I am at it I will implement image clicking expanding the image or playing any video tied to a custom field. Note sure what name I will use yet.

Please post here any concerns you have about this pending fairly major design change to HousePanel.

Good stuff. I think the image tiles were unlikely heavily used because of the way you could only get them to work with CSS, the URL returned on fast polls isn’t that helpful since it’s not wrapped in an img tag.

As you’re thinking through the use cases, I’ll share how I got mine to work with ring doorbells / cams to always show the most recent action.

  1. use the ring doorbell python package from:
    https://github.com/tchellomello/python-ring-doorbell

  2. create a python script that runs every few minutes to download the latest videos:

    doorbells = list(myring.stickup_cams + myring.doorbells)
    for i in range(len(doorbells)):
    db = doorbells[i]
    history = db.history(limit=1)
    fname = ā€œdata/%s.mp4ā€ % history[0][ā€˜id’]
    if not os.path.isfile(fname):
    db.recording_download(history[0][ā€˜id’], filename=fname, override=True)

  3. Then run create a symlink to that video so that we keep all the old ones around but always refer to the newest one:

    try:
    os.remove(ā€œvideo%s.mp4ā€ % (i+1)) # remove a link if it exists otherwise we get errors
    except:
    pass
    os.symlink(fname, ā€œvideo%s.mp4ā€ % (i+1))

  4. Finally, run that video through ffmpeg to scrape out a frame 6 seconds in (hopefully something useful will be there)

    os.system("ffmpeg -y -ss 00:00:06 -i video%s.mp4 -vframes 1 -vf ā€œtext=’%{localtime}’: x=w-tw: y=h-lh: " -vcodec png img%s.pngā€ % (i+1, i+1))

  5. Create image tiles and link in some CSS to point to the png files that our script is creating:

    div.image.url.img1 {
    background-image: url(…/ring/img1.png);
    background-size: cover;
    }

  6. This works great, except the browser will cache these images so they’ll never get updated even when they change on the server. So we need to add some code to force a refresh. In housepanel.js around line 1814 (after if key === color):

    } else if ( key === ā€œurlā€) {
    bg_old = $(targetid).css(ā€˜backgroundImage’);
    if(bg_old.toLowerCase().startsWith(ā€œurl(ā€) && bg_old.endsWith(")")){
    cache_busting_date = new Date().toUTCString();

                 if(bg_old.indexOf("?") > -1){
                     bg_new = bg_old.substring(0, bg_old.indexOf("?")+1) + cache_busting_date + bg_old.substring(bg_old.length-2);
                 } else {
                     bg_new = bg_old.substring(0, bg_old.length-2) + "?" + cache_busting_date + bg_old.substring(bg_old.length-2);
                 }
             }
             //console.log(" URL changing background to " + bg_new);
             $(targetid).css('backgroundImage', bg_new);
    
  1. and now it all works fairly well. The images flicker every time there’s a fast refresh, which bothers me, but the hack around it doesn’t seem worth it to me yet, especially if you’re about to redesign things.

  2. This whole thing is kind of a hack. One way to do this better would be:

  • read the name of the image file from a user field just like custom frames do (not just img1, etc)
  • in the server code do a read of that image last_updated from the filesystem.
  • when sending the response to fast polls, send three pieces of data. 1) the image name, 2) an img tag that you can just save into the page. 3) the last-modified date.
  • in javascript you can do then check if the current image src === img name + last_modified already. If so, do nothing. If not, then there is a fresh image, so you’ll want to force a reload by changing src to img name + new_last_modified that you just got from the server. This would fix my flickering problem for all the requests when the image hasn’t changed.

Hope this helps.

1 Like

Agree completely, so I’m rewriting them now to act more like frame and video tiles, but better, thanks for your excellent ideas.

Thanks for this pointer. This is similar to how I grab Arlo camera images and videos today. I will put some thought into how to make the Python script feel more integrated into the app. At a minimum I should add it to the install script as an option.

I currently do this with my Arlo script using crontab. Is that how you do this too? Any concerns about using cron for this?

I like this a lot. I presently just chuck the old Arlo images. I’m thinking some mix of the two would be best such that I keep say the last 10 to 30 videos - otherwise it could lead to a space hog problem.

With the rewrite I’m working on this won’t be needed. I will tie it to an image name. One thing I am considering is to just name a prefix and have the code pick out the most file that starts with this prefix so nothing needs to be done other than saving a file with the proper prefix.

Yup, this is basically the design I have in mind. Might deviate a small bit but the idea is solid. Thanks for much for your knowledge and willingness to share it.

1 Like

Yes, I use a cron job, seems to be a good place as we all have a rasberrypi running HP. I like the prefix idea on files - even easier for people to understand what’s going on.

I got the onclick popups to work today. In my housepanel-theme.js file I added a few lines that are specific to my installation:

image_tile_ids = [ā€œ21ā€, ā€œ22ā€, ā€œ23ā€];
video_urls = [ā€œring/video1.mp4ā€, ā€œring/video2.mp4ā€, ā€œring/video3.mp4ā€];

and then some code that should work fine (except maybe the dimensions of the popup)

$(document).ready(function(){

// let keeps the variable within the scope of the below event handlers
for(let i=0; i<image_tile_ids.length; i++){
let hidden_div_name = ā€œ#a-ā€ + image_tile_ids[i] + ā€œ-nameā€;
hidden_div = $(hidden_div_name);
hidden_div.hide();
hidden_div.html("");
hidden_div.append("");

  //setup two event handlers.  one for when you click on the url overlay, which opens the dialog.
  //second is when you click on the dialog, which pauses video and closes the dialog
$("#a-" + image_tile_ids[i] + "-url").click(function(){
    $(hidden_div_name).dialog({position: { my: "left top", at: "left top"}, height: 1200, width: 1920, modal: true,
                            beforeClose: function(event, ui){ document.getElementById("a-"+image_tile_ids[i]+"-video").pause(); }, }).siblings('.ui-dialog-titlebar').remove(\

);
(hidden_div_name).click(function(evt){ (hidden_div_name).dialog(ā€˜close’); document.getElementById(ā€œa-ā€+image_tile_ids[i]+"-video").pause(); evt.preventDefault(); });
document.getElementById(ā€œa-ā€+image_tile_ids[i]+"-video").play();
});
}
});

The ā€œletā€ variables in javascript closures was new to me and a little bit tricky, so thought I’d share.

I’m almost out of ideas for other cool things to do in HP. I still haven’t moved into my new place, so I haven’t had a chance to install most of my switches, thermostat, samsung tvs with ambient mode, fire tv sticks, etc. Maybe I’ll have some new ideas then.

1 Like

Well you have already had plenty!

The big remaining items on my ā€œto doā€ wish list are boring but high impact things like better doc, finish converting website to full blown Wordpress blog (partly done), and a more robust install script. The Node.js push companion app also has a bug that creates multiple connections to a client over time that I need to hunt down and squash.

I also have a ton of efficiency speed up work to do. As the HP user base grows I probably need to also formalize the testing process to ensure robustness. Again, boring but high impact work.

The fun things on my list include:

  • a more complete library of curated icons
  • Integrate the KuKu Harmony hack
  • Spotify controller using web api
  • Auto blank Fully Kiosk using api functions
  • and integrate your onclick feature

Thanks again for your support and ideas.

I just found out about housepanel while trying to setup a dashboard for my alarm system. This looks like it can be a fun project.

I have a spare raspberry Pi 2 B I would like to use, will it work or do I need a Pi 3? What size SD card will I need? Thanks.

A Pi 2 should work fine. Just need enough space for an Apache web server and a small web app. I haven’t sized it but it isn’t huge.

I am having trouble getting accuweather to update for my location too.
I got the first line of code from the web browser

I think I need the ID# for the second line, but I am not sure where to find it:

div id="awcc153195968647 and data-uid="awcc1531959686475

Thanks