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 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 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 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 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='') _keyset = db.Column('keyset', db.ForeignKey('alarmkeysets.id')) keyset = db.relationship( "AlarmkeySet", collection_class=attribute_mapped_collection('id')) keysetitem = db.Column(db.INTEGER, default=0) remark = db.Column(db.Text) def __init__(self, category, key, key_internal, remark, keyset=None, keysetitem=None): self.category = category self.key = key self.key_internal = key_internal self.remark = remark self._keyset = keyset self.keysetitem = keysetitem 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='', keysetid=None): """ Get all alarmkey definitions or single definition with given 'id' :param id: id of alarmkey :param keysetid: id of :py:class:`emonitor.modules.alarmkeys.AlarmkeySet` oder *None* :return: list of defintions or single definition """ if id not in ['', 'None']: return Alarmkey.query.filter_by(id=id).first() elif keysetid: if int(keysetid) == 0: # deliver all un-matched items return Alarmkey.query.filter_by( _keyset=None).order_by('category').all() return Alarmkey.query.filter_by( _keyset=keysetid).order_by('category').all() else: keyset = AlarmkeySet.getCurrentKeySet() if keyset is None: return Alarmkey.query.order_by('category').all() else: return Alarmkey.query.filter_by( _keyset=keyset.id).order_by('category').all() @staticmethod def getOrphanKeys(): """ Get list of all orphan alarmkeys :return: list of orphan alarmkeys """ return Alarmkey.query.filter_by(keyset=None).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, keysetid=None): """ Get all alarmkey definitions of given category id :param categoryid: category as string :param keysetid: keysetid as integer, 0 for un-matched, None for all :return: :py:class:`emonitor.modules.alarmkeys.alarmkey.Alarmkey` object list """ key = Alarmkey.query.filter_by(id=categoryid).one() if keysetid is None: return Alarmkey.query.filter_by(category=key.category).all() elif int(keysetid) == 0: return Alarmkey.query.filter_by(category=key.category, _keyset=None).all() else: return Alarmkey.query.filter( Alarmkey.category == key.category and Alarmkey._keyset == keysetid).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 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 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 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 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 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 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()