Beispiel #1
0
def generate_mqtt_info():
    if current_user.is_authenticated and 'MQTT_HOST' in app.config:
        return {
            'host': app.config['MQTT_HOST'],
            'port': app.config.get('MQTT_PORT', 443),
            'token': message_auth_token(current_user.id),
            'clientId': '%d-%d' % (current_user.id, random.randint(
                0, 10000000)),  # fix: reconsider client IDs
            'enableOld': int(app.config.get('ENABLE_OLD_MESSAGING', False)),
        }
    else:
        return {}
Beispiel #2
0
    def connect(self):
        from main.users.auth import message_auth_token

        def on_connect(client, userdata, flags, rc):
            # pylint: disable=unused-argument
            if rc:
                print('unable to connect to MQTT broker/server at %s:%d' % (self.mqtt_host, self.mqtt_port))
            else:
                print('connected to MQTT broker/server at %s:%d' % (self.mqtt_host, self.mqtt_port))
        self.mqtt_client = mqtt.Client(transport='websockets')
        self.mqtt_client.on_connect = on_connect
        self.mqtt_client.username_pw_set('token', message_auth_token(0))  # user_id 0 indicates that this is an internal connection from the server
        if self.mqtt_tls:
            self.mqtt_client.tls_set()  # enable SSL
        self.mqtt_client.connect(self.mqtt_host, self.mqtt_port)
        self.mqtt_client.loop_start()
def generate_mqtt_info():
    if current_user.is_authenticated and app.config['MQTT_HOST']:
        info = {
            'token': message_auth_token(current_user.id),
            'clientId': '%d-%d' % (current_user.id, random.randint(0, 10000000)),  # fix: reconsider client IDs
            'enableOld': int(app.config.get('ENABLE_OLD_MESSAGING', False)),
            'ssl': app.config['MQTT_TLS'],
        }

        if not app.config['WEB_MQTT_SAME_HOST']:
            info['host'] = app.config['MQTT_HOST']
        if not app.config['WEB_MQTT_SAME_PORT']:
            info['port'] = app.config['MQTT_PORT']
    else:
        info = {}

    return info
Beispiel #4
0
def message_monitor():
    server_config = load_server_config()
    if 'MQTT_HOST' not in server_config:
        worker_log('message_monitor', 'MQTT host not configured')
        return
    worker_log('message_monitor', 'starting')
    mqtt_host = server_config['MQTT_HOST']
    mqtt_port = server_config.get('MQTT_PORT', 443)

    # run this on connect/reconnect
    def on_connect(client, userdata, flags, rc):
        # pylint: disable=unused-argument
        if rc:
            worker_log(
                'message_monitor',
                'unable to connect to MQTT broker/server at %s:%d' %
                (mqtt_host, mqtt_port))
        else:
            worker_log(
                'message_monitor', 'connected to MQTT broker/server at %s:%d' %
                (mqtt_host, mqtt_port))
        client.subscribe('#')  # subscribe to all messages

    # run this on message
    def on_message(client, userdata, msg):
        # pylint: disable=unused-argument
        payload = msg.payload.decode()

        # handle full (JSON) messages
        if payload.startswith('{'):
            message_struct = json.loads(payload)
            for message_type, parameters in message_struct.items():

                # update sequence values; doesn't support image sequence; should use REST API for image sequences
                if message_type == 'update':
                    folder = find_resource(
                        '/' + msg.topic
                    )  # for now we assume these messages are published on controller channels
                    if folder and folder.type in (Resource.BASIC_FOLDER,
                                                  Resource.ORGANIZATION_FOLDER,
                                                  Resource.CONTROLLER_FOLDER):
                        timestamp = parameters.get('$t', '')
                        if timestamp:
                            timestamp = parse_json_datetime(
                                timestamp
                            )  # fix(soon): handle conversion errors
                        else:
                            timestamp = datetime.datetime.utcnow()
                        for name, value in parameters.items():
                            if name != '$t':
                                seq_name = '/' + msg.topic + '/' + name
                                resource = find_resource(seq_name)
                                if resource:
                                    # don't emit new message since UI will receive this message
                                    update_sequence_value(resource,
                                                          seq_name,
                                                          timestamp,
                                                          value,
                                                          emit_message=False)
                                    db.session.commit()

                # update controller watchdog status
                elif message_type == 'watchdog':
                    controller = find_resource(
                        '/' + msg.topic
                    )  # for now we assume these messages are published on controller channels
                    if controller and controller.type == Resource.CONTROLLER_FOLDER:
                        controller_status = ControllerStatus.query.filter(
                            ControllerStatus.id == controller.id).one()
                        controller_status.last_watchdog_timestamp = datetime.datetime.utcnow(
                        )
                        db.session.commit()

                # send emails
                elif message_type == 'send_email':
                    controller = find_resource(
                        '/' + msg.topic
                    )  # for now we assume these messages are published on controller channels
                    if controller and controller.type == Resource.CONTROLLER_FOLDER:
                        print('sending email')
                        handle_send_email(controller.id, parameters)

                # send SMS messages
                elif message_type == 'send_sms' or message_type == 'send_text_message':
                    controller = find_resource(
                        '/' + msg.topic
                    )  # for now we assume these messages are published on controller channels
                    if controller and controller.type == Resource.CONTROLLER_FOLDER:
                        handle_send_text_message(controller.id, parameters)

        # handle short (non-JSON) messages
        else:
            # print('MQTT: %s %s' % (msg.topic, payload))
            if payload.startswith(
                    's,'
            ):  # type 's' is "store and display new sequence value"
                parts = payload.split(',', 3)
                if len(parts) == 4:
                    seq_name = '/' + msg.topic + '/' + parts[1]
                    timestamp = parse_json_datetime(
                        parts[2])  # fix(soon): handle conversion errors
                    value = parts[3]
                    resource = find_resource(seq_name)
                    if resource and resource.type == Resource.SEQUENCE:
                        # don't emit new message since UI will receive this message
                        update_sequence_value(resource,
                                              seq_name,
                                              timestamp,
                                              value,
                                              emit_message=False)
                        db.session.commit()

    # connect and run
    mqtt_client = mqtt.Client(transport='websockets')
    mqtt_client.on_connect = on_connect
    mqtt_client.on_message = on_message
    mqtt_client.username_pw_set(
        'token', message_auth_token(0)
    )  # user_id 0 indicates that this is an internal connection from the server
    mqtt_client.tls_set()  # enable SSL
    mqtt_client.connect(mqtt_host, mqtt_port)
    mqtt_client.loop_start()
    while True:
        gevent.sleep(60)
Beispiel #5
0
def message_monitor():
    server_config = load_server_config()
    if 'MQTT_HOST' not in server_config:
        worker_log('message_monitor', 'MQTT host not configured')
        return
    worker_log('message_monitor', 'starting')
    mqtt_host = server_config['MQTT_HOST']
    mqtt_port = server_config.get('MQTT_PORT', 443)

    # run this on connect/reconnect
    def on_connect(client, userdata, flags, rc):
        # pylint: disable=unused-argument
        if rc:
            worker_log('message_monitor', 'unable to connect to MQTT broker/server at %s:%d' % (mqtt_host, mqtt_port))
        else:
            worker_log('message_monitor', 'connected to MQTT broker/server at %s:%d' % (mqtt_host, mqtt_port))
        client.subscribe('#')  # subscribe to all messages

    # run this on message
    def on_message(client, userdata, msg):
        # pylint: disable=unused-argument
        # print('MQTT: %s %s' % (msg.topic, msg.payload.decode()))
        message_struct = json.loads(msg.payload.decode())
        message_type = message_struct['type']
        if message_type == 'update_sequence':
            controller = find_resource('/' + msg.topic)  # for now we assume these messages are published on controller channels
            if controller and controller.type == Resource.CONTROLLER_FOLDER:
                parameters = message_struct['parameters']
                seq_name = parameters['sequence']
                if not seq_name.startswith('/'):  # handle relative sequence names
                    resource = Resource.query.filter(Resource.id == controller.id).one()
                    # this is ok for now since .. doesn't have special meaning in resource path (no way to escape controller folder)
                    seq_name = resource.path() + '/' + seq_name
                timestamp = parameters.get('timestamp', '')  # fix(soon): need to convert to datetime
                if not timestamp:
                    timestamp = datetime.datetime.utcnow()
                value = parameters['value']
                if 'encoded' in parameters:
                    value = base64.b64decode(value)

                # remove this; require clients to use REST POST for images
                resource = find_resource(seq_name)
                if not resource:
                    return
                system_attributes = json.loads(resource.system_attributes) if resource.system_attributes else None
                if system_attributes and system_attributes['data_type'] == Resource.IMAGE_SEQUENCE:
                    value = base64.b64decode(value)
                else:
                    value = str(value)

                # don't emit message since the message is already in the system
                update_sequence_value(resource, seq_name, timestamp, value, emit_message=False)
                db.session.commit()

        # update controller watchdog status
        elif message_type == 'watchdog':
            controller = find_resource('/' + msg.topic)  # for now we assume these messages are published on controller channels
            if controller and controller.type == Resource.CONTROLLER_FOLDER:
                controller_status = ControllerStatus.query.filter(ControllerStatus.id == controller.id).one()
                controller_status.last_watchdog_timestamp = datetime.datetime.utcnow()
                db.session.commit()

        # send emails
        elif message_type == 'send_email':
            controller = find_resource('/' + msg.topic)  # for now we assume these messages are published on controller channels
            if controller and controller.type == Resource.CONTROLLER_FOLDER:
                print('sending email')
                handle_send_email(controller.id, message_struct['parameters'])

        # send SMS messages
        elif message_type == 'send_sms' or message_type == 'send_text_message':
            controller = find_resource('/' + msg.topic)  # for now we assume these messages are published on controller channels
            if controller and controller.type == Resource.CONTROLLER_FOLDER:
                handle_send_text_message(controller.id, message_struct['parameters'])

    # connect and run
    mqtt_client = mqtt.Client(transport='websockets')
    mqtt_client.on_connect = on_connect
    mqtt_client.on_message = on_message
    mqtt_client.username_pw_set('token', message_auth_token(0))  # user_id 0 indicates that this is an internal connection from the server
    mqtt_client.tls_set()  # enable SSL
    mqtt_client.connect(mqtt_host, mqtt_port)
    mqtt_client.loop_start()
    while True:
        gevent.sleep(60)