def networks(network_id):
    pico_db = WallflowerDB()
    pico_db.database = config['database']

    # Check network id
    if network_id != config['network-id']:
        response = {
            'network-error':
            "The Wallflower-Pico server only allows for one network with the id "
            + config['network-id'],
            'network-code':
            400
        }
        return jsonify(**response)

    at = datetime.datetime.utcnow().isoformat() + 'Z'

    response = {'network-id': config['network-id']}

    if request.method == 'GET':
        # Read Network Details
        network_request = {'network-id': config['network-id']}

        pico_db.do(network_request, 'read', 'network',
                   (config['network-id'], ), at)
        response.update(pico_db.db_message)

        return jsonify(**response)
def networks(network_id):
    pico_db = WallflowerDB()
    pico_db.database = config['database']

    # Check network id
    if network_id != config['network-id']:
        response = {
            'network-error': "The Wallflower-Pico server only allows for one network with the id "+config['network-id'],
            'network-code': 400
        }
        return jsonify(**response)

    at = datetime.datetime.utcnow().isoformat() + 'Z'

    response = {
        'network-id': config['network-id']
    }

    if request.method == 'GET':
        # Read Network Details
        network_request = {
            'network-id': config['network-id']
        }

        pico_db.do(network_request,'read','network',(config['network-id'],),at)
        response.update( pico_db.db_message )

        return jsonify(**response)
def points(object_id,stream_id):
    pico_db = WallflowerDB()
    pico_db.database = config['database']

    at = datetime.datetime.utcnow().isoformat() + 'Z'

    points_request = {
        'stream-id': stream_id,
        'points': []
    }

    response = {
        'network-id': config['network-id'],
        'object-id': object_id,
        'stream-id': stream_id
    }

    if request.method == 'GET':
        # Read Points (Use Search Instead Of Read)
        # Max number of data points (Optional)
        limit = request.args.get('points-limit',None,type=int)
        # Start date/time (Optional)
        start = request.args.get('points-start',None,type=str)
        # End date/time (Optional)
        end = request.args.get('points-end',None,type=str)

        # Points Search Input
        point_search = {}
        if limit is not None and isinstance(limit,int):
            point_search['limit'] = limit
        if start is not None and isinstance(start,str):
            point_search['start'] = start
        if end is not None and isinstance(end,str):
            point_search['end'] = end

        points_request['points'] = point_search

        pico_db.do(points_request,'search','points',(config['network-id'],object_id,stream_id),at)
        response.update( pico_db.db_message )

    elif request.method == 'POST':
        # Update Points
        # Point value (Required)
        point_value = request.args.get('points-value',None)
        if point_value is None:
            response['points-code'] = 406
            response['points-message'] = 'No value received'
            return jsonify(**response)

        # At date/time (Optional)
        point_at = request.args.get('points-at',at,type=str)
        try:
            datetime.datetime.strptime(point_at, "%Y-%m-%dT%H:%M:%S.%fZ")
        except:
            response['points-code'] = 400
            response['points-message'] = 'Invalid timestamp'
            return jsonify(**response)

        points = [{
            'value': point_value,
            'at': point_at
        }]

        points_request['points'] = points

        pico_db.do(points_request,'update','points',(config['network-id'],object_id,stream_id),at)
        response.update( pico_db.db_message )

        if config['enable_ws'] and response['points-code'] == 200:
            response['response-type'] = 'points-update'
            factory.broadcast( json.dumps(response) )

    return jsonify(**response)
def streams(object_id,stream_id):
    pico_db = WallflowerDB()
    pico_db.database = config['database']

    at = datetime.datetime.utcnow().isoformat() + 'Z'

    stream_request = {
        'stream-id': stream_id
    }

    response = {
        'network-id': config['network-id'],
        'object-id': object_id,
        'stream-id': stream_id
    }

    if request.method == 'GET': # Read
        # Read Object Details
        pico_db.do(stream_request,'read','stream',(config['network-id'],object_id,stream_id),at)
        response.update( pico_db.db_message )

    elif request.method == 'PUT': # Create
        # Create Stream
        stream_request['stream-details'] = {
            'stream-name': object_id,
            'stream-type': 'data'
        }
        stream_request['points-details'] = {
            'points-type': 'i',
            'points-length': 0
        }
        stream_name = request.args.get('stream-name',None,type=str)
        if stream_name is not None:
            stream_request['stream-details']['stream-name'] = stream_name

        points_type = request.args.get('points-type',None,type=str)
        if stream_name is not None and points_type in ['i','f','s']:
            stream_request['points-details']['points-type'] = points_type

        pico_db.do(stream_request,'create','stream',(config['network-id'],object_id,stream_id),at)
        response.update( pico_db.db_message )

        if config['enable_ws'] and response['stream-code'] == 201:
            response['response-type'] = 'stream-create'
            factory.broadcast( json.dumps(response) )

    elif request.method == 'POST':
        # Update Object Details
        stream_request['stream-details'] = {
            'object-name': object_id
        }
        stream_name = request.args.get('stream-name',None,type=str)
        if stream_name is not None:
            stream_request['stream-details']['stream-name'] = stream_name

        pico_db.do(stream_request,'update','stream',(config['network-id'],object_id,stream_id),at)
        response.update( pico_db.db_message )

        if config['enable_ws'] and response['stream-code'] == 200:
            response['response-type'] = 'stream-update'
            factory.broadcast( json.dumps(response) )

    elif request.method == 'DELETE':
        # Delete Object
        pico_db.do(stream_request,'delete','stream',(config['network-id'],object_id,stream_id),at)
        response.update( pico_db.db_message )

        if config['enable_ws'] and response['stream-code'] == 200:
            response['response-type'] = 'stream-delete'
            factory.broadcast( json.dumps(response) )

    return jsonify(**response)
def objects(object_id):
    pico_db = WallflowerDB()
    pico_db.database = config['database']

    at = datetime.datetime.utcnow().isoformat() + 'Z'

    object_request = {
        'object-id': object_id
    }

    response = {
        'network-id': config['network-id'],
        'object-id': object_id
    }

    if request.method == 'GET': # Read
        # Read Object Details
        pico_db.do(object_request,'read','object',(config['network-id'],object_id),at)
        response.update( pico_db.db_message )

    elif request.method == 'PUT': # Create
        # Create Object
        object_request['object-details'] = {
            'object-name': object_id
        }
        object_name = request.args.get('object-name',None,type=str)
        if object_name is not None:
            object_request['object-details']['object-name'] = object_name

        pico_db.do(object_request,'create','object',(config['network-id'],object_id),at)
        response.update( pico_db.db_message )

        # Broadcast response over websocket
        if config['enable_ws'] and response['object-code'] == 201:
            response['response-type'] = 'object-create'
            factory.broadcast( json.dumps(response) )

    elif request.method == 'POST':
        # Update Object Details
        object_request['object-details'] = {
            'object-name': object_id
        }
        object_name = request.args.get('object-name',None,type=str)
        if object_name is not None:
            object_request['object-details']['object-name'] = object_name

        pico_db.do(object_request,'update','object',(config['network-id'],object_id),at)
        response.update( pico_db.db_message )

        # Broadcast response over websocket
        if config['enable_ws'] and response['object-code'] == 200:
            response['response-type'] = 'object-update'
            factory.broadcast( json.dumps(response) )

    elif request.method == 'DELETE':
        # Delete Object
        pico_db.do(object_request,'delete','object',(config['network-id'],object_id),at)
        response.update( pico_db.db_message )

        if config['enable_ws'] and response['object-code'] == 200:
            response['response-type'] = 'object-delete'
            factory.broadcast( json.dumps(response) )

    return jsonify(**response)
                self.clients.remove(client)

        def broadcast(self, msg):
            print("Broadcasting message '{}' ..".format(msg))
            for c in self.clients:
                c.sendMessage(msg.encode('utf8'))
                print("Message sent to {}".format(c.peer))



if __name__ == '__main__':
    # Check if the network exists and create, if necessary
    at = datetime.datetime.utcnow().isoformat() + 'Z'

    with app.app_context():
        pico_db = WallflowerDB()
        pico_db.database = config['database']

        # Create wcc_networks table, if necessary
        pico_db.execute( 'CREATE TABLE IF NOT EXISTS wcc_networks (timestamp date, network_id text, network_record text)' )

        # Check if default network exists
        exists = pico_db.loadNetworkRecord(config['network-id'])
        if not exists:
            # Create the default network
            network_request = {
                'network-id': config['network-id'],
                'network-details': {
                    'network-name': 'Local Wallflower.cc Network'
                }
            }
def points(object_id, stream_id):
    pico_db = WallflowerDB()
    pico_db.database = config['database']

    at = datetime.datetime.utcnow().isoformat() + 'Z'

    points_request = {'stream-id': stream_id, 'points': []}

    response = {
        'network-id': config['network-id'],
        'object-id': object_id,
        'stream-id': stream_id
    }

    if request.method == 'GET':
        # Read Points (Use Search Instead Of Read)
        # Max number of data points (Optional)
        limit = request.args.get('points-limit', None, type=int)
        # Start date/time (Optional)
        start = request.args.get('points-start', None, type=str)
        # End date/time (Optional)
        end = request.args.get('points-end', None, type=str)

        # Points Search Input
        point_search = {}
        if limit is not None and isinstance(limit, int):
            point_search['limit'] = limit
        if start is not None and isinstance(start, str):
            point_search['start'] = start
        if end is not None and isinstance(end, str):
            point_search['end'] = end

        points_request['points'] = point_search

        pico_db.do(points_request, 'search', 'points',
                   (config['network-id'], object_id, stream_id), at)
        response.update(pico_db.db_message)

    elif request.method == 'POST':
        # Update Points
        # Point value (Required)
        point_value = request.args.get('points-value', None)
        if point_value is None:
            response['points-code'] = 406
            response['points-message'] = 'No value received'
            return jsonify(**response)

        # At date/time (Optional)
        point_at = request.args.get('points-at', at, type=str)
        try:
            datetime.datetime.strptime(point_at, "%Y-%m-%dT%H:%M:%S.%fZ")
        except:
            response['points-code'] = 400
            response['points-message'] = 'Invalid timestamp'
            return jsonify(**response)

        points = [{'value': point_value, 'at': point_at}]

        points_request['points'] = points

        pico_db.do(points_request, 'update', 'points',
                   (config['network-id'], object_id, stream_id), at)
        response.update(pico_db.db_message)

        if config['enable_ws'] and response['points-code'] == 200:
            response['response-type'] = 'points-update'
            factory.broadcast(json.dumps(response))

    return jsonify(**response)
def streams(object_id, stream_id):
    pico_db = WallflowerDB()
    pico_db.database = config['database']

    at = datetime.datetime.utcnow().isoformat() + 'Z'

    stream_request = {'stream-id': stream_id}

    response = {
        'network-id': config['network-id'],
        'object-id': object_id,
        'stream-id': stream_id
    }

    if request.method == 'GET':  # Read
        # Read Object Details
        pico_db.do(stream_request, 'read', 'stream',
                   (config['network-id'], object_id, stream_id), at)
        response.update(pico_db.db_message)

    elif request.method == 'PUT':  # Create
        # Create Stream
        stream_request['stream-details'] = {
            'stream-name': object_id,
            'stream-type': 'data'
        }
        stream_request['points-details'] = {
            'points-type': 'i',
            'points-length': 0
        }
        stream_name = request.args.get('stream-name', None, type=str)
        if stream_name is not None:
            stream_request['stream-details']['stream-name'] = stream_name

        points_type = request.args.get('points-type', None, type=str)
        if stream_name is not None and points_type in ['i', 'f', 's']:
            stream_request['points-details']['points-type'] = points_type

        pico_db.do(stream_request, 'create', 'stream',
                   (config['network-id'], object_id, stream_id), at)
        response.update(pico_db.db_message)

        if config['enable_ws'] and response['stream-code'] == 201:
            response['response-type'] = 'stream-create'
            factory.broadcast(json.dumps(response))

    elif request.method == 'POST':
        # Update Object Details
        stream_request['stream-details'] = {'object-name': object_id}
        stream_name = request.args.get('stream-name', None, type=str)
        if stream_name is not None:
            stream_request['stream-details']['stream-name'] = stream_name

        pico_db.do(stream_request, 'update', 'stream',
                   (config['network-id'], object_id, stream_id), at)
        response.update(pico_db.db_message)

        if config['enable_ws'] and response['stream-code'] == 200:
            response['response-type'] = 'stream-update'
            factory.broadcast(json.dumps(response))

    elif request.method == 'DELETE':
        # Delete Object
        pico_db.do(stream_request, 'delete', 'stream',
                   (config['network-id'], object_id, stream_id), at)
        response.update(pico_db.db_message)

        if config['enable_ws'] and response['stream-code'] == 200:
            response['response-type'] = 'stream-delete'
            factory.broadcast(json.dumps(response))

    return jsonify(**response)
def objects(object_id):
    pico_db = WallflowerDB()
    pico_db.database = config['database']

    at = datetime.datetime.utcnow().isoformat() + 'Z'

    object_request = {'object-id': object_id}

    response = {'network-id': config['network-id'], 'object-id': object_id}

    if request.method == 'GET':  # Read
        # Read Object Details
        pico_db.do(object_request, 'read', 'object',
                   (config['network-id'], object_id), at)
        response.update(pico_db.db_message)

    elif request.method == 'PUT':  # Create
        # Create Object
        object_request['object-details'] = {'object-name': object_id}
        object_name = request.args.get('object-name', None, type=str)
        if object_name is not None:
            object_request['object-details']['object-name'] = object_name

        pico_db.do(object_request, 'create', 'object',
                   (config['network-id'], object_id), at)
        response.update(pico_db.db_message)

        # Broadcast response over websocket
        if config['enable_ws'] and response['object-code'] == 201:
            response['response-type'] = 'object-create'
            factory.broadcast(json.dumps(response))

    elif request.method == 'POST':
        # Update Object Details
        object_request['object-details'] = {'object-name': object_id}
        object_name = request.args.get('object-name', None, type=str)
        if object_name is not None:
            object_request['object-details']['object-name'] = object_name

        pico_db.do(object_request, 'update', 'object',
                   (config['network-id'], object_id), at)
        response.update(pico_db.db_message)

        # Broadcast response over websocket
        if config['enable_ws'] and response['object-code'] == 200:
            response['response-type'] = 'object-update'
            factory.broadcast(json.dumps(response))

    elif request.method == 'DELETE':
        # Delete Object
        pico_db.do(object_request, 'delete', 'object',
                   (config['network-id'], object_id), at)
        response.update(pico_db.db_message)

        if config['enable_ws'] and response['object-code'] == 200:
            response['response-type'] = 'object-delete'
            factory.broadcast(json.dumps(response))

    return jsonify(**response)
                print("Unregistered client {}".format(client.peer))
                self.clients.remove(client)

        def broadcast(self, msg):
            print("Broadcasting message '{}' ..".format(msg))
            for c in self.clients:
                c.sendMessage(msg.encode('utf8'))
                print("Message sent to {}".format(c.peer))


if __name__ == '__main__':
    # Check if the network exists and create, if necessary
    at = datetime.datetime.utcnow().isoformat() + 'Z'

    with app.app_context():
        pico_db = WallflowerDB()
        pico_db.database = config['database']

        # Create wcc_networks table, if necessary
        pico_db.execute(
            'CREATE TABLE IF NOT EXISTS wcc_networks (timestamp date, network_id text, network_record text)'
        )

        # Check if default network exists
        exists = pico_db.loadNetworkRecord(config['network-id'])
        if not exists:
            # Create the default network
            network_request = {
                'network-id': config['network-id'],
                'network-details': {
                    'network-name': 'Local Wallflower.cc Network'