Find the answer to your Linux question:
Results 1 to 7 of 7
I would like to integrate musicpd into my home automation. My home automation system can send UDP telegrams. Therefor, I was wondering if it would be possible to set up ...
Enjoy an ad free experience by logging in. Not a member yet? Register.
  1. #1
    Just Joined!
    Join Date
    Aug 2005
    Posts
    9

    UDP listener


    I would like to integrate musicpd into my home automation. My home automation system can send UDP telegrams.

    Therefor, I was wondering if it would be possible to set up a udp listener or daemon that listens to a specific port. Whenever there is a telegram on that port, it compares it with a predefined list of telegrams. Each predefined telegram should be linked to a command shell program.

    By doing so, I would be able to start, stop, pauze, ... Music by using the musicpd command shell app (mpc).

    Can you help me (I must admit that I have no experience with udp telegrams).

    Ivan

  2. #2
    Trusted Penguin Irithori's Avatar
    Join Date
    May 2009
    Location
    Munich
    Posts
    3,382
    Well, listening to a udp port is trivial.
    For first tests, netcat or socat can be used.
    Code:
    netcat -ul 2000
    This will listen to udp port 2000 and send every incoming udp datagram to standardout.
    An actual implementation may use xinetd or a dedicated server.

    The problem is to understand, what your home automation sends, and what it expects in return.
    This may or may not be documented.
    If it is documented, some coding may be needed, as you have already indicated in your post.
    You must always face the curtain with a bow.

  3. #3
    Just Joined!
    Join Date
    Aug 2005
    Posts
    9
    Tx for your reply. My home automation can send whatever string by an UDP connection. E.g. I can send a UDP telegram by specifying "sendudp(3807u,192.168.1.53,$Start$)". This will send the string "start" to port 3807 on the specified IP address.

    When listening to this port (thanks to your post), I can see that "Start" is coming over ("netstat -ulp 3807").

    Can you point me in the right direction so I can write a shell script that runs as a daemon. The script should react as follows:
    - when receiving "Start" -> run "/usr/bin/mpc -h 192.168.1.53 play"
    - when receiving "Stop" -> run "/usr/bin/mpc -h 192.168.1.53 stop"
    - when receiving "Next" -> run "/usr/bin/mpc -h 192.168.1.53 next"
    ...

    Tx for your help

  4. #4
    Trusted Penguin Irithori's Avatar
    Join Date
    May 2009
    Location
    Munich
    Posts
    3,382
    Ok, I got a skeleton implementation.
    There is surely a lot room for improvements.

    It works with tcp only for now.
    For the udp version, there is a problem with (presumably) the socket_type.

    Need to investigate some more here, but maybe s/o else has a hint?

    What I know: /usr/local/bin/mpdproxy.sh gets called,
    but it stalls on the read command, unless a timeout is used.

    It probably doesnt receive anything via stdin,
    and instead the udp socket opened by xinetd needs to be handed over to the script.


    Anyway, you will need an installed xinetd daemon.

    Disclaimer:
    Make sure you have a backup of this file:
    /etc/services

    Code:
    cat >> /etc/services <<EOF
    mpdproxy         3807/tcp                       # receive commands and use them with mpd
    mpdproxy         3807/udp                       # receive commands and use them with mpd
    EOF
    Code:
    cat >> /etc/xinetd.d/mpdproxy <<EOF
    # default: off
    # description: An xinetd service which triggers mpd actions 
    # based on commands received via udp/tcp
    
    # This is the udp version.
    service mpdproxy
    {
            disable         = no
            socket_type     = dgram
            protocol        = udp
            port            = 3807
            server          = /usr/local/bin/mpdproxy.sh
            user            = nobody
            wait            = yes
    }
    
    # This is the tcp version.
    service mpdproxy
    {
            disable         = no
            socket_type     = stream
            port            = 3807
            server          = /usr/local/bin/mpdproxy.sh
            user            = nobody
            wait            = no
    }
    EOF
    Code:
    mkdir -p /usr/local/bin
    Code:
    cat >> /usr/local/bin/mpdproxy.sh <<EOF
    #!/usr/bin/env bash
    
    ## get command,
    ## strip windows style line feed and perform basic input validation
    read -t 3 STDIN
    INCOMING_COMMAND=$(echo ${STDIN}|sed 's/\x0D$//'|egrep '^(Start|Stop|Next)$)
    
    ## tools
    MPC_BIN="/usr/bin/mpc"
    MPC_OPT="-h 192.168.1.53"
    
    LOGGER_BIN="/usr/bin/logger"
    LOGGER_OPT="-t mpdproxy -p local0.err"
    
    ## depending on the command, call the mpd. 
    ## Log failed calls to syslog 
    case "${INCOMING_COMMAND}" in
        Start)
            if ! $MPC_BIN $MPC_OPT play; then $LOGGER_BIN $LOGGER_OPT ERROR while executing mpd play; fi
                ;;
        Stop)
            if ! $MPC_BIN $MPC_OPT stop; then $LOGGER_BIN $LOGGER_OPT ERROR while executing mpd stop; fi
                ;;
        Next)
            if ! $MPC_BIN $MPC_OPT stop; then $LOGGER_BIN $LOGGER_OPT ERROR while executing mpd next; fi
                ;;
        *)
            $LOGGER_BIN $LOGGER_OPT ERROR unknown command received: $STDIN
                ;;
    esac
    
    exit 0
    
    EOF
    Code:
    chown nobody /usr/local/bin/mpdproxy.sh
    chmod 700 /usr/local/bin/mpdproxy.sh
    Restart the xinetd daemon
    Last edited by Irithori; 08-02-2011 at 11:58 PM.
    You must always face the curtain with a bow.

  5. #5
    Trusted Penguin Irithori's Avatar
    Join Date
    May 2009
    Location
    Munich
    Posts
    3,382
    Ok.
    It seems, in case of udp the server itself needs to read and make sense of the datagram.
    comp.unix.programmer: Re: Writting a UDP server program under inetd/xinetd
    Which might be messy in bash.

    I thought, that xinetd would do some of the magic and just provide the actual data.
    But meh.

    Any chance, that you can implement your server in python/perl/ruby/etc?
    http://www.java2s.com/Code/Python/Ne...verforWait.htm
    Or alternatively: Can that home automation system send tcp as well?
    You must always face the curtain with a bow.

  6. #6
    Just Joined!
    Join Date
    Aug 2005
    Posts
    9
    Quote Originally Posted by Irithori View Post
    Ok.
    Or alternatively: Can that home automation system send tcp as well?
    TCP is also possible, but I have to check how this should be done.

    Nevertheless thanks for thinking with me. I tought it should be easy, but I was mistaken.

    Ivan

  7. #7
    Trusted Penguin Irithori's Avatar
    Join Date
    May 2009
    Location
    Munich
    Posts
    3,382
    Well, for tcp it is fairly simple, even in bash. The above scripts should work.
    udp needs some lines more and something else than bash

    P.S.: Forgot a '
    Code:
    INCOMING_COMMAND=$(echo ${STDIN}|sed 's/\x0D$//'|egrep '^(Start|Stop|Next)$')
    You must always face the curtain with a bow.

Posting Permissions

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