Mercurial > code > home > repos > homeauto
view service/usbReset/usbReset.py @ 846:5c6133c227d0
usb reset mess
Ignore-this: 66107d6e9c5740a91d11a6ece7efc433
darcs-hash:20120827055524-312f9-ffe0e119c519786ace0b3ff8765e9c2c7a7bdb81
author | drewp <drewp@bigasterisk.com> |
---|---|
date | Sun, 26 Aug 2012 22:55:24 -0700 |
parents | |
children | 022921fdafd0 |
line wrap: on
line source
#!bin/python """ resets usb ports and restarts other services. Must run as root for the usb part. Other systems that might be able to do conditional tests and commands like this: https://github.com/azkaban/azkaban nagios run this as root to reset a whole usb device. Ported from http://marc.info/?l=linux-usb&m=121459435621262&w=2 how to learn what device to reset? lsusb or lsusb -t how to learn the ioctl number? cpp on this file: #include "/usr/include/linux/usbdevice_fs.h" #include "/usr/include/asm-generic/ioctl.h" USBDEVFS_RESET last line comes out like this: (((0U) << (((0 +8)+8)+14)) | ((('U')) << (0 +8)) | (((20)) << 0) | ((0) << ((0 +8)+8))) this is a py expression: (((0) << (((0 +8)+8)+14)) | ((ord('U')) << (0 +8)) | (((20)) << 0) | ((0) << ((0 +8)+8))) """ from __future__ import division import cyclone.web, json, traceback, os, sys, time, logging import os, fcntl, commands, socket, logging, time, xmlrpclib, subprocess from twisted.internet import reactor, task from twisted.internet.defer import inlineCallbacks, returnValue from twisted.web.client import getPage sys.path.append("/my/proj/house/frontdoor") from loggingserial import LoggingSerial sys.path.append("/my/proj/homeauto/lib") from cycloneerr import PrettyErrorHandler from logsetup import log USBDEVFS_RESET = 21780 class Id(object): ftdi = "0403:6001" frontDoorHub0 = "8087:0024" # bus2 dev 2 frontDoorHub1 = "0451:2046" # bus2 dev 3 frontDoorHub2 = "1a40:0101" # bus2 dev 7 frontDoorHub3 = "0409:0058" # bus2 dev 62 frontDoorCam = "0ac8:307b" bedroomHub0 = "8087:0020" bedroomHub1 = "05e3:0608" bedroomHub2 = "058f:6254" bedroomHub3 = "0409:005a" bedroomCam = "046d:08aa" bedroomSba = "04d8:000a" bedroomArduino = "0403:6001" garageHub0 = "1d6b:0002" # bus2 dev1 garageHub1 = "05e3:0604" # bus2 dev4 garageArduino = "2341:0001" garagePowerSerial = "0557:2008" blueHub = "1a40:0101" hostname = socket.gethostname() @inlineCallbacks def getOk(url, timeout=1): """can we get a successful status from this url in a short time?""" log.debug("testing %s" % url) try: resp = yield getPage(url, timeout=timeout) except Exception, e: log.warn("getPage %s", e) returnValue(False) returnValue(True) def hubDevice(usbId="1a40:0101"): """ what's the /dev path to the device with this usb id """ for line in commands.getoutput("lsusb").splitlines(): if 'ID '+usbId in line: words = line.split() return "/dev/bus/usb/%s/%s" % (words[1], words[3].rstrip(':')) raise ValueError("no usb device found with id %r" % usbId) def haveDevice(usbId): try: log.debug("checking for %s", usbId) hubDevice(usbId) return True except ValueError: return False def resetDevice(dev): """ send USBDEVFS_RESET to the given /dev address """ log.debug("resetting %s" % dev) f=os.open(dev, os.O_WRONLY) ret = fcntl.ioctl(f, USBDEVFS_RESET, 0) if ret != 0: raise ValueError("ioctl failed with %s" % ret) time.sleep(3) def supervisorRestart(cmds, supervisor="http://localhost:9001"): serv = xmlrpclib.ServerProxy(supervisor) for c in cmds: log.info("restarting %s", c) try: serv.supervisor.stopProcessGroup(c) except xmlrpclib.ResponseError, e: log.warn("supervisor.stopProcessGroup error %r, ignoring", e) serv.supervisor.startProcess(c) def resetModules(modules): log.info("reloading modules: %s", modules) for m in modules: subprocess.call(['modprobe', '-r', m]) for m in modules: subprocess.check_call(['modprobe', m]) class Background(object): def __init__(self, config, period): self.config = config self.period = period self.lastPollTime = 0 def assertIsCurrent(self): """raise an error if the poll data is not fresh""" dt = time.time() - self.lastPollTime if dt > self.period * 2: raise ValueError("last poll time was too old: %.1f sec ago" % dt) @inlineCallbacks def step(self): now = time.time() try: if hostname == 'bang': if (not haveDevice(Id.bedroomCam) or not haveDevice(Id.bedroomArduino)): if haveDevice(Id.bedroomHub3): resetDevice(hubDevice(Id.bedroomHub3)) else: if haveDevice(Id.bedroomHub2): resetDevice(hubDevice(Id.bedroomHub2)) else: if haveDevice(Id.bedroomHub1): resetDevice(hubDevice(Id.bedroomHub1)) else: if haveDevice(Id.bedroomHub0): resetDevice(hubDevice(Id.bedroomHub0)) else: raise ValueError( "don't even have the first hub") resetModules(['gspca_zc3xx']) supervisorRestart(['webcam_9053']) else: log.debug("usb devices look ok") elif hostname == 'slash': haveFrontHub0 = haveDevice(Id.frontDoorHub0) haveFrontHub1 = haveDevice(Id.frontDoorHub1) haveFrontHub2 = haveDevice(Id.frontDoorHub2) haveFrontHub3 = haveDevice(Id.frontDoorHub3) haveGarageHub0 = haveDevice(Id.garageHub0) haveGarageHub1 = haveDevice(Id.garageHub1) haveFrontDoorCam = haveDevice(Id.frontDoorCam) haveV4lDevice = os.path.exists( "/dev/v4l/by-id/usb-Vimicro_Corp._PC_Camera-video-index0") haveFrontArduinoServe = (yield getOk('http://slash:9080/')) haveFrontWebcamImage = (yield getOk( "http://slash:9023/frontDoor", timeout=10)) log.info(str(vars())) if not haveDevice(Id.ftdi): if haveFrontHub3: resetDevice(Id.frontDoorHub3) else: if haveFrontHub2: resetDevice(Id.frontDoorHub2) else: if haveFrontHub1: resetDevice(Id.frontDoorHub1) else: if haveFrontHub0: resetDevice(Id.frontDoorHub0) else: raise ValueError("don't have the first hub") else: log.debug("front door chain looks ok") if not haveDevice(Id.garagePowerSerial): if haveGarageHub1: resetDevice(Id.garageHub1) else: if haveGarageHub0: resetDevice(Id.garageHub0) else: raise ValueError("don't have the first hub") else: log.debug("garage chain looks ok") if not haveDevice(Id.garageArduino): if haveGarageHub1: resetDevice(hubDevice(Id.garageHub1)) else: raise ValueError("don't even have the first hub") resetModules(['gspca_zc3xx']) supervisorRestart(['frontDoorArduino_9080']) else: if not haveFrontArduinoServe: resetDevice(hubDevice(Id.frontDoorHub3)) supervisorRestart(['frontDoorArduino_9080']) time.sleep(10) else: log.debug("frontDoorArduino looks ok") if not haveFrontWebcamImage: supervisorRestart(['webcam_frontDoor_9023']) else: log.debug("front webcam looks ok") elif hostname == 'dash': if not os.path.exists("/dev/serial/by-id/usb-FTDI_FT232R_USB_UART_A900gbcG-if00-port0"): resetDevice("/dev/bus/usb/003/001") else: raise NotImplementedError log.debug(" -- finished") self.lastPollTime = now except Exception, e: print "poll error", e traceback.print_exc() class Index(PrettyErrorHandler, cyclone.web.RequestHandler): def get(self): self.settings.background.assertIsCurrent() self.set_header("Content-Type", "application/xhtml+xml") self.write("usbreset is ok")#open("index.html").read()) if __name__ == '__main__': config = { # to be read from a file 'servePort' : 9100, 'checkPeriod' : 30, } from twisted.python import log as twlog #twlog.startLogging(sys.stdout) log.setLevel(logging.INFO) p = Background(config, config['checkPeriod']) task.LoopingCall(p.step).start(config['checkPeriod']) reactor.listenTCP(config['servePort'], cyclone.web.Application([ (r"/", Index), ], background=p)) reactor.run()