def updateSensorWorker(sessionId):
     try:
         util.debugPrint("updateSensor")
         if not Config.isConfigured():
             util.debugPrint("Please configure system")
             return make_response("Please configure system", 500)
         if not authentication.checkSessionId(sessionId, ADMIN):
             return make_response("Session not found.", 403)
         requestStr = request.data
         sensorConfig = json.loads(requestStr)
         return jsonify(SensorDb.updateSensor(sensorConfig))
     except:
         print "Unexpected error:", sys.exc_info()[0]
         print sys.exc_info()
         traceback.print_exc()
         util.logStackTrace(sys.exc_info())
         raise
Exemple #2
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)
Exemple #3
0
def runGarbageCollector(sensorId):
    SessionLock.acquire()
    try:
        userCount = SessionLock.getUserSessionCount()
        if userCount != 0:
            return {"status": "NOK",
                    "ErrorMessage": "Active user session detected"}
        sensorObj = SensorDb.getSensorObj(sensorId)
        if sensorObj is None:
            return {"status": "NOK", "ErrorMessage": "Sensor Not found"}
        if sensorObj.getSensorStatus() != DISABLED:
            return {"status": "NOK",
                    "ErrorMessage": "Sensor is ENABLED  -- DISABLE it first"}

        dataRetentionDuration = sensorObj.getSensorDataRetentionDurationMonths(
        )
        dataRetentionTime = dataRetentionDuration * 30 * SECONDS_PER_DAY
        cur = DbCollections.getDataMessages(sensorId).find(
            {SENSOR_ID: sensorId})
        #dataMessages = cur.sort('t', pymongo.ASCENDING)
        currentTime = time.time()
        for msg in cur:
            insertionTime = Message.getInsertionTime(msg)
            if currentTime - dataRetentionTime >= insertionTime:
                DbCollections.getDataMessages(sensorId).remove(msg)
                msgutils.removeData(msg)
            else:
                break

            # Now redo our book keeping summary fields.
        #dataMessages = cur.sort('t', pymongo.ASCENDING)
        locationMessages = DbCollections.getLocationMessages().find(
            {SENSOR_ID: sensorId})
        for locationMessage in locationMessages:
            insertionTime = Message.getInsertionTime(locationMessage)
            if currentTime - dataRetentionTime >= insertionTime:
                DbCollections.getLocationMessages().remove(msg)
            else:
                LocationMessage.clean(locationMessage)
                DbCollections.getLocationMessages().update(
                    {"_id": locationMessage["_id"]}, {"$set": locationMessage},
                    upsert=False)
        sensorObj.cleanSensorStats()

        # Update the summary statistics.
        cur = DbCollections.getDataMessages(sensorId).find(
            {SENSOR_ID: sensorId})

        for jsonData in cur:
            freqRange = DataMessage.getFreqRange(jsonData)
            minPower = DataMessage.getMinPower(jsonData)
            maxPower = DataMessage.getMaxPower(jsonData)
            messageId = DataMessage.getLocationMessageId(jsonData)
            lastLocationPost = DbCollections.getLocationMessages().find_one({"_id": messageId})
            if DataMessage.getMeasurementType(jsonData) == FFT_POWER:
                minOccupancy = DataMessage.getMinOccupancy(jsonData)
                maxOccupancy = DataMessage.getMaxOccupancy(jsonData)
                meanOccupancy = DataMessage.getMeanOccupancy(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:
                occupancy = DataMessage.getOccupancy(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)

            DbCollections.getLocationMessages().update(
                {"_id": lastLocationPost["_id"]}, {"$set": lastLocationPost},
                upsert=False)
            # Garbage collect the unprocessed data messages.
            cur = DbCollections.getUnprocessedDataMessages(sensorId).find({SENSOR_ID: sensorId})
            if cur is not None:
                dataMessages = cur.sort('t', pymongo.ASCENDING)
                for msg in dataMessages:
                    insertionTime = Message.getInsertionTime(msg)
                    if currentTime - dataRetentionTime >= insertionTime:
                        DbCollections.getUnprocessedDataMessages(sensorId).remove(msg)
                    else:
                        break

            DbCollections.dropDailyOccupancyCache(sensorId)

        return {"status": "OK", "sensors": SensorDb.getAllSensors()}
    finally:
        SessionLock.release()