class SerialConnection(Connection): # Serial Constants BYTESIZE = { 5: serial.FIVEBITS, 6: serial.SIXBITS, 7: serial.SEVENBITS, 8: serial.EIGHTBITS } PARITY = { 'N': serial.PARITY_NONE, 'E': serial.PARITY_EVEN, 'O': serial.PARITY_ODD } STOPBITS = {1: serial.STOPBITS_ONE, 2: serial.STOPBITS_TWO} def __init__(self): Connection.__init__(self) # New data available notifier self.notifier = None def begin(self, instrument): self.log = logging.getLogger('GDAIS.' + instrument.short_name + '.SerialConnection') self.io_conn = serial.Serial() self.io_conn.port = instrument.connection.serial_port self.io_conn.baudrate = instrument.connection.baudrate self.io_conn.bytesize = self.BYTESIZE[instrument.connection.data_bits] self.io_conn.parity = self.PARITY[instrument.connection.parity] self.io_conn.stopbits = self.STOPBITS[instrument.connection.stop_bits] self.io_conn.timeout = 0 # non-blocking mode (return immediately on read) try: self.io_conn.open() except serial.SerialException: self.log.exception("Serial device can not be found or configured") self.error_occurred.emit() else: Connection.begin(self, instrument) def run(self): self.notifier = QSocketNotifier(self.io_conn.fileno(), QSocketNotifier.Read) self.notifier.activated.connect(self.read_data) Connection.run(self) def quit(self): if self.notifier and self.notifier.isEnabled(): self.notifier.setEnabled(False) if self.io_conn and self.io_conn.isOpen(): self.log.debug("Clearing serial port buffers (In and Out)") self.io_conn.flushOutput() self.io_conn.flushInput() self.log.info("Closing serial port") self.io_conn.close() Connection.quit(self)
def _addNotifier(self, descriptor, descmap, type): if descriptor not in descmap: fd = descriptor.fileno() if fd == -1: raise RuntimeError("Invalid file descriptor") notifier = QSocketNotifier(fd, type) descmap[descriptor] = notifier notifier._descriptor = descriptor self.connect(notifier, SIGNAL("activated(int)"), self._notifierSlot) notifier.setEnabled(True)
class Signal(QObject): signal = pyqtSignal(int) fds = {} def __init__(self, signum, parent): super(Signal,self).__init__(parent) self.signum = signum self.sn = None self.fd = [None,None] if self.setupHandler() < 0: return self.sn = QSocketNotifier(self.fd[1].fileno(), QSocketNotifier.Read, parent) self.sn.activated.connect( self.handleSignal) def __del__(self): signal.signal( self.signum, signal.SIG_DFL) if Signal.fds.has_key( self.signum): Signal.fds.pop(self.signum) if self.fd[0] is not None: self.fd[0].close() if self.fd[1] is not None: self.fd[1].close() super(Signal,self).__del__() @staticmethod def create(signum,parent): if Signal.fds.has_key(signum): if Signal.fds[signum].sn: sip.delete(Signal.fds[signum].sn) del(Signal.fds[signum]) return Signal(signum,parent) def handleSignal(self): self.sn.setEnabled(False) self.fd[1].recv(1) self.signal.emit(self.signum) self.sn.setEnabled(True) def setupHandler(self): self.fd = socket.socketpair(socket.AF_UNIX,socket.SOCK_STREAM,0) if not self.fd: return -1 Signal.fds[self.signum] = self signal.signal(self.signum,self.handler) signal.siginterrupt(self.signum,False) return 0 @staticmethod def handler(signum,frame): Signal.fds[signum].fd[0].send(chr(1))
class QtListener: def __init__(self, evtype, fileno, cb): self.evtype, self.fileno, self.cb = evtype, fileno, cb self.notifier = QSocketNotifier(fileno, self.eventType(evtype)) self.notifier.activated.connect(cb) def __del__(self): self.notifier.setEnabled(False) self.notifier = None def eventType(self, evtype): assert evtype in (BaseHub.READ, BaseHub.WRITE) if evtype == BaseHub.READ: return QSocketNotifier.Read elif evtype == BaseHub.WRITE: return QSocketNotifier.Write
def register_io(self, fd, callback, mode, *args, **kwargs): handler = six.next(self._handlers) notifier = QSocketNotifier(self.fd_number(fd), self.constants[mode]) with self._mutex: self._io_handlers[handler] = notifier def _io_cb(*_): if not self._safe_callback(callback, fd, *args, **kwargs): self.unregister_io(handler) with self._mutex: # we need to store the closure callback to avoid the garbage collector # from collecting the closure self._io_handlers[handler] = (notifier, _io_cb) notifier.setEnabled(True) notifier.activated.connect(_io_cb)
class QtListener: def __init__(self, evtype, fileno, cb, tb=None, mark_as_closed=False): self.evtype, self.fileno, self.cb = evtype, fileno, cb self.tb, self.mark_as_closed = tb, mark_as_closed self.notifier = QSocketNotifier(fileno, self.eventType(evtype)) self.notifier.activated.connect(cb) self.spent = False def __del__(self): self.notifier.setEnabled(False) self.notifier = None def eventType(self, evtype): assert evtype in (BaseHub.READ, BaseHub.WRITE) if evtype == BaseHub.READ: return QSocketNotifier.Read elif evtype == BaseHub.WRITE: return QSocketNotifier.Write def defang(self): self.notifier.activated.disconnected(self.cb) if self.mark_as_closed is not None: self.mark_as_closed() self.spent = True
class FdEvent(Event): def __init__(self, *args, **kw): self.note = QSocketNotifier(*args, **kw) self.note.setEnabled(False) Event.__init__(self, self.note.activated) def arm(self, *args): Event.arm(self, *args) self.note.setEnabled(True) def close(self, *args): self.note.setEnabled(False) Event.close(self, *args)
class TwistedSocketNotifier(QObject): """ Connection between an fd event and reader/writer callbacks. """ def __init__(self, parent, reactor, watcher, socketType): QObject.__init__(self, parent) self.reactor = reactor self.watcher = watcher fd = watcher.fileno() self.notifier = QSocketNotifier(fd, socketType, parent) self.notifier.setEnabled(True) if socketType == QSocketNotifier.Read: self.fn = self.read else: self.fn = self.write QObject.connect(self.notifier, SIGNAL("activated(int)"), self.fn) def shutdown(self): self.notifier.setEnabled(False) self.disconnect(self.notifier, SIGNAL("activated(int)"), self.fn) self.fn = self.watcher = None self.notifier.deleteLater() self.deleteLater() def read(self, fd): if not self.watcher: return w = self.watcher # doRead can cause self.shutdown to be called so keep a # reference to self.watcher def _read(): # Don't call me again, until the data has been read self.notifier.setEnabled(False) why = None try: why = w.doRead() inRead = True except: inRead = False log.err() why = sys.exc_info()[1] if why: self.reactor._disconnectSelectable(w, why, inRead) elif self.watcher: # Re enable notification following sucessfull read self.notifier.setEnabled(True) self.reactor._iterate(fromqt=True) log.callWithLogger(w, _read) def write(self, sock): if not self.watcher: return w = self.watcher def _write(): why = None self.notifier.setEnabled(False) try: why = w.doWrite() except: log.err() why = sys.exc_info()[1] if why: self.reactor._disconnectSelectable(w, why, False) elif self.watcher: self.notifier.setEnabled(True) self.reactor._iterate(fromqt=True) log.callWithLogger(w, _write)
class VNCClient(QObject): started = pyqtSignal() finished = pyqtSignal() imageSizeChanged = pyqtSignal(QSize) imageChanged = pyqtSignal(int, int, int, int) passwordRequested = pyqtSignal(bool) textCut = pyqtSignal(unicode) def __init__(self, host, port, settings, parent=None): super(VNCClient, self).__init__(parent) self.thread = QThread() self.moveToThread(self.thread) self.host = host self.port = port self.settings = settings self.username = None self.password = None self.rfb_client = None self.socket_notifier = None self.thread.started.connect(self._SH_ThreadStarted) self.thread.finished.connect(self._SH_ThreadFinished) def _get_settings(self): return self.__dict__['settings'] def _set_settings(self, settings): old_settings = self.__dict__.get('settings', None) if settings == old_settings: return self.__dict__['settings'] = settings if self.thread.isRunning(): QApplication.postEvent(self, RFBConfigureClientEvent()) settings = property(_get_settings, _set_settings) del _get_settings, _set_settings @property def image(self): return self.rfb_client.image if self.rfb_client is not None else None def start(self): self.thread.start() def stop(self): self.thread.quit() def key_event(self, key, down): if self.thread.isRunning(): QApplication.postEvent(self, RFBKeyEvent(key, down)) def mouse_event(self, x, y, button_mask): if self.thread.isRunning(): QApplication.postEvent(self, RFBMouseEvent(x, y, button_mask)) def cut_text_event(self, text): if text and self.thread.isRunning(): QApplication.postEvent(self, RFBCutTextEvent(text)) def _SH_ThreadStarted(self): self.started.emit() notification_center = NotificationCenter() notification_center.post_notification('VNCClientWillStart', sender=self) self.rfb_client = RFBClient(parent=self) try: self.rfb_client.connect() except RFBClientError: self.thread.quit() else: self.socket_notifier = QSocketNotifier(self.rfb_client.socket, QSocketNotifier.Read, self) self.socket_notifier.activated.connect(self._SH_SocketNotifierActivated) notification_center.post_notification('VNCClientDidStart', sender=self) def _SH_ThreadFinished(self): self.finished.emit() notification_center = NotificationCenter() notification_center.post_notification('VNCClientWillEnd', sender=self) if self.socket_notifier is not None: self.socket_notifier.activated.disconnect(self._SH_SocketNotifierActivated) self.socket_notifier = None self.rfb_client = None notification_center.post_notification('VNCClientDidEnd', sender=self) def _SH_SocketNotifierActivated(self, sock): self.socket_notifier.setEnabled(False) try: self.rfb_client.handle_server_message() except RFBClientError: self.thread.quit() else: self.socket_notifier.setEnabled(True) def _SH_ConfigureRFBClient(self): if self.rfb_client is not None: self.rfb_client.configure() def customEvent(self, event): handler = getattr(self, '_EH_%s' % event.name, Null) handler(event) def _EH_RFBConfigureClientEvent(self, event): if self.rfb_client is not None: self.rfb_client.configure() def _EH_RFBKeyEvent(self, event): if self.rfb_client is not None: self.rfb_client.send_key_event(event.key, event.down) def _EH_RFBMouseEvent(self, event): if self.rfb_client is not None: self.rfb_client.send_pointer_event(event.x, event.y, event.button_mask) def _EH_RFBCutTextEvent(self, event): if self.rfb_client is not None: self.rfb_client.send_client_cut_text(event.text)
class RFIDReaderThread(QThread): signalStatusChange = pyqtSignal(Status) signalAccess = pyqtSignal('QString', dict) def __init__(self, parent=None): QThread.__init__(self, parent) self.status = Status.INIT self.hw = DoorHW(red_pin=qsetup.RED_PIN, green_pin=qsetup.GREEN_PIN, door_pin=qsetup.DOOR_PIN, beep_pin=qsetup.BEEP_PIN) self.reader = rfid_reader.factory(qsetup.READER_TYPE) self.reader.initialize(baud_rate=qsetup.READER_BAUD_RATE) self.authenticate = Authenticate.factory(qsetup.AUTHENTICATE_TYPE, qsetup.AUTHENTICATE_FILE) botlog.info('authentication file date %s' % self.authenticate.get_file_time()) botlog.info('RFIDReaderThread Initialized.') def __del__(self): botlog.info('RFIDReaderThread Thread Deletion.') self.wait() def updateLEDs(self): if self.status == Status.INIT: self.hw.green(on=True) self.hw.red(on=True) elif self.status == Status.READY: self.hw.green(on=self.blinkPhase) self.hw.red(on=False) elif self.status == Status.DENIED or self.status == Status.UNKNOWN: self.hw.green(on=False) self.hw.red(on=True) elif self.status == Status.ALLOWED or self.status == Status.LATCHED: self.hw.green(on=True) self.hw.red(on=False) elif self.status == Status.ERROR: self.hw.green(on=False) self.hw.red(on=self.blinkPhase) def blink(self): self.updateLEDs() self.blinkPhase = not self.blinkPhase def setStatus(self, s): botlog.debug('status change from %s to %s' % (self.status, s)) self.status = s self.signalStatusChange.emit(s) self.updateLEDs() def unlatch(self): self.hw.latch(open=False) self.setStatus(Status.READY) self.reader.flush() self.notifier.setEnabled(True) def undelay(self): self.setStatus(Status.READY) self.reader.flush() self.notifier.setEnabled(True) def onData(self): rfid_str = self.reader.get_card() if not rfid_str: return botlog.debug( 'RFID string >>%s<<' % rfid_str) # Several things can happen: # 1. some error in reading. # 2. good card, not allowed # 3. good card, allowed: # 3a. schedule permits access at this time, so open door # 3b. schedule does not permit access at this time. # 4. bad card from some reason # 5. unknown card try : self.setStatus(Status.READING) rfid = int(rfid_str) access = self.authenticate.get_access(rfid) if access: allowed = access['allowed'] member = access['member'] plan = access['plan'] print(allowed) print(access) print(plan) if 'allowed' in allowed : if qsetup.schedule.isAllowed(plan): # 3a. open the door # botlog.info('%s allowed' % member) self.setStatus(Status.ALLOWED) self.setStatus(Status.LATCHED) self.hw.latch(open=True) self.notifier.setEnabled(False) self.latchTimer.start(4000) else: # 3b. denied due to local schedule botlog.warning('%s DENIED due to schedule restriction' % member) allowed = 'denied' if member['warning'] is None or member['warning'] == '': member['warning'] = qsetup.schedule.scheduleDesc() else: member['warning'] += '\n%s' % qsetup.schedule.scheduleDesc() self.setStatus(Status.DENIED) self.notifier.setEnabled(False) self.delayTimer.start(3000) else : #2 # access failed. blink the red # botlog.warning('%s DENIED' % member) self.setStatus(Status.DENIED) self.notifier.setEnabled(False) self.delayTimer.start(3000) else : #5 botlog.warning('Unknown card %s ' % rfid_str) self.setStatus(Status.UNKNOWN) self.signalAccess.emit('denied', {'member':'Unknown.RFID.Tag', 'plan':None, 'tagid':'', 'allowed':'denied', 'nickname':None, 'warning':'This RFID tag is not recognized. Be sure you are using the correct tag and hold it steady over the read antenna.\n\nContact [email protected] if you continue to have problems.'}) self.notifier.setEnabled(False) self.delayTimer.start(3000) self.signalAccess.emit(allowed, access) except : #4 # bad input catcher, also includes bad cards # botlog.warning('bad card %s ' % rfid_str) # other exception? e = traceback.format_exc().splitlines()[-1] botlog.error('door loop unexpected exception: %s' % e) self.setStatus(Status.ERROR) self.notifier.setEnabled(False) self.delayTimer.start(3000) def run(self): botlog.info('RFIDReaderThread Running.') self.blinkPhase = False self.blinkTimer = QTimer() self.blinkTimer.timeout.connect(self.blink) self.latchTimer = QTimer() self.latchTimer.timeout.connect(self.unlatch) self.latchTimer.setSingleShot(True) self.delayTimer = QTimer() self.delayTimer.timeout.connect(self.undelay) self.delayTimer.setSingleShot(True) self.notifier = QSocketNotifier(self.reader.fileno(), QSocketNotifier.Read) self.notifier.activated.connect(self.onData) self.blinkTimer.start(250) self.notifier.setEnabled(True) self.setStatus(Status.READY) self.exec() botlog.info('RFIDReaderThread Stopped.')
class QJsonRpcClient(QObject): """A JSON-RPC client integrated with the Qt event loop.""" default_timeout = 5 def __init__(self, message_handler=None, timeout=-1, parent=None): """Create a new message bus connection. The *handler* specifies an optional message handler. """ super(QJsonRpcClient, self).__init__(parent) self._message_handler = message_handler self._timeout = timeout if timeout != -1 else self.default_timeout self._socket = None self._method_calls = {} self._outbuf = b"" self._incoming = collections.deque() self._outgoing = collections.deque() self._protocol = jsonrpc.JsonRpcProtocol(True) self._read_notifier = None self._write_notifier = None self._log = logging.get_logger(self) @property def timeout(self): return self._timeout def connect(self, address): """Connect to a JSON-RPC server at *address*.""" if isinstance(address, socket.socket): sock = address else: sock = util.create_connection(address, self._timeout) sock.settimeout(0) self._read_notifier = QSocketNotifier(sock.fileno(), QSocketNotifier.Read, self) self._read_notifier.activated.connect(self._do_read) self._read_notifier.setEnabled(True) self._write_notifier = QSocketNotifier(sock.fileno(), QSocketNotifier.Write, self) self._write_notifier.activated.connect(self._do_write) self._write_notifier.setEnabled(False) self._socket = sock def _do_read(self): # Read messages from the socket and put them into the incoming queue # until nothing more can be read. while True: try: buf = self._socket.recv(4096) except socket.error as e: if e.errno in (errno.EAGAIN, errno.EWOULDBLOCK): break self._log.error("recv() error {0}".format(e.errno)) self.close() break if buf == b"": self._log.error("peer closed connection") self.close() break # XXX: should not be using protocol private attributes # Expose .error and .get_message() ? nbytes = self._protocol.data_received(buf) if self._protocol._error: self._log.error("parse error {0!s}", self._protocol._error) self.close() break while self._protocol._queue.qsize(): message = self._protocol._queue.get(block=False) self._incoming.append(message) # Schedule a dispatch if there are incoming messages if self._incoming: QCoreApplication.instance().postEvent(self, _Dispatch()) def _do_write(self): # Drain message from the outgoing queue until we would block or until # the queue is empty. while True: if not self._outbuf: if not self._outgoing: break message = self._outgoing.popleft() self._outbuf = json.dumps(message).encode("utf8") try: nbytes = self._socket.send(self._outbuf) except socket.error as e: if e.errno in (errno.EAGAIN, errno.EWOULDBLOCK): break self.logger.error("send() error {0}".format(e.errno)) self.close() break self._outbuf = self._outbuf[nbytes:] if not self._outbuf: self._write_notifier.setEnabled(False) def close(self): """Close the connection.""" if self._socket is None: return self._read_notifier.setEnabled(False) self._write_notifier.setEnabled(False) try: self._socket.close() except socket.error: pass self._log.debug("connection closed") self._socket = None def send_message(self, message): """Send a raw JSON-RPC message.""" if self._socket is None: raise RuntimeError("not connected") if not jsonrpc.check_message(message): raise ValueError("invalid JSON-RPC message") self._outgoing.append(message) if not self._write_notifier.isEnabled(): self._write_notifier.setEnabled(True) def send_notification(self, method, *args): """Send a JSON-RPC notification.""" message = jsonrpc.create_notification(method, args) self.send_message(message) def event(self, event): # Process the DispatchMessages event if isinstance(event, _Dispatch): self._dispatch() event.accept() return True else: event.ignore() return False def _dispatch(self): # Dispatch message from the connection. while self._incoming: message = self._incoming.popleft() if "result" in message or "error" in message: # response key = message["id"] callback = self._method_calls.get(key, None) if callback: callback(message, self) elif self._message_handler: self._message_handler(message, self) else: self._log.info("no handler, cannot handle incoming message") def call_method(self, method, *args, **kwargs): """Call a method.""" # XXX: limiting the recusion depth needs more thought if len(self._method_calls) > 5: raise RuntimeError("recursion level too deep") message = jsonrpc.create_request(method, args) self.send_message(message) replies = [] def method_response(message, client): replies.append(message) def method_timeout(): reply = jsonrpc.create_error(message, jsonrpc.SERVER_ERROR, "Method call timed out") replies.append(reply) timeout = kwargs.pop("timeout", self.timeout) if timeout: timer = QTimer(self) timer.setInterval(timeout * 1000) timer.setSingleShot(True) timer.timeout.connect(method_timeout) timer.start() # Run an embedded event loop to process network events until we get a # response. We limit the call depth so that we don't run the risk of # overflowing the stack. self._method_calls[message["id"]] = method_response loop = QEventLoop() mask = QEventLoop.ExcludeUserInputEvents | QEventLoop.WaitForMoreEvents while True: loop.processEvents(mask) if replies: break if timeout: timer.stop() reply = replies[0] del self._method_calls[message["id"]] if reply.get("error"): raise QJsonRpcError(reply["error"]) self.message = reply return reply.get("result")
def create_watch(self, socket, type, callback): socket.setblocking(0) notifier = QSocketNotifier(socket.fileno(), type, self) notifier.activated.connect(callback) notifier.setEnabled(True) return notifier
class _EventDispatcherQTFD: """Internal fdw wrapper used by EventDispatcherQT""" def __init__(self, fdw): self.fdw = fdw self.qsn_read = QSocketNotifier(int(self.fdw), QSocketNotifier.Read) self.qsn_write = QSocketNotifier(int(self.fdw), QSocketNotifier.Read) self.qsn_oob = QSocketNotifier(int(self.fdw), QSocketNotifier.Exception) self.qsn_read.setEnabled(False) self.qsn_write.setEnabled(False) self.qsn_oob.setEnabled(False) connect(self.qsn_read, SIGNAL("activated(int)"), self.fd_read) connect(self.qsn_write, SIGNAL("activated(int)"), self.fd_write) def process_readability(self, fd): self.fdw.process_readability() def process_writability(self, fd): self.fdw.process_writability() def read_r(self): self.qsn_read.setEnabled(True) def write_r(self): self.qsn_write.setEnabled(True) def read_u(self): self.qsn_read.setEnabled(False) def write_u(self): self.qsn_write.setEnabled(False) def _unregister_all(self): for qsn in (self.qsn_read, self.qsn_write, self.qsn_oob): if qsn.isEnabled(): qsn.setEnabled(False) def close(self): self._unregister_all() disconnect(self.qsn_read, SIGNAL("activated(int)"), self.fd_read) disconnect(self.qsn_write, SIGNAL("activated(int)"), self.fd_write) disconnect(self.qsn_oob, SIGNAL("activated(int)"), self.fd_oob) self.qsn_read.deleteLater() self.qsn_write.deleteLater() self.qsn_oob.deleteLater() self.qsn_read = None self.qsn_write = None self.qsn_oob = None
class ComarIface(QObject): def __init__(self): self.com = comar.Link() # Notification self.com.ask_notify("System.Upgrader.progress") self.com.ask_notify("System.Upgrader.error") self.com.ask_notify("System.Upgrader.warning") self.com.ask_notify("System.Upgrader.notify") self.com.ask_notify("System.Upgrader.started") self.com.ask_notify("System.Upgrader.finished") self.com.ask_notify("System.Upgrader.cancelled") self.notifier = QSocketNotifier(self.com.sock.fileno(), QSocketNotifier.Read) self.connect(self.notifier, SIGNAL("activated(int)"), self.slotComar) def slotComar(self, sock): try: reply = self.comar.com.read_cmd() except: if not self.wait_comar(): logger.error("Can not connect to comar daemon") return if reply.command == "notify": (notification, script, data) = (reply.notify, reply.script, reply.data) data = unicode(data) if notification == "System.Upgrader.error": pass elif notification == "System.Upgrader.notify": pass elif notification == "System.Upgrader.progress": pass elif notification == "System.Upgrader.started": self.emit(SIGNAL("stepStarted(QString)", data)) elif notification == "System.Upgrader.finished": self.emit(SIGNAL("stepFinished(QString)", data)) else: print "Got notification : %s , for script : %s , with data : %s" % (notification, script, data) def wait_comar(self): self.notifier.setEnabled(False) import socket, time sock = socket.socket(socket.AF_UNIX, socket.SOCK_STREAM) timeout = 5 while timeout > 0: try: if pisi.api.ctx.comar_sockname: sock.connect(pisi.api.ctx.comar_sockname) return True else: self.comar.notifier.setEnabled(True) sock.connect("/var/run/comar.socket") return True except socket.error: timeout -= 0.2 time.sleep(0.2) return False def prepare(self): self.com.call("System.Upgrader.prepare") def setRepositories(self): self.com.call("System.Upgrader.setRepositories") def download(self): self.com.call("System.Upgrader.download") def upgrade(self): self.com.call("System.Upgrader.upgrade") def cleanup(self): self.com.call("System.Upgrader.cleanup") def cancel(self): self.com.cancel()