def dump_results():
    dynamo_table = Table("weightresult")
    all_cloud_results_output = open("all_cloud_results.csv", "w")
    fog_results_output = open("fog_results.csv", "w")

    for s_string in ["all_cloud_results", "cloud_vs_fog"]:
        item = dynamo_table.getItem({
            "environment": "roomA",
            "sensor": s_string
        })

        for result in item["results"]:
            output_line = ",".join([
                result["gateway_A_subject"], result["gateway_B_subject"],
                result["gateway_C_subject"],
                str(result["Comm_pi_pi"]),
                str(result["Comm_pi_lambda"]),
                str(result["Compu_pi"]),
                str(result["Lambda_ExecTime"]),
                str(result["w_1"]),
                str(result["w_2"]),
                str(result["data_bytes_features"]),
                str(result["data_bytes_entire"]),
                str(result["number_of_sensors"]),
                str(result["Error"])
            ])

            if ("fog_or_cloud" in result
                    and result["fog_or_cloud"] != "all_cloud"):
                fog_results_output.write(output_line + "\n")
            else:
                all_cloud_results_output.write(output_line + "\n")
Пример #2
0
def main():
    figureNumber = sys.argv[1]
    oldTime = 0
    resultTable = Table('weightresult')
    resultItem = resultTable.getItem({
        'environment': 'roomA',
        'sensor': 'sensorA&B&C'
    })
    plotBandwidth(resultItem)
    plotLatency(resultItem)
    plotCosts(resultItem)
    plotAccuracy(resultItem, figureNumber)
    plt.show()
Пример #3
0
def sample_size():
	'''
	Listens to the GUI for the sample size of the experiment.
	Uploads this number to DynamoDB so that the Pi's can access it.

	'''
	tStart = time.time()
	table = Table('SampleSize')
	item = table.getItem({
		'forum'		: '1',
		'subject'	: 'PC1'
	})
	item['timeStamp'] = Decimal(tStart)
	# item['sampleSize'] = e.get() # e.get is the number you entered in the window
	item['sampleSize'] = Decimal(e.get())
	table.addItem(item)
        if aIsReady:
            ready = ready + 1
            oldTimeA = timeA
        if bIsReady:
            ready = ready + 1
            oldTimeB = timeB
        if cIsReady:
            ready = ready + 1
            oldTimeC = timeC

        # This means that all gateways are ready
        if ready >= 3:
            ready = 0
            print("Now triggering lambda...")
            break

    # The Trigger_A table makes Lambda start processing the data.
    # The table needs to be specified in the Lambda function config.
    lambdaTriggerTable = Table('Trigger_A')
    item = lambdaTriggerTable.getItem({'forum': 'roomA', 'subject': '1'})

    tEnd = time.time()
    item['timeStamp'] = Decimal(str(tEnd))
    lambdaTriggerTable.addItem(item)
    print("Lambda triggered!")

    # if KeyboardInterrupt:
    #     print("Closing Lambda Trigger")
    #     sys.exit()
def lambda_handler(event, context):
    # Fetch the DynamoDB resource
    tStart = time.time()

    # Change: Getting the number of samples from the 'SampleSize' table is tricky
    # When we'll have multiple Pi's, keeping track of this number will be buggy
    # For this reason, I'm setting the value of 'datanum' to the number of items
    # that we're going to get from the table containing the aggregated sensor data

    # Initialize helper variables
    featurenum = 3
    collectornum = 2
    betam = np.zeros((featurenum, collectornum))
    dataBytesFeatures = 0
    numSensors = 0

    # Fetch the features calculated by Gateway A
    table_A = Table('sensingdata_A')
    itemKey = {'forum': 'roomA', 'subject': 'sensorA'}
    item_A = table_A.getItem(itemKey)
    betam[0][0] = item_A['feature_A']
    betam[1][0] = item_A['feature_B']
    betam[2][0] = item_A['feature_C']
    #	dataBytesFeatures += item_A['data_bytes']
    #	numSensors += item_A['number_of_sensors']

    # Fetch the features calculated by Gateway B
    table_B = Table('sensingdata_B')
    itemKey = {'forum': 'roomB', 'subject': 'sensorB'}
    item_B = table_B.getItem(itemKey)
    betam[0][1] = item_B['feature_A']
    betam[1][1] = item_B['feature_B']
    betam[2][1] = item_B['feature_C']
    # dataBytesFeatures += item_B['data_bytes']
    # numSensors += item_B['number_of_sensors']

    # Fetch the aggregated data from Gateway C
    table_C = Table('sensingdata_C')
    itemKey = {'forum': 'roomC', 'subject': 'sensorC'}
    item_C = table_C.getItem(itemKey)
    aggregatedData = item_C['aggregated_data']
    #numSensors += item_C['number_of_sensors']
    datanum = len(aggregatedData)
    X = np.zeros((datanum, featurenum))
    y = np.zeros((datanum, 1))

    for i in range(datanum):
        X[i][0] = aggregatedData[i]['X_1']
        X[i][1] = aggregatedData[i]['X_2']
        X[i][2] = aggregatedData[i]['X_3']
        y[i][0] = aggregatedData[i]['Y']
    #data_bytes = item_C['data_bytes']

    def prox_simplex(y):
        # projection onto simplex
        n = len(y)
        val = -np.sort(-y)
        suppt_v = np.cumsum(val) - np.arange(1, n + 1, 1) * val
        k_act = np.sum(suppt_v < 1)
        lam = (np.sum(val[0:k_act]) - 1.0) / k_act
        x = np.maximum(y - lam, 0.0)
        return x

    def combine(y, X, betam):
        K = betam.shape[1]
        w = np.ones((K, )) / K
        maxit = 1000
        tol = 1e-3
        Xb = np.dot(X, betam)
        step = 1.0 / np.max(np.linalg.svd(Xb, full_matrices=0,
                                          compute_uv=0))**2

        for it in range(maxit):
            prev_w = np.copy(w)
            res = y - np.dot(np.matrix(Xb), np.matrix(w).T)
            grad = -np.dot(np.matrix(Xb).T, np.matrix(res))
            w -= step * np.squeeze(np.asarray(grad.T))
            w = prox_simplex(w)
            if np.linalg.norm(w - prev_w) / (1e-20 +
                                             np.linalg.norm(prev_w)) < tol:
                break

        return w

    w = combine(y, X, betam)
    w_temp = [decimal.Decimal(str(w[i])) for i in range(collectornum)]

    wb = np.dot(np.matrix(betam), np.matrix(w).T)
    Predict_y = np.dot(np.matrix(X), wb)
    Predict_y_array = np.squeeze(np.asarray(Predict_y))

    MSE = np.sqrt(np.sum((y - np.squeeze(np.asarray(Predict_y)))**2)) / datanum
    MSE_temp = decimal.Decimal(str(MSE))
    tEnd = time.time()
    Lambda_ExecTime = tEnd - tStart
    tEnd_temp = decimal.Decimal(str(tEnd))
    Lambda_ExecTime_temp = decimal.Decimal(str(Lambda_ExecTime))

    Predict_y_array = Predict_y_array.tolist()
    y = y.tolist()
    for i in range(len(Predict_y_array)):
        y[i] = decimal.Decimal(str(y[i][0]))
        Predict_y_array[i] = decimal.Decimal(str(Predict_y_array[i]))

    table = Table('weightresult')
    resultData = {
        'environment': 'roomA',
        'sensor': 'sensorA&B&C',
        'w_1': w_temp[0],
        'w_2': w_temp[1],
        'Prediction': Predict_y_array,
        'Real_Data': y,
        'Error': MSE_temp,
        'Lambda_ExecTime': Lambda_ExecTime_temp,
        'Time': tEnd_temp
    }
    item = table.addItem(resultData)

    # Record this run
    resultData.pop('environment', None)
    resultData.pop('sensor', None)
    resultData.pop('Prediction', None)
    resultData.pop('Real_Data', None)
    record = table.getItem({'environment': 'roomA', 'sensor': 'expResults'})
    results = record['results']
    results.append(resultData)
    item = table.addItem(record)
Пример #6
0
def main(tableLetter, sleepTime):
    """
    Runs the experiment as indicated below:

    1)  Listens for a trigger on the 'SampleSize' table on DynamoDB
    2)  On the trigger, starts listening and reading from bluetooth (port 1)
    3)  Collects additional data from its sensors
    4)  Calculates the features of the data
    5)  Uploads the features to DynamoDB
    6)  Visualizes these results using an animated matplotlib figure.

    """
    # Establish a connection to the 'SampleSize' table
    table = Table('SampleSize')
    oldSizeTime = 0 # Placeholder. The value will be overwritten by a time stamp

    while True:

        # Break out of the inner while-loop only when the table has been updated
        sense.set_pixels(LED.threeDots('green', 'G'))

        stayInLoop = True
        key = {
            'forum'     : '1',
            'subject'   : 'PC1'
        }

        while stayInLoop:
            try:
                stayInLoop, timeStamp = table.compareValues(key, 'timeStamp', oldSizeTime, True)
                # Sleep because pinging AWS is costs $$$
                time.sleep(sleepTime)

            except KeyboardInterrupt:
                print("Shutting down...")
                sense.set_pixels(LED.pluses('black'))
                sys.exit()

        oldSizeTime = timeStamp

        numDataPoints = table.getItem(key)['sampleSize']
        numFeatures = 3

        # Listen for incoming bluetooth data on port 1
        sense.set_pixels(LED.arrowReceive('orange', 'black'))

        timeOne = time.time()
        btTime, dataFromBT = BT.listenOnBluetooth(1)
        timeTwo = time.time()
        # Edit: timeTwo - timeOne != btTime since some time is spent waiting on the sockets

        # Make the LEDs show the computation state
        sense.set_pixels(LED.diamond('blue'))

        # Transform the received bluetooth data to numpy arrays
        targetMatrix, designMatrix = bluetoothDataToNPArrays(dataFromBT, numDataPoints, numFeatures)

        # Aggregate the bluetooth data, with data collected from the Gateway Pi
        sense.set_pixels(LED.pluses('green'))
        targetMatrix, designMatrix = collectData(targetMatrix, designMatrix, numDataPoints)

        # Signify the computation state
        sense.set_pixels(LED.diamond('blue')) 

        # Calculate how many sensors were used.
        # Number of received readings divided by the number of readings per sensor.
        numSensors = targetMatrix.shape[0] / numDataPoints

        # Calculate the features if the gateway has permission to do so
        if calculateFeatures[tableLetter]:
            features = gradientDescent(targetMatrix, designMatrix, numFeatures, numDataPoints)

        timeThree = time.time()
        compTime = timeThree - timeTwo

        # Upload data to DynamoDB
        sense.set_pixels(LED.arrowSend('blue', 'black'))

        if calculateFeatures[tableLetter]:
            uploadTime = uploadToDB(tableLetter, features, btTime, compTime, numSensors)

        else:
            # Make sure that targetMatrix and designMatrix get read in the correct order
            uploadTime = uploadToDB(tableLetter, [targetMatrix, designMatrix], btTime, compTime, numSensors)
        
        # Reset the state of the LED
        sense.set_pixels(LED.xCross('red'))
Пример #7
0
def uploadToDB(tableLetter, data, btTime, compTime, numSensors):
    """
    Uploads the features and the latencies to DynamoDB

    Param(s):
        (char)          Denotes the table, e.g. A, B
        (numpy array)   Features calculated from the dataset
        (int)           Time taken to load bluetooth data in seconds
        (int)           Time taken to compute the features in seconds

    Returns an int showing the time taken to upload to DynamoDB in seconds

    """

    startTime = time.time()
    table = Table('sensingdata_' + tableLetter)
    room = 'roomA'
    sensor = 'sensor' + tableLetter

    # Prepare the upload payload
    item = table.getItem({
        'forum'     : room,
        'subject'   : sensor
    })

    # If the Gateway was designated to calculate features...
    if calculateFeatures[tableLetter]:
        item['feature_A'] = Decimal(str(float(data[0][0])))
        item['feature_B'] = Decimal(str(float(data[1][0])))
        item['feature_C'] = Decimal(str(float(data[2][0])))
        sizeOfDataInBytes = data.nbytes

    # Otherwise, the Gateway was meant to aggregate data without calculations
    else:
        targetMatrix = data[0]
        designMatrix = data[1]

        # Numpy indexes follow the [row][column] convention
        # ndarray.shape returns the dimensions as a (#OfRows, #OfColumns)
        # Both of our matrices have the same number of rows, hence one measure is enough
        numOfRows = designMatrix.shape[0]
        aggregatedItems = []

        for i in range(numOfRows):
            currentItem = {}
            currentItem['X_1']     = Decimal(str(designMatrix[i][0]))    # Time
            currentItem['X_2']     = Decimal(str(designMatrix[i][1]))    # Pressure
            currentItem['X_3']     = Decimal(str(designMatrix[i][2]))    # Humidity
            currentItem['Y']       = Decimal(str(targetMatrix[i][0]))    # Temperature
            aggregatedItems.append(currentItem)

        sizeOfDataInBytes = designMatrix.nbytes + targetMatrix.nbytes
        item['aggregated_data'] = aggregatedItems

    # Upload this document to DynamoDB
    item['Comm_pi_pi'] = Decimal(str(btTime))
    item['Compu_pi'] = Decimal(str(compTime))
    item['data_bytes'] = Decimal(str(sizeOfDataInBytes))
    table.addItem(item)

    # Attach a time stamp and the size of the file to the header item in DynamoDB
    endTime = time.time()
    uploadDuration = endTime - startTime
    item['Comm_pi_lambda'] = Decimal(str(uploadDuration))
    item['timeStamp'] = Decimal(str(endTime))
    item['number_of_sensors'] = Decimal(str(numSensors))
    table.addItem(item)

    # Log the experiment run to DynamoDB, regardless of gateway type
    item.pop('aggregated_data', None)
    item.pop('forum', None)
    item.pop('subject', None)
    # newData = []
    # labels = []
    # for key in item.keys():
    #     labels.append(key)
    #     newData.append(item[key])

    record = table.getItem({'forum' : 'roomA', 'subject' : 'records'})
    try:
        data = record['data']
    except KeyError:
        record['data'] = []
    data.append(item)
    # record['data_labels'] = labels

    table.addItem(record)

    #print(" ".join(["Uploaded", sizeOfDataInBytes, "bytes of data to DynamoDB"]))
    print("Uploaded ", str(sizeOfDataInBytes), " bytes of data to DynamoDB")


    return uploadDuration