Esempio n. 1
0
def put_data(jsonString,
             headerLength,
             filedesc=None,
             powers=None,
             streamOccupancies=None):
    """
    put data in the database. jsonString starts with {. If filedesc is None
    then the data part of the message is appended to the message (immediately follows it).
    Otherwise, the data is read from filedesc.
    """

    start_time = time.time()

    if filedesc is None:
        # We are not reading from a file:
        # Assume we are given the message in the string with the data
        # tacked at the end of it.
        jsonStringBytes = jsonString[0:headerLength]
    else:
        jsonStringBytes = jsonString

    util.debugPrint("jsonStringBytes = " + jsonStringBytes)
    jsonData = json.loads(jsonStringBytes)
    sensorId = jsonData[SENSOR_ID]
    sensorKey = jsonData[SENSOR_KEY]
    if not authentication.authenticateSensor(sensorId, sensorKey):
        raise Exception("Sensor Authentication Failure")

    sensorObj = SensorDb.getSensorObj(sensorId)
    if not sensorObj.getSensorStatus() == ENABLED:
        raise Exception("Sensor is disabled")

    # remove the sensor key from metadata for safety.
    del jsonData[SENSOR_KEY]

    locationPosts = DbCollections.getLocationMessages()
    systemPosts = DbCollections.getSystemMessages()
    dataPosts = DbCollections.getDataMessages(sensorId)
    db = DbCollections.getSpectrumDb()
    currentLocalTime = time.time()
    Message.setInsertionTime(jsonData, currentLocalTime)
    if jsonData[TYPE] == SYS:
        # see if this system message already exists in the DB to avoid duplicates.
        query = {SENSOR_ID: jsonData[SENSOR_ID], "t": jsonData["t"]}
        found = systemPosts.find_one(query)
        if CAL in jsonData:
            calStr = jsonData[CAL]
            # Ugly!! Need to fix this.
            if calStr != "N/A":
                n = jsonData[CAL]["mPar"]["n"]
                nM = jsonData[CAL]["nM"]
                sensorId = jsonData[SENSOR_ID]
                if n * nM != 0:
                    dataType = jsonData[CAL][DATA_TYPE]
                    lengthToRead = n * nM
                    if filedesc is not None:
                        messageBytes = readDataFromFileDesc(
                            filedesc, dataType, lengthToRead)
                    elif powers is None:
                        messageBytes = jsonString[headerLength:]
                    else:
                        # TODO -- deal with the other data types here
                        messageBytes = struct.pack('%sb' % len(powers),
                                                   *powers)
                fs = gridfs.GridFS(db, jsonData[SENSOR_ID] + "_data")
                key = fs.put(messageBytes)
                jsonData[CAL][DATA_KEY] = str(key)

        if found is None:
            systemPosts.ensure_index([('t', pymongo.DESCENDING)])
            systemPosts.insert(jsonData)
        else:
            util.debugPrint("not inserting duplicate system post")
        end_time = time.time()
        util.debugPrint("Insertion time " + str(end_time - start_time))
        sensorObj.updateSystemMessageTimeStamp(Message.getTime(jsonData))
        SensorDb.updateSensor(sensorObj.getJson(), False, False)
    elif jsonData[TYPE] == LOC:
        print(json.dumps(jsonData, sort_keys=True, indent=4))
        sensorId = jsonData[SENSOR_ID]
        t = jsonData['t']
        lat = jsonData[LAT]
        lon = jsonData[LON]
        alt = jsonData[ALT]
        query = {SENSOR_ID: sensorId, LAT: lat, LON: lon, ALT: alt}
        locMsg = locationPosts.find_one(query)
        if locMsg is not None:
            print "Location Post already exists - not updating "
            return
        (to_zone,
         timeZoneName) = timezone.getLocalTimeZoneFromGoogle(t, lat, lon)
        # If google returned null, then override with local information
        if to_zone is None:
            if TIME_ZONE_KEY in jsonData:
                to_zone = jsonData[TIME_ZONE_KEY]
            else:
                raise Exception("ERROR: Unable to determine timeZone ")
        else:
            jsonData[TIME_ZONE_KEY] = to_zone
        # insert the loc message into the database.
        db.locationMessages.ensure_index([('t', pymongo.DESCENDING)])
        locationPosts.insert(jsonData)
        end_time = time.time()
        sensorObj.updateLocationMessageTimeStamp(Message.getTime(jsonData))
        SensorDb.updateSensor(sensorObj.getJson(), False, False)
        print "inserted Location Message. Insertion time " + str(end_time -
                                                                 start_time)
    elif jsonData[TYPE] == DATA:
        # BUG BUG -- we need to fix this. Need new data.
        if SYS_TO_DETECT not in jsonData:
            jsonData[SYS_TO_DETECT] = "LTE"
        # Fix up issue with sys2detect - should have no spaces.
        # BUGBUG -- this is ugly. Should reject the data.
        jsonData[SYS_TO_DETECT] = jsonData[SYS_TO_DETECT].replace(" ", "")
        DataMessage.init(jsonData)

        freqRange = DataMessage.getFreqRange(jsonData)
        if freqRange not in sensorObj.getThreshold():
            raise Exception("ERROR: Frequency Band  " + freqRange +
                            " not found")

        lastSystemPost = systemPosts.find_one({
            SENSOR_ID: sensorId,
            "t": {
                "$lte": Message.getTime(jsonData)
            }
        })
        lastLocationPost = locationPosts.find_one({
            SENSOR_ID: sensorId,
            "t": {
                "$lte": Message.getTime(jsonData)
            }
        })
        if lastLocationPost is None or lastSystemPost is None:
            raise Exception("Location post or system post not found for " +
                            sensorId)
        # Check for duplicates
        query = {SENSOR_ID: sensorId, "t": Message.getTime(jsonData)}
        found = DbCollections.getDataMessages(sensorId).find_one(query)
        # record the location message associated with the data.
        DataMessage.setLocationMessageId(jsonData,
                                         str(lastLocationPost['_id']))
        DataMessage.setSystemMessageId(jsonData, str(lastSystemPost['_id']))
        # prev data message.
        nM = DataMessage.getNumberOfMeasurements(jsonData)
        n = DataMessage.getNumberOfFrequencyBins(jsonData)
        lengthToRead = n * nM
        dataType = DataMessage.getDataType(jsonData)
        if lengthToRead != 0:
            if filedesc is not None:
                messageBytes = readDataFromFileDesc(filedesc, dataType,
                                                    lengthToRead)
            elif powers is None:
                messageBytes = jsonString[headerLength:]
            else:
                # TODO - deal with the other data types here.
                messageBytes = struct.pack("%sb" % len(powers), *powers)

        occupancyBytes = None
        if streamOccupancies is not None:
            occupancyBytes = struct.pack("%sb" % len(streamOccupancies),
                                         *streamOccupancies)

            # Note: The data needs to be read before it is rejected.
        if found is not None:
            util.debugPrint("ignoring duplicate data message")
            return

        if lengthToRead != 0:
            fs = gridfs.GridFS(db, sensorId + "_data")
            key = fs.put(messageBytes)
            DataMessage.setDataKey(jsonData, str(key))

        if occupancyBytes is not None:
            key = fs.put(occupancyBytes)
            DataMessage.setOccupancyKey(jsonData, str(key))
            DataMessage.setOccupancyVectorLength(jsonData, len(occupancyBytes))

        cutoff = DataMessage.getThreshold(jsonData)
        sensorMeasurementType = SensorDb.getSensor(sensorId)[MEASUREMENT_TYPE]
        if DataMessage.getMeasurementType(jsonData) != sensorMeasurementType:
            raise Exception(
                "MeasurementType Mismatch between sensor and DataMessage")

        #dataPosts.ensure_index([('t', pymongo.ASCENDING)])
        maxPower = -1000
        minPower = 1000
        if DataMessage.getMeasurementType(jsonData) == FFT_POWER:
            occupancyCount = [0 for i in range(0, nM)]
            if powers is None:
                powerVal = np.array(np.zeros(n * nM))
            else:
                powerVal = np.array(powers)
            # unpack the power array.
            if dataType == BINARY_INT8 and powers is None:
                for i in range(0, lengthToRead):
                    powerVal[i] = struct.unpack('b', messageBytes[i:i + 1])[0]
            maxPower = np.max(powerVal)
            minPower = np.min(powerVal)
            powerArray = powerVal.reshape(nM, n)
            for i in range(0, nM):
                occupancyCount[i] = float(
                    len(filter(lambda x: x >= cutoff,
                               powerArray[i, :]))) / float(n)
            minOccupancy = np.min(occupancyCount)
            maxOccupancy = np.max(occupancyCount)
            meanOccupancy = np.mean(occupancyCount)
            medianOccupancy = np.median(occupancyCount)
            DataMessage.setMaxOccupancy(jsonData, maxOccupancy)
            DataMessage.setMeanOccupancy(jsonData, meanOccupancy)
            DataMessage.setMinOccupancy(jsonData, minOccupancy)
            DataMessage.setMedianOccupancy(jsonData, medianOccupancy)
            if DataMessage.isProcessed(jsonData):
                sensorObj.updateMinOccupancy(freqRange, minOccupancy)
                sensorObj.updateMaxOccupancy(freqRange, maxOccupancy)
                sensorObj.updateOccupancyCount(freqRange, meanOccupancy)
                LocationMessage.updateMaxBandOccupancy(lastLocationPost,
                                                       freqRange, maxOccupancy)
                LocationMessage.updateMinBandOccupancy(lastLocationPost,
                                                       freqRange, minOccupancy)
                LocationMessage.updateOccupancySum(lastLocationPost, freqRange,
                                                   meanOccupancy)

        else:
            if dataType == ASCII:
                powerVal = eval(messageBytes)
            else:
                for i in range(0, lengthToRead):
                    powerVal[i] = struct.unpack('f', messageBytes[i:i + 4])[0]
            maxPower = np.max(powerVal)
            minPower = np.min(powerVal)
            occupancyCount = float(len(filter(lambda x: x >= cutoff,
                                              powerVal)))
            occupancy = occupancyCount / float(len(powerVal))
            DataMessage.setOccupancy(jsonData, occupancy)
            if DataMessage.isProcessed(jsonData):
                sensorObj.updateMinOccupancy(freqRange, occupancy)
                sensorObj.updateMaxOccupancy(freqRange, occupancy)
                sensorObj.updateOccupancyCount(freqRange, occupancy)
                LocationMessage.updateMaxBandOccupancy(lastLocationPost,
                                                       freqRange, occupancy)
                LocationMessage.updateMinBandOccupancy(lastLocationPost,
                                                       freqRange, occupancy)
                LocationMessage.updateOccupancySum(lastLocationPost, freqRange,
                                                   occupancy)

        sensorObj.updateTime(freqRange, Message.getTime(jsonData))
        sensorObj.updateDataMessageTimeStamp(Message.getTime(jsonData))
        SensorDb.updateSensor(sensorObj.getJson(), False, False)
        DataMessage.setMaxPower(jsonData, maxPower)
        DataMessage.setMinPower(jsonData, minPower)
        #if filedesc is not None:
        #    print json.dumps(jsonData, sort_keys=True, indent=4)
        if DataMessage.isProcessed(jsonData):
            dataPosts.insert(jsonData)
        else:
            DbCollections.getUnprocessedDataMessages(sensorId).insert(jsonData)

        # Update location specific information for this sensor.

        LocationMessage.addFreqRange(lastLocationPost, freqRange)
        LocationMessage.setMessageTimeStampForBand(lastLocationPost, freqRange,
                                                   Message.getTime(jsonData))
        LocationMessage.incrementMessageCount(lastLocationPost)
        LocationMessage.incrementBandCount(lastLocationPost, freqRange)
        LocationMessage.setMinMaxPower(lastLocationPost, minPower, maxPower)
        locationPostId = lastLocationPost["_id"]
        del lastLocationPost["_id"]

        locationPosts.update({"_id": locationPostId},
                             {"$set": lastLocationPost},
                             upsert=False)
        end_time = time.time()
        if filedesc is not None:
            print " Insertion time " + str(end_time - start_time)
Esempio n. 2
0
def getDataSummaryForAllBands(sensorId,
                              locationMessage,
                              tmin=None,
                              dayCount=None):
    """
    get the summary of the data corresponding to the location message.
    """
    # tmin and tmax are the min and the max of the time range of interest.
    locationMessageId = str(locationMessage["_id"])

    tzId = locationMessage[TIME_ZONE_KEY]
    sensor = SensorDb.getSensor(sensorId)
    if sensor is None:
        return {STATUS: NOK, ERROR_MESSAGE: "Sensor Not found in SensorDb"}
    bands = sensor[THRESHOLDS]
    if len(bands.keys()) == 0:
        return {STATUS: NOK, ERROR_MESSAGE: "Sensor has no bands"}
    measurementType = sensor[MEASUREMENT_TYPE]
    bandStatistics = []
    query = {SENSOR_ID: sensorId, "locationMessageId": locationMessageId}
    msg = DbCollections.getDataMessages(sensorId).find_one(query)
    if msg is None:
        for key in bands.keys():
            band = bands[key]
            minFreq = band[MIN_FREQ_HZ]
            maxFreq = band[MAX_FREQ_HZ]
            sys2detect = band[SYSTEM_TO_DETECT]
            isActive = band[ACTIVE]
            bandInfo = {
                "tStartDayBoundary": 0,
                "tEndDayBoundary": 0,
                "tStartReadings": 0,
                "tStartLocalTime": 0,
                "tStartLocalTimeFormattedTimeStamp": UNKNOWN,
                "tEndReadings": 0,
                "tEndReadingsLocalTime": 0,
                "tEndLocalTimeFormattedTimeStamp": UNKNOWN,
                "tEndDayBoundary": 0,
                "maxOccupancy": 0,
                "meanOccupancy": 0,
                "minOccupancy": 0,
                "maxFreq": maxFreq,
                "minFreq": minFreq,
                SYSTEM_TO_DETECT: sys2detect,
                "measurementType": measurementType,
                "active": isActive,
                COUNT: 0
            }

            bandStatistics.append(bandInfo)
        return {STATUS: "OK", "bands": bandStatistics}

    if tmin is None and dayCount is None:
        query = {SENSOR_ID: sensorId, "locationMessageId": locationMessageId}
        tmin = msgutils.getDayBoundaryTimeStamp(msg)
        mintime = timezone.getDayBoundaryTimeStampFromUtcTimeStamp(
            int(tmin), tzId)
    elif tmin is not None and dayCount is None:
        mintime = timezone.getDayBoundaryTimeStampFromUtcTimeStamp(
            int(tmin), tzId)
    else:
        mintime = timezone.getDayBoundaryTimeStampFromUtcTimeStamp(
            int(tmin), tzId)

    for key in bands.keys():
        band = bands[key]
        minFreq = band[MIN_FREQ_HZ]
        maxFreq = band[MAX_FREQ_HZ]
        sys2detect = band[SYSTEM_TO_DETECT]
        bandSummary = getBandDataSummary(sensorId,
                                         locationMessage,
                                         sys2detect,
                                         minFreq,
                                         maxFreq,
                                         mintime,
                                         dayCount=dayCount)
        bandStatistics.append(bandSummary)

    return {STATUS: "OK", "bands": bandStatistics}
def getHourlyMaxMinMeanStats(sensorId, startTime, sys2detect, fmin, fmax,
                             subBandMinFreq, subBandMaxFreq, sessionId):

    sensor = SensorDb.getSensor(sensorId)
    if sensor is None:
        return {STATUS: NOK, ERROR_MESSAGE: "Sensor Not Found"}

    tstart = int(startTime)
    fmin = int(subBandMinFreq)
    fmax = int(subBandMaxFreq)
    freqRange = msgutils.freqRange(sys2detect, fmin, fmax)

    queryString = {
        SENSOR_ID: sensorId,
        TIME: {
            '$gte': tstart
        },
        FREQ_RANGE: freqRange
    }
    util.debugPrint(queryString)

    startMessage = DbCollections.getDataMessages(sensorId).find_one(
        queryString)
    if startMessage is None:
        errorStr = "Start Message Not Found"
        util.debugPrint(errorStr)
        response = {STATUS: NOK, ERROR_MESSAGE: "No data found"}
        return response

    locationMessageId = DataMessage.getLocationMessageId(startMessage)

    retval = {STATUS: OK}
    values = {}
    locationMessage = DbCollections.getLocationMessages().find_one(
        {"_id": locationMessageId})

    tZId = LocationMessage.getTimeZone(locationMessage)

    tmin = timezone.getDayBoundaryTimeStampFromUtcTimeStamp(
        tstart, LocationMessage.getTimeZone(locationMessage))

    for hour in range(0, 23):
        dataMessages = DbCollections.getDataMessages(sensorId).find({
            "t": {
                "$gte": tmin + hour * SECONDS_PER_HOUR
            },
            "t": {
                "$lte": (hour + 1) * SECONDS_PER_HOUR
            },
            FREQ_RANGE:
            freqRange
        })
        if dataMessages is not None:
            stats = compute_stats_for_fft_power(dataMessages)
            (nChannels, maxFreq, minFreq, cutoff, result) = stats
            values[hour] = result

    retval["values"] = values

    # Now compute the next interval after the last one (if one exists)
    tend = tmin + SECONDS_PER_DAY
    queryString = {
        SENSOR_ID: sensorId,
        TIME: {
            '$gte': tend
        },
        FREQ_RANGE: freqRange
    }
    msg = DbCollections.getDataMessages(sensorId).find_one(queryString)
    if msg is None:
        result["nextTmin"] = tmin
    else:
        nextTmin = timezone.getDayBoundaryTimeStampFromUtcTimeStamp(
            msg[TIME], tZId)
        result["nextTmin"] = nextTmin
    # Now compute the previous interval before this one.
    prevMessage = msgutils.getPrevAcquisition(startMessage)
    if prevMessage is not None:
        newTmin = timezone.getDayBoundaryTimeStampFromUtcTimeStamp(
            prevMessage[TIME] - SECONDS_PER_DAY, tZId)
        queryString = {
            SENSOR_ID: sensorId,
            TIME: {
                '$gte': newTmin
            },
            FREQ_RANGE: msgutils.freqRange(sys2detect, fmin, fmax)
        }
        msg = DbCollections.getDataMessages(sensorId).find_one(queryString)
    else:
        msg = startMessage
    result[STATUS] = OK
    result["prevTmin"] = timezone.getDayBoundaryTimeStampFromUtcTimeStamp(
        msg[TIME], tZId)
    result["tmin"] = tmin
    result["maxFreq"] = maxFreq
    result["minFreq"] = minFreq
    result["cutoff"] = cutoff
    result[CHANNEL_COUNT] = nChannels
    result["startDate"] = timezone.formatTimeStampLong(tmin, tZId)
    result["values"] = values
    return result