Your Universal Remote Control Center
RemoteCentral.com
Philips Pronto Professional Forum - View Post
Previous section Next section Previous page Next page Up level
Up level
The following page was printed from RemoteCentral.com:

Login:
Pass:
 
 

Page 3 of 3
Topic:
Working on KODI feedback
This thread has 41 replies. Displaying posts 31 through 42.
Post 31 made on Thursday August 6, 2020 at 16:17
Lyndel McGee
RC Moderator
Joined:
Posts:
August 2001
12,994
Postfix value needs to end with single \r\n. Compare your last post to the first post in this thread.
Lyndel McGee
Philips Pronto Addict/Beta Tester
OP | Post 32 made on Thursday August 6, 2020 at 17:24
mpg7321
Regular Member
Joined:
Posts:
June 2020
111
I tried both suggestions and still no luck.

Again thanks for all your help.
Mike
Post 33 was deleted by a forum moderator.
OP | Post 34 made on Thursday August 6, 2020 at 17:39
mpg7321
Regular Member
Joined:
Posts:
June 2020
111
I even went back to the sample in the developers guide and still no luck.

function kodi2(){
receivedData = "";
socket.onConnect = function() {
write("GET /t/p/original/"+cover+".jpg /HTTP1.0\r\n");
};
socket.onData = function() {
receivedData += read();
};
socket.onIOError = function (e) {
widget("MOVIE_COVER").label = "IOError " + e;
};
socket.onClose = function () {
var imageStartIndex, bitmapData, myImage;
// remove the HTTP header from the received data
imageStartIndex = receivedData.indexOf("\r\n\r\n");
bitmapData = receivedData.substring(imageStartIndex+4);
// make and display the image
myImage = new Image(bitmapData);
widget("MOVIE_COVER").setImage(myImage);
};
socket.connect("image.tmdb.org",80,3000);
scheduleAfter(500,kodi3);
};

With this script I am getting an error "IOError PanelIERROR: Failed to connect

Last edited by mpg7321 on August 6, 2020 17:46.
OP | Post 35 made on Thursday August 6, 2020 at 17:40
mpg7321
Regular Member
Joined:
Posts:
June 2020
111
Hear is my entire code for returned data.
var url = CF.widget("Kodi_aURL","Kodi_PARAMETERS_test").label;
var FFcommand = "2";
var RRcommand = "2";
function kodi1(){
var socket = new TCPSocket();
socket.onConnect = function() {
prefix = 'GET /jsonrpc?request={"jsonrpc": "2.0", "method": "Player.GetItem", "params": { "properties": ["title", "thumbnail"], "playerid": 1 }, "id": "1"}'
postfix = ' HTTP/1.0\r\n'
try {
socket.write(prefix+postfix);
socket.write("HOST:+url+\r\n\r\n");
} catch(e) {
socket.close()
}}
socket.onData = function() {
var info1 = socket.read();
var cover = info1.split('original%2f').pop().split('.jpg')[0];
//CF.widget("MOVIE_COVER").label=cover;
if (info1.indexOf('unknown') !== -1) {
CF.widget("KODI_TITLE").label="Nothing Playing";
}else{
var title = info1.split('title":"').pop().split('","type')[0];
CF.widget("KODI_TITLE").label=title;
};
socket.close()
}
socket.onIOError = function(e) {
socket.close()
}
socket.connect(url, 9090, 3000);
scheduleAfter(500,kodi2);
};
////////////////////////////////////////////////////////////////////////////////////////////
function kodi2(){
var url1 = "image.tmdb.org";
var socket = new TCPSocket();
socket.onConnect = function() {
prefix = 'GET /t/p/original/'
postfix = '.jpg /HTTP1.0\r\n'
try {
socket.write(prefix+cover+postfix);
socket.write("HOST:+url1+\r\n\r\n");
} catch(e) {
socket.close()
}}
socket.onData = function() {
var cover1 = socket.read();
// remove the HTTP information from the received data
var imageStartIndex = cover1.indexOf("\r\n\r\n");
var bitmapData = cover1.substring(imageStartIndex+4);
// make and display the image
var MyImage = new Image(bitmapData);
widget(“MOVIE_COVER”).setImage(MyImage);
socket.close()
}
socket.onIOError = function(e) {
socket.close()
}
socket.connect(url1, 80, 3000);
scheduleAfter(500,kodi3);
};
Post 36 made on Thursday August 6, 2020 at 17:44
Lyndel McGee
RC Moderator
Joined:
Posts:
August 2001
12,994
Try this:

function kodi2(){
receivedData = "";
socket.onConnect = function() {
write("GET /t/p/original/"+cover+".jpg HTTP/1.0\r\n");
write("HOST: image.tmdb.org\r\n");
write("CONNECTION: close\r\n");
write("\r\n");

};
socket.onData = function() {
receivedData += read();
};
socket.onIOError = function (e) {
widget("output").label = "IOError " + e;
};
socket.onClose = function () {
var imageStartIndex, bitmapData, myImage;
// remove the HTTP header from the received data
imageStartIndex = receivedData.indexOf("\r\n\r\n");
bitmapData = receivedData.substring(imageStartIndex+4);
// make and display the image
myImage = new Image(bitmapData);
widget("MOVIE_COVER").setImage(myImage);
};
socket.connect(image.tmdb.org,80,3000);
scheduleAfter(500,kodi3);
};


Some websites require that the 'Host' HTTP Request header be present.

If you are hitting a site that uses the HTTP 1.1 protocol, it is also good to specify the 'Connection' request header.

If you are interested in learning more about the HTTP protocol, I would recommend not looking at the HTTP RFCs but rather a book by O'Reilly called "Webmaster In A Nutshell".

Last edited by Lyndel McGee on August 6, 2020 17:59.
Lyndel McGee
Philips Pronto Addict/Beta Tester
Post 37 made on Thursday August 6, 2020 at 17:46
Lyndel McGee
RC Moderator
Joined:
Posts:
August 2001
12,994
Your scheduleAfter(100,Kodi3) needs to be called from within either onData or onClose function as it likely depends on data you are receiving from within Kodi or Kodi2 function?

I think there may be a misunderstanding on when certain functions execute in what you are developing.

Only the lines creating the socket and the actual connect function execute at the time kodi() is invoked.

The other functions such as onConnect, onData, onClose and onIOError execute after something has happened on a socket.

onConnect will be executed when the underlying socket connects to the server.
onData will be executed each time a block of data is available from the server.
onClose will be executed when the remote server closes the socket.
onIOError will be executed if there an an underlying socket error.

Once you understand that all these things don't execute at once but rather based on event triggers, you are one up in the game.

Next, if you are interested in why the above applies and why the examples do it this way...

The pattern you are using is called javascript closures. You are creating new functions at the time your kodi() function is executing. What this does is to allow those functions to be able to use and have visibility to a common 'receivedData' and 'socket' variable if need be.

I know you are trying to learn this on your own. The solution you require is complex and requires asynchronous programming expertise as well.

There are about 6 different items that are required for this solution.

1. Core Javascript + Closures/Variable Scoping
2. Asynchronous coding using Javascript Callbacks.
3. ProntoScript object extensions to JavaScript
4. Deep understanding of the HTTP protocol (using raw TCPSockets)
5. JavaScript Object Notation (JSON)
6. JSON Remote Procedure Calls (JSONRPC v2.0)
7. Creating an image from HTTP response data.


I offered to reach out to you via telephone for some pointers if need be. I don't think I got a response. The offer still stands as there is often alot that is lost in translation through a forum.

Last edited by Lyndel McGee on August 6, 2020 17:57.
Lyndel McGee
Philips Pronto Addict/Beta Tester
OP | Post 38 made on Thursday August 6, 2020 at 17:58
mpg7321
Regular Member
Joined:
Posts:
June 2020
111
KODI 3 is independent of the first two. It sends out a second query command to get time info, position etc.

Still not getting any thing in the panel. Also not getting an error this time either.
Post 39 made on Thursday August 6, 2020 at 18:01
Lyndel McGee
RC Moderator
Joined:
Posts:
August 2001
12,994
See my edit above outlining that the HTTP protocol specifier's '/' needs to be between the HTTP and version number.

I just reviewed the philips http module and it has this:

requestText += " HTTP/1.0\r\n";


write("GET /t/p/original/"+cover+".jpg HTTP/1.0\r\n");
write("HOST: image.tmdb.org\r\n");
write("CONNECTION: close\r\n");
write("\r\n");
Lyndel McGee
Philips Pronto Addict/Beta Tester
Post 40 made on Thursday August 6, 2020 at 18:01
Lyndel McGee
RC Moderator
Joined:
Posts:
August 2001
12,994
Please make the changes I noted in bold and report back ASAP.
Lyndel McGee
Philips Pronto Addict/Beta Tester
OP | Post 41 made on Friday August 7, 2020 at 15:00
mpg7321
Regular Member
Joined:
Posts:
June 2020
111
So far this is the code that does work with KODI feedback. Do need to clean it up a bit but does pull all data I wanted. THIS IS FOR MOVIES ONLY. Have not modified to work properly on TV shows or music yet. So this gives me , Title, Progress slider, Cover Art, total time, time remaining, displaying play speed, IE 2x 4x 8x 16x & 32x both Fastforward and Rewind, show or hide the Play or Pause buttons.

System.setDebugMask(9);
var url = CF.widget("Kodi_aURL","Kodi_PARAMETERS_test").label;
var cover;
var data;
function kodi1(){
var socket = new TCPSocket();
socket.onConnect = function() {
prefix = 'GET /jsonrpc?request={"jsonrpc": "2.0", "method": "Player.GetItem", "params": { "properties": ["title", "thumbnail"], "playerid": 1 }, "id": "1"}'
postfix = ' HTTP/1.0\r\n'
try {
socket.write(prefix+postfix);
socket.write("HOST:+url+\r\n\r\n");
} catch(e) {
socket.close()
}}
socket.onData = function() {
var info1 = socket.read();
cover = info1.split('original%2f').pop().split('.jpg')[0];
//CF.widget("MOVIE_COVER").label=cover;
if (info1.indexOf('unknown') !== -1) {
CF.widget("KODI_TITLE").label="Nothing Playing";
}else{
var title = info1.split('title":"').pop().split('","type')[0];
CF.widget("KODI_TITLE").label=title;
};
socket.close()
CF.activity().scheduleAfter(500,kodi2);
}
socket.onIOError = function(e) {
socket.close()
}
socket.connect(url, 9090, 500);
};


function kodi2(){
var socket = new TCPSocket();
var receivedData = "";
socket.onConnect = function() {
socket.write("GET /t/p/w185/"+cover+".jpg HTTP/1.0\r\n");
socket.write("HOST: image.tmdb.org\r\n");
socket.write("CONNECTION: close\r\n");
socket.write("\r\n");
};
socket.onData = function() {
receivedData += socket.read();
};
socket.onIOError = function (e) {
CF.widget("data").label = "IOError " + e;
};
socket.onClose = function () {
var imageStartIndex, bitmapData, myImage;
// remove the HTTP header from the received data
imageStartIndex = receivedData.indexOf("\r\n\r\n");
bitmapData = receivedData.substring(imageStartIndex+4);
// make and display the image
myImage = new Image(bitmapData);
CF.widget("MOVIE_COVER").setImage(myImage);
//CF.widget("MOVIE_COVER").width=100;
//CF.widget("MOVIE_COVER").height=200;
//CF.widget("MOVIE_COVER").label=cover;
CF.activity().scheduleAfter(500,kodi3);
};
socket.connect("image.tmdb.org",80, 500);
}


function kodi3(){
var socket = new TCPSocket();
socket.onConnect = function() {
prefix2 = 'GET /jsonrpc?request={"jsonrpc": "2.0", "method": "Player.GetProperties", "params": { "properties": ["percentage", "totaltime", "time", "speed"], "playerid": 1 }, "id": "1"}'
postfix2 = ' HTTP/1.0\r\n'
try {
socket.write(prefix2+postfix2);
socket.write("HOST:+url+\r\n\r\n");
} catch(e) {
socket.close()
}}
socket.onData = function() {
var info = socket.read();
var percentage = info.split('percentage":').pop().split('.')[0];
var speed = info.split('"speed":').pop().split(',')[0];
var totaltime = info.split('"totaltime"').pop().split('}')[0];
var totaltime_hour = totaltime.split('"hours":').pop().split(',')[0];
var totaltime_minute = totaltime.split('"minutes":').pop().split(',')[0];
if (totaltime_minute <= 9){
totaltime_minute =(0+totaltime_minute);
};
var totaltime_caculated = parseInt(totaltime_minute) + (parseInt(totaltime_hour)*60);
var time = info.split('"time"').pop().split('}')[0];
var time_hour = time.split('"hours":').pop().split(',')[0];
var time_minute = time.split('"minutes":').pop().split(',')[0];
var time_caculated = parseInt(time_minute) + (parseInt(time_hour)*60);
var time_remaning = totaltime_caculated-time_caculated;
if (time_remaning <= 9){
CF.widget("RUN_TIME_REMAIN").label="-0H : 0"+time_remaning + "m";
}else if (time_remaning <= 60){
CF.widget("RUN_TIME_REMAIN").label="-0H : "+time_remaning + "m";
}else{
var hours =time_remaning/60;
var rhours = Math.floor(hours);
var minutes = (hours - rhours) * 60;
var rminutes = Math.round(minutes);
if (rminutes <= 9){
rminutes=("0"+rminutes);
};
CF.widget("RUN_TIME_REMAIN").label="-"+rhours + "H : " + rminutes + "m";
};
if (totaltime_hour == 0){
CF.widget("RUN_TIME").label=": " + totaltime_minute + " m";
//CF.widget("RUN_TIME_REMAIN").label="To Go = : " + (totaltime_minute-time_minute) + " m";
}else{
CF.widget("RUN_TIME").label=totaltime_hour+ "H : " + totaltime_minute + "m";
//CF.widget("RUN_TIME_REMAIN").label="To Go = " + (totaltime_hour-time_hour) + "H : " + (totaltime_minute-time_minute) + "m";
}
if (speed == 1) {
CF.widget("Play").visible = false;
CF.widget("Pause").visible = true;
CF.widget("FF_Speed").label="-";
CF.widget("RR_Speed").label="-";
} else if (speed == 0){
CF.widget("Play").visible = true;
CF.widget("Pause").visible = false;
CF.widget("FF_Speed").label="-";
CF.widget("RR_Speed").label="-";
}else if (speed > 1){
CF.widget("Play").visible = true;
CF.widget("Pause").visible = false;
CF.widget("FF_Speed").label=speed+"x";
CF.widget("RR_Speed").label="-";
}else if (speed < 0){
CF.widget("Play").visible = true;
CF.widget("Pause").visible = false;
CF.widget("RR_Speed").label=speed+"x";
CF.widget("FF_Speed").label="-";
};
if (percentage == 0.0) {
CF.widget("PROGRESS").width=1;
} else {
CF.widget("PROGRESS").width=(percentage/100)*620;
}
socket.close()
}
socket.onIOError = function(e) {
socket.close()
}
socket.connect(url, 9090, 500);
};
Post 42 made on Friday August 7, 2020 at 18:40
Lyndel McGee
RC Moderator
Joined:
Posts:
August 2001
12,994
All these calls you have to CF.widget I would replace with GUI.widget.

CF.widget("FF_Speed").label=speed+"x";

GUI.widget("FF_Speed").label=speed+"x";

If it so turns out that the widget tag you declare is not available on the current page, your code will throw an error.

I'd create a function to handle this and fail silently.

function updateGUIWidgetLabel(tag,value) {
var w;
if (w=GUI.widget(tag)) {
w.label = ''+value;
}
}

then, this line
GUI.widget("FF_Speed").label=speed+"x";

becomes a bit more readable.

updateGUIWidgetLabel("FF_Speed", speed+ "x");


same thing applies for visible property.

CF.widget("Pause").visible = false

function showHideGUIWidget(tag,visible) {
var w;
if (w=GUI.widget(tag)) {
// (true && visible) will do type coercion to boolean type.
w.visible = (true && visible);
}
}

This
CF.widget("Pause").visible = false

becomes...

showHideGUIWidget("Pause",false);
Lyndel McGee
Philips Pronto Addict/Beta Tester
Page 3 of 3


Jump to


Protected Feature Before you can reply to a message...
You must first register for a Remote Central user account - it's fast and free! Or, if you already have an account, please login now.

Please read the following: Unsolicited commercial advertisements are absolutely not permitted on this forum. Other private buy & sell messages should be posted to our Marketplace. For information on how to advertise your service or product click here. Remote Central reserves the right to remove or modify any post that is deemed inappropriate.

Hosting Services by ipHouse