ronhanson/python-dcitools

DoremiAPICLI : stdin

Closed this issue · 19 comments

Hi again,

I'm looking for a method to send various command (pause, play, SPLstatus, jumpforward) while keeping the connection opened, as openning the connection takes few seconds..
the DoremiAPICLI looks interesting but I don't find a way to send command to it, from another process.
I tried echoing command to stdin (/proc/pidof python/fd/0), but it misses the completion..
Any idea ?

I'm also working on adding few functions : JumpForward, JumpBackward, JumpToTimeCode.
if you have an already made python file, please commit it, or I'll suggest mine when done.

Best

Hi,

The CLI is perfect for manual use in a terminal but I admit it is hard to do useful scripts with it, as the results of commands often need parsing/computing and next command are often based on last result.

On our side, for complex usage, we used the library part itself (and no executables), by plugging it on an API to be remotely controllable by other components. I guess your program is not python based isnt it?

What exactly do you mean by "missing completion"?

We could also think of a small rest http server where you could send commands and easily retrieve result. Should not be too hard to do as an experiment if that's of interest for you.

I would be glad to get pull requests of your newly added functions. Everything we coded is already committed. I also have API documentation available if you need it, but I guess you have it already.

Cheers

Hi Ronan,

the final goal I'd like to achieve is controlling the doremi player with an IR or Bluetooth remote, only with play/pause/jumpback/jumpfordward/gotoTimecode. And maybe displaying CPL info and current timecode.

I was considering lirc as ir receiver on a raspberry pi which would trigger a command for each key event.
Dcitools works fine but it takes few sec to connect before sending the pause message for instance. which is too long.
Maybe there is a solution with PyLirc, need to be investigated.
My knowledge in Python is recent, not sure to have time to do it.
If you have better solution let me know.

Thanks

Actually, a listmaker like, but controlled for a wireless remote would be awesome.
basic, realtime, efficient

I see, interesting project.
I guess what you are planning is perfectly valid. And yes, you definitively need to avoid connecting to the doremi server...

IMHO, 2 valid approaches to overcome the "connection duration problem" :

  • or you use the python lib on your program side to do everything, keeping the connection open (using pylirc + your lirc IR receiver seems perfect in Python).
  • or you have a rest like http API running as a daemon, always connected, where you can throw some commands/requests at. Whatever program/language you use, you can easily send http commands to this daemon. This is very valid if you are not a fond of Python but are very efficient in another language.

As a matter of fact, I'll see if I have some time to develop such API. I think it should not take long to do something fun and working relatively well. And it could be useful for everyone.

Also, what do you mean by "listmaker like"?

Listmaker is a old application from Doremi to remote control dms2000 or other doremi video players via "Odetics" protocol, either on com port or network. It's still available to free download on dolby website, on windows only.

the Rest api looks great, but I can't help you with it.

I also found an alternative to lirc : using CEC from hdmi connected TV
https://alexandre-laurent.developpez.com/articles/hardware/raspberry-pi/telecommande-norme-cec/
it doesn't change workflows you suggested.

thanks

I just committed v0.6.0 with a proof of concept HTTP Restful API server :

 > bin/doremiapi http -h                                                                                                                
usage: doremiapi http [-h] [--port PORT] [--debug] [--http-bind HTTP_BIND]
                      [--http-port HTTP_PORT]
                      address
 
positional arguments:
  address               Address of the Doremi server.

optional arguments:
  -h, --help            show this help message and exit
  --port PORT           Port to connect the Doremi server.
  --debug               Enable Debugging Output.
  --http-bind HTTP_BIND
                        HTTP bind address for serving API.
  --http-port HTTP_PORT
                        HTTP Port for serving API.

You can try it, it is very simple and drafty but should work. Tell me how it goes.

LIRC is simple enough, but I guess you'll find plenty of libs to handle HDMI CEC as well.
But that means you need a TV connected to your Rasp Pi, isn't it?
Still interesting to see how it will go.

Just tested the http feature : http server starts well, it receives get commands from client :
"
Connection...
Connected to Doremi DCP2000 server on 10.26.65.53:11730
Bottle v0.12.13 server starting up (using WSGIRefServer())...
Listening on http://127.0.0.1:8080/
Hit Ctrl-C to quit.
127.0.0.1 - - [15/Oct/2018 12:14:38] "GET /GetProductInfo HTTP/1.1" 200 102
"

but the result doesn't have data :
{"status": "success", "message": "OK", "command": "GetProductInfo", "parameters": [], "key": "050100"}

I also tried play/pause, it doesn't affect the player while the cli does.

Let me know

thanks

It is because "GET /GetProductInfo" retrieves you the documentation only, but takes no action. This way you can retrieve info on required parameters :

> curl -H "Accept:application/json" http://127.0.0.1:8087/GetLog

{"status": "success", "message": "OK", "command": "GetLog", "parameters": [{"type": "text", "name": "database"}, {"type": "int", "name": "idmin"}, {"type": "int", "name": "idmax"}], "key": "110100"}

You need to "POST /GetProductInfo" to actually perform the call to the server. And "result" will be filled with request/command output :

> curl -X POST -H "Accept:application/json" -H "Content-Type: application/json" http://127.0.0.1:8080/GetProductInfo -d "{}"

...

Ok fine.

POST command fail:
on server side :
"
Traceback (most recent call last):
File "/usr/local/lib/python2.7/dist-packages/bottle-0.12.13-py2.7.egg/bottle.py", line 862, in _handle
return route.call(**args)
File "/usr/local/lib/python2.7/dist-packages/bottle-0.12.13-py2.7.egg/bottle.py", line 1740, in wrapper
rv = callback(*a, **ka)
File "/usr/local/lib/python2.7/dist-packages/dcitools-0.6.0-py2.7.egg/dcitools/devices/doremi/http.py", line 93, in request
payload = dict(request.json)
TypeError: 'NoneType' object is not iterable
127.0.0.1 - - [15/Oct/2018 13:35:47] "POST /GetProductInfo HTTP/1.1" 500 1490
"

on client side :
"
curl -X POST -H "Accept:application/json" http://localhost:8080/GetProductInfo

<!DOCTYPE HTML PUBLIC "-//IETF//DTD HTML 2.0//EN">
<html>
    <head>
        <title>Error: 500 Internal Server Error</title>
        <style type="text/css">
          html {background-color: #eee; font-family: sans;}
          body {background-color: #fff; border: 1px solid #ddd;
                padding: 15px; margin: 15px;}
          pre {background-color: #eee; border: 1px solid #ddd; padding: 5px;}
        </style>
    </head>
    <body>
        <h1>Error: 500 Internal Server Error</h1>
        <p>Sorry, the requested URL <tt>&#039;http://localhost:8080/GetProductInfo&#039;</tt>
           caused an error:</p>
        <pre>Internal Server Error</pre>
          <h2>Exception:</h2>
          <pre>TypeError(&quot;&#039;NoneType&#039; object is not iterable&quot;,)</pre>
          <h2>Traceback:</h2>
          <pre>Traceback (most recent call last):

File "/usr/local/lib/python2.7/dist-packages/bottle-0.12.13-py2.7.egg/bottle.py", line 862, in _handle
return route.call(**args)
File "/usr/local/lib/python2.7/dist-packages/bottle-0.12.13-py2.7.egg/bottle.py", line 1740, in wrapper
rv = callback(*a, **ka)
File "/usr/local/lib/python2.7/dist-packages/dcitools-0.6.0-py2.7.egg/dcitools/devices/doremi/http.py", line 93, in request
payload = dict(request.json)
TypeError: 'NoneType' object is not iterable



"

let me know

You need to pass valid json data, even empty, to your post request. Simply add -d "{}" to your curl request, but also add "Content-Type: application/json" header so the http server knows that what you are sending is json.

sorry.
now it's better. Play/pause work.

other command fails. example : GetProductInfo
"
File "/usr/local/lib/python2.7/dist-packages/bottle-0.12.13-py2.7.egg/bottle.py", line 862, in _handle
return route.call(**args)
File "/usr/local/lib/python2.7/dist-packages/bottle-0.12.13-py2.7.egg/bottle.py", line 1746, in wrapper
json_response = dumps(rv)
File "/usr/lib/python2.7/dist-packages/simplejson/init.py", line 380, in dumps
return _default_encoder.encode(obj)
File "/usr/lib/python2.7/dist-packages/simplejson/encoder.py", line 291, in encode
chunks = self.iterencode(o, _one_shot=True)
File "/usr/lib/python2.7/dist-packages/simplejson/encoder.py", line 373, in iterencode
return _iterencode(o, 0)
File "/usr/lib/python2.7/dist-packages/simplejson/encoder.py", line 268, in default
raise TypeError(repr(o) + " is not JSON serializable")
TypeError: UUID('00000000-0000-0000-0000-000000000000') is not JSON serializable
127.0.0.1 - - [15/Oct/2018 13:50:54] "POST /GetProductInfo HTTP/1.1" 500 1966
"

I also tried
curl -X POST -H "Accept:application/json" -H "Content-Type: application/json" http://127.0.0.1:8080/GetCPLInfo2 -d '{ "uuid": "5f798b4d-e0c1-4f4e-86c4-87f558fe5598"}'
with the same error

Ok, I've updated the repo, v0.6.1, to add json serialisation over datetime and uuid fields. It should work now.

ok
POST commands fail differently :
"
ERROR | Error while launching client.command
Traceback (most recent call last):
File "/usr/local/lib/python2.7/dist-packages/dcitools-0.6.1-py2.7.egg/dcitools/devices/doremi/http.py", line 137, in call_api
return (self.client.command(command, **kwargs), True)
File "/usr/local/lib/python2.7/dist-packages/dcitools-0.6.1-py2.7.egg/dcitools/devices/doremi/server.py", line 42, in command
return cc(*args, **kwargs)
File "/usr/local/lib/python2.7/dist-packages/dcitools-0.6.1-py2.7.egg/dcitools/devices/doremi/commands.py", line 212, in call
return self.send_and_receive(*args, **kwargs)
File "/usr/local/lib/python2.7/dist-packages/dcitools-0.6.1-py2.7.egg/dcitools/devices/doremi/commands.py", line 205, in send_and_receive
self.send(*args, **kwargs)
File "/usr/local/lib/python2.7/dist-packages/dcitools-0.6.1-py2.7.egg/dcitools/devices/doremi/commands.py", line 173, in send
self.sock.send(request_bin)
AttributeError: 'NoneType' object has no attribute 'send'
ERROR : 'NoneType' object has no attribute 'send'
127.0.0.1 - - [15/Oct/2018 15:34:21] "POST /GetProductInfo HTTP/1.1" 200 143
"

Jérémy

Ok sorry this one is on me.
As I have no Doremi server these days, I bypass connection to mock things while developping... And I forgot a debug line.
This time it should work.
I am also trying to get access to a server again to test things out better and avoid this kind of mistakes.

that is looking good !
curl -X POST -H "Accept:application/json" -H "Content-Type: application/json" http://127.0.0.1:8080/GetProductInfo -d "{}"

{"status": "success", "message": "OK", "command": "GetProductInfo", "payload": {}, "result": {"product_name": "DCP2000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000", "product_serial": "204051-02\u0000\u0000\u0000\u0000\u0000\u0000\u0000", "product_id": "00000000-0000-0000-0000-000000000000", "software_version_major": 2, "software_version_minor": 6, "software_version_revision": 4, "software_version_build": 0, "hardware_version_major": 20, "hardware_version_minor": 4, "hardware_version_build": 110, "hardware_version_extra": 20}}

I tested few command successfully.
only these charactets look ugly : \u0000\u0000\u0000\u0000\u0000\u0000\u0000 on some values.

thanks !

Great! I'll patch it soon to trim those characters at the end because return it to you.
I'll do that on the http side only to avoid big mistakes while not having DCP2000 server to test, but I guess it should be done directly in the engine.

Should be solved now.
I close this ticket, do not hesitate to create other if you find issues.