Plugin to read data from file on Raspberry Pi

Posted on
Tue Sep 05, 2017 8:01 am
Swancoat offline
Posts: 499
Joined: Nov 20, 2009
Location: Houston

Plugin to read data from file on Raspberry Pi

So, I'm not really looking for super specific code examples here or anyone to do the work for me. More like just a general ideas or tips on what methods I need to do something, or where to find examples to do the steps I need here. Of course I WOULD pay for a done solution... but this really is just a hobby for me, and so the amount I'm willing to pay is probably less than anyone would need to do the work!

Background:

I have an Airport Express hooked up to my whole home audio system, and I'd like to capture the metadata from when people stream sources to them so that I can display it on the keypads. There doesn't seem to be any way to do this with an Airport Express, so step one of my solution is Shairport-Sync (https://github.com/mikebrady/shairport-sync). Basically this is an app that runs on a Raspberry Pi that makes it appear as an Airport Express AND can export the metadata of whatever is playing. I've got this part working and it works fine. I have a Raspberry Pi up and running that is effectively an Airport Express. People streaming to it don't know the difference, and it's been bulletproof for a couple of months now.

Next: The metadata.

Shairplay-Sync pushes the metadata into a named pipe on the Raspberry Pi. I want to make a plugin that I can define the IP address of the Pi (and any other info I need to) and then read the metadata (mainly song title, album, artist) and do what I want with them (most simply I'll just store them in a device state, or user-definable variable, but I see Indigo Plugins can now publish/subscribe, so that'd be cool too).

What I need to know is how the heck I make my plugin read that data. Do I have to have something running on the Pi that sort of makes the file available? Or can I just have the plugin log on itself and get the data. I've sampled the data on the Pi and it's in XML, so an XML parser is going to be required to, but I can probably figure that out later.

What do I know? Not much. I know what a named pipe is. Barely. Pretty much what a bunch of googling can tell me (effectively a data 'stream', but defined like a file with a location, etc...?)

I've made a couple of plugins, but they're basically simple serial port interfaces. Open the port, read if something's there, parse it, update some variables. Take some input from the plugin and turn into a command and feed it to the serial port. Reading from a network socket seems a bit more complicated.

Any idea on how I need to go about this?

http://nerdhome.jimdo.com

Posted on
Tue Sep 05, 2017 9:01 am
racarter offline
User avatar
Posts: 239
Joined: Jun 18, 2016
Location: North Yorkshire, UK

Re: Plugin to read data from file on Raspberry Pi

I had a similar requirement (to access a file on the Pi) and went the FTP route. Install a barebones FTP server on the Pi (I used vsftpd) then you can get at your file using an FTP url such as:
Code: Select all
myContent = urllib2.urlopen("ftp://user:pass@%s/now.xml" % devIP).read(500)

where devIP is the Raspberry Pi IP address and now.xml is the file to be read. Not sure if this would work with a named pipe though...

Posted on
Tue Sep 05, 2017 3:34 pm
kw123 offline
User avatar
Posts: 6881
Joined: May 12, 2013
Location: Dallas, TX

Re: Plugin to read data from file on Raspberry Pi

I am using expect to send and get data with ssh and sftp to from the rpi
If anyone is interested I can post the code.


Sent from my iPhone using Tapatalk

Posted on
Tue Sep 05, 2017 6:30 pm
DaveL17 offline
User avatar
Posts: 5346
Joined: Aug 20, 2013
Location: Chicago, IL, USA

Re: Plugin to read data from file on Raspberry Pi

kw123 wrote:
I am using expect to send and get data with ssh and sftp to from the rpi
If anyone is interested I can post the code.


Sent from my iPhone using Tapatalk

I suspect that 'expect' is actually the python requests module.

ETA: Not so much (see below). :D
Last edited by DaveL17 on Tue Sep 05, 2017 7:44 pm, edited 1 time in total.

I came here to drink milk and kick ass....and I've just finished my milk.

[My Plugins] - [My Forums]

Posted on
Tue Sep 05, 2017 7:13 pm
kw123 offline
User avatar
Posts: 6881
Joined: May 12, 2013
Location: Dallas, TX

Plugin to read data from file on Raspberry Pi

The Expect( I am using ) is its own language for terminal interactions based on tcl
And it comes preinstalled on each unix .. even on a mac

Sent from my iPhone using Tapatalk

Posted on
Tue Sep 05, 2017 7:42 pm
DaveL17 offline
User avatar
Posts: 5346
Joined: Aug 20, 2013
Location: Chicago, IL, USA

Re: Plugin to read data from file on Raspberry Pi

kw123 wrote:
The Expect( I am using ) is its own language for terminal interactions based on tcl
And it comes preinstalled on each unix .. even on a mac

Sent from my iPhone using Tapatalk

Sorry, thought you were speaking Python! :D

I came here to drink milk and kick ass....and I've just finished my milk.

[My Plugins] - [My Forums]

Posted on
Tue Sep 05, 2017 7:55 pm
kw123 offline
User avatar
Posts: 6881
Joined: May 12, 2013
Location: Dallas, TX

Re: Plugin to read data from file on Raspberry Pi

there likely many expects .. :D

Posted on
Tue Sep 05, 2017 8:51 pm
Swancoat offline
Posts: 499
Joined: Nov 20, 2009
Location: Houston

Re: Plugin to read data from file on Raspberry Pi

kw123 wrote:
I am using expect to send and get data with ssh and sftp to from the rpi
If anyone is interested I can post the code.


Sent from my iPhone using Tapatalk


Interested. Probably take me a while to decipher it, but I'd like to try! Thanks!

http://nerdhome.jimdo.com

Posted on
Tue Sep 05, 2017 9:48 pm
kw123 offline
User avatar
Posts: 6881
Joined: May 12, 2013
Location: Dallas, TX

Re: Plugin to read data from file on Raspberry Pi

Will post tomorrow.


Sent from my iPhone using Tapatalk

Posted on
Sat Sep 09, 2017 3:39 pm
kw123 offline
User avatar
Posts: 6881
Joined: May 12, 2013
Location: Dallas, TX

Re: Plugin to read data from file on Raspberry Pi

sorry took a bit longer:


this how it is called
in the shell you MUST use the full path to the executable (expect)
then the full path to the expect script and parameters each separated by a space userid password etc

Code: Select all
/usr/bin/expect  '/Library/Application Support/Perceptive Automation/Indigo 7/Plugins/uniFiAP.indigoPlugin/Contents/Server Plugin/dictLoop.exp' userID PASSWORD 192.168.1.x BZ.v xxxThisIsTheEndTokenxxx 40 10  /var/log/message


this is the expect code in file dictLoop.exp:
Code: Select all
set userID [lindex $argv 0 ]
set password [lindex $argv 1 ]
set ipNumber [lindex $argv 2 ]
set promptOnServer [lindex $argv 3]
set endDictToken [lindex $argv 4]
set readDictEverySeconds [lindex $argv 5]
set mcatimeout [lindex $argv 6]
set logfile [lindex $argv 7]

set timeout 10
spawn  ssh $userID@$ipNumber
expect {
    "(yes/no)? " {
        send "yes\n"
        sleep 0.1
        expect "assword: " { send "$password\n"}
    }
    "assword: " {
        send "$password\n"
    }
}
sleep 1.0;
expect "$promptOnServer" {puts "startxxxx\r";}
sleep 1.0

set timeout $mcatimeout
send "\r"
    for {set i 1} {$i >0} {incr i 1} {
        sleep 0.2
        expect "$promptOnServer"
        send "mca-dump | sed -e 's/^ *//' \r"
        expect "$promptOnServer"
        puts "$endDictToken$i\r\r"
        sleep $readDictEverySeconds
        send "\r"
        expect "$promptOnServer"
        if {$logfile != "doNotSendAliveMessage"} {
            send "echo ThisIsTheAliveTestFromUnifiToPlugin >> $logfile\r"
        }

    }

expect "$promptOnServer"
puts "end\r"
send "exit\r"
sleep 0.1
expect eof


it logs into a unifi AP
then it runs mca-dump .. removes leading space (it produces a heavily formatted json dump. with sed -e 's/^ *//' the leading space get removed)
adds the string "xxxThisIsTheEndTokenxxx" to the output
and adds "ThisIsTheAliveTestFromUnifiToPlugin" to the uniform AP log file

and does that in a loop

then the plugin
with :
Code: Select all
 
                    cmd = "/usr/bin/expect  '" + \
                          self.pathToPlugin + self.expectCmdFile[type] + "' " + \
                          self.unifiUserID + " " + \
                          self.unifiPassWd + " " + \
                          ipNumber + " " + \
                          self.promptOnServer[type] + " " + \
                          self.endDictToken[type]+ " " + \
                          str(self.readDictEverySeconds[TT])+ " " + \
                          str(self.timeoutDICT)
                    if type.find("AP") >-1:
                         cmd += "  /var/log/messages"
                    else:
                         cmd += "  doNotSendAliveMessage"
               ListenProcess = subprocess.Popen(cmd, stdin=subprocess.PIPE, stdout=subprocess.PIPE, stderr=subprocess.PIPE, shell=True)
                ##pid = ListenProcess.pid
                ##self.ML.myLog("all", " pid= " + str(pid) )
                msg = unicode(ListenProcess.stderr)
                if msg.find("[Err ") > -1:  # try this again
                    self.ML.myLog("all", type + " error connecting " + msg, type=u"EXPECT")
                    self.sleep(20)
                    continue
                flags = fcntl.fcntl(ListenProcess.stdout, fcntl.F_GETFL)  # get current p.stdout flags
                fcntl.fcntl(ListenProcess.stdout, fcntl.F_SETFL, flags | os.O_NONBLOCK)
                return ListenProcess, ""

receives these dumps every xx seconds through the pipe opened.

hope that is not to complex ..


In a nutshell:

expect sends characters to ssh which can be controlled by the return messages from ssh with If s etc.

then you can start processes on the remote computer, like create dump-file or open a pipe (e.g. tail-f /var/log/syslog) and feed that to a listener process in your plugin.

looks complicated and it is not for beginners ..

a simple expect script should be easy. there are many examples on the web.

Karl

Page 1 of 1

Who is online

Users browsing this forum: No registered users and 0 guests