Digital movie poster - Kodi version (dennisaion) Plex version (Lanky)

Hey just wanted to share what I did. I used the source from this and implemented it in the new “panel_custom” component as mentioned here: https://home-assistant.io/components/panel_custom/

All you need to do is pass the api password as “api_pwd” if applicable and the entity id as “kodi” in the config for the component.

<!-- START CSS -->
<style>
.dmp-content {
	background:
		radial-gradient(black 15%, transparent 16%) 0 0,
		radial-gradient(black 15%, transparent 16%) 8px 8px,
		radial-gradient(rgba(255,255,255,.1) 15%, transparent 20%) 0 1px,
		radial-gradient(rgba(255,255,255,.1) 15%, transparent 20%) 8px 9px;
	background-color:#282828;
	background-size:16px 16px;
	font-size: 14px;
	line-height: 1.42857143;
	color: #c8c8c8;
	height: 100%;
}
.dmp-headline {
	font-size: 2em;
	margin: 0.67em 0;
}

.dmp-content {
	height: 100%;
	text-align: center;
}

.dmp-content img {
	height: 80%;
}

.dmp-state {
	font-size: 20pt;
}

.dmp-runtime {
	font-size: 14pt;
}

.dmp-fullscreen {
  position: fixed;
  top: 0;
  left: 0;
  bottom: 0;
  right: 0;
  overflow: auto;
}
</style>
<!-- END CSS -->
<!-- START TEMPLATE FOR POLYMER -->
<dom-module id='ha-panel-dmp'>
	<template>
		<div class="dmp-content dmp-fullscreen" id="output">
			<div class="firstRun">
				<h1 class="dmp-headline">Could not load the State</h1>
				<p>Please check that you entered the correct entity_id of your Kodi component.</p>
			</div>
		</div>
	</template>
</dom-module>
<!-- END TEMPLATE FOR POLYMER -->
<!-- START CODE -->
<script type="text/javascript">
	// Make config variables global
	var api_pwd;
	var entityId;
	// Update the view with the current state of the Kodi component.
	// ent = entity of your Kodi component
	function updateView(ent){
		var output = document.getElementById('output');
		if ("undefined" !== ent){
			var new_html;
			if ( ent.state == "idle" ) {
				new_html = "<h1 class=dmp-headline><p align=center>No media playing on " + ent.attributes.friendly_name + "</p></h1>";
			} else {
				var rtime = new Date(ent.attributes.media_duration * 1000).toISOString().substr(11, 8);
				new_html = "<img src=" + ent.attributes.entity_picture;
				if("undefined" !== api_pwd) {
					new_html += "&api_password=" + api_pwd;
				}
				 new_html += " /></div><div class=dmp-state><p>Now " + ent.state + " on " + ent.attributes.friendly_name + "</p></div><div class=dmp-runtime><p>Runtime: " + rtime + "</p>";
			}
		}
		output.innerHTML = new_html;
	}
	// Helper function to pass entity to updateView function
	function propChange(entities){
		updateView(entities.entities);
	}
	function render(hass, panel) {
		// Set config
		api_pwd = panel.config.api_pwd;
		entityId = panel.config.kodi;
		// Register for updates
		hass.reactor.observe(hass.entityGetters.byId(entityId), entities => this.propChange({entities}));
		
		// Update the current view initially
		updateView(hass.reactor.evaluate(hass.entityGetters.byId(entityId)));
		}
	// Polymer stuff
	Polymer({
		is: 'ha-panel-dmp',
		properties: {
			// Home Assistant object
			hass: {
			type: Object,
			},
			// If should render in narrow mode
			narrow: {
				type: Boolean,
				value: false,
			},
			// If sidebar is currently shown
			showMenu: {
				type: Boolean,
				value: false,
			},
			// Home Assistant panel info
			// panel.config contains config passed to panel_custom serverside
			panel: {
				type: Object,
			}
		},
		// This will make sure we forward changed properties
		observers: [
			'propsChanged(hass, narrow, showMenu, panel)',
		],
		// Called when properties change
		propsChanged: function (hass, narrow, showMenu, panel) {
			this.mount(hass, narrow, showMenu, panel);
		},
		// Render React. Debounce in case multiple properties change.
		mount: function (hass, narrow, showMenu, panel) {
			this.debounce('mount', function () {
			render(hass, panel);  
			}.bind(this));
		},
		// Unmount React node when panel no longer in use.
		detached: function () {
		},
	});
</script>
<!-- END CODE -->

Example config if you have saved above under panels/dmp.html in your HA config directory:

panel_custom:
  - name: dmp
    sidebar_title: Digital Movie Poster
    sidebar_icon: mdi:movie
    config:
      kodi: media_player.kodi_on_firetv
      api_pwd: xxx

I found this to be pretty useful. And I do not need to wait until the state gets changed. As it gets the current state immediately.

If you find anything that can be done better please share as I am a complete JS and thus Polymer noob :slight_smile:

Cheers

1 Like

I am running 0.32.3 and it is working perfectly fine for me.

{
  "emulated_hue_name": "Media room",
  "entity_picture": "/api/media_player_proxy/media_player.kodi?token=1823294704&cache=63a04",
  "friendly_name": "Media Room",
  "icon": "mdi:filmstrip",
  "is_volume_muted": false,
  "media_content_id": {
    "unknown": ""
  },
  "media_content_type": "video",
  "media_duration": 6458,
  "media_title": "Risen",
  "supported_media_commands": 4927,
  "volume_level": 1
}

Only thing I can think of is that you have username and password set on your Kodi?

I at first had kodi setup with username and password and that did not work when it came to artwork.
When I cleared the credentials from Kodi and from the Kodi setup in the configuration.yaml then it worked for me.

it still needs to be in a www folder. Mine sits in /var/opt/homeassistant/www
My configuration.yaml sits in /var/opt/homeassistant

I’ll get back to playing around with this.

So I had issues with the API password on the API stream as well one way would be to append the ?api_password to the link however this would allow anyone to read out our password when accessing the site.

What I’ve done is to add the following just below <script type="text/javascript"> the following:

   urlParam = function(name, url) {
    if (!url) {
     url = window.location.href;
    }
    var results = new RegExp('[\\?&]' + name + '=([^&#]*)').exec(url);
    if (!results) {
        return undefined;
    }
    return results[1] || undefined;
    };
    var password = urlParam('api_password');

Then change
var source = new EventSource("/api/stream"); to
var source = new EventSource("/api/stream?api_password="+password);

And now just access the it via http://192.168.x.x:8123/local/index.html?api_password=Your_Password

You can still read the password via JS but you will need to pass the correct one via the URL

Hope that helps

2 Likes

I created a new DMP in Kodi itself. Makes for much easier and quicker response and also getting info displayed like time and runtime is much easier. Now looks like this.

2 Likes

Little more playing around with CSS and fonts made it look better.
Added a current time as well.

And a bit of moving image

Care to share some source?

~Cheers

You have Kodi?

Yes Sir

~Cheers

I will send you the CSS and kodi.html I created.

1 Like

Would you mind posting those here?

I’m not in a situation that I could utilise them now but some time in the future it would be great to get back to this thread to get them.

Also other people might take inspiration and/or improve upon your work.

/R

1 Like

Hey guys. awesome work but unfortunaltey i get this :

Could not load the State

Please check that you entered the correct entity_id of your Kodi component.

I double checked the entity:id and it is correct.
Mybe one hint. I use % character in my password and have to write it like this: '%%something%%

this might be an issue?

Help appreciated :slight_smile:

Iirc this is currently broken due to the big frontend changes with 0.38

~Cheers

I have created a new version working directly of Kodi.
Will post code shortly. Sorry for late reply. Some issues in offline life need taking care of 2.

Hi all,

Time for an update on the Digital Movie Poster. I moved away from the SSE version…

…and started working on a version that works directly of (and on) Kodi itself.
Gave me a lot more flexibility and killer response.

Now playing around with the css effects and layout. Came up with this.

For moving image check these videos

Create a kodi.html and put following code in it

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="utf-8">
    <meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1">
    <meta name="mobile-web-app-capable" content="yes">
    <meta name="description" content="Digital Movie Poster">
    <meta name="author" content="Dennis Murray">
    <!-- <link rel="search" href="provider.xml" type="application/opensearchdescription+xml" title="Kodi Library" /> -->
    <link rel="icon" href="favicon.ico" type="image/x-icon">
    <link rel="shortcut icon" href="favicon.ico" type="image/x-icon">
    <!-- <link href="/images/logo.png" rel="image_src" /> -->
    <meta name="robots" content="NOINDEX, NOFOLLOW">
    <link href="css/base.css?1.3.57" rel="stylesheet" type="text/css">
    <link href="css/ipad.css?1.0.5" rel="stylesheet" media="only screen and (max-device-width: 1024px)" type="text/css">
<title>Digital Movie Poster</title>	
<script>
function startTime() {
    var today = new Date();
    var h = today.getHours();
    var m = today.getMinutes();
    var s = today.getSeconds();
    var ampm = h >= 12 ? 'PM' : 'AM';
    h = checkTime(h);
    m = checkTime(m);
    s = checkTime(s);
    document.getElementById('clock').innerHTML =
    h + ":" + m + " " + ampm
    var t = setTimeout(startTime, 500);
}
function checkTime(i) {
    if (i < 10) {i = "0" + i};  // add zero in front of numbers < 10
    return i;
}
</script>
  </head>
  <body onload="startTime()">
      <div id="nowPlayingPanel" style="display: none;>
        <div id="nowPlayingContent">
          <div id="videoDescription">
            <div id="videoCoverArt"></div>
             <div id="footerPopover">
            <div id="videoTitle"></div>
            <div id="videoDuration"></div>
             </div>
           </div>
         </div>
        </div>
      </div>
    </div>
    <script type="text/javascript" src="js/xbmc.launcher.js?v=2.1.0"></script>
  </body>
</html>


Then log onto your Kodi (linux based) via SSH and place kodi.html in /usr/share/kodi/addons/webinterface.default

Once you have done that you can edit the base.css and ipad.css to your liking to show the videoTitle, clock and videoDuration div’s in the font and colours you like.
Best thing you can do is create a seperate kodi.css and replace base.css with kodi.css in kodi.html not to upset the default index webpage of Kodi itself.

So

    <link href="css/base.css?1.3.57" rel="stylesheet" type="text/css">

becomes

    <link href="css/kodi.css?1.3.57" rel="stylesheet" type="text/css">

Now you have the basics. There is a lot you can do with HTML5 and java so have fun with it.

@dennisaion:
I have implemented your Digital Movie Poster. I’m using the version where you host the html-file in the www-folder of HAss, but I have a minor issue.

When I start watching a movie and afterwards go to the URL: homeassistant.local:8123/local/dmp.html the poster isn’t shown. I have to change to another movie or open the website and start the movie later.

Do you know a solution for that?

EDIT: Nevermind, solved it myself using Kodi’s JSON RPC. So I get the image URL directly from there and see a sharper image as well.

It’s based on Server Side Events. So nothing will show unless a SSE happens.
You would have to pause the film and run it again and then you see it popping up.
Or start the DMP first and then the movie.

Best you can do is use my updated Kodi version. That one will show instantly what is running even if the DMP is started later than the movie.

I am having trouble getting this fully implemented in Hass.io. Does anyone have any experience running this on Hass.io from a Pi3 and Plex on Windows 10?

I’ll be adding this when I got home

This is awesome. Thanks for sharing.