From 121cfc241801a3ae466ec5c4dcdb0dbb36b4a299 Mon Sep 17 00:00:00 2001
From: Starbeamrainbowlabs <sbrl@starbeamrainbowlabs.com>
Date: Wed, 10 Jul 2019 12:21:38 +0100
Subject: [PATCH] Write some glue code to insert the measurement info into the
 database

....but it's untested.
---
 server/Helpers/crypto_async.mjs          |  2 +-
 server/Repos.SQLite/GatewayRepo.mjs      | 21 +++++++++++++++++
 server/Repos.SQLite/RSSIRepo.mjs         |  2 +-
 server/Repos.SQLite/ReadingRepo.mjs      |  7 +++++-
 server/db_template.sql                   |  2 +-
 server/ttn-app-server/MessageHandler.mjs | 30 +++++++++++++++++++++---
 6 files changed, 57 insertions(+), 7 deletions(-)

diff --git a/server/Helpers/crypto_async.mjs b/server/Helpers/crypto_async.mjs
index dbb3dd9..03c290c 100644
--- a/server/Helpers/crypto_async.mjs
+++ b/server/Helpers/crypto_async.mjs
@@ -1,7 +1,7 @@
 "use strict";
 
 import util from 'util';
-import crypto from './Objects/FlyingBanana';
+import crypto from 'crypto';
 
 export default {
 	randomBytes: util.promisify(crypto.randomBytes)
diff --git a/server/Repos.SQLite/GatewayRepo.mjs b/server/Repos.SQLite/GatewayRepo.mjs
index dd18522..afcad9d 100644
--- a/server/Repos.SQLite/GatewayRepo.mjs
+++ b/server/Repos.SQLite/GatewayRepo.mjs
@@ -21,6 +21,27 @@ class GatewayRepo {
 			this.insert_query.run(gateway);
 	}
 	
+	/**
+	 * Determines whether a gateway exists in the dayabase with the given name.
+	 * @param	{string}	id	The id of the gateway.
+	 * @return	{bool}		Whether a gateway with the given name exists in the database.
+	 */
+	exists(id) {
+		// Note that normally a count wouldn't be appropriate here just to test for existence, but it's ok because it's guaranteed that there will only ever be a single entry with a given id.
+		let statement = this.db.prepare(`SELECT COUNT(id) AS count
+		FROM gateways
+		WHERE id = :id`);
+		
+		let count = statement.get({ id }).count;
+		
+		return count > 0;
+	}
+	
+	/**
+	 * Iterates over all the gateways in the table.
+	 * TODO: Use Symbol.iterator here?
+ 	 * @return	{Generator}	A generator that can be used with for..of
+	 */
 	iterate() {
 		return this.db.prepare(`SELECT * FROM gateways`).iterate();
 	}
diff --git a/server/Repos.SQLite/RSSIRepo.mjs b/server/Repos.SQLite/RSSIRepo.mjs
index 823011d..6e96bb0 100644
--- a/server/Repos.SQLite/RSSIRepo.mjs
+++ b/server/Repos.SQLite/RSSIRepo.mjs
@@ -14,7 +14,7 @@ class RSSIRepo {
 				channel
 			) VALUES (
 				:id,
-				:reading_id, :gateway_id
+				:reading_id, :gateway_id,
 				:rssi, :snr,
 				:channel
 			)`);
diff --git a/server/Repos.SQLite/ReadingRepo.mjs b/server/Repos.SQLite/ReadingRepo.mjs
index a8b83fc..7193922 100644
--- a/server/Repos.SQLite/ReadingRepo.mjs
+++ b/server/Repos.SQLite/ReadingRepo.mjs
@@ -19,8 +19,13 @@ class ReadingRepo {
 				:data_rate, :code_rate
 			)`);
 		
-		this.insert_query.run(reading);
+		let new_id = this.insert_query.run(reading).lastInsertRowid;
 		
+		// Attach the new id to the rssi objects
+		for(let rssi of reading.rssis)
+			rssi.reading_id = new_id;
+		
+		// Insert the RSSIs into the database
 		this.RSSIRepo.add(...reading.rssis);
 	}
 	
diff --git a/server/db_template.sql b/server/db_template.sql
index 583800e..96e6a36 100644
--- a/server/db_template.sql
+++ b/server/db_template.sql
@@ -10,7 +10,7 @@ CREATE TABLE readings IF NOT EXISTS (
 CREATE TABLE rssis IF NOT EXISTS (
 	id INTEGER PRIMARY KEY, -- Random unique int
 	reading_id INTEGER, -- The id of the object in the readings table that this rssi measurement belongs to
-	gateway_id INTEGER, -- Gateway id that the RSSI was from
+	gateway_id TEXT, -- Gateway id that the RSSI was from
 	rssi FLOAT, -- The RSSI value itself
 	snr FLOAT, -- The signal-to-noise ratio
 	channel INTEGER -- The channel that the RSSI was received over. We might be able to use this to detect single-channel gateways
diff --git a/server/ttn-app-server/MessageHandler.mjs b/server/ttn-app-server/MessageHandler.mjs
index 4d062ca..3700b68 100644
--- a/server/ttn-app-server/MessageHandler.mjs
+++ b/server/ttn-app-server/MessageHandler.mjs
@@ -1,11 +1,11 @@
 "use strict";
 
 import { decode_payload } from './DecodePayload.mjs';
+import { get_id_number } from '../Helpers/IdGenerator.mjs';
 
 class MessageHandler {
-	constructor({ ReadingRepo, RSSIRepo, GatewayRepo }) {
+	constructor({ ReadingRepo, GatewayRepo }) {
 		this.repo_reading = ReadingRepo;
-		this.repo_rssi = RSSIRepo;
 		this.repo_gateway = GatewayRepo;
 	}
 	
@@ -15,13 +15,37 @@ class MessageHandler {
 		let decoded_payload = decode_payload(message.payload_raw);
 		console.log(decoded_payload);
 		
+		let rssis = [];
+		for(let gw in message.metadata.gateways) {
+			// Insert the gateway info into the database if it doesn't exist already
+			if(!this.repo_gateway.exists(gw.gtw_id)) {
+				this.repo_gateway.add({
+					id: gw.gtw_id,
+					latitude: gw.latitude, longitude: gw.longitude,
+					altitude: gw.altitude
+				});
+			}
+			
+			// Generate an RSSI object
+			rssis.push({
+				id: get_id_number,
+				gateway_id: this.repo_gateway,
+				rssi: gw.rssi,
+				snr: gw.snr,
+				channel: gw.channel
+			});
+		}
+		
+		// Add the reading and the associated RSSIs to the database
 		this.repo_reading.add({
 			id: decoded_payload.id,
 			latitude: decoded_payload.latitude,
 			longitude: decoded_payload.longitude,
 			
 			data_rate: message.metadata.data_rate,
-			code_rate: message.metadata.coding_rate
+			code_rate: message.metadata.coding_rate,
+			
+			rssis
 		});
 	}
 }
