I am working with the cwiid library, which is a library written in C, but used in python. The library allows me to use a Wiimote to control some motors on a robot. The code is running as a daemon on an embedded device without a monitor, keyboard, or mouse.
When I try to initialize the object:
import cwiid
while True:
try:
wm = cwiid.Wiimote()
except RuntimeError:
# RuntimeError exception thrown if no Wiimote is trying to connect
# Wait a second
time.sleep(1)
# Try again
continue
99% of the time, everything works, but once in a while, the library gets into some sort of weird state where the call to cwiid.Wiimote()
results in the library writing "Socket connect error (control channel)" to stderr, and python throwing an exception. When this happens, every subsequent call to cwiid.Wiimote()
results in the same thing being written to stderr, and the same exception being thrown until I reboot the device.
What I want to do is detect this problem, and have python reboot the device automatically.
The type of exception the cwiid library throws if it's in a weird state is also RuntimeError
, which is no different than a connection timeout exception (which is very common), so I can't seem to differentiate it that way. What I want to do is read stderr right after running cwiid.Wiimote()
to see if the message "Socket connect error (control channel)" appears, and if so, reboot.
So far, I can redirect stderr to prevent the message from showing up by using some os.dup()
and os.dup2()
methods, but that doesn't appear to help me read stderr.
Most of the examples online deal with reading stderr if you're running something with subprocess, which doesn't apply in this case.
How could I go about reading stderr to detect the message being written to it?
I think what I'm looking for is something like:
while True:
try:
r, w = os.pipe()
os.dup2(sys.stderr.fileno(), r)
wm = cwiid.Wiimote()
except RuntimeError:
# RuntimeError exception thrown if no Wiimote is trying to connect
if ('Socket connect error (control channel)' in os.read(r, 100)):
# Reboot
# Wait a second
time.sleep(1)
# Try again
continue
This doesn't seem to work the way I think it should though.