class AlarmObjectType(db.Model): """Type definition for AlarmObjects""" __tablename__ = 'alarmobjecttypes' __table_args__ = {'extend_existing': True} id = db.Column(db.Integer, primary_key=True) name = db.Column(db.String(50)) remark = db.Column(db.Text) def __init__(self, name, remark): self.name = name self.remark = remark @staticmethod def getAlarmObjectTypes(id=0): """ Get list of AlarmObjectTypes :param id: id of :py:mod:`emonitor.modules.alarmobjects.alarmobjecttype.AlarmObjectType` :return: list or single :py:mod:`emonitor.modules.alarmobjects.alarmobjecttype.AlarmObjectType` """ if id != 0: return AlarmObjectType.query.filter_by(id=id).first() else: try: return AlarmObjectType.query.order_by( collate(AlarmObjectType.name, 'NOCASE')).all() except: return AlarmObjectType.query.order_by( AlarmObjectType.name).all()
class AlarmAttribute(db.Model): """AlarmAttribute class, used in :py:class:`emonitor.modules.alarms.alarm.Alarm`""" __tablename__ = 'alarmattributes' __table_args__ = {'extend_existing': True} id = db.Column(db.Integer, primary_key=True) name = db.Column(db.String(32)) value = db.Column(db.Text) alarm_id = db.Column(db.Integer, db.ForeignKey('alarms.id')) def __repr__(self): return self.name def __init__(self, name, value): self.name = name self.value = value
class MonitorLog(db.Model): __tablename__ = 'monitorlog' timestamp = db.Column(db.TIMESTAMP, primary_key=True) clientid = db.Column(db.Integer) direction = db.Column(db.Integer, default=0) # 0: ->, 1: <- type = db.Column(db.String(16), default='info') operation = db.Column(db.Text, default='') def __init__(self, timestamp, clientid, direction, monitortype, operation): self.timestamp = timestamp self.clientid = clientid self.direction = direction self.type = monitortype self.operation = operation @staticmethod def addLog(clientid, direction, logtype, operation): try: db.session.add( MonitorLog(datetime.datetime.now(), clientid, direction, logtype, str(operation))) db.session.commit() except: pass return None @staticmethod def clearLog(): # not tested db.session.delete(MonitorLog) db.session.commit() @staticmethod def getMonitorLogs(timestamp=0, clientid=0): if timestamp == 0 and clientid == 0: return MonitorLog.query.order_by('timestamp').all() elif timestamp == 0 and clientid != 0: return MonitorLog.query.filter_by( clientid=clientid).order_by('timestamp').all() else: return MonitorLog.query.filter_by(timestamp=timestamp).one() @staticmethod def getLogForClient(clientid): return MonitorLog.query.filter((MonitorLog.clientid == clientid) | (MonitorLog.clientid == 0)).order_by( MonitorLog.timestamp.desc())
class Housenumber(db.Model): """Housenumber class""" __tablename__ = 'housenumbers' __table_args__ = {'extend_existing': True} id = db.Column(db.Integer, primary_key=True) streetid = db.Column(db.Integer, db.ForeignKey('streets.id')) number = db.Column(db.String(10)) _points = db.Column('points', db.Text) street = db.relationship("Street", backref="streets", lazy='joined') def __init__(self, streetid, number, points): self.streetid = streetid self.number = number self._points = points @property def points(self): """ Get points for housenumber :return: yaml structure with point positions """ return yaml.load(self._points) @staticmethod def getHousenumbers(id=0): """ Get list of all housenumbers, filtered by paramters :param optional id: id of housenumber, *0* for all :return: list of :py:class:`emonitor.modules.streets.housenumber.Housenumber` """ if id == 0: return Housenumber.query.order_by(Housenumber.number).all() else: return Housenumber.query.filter_by(id=id).one() def getPosition(self, index=0): try: p = self.points[index] return dict(lat=p[0], lng=p[1]) except: return dict(lat=self.street.lat, lng=self.street.lng)
class AlarmHistory(db.Model): """AlarmHistory class user in :py:class:`emonitor.modules.alarms.alarm.Alarm`""" __tablename__ = 'alarmhistory' __table_args__ = {'extend_existing': True} historytypes = ['autochangeState', 'message'] id = db.Column(db.Integer, primary_key=True) timestamp = db.Column(db.DATETIME, default=datetime.datetime.now()) name = db.Column(db.String(32)) value = db.Column(db.Text) alarm_id = db.Column(db.Integer, db.ForeignKey('alarms.id')) def __repr__(self): return self.name def __init__(self, name, value, dtime): self.name = name self.value = value self.timestamp = dtime
class AlarmkeySet(db.Model): """Alarmkeyset class""" __tablename__ = 'alarmkeysets' __table_args__ = {'extend_existing': True} id = db.Column(db.Integer, primary_key=True) name = db.Column(db.String(40), default='') base = db.Column(db.String(128), default='') startdate = db.Column(db.DATE) enddate = db.Column(db.DATE) remark = db.Column(db.Text) def __init__(self, name, base, startdate, enddate, remark): self.name = name self.base = base self.startdate = startdate self.enddate = enddate self.remark = remark @property def active(self): if (self.startdate or datetime.date.today()) <= datetime.date.today() <= ( self.enddate or datetime.date.today()): return True return False @property def alarmkeys(self): base = AlarmkeySet.getBases(self.base) if len(base) == 1: return base[0].items else: return [] def getDefinedKeys(self): from emonitor.modules.alarmkeys.alarmkey import Alarmkey return Alarmkey.getAlarmkeys(keysetid=self.id) def createBaseKeys(self): from emonitor.modules.alarmkeys.alarmkey import Alarmkey # get items for current key set items = Alarmkey.getOrphanKeys() result = [0, 0] # updated / error items for k in self.alarmkeys: i = filter( lambda x: x.key == k.get('schlagwort') and x.category == k.get( 'stichwort'), items) if len(i) == 1: i[0]._keyset = self.id i[0].keysetitem = k.get('nr') result[0] += 1 else: result[1] += 1 db.session.commit() return result @staticmethod def getAlarmkeySets(id=0): """ Get all alarmkeyset definitions or single definition with given 'id' :param keysetid: id of alarmkeyset :return: list of defintions or single definition """ if id != 0: return AlarmkeySet.query.filter_by(id=int(id)).first() else: return AlarmkeySet.query.order_by('name').all() @staticmethod def getCurrentKeySet(): """ Get active :py:class:`emonitor.modules.alarmkeys.AlarmkeySet` depending in current date and AlarmkeySet attribute *startdate* and *enddate* :return: :py:class:`emonitor.modules.alarmkeys.AlarmkeySet` or *None* """ for a in AlarmkeySet.getAlarmkeySets(): if a.active: return a return None @staticmethod def getBases(basename=""): ret = [] for b in glob.glob("emonitor/modules/alarmkeys/inc/*.json"): ret.append( AlarmkeySetBase(re.split(r'/|\\', b)[-1], json.load(open(b, 'r')), settype="integrated")) for b in glob.glob("{}alarmkeysetbase/*.json".format( current_app.config.get('PATH_DATA'))): ret.append( AlarmkeySetBase(re.split(r'/|\\', b)[-1], json.load(open(b, 'r')), settype="external")) if basename != "": return filter(lambda x: basename == x.id, ret) return ret
class AlarmField(db.Model): __version__ = '0.1' __tablename__ = 'alarmfields' __table_args__ = {'extend_existing': True} id = db.Column(db.Integer, primary_key=True) fieldtype = db.Column('type', db.String(32)) name = db.Column(db.String(64)) _parameters = db.Column('parameters', db.Text) dept = db.Column('dept', db.Integer, db.ForeignKey('departments.id')) position = db.Column(db.Integer) department = db.relationship( "Department", collection_class=attribute_mapped_collection('id')) @property def hasEditForm(self): return True @declared_attr def __mapper_args__(self): return { 'polymorphic_on': self.fieldtype, 'polymorphic_identity': self.__name__ } def __init__(self, name, dept, parameters, position): self.fieldtype = self.__class__.__name__ if self.fieldtype == name: # translate if classname an name are same name = babel.gettext(name) self.name = name self.dept = dept self._parameters = yaml.safe_dump(parameters, encoding='utf-8') self.position = position def __repr__(self): return '{} - {}'.format(self.__class__.__name__, self.id) @property def parameters(self): return yaml.load(self._parameters) @parameters.setter def parameters(self, params): self._parameters = yaml.safe_dump(params, encoding='utf-8') def getFields(self, **params): return [] def getFieldValue(self, fieldname, alarm): if fieldname.startswith('alarm.'): return ">>", alarm.get(fieldname.split('.')[1]) # TODO return None def getExportFields(self): return [] def configForm(self, dept=0): return render_template('fields/field.config_{}.html'.format( self.fieldtype.lower()), field=self, dept=dept) def editForm(self, alarm): try: return render_template('fields/field.edit_{}.html'.format( self.fieldtype.lower()), field=self, alarm=alarm) except TemplateNotFound: return "" def saveForm(self, request, alarm): pass def renderField(self, alarm, **params): try: return render_template('fields/field.render_{}.html'.format( self.fieldtype.lower()), field=self, alarm=alarm, params=params) except: pass @staticmethod def getAlarmFields(id=0, dept=0, fieldtype=""): if id != 0: return AlarmField.query.filter_by(id=id).first() elif dept != 0: return AlarmField.query.filter( AlarmField.dept == dept).order_by('position').all() elif fieldtype != "": return AlarmField.query.filter( AlarmField.fieldtype == fieldtype).first() else: return AlarmField.query.order_by('name').all() @staticmethod def getAlarmFieldsDict(): return dict(map(lambda x: [x.id, [x]], AlarmField.query.all())) @staticmethod def getAlarmFieldsForDepartment(dept): ret = [] for field in AlarmField.getAlarmFields(dept=dept): ret.append(field) i = 0 for name, cls in inspect.getmembers(sys.modules[__name__]): if inspect.isclass(cls) and len( cls.__bases__ ) > 0 and cls.__bases__[0].__name__ == 'AlarmField': if len(filter(lambda c: c.__class__.__name__ == name, ret)) == 0: ret.append(cls(name, dept, [], i)) i += 1 return ret @staticmethod def getAlarmFieldForType(fieldtype, dept=0): for name, cls in inspect.getmembers(sys.modules[__name__]): if inspect.isclass(cls) and cls.__name__ == fieldtype: position = 0 dbFields = AlarmField.getAlarmFieldsDict() if int(dept) in dbFields.keys(): position = len(dbFields[int(dept)]) return cls(cls.__name__, int(dept), {}, position)
class Monitor(db.Model): """Monitor class""" __tablename__ = 'monitors' __table_args__ = {'extend_existing': True} id = db.Column(db.Integer, primary_key=True) clientid = db.Column(db.Integer) name = db.Column(db.String(30)) orientation = db.Column(db.Integer, default=0) resolutionx = db.Column(db.Integer, default=0) resolutiony = db.Column(db.Integer, default=0) formatx = db.Column(db.Integer, default=0) formaty = db.Column(db.Integer, default=0) layouts = db.relationship( "MonitorLayout", collection_class=attribute_mapped_collection('id'), cascade="all, delete-orphan") def _get_current_layout(self): from emonitor.monitorserver import MonitorLog layoutid = 0 def findid(clientid): for ml in MonitorLog.getLogForClient(clientid): if ml.type == 'change layout': for p in ml.operation.split(';'): if p.startswith('layoutid='): return int(p.replace('layoutid=', '')) layoutid = findid(self.clientid) try: if layoutid > 0: return filter(lambda l: l.id == layoutid, self.layouts.values())[0] else: # return defaultlayout return filter(lambda l: l.trigger == 'default', self.layouts.values())[0] except: ml = MonitorLayout(self.id, 'default', '--', '', 0, 0, 0) ml.theme = ml.themes[0] return ml currentlayout = property(_get_current_layout) def __repr__(self): return '<Monitor %r>' % self.clientid def __init__(self, clientid, name, orientation, resolutionx, resolutiony, formatx, formaty): self.clientid = clientid self.name = name self.orientation = orientation self.resolutionx = resolutionx self.resolutiony = resolutiony self.formatx = formatx self.formaty = formaty def layout(self, layoutid): """ Get MonitorLayout for given id :param layoutid: id as integer :return: :py:class:`emonitor.modules.monitors.monitorlayout.MonitorLayout` """ l = MonitorLayout.getLayouts(id=int(layoutid)) if l: return l else: # deliver default layout return self.currentlayout def getLayouts(self, triggername=""): """ Get list of all MonitorLayouts defined for *triggername* or all :param optional triggername: triggername as filter :return: list of :py:class:`emonitor.modules.monitors.monitorlayout.MonitorLayout` """ if triggername == "": return sorted(self.layouts.values()) elif triggername != "": return filter(lambda x: x.trigger.startswith(triggername), sorted(self.layouts.values())) @staticmethod def getMonitors(id=0, clientid=0): """ Get list of monitor definitions filtered by parameters :param optional id: :param optional clientid: :return: list of :py:class:`emonitor.modules.monitors.monitor.Monitor` """ if id != 0: return Monitor.query.filter_by(id=id).first() elif clientid != 0: return Monitor.query.filter_by(clientid=clientid).first() else: return Monitor.query.order_by('clientid').all() @staticmethod def handleEvent(eventname, **kwargs): return kwargs
class Printers(db.Model): """Printers class""" __tablename__ = 'printers' __table_args__ = {'extend_existing': True} id = db.Column(db.Integer, primary_key=True) name = db.Column(db.String(64)) printer = db.Column(db.String(64)) module = db.Column(db.String(64)) layout = db.Column(db.String(64)) _settings = db.Column('settings', db.Text) state = db.Column(db.INTEGER) def __init__(self, name, printer, module, layout, settings="", state=0): self.name = name self.printer = printer self.module = module self.layout = layout self._settings = settings self.state = state @property def settings(self): return yaml.load(self._settings) @settings.setter def settings(self, val): self._settings = yaml.safe_dump(val, encoding='utf-8') def getCallString(self, pdffilename="", **params): # get formated callstring from emonitor import app callstring = Settings.get('printer.callstring') callstring = callstring.replace('[basepath]', app.config.get('PROJECT_ROOT')) if self.printer == '<default>': # use default printer callstring = callstring.replace('-printer [printer]', '') else: if 'printer' in params: callstring = callstring.replace( '[printer]', '"{}"'.format(params['printer'])) else: callstring = callstring.replace('[printer]', '"{}"'.format(self.printer)) try: if 'copies' in params: callstring = callstring.replace('[copies]', "{}".format(params['copies'])) else: callstring = callstring.replace('[copies]', self.settings[0]) except IndexError: callstring = callstring.replace('[copies]', '1') callstring = callstring.replace('[filename]', pdffilename) return callstring def doPrint(self, **params): """ Start printout of defined object :param params: checks for *alarmid* """ from emonitor import app ctx = app.test_request_context('/') # add dummy request ctx.push() pl = PrintLayout('{}.{}'.format(self.module, self.layout)) _params = {} for p in pl.getParameters(self.settings[1].split( ';')): # load parameters from printer definition _params[p.getFullName()] = p.getFormatedValue() tmpfilename = next(tempfile._get_candidate_names()) callstring = self.getCallString(pdffilename='{}{}.pdf'.format( app.config.get('PATH_TMP'), tmpfilename), **params) if "id" in params: with app.test_request_context('/', method='get'): with open( '{}{}.pdf'.format(app.config.get('PATH_TMP'), tmpfilename), 'wb') as tmpfile: _params['id'] = params['id'] _params['style'] = self.layout[6:-5] tmpfile.write( Module.getPdf(params['object'].getExportData( '.html', **_params))) try: with open( '{}{}.pdf'.format(app.config.get('PATH_TMP'), tmpfilename), 'wb') as tmpfile: _params['id'] = params['id'] _params['style'] = self.layout[6:-5] tmpfile.write( Module.getPdf(params['object'].getExportData( '.html', **_params))) subprocess.check_output(callstring, stderr=subprocess.STDOUT, shell=True) os.remove('{}{}.pdf'.format(app.config.get('PATH_TMP'), tmpfilename)) except WindowsError: pass @staticmethod def handleEvent(eventname, **kwargs): """ Event handler for printer class, adds own processing time :param eventname: *emonitor.modules.printers.printers.Printers* :param kwargs: *mode*=*test*, *time*, :return: kwargs """ stime = time.time() _printer = None hdl = [ hdl for hdl in Eventhandler.getEventhandlers(event=eventname) if hdl.handler == 'emonitor.modules.printers.printers.Printers' ][0] if hdl: for p in hdl.getParameterValues('in'): if p[0] == 'in.printerid': _printer = Printers.getPrinters(p[1]) break state = "" if _printer: try: if kwargs['mode'] != 'test': if '{}id'.format(_printer.module[:-1]) in kwargs.keys( ): # add object and id if given kwargs['id'] = kwargs['{}id'.format( _printer.module[:-1])] for key, cls in db.Model._decl_class_registry.iteritems( ): if key.lower() == _printer.module[:-1]: kwargs['object'] = cls break _printer.doPrint(**dict(kwargs)) else: state = "(testmode)" except KeyError: state = "with errors" else: state = "with error 'no printer found'" if 'time' not in kwargs.keys(): kwargs['time'] = [] kwargs['time'].append(u"printer: print done {} in {} sec.".format( state, time.time() - stime)) return kwargs @staticmethod def getPrinters(pid=0): """ Get list of printers definitions filtered by parameters :param pid: id of printerdefinition or *0* for all definitions :return: list of :py:class:`emonitor.modules.printers.printers.Printers` """ if pid == 0: return Printers.query.all() else: return Printers.query.filter_by(id=int(pid)).first() @staticmethod def getActivePrintersOfModule(module): """ Get list of active definitions for given modulename :param module: modulename :return: list of :py:class:`emonitor.modules.printers.printers.Printers` """ return Printers.query.filter( and_(Printers.module == module, Printers.state == '1')).all()
class AlarmType(db.Model): """AlarmType class""" __tablename__ = 'alarmtypes' __table_args__ = {'extend_existing': True} id = db.Column(db.Integer, primary_key=True) name = db.Column(db.String(32)) keywords = db.Column(db.Text, default='') interpreter = db.Column(db.String(64)) sections = db.relationship( "AlarmSection", collection_class=attribute_mapped_collection('id'), cascade="all, delete-orphan") _translations = db.Column('translations', db.Text) _attributes = db.Column('attributes', db.Text) def __repr__(self): return self.name def __init__(self, name, interpreter, keywords='', translations='', attributes=''): self.name = name self.keywords = keywords self.interpreter = interpreter self._translations = translations self._attributes = attributes @staticmethod def buildFromConfigFile(cfile): """ create alarmtype from ini file definition :param cfile: :return: alarmtype """ from emonitor.modules.alarms.alarmsection import AlarmSection _cfg = ConfigParser.ConfigParser() _cfg.readfp(cfile) if not _cfg.has_section('global'): # global section needed return None else: if 'name' not in _cfg.options( 'global') or 'class' not in _cfg.options('global'): return None alarmtype = AlarmType(_cfg.get('global', 'name'), _cfg.get('global', 'class')) alarmtype.keywords = _cfg.get('global', 'keywords').replace(u';', u'\r\n') t = {} for _k, _v in yaml.safe_load(_cfg.get('global', 'translations')).items(): t[_k.strip()] = _v.strip().encode('utf-8') alarmtype.translations = t t = {} for item in [ i for i in _cfg.items('global') if i[0] not in ['keywords', 'name', 'class', 'translations'] ]: t[item[0]] = item[1] alarmtype.attributes = t for section in _cfg.sections(): if section != 'global': # global parameters if 'name' not in _cfg.options( section): # required attribute name missing in section return None _params = {} for p in [ param for param in _cfg.options(section) if param not in ['name', 'method'] ]: _params[p] = _cfg.get(section, p) if 'method' in [k[0] for k in _cfg.items(section)]: _method = _cfg.get(section, 'method') else: _method = "" alarmtype.sections[_cfg.sections().index( section)] = AlarmSection( alarmtype.id, _cfg.get(section, 'name').decode('utf-8'), section, 1, _method, _cfg.sections().index(section), attributes=yaml.safe_dump(_params, encoding="utf-8")) return alarmtype def getConfigFile(self): """ build config file from type definition in database :return: string in .ini format with [global] and fields as section """ class MyConfigParser(ConfigParser.ConfigParser): def getStr(self): """Write an .ini-format string representation of the configuration state.""" ret = [] if self._defaults: ret.append(u"[DEFAULT]") for (key, value) in self._defaults.items(): ret.append(u"{} = {}s".format( key, str(value).replace('\n', '\n\t'))) ret.append("\n") for _section in self._sections: ret.append(u"\n[{}]".format(_section)) for (key, value) in self._sections[_section].items(): if key == "__name__": continue if (value is not None) or (self._optcre == self.OPTCRE): key = u" = ".join( (key, value.replace(u'\n', u'\n\t'))) ret.append(u"{}".format(key)) return u'\n'.join(ret) if self.interpreterclass( ).configtype == 'generic': # only regex parsers use config file _cfg = MyConfigParser() _cfg.add_section('global') _cfg.set('global', 'class', self.interpreter) _cfg.set('global', 'keywords', self.keywords.replace('\r\n', ';')) _cfg.set('global', 'translations', yaml.safe_dump(self.translations, encoding="utf-8")) _cfg.set('global', 'name', self.name) for k, v in self.attributes.items(): _cfg.set('global', k, v) for section in [s for s in self.getSections() if s.active]: _cfg.add_section(section.key) _cfg.set(section.key, 'name', section.name) if section.method: _cfg.set(section.key, 'method', section.method) for _k, _v in section.attributes.items(): _cfg.set(section.key, _k, _v) return _cfg.getStr() else: return "" @property def translations(self): return yaml.load(self._translations) or {} @translations.setter def translations(self, values): self._translations = yaml.safe_dump(values, encoding='utf-8') @property def attributes(self): """ getter for attributes :return: dict with type attributes """ return yaml.load(self._attributes) or {} @attributes.setter def attributes(self, values): """ setter for type attributes :param values: digt with key-value pairs """ self._attributes = yaml.safe_dump(values, encoding='utf-8') def interpreterclass(self): """ Get type interpreter class from directory *emonitor/modules/alarms/inc/* :return: interpreterlass as instance :py:class:`emonitor.modules.alarms.alarmutils.AlarmFaxChecker` """ if self.interpreter: cls = imp.load_source( 'emonitor.modules.alarms.inc', 'emonitor/modules/alarms/inc/%s' % self.interpreter) return getattr(cls, cls.__all__[0])() return None def interpreterStrings(self): """ Get list of needed string for interpreter class :return: list of strings """ if self.interpreterclass(): return sorted( self.interpreterclass().getDefaultConfig()['translations']) return [] def translation(self, name): if name in self.translations: return self.translations[name] return "" def getSections(self): """ Get sorted list of possible sections of :py:class:`emonitor.modules.alarms.alarmtype.AlarmType` :return: list of :py:class:`emonitor.modules.alarms.alarmsection.AlarmSection` """ return sorted(self.sections.values()) @staticmethod def getVariables(): return Settings.get('alarms.evalfields').split('\r\n') @staticmethod def getAlarmTypes(id=0): """ Get list of alarm type objects filtered by parameter :param optional id: id of alarm type or 0 for all types :return: list of single object :py:class:`emonitor.modules.alarms.alarmtype.AlarmType` """ if id != 0: return AlarmType.query.filter_by(id=id).first() else: return AlarmType.query.order_by('id').all() @staticmethod def getAlarmTypeByClassname(name): """ Get list of all alarm types by given class name :param name: name of interpreter class :return: list of :py:class:`emonitor.modules.alarms.alarmtype.AlarmType` """ return AlarmType.query.filter_by(interpreter=name).all() or [] @staticmethod def handleEvent(eventname, **kwargs): """ Eventhandler for alarm type class: do type detection :param eventname: :param kwargs: :return: """ stime = time.time() if 'text' in kwargs.keys(): text = kwargs['text'] atype = None for alarmtype in AlarmType.getAlarmTypes(): for kw in alarmtype.keywords.split('\n'): if kw in text: atype = alarmtype break kwargs['type'] = 0 if atype: kwargs['type'] = atype.id if 'time' not in kwargs.keys(): kwargs['time'] = [] kwargs['time'].append( 'alarmtype: alarmtype detection done in %s sec.' % (time.time() - stime)) return kwargs
class Car(db.Model): """Car class""" __tablename__ = 'cars' __table_args__ = {'extend_existing': True} id = db.Column(db.Integer, primary_key=True) name = db.Column(db.String(64)) description = db.Column(db.Text) fmsid = db.Column(db.String(8)) active = db.Column(db.Integer) type = db.Column(db.Text) _dept = db.Column('dept', db.ForeignKey('departments.id')) dept = db.relationship("Department", collection_class=attribute_mapped_collection('id')) def __init__(self, name, description, fmsid, active, type, dept): self.name = name self.description = description self.fmsid = fmsid self.active = active self.type = type self._dept = dept def getColor(self): """ Get color of car, default *#ffffff* :return: colorcode """ for t in Settings.getCarTypes(): if t[0] == self.type: return t[1] return "#ffffff" def __str__(self): return self.name @staticmethod def getCars(id=0, deptid=0, params=[]): """ Get list of cars filtered by given parameters :param optional id: id of car or 0 for all cars :param optional deptid: only cars of department with given id :param optional params: *onlyactive* :return: list of :py:class:`emonitor.modules.cars.car.Car` """ if id != 0: return Car.query.filter_by(id=int(id)).first() elif int(deptid) != 0: return Car.query.filter_by( _dept=int(deptid)).order_by('name').all() else: if 'onlyactive' in params: return Car.query.filter_by(active=1).order_by('dept', 'name').all() else: return Car.query.order_by('dept', 'name').all() @staticmethod def getCarsDict(): """ Get dict of cars, id as key :return: dict with :py:class:`emonitor.modules.cars.car.Car` """ ret = {} for car in Car.getCars(): ret[car.id] = car return ret
class MapItem(db.Model): """MapItems class""" __tablename__ = "mapitems" __table_args__ = {'extend_existing': True} URL = 'http://overpass-api.de/api/interpreter' id = db.Column(db.Integer, primary_key=True) osmid = db.Column(db.BigInteger) itemtype = db.Column(db.String(32)) _parameters = db.Column('parameter', db.Text) def __init__(self, itemtype, osmid, parameters): self.itemtype = itemtype self.osmid = osmid if type(parameters) == dict: self._parameters = yaml.safe_dump(parameters, encoding='utf-8') else: self._parameters = parameters @property def parameters(self): return yaml.load(self._parameters) @parameters.setter def parameters(self, val): if type(val) == dict: self._parameters = yaml.safe_dump(val, encoding='utf-8') else: self._parameters = val @staticmethod def getitemtypes(): # TODO deprecated return MapItem.itemtype.query.distinct().all() @staticmethod def getMapitems(itemtype='', osmid=0): if itemtype == '' and osmid == 0: return MapItem.query.all() elif osmid == 0: return MapItem.query.filter_by(itemtype='%s' % itemtype).all() elif itemtype == '': return MapItem.query.filter_by(osmid='%s' % osmid).first() @staticmethod def loadFromOSM(itemtype, city): SEARCHSTRING = 'area["name"="%s"];%s(area)%s;(._;>;);out;' % ( city, itemtype['itemtype'], itemtype['filter'] ) # search all objects r = requests.post(MapItem.URL, data={'data': SEARCHSTRING}) xmldoc = minidom.parseString(r._content) items = [] if itemtype['itemtype'] == 'node': for node in xmldoc.getElementsByTagName('node'): data = {} for attr in [ a for a in node.attributes.keys() if a in itemtype['attributes'] ]: data[attr] = node.attributes[attr].value for c in node.childNodes: if c.nodeType == minidom.Node.ELEMENT_NODE: _t = '' for attr in c.attributes.keys(): if attr == 'k' and c.attributes[ attr].value in itemtype['attributes']: _t = c.attributes[attr].value elif attr == 'v' and _t != '': data[_t] = c.attributes[attr].value items.append(data) elif itemtype['itemtype'] == 'way': nodes = {} for node in xmldoc.getElementsByTagName('node'): # get nodes nodes[node.attributes['id'].value] = {} for attr in [ a for a in node.attributes.keys() if a in itemtype['attributes'] ]: nodes[node.attributes['id']. value][attr] = node.attributes[attr].value for way in xmldoc.getElementsByTagName( 'way'): # build ways from nodes i = dict(id=way.attributes['id'].value, nodes=[]) for p in [p for p in way.childNodes if p.nodeName == 'nd']: i['nodes'].append(nodes[p.attributes['ref'].value]) items.append(i) return items @staticmethod def getLayouters(): # get all layouters ret = [] for f in [ f for f in os.listdir('%s/emonitor/modules/mapitems/inc/' % current_app.config.get('PROJECT_ROOT')) if f.endswith('.py') and f.startswith('layout_') ]: cls = imp.load_source('emonitor.modules.mapitems.inc', 'emonitor/modules/mapitems/inc/%s' % f) layouter = getattr(cls, cls.__all__[0])() if isinstance(layouter, ItemLayout): ret.append(layouter) return ret @staticmethod def _buildTiles(items, definition): # build tiles with layouter for layouter in MapItem.getLayouters(): if layouter.getName() == definition['parameters']['layout']: layouter.buildTiles(items, definition['attributes']) break
class City(db.Model): """City class""" __tablename__ = 'cities' __table_args__ = {'extend_existing': True} id = db.Column(db.Integer, primary_key=True) name = db.Column(db.String(30)) dept = db.Column('dept', db.Integer, db.ForeignKey('departments.id')) mapname = db.Column(db.String(30)) default = db.Column(db.Integer) subcity = db.Column(db.Text) color = db.Column(db.String(6), default="000000") osmid = db.Column(db.Integer, default=0) osmname = db.Column(db.String(30), default="") streets = db.relationship("Street", collection_class=attribute_mapped_collection('id'), backref=db.backref('City', remote_side=[Street.cityid]), cascade="all, delete-orphan") department = db.relationship("Department", collection_class=attribute_mapped_collection('id')) def __init__(self, name, dept, mapname, default, subcity, color, osmid, osmname): self.name = name self.dept = dept self.mapname = mapname self.default = default self.subcity = subcity self.color = color self.osmid = osmid self.osmname = osmname @property def serialize(self): return dict(id=self.id, name=self.name) @property def subcities(self): return filter(None, self.subcity.split("\r\n")) def getColorName(self): return '#%s' % self.color def __repr__(self): return '<City %r>' % self.name def addStreet(self, street): """ Add street to current city :param street: :py:class:`emonitor.modules.streeets.street.Street` """ #cache.delete_memoized('getStreets', self) if street.id in self.streets: self.streets[street.id] = street else: self.streets[street.id] = street db.session.commit() # static part @staticmethod def getCities(id=0): """ Get list of all cities :return: list of :py:class:`emonitor.modules.streets.city.City` """ if id == 0: return City.query.order_by(City.default.desc(), City.name).all() else: return City.query.filter_by(id=id).first() @staticmethod def getCitiesDict(): """ Get cities as dict :return: dict of :py:class:`emonitor.modules.streets.city.City`, id as key """ ret = dict(db.get(City.id, City).order_by(City.id)) ret[0] = City.getDefaultCity() return ret @staticmethod def getDefaultCity(): """ Get default city (default=1) :return: :py:class:`emonitor.modules.streets.city.City` """ return City.query.filter_by(default=1).first()
class Department(db.Model): """Department class""" __tablename__ = 'departments' __table_args__ = {'extend_existing': True} id = db.Column(db.Integer, primary_key=True) name = db.Column(db.String(64)) shortname = db.Column(db.String(10)) color = db.Column(db.String(7)) orderpos = db.Column(db.Integer) defaultcity = db.Column( db.Integer) # id of default city for this department _attributes = db.Column('attributes', db.Text) def _get_city(self): from emonitor.modules.streets.city import City return City.getCities(self.defaultcity) city = property(_get_city) cars = db.relationship("Car", collection_class=attribute_mapped_collection('id'), cascade="all, delete-orphan") def __init__(self, name, shortname, color, orderpos, defaultcity=0, attributes={}): self.name = name self.shortname = shortname self.color = color self.orderpos = orderpos self.defaultcity = defaultcity self._attributes = yaml.safe_dump(attributes, encoding='utf-8') def __getattr__(self, name, default=''): if name in self.attributes: return self.attributes[name] else: return default @property def attributes(self): return yaml.load(self._attributes) @attributes.setter def attributes(self, attrs): self._attributes = yaml.safe_dump(attrs, encoding='utf-8') def set(self, name, value): attrs = self.attributes attrs[name] = value self.attributes = attrs def getCars(self): return sorted(self.cars.values(), key=lambda car: car.name) def getLogoStream(self): """ Deliver logo file as stream, base 64 encoded :return: base 64 stream or empty string """ from emonitor import app if self.attributes.get('logo', '') != '' and os.path.exists( '{}{}'.format(app.config.get('PATH_DATA'), self.attributes.get('logo', ''))): return open( '{}{}'.format(app.config.get('PATH_DATA'), self.attributes.get('logo', '')), 'rb').read().encode("base64") else: return open( '{}/emonitor/frontend/web/img/empty.png'.format( app.config.get('PROJECT_ROOT')), 'rb').read().encode("base64") @staticmethod def getDefaultDepartment(): """Get default department :py:class:`emonitor.modules.settings.department.Department`""" return Department.query.order_by('orderpos').first() @staticmethod def getDepartments(id=0): """ Get department list filtered by criteria :param optional id: id of department, *0* for all :return: list of :py:class:`emonitor.modules.settings.department.Department` """ if id == 0: return Department.query.order_by('orderpos').all() else: return Department.query.filter_by(id=id).first() @staticmethod def getDeptsDict(): """ Get departements as dict :return: dict of :py:class:`emonitor.modules.settings.department.Department` """ ret = {} for dept in Department.query.order_by('orderpos'): ret[dept.orderpos] = (dept.name, dept.color) return ret
class Settings(db.Model): """Settings class""" __tablename__ = 'settings' __table_args__ = {'extend_existing': True} id = db.Column(db.Integer, primary_key=True) name = db.Column(db.String(64)) _value = db.Column('value', db.Text) def __init__(self, name, value=""): self.name = name self._value = value @property def value(self): return yaml.load(self._value) @value.setter def value(self, val): self._value = yaml.safe_dump(val, encoding='utf-8') @staticmethod def num2deg(xtile, ytile, zoom=17 or db.config.get('DEFAULTZOOM')): """ Translate tile into coordinate (lat, lon) :param xtile: x-coordinate of tile :param ytile: y-coordinate of tile :param zoom: zoom level :return: lat, lon tuple """ n = 2.0**zoom lon_deg = xtile / n * 360.0 - 180.0 lat_deg = math.degrees( math.atan(math.sinh(math.pi * (1 - 2 * ytile / n)))) return lat_deg, lon_deg def getCarTypeNames(self): return self.value @staticmethod def getCarTypes(): ctypes = Settings.query.filter_by(name='cartypes') if ctypes.count(): return ctypes.one().value return "" @staticmethod def get_byType(type): return Settings.query.filter_by(name=type).first() or "" @staticmethod def getMapTiles(mid=0, zoom=17 or db.app.config.get('DEFAULTZOOM')): from emonitor.modules.maps.map import Map _map = Map.getMaps(mid) tiles = [] try: for ts in [ f for f in os.listdir(_map.path + str(zoom) + '/') if f.endswith('png') ]: tiles.append(ts.replace('-', '/')) except: pass return tiles @staticmethod def getFrontendSettings(area=""): s = Settings.query.filter_by(name='frontend.default') if s.count() == 1: if area == "": return s.first().value elif area in s.first().value.keys(): return s.first().value[area] return { 'module': 'default', 'width': '.2', 'visible': '0', 'center': { 'module': 'default' }, 'west': { 'module': 'default', 'width': '.2' }, 'east': { 'module': 'default', 'width': '.2' } } @staticmethod def get(option, default=''): """ Getter for option values :param option: name as string :param optional default: default value if not found in database :return: value of option """ s = Settings.query.filter_by(name=option) if s.count() == 1: # update return s.first().value return default # deliver default value @staticmethod def set(option, val): """ Setter for option :param option: name as string :param val: value of option :return: value of option """ s = Settings.query.filter_by(name=option).first() if s: # update settings s.value = val else: # add value s = Settings(option, yaml.safe_dump(val, encoding='utf-8')) db.session.add(s) db.session.commit() return s @staticmethod def getIntList(option, default=[]): try: return map(int, Settings.get(option, '').split(',')) except ValueError: return default @staticmethod def getYaml(option): try: return Struct(**(Settings.get(option))) except TypeError: return Struct()
class Eventhandler(db.Model): """Eventhandler class""" __tablename__ = 'eventhandlers' __table_args__ = {'extend_existing': True} id = db.Column(db.Integer, primary_key=True) event = db.Column(db.String(32)) handler = db.Column(db.String(64)) position = db.Column(db.Integer, default=0) parameters = db.Column(db.Text, default="") def __init__(self, event, handler, position, parameters): self.event = event self.handler = handler self.position = position self.parameters = parameters def getParameterValue(self, parameter): """ Get parameter value of given parameter :param parameter: name of parameter as string :return: value of parameter, '' if not found """ for p in self.parameters.split("\r\n"): if p.startswith(parameter + "="): return p.split('=')[-1] return "" def getParameterList(self, t='out'): """ Get list of parameter names :param optional t: type of parameters (default *out*) :return: list of parameter names """ return [ param.split('=')[0] for param in self.parameters.split('\r\n') if param.startswith(t + '.') ] def getParameterValues(self, t='out'): """ Get list of parameter values :param optional t: type of parameters (default *out*) :return: list of all values """ return [ param.split('=') for param in self.parameters.split('\r\n') if param.startswith(t + '.') ] def getInParameters(self): """ Get list of all input-parameters of eventhandler :return: handler list """ event = events.getEvents(self.event) if self.position < 2: return event.parameters elif self.position == '': if len(event.getHandlers()) > 0: hdl = event.getHandlers()[-1] return hdl.getParameterList( ) + event.parameters # add event parameters else: return [] else: for hdl in event.getHandlers(): if hdl.position == self.position - 1: #return [param.split('=')[0] for param in hdl.parameters.split('\r\n') if param.startswith('out.')] return hdl.getParameterList( ) + event.parameters # add event parameters return [] @property def serialize(self): """Return object data in easily serializeable format""" return { 'id': self.id, 'event': self.event, 'handler': self.handler, 'position': self.position, 'parameters': self.parameters } @staticmethod def getEventhandlers(id="", event=""): """ Get list of eventhandlers stored in database :param optional id: id of eventhander or 0 for all eventhandlers :param optional event: name of event :return: list or single object :py:class:`emonitor.modules.events.eventhandler.Eventhandler` """ if id != '': return Eventhandler.query.filter_by(id=id).first() elif event != '': return Eventhandler.query.filter_by( event=event).order_by('position').all() else: return Eventhandler.query.order_by('event', 'position').all()
class AlarmObjectFile(db.Model): """Files for alarmobjects""" __tablename__ = 'alarmobjectfile' __table_args__ = {'extend_existing': True} id = db.Column(db.Integer, primary_key=True) object_id = db.Column(db.Integer, db.ForeignKey('alarmobjects.id')) filename = db.Column(db.String(80)) filetype = db.Column(db.String(50)) def __repr__(self): return "<alarmobjectfile %s>" % self.filename def __init__(self, objectid, filename, filetype): self.object_id = objectid self.filename = filename self.filetype = filetype @property def filesize(self): def sizeof_fmt(num): for x in ['bytes', 'KB', 'MB', 'GB', 'TB']: if num < 1024.0: return "%3.1f %s" % (num, x) num /= 1024.0 if os.path.exists('%salarmobjects/%s/%s' % (current_app.config.get('PATH_DATA'), self.object_id, self.filename)): return sizeof_fmt( os.stat('%salarmobjects/%s/%s' % (current_app.config.get('PATH_DATA'), self.object_id, self.filename)).st_size) return sizeof_fmt(0) @staticmethod def getFile(id, filename=""): """ Get file(s) for alarmobject :param id: objectid as integer :param filename: filename as string :return: :py:class:`emonitor.modules.alarmobjects.alarmobjectfile.AlarmObjectFile` """ if filename == "": return AlarmObjectFile.query.filter_by(id=id).first() else: return AlarmObjectFile.query.filter_by(object_id=id, filename=filename).first() @staticmethod def getAlarmObjectTypes(objectid=0): """ Get all possible alarmobject types :param objectid: objectid as integer :return: list of :py:mod:`emonitor.modules.alarmobjects.alarmobjectfile.AlarmObjectFile` """ if objectid != 0: return AlarmObjectFile.query.filter_by(id=objectid).all() else: return AlarmObjectFile.query.order_by( collate(AlarmObjectFile.name, 'NOCASE')).all()
class AlarmkeyCars(db.Model): """AlarmkeyCars class""" __tablename__ = 'alarmkeycars' __table_args__ = {'extend_existing': True} kid = db.Column(db.Integer, primary_key=True) dept = db.Column(db.String(30), primary_key=True) _cars1 = db.Column('cars1', db.String(100), default='') _cars2 = db.Column('cars2', db.String(100), default='') _material = db.Column('material', db.String(100), default='') def _get_cars_proto(self, cartype): # type 1:cars1, 2:cars2, 3:material ret = [] l = [] cars = Car.getCars() try: if cartype == 1: l = [int(i) for i in self._cars1.split(';') if i != ''] elif cartype == 2: l = [int(i) for i in self._cars2.split(';') if i != ''] elif cartype == 3: l = [int(i) for i in self._material.split(';') if i != ''] except: l = [] for c_id in l: c = filter(lambda c: c.id == c_id, cars) if len(c) == 1: ret.append(c[0]) return ret # cars1 def _get_cars1(self): return self._get_cars_proto(1) def _set_cars1(self, cars): self._cars1 = cars def _get_cars1id(self): return [int(i) for i in self._cars1.split(';') if i != ''] # cars2 def _get_cars2(self): return self._get_cars_proto(2) def _set_cars2(self, cars): self._cars2 = cars def _get_cars2id(self): return [int(i) for i in self._cars2.split(';') if i != ''] # material def _get_material(self): return self._get_cars_proto(3) def _set_material(self, material): self._material = material def _get_materialid(self): return [int(i) for i in self.material.split(';') if i != ''] car1id = property(_get_cars1id) cars1 = property(_get_cars1, _set_cars1) car2id = property(_get_cars2id) cars2 = property(_get_cars2, _set_cars2) materialid = property(_get_materialid) materials = property(_get_material, _set_material) def __init__(self, kid, dept, cars1, cars2, material): self.kid = kid self.dept = dept self._cars1 = cars1 self._cars2 = cars2 self._material = material acc = AlarmkeyCars.getAlarmkeyCars(0, dept=dept) if acc: self.defaultcars1 = acc.cars1 self.defaultcars2 = acc.cars2 self.defaultmaterial = acc.materials else: self.defaultcars1 = [] self.defaultcars2 = [] self.defaultmaterial = [] @staticmethod def getAlarmkeyCars(kid=9999, dept=''): """ Get a list of all car objects with given parameters :param kid: (optional) id of alarmkey, default = *9999* :param dept: (optional) id of department, default = *''* :return: list of :py:class:`emonitor.modules.alarmkeys.alarmkeycar.AlarmkeyCars` """ if int(kid) != 9999 and dept != '': return AlarmkeyCars.query.filter_by(kid=int(kid), dept=int(dept)).first() elif int(kid) == 9999 and dept != '': # default aao cars for dept return AlarmkeyCars.query.filter_by(kid=int(kid), dept=int(dept)).first() elif dept != '': return AlarmkeyCars.query.filter_by(dept=int(dept)).all() else: return AlarmkeyCars.query.filter_by(kid=int(kid)).all()
class Alarm(db.Model): """Alarm class""" __tablename__ = 'alarms' __table_args__ = {'extend_existing': True} ALARMSTATES = {'0': 'created', '1': 'active', '2': 'done'} """ - 0: alarm *created* - 1: alarm *active* - 2: alarm *done* - 3: alarm *archived* (not in list, only for admin area) """ ALARMTYPES = {'1': 'fax', '2': 'manual'} """ - 1: alarm by *fax* created - 2: alarm *manual* created """ ROUTEURL = "http://www.yournavigation.org/api/1.0/gosmore.php" """ URL for routing webservice """ id = db.Column(db.Integer, primary_key=True) timestamp = db.Column(db.DATETIME) _key = db.Column('key', db.Text) type = db.Column(db.Integer, default=0) state = db.Column(db.Integer, default=0) attributes = db.relationship("AlarmAttribute", collection_class=attribute_mapped_collection('name'), cascade="all, delete-orphan") history = db.relationship(AlarmHistory.__name__, backref="alarms", lazy='joined', cascade="all, delete-orphan") # additional properties defined in alarmutils endtimestamp = property(alarmutils.get_endtimestamp) cars1 = property(alarmutils.get_cars1) cars2 = property(alarmutils.get_cars2) material = property(alarmutils.get_material, alarmutils.set_material) city = property(alarmutils.get_city, alarmutils.set_city) key = property(alarmutils.get_key) street = property(alarmutils.get_street, alarmutils.set_street) street2 = property(alarmutils.get_street2) streetno = property(alarmutils.get_streetno) housenumber = property(alarmutils.get_housenumber) object = property(alarmutils.get_object, alarmutils.set_object) person = property(alarmutils.get_person) priority = property(alarmutils.get_priority) remark = property(alarmutils.get_remark) lat = property(alarmutils.get_lat) lng = property(alarmutils.get_lng) zoom = property(alarmutils.get_zoom) position = property(alarmutils.get_position, alarmutils.set_position) marker = property(alarmutils.get_marker) def __init__(self, timestamp, key, type, state): self.timestamp = timestamp self._key = key self.type = type # 1:automatic/fax, 2: manual self.state = state # 1: active, 0:created, 2:done, 3:archived def get(self, attrname, default=''): """ Getter for attribute names :param attrname: name of attribute :param optional default: deliver default value if not stored in database :return: value of attribute """ if attrname in self.attributes: return self.attributes[attrname].value return default def set(self, attrname, value): """ Setter for attributes :param attrname: attribute name :param value: value """ if attrname in self.attributes: self.attributes[attrname].value = value else: self.attributes[attrname] = AlarmAttribute(attrname, value) def addHistory(self, name, value, dtime=None): """ Add history entry for alarm to store actions of alarm using :py:class:`emonitor.modules.alarms.alarmhistory.AlarmHistory` :param name: name of event :param value: value of history entry :param optional dtime: timestamp of history entry (now) """ if not dtime: dtime = datetime.datetime.now() self.history.append(AlarmHistory(name, value, dtime)) def getAdditionalLayers(self): """ Get additional layers of default map definition of current alarm :return: list of :py:class:`emonitor.modules.mapitems.mapitem.MapItem` objects """ cat = self.key.category items = [] for itemtype in self.getMap().getMapItemDefinitions(): for r in itemtype['key']: regex = re.compile(r) if regex.search(cat): items.append(itemtype) return items def updateSchedules(self, reference=0): """ set scheduler events for current alarm: * autoclose * autoarchive :param reference: 0 (default)= time.time() 1 = alarm.timestamp """ for job in scheduler.get_jobs(): # remove schedules of current alarm if job.name.startswith('alarms_') and job.name.endswith('_{}'.format(self.id)): scheduler.remove_job(job.id) if reference == 0: reference = time.time() else: reference = time.mktime(self.timestamp.timetuple()) # autoclose if self.state == 1 and self.type == 1 and Settings.get('alarms.autoclose', '0') != '0': # only for open alarms closingtime = reference + float(Settings.get('alarms.autoclose', 30)) * 60.0 # minutes -> seconds if closingtime > time.time(): # close alarm in future logger.debug("add close schedule in future for alarmid {}".format(self.id)) scheduler.add_job(Alarm.changeState, run_date=datetime.datetime.fromtimestamp(closingtime), args=[self.id, 2], name="alarms_close_{}".format(self.id)) else: # close alarm now logger.debug("add close schedule now for alarmid {}".format(self.id)) scheduler.add_job(Alarm.changeState, args=[self.id, 2], name="alarms_close_{}".format(self.id)) self.state = 2 # autoarchive if self.state == 2 and Settings.get('alarms.autoarchive', '0') != '0': # only closed alarms archivetime = reference + float(Settings.get('alarms.autoarchive', 12)) * 3600.0 # hours -> seconds if archivetime > time.time(): # archive alarm in future logger.debug("add archive schedule in future for alarmid {}".format(self.id)) scheduler.add_job(Alarm.changeState, run_date=datetime.datetime.fromtimestamp(archivetime), args=[self.id, 3], name="alarms_archive_{}".format(self.id)) else: # archive alarm now logger.debug("add archive schedule now for alarmid {}".format(self.id)) scheduler.add_job(Alarm.changeState, args=[self.id, 3], name="alarms_archive_{}".format(self.id)) def getDepartment(self): if self.street.city: return Department.getDepartments(id=self.street.city.dept) else: Department.getDefaultDepartment() def getAlarmFields(self): if self.street.city: fields = AlarmField.getAlarmFields(dept=self.street.city.dept) else: fields = AlarmField.getAlarmFields(dept=Department.getDefaultDepartment().id) return fields def getFieldValue(self, field): value = field if '-' in field: value = AlarmField.getAlarmFields(fieldtype=field.split('-')[0]).getFieldValue(field.split('-')[1], self) elif field.startswith('basic.'): value = AFBasic().getFieldValue(field, self) elif field.startswith('alarm.'): if field == 'alarm.key': if self.key.id: return "{}: {}".format(self.key.category, self.key.key) return self.key.key elif field == 'alarm.date': return self.timestamp.strftime("%d.%m.%Y") elif field == 'alarm.time': return self.timestamp.strftime("%H:%M") else: value = field return value @staticmethod def getMap(): """ Returns default map defined in eMonitor :return: :py:class:`emonitor.modules.maps.map.Map` """ return Map.getDefaultMap() @staticmethod def getAlarms(id=0, days=0, state=-1): """ Get list of alarm objects filtered by parameters :param optional id: id of alarm or 0 for all alarms :param optional days: number of days since alarmdate :param optional state: -1 for alarms of all states, see :py:attr:`emonitor.modules.alarms.alarm.Alarm.ALARMSTATES` for value definition :return: list or single object :py:class:`emonitor.modules.alarms.alarm.Alarm` """ if id != 0: return Alarm.query.filter_by(id=id).first() elif days != 0: # filter last days, 0 = all days if int(state) == -1: return Alarm.query.filter(Alarm.timestamp > (datetime.datetime.now() - datetime.timedelta(days=days))).order_by(Alarm.timestamp.desc()).all() else: return Alarm.query.filter(Alarm.timestamp > (datetime.datetime.now() - datetime.timedelta(days=days)), Alarm.state == state).order_by(Alarm.timestamp.desc()).all() else: if int(state) == -1: # all states return Alarm.query.order_by(Alarm.timestamp.desc()).all() else: return Alarm.query.filter(Alarm.state == state).order_by(Alarm.timestamp.desc()).all() @staticmethod def getAlarmCount(days=0): """ Get number of alarms, grouped by state :param optional days: 0 for all alarms, since days else :return: list grouped by state """ if days != 0: return db.get(Alarm.state, count(Alarm.id)).filter(Alarm.timestamp > (datetime.datetime.now() - datetime.timedelta(days=days))).order_by(Alarm.timestamp.desc()).group_by(Alarm.state).all() else: return db.get(Alarm.state, count(Alarm.id)).group_by(Alarm.state).all() @staticmethod def getActiveAlarms(): """ Get list of all active alarms :return: list or :py:class:`emonitor.modules.alarms.alarm.Alarm` """ from sqlalchemy.exc import OperationalError try: return Alarm.query.filter_by(state=1).order_by(Alarm.timestamp.desc()).all() except OperationalError: return [] @staticmethod def changeStates(state): """ Set states of ALL alarms to given state :param state: state as :py:attr:`emonitor.modules.alarms.alarm.Alarm.ALARMSTATES` """ for alarm in Alarm.getAlarms(0): Alarm.changeState(alarm.id, state) def getRouting(self): if self.get('routing', '') == "": # load from webservice if not stored routingdata = alarmutils.getAlarmRoute(self) if len(routingdata['coordinates']) > 0: self.set('routing', yaml.safe_dump(routingdata, encoding="UTF-8")) db.session.commit() data = yaml.load(self.get('routing')) if 'error' in data: data['errormessage'] = babel.gettext(u'alarms.routingerror') return data @staticmethod def changeState(id, state): """ Change state of alarm with given id. Adds entry in alarmhistory and sends signal :param id: id of alarm :param state: new state as :py:attr:`emonitor.modules.alarms.alarm.Alarm.ALARMSTATES` """ from emonitor.extensions import monitorserver global LASTALARM alarm = Alarm.getAlarms(id=id) if not alarm: return [] if alarm.state != state and alarm.state != 0: # only change _op = 'changestate' else: _op = 'added' if alarm.get('alarmtype', '') != '': _type = '.{}'.format(alarm.get('alarmtype')) else: _type = '' alarm.state = state try: alarm.addHistory('autochangeState', Alarm.ALARMSTATES[str(state)]) except KeyError: alarm.addHistory('autochangeState', 'archived') db.session.commit() if state == 1: # activate alarm c = [] for a in Alarm.getActiveAlarms(): # check cars if a.id == id: continue c.extend(set(a.cars1).intersection(set(alarm.cars1))) c.extend(set(a.cars2).intersection(set(alarm.cars2))) c.extend(set(a.material).intersection(set(alarm.material))) if time.time() - LASTALARM < 60.0: try: ids = [a.id for a in Alarm.getActiveAlarms()] for j in [job for job in scheduler.get_jobs() if job.name == 'changeLayout']: for i in ids: if "'alarmid', %s" % i in str(j.args): # layout changes for given alarm scheduler.unschedule_job(j) except: logger.error('%s' % [a.id for a in Alarm.getActiveAlarms()]) LASTALARM = time.time() alarm.updateSchedules(reference=0) # use current time + delta j = scheduler.add_job(events.raiseEvent, next_run_time=datetime.datetime.fromtimestamp(LASTALARM), args=['alarm_{}{}'.format(_op, _type)], kwargs={'alarmid': id}, name="alarms_activate_{}".format(id)) signal.send('alarm', _op, alarmid=id, newstate=state) try: flash(babel.gettext(u'alarms.statechangeactivated'), 'alarms.activate') except: pass finally: monitorserver.sendMessage('0', 'reset') # refresh monitor layout return list(set(c)) elif state == 2: # close alarm LASTALARM = 0.0 alarm.updateSchedules(reference=1) # use alarm.timestamp + delta monitorserver.sendMessage('0', 'reset') # refresh monitor layout signal.send('alarm', 'changestate', newstate=2) return [] elif state == 3: # archive alarm alarm.updateSchedules() signal.send('alarm', 'changestate', newstate=3) return [] signal.send('alarm', 'changestate', newstate=state) @staticmethod def getExportData(exportformat, **params): """ Export alarm to given format :param exportformat: *.html*, *.png*, *telegram*, [*mail*] :param params: - style: exportstyle: *alarmmap*, *routemap*, *telegram.text*, *telegram.venue* - filename: name of exportfile :return: alarm in correct format """ if params['id'] and params: alarm = Alarm.getAlarms(id=params['id']) logger.debug('load export data for alarm {}, style {}, exportformat {}'.format(params['id'], params['style'], exportformat)) if not alarm: # create dummy alarm alarm = Alarm(datetime.datetime.now(), '', 2, 0) alarm.position = dict(lat=Settings.get('defaultLat'), lng=Settings.get('defaultLng')) alarm.set('id.key', '1') alarm.set('id.address', '1') alarm.set('id.city', '1') alarm.set('remark', 'TEST TEST TEST') if alarm: if exportformat == '.html' and 'style' in params: # build html-template params.update({'alarm': alarm}) try: if params['style'].startswith(u'report'): return render_template('{}.html'.format(params['style']), **params) elif params['style'] == 'alarm_original': fname = "{}/{}".format(current_app.config.get('PATH_DONE'), alarm.get('filename')) if fname.endswith('.pdf'): # file still in pdf format if os.path.exists(fname): with open(fname, 'rb') as f: return f.read() else: return render_template('print.error.html') elif fname.split('.')[-1] in Settings.get('ocr.inputformat'): # image formats if os.path.exists(fname): with open(fname, 'rb') as f: imgstr = base64.b64encode(f.read()) return render_template('print.alarm_original.html', alarm=alarm, txtstr="", imgstr=imgstr, imgmime="image/{}".format(fname.split('.')[-1])) elif fname.split('.')[-1] in Settings.get('ocr.inputtextformat'): if os.path.exists(fname): with codecs.open(fname, 'r', encoding='utf-8') as f: txtstr = f.read() return render_template('print.alarm_original.html', alarm=alarm, txtstr=txtstr, imgstr="", imgmime="") else: params.update({'path': current_app.config.get('PATH_DONE')}) return render_template('print.{}.html'.format(params['style']), **params) else: return render_template('print.{}.html'.format(params['style']), **params) except TemplateNotFound: logger.error('template {}{} not found'.format(params['style'], exportformat)) return abort(404) elif exportformat == '.png': # send image file if params['style'].startswith('alarmmap'): # deliver map for alarmid from emonitor.modules.maps.map_utils import getAlarmMap args = dict() if params['style'] != 'alarmmap': args = dict(style=params['style'].split('_')[-1]) return getAlarmMap(alarm, current_app.config.get('PATH_TILES'), **args) elif params['style'] == 'routemap': # deliver map with route from emonitor.modules.maps.map_utils import getAlarmRoute return getAlarmRoute(alarm, current_app.config.get('PATH_TILES')) if 'filename' in params and os.path.exists("%s/inc/%s.png" % (os.path.abspath(os.path.dirname(__file__)), params['filename'])): with open("%s/inc/%s.png" % (os.path.abspath(os.path.dirname(__file__)), params['filename']), 'rb') as f: return f.read() elif exportformat == 'telegram': # build telegram information for alarm if alarm.streetno: details = u"*Alarm ({})*\n*{}: {}*\n{} {} ({})\n{}\n\n{}".format(alarm.timestamp, alarm.key.category, alarm.key.key, alarm.street.name, alarm.streetno, alarm.city.name, alarm.street2.name, alarm.remark) address = u"{} {} ({})\n{}".format(alarm.street.name, alarm.streetno, alarm.city.name, alarm.street2.name) else: details = u"*Alarm ({})*\n*{}: {}*\n{} ({})\n\n{}".format(alarm.timestamp, alarm.key.category, alarm.key.key, alarm.street.name, alarm.city.name, alarm.remark) address = u"{} ({})".format(alarm.street.name, alarm.city.name) attrs = {'text': u"{}: {}".format(alarm.key.category, alarm.key.key), 'details': details, 'address': address, 'filename': alarm.get('filename'), 'lat': alarm.lat, 'lng': alarm.lng, 'reply': []} if alarm.type == 1: # fax type can send file attrs['reply'].append(params.get('button')("Fax", callback_data=u'file_{}'.format(attrs['filename']))) if params.get('style') == 'text': attrs['reply'].append(params.get('button')("Position", callback_data=u'location_{}_{}'.format(alarm.lat, alarm.lng))) if params.get('style') == 'venue': attrs['reply'].append(params.get('button')("Details", callback_data=u'details_alarm_{}'.format(alarm.id))) attrs['reply'] = params.get('keyboard')([attrs['reply']]) return attrs elif exportformat == 'mail': # TODO: Add mailer handler return None abort(404) @staticmethod def handleEvent(eventname, **kwargs): """ Eventhandler for alarm class :param eventname: name of event :param kwargs: parameter list: error, fields, filename, id, incomepath, mode, time :return: all kwargs """ try: from emonitor import app global LASTALARM alarm_fields = dict() stime = time.time() alarmtype = None for t in AlarmType.getAlarmTypes(): if re.search(t.keywords.replace('\r\n', '|'), kwargs.get('text', '')): alarm_fields = t.interpreterclass().buildAlarmFromText(t, kwargs.get('text', '')) if alarm_fields.get('error'): kwargs['error'] = alarm_fields['error'] del alarm_fields['error'] alarmtype = t break alarm = Alarm(datetime.datetime.now(), '', 1, 0) etime = time.time() _missing = 0 for p in ['time', 'city', 'address', 'key']: if p not in alarm_fields: # test required fields _missing += 1 kwargs['error'] = kwargs.get('error', 'Missing parameter:') + "<br/>- '{}'".format(p) try: t = datetime.datetime.strptime(alarm_fields.get('time')[0], '%d.%m.%Y - %H:%M:%S') except ValueError: t = datetime.datetime.now() alarm.timestamp = t kwargs['id'] = u'<ul><li>-test-</li></ul>' # add dummy id kwargs['fields'] = u'<ul>' # set evaluated fields from fax for k in sorted(alarm_fields): # add field values as unicode string if len(alarm_fields[k]) > 1: kwargs['fields'] = u'{}<li><b>{}:</b>\n <small style="color:silver">value:</small> "{}" → <small style="color:silver">id:</small> {}</li>'.format(kwargs.get('fields'), k, alarm_fields[k][0], alarm_fields[k][1]) else: kwargs['fields'] = u'{}<li><b>{}:</b>\n <small style="color:silver">value:</small> "{}"</li>'.format(kwargs.get('fields'), k, alarm_fields[k]) kwargs['fields'] = kwargs.get('fields', ' ') + '</ul></pre>\n\n<h5> ALARM-Object</h5>\n<pre><ul>' if _missing == 0: # all required parameters found if kwargs.get('mode') != 'test': if not os.path.exists('{}{}'.format(app.config.get('PATH_DONE'), t.strftime('%Y/%m/'))): os.makedirs('{}{}'.format(app.config.get('PATH_DONE'), t.strftime('%Y/%m/'))) try: shutil.copy2('{incomepath}{filename}'.format(**kwargs), '{}{}{}'.format(app.config.get('PATH_DONE'), t.strftime('%Y/%m/%Y%m%d-%H%M%S'), os.path.splitext(kwargs.get('filename'))[1])) except: pass try: # remove file os.remove('{incomepath}{filename}'.format(**kwargs)) except: pass kwargs['filename'] = '{}{}'.format(t.strftime('%Y/%m/%Y%m%d-%H%M%S'), os.path.splitext(kwargs['filename'])[1]) logger.debug('alarm_fields: {}'.format(alarm_fields)) if len(alarm_fields) == 0: # no alarmfields found kwargs['id'] = 0 logger.error('no alarm fields found.') return kwargs if not alarmtype: # alarmtype not found kwargs['id'] = 0 kwargs['error'] = kwargs.get('error', '') + 'alarmtype not found' logger.error('alarmtype not found.') return kwargs # position if alarm_fields.get('lat'): _position = dict(lat=alarm_fields.get('lat')[0], lng=alarm_fields.get('lng')[0]) else: _position = dict(lat=u'0.0', lng=u'0.0') if USE_NOMINATIM == 1: try: url = 'http://nominatim.openstreetmap.org/search' params = 'format=json&city={}&street={}'.format(alarm_fields['city'][0], alarm_fields['address'][0]) if 'streetno' in alarm_fields: params += ' {}'.format(alarm_fields['streetno'][0].split()[0]) # only first value r = requests.get('{}?{}'.format(url, params)) _position = dict(lat=r.json()[0]['lat'], lng=r.json()[0]['lon']) except: pass # create alarm object if alarm_fields.get('key', [u'', 0])[0] == u'': if alarmtype.translation(u'_bma_main_') in alarm_fields.get('remark', [u'', 0])[0] or alarmtype.translation(u'_bma_main_') in alarm_fields.get('person', [u'', 0])[0]: alarmkey = Alarmkey.query.filter(Alarmkey.key.like(u"%{}%".format(alarmtype.translation(u'_bma_')))).all() if len(alarmkey) > 0: alarm_fields['key'] = ('{}: {}'.format(alarmkey[0].category, alarmkey[0].key), str(alarmkey[0].id)) else: alarm_fields['key'] = (alarmtype.translation(u'_bma_key_'), u'0') if alarm_fields.get('time', [u'', 0])[1] == 1: # found correct time t = datetime.datetime.strptime(alarm_fields.get('time', [u'', 0])[0], '%d.%m.%Y - %H:%M:%S') else: t = datetime.datetime.now() alarm.timestamp = t alarm.set('id.key', alarm_fields['key'][1]) alarm._key = alarm_fields['key'][0] alarm.material = dict(cars1='', cars2='', material='') # set required attributes alarm.set('marker', '0') alarm.set('filename', kwargs['filename']) alarm.set('priority', '1') # set normal priority alarm.set('alarmtype', alarmtype.name) # set checker name alarm.position = _position alarm.state = 1 # city if alarm_fields.get('city', ['', 0])[1] > 0: alarm.city = City.getCities(id=alarm_fields.get('city')[1]) if alarm_fields.get('address'): alarm.street = Street.getStreets(id=alarm_fields.get('address')[1]) else: # city not found -> build from fax url = 'http://nominatim.openstreetmap.org/search' if len(alarm_fields.get('city', [u'', 0])[0].split()) > 0: params = u'format=json&city={}&street={}'.format(alarm_fields.get('city', [u'', 0])[0].split()[0], alarm_fields.get('address', [u'', 0])[0]) if alarm_fields.get('streetno'): try: params += u' {}'.format(alarm_fields.get('streetno')[0].split()[0]) # only first value except: pass alarm.set('streetno', alarm_fields.get('streetno')[0]) try: r = requests.get(u'{}?{}'.format(url, params)) logger.debug(u'load address data from nomination with parameters: city={} street={}'.format(alarm_fields.get('city')[0].split()[0], alarm_fields.get('address', ['', 0])[0])) _position = dict(lat=r.json()[0]['lat'], lng=r.json()[0]['lon']) alarm.position = _position except: pass if len(alarm_fields.get('city', ['', 0])[0].split()) > 0: alarm.set('city', alarm_fields.get('city', ['', 0])[0].split()[0]) alarm.set('id.city', alarm_fields.get('city')[1]) alarm.set('address', alarm_fields.get('address', ['', 0])[0]) if alarm_fields.get('address', [u'', 0])[1] != 0: alarm.street = Street.getStreets(id=alarm_fields.get('address')[1]) if alarm_fields.get('cars'): # add cars found in material for _c in alarm_fields.get('cars')[1].split(';'): alarm.set('k.cars1', alarm.get('k.cars1') + ';' + _c) # street / street2 if alarm_fields.get('address', [u'', 0]) != '': # check correct city -> change if street has different city if len(str(alarm_fields.get('address')[1]).split(';')) > 0 and alarm_fields.get('address')[1] != 0: _c = [] for s in str(alarm_fields.get('address')[1]).split(';'): _s = Street.getStreets(id=s) if _s.cityid and _s.cityid not in _c and _s.cityid == alarm_fields.get('city', [u'', 0])[1]: _c.append(_s.cityid) alarm.street = _s if alarm_fields.get('object', [u'', 0])[1] == 0: if not alarm_fields.get('lat') and not alarm_fields.get('lng'): alarm.position = dict(lat=_s.lat, lng=_s.lng, zoom=_s.zoom) if _position['lat'] != u'0.0' and _position['lng'] != u'0.0': # set marker if nominatim delivers result alarm.position = _position alarm.set('marker', '1') else: # add unknown street alarm.set('id.address', 0) alarm.set('address', alarm_fields['address'][0]) # houseno if alarm_fields.get('streetno'): alarm.set('streetno', alarm_fields.get('streetno')[0]) if alarm_fields.get('id.streetno') and alarm_fields.get('lat') and alarm_fields.get('lng'): alarm.position = dict(lat=alarm_fields.get('lat')[0], lng=alarm_fields.get('lng')[0]) alarm.set('id.streetno', alarm_fields.get('id.streetno')[1]) else: # new hn = alarm.street.getHouseNumber(name=alarm_fields.get('streetno')[0]) if hn: alarm.position = hn.getPosition(0) if alarm_fields.get('zoom'): alarm.set('zoom', alarm_fields.get('zoom')[0]) # crossing if alarm_fields.get('crossing', [u'', 0])[0] != '': if alarm_fields.get('crossing', [u'', 0])[1] != alarm_fields.get('address',[u'', 0])[1]: alarm.set('id.address2', alarm_fields.get('crossing')[1]) alarm.set('address2', alarm_fields.get('crossing')[0]) else: alarm.set('id.address2', '0') alarm.set('address2', alarm_fields.get('crossing')[0]) # addresspart if alarm_fields.get('addresspart', [u'', 0])[0] != u'' and alarm_fields.get('addresspart', [u'', 0])[0] != alarm_fields.get('address', [u'', 0])[0]: if alarm_fields.get('addresspart')[1] > 0: if len(str(alarm_fields.get('addresspart')[1]).split(';')) > 0: _c = [] for s in str(alarm_fields.get('addresspart')[1]).split(';'): try: _s = Street.getStreets(id=s) if _s.cityid not in _c and _s.cityid == alarm_fields.get('city')[1]: _c.append(_s.cityid) alarm.set('id.address2', _s.id) except: pass else: alarm.set('id.address2', alarm_fields.get('addresspart')[1]) else: alarm.set('id.address2', '0') alarm.set('address2', alarm_fields.get('addresspart')[0]) # person if alarm_fields.get('person', [u'', 0])[0] != u'': alarm.set('person', alarm_fields.get('person')[0]) # alarmplan if alarm_fields.get('alarmplan', [u'', 0])[0] != u'': alarm.set('alarmplan', alarm_fields.get('alarmplan')[0]) # alarmobject _ao = None if alarm_fields.get('object', [u'', 0])[0] != u'' and alarm_fields.get('city', [u'', 0])[1] > 0: alarm.set('object', alarm_fields.get('object')[0]) alarm.set('id.object', alarm_fields.get('object')[1]) # alarmplan from object if alarm_fields.get('object')[1] != 0: _ao = AlarmObject.getAlarmObjects(id=alarm_fields.get('object')[1]) if _ao: if _ao.alarmplan != 0: alarm.set('alarmplan', _ao.alarmplan) elif alarm_fields.get('alarmplan'): alarm.set('alarmplan', alarm_fields.get('alarmplan')[0]) if _ao.street.id != alarm_fields.get('address', [u'', 0])[1]: # street config from alarmobject alarm.street = Street.getStreets(id=_ao.street.id) if _ao.streetno == "": alarm.set('streetno', alarm_fields.get('streetno')[0]) else: alarm.set('streetno', _ao.streetno) alarm.position = dict(lat=_ao.lat, lng=_ao.lng, zoom=_ao.zoom) # remark if alarm_fields.get('remark', [u'', 0])[0] != u'': alarm.set('remark', alarm_fields.get('remark')[0]) _bma = 0 for v in alarmtype.translation(u'_bma_main_').split(): if v in alarm_fields.get('remark', [u'', 0])[0] or v in alarm_fields.get('person', [u'', 0])[0]: _bma = 1 break if _bma == 1: alarmkey = Alarmkey.query.filter(Alarmkey.key.like(u"%{}%".format(alarmtype.translation(u'_bma_')))).first() if alarmkey: alarm.set('id.key', alarmkey.id) alarm._key = u'{}: {}'.format(alarmkey.category, alarmkey.key) else: alarm.set('id.key', '0') alarm._key = alarmtype.translation(u'_bma_key_') # additional remarks if alarm_fields.get('remark2', [u'', 0])[0] != u'': alarm.set('remark', u'{}\n{}'.format(alarm.get('remark'), alarm_fields.get('remark2')[0])) # material if alarm.get('id.key') != 0 and alarm_fields.get('city'): # found key with aao if alarm_fields.get('city')[1] not in [0, -1]: # default city if Department.getDepartments(id=alarm.city.dept).defaultcity == alarm_fields.get('city')[1]: # default city for dep if alarm_fields.get('material'): if str(alarm_fields.get('material')[1])[0] == '0': # default cars for aao try: alarm.material = dict(cars1=u','.join([str(c.id) for c in alarm.key.getCars1(alarm.street.city.dept)]), cars2=u','.join([str(c.id) for c in alarm.key.getCars2(alarm.street.city.dept)]), material=u','.join([str(c.id) for c in alarm.key.getMaterial(alarm.street.city.dept)])) except AttributeError: alarm.material = dict(cars1=u','.join([str(c.id) for c in alarm.key.getCars1(alarm.city.dept)]), cars2=u','.join([str(c.id) for c in alarm.key.getCars2(alarm.city.dept)]), material=u','.join([str(c.id) for c in alarm.key.getMaterial(alarm.city.dept)])) for _c in u'{}'.format(alarm_fields.get('material')[1]).split(','): # add additional cars if _c != '0' and _c not in alarm.get('k.cars1').split(','): alarm.set('k.cars1', u'{},{}'.format(alarm.get('k.cars1'), _c)) else: # only alarmed material alarm.material = dict(cars1=alarm_fields.get('material', [u'', ''])[1]) else: # else city if alarm_fields.get('material', [u'', u''])[1] == u'0': # default cars for aao alarm.material = dict(cars1=u','.join([str(c.id) for c in alarm.key.getCars1(alarm.city.dept)]), cars2=u','.join([str(c.id) for c in alarm.key.getCars2(alarm.city.dept)]), material=u','.join([str(c.id) for c in alarm.key.getMaterial(alarm.city.dept)])) else: alarm.material = dict(cars1=u','.join(list(OrderedDict.fromkeys(filter(lambda x: x != '0', str(alarm_fields.get('material', ['', '-1'])[1]).split(',')))))) else: # default aao of current department (without aao) if alarm_fields.get('city', [u'', 0])[1] != 0: # found city -> use default aao if City.getCities(id=alarm_fields.get('city')[1]): c = City.getCities(id=alarm_fields.get('city')[1]).dept else: c = City.getDefaultCity().dept akc = Alarmkey.getDefault(c) if len(akc.cars1) + len(akc.cars2) + len(akc.materials) == 0: # no default aao defined # use cars of fax alarm.material = {'cars1': re.sub(r'^0,', '', alarm_fields.get('material')[1]), 'cars2': '', 'material': ''} else: # use cars of default aao alarm.material = dict(cars1=u','.join([str(c.id) for c in akc.cars1]), cars2=u",".join([str(c.id) for c in akc.cars2]), material=u",".join([str(c.id) for c in akc.materials])) l = (u'{},{},{}'.format(alarm.get('k.cars1'), alarm.get('k.cars2'), alarm.get('k.material'))).split(',') if len(set(str(alarm_fields.get('material', ([], '-1'))[1]).split(',')).intersection(set(l))) == 0: _dep = Department.getDefaultDepartment() for c in str(alarm_fields.get('material', ([], '-1'))[1]).split(','): if c == u'0': # default of home department needed alarm.material = dict(cars1=u','.join([str(c.id) for c in alarm.key.getCars1(_dep.id)]), cars2=u",".join([str(c.id) for c in alarm.key.getCars2(_dep.id)]), material=u",".join([str(c.id) for c in alarm.key.getMaterial(_dep.id)])) break if u'0' not in str(alarm_fields.get('material', ([], '-1'))[1]): # only single car needed alarm.set('k.cars1', u'{},{}'.format(alarm_fields.get('material', ([], '-1'))[1], alarm.get('k.cars1'))) if _ao and _ao.hasOwnAAO(): # use aao of current object alarm.material = dict(cars1=u",".join([str(c.id) for c in _ao.getCars1()]), cars2=u",".join([str(c.id) for c in _ao.getCars2()]), material=u",".join([str(c.id) for c in _ao.getMaterial()])) if not kwargs.get('time'): kwargs['time'] = [] kwargs['time'].append('alarm creation done in {} sec.'.format(etime - stime)) if kwargs.get('mode') != 'test': db.session.add(alarm) db.session.commit() signal.send('alarm', 'added', alarmid=alarm.id) Alarm.changeState(alarm.id, 1) # activate alarm logger.info('alarm created with id {} ({})'.format(alarm.id, (etime - stime))) else: _cdict = Car.getCarsDict() for a in sorted(alarm.attributes): try: if a in ['k.cars1', 'k.cars2', 'k.material']: kwargs['fields'] += '<li><b>%s:</b>\n <small style="color:silver">id:</small> "%s" → "%s"</li>' % (a, alarm.get(a), ", ".join([_cdict[int(_c)].name for _c in alarm.get(a).split(',') if _c not in ['', '0']])) elif a in 'id.key': if alarm.get(a) > 0: _k = Alarmkey.getAlarmkeys(id=alarm.get(a)) kwargs['fields'] += '<li><b>%s:</b>\n <small style="color:silver">id:</small> "%s" → "%s: %s"</li>' % (a, alarm.get(a), _k.category, _k.key) else: kwargs['fields'] += '<li><b>%s:</b>\n <small style="color:silver">value:</small> "%s"</li>' % (a, alarm.get(a)) kwargs['fields'] += '<li><b>key:</b>\n <small style="color:silver">value:</small> "%s"</li>' % alarm._key elif a == 'id.address': kwargs['fields'] += '<li><b>%s:</b>\n <small style="color:silver">id:</small> "%s" → "%s"</li>' % (a, alarm.get(a), Street.getStreets(id=alarm.get(a)).name) elif a == 'id.object': kwargs['id.object'] = '<li><b>%s:</b>\n <small style="color:silver">value:</small> "%s"</li>' % (a, alarm.get(a)) kwargs['object'] = '<li><b>object:</b>\n <small style="color:silver">value:</small> "%s"</li>' % alarm.get('object') else: kwargs['fields'] += '<li><b>%s:</b>\n <small style="color:silver">value:</small> "%s"</li>' % (a, alarm.get(a)) except (AttributeError, KeyError): kwargs['fields'] += '<li style="color:red"><b>%s:</b>\n <small style="color:silver">value:</small> "%s" (error)</li>' % (a, alarm.get(a)) kwargs['fields'] += "</ul>" db.session.rollback() logger.info('alarm created in TESTMODE (%s)' % (etime - stime)) except: signal.send('alarm', 'error', message='alarms.errorincreation', text=kwargs.get('text', '')) return kwargs
class MonitorLayout(db.Model): """MonitorLayout class""" __tablename__ = 'monitorlayouts' __table_args__ = {'extend_existing': True} id = db.Column(db.Integer, primary_key=True) mid = db.Column(db.Integer, db.ForeignKey('monitors.id')) trigger = db.Column(db.TEXT, default='default') _layout = db.Column('layout', db.Text) theme = db.Column(db.String(30)) mintime = db.Column(db.Integer, default=0) maxtime = db.Column(db.Integer, default=0) nextid = db.Column(db.Integer, default=0) monitor = relationship("Monitor", backref="monitors", lazy='joined') @property def layout(self): """ Use yaml for layout :return: yaml formated data """ return yaml.load(self._layout) @layout.setter def layout(self, val): """ Setter for layout :param val: value list with parameters for widgets """ l = [] for item in val: if len(item.split(';')) == 5: i = item.split(';') l.append( dict(widget=i[0], width=int(i[1]), height=int(i[2]), col=int(i[3]), row=int(i[4]))) self._layout = yaml.safe_dump(l, encoding='utf-8') #@property #def monitor(self): # """Build monitor from mid""" # return Monitor.getMonitors(id=self.mid) def _get_themes(self): ret = [] for root, dirs, files in os.walk( "%s/emonitor/frontend/web/css" % current_app.config.get('PROJECT_ROOT')): for name in [f for f in files if f.startswith('monitor_')]: ret.append(name.split('_')[1][:-4]) return ret themes = property(_get_themes) def _get_html_layout(self): """ Build default html layout for widget configuration :return: html string with layout areas for widget content """ ret = "" items, max_x, max_y = MonitorLayout._evalLayout(self.layout) for l in items: _l = str(int(ceil((l['startx'] - 1) * (100.0 / max_x)))) + '%' _t = str(int(ceil((l['starty'] - 1) * (100.0 / max_y)))) + '%' _r = str(100 - int(ceil((l['endx']) * (100.0 / max_x)))) + '%' _b = str(100 - int(ceil((l['endy']) * (100.0 / max_y)))) + '%' ret += '<div id="area" style="position:fixed;left:%s;top:%s;right:%s;bottom:%s;">[[%s]]</div>\n' % ( _l, _t, _r, _b, l['widget']) return ret htmllayout = property(_get_html_layout) def __repr__(self): return "monitorlayout" def __init__(self, mid, trigger, layout, theme, mintime, maxtime, nextid): self.mid = mid self.trigger = trigger self.layout = layout self.theme = theme self.mintime = mintime self.maxtime = maxtime self.nextid = nextid @staticmethod def _evalLayout(text): ret = [] max_x = max_y = 1 if text is None: return [ dict(startx=1, starty=1, endx=1, endy=1, name='placeholder') ], 1, 1 for l in text: ret.append( dict(startx=l['col'], starty=l['row'], endx=(l['width'] + l['col'] - 1), endy=(l['height'] + l['row'] - 1), widget=l['widget'])) if l['width'] + l['col'] - 1 > max_x: max_x = l['width'] + l['col'] - 1 if l['height'] + l['row'] - 1 > max_y: max_y = l['height'] + l['row'] - 1 return ret, max_x, max_y def getHTMLLayoutScript(self): ret = '$(function(){' for l in self.layout: try: ret += 'addWidget("%s", %s, %s, %s, %s);\n' % ( l['widget'], l['width'], l['height'], l['col'], l['row']) except: pass return ret + '});' def getLayoutThumb(self): """ Calculate the thumbnail of the layout on-the-fly :return: stream of image file """ dimension = (12, 9) ret, max_x, max_y = MonitorLayout._evalLayout(self.layout) img = Image.new('RGB', (max_x * dimension[0] + 1, max_y * dimension[1] + 1), (171, 171, 171)) draw = ImageDraw.Draw(img) for l in ret: draw.rectangle([((l['startx'] - 1) * dimension[0], (l['starty'] - 1) * dimension[1]), ((l['endx']) * dimension[0], (l['endy']) * dimension[1])], fill="white", outline='black') output = StringIO() img.save(output, format="PNG", dpi=(300, 300)) return output.getvalue() @staticmethod def getLayouts(id=0, mid=0): """ Get list of layout definitions filtered by parameters :param optional id: filter only layout with id, *0* for all layouts :param optional mid: monitorid as integer :return: list of :py:class:`emonitor.modules.monitors.monitorlyout.MonitorLayout` """ if id != 0: return MonitorLayout.query.filter_by(id=id).first() elif mid != 0: return MonitorLayout.query.filter_by(mid=mid).all() else: return MonitorLayout.query.order_by('mid').all() def getTriggerNames(self): return self.trigger.split(';')
class Street(db.Model): """Street class""" __tablename__ = 'streets' __table_args__ = {'extend_existing': True} id = db.Column(db.Integer, primary_key=True) name = db.Column(db.String(50)) navigation = db.Column(db.Text) cityid = db.Column(db.Integer, db.ForeignKey('cities.id')) subcity = db.Column(db.String(40)) lat = db.Column(db.Float) lng = db.Column(db.Float) zoom = db.Column(db.Integer) active = db.Column(db.Integer, default=0) osmid = db.Column(db.Integer, default=0) city = relationship("City", backref="cities", lazy='joined') housenumbers = relationship(Housenumber.__name__, backref="streets", lazy='subquery', order_by=Housenumber.number) def __init__(self, name, navigation, cityid, subcity, lat, lng, zoom, active, osmid): self.name = name self.navigation = navigation self.cityid = cityid self.subcity = subcity self.lat = lat self.lng = lng self.zoom = zoom self.active = active self.osmid = osmid def __repr__(self): return '<Street %r - %r>' % (self.id, self.name) @property def serialize(self): """ Serialize street object for json calls :return: dict with street attributes """ return dict(id=self.id, name=self.name, city=self.city.serialize, subcity=self.subcity, lat=self.lat, lng=self.lng, zoom=self.zoom, active=self.active) def addHouseNumber(self, number, points): """ Add housenumber for street :param number: housenumber as string :param points: list of points for housenumber """ if number not in [hn.number for hn in self.housenumbers]: db.session.add(Housenumber(self.id, number, yaml.dump(points))) db.session.commit() def getHouseNumber(self, **kwargs): ret = [] if "id" in kwargs: ret = filter(lambda x: x.id == kwargs['id'], self.housenumbers) elif "number" in kwargs: ret = filter(lambda x: x.number == kwargs['number'], self.housenumbers) if len(ret) > 0: return ret[0] return None @staticmethod def getStreets(id=0, cityid=0): """ Get all streets of city given by id, *0* for all streets :param optional id: id of street, *0* for all :param optional cityid: id of city, *0* for all :return: list of :py:class:`emonitor.modules.streets.street.Street` """ if id != 0: return Street.query.filter_by(id=id).scalar() if cityid != 0: return Street.query.filter_by(cityid=cityid).order_by( Street.name).all() else: return Street.query.order_by(Street.name).all() @staticmethod def getStreetsDict(): """ Get dict of streets, id as key :return: cict of :py:class:`emonitor.modules.streets.street.Street` """ ret = dict( db.get(Street.id, Street).filter_by(active=1).order_by(Street.name)) ret[0] = Street('', '', 0, '', 0, 0, 0, 1, 0) return ret
class Map(db.Model): """Maps class""" __tablename__ = 'maps' __table_args__ = {'extend_existing': True} id = db.Column(db.Integer, primary_key=True) name = db.Column(db.String(64)) path = db.Column(db.String(128)) maptype = db.Column(db.Integer, default=0) tileserver = db.Column(db.Text) default = db.Column(db.Integer, default=0) def __init__(self, name, path, maptype=0, tileserver="", default=0): self.name = name self.path = path self.maptype = maptype self.tileserver = tileserver self.default = default def getMapItems(self, itemtype=""): return MapItem.getMapitems(itemtype) def getMapItemDefinitions(self): return Settings.get('mapitemdefinition') @staticmethod def getMapBox(tilepath="", mappath="", zoom=DEFAULTZOOM): """ Deliver a hashmap with the bounding box of current map definition :param tilepath: path to tile images :param mappath: :param zoom: zoom level :return: hashmap with parameters """ ret = dict(mappath=[], coord=[], min_lngtile=10000, min_lattile=10000, max_lngtile=0, max_lattile=0, min_lngdeg=0.0, max_lngdeg=0.0, min_latdeg=0.0, max_latdeg=0.0) """Default hashmap""" for path, dirs, files in os.walk('%s%s' % (tilepath, mappath)): if path.endswith('/%s' % zoom) or path.endswith('\\%s' % zoom): for _file in files: lat, lng = _file.split(".")[0].split('-') # build bounding box if int(lat) < ret['min_lattile']: ret['min_lattile'] = int(lat) if int(lat) > ret['max_lattile']: ret['max_lattile'] = int(lat) if int(lng) < ret['min_lngtile']: ret['min_lngtile'] = int(lng) if int(lng) > ret['max_lngtile']: ret['max_lngtile'] = int(lng) lat1, lng1 = Settings.num2deg(ret['min_lattile'], ret['min_lngtile'], zoom) lat2, lng2 = Settings.num2deg(ret['max_lattile'] + 1, ret['max_lngtile'] + 1, zoom) lat = [lat1, lat2] lng = [lng1, lng2] lat.sort() lng.sort() ret['min_latdeg'] = lat[0] ret['max_latdeg'] = lat[-1] ret['min_lngdeg'] = lng[0] ret['max_lngdeg'] = lng[-1] ret['mappath'].append(_file.replace('-', '/')) ret['coord'].append('.'.join(_file.split('.')[:-1])) break return ret @staticmethod def getMaps(id=0): """ Get list of map definitions filtered by parameters :param optional id: id of map or 0 for all maps :return: list or single object :py:class:`emonitor.modules.maps.map.Map` """ if id != 0: return Map.query.filter_by(id=id).first() else: return Map.query.all() @staticmethod def getDefaultMap(): """ Get default map defined in database, field default=1 :return: :py:class:`emonitor.modules.maps.map.Map` """ return Map.query.filter_by(default=1).first()
class Messages(db.Model): """Messages class""" __tablename__ = 'messages' __table_args__ = {'extend_existing': True} ACTIVE_MESSAGES = [] id = db.Column(db.Integer, primary_key=True) name = db.Column(db.String(64)) remark = db.Column(db.TEXT) startdate = db.Column(db.DATETIME) enddate = db.Column(db.DATETIME) state = db.Column(db.Integer) _monitors = db.Column('monitors', db.String(32)) _type = db.Column('type', db.String(32)) _attributes = db.Column('attributes', db.TEXT) def __init__(self, name, remark, startdate, enddate, state, mtype=TextWidget('dd')): self.name = name self.remark = remark self.startdate = startdate self.enddate = enddate self.state = state self.type = mtype def __str__(self): return "<Message %s> %s: %s-%s, visible: %s, on monitor: %s" % ( self.id, self.name, self.startdate, self.enddate, self.currentState, self.monitors) @property def attributes(self): """ Load attributes from database in yaml format :return: attributes as dict """ try: return yaml.load(self._attributes) except AttributeError: return {} @attributes.setter def attributes(self, val): """ Store given attributes in yaml format in database :param val: value for attribute """ self._attributes = yaml.safe_dump(val, encoding='utf-8') def get(self, attribute, default=""): """ Get attribute value if found in definition of object, default else :param attribute: name of attribute as string :param optional default: use default value if attribute not found :return: value of attribute or default """ if attribute in self.attributes: return self.attributes[attribute] attr = attribute.split('.') if attr[0] in self.attributes: if len(attr) == 2: if attr[1] in self.attributes[attr[0]]: return self.attributes[attr[0]][attr[1]] else: return self.attributes[attr[0]] return default def set(self, attribute, value): """ Set attribute with given value :param attribute: name of attribute :param value: value for attribute """ self.attributes[attribute] = value @property def type(self): """ Get message type as MessageType class object :return: :py:class:`emonitor.modules.messages.messagetype.MessageType` """ if self._type == '': self._type = Settings.get('messages.base.type') impl = filter(lambda x: x[0].split('.')[0] == self._type, MessageType.getMessageTypes()) if len(impl) == 1: return impl[0][1] return None @type.setter def type(self, messageType): """ Set typename for message and store value in type column of database table :param messageType: use messagetype object or objectname """ self._type = str(messageType).split('.')[0] @property def monitors(self): """ Getter for monitors property :return: list of monitor ids """ try: return [int(m) for m in self._monitors.split(',')] except (ValueError, AttributeError): return [] @monitors.setter def monitors(self, monitors): """ Setter for monitors property :param monitors: list of monitor ids """ self._monitors = ','.join(monitors) @property def currentState(self, timestamp=None): """ Return current state of message, use calculated value for next state change if defined :param optional timestamp: use given timestamp or now as reference :return: boolean """ if self.get('cron', None): if not timestamp: timestamp = datetime.datetime.now(tz=pytz.timezone('CET')) return not calcNextStateChange(timestamp, self.get('cron'))[1] return True @staticmethod def getMessages(id=0, state=-1): """ Get messages filtered by criteria :param optional id: id of message :param optional state: -1: all messages, else only messages with given state :return: :py:class:`emonitor.modules.messages.messages.Messages` list """ if id == 0: if state == -1: return Messages.query.order_by('messages.startdate').all() else: return Messages.query.filter(Messages.state == state).order_by( 'messages.startdate').all() else: return Messages.query.filter(Messages.id == int(id)).first() @staticmethod def getActiveMessages(): """ Filters only startdate, enddate and state > 0 :return: :py:class:`emonitor.modules.messages.messages.Messages` list """ try: return Messages.query.filter(Messages.state > 0).filter( Messages.startdate <= datetime.datetime.now()).filter( Messages.enddate >= datetime.datetime.now()).order_by( Messages.startdate.asc()).all() except OperationalError: return [] @staticmethod def initMessageTrigger(): """Init scheduler tasks for messages""" job = scheduler.add_job(Messages.doMessageTrigger, name="messages", id="messages", trigger=MessageTrigger( Messages.getActiveMessages(), minutes=60)) if len(job.trigger.messagelist ) == 0: # pause job if no active messages job.pause() @staticmethod def updateMessageTrigger(): """Update message trigger after changes in message objects and update next fire time""" job = scheduler.get_job(job_id="messages") job.trigger.messagelist = Messages.getActiveMessages( ) # update message list for new firetime if len(job.trigger.messagelist) == 0: job.pause() # pause job if no active messages else: job.resume() # reactivate if active messages scheduler.modify_job(job_id="messages", next_run_time=job.trigger.get_next_fire_time( '', '')) scheduler.app.logger.info( 'message trigger: update message trigger, next run %s' % job.next_run_time) monitorserver.sendMessage('0', 'reset') # refresh monitor layout @staticmethod def doMessageTrigger(): """Run every state-change of a message and update messagelist for displays and call monitors""" scheduler.app.logger.info('message trigger: run state changes at %s' % datetime.datetime.now()) Messages.updateMessageTrigger( ) # update trigger and calculate next run
class Person(db.Model): """Person class""" __tablename__ = 'persons' __table_args__ = {'extend_existing': True} id = db.Column(db.Integer, primary_key=True) firstname = db.Column(db.String(64)) lastname = db.Column(db.String(64)) salutation = db.Column(db.String(16)) grade = db.Column(db.String(32)) position = db.Column(db.String(32)) identifier = db.Column(db.String(32)) active = db.Column(db.BOOLEAN) birthdate = db.Column(db.DATETIME) remark = db.Column(db.TEXT) _dept = db.Column('dept', db.ForeignKey('departments.id')) _options = db.Column('options', db.TEXT) dept = db.relationship("Department", collection_class=attribute_mapped_collection('id')) def __init__(self, firstname, lastname, salutation, grade, position, identifier, active, birthdate, remark, dept, **options): self.firstname = firstname self.lastname = lastname self.salutation = salutation self.grade = grade self.position = position self.identifier = identifier self.active = active self.birthdate = birthdate self.remark = remark self._dept = dept self._options = yaml.safe_dump(options, encoding='utf-8') @property def fullname(self): """format fullname""" return u"{}, {}".format(self.lastname, self.firstname) @property def age(self): """calculate age in years""" return int(round((datetime.now() - self.birthdate).days / 365.25, 0)) @property def birthday(self): """ calculate day of birthdate for sorting caution: use the same year for day calculation (1903/1904) and respect leap year """ if calendar.isleap(datetime.now().year): return int((datetime(1904, *self.birthdate.timetuple()[1:-2]) ).strftime('%j')) # use a leapyear as reference else: return int((datetime(1903, *self.birthdate.timetuple()[1:-2]) ).strftime('%j')) # use a non-leapyear as reference @property def options(self): return yaml.load(self._options) @staticmethod def getPersons(id=0, identifier=0, dept=0, onlyactive=False): if id != 0: return Person.query.filter_by(id=id).first() elif identifier != 0: return Person.query.filter_by(identifier=identifier).first() elif dept != 0: if onlyactive: return Person.query.filter_by( _dept=dept, active=True).order_by('lastname').all() return Person.query.filter_by( _dept=dept).order_by('lastname').all() else: if onlyactive: return Person.query.filter_by( active=True).order_by('lastname').all() return Person.query.order_by('lastname').all() @staticmethod def settings(): return dict(Settings.getYaml('persons.settings'))
class Alarmkey(db.Model): """Alarmkey class""" __tablename__ = 'alarmkeys' __table_args__ = {'extend_existing': True} id = db.Column(db.Integer, primary_key=True) category = db.Column(db.String(40), default='') key = db.Column(db.String(40), default='') key_internal = db.Column(db.String(40), default='') remark = db.Column(db.Text) def __init__(self, category, key, key_internal, remark): self.category = category self.key = key self.key_internal = key_internal self.remark = remark def _getCars(self, cartype, department): """ Prototype method for car or material lists :param cartype: 1|2|3: cars1, cars2, material as integer :param department: id of department as integer :return: list of cars, material """ alarmcars = AlarmkeyCars.getAlarmkeyCars(kid=self.id or 9999, dept=department) if not alarmcars: # try default alarmcars = AlarmkeyCars.getAlarmkeyCars(kid=9999, dept=department) if alarmcars: if cartype == 1: return alarmcars.cars1 elif cartype == 2: return alarmcars.cars2 elif cartype == 3: return alarmcars.materials else: return [] def setCars(self, department, **kwargs): """ Set carlist of department :param department: id of department as integer :param kwargs: - *cars1*: list of :py:class:`emonitor.modules.cars.car.Car` objects for cars1 - *cars2*: list of :py:class:`emonitor.modules.cars.car.Car` objects for cars2 - *material*: list of :py:class:`emonitor.modules.cars.car.Car` objects for material """ alarmcars = AlarmkeyCars.getAlarmkeyCars(kid=self.id, dept=department) if not alarmcars: alarmcars = AlarmkeyCars(self.id, department, '', '', '') db.session.add(alarmcars) if "cars1" in kwargs.keys(): alarmcars._cars1 = kwargs['cars1'] if "cars2" in kwargs.keys(): alarmcars._cars2 = kwargs['cars2'] if "material" in kwargs.keys(): alarmcars._material = kwargs['material'] def getCars1(self, department): """ Get list of Car objects for cars1 of current alarmkey definition of given department :param department: id of department as integer :return: list of :py:class:`emonitor.modules.cars.car.Car` objects """ return self._getCars(1, department) def getCars2(self, department): """ Get list of Car objects for cars2 of current alarmkey definition of given department :param department: id of department as integer :return: list of :py:class:`emonitor.modules.cars.car.Car` objects """ return self._getCars(2, department) def getMaterial(self, department): """ Get list of Car objects for material of current alarmkey definition of given department :param department: id of department as integer :return: list of :py:class:`emonitor.modules.cars.car.Car` objects """ return self._getCars(3, department) def hasDefinition(self, department): """ Get definition for current alarmkey of given department :param department: id of department :return: :py:class:`emonitor.modules.alarmkeys.alarmkey.Alarmkey` or *None* """ return AlarmkeyCars.getAlarmkeyCars(kid=self.id or 9999, dept=department) is None @staticmethod def getAlarmkeys(id=''): """ Get all alarmkey definitions or single definition with given 'id' :param id: id of alarmkey :return: list of defintions or single definition """ if id not in ['', 'None']: return Alarmkey.query.filter_by(id=id).first() else: return Alarmkey.query.order_by('category').all() @staticmethod def getAlarmkeysByName(name): """ Get Alarmkey object with given name :param name: name as string (like) :return: :py:class:`emonitor.modules.alarmkeys.alarmkey.Alarmkey` object """ return Alarmkey.query.filter(Alarmkey.key.like('%' + name + '%')).all() @staticmethod def getAlarmkeysByCategory(category): """ Get all alarmkey definitions of given category :param category: category as string :return: :py:class:`emonitor.modules.alarmkeys.alarmkey.Alarmkey` object list """ return Alarmkey.query.filter_by(category=category).all() @staticmethod def getAlarmkeysByCategoryId(categoryid): """ Get all alarmkey definitions of given category id :param category: category as string :return: :py:class:`emonitor.modules.alarmkeys.alarmkey.Alarmkey` object list """ key = Alarmkey.query.filter_by(id=categoryid).one() return Alarmkey.query.filter_by(category=key.category).all() @staticmethod def getAlarmkeysDict(): """ Get dict of all alarmkeys with alarmkey.id as dict key :return: dict of alarmkeys """ return dict(db.get(Alarmkey.id, Alarmkey).order_by(Alarmkey.key).all()) @staticmethod def getDefault(department): """ Get default alarmkey definition of given department :param department: id as integer :return: :py:class:`emonitor.modules.alarmkeys.alarmkey.Alarmkey` object """ return AlarmkeyCars.query.filter_by(kid=9999, dept=department).first() or AlarmkeyCars(9999, department, '', '', '')
class AlarmReport(db.Model): """ alarm report class for database definition """ __tablename__ = 'alarmreports' __table_args__ = {'extend_existing': True} id = db.Column(db.Integer, primary_key=True) name = db.Column(db.String(32)) filename = db.Column(db.TEXT) _reporttype = db.Column('reporttype', db.String(32)) _fields = db.Column('fields', db.Text) _dept = db.Column('dept', db.String(32)) def __init__(self, name, filename, reporttype, dept, fields=[]): self.name = name self.filename = filename self._reporttype = reporttype self._dept = dept self._fields = yaml.safe_dump(fields) @property def fields(self): """ load field definition from database :return: """ return yaml.load(self._fields) @fields.setter def fields(self, fields): """ save fields in yaml format in database :param fields: :return: """ self._fields = yaml.safe_dump(fields) def getFieldsJson(self): """ defliver field definition in json format for web-forms :return: """ return json.dumps(self.fields) @property def departments(self): try: return [int(m) for m in self._dept.split(',')] except ValueError: return [] @departments.setter def departments(self, departments): self._dept = ','.join(departments) @property def reporttype(self): if self._reporttype == 'internal': fname = "{}/emonitor/modules/alarms/templates/{}".format( current_app.config.get('PROJECT_ROOT'), self.filename) else: fname = "{}{}".format(current_app.config.get('PATH_DATA'), self.filename) return AlarmReportType(fname.replace('\\', '/'), rtype=self._reporttype) def getHTML(self, **params): return render_template('reports/{}'.format(self.filename), **params) def createReport(self, **kwargs): if 'ids' in kwargs: return self.reporttype.createReport(kwargs['ids'], self.fields) @staticmethod def getReportTypes(filename=""): from emonitor import app ret = [ AlarmReportType(f.replace('\\', '/')) for f in glob.glob( '{}/emonitor/modules/alarms/templates/report.*.html'.format( app.config.get('PROJECT_ROOT'))) ] ret.extend([ AlarmReportType(f.replace('\\', '/'), rtype="external") for f in glob.glob('{}alarmreports/*.*'.format( app.config.get('PATH_DATA'))) ]) if filename != "": # filter elements return filter(lambda x: x.filename == filename, ret)[0] return ret @staticmethod def getReports(id=0): if id == 0: return AlarmReport.query.all() else: return AlarmReport.query.filter_by(id=id).first()
class AlarmObject(db.Model): """AlarmObject class""" __tablename__ = 'alarmobjects' __table_args__ = {'extend_existing': True} id = db.Column(db.Integer, primary_key=True) name = db.Column(db.String(50)) _streetid = db.Column('streetid', db.ForeignKey('streets.id')) _objecttype = db.Column('typeid', db.ForeignKey('alarmobjecttypes.id')) _attributes = db.Column('attributes', db.Text) remark = db.Column(db.Text) lat = db.Column(db.Float) lng = db.Column(db.Float) zoom = db.Column(db.Integer) alarmplan = db.Column(db.String(5), default='') streetno = db.Column(db.String(10), default='') bma = db.Column(db.String(10), default='') active = db.Column(db.Integer) street = db.relationship(Street, collection_class=attribute_mapped_collection('id'), lazy='subquery') objecttype = db.relationship(AlarmObjectType, collection_class=attribute_mapped_collection('id'), lazy='subquery') files = db.relationship(AlarmObjectFile, collection_class=attribute_mapped_collection('id'), cascade="all, delete-orphan", lazy='subquery') def __init__(self, name, streetid, remark, lat, lng, zoom, alarmplan, streetno, bma, active, objecttype): self.name = name self._streetid = streetid self.remark = remark self.lat = lat self.lng = lng self.zoom = zoom self.alarmplan = alarmplan self.streetno = streetno self.bma = bma self.active = active self._objecttype = objecttype @property def serialize(self): return dict(id=self.id, name=self.name, lat=self.lat, lng=self.lng, zoom=self.zoom, alarmplan=self.alarmplan, street=self.street.serialize, streetno=self.streetno) def get(self, attribute, default=""): """ Getter for attribute names :param attribute: name of attribute as string :param optional default: default value :return: value of attribute """ try: values = yaml.load(self._attributes) return values[attribute] except: return default def set(self, attribute, val): """ Setter for attributes :param attribute: attribute name as string :param val: value as string """ try: values = yaml.load(self._attributes) except: values = {} values[attribute] = val self._attributes = yaml.safe_dump(values, encoding='utf-8') def get_cars_proto(self, ctype): """ Prototype of car, material getter :param ctype: 1:cars1, 2:cars2, 3:material :return: list of :py:class:`emonitor.modules.cars.car.Car` """ _t = {1: 'cars1', 2: 'cars2', 3: 'material'} ret = [] cars = Car.getCars() for _c in [int(c) for c in self.get(_t[ctype]) if c != '']: try: ret.append(filter(lambda c: c.id == _c, cars)[0]) except IndexError: pass return ret def getCars1(self): return self.get_cars_proto(1) def getCars2(self): return self.get_cars_proto(2) def getMaterial(self): return self.get_cars_proto(3) def hasOwnAAO(self): return len(self.get('cars1') + self.get('cars2') + self.get('material')) > 0 @staticmethod def getAlarmObjectsDict(): return dict((_o.id, _o) for _o in AlarmObject.query.order_by('name')) @staticmethod def getAlarmObjects(id=0, active=1): """ Get list of alarmobjects with given params :param id: id of alarmobject or *0* for all objects :param active: *1* for active objects or *0* for all objects :return: list of :py:class:`emonitor.modules.alarmobjects.alarmobject.AlarmObject` """ if id != 0: return AlarmObject.query.filter_by(id=id).first() else: if active == 1: # only active objects return AlarmObject.query.filter_by(active=1).order_by('name').all() else: # deliver all objects return AlarmObject.query.order_by('name').all()