Announcement

Collapse
No announcement yet.

LMSTools - python library for Logitech Media Server

Collapse
X
 
  • Filter
  • Time
  • Show
Clear All
new posts

    LMSTools - python library for Logitech Media Server

    Previously, I used the PyLMS library (which is excellent) but I found that there some was some functionality missing. As a result, I ended up having to add my own code to get the desired outcome and I thought that I should try to put it all together into a library. The end result is my LMSTools library.

    The main differences from PyLMS are:
    • Server and Player objects use the JSON interface rather than telnet (no need to maintain a persistent connection)
    • Add a callback server to handle asynchronous callback from server events
    • Adds the ability to generate squeezeplayer menus (for designing your own interface)


    There is more detailed documentation available here: http://lmstools.readthedocs.io/

    The library is available to download from here: https://github.com/elParaguayo/LMSTools

    Any bugs, enhancement requests etc. can be posted here on the github issues tracker.

    I hope it's of some use for your own projects. Enjoy!

    #2
    Interesting project.
    You say you use JSON/RPC for the server communication but that's not how you build that custom menu, isn't it?
    How do you do that?
    ---
    learn more about iPeng, the iPhone and iPad remote for the Squeezebox and
    Logitech UE Smart Radio as well as iPeng Party, the free Party-App,
    at penguinlovesmusic.com
    New: iPeng 9, the Universal App for iPhone, iPad and Apple Watch

    Comment


      #3
      Yes. The menu is retrieved by sending a json command. The module interprets the response and turns it into menu item objects.

      Comment


        #4
        LMSTools - python library for Logitech MediaServer

        > Yes. The menu is retrieved by sending a json command. The module
        > interprets the response and turns it into menu item objects.


        TBH I was confused about this, too. I think what you're doing in the
        library actually belongs in the application specific space: you're
        taking a menu definition and transform it into something _your_
        application will understand. But for the library I'd just leave the meu
        definition as it is, and leave it to the application to figure out what
        it wants to do with it.

        But other than that I think it's great to see some more work for Python,
        as it's clearly becoming more and more popular (thanks Pi!)

        --

        Michael
        Michael

        "It doesn't work - what shall I do?" - "Please check your server.log and/or scanner.log file!"
        (LMS: Settings/Information)

        Comment


          #5
          Michael,

          That's not an unfair comment!

          What I was trying to do was convert the response into the separate menu items and provide a means to access the relevant actions in a way that would be familiar to python coders, instead of having them trying to interpret the raw json response themselves.

          Obviously, the way I did this was based on how I wanted to use it in my own applications.

          Users don't have to use this module if they don't want to!

          If you think it should be done differently then I'd certainly consider changing the code.

          Comment


            #6
            Ah, ok, that's what confused me.
            So your custom menus are only delivered to applications using your library, not to all controllers/devices connected to LMS, right?
            So you just change the data the library delivers, you don't change the menus as managed by LMS ?
            ---
            learn more about iPeng, the iPhone and iPad remote for the Squeezebox and
            Logitech UE Smart Radio as well as iPeng Party, the free Party-App,
            at penguinlovesmusic.com
            New: iPeng 9, the Universal App for iPhone, iPad and Apple Watch

            Comment


              #7
              I should probably make it clearer in the docs. You can control the players without using the menu module. It's sole purpose is to help create a user interface.

              Comment


                #8
                LMSTools port to python3 and raspbian strech

                Hi,
                I am a big fan of LMS, python and DIY project.

                I have port the LMSTools library of @elParaguayo to python3 on raspbian strech, and used it on raspberry Pi :

                - to build a DIY USB controller/LMS Player for a mini-dsp DDRC-24 on my home HIFI setup

                - to interface a voice control for my LMS players with qobuz using google assistant and Home Assistant, the home automation system

                You can find the forked version of LMSTools on my github account

                URL=https://github.com/mbuffat/LMSTools
                Last edited by mbuffat69; 2020-01-11, 13:43.

                Comment


                  #9
                  This is a nice little module. It would have saved me a lot of trouble messing with the telnet interface if I'd known about it earlier.

                  BTW, the requests module makes JSON even easier to deal with (at the cost of an external dependency). It's just

                  r = requests.get(url, json=data)
                  result = r.json()['result']

                  Comment


                    #10
                    Originally posted by Daverz View Post
                    This is a nice little module. It would have saved me a lot of trouble messing with the telnet interface if I'd known about it earlier.

                    BTW, the requests module makes JSON even easier to deal with (at the cost of an external dependency). It's just
                    Yes, it's sometimes confusing that there's so much outdated information out there. I also started with Telnet using a Perl script, but got very frustrated with that.. Main issue with Telnet is that the responses get confused if you send too many messages at the same time... Then I also used LMSTools for a while, but also found that a bit frustrating and complicated. Simply using JSON (in Python or in Shell scripts) is way easier, but the info is much harder to find..

                    In Python, for more complicated stuff, I use Request. Example (count players):
                    Code:
                    import requests
                    def countplayers():
                            data = '{ "id": 1, "method": "slim.request", "params": ["", ["player", "count", "?"]]}'
                            try:
                            	response = requests.get(ServerLMS, data=data).json()['result']['_count']
                            except: response = 0
                            return response
                    Other example (all players on):
                    Code:
                    def powerplayerson():
                        for EachPlayer in Players:
                            try:
                                    data = '{ "id": 1, "method": "slim.request", "params":["'+EachPlayer+'", ["power", 1]]}'
                                    requests.post(ServerLMS, data=data)
                    In a Shell script, for simple scripting on pCP without installing Python, I use Curl. Example (>lmsjson.sh command var1 var2):
                    Code:
                    LMSIP=$(netstat -nt 2>&1 | grep :3483 | grep ESTABLISHED | uniq -f 4 | awk '{ print $5 }' | grep :3483 | awk -F: '{ print $1 }')
                    MAC=aa.bb.cc.dd.ee
                    
                    command='{"id": 1, "method": "slim.request", "params":["'$MAC'", ["'$1'", "'$2'", "'$3'"]]}'
                    eval "curl -X POST -d '"$command"' "$LMSIP":9000/jsonrpc.js"
                    Last edited by jeroen2; 2021-01-11, 11:06.

                    Comment


                      #11
                      Originally posted by jeroen2 View Post
                      Simply using JSON (in Python or in Shell scripts) is way easier, but the info is much harder to find..

                      In Python, for more complicated stuff, I use Request.
                      Hi @jeroen2,

                      I am trying to setup volume control using JSON in Python 3.9 (with requests.post) and encountering errors as below. Could you please share a full sample python program for JSON post ?

                      urllib3.exceptions.ProtocolError: ('Connection aborted.', RemoteDisconnected('Remote end closed connection without response'))

                      Comment


                        #12
                        Originally posted by sh1ntomi View Post
                        Hi @jeroen2,

                        I am trying to setup volume control using JSON in Python 3.9 (with requests.post) and encountering errors as below. Could you please share a full sample python program for JSON post ?

                        urllib3.exceptions.ProtocolError: ('Connection aborted.', RemoteDisconnected('Remote end closed connection without response'))
                        I haven't tried using Python for volume, but I do have one setup where the remote (through Lirc) sends JSON to the server through a bash script to set the volume. So in principle I would think that setting volume through JSON should work. :-)

                        Did you try using Curl on the command line to check the JSON?
                        Code:
                        curl -X POST -d '"$command"' "$LMSIP":9000/jsonrpc.js"
                        (where $command is the JSON data, and $LMSip is the address of the server)

                        An example of the full python code would be this:
                        Code:
                        #!/usr/bin/env python
                        
                        import requests
                        
                        # ----------configure players and set base values
                        ServerLMS = 'http://314.local:9000/jsonrpc.js'
                        PlayersOn =  ["xx:xx:xx:xx","xx:xx:xx:xx","xx:xx:xx:xx"]
                        
                        
                        for EachPlayer in PlayersOn:
                        	try:
                        		data = '{ "id": 1, "method": "slim.request", "params":["'+EachPlayer+'", ["power", 1]]}'
                        		requests.post(ServerLMS, data=data)
                        	except:
                        Where replacing ["power", 1] with something like ["mixer", "volume", 70] should work to set the volume.

                        As an alternative, when your script is running on the same Pi that runs the player, you could just use the command line shortcuts. ("pcp up", "pcp down") through os.system?

                        Comment

                        Working...
                        X