def onStart(self): if not self.hosts: log.warn('No hosts to ping') return started = False while not self._shutdown: for name in self.hosts: host = self.hosts[name] if self.ping(host): if self.isDown(host) or not started: self.sendEvent(name, { 'value': 'up', 'address': host }) try: del self.down[host] except: pass else: if not self.isDown(host): self.sendEvent(name, { 'value': 'down', 'address': host }) self.down[host] = True started = True time.sleep(self.interval)
def setOnline(self, type, key, force=False): if not type or not key: log.warn('Ignore attempt to set type=%s id=%s as online' % (type,key)) return # Init dict path if not set if not self.data[type].has_key(key): self.data[type][key] = {'online': None} #if type == 'manager': # self.data[type][key]['services'] = None # If not already online (or force [re-]online) # Set online and send online-event if self.data[type][key]['online'] != True or force: log.info('%s %s changed status to online' % (type, key)) self.data[type][key]['online'] = True eventTopic = '%s%s.%s.online' % ( self.typeToPrefix(type), amqp.PREFIX_EVENT, key ) event = {'data': {'value': True}, 'key': 'online'} if type == 'service': event['service'] = key else: event['host'] = key self.producer.put(eventTopic, event) # Update last heartbeat time self.data[type][key]['heartbeat'] = time.time()
def poll(self): data = {} keys = [ 'firmware_version', 'power_loss', 'battery_voltage', 'rpi_voltage', 'sot23_temperature', 'to92_temperature', 'shutdown_time', 'battery_temperature_on_error', 'ad1', 'ad2' ] for key in keys: func = 'get_%s' % key try: func = getattr(self, func) value = func() except Exception, e: log.warn("Ignoring error on get %s: %s" % (key, utils.e2str(e))) continue data[key] = value
def setOffline(self, type, key): if not type or not key: log.warn('Ignore attempt to set type=%s id=%s as offline' % (type,key)) return # Init dict path if not set if not self.data[type].has_key(key): self.data[type][key] = {'online': None} # If not already offline, set offline and send offline event if self.data[type][key]['online'] != False: log.info('%s %s changed status to offline' % (type, key)) self.data[type][key]['online'] = False self.data[type][key]['offlineTimer'] = time.time() eventTopic = '%s%s.%s.online' % ( self.typeToPrefix(type), amqp.PREFIX_EVENT, key ) event = {'data': {'value': False}, 'key': 'online'} if type == 'service': event['service'] = key else: event['host'] = key self.producer.put(eventTopic, event)
def on_pubmsg(self, c, e): try: nick = NickMask(e.source()).nick a = e.arguments()[0].split(":", 1) #print "pub_msg: %s" % a #print "pub_msg first char: '%s'" % a[0][0] # parse first word as a command if pre'ed by <botname:> if len(a) > 1 and irc_lower(a[0]) == irc_lower(self.connection.get_nickname()): #self.command_switch(e, a[1].strip()) a2 = e.arguments()[0].split(" ") if len(a2[0][1:]) > 0: self.command_switch(nick,e,a2[1],a2[2:]) # parse first word as a command if pre'ed by "!" elif e.arguments()[0][0] == '!': a2 = e.arguments()[0].split(" ") if len(a2[0][1:]) > 0: self.command_switch(nick,e,a2[0][1:],a2[1:]) # else: send as generic pubmessage event else: a2 = e.arguments()[0] data = {'key':'pubmessage', 'value':a2, 'extra': {'nick':nick}} self.botEvent(data) return except Exception, e: self.say_public('Exception in on_pubmsg: %s' % e) log.warn('Exception in on_privmsg: %s' % utils.e2str(e))
def onInit(self): self.from_addr = self.config.get('from_addr') self.to_addr = self.config.get('to_addr') if not self.to_addr: self.to_addr = self.from_addr self.username = self.config.get('username') self.password = self.config.get('password') self.polldelay = self.config.get('polldelay') if not self.polldelay: self.polldelay = 600 self.mailserver = self.config.get('mailserver') if not self.mailserver: self.mailserver = '127.0.0.1' self.smtpserver = self.config.get('smtpserver') self.deletemail = self.config.get('deletemail') if not self.deletemail or not self.deletemail.lower() == 'yes' or not self.deletemail.lower() == 'true': self.deletemail = False self.maxheaders = self.config.get('maxheader') if not self.maxheaders: self.maxheaders = 10 self.maxsize = self.config.get('maxsize') if not self.maxsize: self.maxsize = 12000 if not self.smtpserver: self.smtpserver = '127.0.0.1' if not self.from_addr: log.warn('Service needs senders email address to work.') sys.exit(1)
def onInit(self): self.button_events = [ array('B', [1, 0, 0, 0, 0, 0, 0]), 'button_release', array('B', [1, 1, 0, 0, 0, 0, 0]), 'button_left', array('B', [1, 2, 0, 0, 0, 0, 0]), 'button_right', array('B', [1, 4, 0, 0, 0, 0, 0]), 'button_middle', array('B', [1, 8, 0, 0, 0, 0, 0]), 'button_3', array('B', [1, 16, 0, 0, 0, 0, 0]), 'button_4', array('B', [1, 32, 0, 0, 0, 0, 0]), 'button_5', array('B', [1, 64, 0, 0, 0, 0, 0]), 'button_6', array('B', [1, 128, 0, 0, 0, 0, 0]), 'button_7', array('B', [1, 255, 0, 0, 0, 0, 0]), 'button_8', array('B', [1, 0, 0, 0, 0, 0, 1]), 'wheel_up', array('B', [1, 0, 0, 0, 0, 0, 255]), 'wheel_down', # mouse button combinations # TODO: do this by using bitwise operator to generate all combinations array('B', [1, 3, 0, 0, 0, 0, 0]), 'button_left_right', array('B', [1, 5, 0, 0, 0, 0, 0]), 'button_left_middle', array('B', [1, 6, 0, 0, 0, 0, 0]), 'button_right_middle', array('B', [1, 7, 0, 0, 0, 0, 0]), 'button_left_right_middle', ] # "slow" mouse movements self.move_events = [ array('B', [1, 0, 0, 0, 1, 0, 0]), 'down', array('B', [1, 0, 255, 255, 1, 0, 0]), 'down-left', array('B', [1, 0, 1, 0, 1, 0, 0]), 'down-right', array('B', [1, 0, 0, 0, 255, 255, 0]), 'up', array('B', [1, 0, 255, 255, 255, 255, 0]), 'up-left', array('B', [1, 0, 1, 0, 255, 255, 0]), 'up-right', array('B', [1, 0, 255, 255, 0, 0, 0]), 'left', array('B', [1, 0, 1, 0, 0, 0, 0]), 'right', ] # ## Service config self.interval = int(self.config.get('interval')) or 600 # milliseconds self.vendorid = int(self.config.get('vendorid')) self.productid = int(self.config.get('productid')) self.search_params = {} if self.vendorid and self.productid: self.search_params.update({'idVendor': self.vendorid, 'idProduct': self.productid}) mousedevs = cusb.find_mouse(self.search_params) else: log.warn("No config, using first found mouse service") mousedevs = cusb.find_mouse() if not mousedevs: log.error("Can't find mouse service") sys.exit("Can't find mouse service") # Use first matching mouse mouse = mousedevs[0] # ## vendor and product ids self.dev = usb.core.find(address=mouse['address'], bus=mouse['bus']) self.interface = mouse['interface'] # use the first endpoint # dev[configuration][(interface, alt_config)][endpoint] self.endpoint = self.dev[mouse['configuration']][(mouse['interface'], 0)][0]
def onMessage(self, topic, data, correlationId): topic = topic.split('.') # Heartbeats if topic[0][1] == amqp.PREFIX_HEARTBEAT_RESPONSE: if data == amqp.HEARTBEAT_VALUE_OFFLINE: self.setOffline(self.prefixToType(topic[0][0]), topic[1]) elif data == amqp.HEARTBEAT_VALUE_ONLINE: self.setOnline(self.prefixToType(topic[0][0]), topic[1], force=True) elif data == amqp.HEARTBEAT_VALUE_RESPONSE: self.setOnline(self.prefixToType(topic[0][0]), topic[1]) else: log.warn('Unknown heartbeat event: %s' % (topic,))
def getBluetoothServices(self): log.debug('Getting bluetooth services') result = [] if self.config.getBool('discover'): log.debug('Using services_discover() to find services') try: for addr in bluetooth.discover_services(flush_cache=True): log.debug('Found service: %s' % addr) result.append(addr) # This happens from time to time, and we don't want to die because of it: # BluetoothError: error communicating with local bluetooth adapter except bluetooth.btcommon.BluetoothError, e: log.warn('BluetoothError ignored: %s' % e)
def getBluetoothServices(self): log.debug('Getting bluetooth services') result = [] if self.config.getBool('discover'): log.debug('Using services_discover() to find services') try: for addr in bluetooth.discover_services(flush_cache=True): log.debug('Found service: %s' % addr) result.append(addr) # This happens from time to time, and we don't want to die because of it: # BluetoothError: error communicating with local bluetooth adapter except bluetooth.btcommon.BluetoothError,e: log.warn('BluetoothError ignored: %s' % e)
def action_power_toggle(self, cecdev=None): ''' Toggle CEC service power @param adapter int CEC service ID ''' if not cecdev: cecdev = self.cur_service dev = cec.Service(cecdev) if dev.is_on: dev.power_off() elif not dev.is_on: dev.power_on() else: log.warn('powertoggle failed because power status could not be determined')
def on_privmsg(self, c, e): nick = NickMask(e.source()).nick try: if e.arguments()[0][0] == '!': a2 = e.arguments()[0].split(" ") if len(a2[0][1:]) > 0: self.command_switch(nick,e,a2[0][1:],a2[1:]) else: a2 = e.arguments()[0].split(" ") data = {'key':'privmsg', 'value':e.arguments()[0], 'extra': {'nick':nick, 'type':e.eventtype(),'source':e.source(), 'target':e.target()}} #data = {'key':'privmessage', 'value':e.arguments()[0], 'extra': {'nick':nick}} self.botEvent(data) except Exception, e: self.say_private(nick, 'Exception: %s' % e) log.warn('Exception in on_privmsg: %s' % utils.e2str(e))
def shutdown(self): AmqpDaemon.shutdown(self) #log.info('Shutdown called') #self._shutdown = True # Send an action message to ourself to make sure # we break out of the wait-loop for actions asap. #log.info('Send _shutdown action') #self.sendShutdownAction() #log.info('Wait 0.5') time.sleep(0.5) log.info('Joining actionThread') if self.actionThread: try: self.actionThread.join() except RuntimeError, e: log.warn('Ignoring exception about joining actionThread: %s' % e)
def action_power_toggle(self, cecdev=None): ''' Toggle CEC service power @param adapter int CEC service ID ''' if not cecdev: cecdev = self.cur_service dev = cec.Service(cecdev) if dev.is_on: dev.power_off() elif not dev.is_on: dev.power_on() else: log.warn( 'powertoggle failed because power status could not be determined' )
def close(self): items = [] if self.channels: for item in self.channels: items.append(('channel', item)) if self.conn: items.append(('connection', self.conn)) if self.conn.transport and self.conn.transport.sock: items.append(('socket', self.conn.transport.sock)) for type, obj in items: # log.info('Try close %s: %s' % (type,obj)) try: obj.close() except Exception as e: log.warn('Ignoring fail on close %s: %s' % (type, repr(e))) self.channels = [] self.conn = None
def onInit(self): # Required parameters for pushover self.token = self.config.get('token') self.username = self.config.get('username') if not self.token or self.username: log.warn('Service needs token and username to work.') sys.exit(1) # Optional parameters for pushover # TODO: optionally set default values for these in config self.pushurl = 'https://api.pushover.net/1/messages.json' self.message = self.config.get('message') or "Chains calling!" self.targetdevice = self.config.get('targetdevice') self.title = self.config.get('title') self.url = self.config.get('url') self.urltitle = self.config.get('urltitle') self.priority = self.config.getInt('priority') or 1 # "-2" no notification, -1 quiet notification, 1 - high priority, 2 requires confirmation by user self.sound = self.config.get('sound') or "bike" # https://pushover.net/api#sounds
def getBridgeConfig(self): address = self.config.get('address') username = self.config.get('username') if not address: raise Exception('Must configure address = <ip> or "auto" under [main] in config') if not username: raise Exception('Must configure username = <username-for-hue-bridge> under [main] in config') if address == 'auto': from chains.services.philipshue import discovery info = discovery.discover() if info: info = info[0] # todo: handle multiple bridges? if info and info.has_key('internalipaddress'): address = info['internalipaddress'] log.info('discovered bridge-address: %s' % address) else: log.warn('could not find bridge-address by auto-discovery') else: log.info('got bridge-address from config: %s' % address) return (address, username)
def onInit(self): # Required parameters for pushover self.token = self.config.get('token') self.username = self.config.get('username') if not self.token or self.username: log.warn('Service needs token and username to work.') sys.exit(1) # Optional parameters for pushover # TODO: optionally set default values for these in config self.pushurl = 'https://api.pushover.net/1/messages.json' self.message = self.config.get('message') or "Chains calling!" self.targetdevice = self.config.get('targetdevice') self.title = self.config.get('title') self.url = self.config.get('url') self.urltitle = self.config.get('urltitle') self.priority = self.config.getInt( 'priority' ) or 1 # "-2" no notification, -1 quiet notification, 1 - high priority, 2 requires confirmation by user self.sound = self.config.get( 'sound') or "bike" # https://pushover.net/api#sounds
def action_op(self, nick, channel=None): if not channel: channel = self.channel channel = self.addChannelPrefix(channel) log.info('do_op1: %s' % channel) chanobj = None for cn, co in self.channels.items(): if cn == channel: chanobj = co break if not chanobj: msg = 'Cannot op %s on %s because I am not joined to that channel' % (nick, channel) self.connection.notice(self.channel, msg) log.warn(msg) return if not self.connection.get_nickname() in chanobj.opers(): msg = 'Cannot op %s on %s because I am not op on that channel' % (nick, channel) self.connection.notice(self.channel, msg) log.warn(msg) return cmd = '+o %s' % nick #log.info('do_op: MODE %s %s' % (channel,cmd)) self.connection.mode(channel, cmd)
def reconnect(self, e): if self.connection: self.connection.close() self.producer = None self.consumer = None self.connection = None delay = 2 retry = 0 while True: retry += 1 log.error( 'Attempting to reconnect #%s and continue in %s sec after socket error: %s' % (retry, delay, e)) time.sleep(delay) try: self._connect() log.error( 'Successfully reconnected (after %s retries) - back to work!' % (retry)) return except socket.error as e2: log.info( 'Ignoring expected exception on reconnect and will soon try again: %s' % repr(e2)) except amqplib.client_0_8.exceptions.AMQPConnectionException as e2: log.info( 'Ignoring expected exception on reconnect and will soon try again: %s' % repr(e2)) except ConnectionNotReadyException as e2: log.info( 'Ignoring expected exception on reconnect and will soon try again: %s' % repr(e2)) except Exception as e2: log.warn( 'Ignoring unexpected exception on reconnect and will soon try again: %s' % repr(e2))
def getBridgeConfig(self): address = self.config.get('address') username = self.config.get('username') if not address: raise Exception( 'Must configure address = <ip> or "auto" under [main] in config' ) if not username: raise Exception( 'Must configure username = <username-for-hue-bridge> under [main] in config' ) if address == 'auto': from chains.services.philipshue import discovery info = discovery.discover() if info: info = info[0] # todo: handle multiple bridges? if info and info.has_key('internalipaddress'): address = info['internalipaddress'] log.info('discovered bridge-address: %s' % address) else: log.warn('could not find bridge-address by auto-discovery') else: log.info('got bridge-address from config: %s' % address) return (address, username)
def onStart(self): if not self.hosts: log.warn('No hosts to ping') return started = False while not self._shutdown: for name in self.hosts: host = self.hosts[name] if self.ping(host): if self.isDown(host) or not started: self.sendEvent(name, {'value': 'up', 'address': host}) try: del self.down[host] except: pass else: if not self.isDown(host): self.sendEvent(name, { 'value': 'down', 'address': host }) self.down[host] = True started = True time.sleep(self.interval)
def reconnect(self, e): if self.connection: self.connection.close() self.producer = None self.consumer = None self.connection = None delay = 2 retry = 0 while True: retry += 1 log.error('Attempting to reconnect #%s and continue in %s sec after socket error: %s' % (retry, delay, e)) time.sleep(delay) try: self._connect() log.error('Successfully reconnected (after %s retries) - back to work!' % (retry)) return except socket.error as e2: log.info('Ignoring expected exception on reconnect and will soon try again: %s' % repr(e2)) except amqplib.client_0_8.exceptions.AMQPConnectionException as e2: log.info('Ignoring expected exception on reconnect and will soon try again: %s' % repr(e2)) except ConnectionNotReadyException as e2: log.info('Ignoring expected exception on reconnect and will soon try again: %s' % repr(e2)) except Exception as e2: log.warn('Ignoring unexpected exception on reconnect and will soon try again: %s' % repr(e2))
def closeTelldus(self): log.info('Closing telldus') try: td.unregisterCallback(self.deviceCallbackId) except: log.warn('ignored error unregistering device callback') try: td.unregisterCallback(self.sensorCallbackId) except: log.warn('ignored error unregistering sensor callback') try: td.close() except: log.warn('ignored error closing td')
def onInit(self): self.keymaps = { 'en_US': [ '', '', '', '', 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z', '1', '2', '3', '4', '5', '6', '7', '8', '9', '0', '\n', '^]', '^H', '^I', ' ', '-', '=', '[', ']', '\\', '>', ';', "'", '`', ',', '.', '/', 'CapsLock', 'F1', 'F2', 'F3', 'F4', 'F5', 'F6', 'F7', 'F8', 'F9', 'F10', 'F11', 'F12', 'PS', 'SL', 'Pause', 'Ins', 'Home', 'PU', '^D', 'End', 'PD', '->', '<-', '-v', '-^', 'NL', 'KP/', 'KP*', 'KP-', 'KP+', 'KPE', 'KP1', 'KP2', 'KP3', 'KP4', 'KP5', 'KP6', 'KP7', 'KP8', 'KP9', 'KP0', '\\', 'App', 'Pow', 'KP=', 'F13', 'F14' ] } self.shiftmaps = { 'en_US': [ '', '', '', '', 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z', '!', '@', '#', '$', '%', '^', '&', '*', '(', ')', '\n', '^]', '^H', '^I', ' ', '_', '+', '{', '}', '|', '<', ':', '"', '~', '<', '>', '?', 'CapsLock', 'F1', 'F2', 'F3', 'F4', 'F5', 'F6', 'F7', 'F8', 'F9', 'F10', 'F11', 'F12', 'PS', 'SL', 'Pause', 'Ins', 'Home', 'PU', '^D', 'End', 'PD', '->', '<-', '-v', '-^', 'NL', 'KP/', 'KP*', 'KP-', 'KP+', 'KPE', 'KP1', 'KP2', 'KP3', 'KP4', 'KP5', 'KP6', 'KP7', 'KP8', 'KP9', 'KP0', '|', 'App', 'Pow', 'KP=', 'F13', 'F14' ] } self.mods = { 1: 'control_left', # Left control 2: 'shift_left', # Left shift 4: 'alt_left', # Left alt 8: 'super_left', # Left super 16: 'control_right', # Right control 32: 'shift_right', # Right shift 64: 'alt_right', # Right alt 128: 'super_right', # Right super } # ## Service config self.interval = int(self.config.get('interval')) or 10 self.max_word = int(self.config.get('max_word')) or 50 self.max_line = int(self.config.get('max_line')) or 250 self.vendorid = int(self.config.get('vendorid')) self.productid = int(self.config.get('productid')) self.search_params = {} if self.vendorid and self.productid: self.search_params.update({'idVendor': self.vendorid, 'idProduct': self.productid}) kbdevs = cusb.find_keyboard(self.search_params) else: log.warn("No config, using first found usb keyboard") kbdevs = cusb.find_keyboard() if not kbdevs: log.error("Can't find keyboard") sys.exit("Can't find keyboard") # Use first matching keyboard keyboard = kbdevs[0] # ## vendor and product ids self.dev = usb.core.find(address=keyboard['address'], bus=keyboard['bus']) self.interface = keyboard['interface'] # use the first endpoint # dev[configuration][(interface, alt_config)][endpoint] self.endpoint = self.dev[keyboard['configuration']][(keyboard['interface'], 0)][0]
def onInit(self): # Channel(s) from config defaultChannel = 'chains' channels = [] try: channels = self.config['main']['channel'].split(',') except KeyError: pass if not channels: channels = ['chains'] log.warn('Missing or empty "channel" in %s service config, using %s' % (self.config['id'], defaultChannel)) for i in range(len(channels)): channels[i] = self.addChannelPrefix(channels[i].strip()) # Secret(s) secrets = {} for k in self.config['main']: tmp = k.split('.') if len(tmp) == 2 and tmp[0] == 'secret': secret[tmp[1]] = self.config['main'][k] # Nick nickname = 'chainsbot' try: nickname = self.config['main']['nickname'] except KeyError: log.warn('No "nickname" in %s service config, using %s' % (self.config['id'], nickname)) # Realname realname = 'chainsbot' try: realname = self.config['main']['realname'] except KeyError: realname = nickname log.info('No "realname" in %s service config, using nickname: %s' % (self.config['id'], nickname)) # Server server = 'localhost' try: server = self.config['main']['server'] except KeyError: log.warn('No "server" in %s service config, using %s' % (self.config['id'], server)) # Port port = 6667 try: port = int(self.config['main']['port']) except KeyError: log.warn('No "port" in %s service config, using %s' % (self.config['id'], str(port))) def onStart(self): # For handelig async stuff self.waitEvents = {} SingleServerIRCBot.__init__(self, [(server, port)], nickname, realname) self.allChannels = channels self.channel = channels[0] # first chan is default chan log.info('all configured channels: %s' % self.allChannels) log.info('configured main channel: %s' % self.channel) self.secrets = secrets self.help_hash = {'help':('This menu',{}), } self.queue = OutputManager(self.connection, .9) self.queue.start() try: self.start() except KeyboardInterrupt: self.connection.quit("Ctrl-C at console") print "Quit IRC." except Exception, e: self.connection.quit("%s: %s" % (e.__class__.__name__, e.args)) raise
'Not configured to use services_discover() to find services') if self.config.getBool('lookup'): log.debug('Using lookup_name() to find services') try: for addr in self.guests: name = bluetooth.lookup_name(addr) if name: log.debug('Found service: %s' % addr) result.append(addr) else: log.debug('Did not find service: %s' % addr) # This happens from time to time, and we don't want to die because of it: # BluetoothError: error communicating with local bluetooth adapter except bluetooth.btcommon.BluetoothError, e: log.warn('BluetoothError ignored: %s' % e) else: log.debug('Not configured to use lookup_name() to find services') log.debug('Finished getting blueooth services') return result def guestsToState(self): for mac, nick in self.guests.iteritems(): self.addToState(mac, False, nick) def addToState(self, address, present, nick=None): self.state[address] = { 'name': None, # name that service identifies itself by via bluetooth
def onInit(self): self.keymaps = { 'en_US': [ '', '', '', '', 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z', '1', '2', '3', '4', '5', '6', '7', '8', '9', '0', '\n', '^]', '^H', '^I', ' ', '-', '=', '[', ']', '\\', '>', ';', "'", '`', ',', '.', '/', 'CapsLock', 'F1', 'F2', 'F3', 'F4', 'F5', 'F6', 'F7', 'F8', 'F9', 'F10', 'F11', 'F12', 'PS', 'SL', 'Pause', 'Ins', 'Home', 'PU', '^D', 'End', 'PD', '->', '<-', '-v', '-^', 'NL', 'KP/', 'KP*', 'KP-', 'KP+', 'KPE', 'KP1', 'KP2', 'KP3', 'KP4', 'KP5', 'KP6', 'KP7', 'KP8', 'KP9', 'KP0', '\\', 'App', 'Pow', 'KP=', 'F13', 'F14' ] } self.shiftmaps = { 'en_US': [ '', '', '', '', 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z', '!', '@', '#', '$', '%', '^', '&', '*', '(', ')', '\n', '^]', '^H', '^I', ' ', '_', '+', '{', '}', '|', '<', ':', '"', '~', '<', '>', '?', 'CapsLock', 'F1', 'F2', 'F3', 'F4', 'F5', 'F6', 'F7', 'F8', 'F9', 'F10', 'F11', 'F12', 'PS', 'SL', 'Pause', 'Ins', 'Home', 'PU', '^D', 'End', 'PD', '->', '<-', '-v', '-^', 'NL', 'KP/', 'KP*', 'KP-', 'KP+', 'KPE', 'KP1', 'KP2', 'KP3', 'KP4', 'KP5', 'KP6', 'KP7', 'KP8', 'KP9', 'KP0', '|', 'App', 'Pow', 'KP=', 'F13', 'F14' ] } self.mods = { 1: 'control_left', # Left control 2: 'shift_left', # Left shift 4: 'alt_left', # Left alt 8: 'super_left', # Left super 16: 'control_right', # Right control 32: 'shift_right', # Right shift 64: 'alt_right', # Right alt 128: 'super_right', # Right super } # ## Service config self.interval = int(self.config.get('interval')) or 10 self.max_word = int(self.config.get('max_word')) or 50 self.max_line = int(self.config.get('max_line')) or 250 self.vendorid = int(self.config.get('vendorid')) self.productid = int(self.config.get('productid')) self.search_params = {} if self.vendorid and self.productid: self.search_params.update({ 'idVendor': self.vendorid, 'idProduct': self.productid }) kbdevs = cusb.find_keyboard(self.search_params) else: log.warn("No config, using first found usb keyboard") kbdevs = cusb.find_keyboard() if not kbdevs: log.error("Can't find keyboard") sys.exit("Can't find keyboard") # Use first matching keyboard keyboard = kbdevs[0] # ## vendor and product ids self.dev = usb.core.find(address=keyboard['address'], bus=keyboard['bus']) self.interface = keyboard['interface'] # use the first endpoint # dev[configuration][(interface, alt_config)][endpoint] self.endpoint = self.dev[keyboard['configuration']][( keyboard['interface'], 0)][0]
log.debug('Not configured to use services_discover() to find services') if self.config.getBool('lookup'): log.debug('Using lookup_name() to find services') try: for addr in self.guests: name = bluetooth.lookup_name(addr) if name: log.debug('Found service: %s' % addr) result.append(addr) else: log.debug('Did not find service: %s' % addr) # This happens from time to time, and we don't want to die because of it: # BluetoothError: error communicating with local bluetooth adapter except bluetooth.btcommon.BluetoothError,e: log.warn('BluetoothError ignored: %s' % e) else: log.debug('Not configured to use lookup_name() to find services') log.debug('Finished getting blueooth services') return result def guestsToState(self): for mac, nick in self.guests.iteritems(): self.addToState(mac, False, nick) def addToState(self, address, present, nick=None): self.state[address] = { 'name': None, # name that service identifies itself by via bluetooth 'nick': nick, # friendly name for guest from config
self.actionThread.join() except RuntimeError, e: log.warn('Ignoring exception about joining actionThread: %s' % e) log.info('actionThread done') log.info('Running onShutdown()') try: self.onShutdown() except Exception, e: log.warn('Ignoring exception during onShutdown: %s' % e) log.info('Finished running onShutdown()') log.info('Joining eventThread') if self.eventThread: try: self.eventThread.join() except RuntimeError, e: log.warn('Ignoring exception about joining eventThread: %s' % e) log.info('eventThread done') # Send an event about being online log.info('Send offline event') try: self.sendOfflineEvent() except Exception, e: log.warn('Ignoring exception during sendOfflineEvent: %s' % e) time.sleep(1) log.info('Shutdown complete') # ============================================= # Lifecycle functions, # that can be implemented as needed. # None of these are required. # =============================================
def action_setLogLevel(self, level): log.setLevel(level) log.warn('Changed loglevel to "%s" during runtime' % level)
def onInit(self): self.button_events = [ array('B', [1, 0, 0, 0, 0, 0, 0]), 'button_release', array('B', [1, 1, 0, 0, 0, 0, 0]), 'button_left', array('B', [1, 2, 0, 0, 0, 0, 0]), 'button_right', array('B', [1, 4, 0, 0, 0, 0, 0]), 'button_middle', array('B', [1, 8, 0, 0, 0, 0, 0]), 'button_3', array('B', [1, 16, 0, 0, 0, 0, 0]), 'button_4', array('B', [1, 32, 0, 0, 0, 0, 0]), 'button_5', array('B', [1, 64, 0, 0, 0, 0, 0]), 'button_6', array('B', [1, 128, 0, 0, 0, 0, 0]), 'button_7', array('B', [1, 255, 0, 0, 0, 0, 0]), 'button_8', array('B', [1, 0, 0, 0, 0, 0, 1]), 'wheel_up', array('B', [1, 0, 0, 0, 0, 0, 255]), 'wheel_down', # mouse button combinations # TODO: do this by using bitwise operator to generate all combinations array('B', [1, 3, 0, 0, 0, 0, 0]), 'button_left_right', array('B', [1, 5, 0, 0, 0, 0, 0]), 'button_left_middle', array('B', [1, 6, 0, 0, 0, 0, 0]), 'button_right_middle', array('B', [1, 7, 0, 0, 0, 0, 0]), 'button_left_right_middle', ] # "slow" mouse movements self.move_events = [ array('B', [1, 0, 0, 0, 1, 0, 0]), 'down', array('B', [1, 0, 255, 255, 1, 0, 0]), 'down-left', array('B', [1, 0, 1, 0, 1, 0, 0]), 'down-right', array('B', [1, 0, 0, 0, 255, 255, 0]), 'up', array('B', [1, 0, 255, 255, 255, 255, 0]), 'up-left', array('B', [1, 0, 1, 0, 255, 255, 0]), 'up-right', array('B', [1, 0, 255, 255, 0, 0, 0]), 'left', array('B', [1, 0, 1, 0, 0, 0, 0]), 'right', ] # ## Service config self.interval = int(self.config.get('interval')) or 600 # milliseconds self.vendorid = int(self.config.get('vendorid')) self.productid = int(self.config.get('productid')) self.search_params = {} if self.vendorid and self.productid: self.search_params.update({ 'idVendor': self.vendorid, 'idProduct': self.productid }) mousedevs = cusb.find_mouse(self.search_params) else: log.warn("No config, using first found mouse service") mousedevs = cusb.find_mouse() if not mousedevs: log.error("Can't find mouse service") sys.exit("Can't find mouse service") # Use first matching mouse mouse = mousedevs[0] # ## vendor and product ids self.dev = usb.core.find(address=mouse['address'], bus=mouse['bus']) self.interface = mouse['interface'] # use the first endpoint # dev[configuration][(interface, alt_config)][endpoint] self.endpoint = self.dev[mouse['configuration']][(mouse['interface'], 0)][0]
class Service(AmqpDaemon): ''' Service - base class for all services A Service's mission is to send events and respond to actions. Typical approach for a service is this: == Init == In onInit(), do any setup-tasks that does not block forever, like making sure relevant config settings are okay, opening a serial port, checking for needed files etc. == Run == In onStart(), do any "while true do this" tasks that block forever, like polling values from an external interface and sending events, or running a webserver that listens forever, or reading from the serial port etc. == Actions == Implement a number of cmd_xxx() functions, one for each action that the service can perform. == Shutdown == In onShutdown() do any cleanup tasks if necceceary. Note however that this is not guaranteed to be run! == Describe == In onDescribe() describe the various events that the service can send. You can also describe the actions, but if you use the cmd_xxx() approach, you should not need to. Implementing onDescribe() is optional, but should be done (eventually) to lay the grounds for a nice rules-creation-gui in the future. See documentation of each method below for more info. ''' # Signals that shutdown is in progress. # If this is changed to True (by shutdown()), # then any "while forever do this and that" loops # should shop doing whatever they're doing. _shutdown = False # ============================================= # Core functions, # that should (usually) not be overriden. # ============================================= def __init__(self, config): AmqpDaemon.__init__(self, 'service', config.get('id')) #, sendHeartBeat=True) self.config = config self.eventThread = None self.actionThread = None self.onInit() def start(self, block=False): ''' Run the service Will start main loop, onStart(), in a separate thread, and then start listening for incoming actions. This function should typically NOT be overridden. Your service's custom main loop code should be implemented in onStart() instead. ''' # Send an event about being online self.sendOnlineEvent() # @todo: shutdown of loop # - how to break loop(s) when shutdown() is called # - up to each service to implement? # Do main loop, i.e. onStart(), in a separate thread # (It will typically do stuff and call onEvent() to # push events to the queue). log.info('Starting thread for onStart') self.eventThread = ServiceThread(self.onStart, 'OnStart', self.config.get('id')) self.eventThread.start() if block: self.listen() else: self.actionThread = ServiceThread(self.listen, 'Actions', self.config.get('id')) self.actionThread.start() def shutdown(self): AmqpDaemon.shutdown(self) #log.info('Shutdown called') #self._shutdown = True # Send an action message to ourself to make sure # we break out of the wait-loop for actions asap. #log.info('Send _shutdown action') #self.sendShutdownAction() #log.info('Wait 0.5') time.sleep(0.5) log.info('Joining actionThread') if self.actionThread: try: self.actionThread.join() except RuntimeError, e: log.warn('Ignoring exception about joining actionThread: %s' % e) log.info('actionThread done') log.info('Running onShutdown()') try: self.onShutdown() except Exception, e: log.warn('Ignoring exception during onShutdown: %s' % e)
while True: retry += 1 log.error('Attempting to reconnect #%s and continue in %s sec after socket error: %s' % (retry,delay,e)) time.sleep(delay) try: self._connect() log.error('Successfully reconnected (after %s retries) - back to work!' % (retry)) return except socket.error, e2: log.info('Ignoring expected exception on reconnect and will soon try again: %s' % e2) except amqplib.client_0_8.exceptions.AMQPConnectionException, e2: log.info('Ignoring expected exception on reconnect and will soon try again: %s' % e2) except ConnectionNotReadyException, e2: log.info('Ignoring expected exception on reconnect and will soon try again: %s' % e2) except Exception, e2: log.warn('Ignoring unexpected exception on reconnect and will soon try again: %s' % e2) def listen(self): log.info('Start listening for messages, topics = %s' % self.getConsumeKeys()) actionPrefix = self.getActionPrefix() heartBeatRequestPrefix = self.getHeartBeatRequestPrefix() while not self._shutdown: log.notice('Waiting for messages') try: topic, data, correlationId = self.consumer.get() except socket.error, e: self.reconnect(e) continue except amqplib.client_0_8.exceptions.AMQPConnectionException, e: self.reconnect(e) continue