I have a raspberry pi (I'm using linux) and a device that measures some values.
I have a python server and when a client sends a "I want the values" command, I ask the device some values. This is the function for my device:
def usbDevice:
dev = usb.core.find(idVendor=0xXXXX, idProduct=0xXXXX)
if dev is None:
return 'Not found'
dev.set_configuration()
dev.write(1, '\x05', 0) # ask for the values
time.sleep(2)
ret = dev.read(0x81,2048 , 0,1200) # endpoint, siz, interf, timeout ->meas. vals
print ret
return ret
When I start the communication it always goes well (both ways, I send the command and I get the
proper response ...).However, the second time I try it (no matter if I wait too long or not) I'm getting no response from the device. I know I can send the request (I used a print "step XX" to see where it is failing), but I get no answer... I am usually getting a timeout exception, but sometimes getting a "resource busy" exception.
Should I close the usb communication after using it the first time? How? Despite, I'm always compiling with sudo permissions, I created a .rules file, so I think there's not the problem.
Apart from this, I would really like to know if something's wrong with this way to establish the USB communication as I used something similar in the past. ( and I'm not good with python...)
Can you provide additional information such as the linux distribution and kernel number e.g.
uname -a
There are known USB issues. The good news is that a recent fix may have resolved them. Basically, use rpi-update and it should update the kernel (you want at least #389).
Related
I'll try to be as clear as possible with what I'm trying to aim for.
I have a running Python script on my Raspberry Pi and I'd like multiple users to send inputs to the script remotely (through SSH or anything else that might work better).
So for example if I have this script running:
Name = input ("Please type in your name. \n")
type (Name)
print ("Hello there" , Name)
time.sleep(3) # Pause for 3 seconds.
I want users to send names to this script remotely from devices that are connected to the same network as the Raspberry Pi.
If possible, I also want to implement the following functionalities:
Sending the output (aka the printed text) back to the specific device the input came from.
A queuing system: If multiple users send names at the same time, the script will take the names in order, one by one.
I know it's a lot to ask for, but I'd really appreciate if someone could help me get started with this by pointing me in the right direction. I've searched around quite a bit for the past few days but I haven't really come across anything that fits my needs.
Edit: I'm running this on PYTHON 3
Your comment that you would like to communicate (via network) to the script directly, opens up a world of possibilities. You have to modify your Python script a little though, because it won't communicate via stdin/stdout any longer.
I'm still not entirely sure how you want things to work but it does sound to me that a solution based around RPC can possibly work for you. May I suggest you have a look at Pyro4? Basically what that does for you is enable you to do normal Python method calls, but over the network, to code running on another computer.
So you can set up a server on your Pi (that needs to run continuously) which accepts remote calls from other computers, and can then call into your python code on the pi. It can process calls in parallel or in sequence. You didn't say if you need any form of security, but some basic security features are provided (no built-in encryption or communication over TLS yet, sorry).
A simple example is here and lots more are on github so you can have a look to see if this fits your requirements?
Another solution that doesn't require third party libraries is perhaps to write a WSGI http server that calls your script, run this on the pi, and access it via HTTP from your other computers.
I am having problems with sending triggers from a 32 bit PC with Windows XP Professional and Psychopy v.1.81.03 to the parallel port.
I am positive that the port address is 378, and am able to send triggers with Eprime and I am able to turn specific pins on and off with the software parmon (http://english.eazel.com/lv/group/view/kl35264/Parmon.htm)
I have tried using the experiment posted by Stéphanie and Nicholas (see this post in the psychopy google group: https://groups.google.com/forum/#!topic/psychopy-users/PxPhRDkuu2A)
I have verified that pywin32 (version 217) and parallel are installed, and tried both
port = parallel.ParallelPort(address=0x0378)
port = parallel.PParallelInpOut32(address=0x0378)
When using ParallelPort, I get:
Traceback (most recent call last):
File “ D:\SebastianKorb\untitled2_lastrun.py”, line 65, in
port = parallel.ParallelPort(address=0x0378) AttributeError: ‘module’
object has no attribute ‘ParallelPort’
Line 65 is where the command port = parallel.ParallelPort(address=0x0378)
is executed (note though that before that there is the line from psychopy import parallel)
When using PParallelInpOut32 I get the same (only now the error is about ‘PParallelInpOut32’)
I also tried to run the few lines of code shown on the psychopy reference manual (http://www.psychopy.org/api/parallel.html):
from psychopy import parallel
port = parallel.ParallelPort(address=0x0378)
port.setData(4)
port.readPin(2)
port.setPin(2, 1)
But again, I get the same type of error.
I should mention that I have also verified that I have administrator access to the file C:\Windows\system32\drivers\parport.sys
Can you please advise me on what I should try next?
I overlooked that it's actually the other way around. The direct calls to the parallel-port functions (as below) are deprecated. Nevertheless, they should still work. So maybe give it a try:
from psychopy import parallel
parallel.setPortAddress(0x378) #address for parallel port on many machines
parallel.setData(0) #sets all pins low
parallel.setPin(2,1) # set a certain pin high
parallel.setData(0) #sets all pins low
You should leave the pin high for a while or leave out the last line. Otherwise, you won't be able to detect the change. That's also how it is done in the Coder hardware demo "parallelPortOutput.py". Maybe try this first.
Best,
Axel
Addition:
Sebastian, my hunch at the moment is that the port does not even get initiated. I think the problem at the moment is that the respective error messages are only logged, but no informative error message is thrown (check the log files). That means that actually somehow the port drivers cannot be accessed on your system for some reason.
In the Coder Shell type from psychopy import parallel and then do next port = parallel.ParallelPort() (no address). Now just type port and paste the output here. My guess is that you only get the base class (ParallelPort) with which you cannot do anything, i.e., something like <psychopy.parallel.ParallelPort object at 0xe4805b0>. In that case, you would need to fix access to the drivers somehow.
I'm gong to back Axel's "hunch" here. I think it's extremely likely that either you don't have a parallel port driver installed or it isn't working. Try installing the InpOut32 driver from here, restart your computer and see if that fixes it:
http://www.highrez.co.uk/Downloads/InpOut32/
cheers,
Jon
I'm having trouble reading the response from a RS232 OBD2 interface via pySerial.
The code successfully enters the data, as I can see from a direct parallel terminal screen, but fails to read and print the response, regardless of the response.
Right now the code is not capable of printing the response in neither versions of Python.
The code looks something like this :
from serial import * # I also tried using /from serial import Serial
import time
ser = Serial("/dev/rfcomm1", 38400, timeout=1)
#print ('Starting up, formatting responses')
#ser.write("ATZ\r"),
#ser.write("ATSP0\r"),
#ser.write("ATS1\r"),
#ser.write("ATL1\r"),
#ser.write("ATH1\r"),
#ser.write("ATF1\r")
#time.sleep(1)
#print ('We have lift-off !')
if ser.inWaiting() > 0:
ser.flushInput()
#ser.timeout = 1.
time.sleep(1)
#print (raw_data)
ser.write("AT RV\r") #The response should be something like 13.5V, but nothing
ser.timeout = 1.
msg = ser.read(size=1024)
print msg
ser.close()
I left only the AT RV command because while I'm working on it I sent the text formatting commands to ease the job. Right now when I send it it just gives me a blank line (although the terminal which is running on the same machine displays the desired output)
There are no errors in the code, and the commands go through and are responded to by the interface, and I can see that in another live term, but nothing appears when running the Python code.
What should I do ?
You should read after writing, not before.
# before writing anything, ensure there is nothing in the buffer
if ser.inWaiting() > 0:
ser.flushInput()
# set the timeout to something reasonable, e.g., 1 s
ser.timeout = 1.
# send the commands:
ser.write("ATZ\r")
# ...
# read the response, guess a length that is more than the message
msg = ser.read(1024)
print msg
# send more commands
# read more responses
# ...
The point here is that there is no way to know when the response has been received. This code waits for one second after each command sent, unless more than 1024 bytes arrive during that time. There are more clever algorithms, but let's try with this one, first.
If you want to do something more complicated with the serial line, have a look at the pexpect module.
Some thoughts debugging python serial problems
Serial communication problems are sometimes a bit sticky to solve. pySerial is a reliable library, but as different platforms have different types of serial API, there are a lot of details. Things have not become any easier by the removal of physical serial ports, as the USB converters bring an extra layer into the game. Bluetooth converters are even worse.
The best way to debug the physical layer is to have some monitor hardware with two serial ports tapped into the serial lines. This kind of sniffer helps to isolate the problem to either end of the connection. Unfortunately, such sniffers are very rarely at hand when needed.
The next best thing is to short the RD and TD (RXD, TXD) pins of the serial line. This way all data will be echoed. If the data is received as sent, the physical connection is good. One thing to take care is handshaking. If you do not know what you are doing, disable all flow control (xon/xoff, rts/cts, dtr/dsr. pySerial disables these all if otherwise instructed.
In the case of the question above the physical connection is ok, as another piece of software demonstrates that the data is sent and understood by the other device. (Seeing that something is sent does not prove anything, as that information does not go through the physical layer, but seeing something produced by another device is received proves that the physical connection is ok.)
Now we know the data comes into the operating system, but pySerial does not see it. Or then our code is still somehow bad (no, it shouldn't, but...)
Let us suspect own own code and try someone else's code. This can be run from command prompt:
python -m serial.tools.miniterm /dev/rfcomm1 38400
Now we have a terminal which can be used to manually send/receive data form the other party. If the behaviour can be repeated (sends ok, data is received into the system, but not shown on the terminal) with this, then the problem is probably not in our code.
The next step then is to try:
sudo python -m serial.tools.miniterm /dev/rfcomm1 38400
In principle access right problems lead to situations where we can receive but not send. But it does not harm to test this, because odd rights cause odd problems.
pySerialhas a handy function readline which should read one line at a time from the serial line. This is often what is wanted. However, in this specific case the lines seem to end with \r instead of \n. The same may be repeated elsewhere in code, so with special data special care is needed. (The simple "read with timeout" is safe but slow in this sense.) This is discussed in: pySerial 2.6: specify end-of-line in readline()
The same issue plagues all terminal programs. For the pySerial miniterm, see its documentation (command-line option --cr).
If there are timeouts, they can and should be made longer for debugging purposes. A one-second timeout may be changed into a ten-second timeout to make sure the other device has ample time to answer.
I had exactly the same problem, through Python 2 IDLE no results displayed on the IDLE screen, but the results were redirected to picocom active at the terminal. I needed to capture results because my goal is to read incoming SMSs.
The following code solved my problem, I do not know the reason yet, ongoing analysis.
import time
import serial
modem1 = serial.Serial("/dev/ttyUSB3",baudrate=115200,timeout=0,rtscts=0,xonxoff=0)
def sendat1(cmd):
if cmd == 'res' : modem1.write('Z'); return
if cmd == 'out' : modem1.write(chr(26)); return
modem1.write('AT+'+cmd+'\r')
time.sleep(3)
obu = str(modem1.inWaiting())
msg = modem1.read(32798)
print(obu+':\n'+msg)
return
try:
if modem1.inWaiting()>0: modem1.flushInput()
sendat1('res')
sendat1('CMGF=1')
sendat1('CMGL')
sendat1('out')
finally:
modem1.close()
I have a python script (running on Mac OS X) that needs to be restarted when the internet goes down. If the internet is down, I would like to kill the current script, wait for the internet to go back up, and then restart it. Or, if possible, restart the function from within.
The problematic section of the Python code is as follows:
import tweetstream
# ...
with tweetstream.FilterStream(username, password, track = words) as stream:
for tweet in stream:
db.tweets.save(tweet)
Currently, if the internet goes down, the stream stops and doesn't reconnect.
It depends from os. There are few os specific methods.
First cross platform method will be own ping which will be send some packets to the Internet server. If you can not receive info that means Internet is goes down.
Try using this python implementation of ping as a subprocess. Thus, if too many timeouts occur, then you'll know the network's down and you can re-initiate the tweet process (however, to do this, you should probably put the entire tweeting process in a function of its own)
Perhaps you could try something like this:
import urllib2
def internet_on():
try:
response=urllib2.urlopen('http://74.125.131.94/',timeout=1)
return True
except urllib2.URLError as err: pass
return False
74.125.131.94 is the ip address of google.co.in . You can use whatever site you think will respond more quickly. Using a numerical IP-address avoids a DNS lookup, which may block the urllib2.urlopen call.The timeout=1 parameter makes sure that the call to urlopen will not take longer than 1 second even if the internet is not available.
Now you just need to call the internet_on() function. It will return true if the connection is on, else return false. Then you might want to wrap all the tweeting code inside a function and call it. (As #inspectorG4dget suggested).
EDIT:
For continuous checking you could do something like
def check():
while not internet_on():
pass
print "internet connection is on"
// call the tweet stuff function here.
Then when your stream stops just call the check() function and when the internet connection is back , it will call your tweet function to restart it.
On linux (ubuntu), is it possible to execute a script upon any incoming network connection?
During long periods inactivity on my home server, I plan on stopping the software raid, parking the data disks and restarting the raid array upon encountering an incoming network connection.
I've been researching this problem and haven't come across an appropriate solution yet, any help is appreciated.
Neil
Note: I'm aware it's unnessecary to stop/start the array and there are downsides (disk wear & tear...). However I'm set in my ways, please do not post advising me not to stop/start the disks.
Edit (1):
Thought I'd share my opinion and hopefully get some feedback on it.
I think I'd need to use xinetd binding a catcher script that catches incoming connection data on all ports, launches my launch script and passes the incoming connection data to the relevant service for that port. Only issue is I don't know what data I would need to catch or how to in python.
Edit (2):
I've hacked together a solution using the python library pypcap http://code.google.com/p/pypcap/ . For future reference, here is the code.
import pcap
...
pc = pcap.pcap(name)
pc.setfilter(' '.join(args))
pc.setnonblock()
try:
for ts, pkt in pc:
# subprocess.call([filename, args])
print 'readying disks...'
break
except OSError, ValueError:
print 'Error: invalid arguements passed to subprocess'
except KeyboardInterrupt:
print 'Error: keyboard interupt'
Take a look at netfilter/iptables. You may be able to write code to use the userspace API libraries to detect incoming packet events.