Plugin to read data from file on Raspberry Pi
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?
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
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:
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...
Code: Select all
myContent = urllib2.urlopen("ftp://user:pass@%s/now.xml" % devIP).read(500)
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
If anyone is interested I can post the code.
Sent from my iPhone using Tapatalk
Re: Plugin to read data from file on Raspberry Pi
I suspect that 'expect' is actually the python requests module.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
ETA: Not so much (see below).
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]
[My Plugins] - [My Forums]
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
And it comes preinstalled on each unix .. even on a mac
Sent from my iPhone using Tapatalk
Re: Plugin to read data from file on Raspberry Pi
Sorry, thought you were speaking Python!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
I came here to drink milk and kick ass....and I've just finished my milk.
[My Plugins] - [My Forums]
[My Plugins] - [My Forums]
Re: Plugin to read data from file on Raspberry Pi
there likely many expects ..
Re: Plugin to read data from file on Raspberry Pi
Interested. Probably take me a while to decipher it, but I'd like to try! Thanks!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
http://nerdhome.jimdo.com
Re: Plugin to read data from file on Raspberry Pi
Will post tomorrow.
Sent from my iPhone using Tapatalk
Sent from my iPhone using Tapatalk
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
this is the expect code in file dictLoop.exp:
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 :
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
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
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
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, ""
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