Home of the Squeezebox™ & Transporter® network music players.
Page 1 of 2 12 LastLast
Results 1 to 10 of 11
  1. #1
    Senior Member meep's Avatar
    Join Date
    Aug 2007
    Location
    Ireland
    Posts
    232

    Help: Implementing websockets in a plugin

    Still working on the Alexa for Squeezebox plugin and, while it's working well with a local proxy built in to the plugin, this still requires an open port and we're all aware of the risk there (even though this does not expose any LMS ports).

    Anyway, I'd hoped to implement an alternative that would not require an open port. The options are MQTT or WebSockets. I went for the later as the server side implementation in Node-Red was trivial. However, I'm running into problems building a websocket client inside my LMS plugin and wondered if anyone had encountered/solved similar or had a suggestion for an alternative ws implementation approach.

    (I have posted the remaining section to PerlMonks but thought I'd cross-post here as I might get more LMS-focused responses.)



    I have a WebSocket server application built in Node-Red sitting behind an Apache reverse-proxy configuration. (The server is very simple, responding only to 'Ping' commands with an 'OK' response.)

    Using the 'Simple Websocket Client' extension for Google Chrome, I can successfully open the server URL, send the 'Ping' request and receive the 'OK' response, so I know that the server setup works.

    However, attempting to implement the same in PERL via AnyEvent:Socket, I consistently receive a 'No such device or address' error.(AnyEvent is correctly installed via the lib folder in my plugin).

    The relevant section of my PERL code looks like this;

    Code:
    sub sockInit{
    
    use AnyEvent::WebSocket::Client 0.12;
    use URI
    
    my $client = AnyEvent::WebSocket::Client->new( );
    
        my $uri = URI->new('ws://mydomain.com/ws/test');
    
        $client->connect($uri)->cb(sub {
     
          our $connection = eval { shift->recv };
             if($@) {
              # handle error...
              myDebug($@);
              return;
         }
       
        # send a message through the websocket...
        # $connection->send('ping');
       
       });
    
      }
    Ultimately, this fails in this section of AnyEvent/WebSocket/Client.pm (around line 90);

    Code:
    AnyEvent::Socket::tcp_connect $uri->host, $uri->port, sub {
        AnyEvent::Socket::tcp_connect $uri->as_string, 80, sub {
        my $fh = shift;
        unless($fh)
        {
          $done->croak("unable to connect to ".$uri->as_string." $!");
          return;
        }
    I've made some small edits there to get around issues with $uri->host and $uri->port not existing for URI::_generic which is what ws protocol comes through as. I've also extended the croak message to include the uri)


    Here's what it typically generates;

    unable to connect to ws://mydomain.com/ws/test No such device or address at /usr/share/squeezeboxserver/Plugins/Alexa/HabProxy.pm line 201

    This code runs inside a plugin I'm writing for the Logitech SqueezeServer platform)


    The relevant part of my Apache hosts config includes these lines in <VirtualHost *.80>

    Code:
    ProxyPass /ws ws://127.0.0.1:1880/ws
    ProxyPassReverse  /ws ws://127.0.0.1:1880/ws
    As noted, I know this to be working. Ultimately, I need this to work with user authentication in Apache against a DB and with WSS: but I've simplified extensively here to see if I can track down why my Perl implementation might be failing but it works fine in other clients.
    Last edited by meep; 2017-03-27 at 08:17. Reason: code tags / cleanup


    ALEXA LMS SKILL: http://www.hab-tunes.com | Twitter: #habtunes
    Personal HA BLOG: http://mediaserver8.blogspot.com

    Squeezebox x2 | Squeezebox Radio x 2 | Squeezebox Duet x2

  2. #2
    Babelfish's Best Boy mherger's Avatar
    Join Date
    Apr 2005
    Location
    Switzerland
    Posts
    20,545

    Help: Implementing websockets in a plugin

    > However, attempting to implement the same in PERL via 'AnyEvent:Socket'
    > (http://search.cpan.org/~plicease/Any...cket/Client.pm),
    > I consistently receive a 'No such device or address' error.(AnyEvent is
    > correctly installed via the lib folder in my plugin).


    You shouldn't need to install AnyEvent in your plugin, as LMS is based
    on it already. Alas I wouldn't be surprised if the version we're using
    was outdated. And if that was actually what your code was using, rather
    than yours.

    > Ultimately, this fails in this section of AnyEvent/WebSocket/Client.pm
    > (around line 90);
    > #AnyEvent::Socket::tcp_connect $uri->host, $uri->port, sub {
    > AnyEvent::Socket::tcp_connect $uri->as_string, 80, sub {
    > my $fh = shift;
    > unless($fh)
    > {
    > $done->croak("unable to connect to ".$uri->as_string." $!");
    > return;
    > }


    Aren't there dependencies for modules to support the ws protocol? Did
    you add them as well?

    --

    Michael

  3. #3
    Senior Member meep's Avatar
    Join Date
    Aug 2007
    Location
    Ireland
    Posts
    232
    Many thanks for that Michael

    I'm definitely using the current version of AnyEvent in my plugin lib folder as I can make code changes to those files and see it have an effect.

    However, it's still possible there's a conflict there somewhere. I also believe I have all the dependencies in place as initially, there were a good number of errors relating to missing files etc. but all now resolved. I will check this further though.

    Right now, my plan is to build the simple websocket client in PERL outside the LMS plugin context to see if it's an issue with the libs or the libs inside LMS. Then, I'll try removing the AnyEvent packages from my plugin folder to see if I can call back on those used in LMS.

    I'll report back on what I find.

    Peter


    ALEXA LMS SKILL: http://www.hab-tunes.com | Twitter: #habtunes
    Personal HA BLOG: http://mediaserver8.blogspot.com

    Squeezebox x2 | Squeezebox Radio x 2 | Squeezebox Duet x2

  4. #4
    Senior Member meep's Avatar
    Join Date
    Aug 2007
    Location
    Ireland
    Posts
    232
    So I gave up implementing a standalone test as it's beyond my PERL abilities. However, I see that the LMS AnyEvent is at version 5.x and doesn't include the WebSockets packages. The plugin does indeed run this older version, with only the additional, newer WebSockets code running from the plugin lib folder. I don't see any way to override the older AnyEvent core packages in the LMS with the newer versions and I'd guess this would be a very bad thing in any case.

    I'll try to implement an alternative WebSockets solution with Mojolicious or some other solution that won't conflict with LMS.

    Peter


    ALEXA LMS SKILL: http://www.hab-tunes.com | Twitter: #habtunes
    Personal HA BLOG: http://mediaserver8.blogspot.com

    Squeezebox x2 | Squeezebox Radio x 2 | Squeezebox Duet x2

  5. #5
    Senior Member meep's Avatar
    Join Date
    Aug 2007
    Location
    Ireland
    Posts
    232

    cc

    Looks like Websocket clients just won't work in the context of LMS.

    The obvious way would be AnyEvent::Websocket::Client but this is at version 7.x and the AnyEvent libs in LMS are at 5.x and don't include WebSocket support. Adding the WebSocket package and dependencies to my plugin lib folder works OK but attempting to construct sockets fails as described above, likely due to version conflicts.

    I also tried Mojo::Websocket and Net:;Async::Websocket but both of these seem to require their own loops and implementing causes LMS to quit :-( Couldn't get them to function at all with Slim::Networking.

    I guess I could try to build my own Websocket implementation using lower-level libs but my Perl is just not up to that.

    I'm moving on to Anyevent::MQTT which is showing a little more promise but will be more involved on the server side, unfortunately.


    ALEXA LMS SKILL: http://www.hab-tunes.com | Twitter: #habtunes
    Personal HA BLOG: http://mediaserver8.blogspot.com

    Squeezebox x2 | Squeezebox Radio x 2 | Squeezebox Duet x2

  6. #6
    Senior Member meep's Avatar
    Join Date
    Aug 2007
    Location
    Ireland
    Posts
    232
    For anyone who trips across this in the future, I got MQTT working through Net::MQTT::Message and IO::Socket::INET which will co-operate with Slim::Utils::Network::blocking and Slim::Networking::Select


    ALEXA LMS SKILL: http://www.hab-tunes.com | Twitter: #habtunes
    Personal HA BLOG: http://mediaserver8.blogspot.com

    Squeezebox x2 | Squeezebox Radio x 2 | Squeezebox Duet x2

  7. #7
    Senior Member
    Join Date
    Apr 2005
    Location
    UK/London
    Posts
    4,208
    Bringing this up again as I have come across another place that could use WebSockets as a solution.
    I was looking at a radio station to grab Now Playing info and they use WebSockets for it - and they do not seem to have a simple HTTP alternative.

    Perhaps updating AnyEvent from 5.26 (2010) to 7.x could be part of LMS 8.1
    I recognise that it is a big jump though and backwards compatibility may well make it impossible to do without another good reason.

    https://metacpan.org/changes/distribution/AnyEvent
    Paul Webster
    http://dabdig.blogspot.com
    Author of "Now Playing" plugins covering Radio France (FIP etc), PlanetRadio (Bauer - Kiss, Absolute, Scala, JazzFM etc), KCRW, Supla Finland, ABC Australia, CBC/Radio-Canada and RTE Ireland

  8. #8
    Senior Member
    Join Date
    Oct 2005
    Location
    Ireland
    Posts
    20,442
    Quote Originally Posted by Paul Webster View Post
    Bringing this up again as I have come across another place that could use WebSockets as a solution.
    I was looking at a radio station to grab Now Playing info and they use WebSockets for it - and they do not seem to have a simple HTTP alternative.
    ClassicFM ?

    Perhaps updating AnyEvent from 5.26 (2010) to 7.x could be part of LMS 8.1
    I recognise that it is a big jump though and backwards compatibility may well make it impossible to do without another good reason.
    A few years ago, when HLS & DASH needed HTTP 1.1 (before philippe added it to LMS) and so I used the AnyEvent module. I thought about the need to update the LMS AnyEvent and did some investigation but shied away.

    It would make sense to add it in 8.1 as I think it is right to have the module kept up to date as AnyEvent provides flexibility and I think there are a few other uses for WebSockets.

    I might look into it to assess feasibility and trouble spots so that we can understand possible implications.

  9. #9
    Senior Member
    Join Date
    Apr 2005
    Location
    UK/London
    Posts
    4,208
    Quote Originally Posted by bpa View Post
    ClassicFM ?
    Yes - because of the forum post earlier today.
    It looks straight-forward to handle the data.

    sending
    Code:
    {"actions":[{"type":"subscribe","service":"121"}]}
    returns useful json - plus it is GlobalRadio group so I presume that lots (all?) of the stations in the group are using it (each with a different service id).

    They do not appear to be sending Now Playing track info to TuneIn (so not in LMS), RadioPlayer or last.fm

    However, I just noticed that they are (or someone is) sending it to radio.net ... so maybe you could grab it from there (although no artwork).
    radio.net have an API that is very similar to TuneIn that broadcasters can use to send Now Playing info to (I use both from the Internet radio station that I am involved with).
    Probably discussion of that sort of thing is best on your radio.net thread.
    Paul Webster
    http://dabdig.blogspot.com
    Author of "Now Playing" plugins covering Radio France (FIP etc), PlanetRadio (Bauer - Kiss, Absolute, Scala, JazzFM etc), KCRW, Supla Finland, ABC Australia, CBC/Radio-Canada and RTE Ireland

  10. #10
    Senior Member
    Join Date
    Oct 2005
    Location
    Ireland
    Posts
    20,442
    Quote Originally Posted by Paul Webster View Post
    Yes - because of the forum post earlier today.
    I checked ClassicFM a while ago and noticed "wss://" - again check again today as a result of the post.

    A few years ago, I had a Classicfm plugin for their live & "listen Again" but they changed and haven't maintained it.



    it is GlobalRadio group so I presume that lots (all?) of the stations in the group are using it (each with a different service id).
    Always a big plus when station is part of a group.

    However, I just noticed that they are (or someone is) sending it to radio.net ... so maybe you could grab it from there (although no artwork).
    radio.net have an API that is very similar to TuneIn that broadcasters can use to send Now Playing info to (I use both from the Internet radio station that I am involved with).
    Probably discussion of that sort of thing is best on your radio.net thread.
    I have avoided doing "live" info for radio.net - as they changed their layout a few times, removed some info from station list and seemed to be in flux and . So wasn't sure whether access would continue.
    IIRC Their "Live info" support was patchy which if it is still so, I rather not offer as it is confusing for users who may think plugin is broken.

Tags for this Thread

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •