def navdatapush(self): """ Pushes the current :referenceframe: out to clients. :return: """ try: self.fireEvent( referenceframe({ 'data': self.referenceframe, 'ages': self.referenceages }), "navdata") self.intervalcount += 1 if self.intervalcount == self.passiveinterval: self.fireEvent( broadcast( 'users', { 'component': 'navdata', 'action': 'update', 'data': { 'data': self.referenceframe.serializablefields(), 'ages': self.referenceages } }), "hfosweb") self.intervalcount = 0 hfoslog("[NAVDATA] Reference frame successfully pushed.", lvl=verbose) except Exception as e: hfoslog("[NAVDATA] Could not push referenceframe: ", e, type(e), lvl=critical)
def install_service(): """Install systemd service configuration""" _check_root() hfoslog("Installing systemd service", emitter="MANAGE") launcher = os.path.realpath(__file__).replace('manage', 'launcher') executable = sys.executable + " " + launcher executable += " --dolog --logfile /var/log/hfos.log" executable += " --logfileverbosity 30 -q" definitions = { 'executable': executable } write_template_file(os.path.join('dev/templates', service_template), '/etc/systemd/system/hfos.service', definitions) Popen([ 'systemctl', 'enable', 'hfos.service' ]) hfoslog("Done: Install Service", emitter="MANAGE")
def install_provisions(provision, dbhost, clear=False, overwrite=False): """Install default provisioning data""" hfoslog("Installing HFOS default provisions", emitter='MANAGE') # from hfos.logger import verbosity, events # verbosity['console'] = verbosity['global'] = events from hfos import database database.initialize(dbhost) from hfos.provisions import provisionstore if provision is not None: if provision in provisionstore: hfoslog("Provisioning ", provision, emitter="MANAGE") provisionstore[provision](overwrite=overwrite, clear=clear) else: hfoslog("Unknown provision: ", provision, "\nValid provisions are", list(provisionstore.keys()), lvl=error, emitter='MANAGE') else: for provision_name in provisionstore: hfoslog("Provisioning " + provision_name, emitter='MANAGE') provisionstore[provision_name](overwrite=overwrite, clear=clear) hfoslog("Done: Install Provisions")
def _handle(self, nmeadata): for sentence, sen_time in nmeadata: try: if type(sentence) in [types.GGA, types.GLL, types.GSV, types.MWD]: data = sensordataobject() data.Time_Created = sen_time if type(sentence) == types.GGA: data.GPS_LatLon = str((sentence.lat, sentence.lat_dir, sentence.lon, sentence.lon_dir)) data.GPS_SatCount = int(sentence.num_sats) data.GPS_Quality = int(sentence.gps_qual) elif type(sentence) == types.GLL: data.GPS_LatLon = str((sentence.lat, sentence.lat_dir, sentence.lon, sentence.lon_dir)) elif type(sentence) == types.GSV: data.GPS_SatCount = int(sentence.num_sv_in_view) elif type(sentence) == types.MWD: data.Wind_Direction_True = int(sentence.direction_true) data.Wind_Speed_True = int(sentence.wind_speed_meters) self.fireEvent(sensordata(data), "navdata") else: hfoslog("[NMEA] Unhandled sentence acquired: ", sentence) except Exception as e: hfoslog("[NMEA] Error during sending: ", nmeadata, e, type(e), lvl=error)
def sensordata(self, event): """ Generates a new reference frame from incoming sensordata :param event: new sensordata to be merged into referenceframe """ newdata = event.data try: newdata.validate() except ValidationError as e: hfoslog("[NAVDATA] Invalid sensordata received: ", newdata, e, lvl=error) try: for key in newdata._fields: if key not in ('uuid', 'Time_Created'): self.referenceframe._fields[key] = newdata._fields[key] self.referenceages[key] = newdata._fields['Time_Created'] # hfoslog("[NAVDATA] New reference frame data: ", self.referenceages, self.referenceframe, lvl=critical) except Exception as e: hfoslog("[NAVDATA] Problem during sensordata evaluation: ", newdata, e, type(e), lvl=error)
def __init__(self, clientuuid, useruuid, *args): super(userlogin, self).__init__(*args) self.clientuuid = clientuuid self.useruuid = useruuid hfoslog("[CM-EVENT] User login event generated:", clientuuid, useruuid, lvl=events)
def install_all(clear): """Default-Install everything installable \b This includes * System user (hfos.hfos) * Self signed certificate * Variable data locations (/var/lib/hfos and /var/cache/hfos) * All the official modules in this repository * Default module provisioning data * Documentation * systemd service descriptor It also builds and installs the HTML5 frontend.""" _check_root() install_system_user() install_cert(selfsigned=True) install_var(clear=clear, clear_all=clear) install_modules() install_provisions(provision=None, dbhost=db_host_default, clear=clear) install_docs(clear=clear) install_frontend(forcerebuild=True, development=True) install_service() install_nginx() hfoslog('Done')
def _handle(self, nmeadata): for sentence, sen_time in nmeadata: try: if type(sentence) in [ types.GGA, types.GLL, types.GSV, types.MWD ]: data = sensordataobject() data.Time_Created = sen_time if type(sentence) == types.GGA: data.GPS_LatLon = str((sentence.lat, sentence.lat_dir, sentence.lon, sentence.lon_dir)) data.GPS_SatCount = int(sentence.num_sats) data.GPS_Quality = int(sentence.gps_qual) elif type(sentence) == types.GLL: data.GPS_LatLon = str((sentence.lat, sentence.lat_dir, sentence.lon, sentence.lon_dir)) elif type(sentence) == types.GSV: data.GPS_SatCount = int(sentence.num_sv_in_view) elif type(sentence) == types.MWD: data.Wind_Direction_True = int(sentence.direction_true) data.Wind_Speed_True = int(sentence.wind_speed_meters) self.fireEvent(sensordata(data), "navdata") else: hfoslog("[NMEA] Unhandled sentence acquired: ", sentence) except Exception as e: hfoslog("[NMEA] Error during sending: ", nmeadata, e, type(e), lvl=error)
def _splitURL(self, url): try: if self.path is not None: url = url[len(self.path):] # Cut off server's url path url = unquote(url) if '..' in url: # Does this need more safety checks? hfoslog("Fishy url with parent path: ", url, lvl=error, emitter="MTS") raise UrlError spliturl = url.split("/") service = "/".join( spliturl[1:-3]) # get all but the coords as service x = spliturl[-3] y = spliturl[-2] z = spliturl[-1].split('.')[0] filename = os.path.join(self.tilepath, service, x, y) + "/" + z + ".png" realurl = "http://" + service + "/" + x + "/" + y + "/" + z + \ ".png" except Exception as e: hfoslog("ERROR (%s) in URL: %s" % (e, url), emitter="MTS") raise UrlError return filename, realurl
def rec(self): """Records a single snapshot""" try: self._snapshot() except Exception as e: hfoslog("[CAM] Timer error: ", e, type(e), lvl=error)
def _splitURL(self, url): try: if self.path is not None: url = url[len(self.path):] # Cut off server's url path url = unquote(url) if '..' in url: # Does this need more safety checks? hfoslog("[TC] Fishy url with parent path: ", url, lvl=error) raise UrlError spliturl = url.split("/") service = "/".join( spliturl[1:-3]) # get all but the coords as service x = spliturl[-3] y = spliturl[-2] z = spliturl[-1].split('.')[0] filename = os.path.join(self.tilepath, service, x, y) + "/" + z + ".png" realurl = "http://" + service + "/" + x + "/" + y + "/" + z + ".png" except Exception as e: hfoslog("[TC] ERROR (%s) in URL: %s" % (e, url)) raise UrlError return filename, realurl
def __init__(self, clientuuid, useruuid=None, *args): super(clientdisconnect, self).__init__(*args) self.clientuuid = clientuuid self.useruuid = useruuid hfoslog("[CM-EVENT] Client disconnect event generated:", clientuuid, useruuid, lvl=events)
def read(self, *args): """ Handles incoming data from the machine room hardware control system. :param args: """ hfoslog("[MR] Data received from machineroom: ", args)
def modify(ctx, schema, uuid, filter, field, value): """Modify field values of objects""" database = ctx.obj['db'] model = database.objectmodels[schema] obj = None if uuid: obj = model.find_one({'uuid': uuid}) elif filter: obj = model.find_one(literal_eval(filter)) else: hfoslog('No object uuid or filter specified.', lvl=error, emitter='manage') if obj is None: hfoslog('No object found', lvl=error, emitter='manage') return hfoslog('Object found, modifying', lvl=debug, emitter='manage') obj._fields[field] = literal_eval(value) obj.validate() hfoslog('Changed object validated', lvl=debug, emitter='manage') obj.save() hfoslog('Done')
def _build_collections(store): result = {} client = pymongo.MongoClient(host='localhost', port=27017) db = client['hfos'] for schemaname in store: schema = None try: schema = store[schemaname]['schema'] except KeyError: hfoslog("No schema found for ", schemaname, lvl=critical, emitter='DB') try: result[schemaname] = db[schemaname] except Exception as e: hfoslog("Could not get collection for schema ", schemaname, schema, e, lvl=critical, emitter='DB') return result
def __init__(self, useruuid, *args): super(userlogout, self).__init__(*args) self.useruuid = useruuid hfoslog("[CM-EVENT] User logout event generated:", useruuid, lvl=events)
def __init__(self, uuid, packet, sendtype="client", raw=False, username=None, fail_quiet=False, *args): """ :param uuid: Unique User ID of known connection :param packet: Data packet to transmit to client :param args: Further Args """ super(send, self).__init__(*args) if uuid is None and username is None: hfoslog("[SEND-EVENT] No recipient (uuid/name) given!", lvl=warn) self.uuid = uuid self.packet = packet self.username = username self.sendtype = sendtype self.raw = raw self.fail_quiet = fail_quiet hfoslog("[CM-EVENT] Send event generated:", uuid, str(packet)[:50], sendtype, lvl=events)
def _get_credentials(username=None, password=None, dbhost=None): """Obtain user credentials by arguments or asking the user""" # Database salt system_config = dbhost.objectmodels['systemconfig'].find_one({ 'active': True }) try: salt = system_config.salt.encode('ascii') except (KeyError, AttributeError): hfoslog('No systemconfig or it is without a salt! ' 'Reinstall the system provisioning with' 'hfos_manage.py install provisions -p system') sys.exit(3) if username is None: username = _ask("Please enter username: ") else: username = username if password is None: password = _ask_password() else: password = password try: password = password.encode('utf-8') except UnicodeDecodeError: password = password passhash = hashlib.sha512(password) passhash.update(salt) return username, passhash.hexdigest()
def __init__(self, maxcams=16, *args): super(CameraManager, self).__init__(*args) self._cameras = {} self._subscribers = {} self._filming = True self._framecount = 0 self._frames = {} hfoslog("[CAM] Checking opencv for cameras.", lvl=debug) for cam in range(maxcams): video = opencv.VideoCapture(cam) if video.isOpened(): camera = { 'uuid': str(uuid4()), 'name': 'Camera' + str(cam), 'cam': video } self._cameras[cam] = camera hfoslog("[CAM] Found camera [", cam, "]: ", camera) hfoslog("[CAM] Starting timer") self.timer = Timer(0.05, Event.create("rec"), persist=True).register(self) hfoslog("[CAM] Found cameras: ", self._cameras, lvl=debug) hfoslog("[CAM] Started")
def _broadcast(self, camerapacket, camerauuid): try: for recipient in self._subscribers[camerauuid]: self.fireEvent(send(recipient, camerapacket, raw=True), "hfosweb") except Exception as e: hfoslog("[CAM] Failed broadcast: ", e, type(e), lvl=error)
def apply_additions(additions, result): for addition in additions: path = get_path(addition) entry = additions[addition] hfoslog('Adding:', entry, 'at', path) dpath.util.new(result, path, entry) return result
def __init__(self, maxcams=16, *args): super(CameraManager, self).__init__(*args) self._cameras = {} self._subscribers = {} self._filming = True self._framecount = 0 self._frames = {} hfoslog("[CAM] Checking opencv for cameras.", lvl=debug) for cam in range(maxcams): video = opencv.VideoCapture(cam) if video.isOpened(): camera = {'uuid': str(uuid4()), 'name': 'Camera' + str(cam), 'cam': video } self._cameras[cam] = camera hfoslog("[CAM] Found camera [", cam, "]: ", camera) hfoslog("[CAM] Starting timer") self.timer = Timer(0.05, Event.create("rec"), persist=True).register(self) hfoslog("[CAM] Found cameras: ", self._cameras, lvl=debug) hfoslog("[CAM] Started")
def addNode(self, uuid, ip): hoststring = 'tcp://' + ip + ':' + str(PORT) hfoslog("ZMQ Dealer peer:", hoststring) p = self.ctx.socket(zmq.DEALER) p.connect(hoststring) p.send_string('HELLO:' + self.uuid) self.sockets[uuid] = p
def construct_graph(args): """Preliminary HFOS application Launcher""" app = Core(host=args.host, port=args.port, insecure=args.insecure) setup_root(app) # if dodebug: # from circuits import Debugger # dbg = Debugger() # dbg.IgnoreEvents.extend(["write", "_write", "streamsuccess"]) # HFDebugger(root=server).register(server) hfoslog("Beginning graph assembly.", emitter='GRAPH') if args.drawgraph: from circuits.tools import graph graph(app) if args.opengui: import webbrowser webbrowser.open("http://%s:%i/" % (args.host, args.port)) hfoslog("Graph assembly done.", emitter='GRAPH') return app
def _build_model_factories(store): result = {} for schemaname in store: schema = None try: schema = store[schemaname]['schema'] except KeyError: hfoslog("No schema found for ", schemaname, lvl=critical, emitter='DB') try: result[schemaname] = warmongo.model_factory(schema) except Exception as e: hfoslog("Could not create factory for schema ", e, type(e), schemaname, schema, lvl=critical, emitter='DB') return result
def serial_ports(): """ Lists serial port names :raises EnvironmentError: On unsupported or unknown platforms :returns: A list of the serial ports available on the system Courtesy: Thomas ( http://stackoverflow.com/questions/12090503 /listing-available-com-ports-with-python ) """ if sys.platform.startswith('win'): ports = ['COM%s' % (i + 1) for i in range(256)] elif sys.platform.startswith('linux') or sys.platform.startswith('cygwin'): # this excludes your current terminal "/dev/tty" ports = glob.glob('/dev/tty[A-Za-z]*') elif sys.platform.startswith('darwin'): ports = glob.glob('/dev/tty.*') else: raise EnvironmentError('Unsupported platform') result = [] for port in ports: try: s = serial.Serial(port) s.close() result.append(port) except (OSError, serial.SerialException) as e: hfoslog('Could not open serial port:', port, e, type(e), exc=True, lvl=warn) return result
def __init__(self, data): """ :param data: Parsed NMEA? Data """ super(referenceframe, self).__init__() self.data = data hfoslog("[NAVDATA-EVENT] Reference frame generated: ", data, lvl=events)
def client_disconnect(self, event): """Handles unsubscription of disconnected clients :param event: """ hfoslog("[MVM] Removing disconnected client from subscriptions", lvl=debug) clientuuid = event.clientuuid self._unsubscribe(clientuuid)
def _generatemapviewlist(self): try: result = {} for item in mapviewobject.find({'shared': True}): result[item.uuid] = item.serializablefields() return result except Exception as e: hfoslog("[MVM] Error during list retrieval:", e, type(e), lvl=error)
def _broadcast(self, mapviewpacket, mapviewuuid): try: hfoslog("[MVM] Transmitting message '%s'" % mapviewpacket) for recipient in self._subscribers[mapviewuuid]: self.fireEvent(send(recipient, mapviewpacket)) except Exception as e: hfoslog("[MVM] Failed broadcast: ", e, type(e), lvl=error)
def on_rudderrequest(self, event): """ Sets a new rudder angle. :param event: """ hfoslog("[MR] Updating new rudder angle: ", event.controlvalue) self._handleServo(self._rudderchannel, event.controlvalue)
def on_pumprequest(self, event): """ Activates or deactivates a connected pump. :param event: """ hfoslog("[MR] Updating pump status: ", event.controlvalue) self._setDigitalPin(self._pumpchannel, event.controlvalue)
def __init__(self, *args): super(AlertManager, self).__init__(*args) hfoslog("[ALERT] Started") self.referenceframe = None self.mobalert = False self.alertlist = []
def on_ping(self): """ Demo function for debugging purposes. """ # TODO: Delete me hfoslog("[MR] Pinging") self._handleServo(self._rudderchannel, randint(0, 255))
def on_machinerequest(self, event): """ Sets a new machine speed. :param event: """ hfoslog("[MR] Updating new machine power: ", event.controlvalue) self._handleServo(self._machinechannel, event.controlvalue)
def test_script_logging(): logger.live = True logger.hfoslog('FOOBAR') lastlog = "".join(logger.LiveLog[-1:]) assert "FOOBAR" in lastlog
def on_remotecontrolupdate(self, event): """ A remote control update request containing control data that has to be analysed according to the selected controller configuration. :param event: RemotecontrolUpdate """ hfoslog("[MR] Control updaterequest: ", event.controldata, lvl=critical)
def _broadcast(self, layerupdatepacket, layeruuid): try: hfoslog("[LM] Transmitting message '%s'" % layerupdatepacket) for recipient in self._subscribers[layeruuid]: self.fireEvent(send(recipient, layerupdatepacket), "wsserver") except Exception as e: hfoslog("[LM] Failed broadcast: ", e, type(e), lvl=error)
def __init__(self, uuid, schema, *args, **kwargs): super(objectevent, self).__init__(*args, **kwargs) self.uuid = uuid self.schema = schema hfoslog("[OBJECT-EVENT] Object event created: ", self.__doc__, self.__dict__, lvl=events)
def unique(it): s = set() for el in it: if el not in s: s.add(el) yield el else: hfoslog("[NMEA] Duplicate sentence received: ", el, lvl=debug)
def _generatecameralist(self): try: result = {} for item in self._cameras.values(): result[item['name']] = item['uuid'] return result except Exception as e: hfoslog("[CAM] Error during list retrieval:", e, type(e), lvl=error)
def read(self, data): """Handles incoming raw sensor data :param data: NMEA raw sentences incoming data """ hfoslog("[NMEA] Incoming data: ", '%.50s ...' % data, lvl=debug) nmeadata = self._parse(data) self._handle(nmeadata)
def __init__(self, uuid, schema, client, *args, **kwargs): super(objectevent, self).__init__(*args, **kwargs) self.uuid = uuid self.schema = schema self.client = client hfoslog("Object event created: ", self.__doc__, self.__dict__, lvl=events, emitter="OBJECT-EVENT")
def construct_graph(dodebug=False, dograph=False, dogui=False): """Preliminary HFOS application Launcher""" if dodebug: from circuits import Debugger server = Server(("0.0.0.0", 8055)) setup_root(server) Logger().register(server) hfoslog("[HFOS] Beginning graph assembly.") HFDebugger().register(server) app = App().register(server) # Machineroom().register(app) navdata = NavData().register(server) NMEAParser("localhost", 2222).register(navdata) TileCache().register(server) Static("/", docroot="/var/lib/hfos/static").register(server) WebSocketsDispatcher("/websocket").register(server) clientmanager = ClientManager().register(server) AlertManager().register(clientmanager) SchemaManager().register(clientmanager) ObjectManager().register(clientmanager) Authenticator().register(clientmanager) Chat().register(clientmanager) MapViewManager().register(clientmanager) LayerManager().register(clientmanager) RemoteControlManager().register(clientmanager) WebDemo().register(clientmanager) Wiki().register(clientmanager) # CameraManager().register(clientmanager) # Logger().register(server) if dodebug: dbg = Debugger() dbg.IgnoreEvents.extend(["write", "_write", "streamsuccess"]) # dbg.register(lm) if dograph: from circuits.tools import graph graph(server) if dogui: import webbrowser webbrowser.open("http://127.0.0.1:8055") hfoslog("[HFOS] Graph assembly done.") return server
def _generatelayerlist(self): try: result = {} for item in layerobject.find({'shared': True}): result[item.uuid] = item.serializablefields() hfoslog("[LM] Generated layer list: ", result, lvl=verbose) return result except Exception as e: hfoslog("[LM] Error during list retrieval:", e, type(e), lvl=error)
def client_disconnect(self, event): """ A client has disconnected, update possible subscriptions accordingly. :param event: """ hfoslog("[CAM] Removing disconnected client from subscriptions", lvl=debug) clientuuid = event.clientuuid self._unsubscribe(clientuuid)
def __init__(self, *args): """ :param user: Userobject of client :param data: The new profile data """ super(profilerequest, self).__init__(*args) hfoslog("[PROFILE-EVENT] Profile update request: ", self.__dict__, lvl=events)
def referenceframe(self, event): """Handles navigational reference frame updates. These are necessary to assign geo coordinates to alerts and other misc things. :param event with incoming referenceframe message """ hfoslog("[ALERT] Got a reference frame update! ", event, lvl=verbose) self.referenceframe = event.data