コード例 #1
0
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()
コード例 #2
0
ファイル: alarmattribute.py プロジェクト: sambandi/eMonitor
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
コード例 #3
0
ファイル: monitorserver.py プロジェクト: sambandi/eMonitor
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())
コード例 #4
0
ファイル: housenumber.py プロジェクト: sambandi/eMonitor
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)
コード例 #5
0
ファイル: alarmhistory.py プロジェクト: sambandi/eMonitor
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
コード例 #6
0
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
コード例 #7
0
ファイル: alarmfield.py プロジェクト: sambandi/eMonitor
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)
コード例 #8
0
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
コード例 #9
0
ファイル: printers.py プロジェクト: sambandi/eMonitor
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()
コード例 #10
0
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
コード例 #11
0
ファイル: car.py プロジェクト: sambandi/eMonitor
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
コード例 #12
0
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
コード例 #13
0
ファイル: city.py プロジェクト: sambandi/eMonitor
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()
コード例 #14
0
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
コード例 #15
0
ファイル: settings.py プロジェクト: sambandi/eMonitor
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()
コード例 #16
0
ファイル: eventhandler.py プロジェクト: sambandi/eMonitor
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()
コード例 #17
0
ファイル: alarmobjectfile.py プロジェクト: sambandi/eMonitor
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()
コード例 #18
0
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()
コード例 #19
0
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> "{}" &rarr; <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" &rarr; "%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" &rarr; "%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" &rarr; "%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
コード例 #20
0
ファイル: monitorlayout.py プロジェクト: sambandi/eMonitor
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(';')
コード例 #21
0
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
コード例 #22
0
ファイル: map.py プロジェクト: sambandi/eMonitor
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()
コード例 #23
0
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
コード例 #24
0
ファイル: persons.py プロジェクト: nordi81/eMonitor
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'))
コード例 #25
0
ファイル: alarmkey.py プロジェクト: sambandi/eMonitor
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, '', '', '')
コード例 #26
0
ファイル: alarmreport.py プロジェクト: sambandi/eMonitor
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()
コード例 #27
0
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()