diff --git a/Birdmap.API/ClientApp/package-lock.json b/Birdmap.API/ClientApp/package-lock.json
index 506d86f..cf85909 100644
--- a/Birdmap.API/ClientApp/package-lock.json
+++ b/Birdmap.API/ClientApp/package-lock.json
@@ -1733,6 +1733,11 @@
"@types/node": "*"
}
},
+ "@types/googlemaps": {
+ "version": "3.40.3",
+ "resolved": "https://registry.npmjs.org/@types/googlemaps/-/googlemaps-3.40.3.tgz",
+ "integrity": "sha512-ivlG5S0LlnQgpgPnQCUNAs7kjBtO367ZwDmuK+ggsQfW+w4N0RyWbxWZ6vPwegDe50Du3Xbb5+QVwJuB/U1XpA=="
+ },
"@types/history": {
"version": "4.7.3",
"resolved": "https://registry.npmjs.org/@types/history/-/history-4.7.3.tgz",
@@ -6321,6 +6326,19 @@
}
}
},
+ "google-maps": {
+ "version": "4.3.3",
+ "resolved": "https://registry.npmjs.org/google-maps/-/google-maps-4.3.3.tgz",
+ "integrity": "sha512-MQbEgBNQbGyV7mfS2tlFgW4EoGKLia24BvAl4a+kgsYWt4283kyPpaay/yKIsScQLr7nSUONaLNfOdMsCuJDEw==",
+ "requires": {
+ "@types/googlemaps": "^3.39.1"
+ }
+ },
+ "google-maps-react": {
+ "version": "2.0.6",
+ "resolved": "https://registry.npmjs.org/google-maps-react/-/google-maps-react-2.0.6.tgz",
+ "integrity": "sha512-M8Eo9WndfQEfxcmm6yRq03qdJgw1x6rQmJ9DN+a+xPQ3K7yNDGkVDbinrf4/8vcox7nELbeopbm4bpefKewWfQ=="
+ },
"graceful-fs": {
"version": "4.2.3",
"resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.3.tgz",
diff --git a/Birdmap.API/ClientApp/package.json b/Birdmap.API/ClientApp/package.json
index e5fe9fd..462cb73 100644
--- a/Birdmap.API/ClientApp/package.json
+++ b/Birdmap.API/ClientApp/package.json
@@ -8,6 +8,8 @@
"@material-ui/lab": "^4.0.0-alpha.56",
"bootstrap": "^4.3.1",
"connected-react-router": "6.5.2",
+ "google-maps": "^4.3.3",
+ "google-maps-react": "^2.0.6",
"history": "4.10.1",
"jquery": "^3.5.1",
"merge": "1.2.1",
diff --git a/Birdmap.API/ClientApp/src/components/devices/DeviceService.js b/Birdmap.API/ClientApp/src/components/devices/DeviceService.js
new file mode 100644
index 0000000..25fda0c
--- /dev/null
+++ b/Birdmap.API/ClientApp/src/components/devices/DeviceService.js
@@ -0,0 +1,601 @@
+"use strict";
+/* tslint:disable */
+/* eslint-disable */
+//----------------------
+//
+// Generated using the NSwag toolchain v13.8.2.0 (NJsonSchema v10.2.1.0 (Newtonsoft.Json v12.0.0.0)) (http://NSwag.org)
+//
+//----------------------
+// ReSharper disable InconsistentNaming
+var __extends = (this && this.__extends) || (function () {
+ var extendStatics = function (d, b) {
+ extendStatics = Object.setPrototypeOf ||
+ ({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) ||
+ function (d, b) { for (var p in b) if (Object.prototype.hasOwnProperty.call(b, p)) d[p] = b[p]; };
+ return extendStatics(d, b);
+ };
+ return function (d, b) {
+ extendStatics(d, b);
+ function __() { this.constructor = d; }
+ d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());
+ };
+})();
+Object.defineProperty(exports, "__esModule", { value: true });
+exports.ApiException = exports.SensorStatus = exports.Coordinates = exports.DeviceStatus = exports.Sensor = exports.Device = exports.DeviceService = void 0;
+var DeviceService = /** @class */ (function () {
+ function DeviceService(baseUrl, http) {
+ this.jsonParseReviver = undefined;
+ this.http = http ? http : window;
+ this.baseUrl = baseUrl !== undefined && baseUrl !== null ? baseUrl : "api/devices";
+ }
+ /**
+ * Get all device info
+ * @return Array of devices
+ */
+ DeviceService.prototype.getall = function () {
+ var _this = this;
+ var url_ = this.baseUrl;
+ var options_ = {
+ method: "GET",
+ headers: {
+ "Accept": "application/json"
+ }
+ };
+ return this.http.fetch(url_, options_).then(function (_response) {
+ return _this.processGetall(_response);
+ });
+ };
+ DeviceService.prototype.processGetall = function (response) {
+ var _this = this;
+ var status = response.status;
+ var _headers = {};
+ if (response.headers && response.headers.forEach) {
+ response.headers.forEach(function (v, k) { return _headers[k] = v; });
+ }
+ ;
+ if (status === 200) {
+ return response.text().then(function (_responseText) {
+ var result200 = null;
+ var resultData200 = _responseText === "" ? null : JSON.parse(_responseText, _this.jsonParseReviver);
+ if (Array.isArray(resultData200)) {
+ result200 = [];
+ for (var _i = 0, resultData200_1 = resultData200; _i < resultData200_1.length; _i++) {
+ var item = resultData200_1[_i];
+ result200.push(Device.fromJS(item));
+ }
+ }
+ return result200;
+ });
+ }
+ else if (status === 404) {
+ return response.text().then(function (_responseText) {
+ return throwException("No device found", status, _responseText, _headers);
+ });
+ }
+ else if (status !== 200 && status !== 204) {
+ return response.text().then(function (_responseText) {
+ return throwException("An unexpected server error occurred.", status, _responseText, _headers);
+ });
+ }
+ return Promise.resolve(null);
+ };
+ /**
+ * Shut down all devices
+ * @return Message sent
+ */
+ DeviceService.prototype.offlineall = function () {
+ var _this = this;
+ var url_ = this.baseUrl + "/offline";
+ url_ = url_.replace(/[?&]$/, "");
+ var options_ = {
+ method: "POST",
+ headers: {}
+ };
+ return this.http.fetch(url_, options_).then(function (_response) {
+ return _this.processOfflineall(_response);
+ });
+ };
+ DeviceService.prototype.processOfflineall = function (response) {
+ var status = response.status;
+ var _headers = {};
+ if (response.headers && response.headers.forEach) {
+ response.headers.forEach(function (v, k) { return _headers[k] = v; });
+ }
+ ;
+ if (status === 200) {
+ return response.text().then(function (_responseText) {
+ return;
+ });
+ }
+ else if (status === 500) {
+ return response.text().then(function (_responseText) {
+ return throwException("Message sending unsuccessful", status, _responseText, _headers);
+ });
+ }
+ else if (status !== 200 && status !== 204) {
+ return response.text().then(function (_responseText) {
+ return throwException("An unexpected server error occurred.", status, _responseText, _headers);
+ });
+ }
+ return Promise.resolve(null);
+ };
+ /**
+ * Bring all devices online
+ * @return Message sent
+ */
+ DeviceService.prototype.onlineall = function () {
+ var _this = this;
+ var url_ = this.baseUrl + "/online";
+ url_ = url_.replace(/[?&]$/, "");
+ var options_ = {
+ method: "POST",
+ headers: {}
+ };
+ return this.http.fetch(url_, options_).then(function (_response) {
+ return _this.processOnlineall(_response);
+ });
+ };
+ DeviceService.prototype.processOnlineall = function (response) {
+ var status = response.status;
+ var _headers = {};
+ if (response.headers && response.headers.forEach) {
+ response.headers.forEach(function (v, k) { return _headers[k] = v; });
+ }
+ ;
+ if (status === 200) {
+ return response.text().then(function (_responseText) {
+ return;
+ });
+ }
+ else if (status === 500) {
+ return response.text().then(function (_responseText) {
+ return throwException("Message sending unsuccessful", status, _responseText, _headers);
+ });
+ }
+ else if (status !== 200 && status !== 204) {
+ return response.text().then(function (_responseText) {
+ return throwException("An unexpected server error occurred.", status, _responseText, _headers);
+ });
+ }
+ return Promise.resolve(null);
+ };
+ /**
+ * Get all device info
+ * @param deviceID ID of device to query
+ * @return Information about a particular device
+ */
+ DeviceService.prototype.getdevice = function (deviceID) {
+ var _this = this;
+ var url_ = this.baseUrl + "/{deviceID}";
+ if (deviceID === undefined || deviceID === null)
+ throw new Error("The parameter 'deviceID' must be defined.");
+ url_ = url_.replace("{deviceID}", encodeURIComponent("" + deviceID));
+ url_ = url_.replace(/[?&]$/, "");
+ var options_ = {
+ method: "GET",
+ headers: {
+ "Accept": "application/json"
+ }
+ };
+ return this.http.fetch(url_, options_).then(function (_response) {
+ return _this.processGetdevice(_response);
+ });
+ };
+ DeviceService.prototype.processGetdevice = function (response) {
+ var _this = this;
+ var status = response.status;
+ var _headers = {};
+ if (response.headers && response.headers.forEach) {
+ response.headers.forEach(function (v, k) { return _headers[k] = v; });
+ }
+ ;
+ if (status === 200) {
+ return response.text().then(function (_responseText) {
+ var result200 = null;
+ var resultData200 = _responseText === "" ? null : JSON.parse(_responseText, _this.jsonParseReviver);
+ result200 = Device.fromJS(resultData200);
+ return result200;
+ });
+ }
+ else if (status === 404) {
+ return response.text().then(function (_responseText) {
+ return throwException("Device not found", status, _responseText, _headers);
+ });
+ }
+ else if (status !== 200 && status !== 204) {
+ return response.text().then(function (_responseText) {
+ return throwException("An unexpected server error occurred.", status, _responseText, _headers);
+ });
+ }
+ return Promise.resolve(null);
+ };
+ /**
+ * Shut down device
+ * @param deviceID ID of device to shut down
+ * @return Message sent
+ */
+ DeviceService.prototype.offlinedevice = function (deviceID) {
+ var _this = this;
+ var url_ = this.baseUrl + "/{deviceID}/offline";
+ if (deviceID === undefined || deviceID === null)
+ throw new Error("The parameter 'deviceID' must be defined.");
+ url_ = url_.replace("{deviceID}", encodeURIComponent("" + deviceID));
+ url_ = url_.replace(/[?&]$/, "");
+ var options_ = {
+ method: "POST",
+ headers: {}
+ };
+ return this.http.fetch(url_, options_).then(function (_response) {
+ return _this.processOfflinedevice(_response);
+ });
+ };
+ DeviceService.prototype.processOfflinedevice = function (response) {
+ var status = response.status;
+ var _headers = {};
+ if (response.headers && response.headers.forEach) {
+ response.headers.forEach(function (v, k) { return _headers[k] = v; });
+ }
+ ;
+ if (status === 200) {
+ return response.text().then(function (_responseText) {
+ return;
+ });
+ }
+ else if (status === 500) {
+ return response.text().then(function (_responseText) {
+ return throwException("Message sending unsuccessful", status, _responseText, _headers);
+ });
+ }
+ else if (status !== 200 && status !== 204) {
+ return response.text().then(function (_responseText) {
+ return throwException("An unexpected server error occurred.", status, _responseText, _headers);
+ });
+ }
+ return Promise.resolve(null);
+ };
+ /**
+ * Bring device online
+ * @param deviceID ID of device to bring online
+ * @return Message sent
+ */
+ DeviceService.prototype.onlinedevice = function (deviceID) {
+ var _this = this;
+ var url_ = this.baseUrl + "/{deviceID}/online";
+ if (deviceID === undefined || deviceID === null)
+ throw new Error("The parameter 'deviceID' must be defined.");
+ url_ = url_.replace("{deviceID}", encodeURIComponent("" + deviceID));
+ url_ = url_.replace(/[?&]$/, "");
+ var options_ = {
+ method: "POST",
+ headers: {}
+ };
+ return this.http.fetch(url_, options_).then(function (_response) {
+ return _this.processOnlinedevice(_response);
+ });
+ };
+ DeviceService.prototype.processOnlinedevice = function (response) {
+ var status = response.status;
+ var _headers = {};
+ if (response.headers && response.headers.forEach) {
+ response.headers.forEach(function (v, k) { return _headers[k] = v; });
+ }
+ ;
+ if (status === 200) {
+ return response.text().then(function (_responseText) {
+ return;
+ });
+ }
+ else if (status === 500) {
+ return response.text().then(function (_responseText) {
+ return throwException("Message sending unsuccessful", status, _responseText, _headers);
+ });
+ }
+ else if (status !== 200 && status !== 204) {
+ return response.text().then(function (_responseText) {
+ return throwException("An unexpected server error occurred.", status, _responseText, _headers);
+ });
+ }
+ return Promise.resolve(null);
+ };
+ /**
+ * Get info about a particular device's sensor
+ * @param deviceID ID of device to query
+ * @param sensorID ID of sensor to query
+ * @return Information about a sensor
+ */
+ DeviceService.prototype.getsensor = function (deviceID, sensorID) {
+ var _this = this;
+ var url_ = this.baseUrl + "/{deviceID}/{sensorID}";
+ if (deviceID === undefined || deviceID === null)
+ throw new Error("The parameter 'deviceID' must be defined.");
+ url_ = url_.replace("{deviceID}", encodeURIComponent("" + deviceID));
+ if (sensorID === undefined || sensorID === null)
+ throw new Error("The parameter 'sensorID' must be defined.");
+ url_ = url_.replace("{sensorID}", encodeURIComponent("" + sensorID));
+ url_ = url_.replace(/[?&]$/, "");
+ var options_ = {
+ method: "GET",
+ headers: {
+ "Accept": "application/json"
+ }
+ };
+ return this.http.fetch(url_, options_).then(function (_response) {
+ return _this.processGetsensor(_response);
+ });
+ };
+ DeviceService.prototype.processGetsensor = function (response) {
+ var _this = this;
+ var status = response.status;
+ var _headers = {};
+ if (response.headers && response.headers.forEach) {
+ response.headers.forEach(function (v, k) { return _headers[k] = v; });
+ }
+ ;
+ if (status === 200) {
+ return response.text().then(function (_responseText) {
+ var result200 = null;
+ var resultData200 = _responseText === "" ? null : JSON.parse(_responseText, _this.jsonParseReviver);
+ result200 = Sensor.fromJS(resultData200);
+ return result200;
+ });
+ }
+ else if (status === 404) {
+ return response.text().then(function (_responseText) {
+ return throwException("Device or sensor not found", status, _responseText, _headers);
+ });
+ }
+ else if (status !== 200 && status !== 204) {
+ return response.text().then(function (_responseText) {
+ return throwException("An unexpected server error occurred.", status, _responseText, _headers);
+ });
+ }
+ return Promise.resolve(null);
+ };
+ /**
+ * Shut down sensor
+ * @param deviceID ID of device to query
+ * @param sensorID ID of sensor to query
+ * @return Message sent
+ */
+ DeviceService.prototype.offlinesensor = function (deviceID, sensorID) {
+ var _this = this;
+ var url_ = this.baseUrl + "/{deviceID}/{sensorID}/offline";
+ if (deviceID === undefined || deviceID === null)
+ throw new Error("The parameter 'deviceID' must be defined.");
+ url_ = url_.replace("{deviceID}", encodeURIComponent("" + deviceID));
+ if (sensorID === undefined || sensorID === null)
+ throw new Error("The parameter 'sensorID' must be defined.");
+ url_ = url_.replace("{sensorID}", encodeURIComponent("" + sensorID));
+ url_ = url_.replace(/[?&]$/, "");
+ var options_ = {
+ method: "POST",
+ headers: {}
+ };
+ return this.http.fetch(url_, options_).then(function (_response) {
+ return _this.processOfflinesensor(_response);
+ });
+ };
+ DeviceService.prototype.processOfflinesensor = function (response) {
+ var status = response.status;
+ var _headers = {};
+ if (response.headers && response.headers.forEach) {
+ response.headers.forEach(function (v, k) { return _headers[k] = v; });
+ }
+ ;
+ if (status === 200) {
+ return response.text().then(function (_responseText) {
+ return;
+ });
+ }
+ else if (status === 500) {
+ return response.text().then(function (_responseText) {
+ return throwException("Message sending unsuccessful", status, _responseText, _headers);
+ });
+ }
+ else if (status !== 200 && status !== 204) {
+ return response.text().then(function (_responseText) {
+ return throwException("An unexpected server error occurred.", status, _responseText, _headers);
+ });
+ }
+ return Promise.resolve(null);
+ };
+ /**
+ * Bring sensor online
+ * @param deviceID ID of device to query
+ * @param sensorID ID of sensor to query
+ * @return Message sent
+ */
+ DeviceService.prototype.onlinesensor = function (deviceID, sensorID) {
+ var _this = this;
+ var url_ = this.baseUrl + "/{deviceID}/{sensorID}/online";
+ if (deviceID === undefined || deviceID === null)
+ throw new Error("The parameter 'deviceID' must be defined.");
+ url_ = url_.replace("{deviceID}", encodeURIComponent("" + deviceID));
+ if (sensorID === undefined || sensorID === null)
+ throw new Error("The parameter 'sensorID' must be defined.");
+ url_ = url_.replace("{sensorID}", encodeURIComponent("" + sensorID));
+ url_ = url_.replace(/[?&]$/, "");
+ var options_ = {
+ method: "POST",
+ headers: {}
+ };
+ return this.http.fetch(url_, options_).then(function (_response) {
+ return _this.processOnlinesensor(_response);
+ });
+ };
+ DeviceService.prototype.processOnlinesensor = function (response) {
+ var status = response.status;
+ var _headers = {};
+ if (response.headers && response.headers.forEach) {
+ response.headers.forEach(function (v, k) { return _headers[k] = v; });
+ }
+ ;
+ if (status === 200) {
+ return response.text().then(function (_responseText) {
+ return;
+ });
+ }
+ else if (status === 500) {
+ return response.text().then(function (_responseText) {
+ return throwException("Message sending unsuccessful", status, _responseText, _headers);
+ });
+ }
+ else if (status !== 200 && status !== 204) {
+ return response.text().then(function (_responseText) {
+ return throwException("An unexpected server error occurred.", status, _responseText, _headers);
+ });
+ }
+ return Promise.resolve(null);
+ };
+ return DeviceService;
+}());
+exports.DeviceService = DeviceService;
+var Device = /** @class */ (function () {
+ function Device(data) {
+ if (data) {
+ for (var property in data) {
+ if (data.hasOwnProperty(property))
+ this[property] = data[property];
+ }
+ }
+ if (!data) {
+ this.coordinates = new Coordinates();
+ this.sensors = [];
+ }
+ }
+ Device.prototype.init = function (_data) {
+ if (_data) {
+ this.id = _data["id"];
+ this.status = _data["status"];
+ this.url = _data["url"];
+ this.coordinates = _data["coordinates"] ? Coordinates.fromJS(_data["coordinates"]) : new Coordinates();
+ if (Array.isArray(_data["sensors"])) {
+ this.sensors = [];
+ for (var _i = 0, _a = _data["sensors"]; _i < _a.length; _i++) {
+ var item = _a[_i];
+ this.sensors.push(Sensor.fromJS(item));
+ }
+ }
+ }
+ };
+ Device.fromJS = function (data) {
+ data = typeof data === 'object' ? data : {};
+ var result = new Device();
+ result.init(data);
+ return result;
+ };
+ Device.prototype.toJSON = function (data) {
+ data = typeof data === 'object' ? data : {};
+ data["id"] = this.id;
+ data["status"] = this.status;
+ data["url"] = this.url;
+ data["coordinates"] = this.coordinates ? this.coordinates.toJSON() : undefined;
+ if (Array.isArray(this.sensors)) {
+ data["sensors"] = [];
+ for (var _i = 0, _a = this.sensors; _i < _a.length; _i++) {
+ var item = _a[_i];
+ data["sensors"].push(item.toJSON());
+ }
+ }
+ return data;
+ };
+ return Device;
+}());
+exports.Device = Device;
+var Sensor = /** @class */ (function () {
+ function Sensor(data) {
+ if (data) {
+ for (var property in data) {
+ if (data.hasOwnProperty(property))
+ this[property] = data[property];
+ }
+ }
+ }
+ Sensor.prototype.init = function (_data) {
+ if (_data) {
+ this.id = _data["id"];
+ this.status = _data["status"];
+ }
+ };
+ Sensor.fromJS = function (data) {
+ data = typeof data === 'object' ? data : {};
+ var result = new Sensor();
+ result.init(data);
+ return result;
+ };
+ Sensor.prototype.toJSON = function (data) {
+ data = typeof data === 'object' ? data : {};
+ data["id"] = this.id;
+ data["status"] = this.status;
+ return data;
+ };
+ return Sensor;
+}());
+exports.Sensor = Sensor;
+var DeviceStatus;
+(function (DeviceStatus) {
+ DeviceStatus["Online"] = "online";
+ DeviceStatus["Error"] = "error";
+ DeviceStatus["Offline"] = "offline";
+})(DeviceStatus = exports.DeviceStatus || (exports.DeviceStatus = {}));
+var Coordinates = /** @class */ (function () {
+ function Coordinates(data) {
+ if (data) {
+ for (var property in data) {
+ if (data.hasOwnProperty(property))
+ this[property] = data[property];
+ }
+ }
+ }
+ Coordinates.prototype.init = function (_data) {
+ if (_data) {
+ this.latitude = _data["latitude"];
+ this.longitude = _data["longitude"];
+ }
+ };
+ Coordinates.fromJS = function (data) {
+ data = typeof data === 'object' ? data : {};
+ var result = new Coordinates();
+ result.init(data);
+ return result;
+ };
+ Coordinates.prototype.toJSON = function (data) {
+ data = typeof data === 'object' ? data : {};
+ data["latitude"] = this.latitude;
+ data["longitude"] = this.longitude;
+ return data;
+ };
+ return Coordinates;
+}());
+exports.Coordinates = Coordinates;
+var SensorStatus;
+(function (SensorStatus) {
+ SensorStatus["Online"] = "online";
+ SensorStatus["Unknown"] = "unknown";
+ SensorStatus["Offline"] = "offline";
+})(SensorStatus = exports.SensorStatus || (exports.SensorStatus = {}));
+var ApiException = /** @class */ (function (_super) {
+ __extends(ApiException, _super);
+ function ApiException(message, status, response, headers, result) {
+ var _this = _super.call(this) || this;
+ _this.isApiException = true;
+ _this.message = message;
+ _this.status = status;
+ _this.response = response;
+ _this.headers = headers;
+ _this.result = result;
+ return _this;
+ }
+ ApiException.isApiException = function (obj) {
+ return obj.isApiException === true;
+ };
+ return ApiException;
+}(Error));
+exports.ApiException = ApiException;
+function throwException(message, status, response, headers, result) {
+ if (result !== null && result !== undefined)
+ throw result;
+ else
+ throw new ApiException(message, status, response, headers, null);
+}
+//# sourceMappingURL=DeviceService.js.map
\ No newline at end of file
diff --git a/Birdmap.API/ClientApp/src/components/devices/DeviceService.js.map b/Birdmap.API/ClientApp/src/components/devices/DeviceService.js.map
new file mode 100644
index 0000000..e562720
--- /dev/null
+++ b/Birdmap.API/ClientApp/src/components/devices/DeviceService.js.map
@@ -0,0 +1 @@
+{"version":3,"file":"DeviceService.js","sourceRoot":"","sources":["DeviceService.ts"],"names":[],"mappings":"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"}
\ No newline at end of file
diff --git a/Birdmap.API/ClientApp/src/components/devices/DeviceService.ts b/Birdmap.API/ClientApp/src/components/devices/DeviceService.ts
new file mode 100644
index 0000000..5230923
--- /dev/null
+++ b/Birdmap.API/ClientApp/src/components/devices/DeviceService.ts
@@ -0,0 +1,599 @@
+/* tslint:disable */
+/* eslint-disable */
+//----------------------
+//
+// Generated using the NSwag toolchain v13.8.2.0 (NJsonSchema v10.2.1.0 (Newtonsoft.Json v12.0.0.0)) (http://NSwag.org)
+//
+//----------------------
+// ReSharper disable InconsistentNaming
+
+export class DeviceService {
+ private http: { fetch(url: RequestInfo, init?: RequestInit): Promise };
+ private baseUrl: string;
+ protected jsonParseReviver: ((key: string, value: any) => any) | undefined = undefined;
+
+ constructor(baseUrl?: string, http?: { fetch(url: RequestInfo, init?: RequestInit): Promise }) {
+ this.http = http ? http : window;
+ this.baseUrl = baseUrl !== undefined && baseUrl !== null ? baseUrl : "api/devices";
+ }
+
+ /**
+ * Get all device info
+ * @return Array of devices
+ */
+ getall(): Promise {
+ let url_ = this.baseUrl;
+
+ let options_ = {
+ method: "GET",
+ headers: {
+ "Accept": "application/json"
+ }
+ };
+
+ return this.http.fetch(url_, options_).then((_response: Response) => {
+ return this.processGetall(_response);
+ });
+ }
+
+ protected processGetall(response: Response): Promise {
+ const status = response.status;
+ let _headers: any = {}; if (response.headers && response.headers.forEach) { response.headers.forEach((v: any, k: any) => _headers[k] = v); };
+ if (status === 200) {
+ return response.text().then((_responseText) => {
+ let result200: any = null;
+ let resultData200 = _responseText === "" ? null : JSON.parse(_responseText, this.jsonParseReviver);
+ if (Array.isArray(resultData200)) {
+ result200 = [] as any;
+ for (let item of resultData200)
+ result200!.push(Device.fromJS(item));
+ }
+ return result200;
+ });
+ } else if (status === 404) {
+ return response.text().then((_responseText) => {
+ return throwException("No device found", status, _responseText, _headers);
+ });
+ } else if (status !== 200 && status !== 204) {
+ return response.text().then((_responseText) => {
+ return throwException("An unexpected server error occurred.", status, _responseText, _headers);
+ });
+ }
+ return Promise.resolve(null);
+ }
+
+ /**
+ * Shut down all devices
+ * @return Message sent
+ */
+ offlineall(): Promise {
+ let url_ = this.baseUrl + "/offline";
+ url_ = url_.replace(/[?&]$/, "");
+
+ let options_ = {
+ method: "POST",
+ headers: {
+ }
+ };
+
+ return this.http.fetch(url_, options_).then((_response: Response) => {
+ return this.processOfflineall(_response);
+ });
+ }
+
+ protected processOfflineall(response: Response): Promise {
+ const status = response.status;
+ let _headers: any = {}; if (response.headers && response.headers.forEach) { response.headers.forEach((v: any, k: any) => _headers[k] = v); };
+ if (status === 200) {
+ return response.text().then((_responseText) => {
+ return;
+ });
+ } else if (status === 500) {
+ return response.text().then((_responseText) => {
+ return throwException("Message sending unsuccessful", status, _responseText, _headers);
+ });
+ } else if (status !== 200 && status !== 204) {
+ return response.text().then((_responseText) => {
+ return throwException("An unexpected server error occurred.", status, _responseText, _headers);
+ });
+ }
+ return Promise.resolve(null);
+ }
+
+ /**
+ * Bring all devices online
+ * @return Message sent
+ */
+ onlineall(): Promise {
+ let url_ = this.baseUrl + "/online";
+ url_ = url_.replace(/[?&]$/, "");
+
+ let options_ = {
+ method: "POST",
+ headers: {
+ }
+ };
+
+ return this.http.fetch(url_, options_).then((_response: Response) => {
+ return this.processOnlineall(_response);
+ });
+ }
+
+ protected processOnlineall(response: Response): Promise {
+ const status = response.status;
+ let _headers: any = {}; if (response.headers && response.headers.forEach) { response.headers.forEach((v: any, k: any) => _headers[k] = v); };
+ if (status === 200) {
+ return response.text().then((_responseText) => {
+ return;
+ });
+ } else if (status === 500) {
+ return response.text().then((_responseText) => {
+ return throwException("Message sending unsuccessful", status, _responseText, _headers);
+ });
+ } else if (status !== 200 && status !== 204) {
+ return response.text().then((_responseText) => {
+ return throwException("An unexpected server error occurred.", status, _responseText, _headers);
+ });
+ }
+ return Promise.resolve(null);
+ }
+
+ /**
+ * Get all device info
+ * @param deviceID ID of device to query
+ * @return Information about a particular device
+ */
+ getdevice(deviceID: string): Promise {
+ let url_ = this.baseUrl + "/{deviceID}";
+ if (deviceID === undefined || deviceID === null)
+ throw new Error("The parameter 'deviceID' must be defined.");
+ url_ = url_.replace("{deviceID}", encodeURIComponent("" + deviceID));
+ url_ = url_.replace(/[?&]$/, "");
+
+ let options_ = {
+ method: "GET",
+ headers: {
+ "Accept": "application/json"
+ }
+ };
+
+ return this.http.fetch(url_, options_).then((_response: Response) => {
+ return this.processGetdevice(_response);
+ });
+ }
+
+ protected processGetdevice(response: Response): Promise {
+ const status = response.status;
+ let _headers: any = {}; if (response.headers && response.headers.forEach) { response.headers.forEach((v: any, k: any) => _headers[k] = v); };
+ if (status === 200) {
+ return response.text().then((_responseText) => {
+ let result200: any = null;
+ let resultData200 = _responseText === "" ? null : JSON.parse(_responseText, this.jsonParseReviver);
+ result200 = Device.fromJS(resultData200);
+ return result200;
+ });
+ } else if (status === 404) {
+ return response.text().then((_responseText) => {
+ return throwException("Device not found", status, _responseText, _headers);
+ });
+ } else if (status !== 200 && status !== 204) {
+ return response.text().then((_responseText) => {
+ return throwException("An unexpected server error occurred.", status, _responseText, _headers);
+ });
+ }
+ return Promise.resolve(null);
+ }
+
+ /**
+ * Shut down device
+ * @param deviceID ID of device to shut down
+ * @return Message sent
+ */
+ offlinedevice(deviceID: string): Promise {
+ let url_ = this.baseUrl + "/{deviceID}/offline";
+ if (deviceID === undefined || deviceID === null)
+ throw new Error("The parameter 'deviceID' must be defined.");
+ url_ = url_.replace("{deviceID}", encodeURIComponent("" + deviceID));
+ url_ = url_.replace(/[?&]$/, "");
+
+ let options_ = {
+ method: "POST",
+ headers: {
+ }
+ };
+
+ return this.http.fetch(url_, options_).then((_response: Response) => {
+ return this.processOfflinedevice(_response);
+ });
+ }
+
+ protected processOfflinedevice(response: Response): Promise {
+ const status = response.status;
+ let _headers: any = {}; if (response.headers && response.headers.forEach) { response.headers.forEach((v: any, k: any) => _headers[k] = v); };
+ if (status === 200) {
+ return response.text().then((_responseText) => {
+ return;
+ });
+ } else if (status === 500) {
+ return response.text().then((_responseText) => {
+ return throwException("Message sending unsuccessful", status, _responseText, _headers);
+ });
+ } else if (status !== 200 && status !== 204) {
+ return response.text().then((_responseText) => {
+ return throwException("An unexpected server error occurred.", status, _responseText, _headers);
+ });
+ }
+ return Promise.resolve(null);
+ }
+
+ /**
+ * Bring device online
+ * @param deviceID ID of device to bring online
+ * @return Message sent
+ */
+ onlinedevice(deviceID: string): Promise {
+ let url_ = this.baseUrl + "/{deviceID}/online";
+ if (deviceID === undefined || deviceID === null)
+ throw new Error("The parameter 'deviceID' must be defined.");
+ url_ = url_.replace("{deviceID}", encodeURIComponent("" + deviceID));
+ url_ = url_.replace(/[?&]$/, "");
+
+ let options_ = {
+ method: "POST",
+ headers: {
+ }
+ };
+
+ return this.http.fetch(url_, options_).then((_response: Response) => {
+ return this.processOnlinedevice(_response);
+ });
+ }
+
+ protected processOnlinedevice(response: Response): Promise {
+ const status = response.status;
+ let _headers: any = {}; if (response.headers && response.headers.forEach) { response.headers.forEach((v: any, k: any) => _headers[k] = v); };
+ if (status === 200) {
+ return response.text().then((_responseText) => {
+ return;
+ });
+ } else if (status === 500) {
+ return response.text().then((_responseText) => {
+ return throwException("Message sending unsuccessful", status, _responseText, _headers);
+ });
+ } else if (status !== 200 && status !== 204) {
+ return response.text().then((_responseText) => {
+ return throwException("An unexpected server error occurred.", status, _responseText, _headers);
+ });
+ }
+ return Promise.resolve(null);
+ }
+
+ /**
+ * Get info about a particular device's sensor
+ * @param deviceID ID of device to query
+ * @param sensorID ID of sensor to query
+ * @return Information about a sensor
+ */
+ getsensor(deviceID: string, sensorID: string): Promise {
+ let url_ = this.baseUrl + "/{deviceID}/{sensorID}";
+ if (deviceID === undefined || deviceID === null)
+ throw new Error("The parameter 'deviceID' must be defined.");
+ url_ = url_.replace("{deviceID}", encodeURIComponent("" + deviceID));
+ if (sensorID === undefined || sensorID === null)
+ throw new Error("The parameter 'sensorID' must be defined.");
+ url_ = url_.replace("{sensorID}", encodeURIComponent("" + sensorID));
+ url_ = url_.replace(/[?&]$/, "");
+
+ let options_ = {
+ method: "GET",
+ headers: {
+ "Accept": "application/json"
+ }
+ };
+
+ return this.http.fetch(url_, options_).then((_response: Response) => {
+ return this.processGetsensor(_response);
+ });
+ }
+
+ protected processGetsensor(response: Response): Promise {
+ const status = response.status;
+ let _headers: any = {}; if (response.headers && response.headers.forEach) { response.headers.forEach((v: any, k: any) => _headers[k] = v); };
+ if (status === 200) {
+ return response.text().then((_responseText) => {
+ let result200: any = null;
+ let resultData200 = _responseText === "" ? null : JSON.parse(_responseText, this.jsonParseReviver);
+ result200 = Sensor.fromJS(resultData200);
+ return result200;
+ });
+ } else if (status === 404) {
+ return response.text().then((_responseText) => {
+ return throwException("Device or sensor not found", status, _responseText, _headers);
+ });
+ } else if (status !== 200 && status !== 204) {
+ return response.text().then((_responseText) => {
+ return throwException("An unexpected server error occurred.", status, _responseText, _headers);
+ });
+ }
+ return Promise.resolve(null);
+ }
+
+ /**
+ * Shut down sensor
+ * @param deviceID ID of device to query
+ * @param sensorID ID of sensor to query
+ * @return Message sent
+ */
+ offlinesensor(deviceID: string, sensorID: string): Promise {
+ let url_ = this.baseUrl + "/{deviceID}/{sensorID}/offline";
+ if (deviceID === undefined || deviceID === null)
+ throw new Error("The parameter 'deviceID' must be defined.");
+ url_ = url_.replace("{deviceID}", encodeURIComponent("" + deviceID));
+ if (sensorID === undefined || sensorID === null)
+ throw new Error("The parameter 'sensorID' must be defined.");
+ url_ = url_.replace("{sensorID}", encodeURIComponent("" + sensorID));
+ url_ = url_.replace(/[?&]$/, "");
+
+ let options_ = {
+ method: "POST",
+ headers: {
+ }
+ };
+
+ return this.http.fetch(url_, options_).then((_response: Response) => {
+ return this.processOfflinesensor(_response);
+ });
+ }
+
+ protected processOfflinesensor(response: Response): Promise {
+ const status = response.status;
+ let _headers: any = {}; if (response.headers && response.headers.forEach) { response.headers.forEach((v: any, k: any) => _headers[k] = v); };
+ if (status === 200) {
+ return response.text().then((_responseText) => {
+ return;
+ });
+ } else if (status === 500) {
+ return response.text().then((_responseText) => {
+ return throwException("Message sending unsuccessful", status, _responseText, _headers);
+ });
+ } else if (status !== 200 && status !== 204) {
+ return response.text().then((_responseText) => {
+ return throwException("An unexpected server error occurred.", status, _responseText, _headers);
+ });
+ }
+ return Promise.resolve(null);
+ }
+
+ /**
+ * Bring sensor online
+ * @param deviceID ID of device to query
+ * @param sensorID ID of sensor to query
+ * @return Message sent
+ */
+ onlinesensor(deviceID: string, sensorID: string): Promise {
+ let url_ = this.baseUrl + "/{deviceID}/{sensorID}/online";
+ if (deviceID === undefined || deviceID === null)
+ throw new Error("The parameter 'deviceID' must be defined.");
+ url_ = url_.replace("{deviceID}", encodeURIComponent("" + deviceID));
+ if (sensorID === undefined || sensorID === null)
+ throw new Error("The parameter 'sensorID' must be defined.");
+ url_ = url_.replace("{sensorID}", encodeURIComponent("" + sensorID));
+ url_ = url_.replace(/[?&]$/, "");
+
+ let options_ = {
+ method: "POST",
+ headers: {
+ }
+ };
+
+ return this.http.fetch(url_, options_).then((_response: Response) => {
+ return this.processOnlinesensor(_response);
+ });
+ }
+
+ protected processOnlinesensor(response: Response): Promise {
+ const status = response.status;
+ let _headers: any = {}; if (response.headers && response.headers.forEach) { response.headers.forEach((v: any, k: any) => _headers[k] = v); };
+ if (status === 200) {
+ return response.text().then((_responseText) => {
+ return;
+ });
+ } else if (status === 500) {
+ return response.text().then((_responseText) => {
+ return throwException("Message sending unsuccessful", status, _responseText, _headers);
+ });
+ } else if (status !== 200 && status !== 204) {
+ return response.text().then((_responseText) => {
+ return throwException("An unexpected server error occurred.", status, _responseText, _headers);
+ });
+ }
+ return Promise.resolve(null);
+ }
+}
+
+export class Device implements IDevice {
+ id!: string;
+ status!: DeviceStatus;
+ url!: string;
+ coordinates!: Coordinates;
+ sensors!: Sensor[];
+
+ constructor(data?: IDevice) {
+ if (data) {
+ for (var property in data) {
+ if (data.hasOwnProperty(property))
+ (this)[property] = (data)[property];
+ }
+ }
+ if (!data) {
+ this.coordinates = new Coordinates();
+ this.sensors = [];
+ }
+ }
+
+ init(_data?: any) {
+ if (_data) {
+ this.id = _data["id"];
+ this.status = _data["status"];
+ this.url = _data["url"];
+ this.coordinates = _data["coordinates"] ? Coordinates.fromJS(_data["coordinates"]) : new Coordinates();
+ if (Array.isArray(_data["sensors"])) {
+ this.sensors = [] as any;
+ for (let item of _data["sensors"])
+ this.sensors!.push(Sensor.fromJS(item));
+ }
+ }
+ }
+
+ static fromJS(data: any): Device {
+ data = typeof data === 'object' ? data : {};
+ let result = new Device();
+ result.init(data);
+ return result;
+ }
+
+ toJSON(data?: any) {
+ data = typeof data === 'object' ? data : {};
+ data["id"] = this.id;
+ data["status"] = this.status;
+ data["url"] = this.url;
+ data["coordinates"] = this.coordinates ? this.coordinates.toJSON() : undefined;
+ if (Array.isArray(this.sensors)) {
+ data["sensors"] = [];
+ for (let item of this.sensors)
+ data["sensors"].push(item.toJSON());
+ }
+ return data;
+ }
+}
+
+export interface IDevice {
+ id: string;
+ status: DeviceStatus;
+ url: string;
+ coordinates: Coordinates;
+ sensors: Sensor[];
+}
+
+export class Sensor implements ISensor {
+ id!: string;
+ status!: SensorStatus;
+
+ constructor(data?: ISensor) {
+ if (data) {
+ for (var property in data) {
+ if (data.hasOwnProperty(property))
+ (this)[property] = (data)[property];
+ }
+ }
+ }
+
+ init(_data?: any) {
+ if (_data) {
+ this.id = _data["id"];
+ this.status = _data["status"];
+ }
+ }
+
+ static fromJS(data: any): Sensor {
+ data = typeof data === 'object' ? data : {};
+ let result = new Sensor();
+ result.init(data);
+ return result;
+ }
+
+ toJSON(data?: any) {
+ data = typeof data === 'object' ? data : {};
+ data["id"] = this.id;
+ data["status"] = this.status;
+ return data;
+ }
+}
+
+export interface ISensor {
+ id: string;
+ status: SensorStatus;
+}
+
+export enum DeviceStatus {
+ Online = "online",
+ Error = "error",
+ Offline = "offline",
+}
+
+export class Coordinates implements ICoordinates {
+ latitude!: number;
+ longitude!: number;
+
+ constructor(data?: ICoordinates) {
+ if (data) {
+ for (var property in data) {
+ if (data.hasOwnProperty(property))
+ (this)[property] = (data)[property];
+ }
+ }
+ }
+
+ init(_data?: any) {
+ if (_data) {
+ this.latitude = _data["latitude"];
+ this.longitude = _data["longitude"];
+ }
+ }
+
+ static fromJS(data: any): Coordinates {
+ data = typeof data === 'object' ? data : {};
+ let result = new Coordinates();
+ result.init(data);
+ return result;
+ }
+
+ toJSON(data?: any) {
+ data = typeof data === 'object' ? data : {};
+ data["latitude"] = this.latitude;
+ data["longitude"] = this.longitude;
+ return data;
+ }
+}
+
+export interface ICoordinates {
+ latitude: number;
+ longitude: number;
+}
+
+export enum SensorStatus {
+ Online = "online",
+ Unknown = "unknown",
+ Offline = "offline",
+}
+
+export class ApiException extends Error {
+ message: string;
+ status: number;
+ response: string;
+ headers: { [key: string]: any; };
+ result: any;
+
+ constructor(message: string, status: number, response: string, headers: { [key: string]: any; }, result: any) {
+ super();
+
+ this.message = message;
+ this.status = status;
+ this.response = response;
+ this.headers = headers;
+ this.result = result;
+ }
+
+ protected isApiException = true;
+
+ static isApiException(obj: any): obj is ApiException {
+ return obj.isApiException === true;
+ }
+}
+
+function throwException(message: string, status: number, response: string, headers: { [key: string]: any; }, result?: any): any {
+ if (result !== null && result !== undefined)
+ throw result;
+ else
+ throw new ApiException(message, status, response, headers, null);
+}
\ No newline at end of file
diff --git a/Birdmap.API/ClientApp/src/components/heatmap/heatmap.js b/Birdmap.API/ClientApp/src/components/heatmap/heatmap.js
new file mode 100644
index 0000000..0e3bc3e
--- /dev/null
+++ b/Birdmap.API/ClientApp/src/components/heatmap/heatmap.js
@@ -0,0 +1,555 @@
+"use strict";
+Object.defineProperty(exports, "__esModule", { value: true });
+exports.initMap = void 0;
+var google_maps_1 = require("google-maps");
+var map, heatmap;
+function initMap() {
+ var options = { /* todo */};
+ var loader = new google_maps_1.Loader('AIzaSyCZ51VFfxqZ2GkCmVrcNZdUKsM0fuBQUCY', options);
+ loader.load().then(function (google) {
+ map = new google.maps.Map(document.getElementById("map"), {
+ zoom: 13,
+ center: { lat: 37.775, lng: -122.434 },
+ mapTypeId: "satellite",
+ });
+ heatmap = new google.maps.visualization.HeatmapLayer({
+ data: getPoints(),
+ map: map,
+ });
+ });
+}
+exports.initMap = initMap;
+function toggleHeatmap() {
+ heatmap.setMap(heatmap.getMap() ? null : map);
+}
+function changeGradient() {
+ var gradient = [
+ "rgba(0, 255, 255, 0)",
+ "rgba(0, 255, 255, 1)",
+ "rgba(0, 191, 255, 1)",
+ "rgba(0, 127, 255, 1)",
+ "rgba(0, 63, 255, 1)",
+ "rgba(0, 0, 255, 1)",
+ "rgba(0, 0, 223, 1)",
+ "rgba(0, 0, 191, 1)",
+ "rgba(0, 0, 159, 1)",
+ "rgba(0, 0, 127, 1)",
+ "rgba(63, 0, 91, 1)",
+ "rgba(127, 0, 63, 1)",
+ "rgba(191, 0, 31, 1)",
+ "rgba(255, 0, 0, 1)",
+ ];
+ heatmap.set("gradient", heatmap.get("gradient") ? null : gradient);
+}
+function changeRadius() {
+ heatmap.set("radius", heatmap.get("radius") ? null : 20);
+}
+function changeOpacity() {
+ heatmap.set("opacity", heatmap.get("opacity") ? null : 0.2);
+}
+// Heatmap data: 500 Points
+function getPoints() {
+ return [
+ new google.maps.LatLng(37.782551, -122.445368),
+ new google.maps.LatLng(37.782745, -122.444586),
+ new google.maps.LatLng(37.782842, -122.443688),
+ new google.maps.LatLng(37.782919, -122.442815),
+ new google.maps.LatLng(37.782992, -122.442112),
+ new google.maps.LatLng(37.7831, -122.441461),
+ new google.maps.LatLng(37.783206, -122.440829),
+ new google.maps.LatLng(37.783273, -122.440324),
+ new google.maps.LatLng(37.783316, -122.440023),
+ new google.maps.LatLng(37.783357, -122.439794),
+ new google.maps.LatLng(37.783371, -122.439687),
+ new google.maps.LatLng(37.783368, -122.439666),
+ new google.maps.LatLng(37.783383, -122.439594),
+ new google.maps.LatLng(37.783508, -122.439525),
+ new google.maps.LatLng(37.783842, -122.439591),
+ new google.maps.LatLng(37.784147, -122.439668),
+ new google.maps.LatLng(37.784206, -122.439686),
+ new google.maps.LatLng(37.784386, -122.43979),
+ new google.maps.LatLng(37.784701, -122.439902),
+ new google.maps.LatLng(37.784965, -122.439938),
+ new google.maps.LatLng(37.78501, -122.439947),
+ new google.maps.LatLng(37.78536, -122.439952),
+ new google.maps.LatLng(37.785715, -122.44003),
+ new google.maps.LatLng(37.786117, -122.440119),
+ new google.maps.LatLng(37.786564, -122.440209),
+ new google.maps.LatLng(37.786905, -122.44027),
+ new google.maps.LatLng(37.786956, -122.440279),
+ new google.maps.LatLng(37.800224, -122.43352),
+ new google.maps.LatLng(37.800155, -122.434101),
+ new google.maps.LatLng(37.80016, -122.43443),
+ new google.maps.LatLng(37.800378, -122.434527),
+ new google.maps.LatLng(37.800738, -122.434598),
+ new google.maps.LatLng(37.800938, -122.43465),
+ new google.maps.LatLng(37.801024, -122.434889),
+ new google.maps.LatLng(37.800955, -122.435392),
+ new google.maps.LatLng(37.800886, -122.435959),
+ new google.maps.LatLng(37.800811, -122.436275),
+ new google.maps.LatLng(37.800788, -122.436299),
+ new google.maps.LatLng(37.800719, -122.436302),
+ new google.maps.LatLng(37.800702, -122.436298),
+ new google.maps.LatLng(37.800661, -122.436273),
+ new google.maps.LatLng(37.800395, -122.436172),
+ new google.maps.LatLng(37.800228, -122.436116),
+ new google.maps.LatLng(37.800169, -122.43613),
+ new google.maps.LatLng(37.800066, -122.436167),
+ new google.maps.LatLng(37.784345, -122.422922),
+ new google.maps.LatLng(37.784389, -122.422926),
+ new google.maps.LatLng(37.784437, -122.422924),
+ new google.maps.LatLng(37.784746, -122.422818),
+ new google.maps.LatLng(37.785436, -122.422959),
+ new google.maps.LatLng(37.78612, -122.423112),
+ new google.maps.LatLng(37.786433, -122.423029),
+ new google.maps.LatLng(37.786631, -122.421213),
+ new google.maps.LatLng(37.78666, -122.421033),
+ new google.maps.LatLng(37.786801, -122.420141),
+ new google.maps.LatLng(37.786823, -122.420034),
+ new google.maps.LatLng(37.786831, -122.419916),
+ new google.maps.LatLng(37.787034, -122.418208),
+ new google.maps.LatLng(37.787056, -122.418034),
+ new google.maps.LatLng(37.787169, -122.417145),
+ new google.maps.LatLng(37.787217, -122.416715),
+ new google.maps.LatLng(37.786144, -122.416403),
+ new google.maps.LatLng(37.785292, -122.416257),
+ new google.maps.LatLng(37.780666, -122.390374),
+ new google.maps.LatLng(37.780501, -122.391281),
+ new google.maps.LatLng(37.780148, -122.392052),
+ new google.maps.LatLng(37.780173, -122.391148),
+ new google.maps.LatLng(37.780693, -122.390592),
+ new google.maps.LatLng(37.781261, -122.391142),
+ new google.maps.LatLng(37.781808, -122.39173),
+ new google.maps.LatLng(37.78234, -122.392341),
+ new google.maps.LatLng(37.782812, -122.393022),
+ new google.maps.LatLng(37.7833, -122.393672),
+ new google.maps.LatLng(37.783809, -122.394275),
+ new google.maps.LatLng(37.784246, -122.394979),
+ new google.maps.LatLng(37.784791, -122.395958),
+ new google.maps.LatLng(37.785675, -122.396746),
+ new google.maps.LatLng(37.786262, -122.39578),
+ new google.maps.LatLng(37.786776, -122.395093),
+ new google.maps.LatLng(37.787282, -122.394426),
+ new google.maps.LatLng(37.787783, -122.393767),
+ new google.maps.LatLng(37.788343, -122.393184),
+ new google.maps.LatLng(37.788895, -122.392506),
+ new google.maps.LatLng(37.789371, -122.391701),
+ new google.maps.LatLng(37.789722, -122.390952),
+ new google.maps.LatLng(37.790315, -122.390305),
+ new google.maps.LatLng(37.790738, -122.389616),
+ new google.maps.LatLng(37.779448, -122.438702),
+ new google.maps.LatLng(37.779023, -122.438585),
+ new google.maps.LatLng(37.778542, -122.438492),
+ new google.maps.LatLng(37.7781, -122.438411),
+ new google.maps.LatLng(37.777986, -122.438376),
+ new google.maps.LatLng(37.77768, -122.438313),
+ new google.maps.LatLng(37.777316, -122.438273),
+ new google.maps.LatLng(37.777135, -122.438254),
+ new google.maps.LatLng(37.776987, -122.438303),
+ new google.maps.LatLng(37.776946, -122.438404),
+ new google.maps.LatLng(37.776944, -122.438467),
+ new google.maps.LatLng(37.776892, -122.438459),
+ new google.maps.LatLng(37.776842, -122.438442),
+ new google.maps.LatLng(37.776822, -122.438391),
+ new google.maps.LatLng(37.776814, -122.438412),
+ new google.maps.LatLng(37.776787, -122.438628),
+ new google.maps.LatLng(37.776729, -122.43865),
+ new google.maps.LatLng(37.776759, -122.438677),
+ new google.maps.LatLng(37.776772, -122.438498),
+ new google.maps.LatLng(37.776787, -122.438389),
+ new google.maps.LatLng(37.776848, -122.438283),
+ new google.maps.LatLng(37.77687, -122.438239),
+ new google.maps.LatLng(37.777015, -122.438198),
+ new google.maps.LatLng(37.777333, -122.438256),
+ new google.maps.LatLng(37.777595, -122.438308),
+ new google.maps.LatLng(37.777797, -122.438344),
+ new google.maps.LatLng(37.77816, -122.438442),
+ new google.maps.LatLng(37.778414, -122.438508),
+ new google.maps.LatLng(37.778445, -122.438516),
+ new google.maps.LatLng(37.778503, -122.438529),
+ new google.maps.LatLng(37.778607, -122.438549),
+ new google.maps.LatLng(37.77867, -122.438644),
+ new google.maps.LatLng(37.778847, -122.438706),
+ new google.maps.LatLng(37.77924, -122.438744),
+ new google.maps.LatLng(37.779738, -122.438822),
+ new google.maps.LatLng(37.780201, -122.438882),
+ new google.maps.LatLng(37.7804, -122.438905),
+ new google.maps.LatLng(37.780501, -122.438921),
+ new google.maps.LatLng(37.780892, -122.438986),
+ new google.maps.LatLng(37.781446, -122.439087),
+ new google.maps.LatLng(37.781985, -122.439199),
+ new google.maps.LatLng(37.782239, -122.439249),
+ new google.maps.LatLng(37.782286, -122.439266),
+ new google.maps.LatLng(37.797847, -122.429388),
+ new google.maps.LatLng(37.797874, -122.42918),
+ new google.maps.LatLng(37.797885, -122.429069),
+ new google.maps.LatLng(37.797887, -122.42905),
+ new google.maps.LatLng(37.797933, -122.428954),
+ new google.maps.LatLng(37.798242, -122.42899),
+ new google.maps.LatLng(37.798617, -122.429075),
+ new google.maps.LatLng(37.798719, -122.429092),
+ new google.maps.LatLng(37.798944, -122.429145),
+ new google.maps.LatLng(37.79932, -122.429251),
+ new google.maps.LatLng(37.79959, -122.429309),
+ new google.maps.LatLng(37.799677, -122.429324),
+ new google.maps.LatLng(37.799966, -122.42936),
+ new google.maps.LatLng(37.800288, -122.42943),
+ new google.maps.LatLng(37.800443, -122.429461),
+ new google.maps.LatLng(37.800465, -122.429474),
+ new google.maps.LatLng(37.800644, -122.42954),
+ new google.maps.LatLng(37.800948, -122.42962),
+ new google.maps.LatLng(37.801242, -122.429685),
+ new google.maps.LatLng(37.801375, -122.429702),
+ new google.maps.LatLng(37.8014, -122.429703),
+ new google.maps.LatLng(37.801453, -122.429707),
+ new google.maps.LatLng(37.801473, -122.429709),
+ new google.maps.LatLng(37.801532, -122.429707),
+ new google.maps.LatLng(37.801852, -122.429729),
+ new google.maps.LatLng(37.802173, -122.429789),
+ new google.maps.LatLng(37.802459, -122.429847),
+ new google.maps.LatLng(37.802554, -122.429825),
+ new google.maps.LatLng(37.802647, -122.429549),
+ new google.maps.LatLng(37.802693, -122.429179),
+ new google.maps.LatLng(37.802729, -122.428751),
+ new google.maps.LatLng(37.766104, -122.409291),
+ new google.maps.LatLng(37.766103, -122.409268),
+ new google.maps.LatLng(37.766138, -122.409229),
+ new google.maps.LatLng(37.766183, -122.409231),
+ new google.maps.LatLng(37.766153, -122.409276),
+ new google.maps.LatLng(37.766005, -122.409365),
+ new google.maps.LatLng(37.765897, -122.40957),
+ new google.maps.LatLng(37.765767, -122.409739),
+ new google.maps.LatLng(37.765693, -122.410389),
+ new google.maps.LatLng(37.765615, -122.411201),
+ new google.maps.LatLng(37.765533, -122.412121),
+ new google.maps.LatLng(37.765467, -122.412939),
+ new google.maps.LatLng(37.765444, -122.414821),
+ new google.maps.LatLng(37.765444, -122.414964),
+ new google.maps.LatLng(37.765318, -122.415424),
+ new google.maps.LatLng(37.763961, -122.415296),
+ new google.maps.LatLng(37.763115, -122.415196),
+ new google.maps.LatLng(37.762967, -122.415183),
+ new google.maps.LatLng(37.762278, -122.415127),
+ new google.maps.LatLng(37.761675, -122.415055),
+ new google.maps.LatLng(37.760932, -122.414988),
+ new google.maps.LatLng(37.759337, -122.414862),
+ new google.maps.LatLng(37.773187, -122.421922),
+ new google.maps.LatLng(37.773043, -122.422118),
+ new google.maps.LatLng(37.773007, -122.422165),
+ new google.maps.LatLng(37.772979, -122.422219),
+ new google.maps.LatLng(37.772865, -122.422394),
+ new google.maps.LatLng(37.772779, -122.422503),
+ new google.maps.LatLng(37.772676, -122.422701),
+ new google.maps.LatLng(37.772606, -122.422806),
+ new google.maps.LatLng(37.772566, -122.42284),
+ new google.maps.LatLng(37.772508, -122.422852),
+ new google.maps.LatLng(37.772387, -122.423011),
+ new google.maps.LatLng(37.772099, -122.423328),
+ new google.maps.LatLng(37.771704, -122.423783),
+ new google.maps.LatLng(37.771481, -122.424081),
+ new google.maps.LatLng(37.7714, -122.424179),
+ new google.maps.LatLng(37.771352, -122.42422),
+ new google.maps.LatLng(37.771248, -122.424327),
+ new google.maps.LatLng(37.770904, -122.424781),
+ new google.maps.LatLng(37.77052, -122.425283),
+ new google.maps.LatLng(37.770337, -122.425553),
+ new google.maps.LatLng(37.770128, -122.425832),
+ new google.maps.LatLng(37.769756, -122.426331),
+ new google.maps.LatLng(37.7693, -122.426902),
+ new google.maps.LatLng(37.769132, -122.427065),
+ new google.maps.LatLng(37.769092, -122.427103),
+ new google.maps.LatLng(37.768979, -122.427172),
+ new google.maps.LatLng(37.768595, -122.427634),
+ new google.maps.LatLng(37.768372, -122.427913),
+ new google.maps.LatLng(37.768337, -122.427961),
+ new google.maps.LatLng(37.768244, -122.428138),
+ new google.maps.LatLng(37.767942, -122.428581),
+ new google.maps.LatLng(37.767482, -122.429094),
+ new google.maps.LatLng(37.767031, -122.429606),
+ new google.maps.LatLng(37.766732, -122.429986),
+ new google.maps.LatLng(37.76668, -122.430058),
+ new google.maps.LatLng(37.766633, -122.430109),
+ new google.maps.LatLng(37.76658, -122.430211),
+ new google.maps.LatLng(37.766367, -122.430594),
+ new google.maps.LatLng(37.76591, -122.431137),
+ new google.maps.LatLng(37.765353, -122.431806),
+ new google.maps.LatLng(37.764962, -122.432298),
+ new google.maps.LatLng(37.764868, -122.432486),
+ new google.maps.LatLng(37.764518, -122.432913),
+ new google.maps.LatLng(37.763435, -122.434173),
+ new google.maps.LatLng(37.762847, -122.434953),
+ new google.maps.LatLng(37.762291, -122.435935),
+ new google.maps.LatLng(37.762224, -122.436074),
+ new google.maps.LatLng(37.761957, -122.436892),
+ new google.maps.LatLng(37.761652, -122.438886),
+ new google.maps.LatLng(37.761284, -122.439955),
+ new google.maps.LatLng(37.76121, -122.440068),
+ new google.maps.LatLng(37.761064, -122.44072),
+ new google.maps.LatLng(37.76104, -122.441411),
+ new google.maps.LatLng(37.761048, -122.442324),
+ new google.maps.LatLng(37.760851, -122.443118),
+ new google.maps.LatLng(37.759977, -122.444591),
+ new google.maps.LatLng(37.759913, -122.444698),
+ new google.maps.LatLng(37.759623, -122.445065),
+ new google.maps.LatLng(37.758902, -122.445158),
+ new google.maps.LatLng(37.758428, -122.44457),
+ new google.maps.LatLng(37.757687, -122.44334),
+ new google.maps.LatLng(37.757583, -122.44324),
+ new google.maps.LatLng(37.757019, -122.442787),
+ new google.maps.LatLng(37.756603, -122.442322),
+ new google.maps.LatLng(37.75638, -122.441602),
+ new google.maps.LatLng(37.75579, -122.441382),
+ new google.maps.LatLng(37.754493, -122.442133),
+ new google.maps.LatLng(37.754361, -122.442206),
+ new google.maps.LatLng(37.753719, -122.44265),
+ new google.maps.LatLng(37.753096, -122.442915),
+ new google.maps.LatLng(37.751617, -122.443211),
+ new google.maps.LatLng(37.751496, -122.443246),
+ new google.maps.LatLng(37.750733, -122.443428),
+ new google.maps.LatLng(37.750126, -122.443536),
+ new google.maps.LatLng(37.750103, -122.443784),
+ new google.maps.LatLng(37.75039, -122.44401),
+ new google.maps.LatLng(37.750448, -122.444013),
+ new google.maps.LatLng(37.750536, -122.44404),
+ new google.maps.LatLng(37.750493, -122.444141),
+ new google.maps.LatLng(37.790859, -122.402808),
+ new google.maps.LatLng(37.790864, -122.402768),
+ new google.maps.LatLng(37.790995, -122.402539),
+ new google.maps.LatLng(37.791148, -122.402172),
+ new google.maps.LatLng(37.791385, -122.401312),
+ new google.maps.LatLng(37.791405, -122.400776),
+ new google.maps.LatLng(37.791288, -122.400528),
+ new google.maps.LatLng(37.791113, -122.400441),
+ new google.maps.LatLng(37.791027, -122.400395),
+ new google.maps.LatLng(37.791094, -122.400311),
+ new google.maps.LatLng(37.791211, -122.400183),
+ new google.maps.LatLng(37.79106, -122.399334),
+ new google.maps.LatLng(37.790538, -122.398718),
+ new google.maps.LatLng(37.790095, -122.398086),
+ new google.maps.LatLng(37.789644, -122.39736),
+ new google.maps.LatLng(37.789254, -122.396844),
+ new google.maps.LatLng(37.788855, -122.396397),
+ new google.maps.LatLng(37.788483, -122.395963),
+ new google.maps.LatLng(37.788015, -122.395365),
+ new google.maps.LatLng(37.787558, -122.394735),
+ new google.maps.LatLng(37.787472, -122.394323),
+ new google.maps.LatLng(37.78763, -122.394025),
+ new google.maps.LatLng(37.787767, -122.393987),
+ new google.maps.LatLng(37.787486, -122.394452),
+ new google.maps.LatLng(37.786977, -122.395043),
+ new google.maps.LatLng(37.786583, -122.395552),
+ new google.maps.LatLng(37.78654, -122.39561),
+ new google.maps.LatLng(37.786516, -122.395659),
+ new google.maps.LatLng(37.786378, -122.395707),
+ new google.maps.LatLng(37.786044, -122.395362),
+ new google.maps.LatLng(37.785598, -122.394715),
+ new google.maps.LatLng(37.785321, -122.394361),
+ new google.maps.LatLng(37.785207, -122.394236),
+ new google.maps.LatLng(37.785751, -122.394062),
+ new google.maps.LatLng(37.785996, -122.393881),
+ new google.maps.LatLng(37.786092, -122.39383),
+ new google.maps.LatLng(37.785998, -122.393899),
+ new google.maps.LatLng(37.785114, -122.394365),
+ new google.maps.LatLng(37.785022, -122.394441),
+ new google.maps.LatLng(37.784823, -122.394635),
+ new google.maps.LatLng(37.784719, -122.394629),
+ new google.maps.LatLng(37.785069, -122.394176),
+ new google.maps.LatLng(37.7855, -122.39365),
+ new google.maps.LatLng(37.78577, -122.393291),
+ new google.maps.LatLng(37.785839, -122.393159),
+ new google.maps.LatLng(37.782651, -122.400628),
+ new google.maps.LatLng(37.782616, -122.400599),
+ new google.maps.LatLng(37.782702, -122.40047),
+ new google.maps.LatLng(37.782915, -122.400192),
+ new google.maps.LatLng(37.783137, -122.399887),
+ new google.maps.LatLng(37.783414, -122.399519),
+ new google.maps.LatLng(37.783629, -122.399237),
+ new google.maps.LatLng(37.783688, -122.399157),
+ new google.maps.LatLng(37.783716, -122.399106),
+ new google.maps.LatLng(37.783798, -122.399072),
+ new google.maps.LatLng(37.783997, -122.399186),
+ new google.maps.LatLng(37.784271, -122.399538),
+ new google.maps.LatLng(37.784577, -122.399948),
+ new google.maps.LatLng(37.784828, -122.40026),
+ new google.maps.LatLng(37.784999, -122.400477),
+ new google.maps.LatLng(37.785113, -122.400651),
+ new google.maps.LatLng(37.785155, -122.400703),
+ new google.maps.LatLng(37.785192, -122.400749),
+ new google.maps.LatLng(37.785278, -122.400839),
+ new google.maps.LatLng(37.785387, -122.400857),
+ new google.maps.LatLng(37.785478, -122.40089),
+ new google.maps.LatLng(37.785526, -122.401022),
+ new google.maps.LatLng(37.785598, -122.401148),
+ new google.maps.LatLng(37.785631, -122.401202),
+ new google.maps.LatLng(37.78566, -122.401267),
+ new google.maps.LatLng(37.803986, -122.426035),
+ new google.maps.LatLng(37.804102, -122.425089),
+ new google.maps.LatLng(37.804211, -122.424156),
+ new google.maps.LatLng(37.803861, -122.423385),
+ new google.maps.LatLng(37.803151, -122.423214),
+ new google.maps.LatLng(37.802439, -122.423077),
+ new google.maps.LatLng(37.80174, -122.422905),
+ new google.maps.LatLng(37.801069, -122.422785),
+ new google.maps.LatLng(37.800345, -122.422649),
+ new google.maps.LatLng(37.799633, -122.422603),
+ new google.maps.LatLng(37.79975, -122.4217),
+ new google.maps.LatLng(37.799885, -122.420854),
+ new google.maps.LatLng(37.799209, -122.420607),
+ new google.maps.LatLng(37.795656, -122.400395),
+ new google.maps.LatLng(37.795203, -122.400304),
+ new google.maps.LatLng(37.778738, -122.415584),
+ new google.maps.LatLng(37.778812, -122.415189),
+ new google.maps.LatLng(37.778824, -122.415092),
+ new google.maps.LatLng(37.778833, -122.414932),
+ new google.maps.LatLng(37.778834, -122.414898),
+ new google.maps.LatLng(37.77874, -122.414757),
+ new google.maps.LatLng(37.778501, -122.414433),
+ new google.maps.LatLng(37.778182, -122.414026),
+ new google.maps.LatLng(37.777851, -122.413623),
+ new google.maps.LatLng(37.777486, -122.413166),
+ new google.maps.LatLng(37.777109, -122.412674),
+ new google.maps.LatLng(37.776743, -122.412186),
+ new google.maps.LatLng(37.77644, -122.4118),
+ new google.maps.LatLng(37.776295, -122.411614),
+ new google.maps.LatLng(37.776158, -122.41144),
+ new google.maps.LatLng(37.775806, -122.410997),
+ new google.maps.LatLng(37.775422, -122.410484),
+ new google.maps.LatLng(37.775126, -122.410087),
+ new google.maps.LatLng(37.775012, -122.409854),
+ new google.maps.LatLng(37.775164, -122.409573),
+ new google.maps.LatLng(37.775498, -122.40918),
+ new google.maps.LatLng(37.775868, -122.40873),
+ new google.maps.LatLng(37.776256, -122.40824),
+ new google.maps.LatLng(37.776519, -122.407928),
+ new google.maps.LatLng(37.776539, -122.407904),
+ new google.maps.LatLng(37.776595, -122.407854),
+ new google.maps.LatLng(37.776853, -122.407547),
+ new google.maps.LatLng(37.777234, -122.407087),
+ new google.maps.LatLng(37.777644, -122.406558),
+ new google.maps.LatLng(37.778066, -122.406017),
+ new google.maps.LatLng(37.778468, -122.405499),
+ new google.maps.LatLng(37.778866, -122.404995),
+ new google.maps.LatLng(37.779295, -122.404455),
+ new google.maps.LatLng(37.779695, -122.40395),
+ new google.maps.LatLng(37.779982, -122.403584),
+ new google.maps.LatLng(37.780295, -122.403223),
+ new google.maps.LatLng(37.780664, -122.402766),
+ new google.maps.LatLng(37.781043, -122.402288),
+ new google.maps.LatLng(37.781399, -122.401823),
+ new google.maps.LatLng(37.781727, -122.401407),
+ new google.maps.LatLng(37.781853, -122.401247),
+ new google.maps.LatLng(37.781894, -122.401195),
+ new google.maps.LatLng(37.782076, -122.400977),
+ new google.maps.LatLng(37.782338, -122.400603),
+ new google.maps.LatLng(37.782666, -122.400133),
+ new google.maps.LatLng(37.783048, -122.399634),
+ new google.maps.LatLng(37.78345, -122.399198),
+ new google.maps.LatLng(37.783791, -122.398998),
+ new google.maps.LatLng(37.784177, -122.398959),
+ new google.maps.LatLng(37.784388, -122.398971),
+ new google.maps.LatLng(37.784404, -122.399128),
+ new google.maps.LatLng(37.784586, -122.399524),
+ new google.maps.LatLng(37.784835, -122.399927),
+ new google.maps.LatLng(37.785116, -122.400307),
+ new google.maps.LatLng(37.785282, -122.400539),
+ new google.maps.LatLng(37.785346, -122.400692),
+ new google.maps.LatLng(37.765769, -122.407201),
+ new google.maps.LatLng(37.76579, -122.407414),
+ new google.maps.LatLng(37.765802, -122.407755),
+ new google.maps.LatLng(37.765791, -122.408219),
+ new google.maps.LatLng(37.765763, -122.408759),
+ new google.maps.LatLng(37.765726, -122.409348),
+ new google.maps.LatLng(37.765716, -122.409882),
+ new google.maps.LatLng(37.765708, -122.410202),
+ new google.maps.LatLng(37.765705, -122.410253),
+ new google.maps.LatLng(37.765707, -122.410369),
+ new google.maps.LatLng(37.765692, -122.41072),
+ new google.maps.LatLng(37.765699, -122.411215),
+ new google.maps.LatLng(37.765687, -122.411789),
+ new google.maps.LatLng(37.765666, -122.412373),
+ new google.maps.LatLng(37.765598, -122.412883),
+ new google.maps.LatLng(37.765543, -122.413039),
+ new google.maps.LatLng(37.765532, -122.413125),
+ new google.maps.LatLng(37.7655, -122.413553),
+ new google.maps.LatLng(37.765448, -122.414053),
+ new google.maps.LatLng(37.765388, -122.414645),
+ new google.maps.LatLng(37.765323, -122.41525),
+ new google.maps.LatLng(37.765303, -122.415847),
+ new google.maps.LatLng(37.765251, -122.416439),
+ new google.maps.LatLng(37.765204, -122.41702),
+ new google.maps.LatLng(37.765172, -122.417556),
+ new google.maps.LatLng(37.765164, -122.418075),
+ new google.maps.LatLng(37.765153, -122.418618),
+ new google.maps.LatLng(37.765136, -122.419112),
+ new google.maps.LatLng(37.765129, -122.419378),
+ new google.maps.LatLng(37.765119, -122.419481),
+ new google.maps.LatLng(37.7651, -122.419852),
+ new google.maps.LatLng(37.765083, -122.420349),
+ new google.maps.LatLng(37.765045, -122.42093),
+ new google.maps.LatLng(37.764992, -122.421481),
+ new google.maps.LatLng(37.76498, -122.421695),
+ new google.maps.LatLng(37.764993, -122.421843),
+ new google.maps.LatLng(37.764986, -122.422255),
+ new google.maps.LatLng(37.764975, -122.422823),
+ new google.maps.LatLng(37.764939, -122.423411),
+ new google.maps.LatLng(37.764902, -122.424014),
+ new google.maps.LatLng(37.764853, -122.424576),
+ new google.maps.LatLng(37.764826, -122.424922),
+ new google.maps.LatLng(37.764796, -122.425375),
+ new google.maps.LatLng(37.764782, -122.425869),
+ new google.maps.LatLng(37.764768, -122.426089),
+ new google.maps.LatLng(37.764766, -122.426117),
+ new google.maps.LatLng(37.764723, -122.426276),
+ new google.maps.LatLng(37.764681, -122.426649),
+ new google.maps.LatLng(37.782012, -122.4042),
+ new google.maps.LatLng(37.781574, -122.404911),
+ new google.maps.LatLng(37.781055, -122.405597),
+ new google.maps.LatLng(37.780479, -122.406341),
+ new google.maps.LatLng(37.779996, -122.406939),
+ new google.maps.LatLng(37.779459, -122.407613),
+ new google.maps.LatLng(37.778953, -122.408228),
+ new google.maps.LatLng(37.778409, -122.408839),
+ new google.maps.LatLng(37.777842, -122.409501),
+ new google.maps.LatLng(37.777334, -122.410181),
+ new google.maps.LatLng(37.776809, -122.410836),
+ new google.maps.LatLng(37.77624, -122.411514),
+ new google.maps.LatLng(37.775725, -122.412145),
+ new google.maps.LatLng(37.77519, -122.412805),
+ new google.maps.LatLng(37.774672, -122.413464),
+ new google.maps.LatLng(37.774084, -122.414186),
+ new google.maps.LatLng(37.773533, -122.413636),
+ new google.maps.LatLng(37.773021, -122.413009),
+ new google.maps.LatLng(37.772501, -122.412371),
+ new google.maps.LatLng(37.771964, -122.411681),
+ new google.maps.LatLng(37.771479, -122.411078),
+ new google.maps.LatLng(37.770992, -122.410477),
+ new google.maps.LatLng(37.770467, -122.409801),
+ new google.maps.LatLng(37.77009, -122.408904),
+ new google.maps.LatLng(37.769657, -122.408103),
+ new google.maps.LatLng(37.769132, -122.407276),
+ new google.maps.LatLng(37.768564, -122.406469),
+ new google.maps.LatLng(37.76798, -122.405745),
+ new google.maps.LatLng(37.76738, -122.405299),
+ new google.maps.LatLng(37.766604, -122.405297),
+ new google.maps.LatLng(37.765838, -122.4052),
+ new google.maps.LatLng(37.765139, -122.405139),
+ new google.maps.LatLng(37.764457, -122.405094),
+ new google.maps.LatLng(37.763716, -122.405142),
+ new google.maps.LatLng(37.762932, -122.405398),
+ new google.maps.LatLng(37.762126, -122.405813),
+ new google.maps.LatLng(37.761344, -122.406215),
+ new google.maps.LatLng(37.760556, -122.406495),
+ new google.maps.LatLng(37.759732, -122.406484),
+ new google.maps.LatLng(37.75891, -122.406228),
+ new google.maps.LatLng(37.758182, -122.405695),
+ new google.maps.LatLng(37.757676, -122.405118),
+ new google.maps.LatLng(37.757039, -122.404346),
+ new google.maps.LatLng(37.756335, -122.403719),
+ new google.maps.LatLng(37.755503, -122.403406),
+ new google.maps.LatLng(37.754665, -122.403242),
+ new google.maps.LatLng(37.753837, -122.403172),
+ new google.maps.LatLng(37.752986, -122.403112),
+ new google.maps.LatLng(37.751266, -122.403355),
+ ];
+}
+//# sourceMappingURL=heatmap.js.map
\ No newline at end of file
diff --git a/Birdmap.API/ClientApp/src/components/heatmap/heatmap.js.map b/Birdmap.API/ClientApp/src/components/heatmap/heatmap.js.map
new file mode 100644
index 0000000..6a72953
--- /dev/null
+++ b/Birdmap.API/ClientApp/src/components/heatmap/heatmap.js.map
@@ -0,0 +1 @@
+{"version":3,"file":"heatmap.js","sourceRoot":"","sources":["heatmap.ts"],"names":[],"mappings":"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CAAC,MAAM,CAAC,SAAS,EAAE,CAAC,UAAU,CAAC;QAC9C,IAAI,MAAM,CAAC,IAAI,CAAC,MAAM,CAAC,SAAS,EAAE,CAAC,UAAU,CAAC;QAC9C,IAAI,MAAM,CAAC,IAAI,CAAC,MAAM,CAAC,SAAS,EAAE,CAAC,UAAU,CAAC;QAC9C,IAAI,MAAM,CAAC,IAAI,CAAC,MAAM,CAAC,SAAS,EAAE,CAAC,UAAU,CAAC;QAC9C,IAAI,MAAM,CAAC,IAAI,CAAC,MAAM,CAAC,SAAS,EAAE,CAAC,UAAU,CAAC;QAC9C,IAAI,MAAM,CAAC,IAAI,CAAC,MAAM,CAAC,SAAS,EAAE,CAAC,UAAU,CAAC;QAC9C,IAAI,MAAM,CAAC,IAAI,CAAC,MAAM,CAAC,SAAS,EAAE,CAAC,UAAU,CAAC;QAC9C,IAAI,MAAM,CAAC,IAAI,CAAC,MAAM,CAAC,SAAS,EAAE,CAAC,UAAU,CAAC;QAC9C,IAAI,MAAM,CAAC,IAAI,CAAC,MAAM,CAAC,SAAS,EAAE,CAAC,UAAU,CAAC;QAC9C,IAAI,MAAM,CAAC,IAAI,CAAC,MAAM,CAAC,SAAS,EAAE,CAAC,UAAU,CAAC;QAC9C,IAAI,MAAM,CAAC,IAAI,CAAC,MAAM,CAAC,SAAS,EAAE,CAAC,SAAS,CAAC;QAC7C,IAAI,MAAM,CAAC,IAAI,CAAC,MAAM,CAAC,SAAS,EAAE,CAAC,UAAU,CAAC;QAC9C,IAAI,MAAM,CAAC,IAAI,CAAC,MAAM,CAAC,SAAS,EAAE,CAAC,UAAU,CAAC;QAC9C,IAAI,MAAM,CAAC,IAAI,CAAC,MAAM,CAAC,SAAS,EAAE,CAAC,UAAU,CAAC;QAC9C,IAAI,MAAM,CAAC,IAAI,CAAC,MAAM,CAAC,SAAS,EAAE,CAAC,UAAU,CAAC;QAC9C,IAAI,MAAM,CAAC,IAAI,CAAC,MAAM,CAAC,SAAS,EAAE,CAAC,UAAU,CAAC;QAC9C,IAAI,MAAM,CAAC,IAAI,CAAC,MAAM,CAAC,SAAS,EAAE,CAAC,UAAU,CAAC;QAC9C,IAAI,MAAM,CAAC,IAAI,CAAC,MAAM,CAAC,QAAQ,EAAE,CAAC,UAAU,CAAC;QAC7C,IAAI,MAAM,CAAC,IAAI,CAAC,MAAM,CAAC,SAAS,EAAE,CAAC,UAAU,CAAC;QAC9C,IAAI,MAAM,CAAC,IAAI,CAAC,MAAM,CAAC,SAAS,EAAE,CAAC,UAAU,CAAC;QAC9C,IAAI,MAAM,CAAC,IAAI,CAAC,MAAM,CAAC,QAAQ,EAAE,CAAC,UAAU,CAAC;QAC7C,IAAI,MAAM,CAAC,IAAI,CAAC,MAAM,CAAC,SAAS,EAAE,CAAC,UAAU,CAAC;QAC9C,IAAI,MAAM,CAAC,IAAI,CAAC,MAAM,CAAC,SAAS,EAAE,CAAC,UAAU,CAAC;QAC9C,IAAI,MAAM,CAAC,IAAI,CAAC,MAAM,CAAC,SAAS,EAAE,CAAC,UAAU,CAAC;QAC9C,IAAI,MAAM,CAAC,IAAI,CAAC,MAAM,CAAC,SAAS,EAAE,CAAC,UAAU,CAAC;QAC9C,IAAI,MAAM,CAAC,IAAI,CAAC,MAAM,CAAC,SAAS,EAAE,CAAC,UAAU,CAAC;QAC9C,IAAI,MAAM,CAAC,IAAI,CAAC,MAAM,CAAC,SAAS,EAAE,CAAC,UAAU,CAAC;QAC9C,IAAI,MAAM,CAAC,IAAI,CAAC,MAAM,CAAC,SAAS,EAAE,CAAC,UAAU,CAAC;QAC9C,IAAI,MAAM,CAAC,IAAI,CAAC,MAAM,CAAC,SAAS,EAAE,CAAC,UAAU,CAAC;QAC9C,IAAI,MAAM,CAAC,IAAI,CAAC,MAAM,CAAC,SAAS,EAAE,CAAC,UAAU,CAAC;QAC9C,IAAI,MAAM,CAAC,IAAI,CAAC,MAAM,CAAC,SAAS,EAAE,CAAC,UAAU,CAAC;QAC9C,IAAI,MAAM,CAAC,IAAI,CAAC,MAAM,CAAC,SAAS,EAAE,CAAC,UAAU,CAAC;QAC9C,IAAI,MAAM,CAAC,IAAI,CAAC,MAAM,CAAC,SAAS,EAAE,CAAC,UAAU,CAAC;QAC9C,IAAI,MAAM,CAAC,IAAI,CAAC,MAAM,CAAC,SAAS,EAAE,CAAC,UAAU,CAAC;QAC9C,IAAI,MAAM,CAAC,IAAI,CAAC,MAAM,CAAC,SAAS,EAAE,CAAC,UAAU,CAAC;QAC9C,IAAI,MAAM,CAAC,IAAI,CAAC,MAAM,CAAC,SAAS,EAAE,CAAC,UAAU,CAAC;QAC9C,IAAI,MAAM,CAAC,IAAI,CAAC,MAAM,CAAC,SAAS,EAAE,CAAC,SAAS,CAAC;QAC7C,IAAI,MAAM,CAAC,IAAI,CAAC,MAAM,CAAC,QAAQ,EAAE,CAAC,UAAU,CAAC;QAC7C,IAAI,MAAM,CAAC,IAAI,CAAC,MAAM,CAAC,SAAS,EAAE,CAAC,UAAU,CAAC;QAC9C,IAAI,MAAM,CAAC,IAAI,CAAC,MAAM,CAAC,OAAO,EAAE,CAAC,UAAU,CAAC;QAC5C,IAAI,MAAM,CAAC,IAAI,CAAC,MAAM,CAAC,SAAS,EAAE,CAAC,UAAU,CAAC;QAC9C,IAAI,MAAM,CAAC,IAAI,CAAC,MAAM,CAAC,SAAS,EAAE,CAAC,UAAU,CAAC;QAC9C,IAAI,MAAM,CAAC,IAAI,CAAC,MAAM,CAAC,SAAS,EAAE,CAAC,UAAU,CAAC;QAC9C,IAAI,MAAM,CAAC,IAAI,CAAC,MAAM,CAAC,SAAS,EAAE,CAAC,UAAU,CAAC;QAC9C,IAAI,MAAM,CAAC,IAAI,CAAC,MAAM,CAAC,SAAS,EAAE,CAAC,SAAS,CAAC;QAC7C,IAAI,MAAM,CAAC,IAAI,CAAC,MAAM,CAAC,SAAS,EAAE,CAAC,UAAU,CAAC;QAC9C,IAAI,MAAM,CAAC,IAAI,CAAC,MAAM,CAAC,SAAS,EAAE,CAAC,UAAU,CAAC;QAC9C,IAAI,MAAM,CAAC,IAAI,CAAC,MAAM,CAAC,SAAS,EAAE,CAAC,UAAU,CAAC;QAC9C,IAAI,MAAM,CAAC,IAAI,CAAC,MAAM,CAAC,SAAS,EAAE,CAAC,UAAU,CAAC;QAC9C,IAAI,MAAM,CAAC,IAAI,CAAC,MAAM,CAAC,SAAS,EAAE,CAAC,UAAU,CAAC;QAC9C,IAAI,MAAM,CAAC,IAAI,CAAC,MAAM,CAAC,SAAS,EAAE,CAAC,UAAU,CAAC;QAC9C,IAAI,MAAM,CAAC,IAAI,CAAC,MAAM,CAAC,SAAS,EAAE,CAAC,UAAU,CAAC;QAC9C,IAAI,MAAM,CAAC,IAAI,CAAC,MAAM,CAAC,SAAS,EAAE,CAAC,UAAU,CAAC;QAC9C,IAAI,MAAM,CAAC,IAAI,CAAC,MAAM,CAAC,SAAS,EAAE,CAAC,UAAU,CAAC;QAC9C,IAAI,MAAM,CAAC,IAAI,CAAC,MAAM,CAAC,SAAS,EAAE,CAAC,UAAU,CAAC;QAC9C,IAAI,MAAM,CAAC,IAAI,CAAC,MAAM,CAAC,SAAS,EAAE,CAAC,UAAU,CAAC;QAC9C,IAAI,MAAM,CAAC,IAAI,CAAC,MAAM,CAAC,SAAS,EAAE,CAAC,UAAU,CAAC;QAC9C,IAAI,MAAM,CAAC,IAAI,CAAC,MAAM,CAAC,OAAO,EAAE,CAAC,UAAU,CAAC;QAC5C,IAAI,MAAM,CAAC,IAAI,CAAC,MAAM,CAAC,SAAS,EAAE,CAAC,UAAU,CAAC;QAC9C,IAAI,MAAM,CAAC,IAAI,CAAC,MAAM,CAAC,QAAQ,EAAE,CAAC,UAAU,CAAC;QAC7C,IAAI,MAAM,CAAC,IAAI,CAAC,MAAM,CAAC,SAAS,EAAE,CAAC,UAAU,CAAC;QAC9C,IAAI,MAAM,CAAC,IAAI,CAAC,MAAM,CAAC,SAAS,EAAE,CAAC,UAAU,CAAC;QAC9C,IAAI,MAAM,CAAC,IAAI,CAAC,MAAM,CAAC,SAAS,EAAE,CAAC,UAAU,CAAC;QAC9C,IAAI,MAAM,CAAC,IAAI,CAAC,MAAM,CAAC,SAAS,EAAE,CAAC,UAAU,CAAC;QAC9C,IAAI,MAAM,CAAC,IAAI,CAAC,MAAM,CAAC,SAAS,EAAE,CAAC,UAAU,CAAC;QAC9C,IAAI,MAAM,CAAC,IAAI,CAAC,MAAM,CAAC,SAAS,EAAE,CAAC,UAAU,CAAC;QAC9C,IAAI,MAAM,CAAC,IAAI,CAAC,MAAM,CAAC,SAAS,EAAE,CAAC,UAAU,CAAC;QAC9C,IAAI,MAAM,CAAC,IAAI,CAAC,MAAM,CAAC,SAAS,EAAE,CAAC,UAAU,CAAC;QAC9C,IAAI,MAAM,CAAC,IAAI,CAAC,MAAM,CAAC,SAAS,EAAE,CAAC,UAAU,CAAC;QAC9C,IAAI,MAAM,CAAC,IAAI,CAAC,MAAM,CAAC,SAAS,EAAE,CAAC,UAAU,CAAC;QAC9C,IAAI,MAAM,CAAC,IAAI,CAAC,MAAM,CAAC,SAAS,EAAE,CAAC,SAAS,CAAC;QAC7C,IAAI,MAAM,CAAC,IAAI,CAAC,MAAM,CAAC,SAAS,EAAE,CAAC,UAAU,CAAC;QAC9C,IAAI,MAAM,CAAC,IAAI,CAAC,MAAM,CAAC,SAAS,EAAE,CAAC,UAAU,CAAC;QAC9C,IAAI,MAAM,CAAC,IAAI,CAAC,MAAM,CAAC,SAAS,EAAE,CAAC,UAAU,CAAC;QAC9C,IAAI,MAAM,CAAC,IAAI,CAAC,MAAM,CAAC,SAAS,EAAE,CAAC,UAAU,CAAC;QAC9C,IAAI,MAAM,CAAC,IAAI,CAAC,MAAM,CAAC,QAAQ,EAAE,CAAC,UAAU,CAAC;QAC7C,IAAI,MAAM,CAAC,IAAI,CAAC,MAAM,CAAC,SAAS,EAAE,CAAC,UAAU,CAAC;QAC9C,IAAI,MAAM,CAAC,IAAI,CAAC,MAAM,CAAC,SAAS,EAAE,CAAC,UAAU,CAAC;QAC9C,IAAI,MAAM,CAAC,IAAI,CAAC,MAAM,CAAC,SAAS,EAAE,CAAC,UAAU,CAAC;QAC9C,IAAI,MAAM,CAAC,IAAI,CAAC,MAAM,CAAC,SAAS,EAAE,CAAC,UAAU,CAAC;QAC9C,IAAI,MAAM,CAAC,IAAI,CAAC,MAAM,CAAC,QAAQ,EAAE,CAAC,UAAU,CAAC;QAC7C,IAAI,MAAM,CAAC,IAAI,CAAC,MAAM,CAAC,SAAS,EAAE,CAAC,UAAU,CAAC;QAC9C,IAAI,MAAM,CAAC,IAAI,CAAC,MAAM,CAAC,SAAS,EAAE,CAAC,UAAU,CAAC;QAC9C,IAAI,MAAM,CAAC,IAAI,CAAC,MAAM,CAAC,SAAS,EAAE,CAAC,UAAU,CAAC;QAC9C,IAAI,MAAM,CAAC,IAAI,CAAC,MAAM,CAAC,SAAS,EAAE,CAAC,UAAU,CAAC;QAC9C,IAAI,MAAM,CAAC,IAAI,CAAC,MAAM,CAAC,QAAQ,EAAE,CAAC,UAAU,CAAC;QAC7C,IAAI,MAAM,CAAC,IAAI,CAAC,MAAM,CAAC,SAAS,EAAE,CAAC,UAAU,CAAC;QAC9C,IAAI,MAAM,CAAC,IAAI,CAAC,MAAM,CAAC,QAAQ,EAAE,CAAC,UAAU,CAAC;QAC7C,IAAI,MAAM,CAAC,IAAI,CAAC,MAAM,CAAC,SAAS,EAAE,CAAC,UAAU,CAAC;QAC9C,IAAI,MAAM,CAAC,IAAI,CAAC,MAAM,CAAC,SAAS,EAAE,CAAC,UAAU,CAAC;QAC9C,IAAI,MAAM,CAAC,IAAI,CAAC,MAAM,CAAC,OAAO,EAAE,CAAC,UAAU,CAAC;QAC5C,IAAI,MAAM,CAAC,IAAI,CAAC,MAAM,CAAC,SAAS,EAAE,CAAC,UAAU,CAAC;QAC9C,IAAI,MAAM,CAAC,IAAI,CAAC,MAAM,CAAC,SAAS,EAAE,CAAC,UAAU,CAAC;QAC9C,IAAI,MAAM,CAAC,IAAI,CAAC,MAAM,CAAC,SAAS,EAAE,CAAC,UAAU,CAAC;QAC9C,IAAI,MAAM,CAAC,IAAI,CAAC,MAAM,CAAC,SAAS,EAAE,CAAC,UAAU,CAAC;QAC9C,IAAI,MAAM,CAAC,IAAI,CAAC,MAAM,CAAC,SAAS,EAAE,CAAC,UAAU,CAAC;QAC9C,IAAI,MAAM,CAAC,IAAI,CAAC,MAAM,CAAC,SAAS,EAAE,CAAC,UAAU,CAAC;QAC9C,IAAI,MAAM,CAAC,IAAI,CAAC,MAAM,CAAC,SAAS,EAAE,CAAC,UAAU,CAAC;QAC9C,IAAI,MAAM,CAAC,IAAI,CAAC,MAAM,CAAC,SAAS,EAAE,CAAC,SAAS,CAAC;QAC7C,IAAI,MAAM,CAAC,IAAI,CAAC,MAAM,CAAC,SAAS,EAAE,CAAC,UAAU,CAAC;QAC9C,IAAI,MAAM,CAAC,IAAI,CAAC,MAAM,CAAC,SAAS,EAAE,CAAC,SAAS,CAAC;QAC7C,IAAI,MAAM,CAAC,IAAI,CAAC,MAAM,CAAC,SAAS,EAAE,CAAC,UAAU,CAAC;QAC9C,IAAI,MAAM,CAAC,IAAI,CAAC,MAAM,CAAC,SAAS,EAAE,CAAC,SAAS,CAAC;QAC7C,IAAI,MAAM,CAAC,IAAI,CAAC,MAAM,CAAC,SAAS,EAAE,CAAC,UAAU,CAAC;QAC9C,IAAI,MAAM,CAAC,IAAI,CAAC,MAAM,CAAC,SAAS,EAAE,CAAC,UAAU,CAAC;QAC9C,IAAI,MAAM,CAAC,IAAI,CAAC,MAAM,CAAC,SAAS,EAAE,CAAC,UAAU,CAAC;QAC9C,IAAI,MAAM,CAAC,IAAI,CAAC,MAAM,CAAC,QAAQ,EAAE,CAAC,UAAU,CAAC;QAC7C,IAAI,MAAM,CAAC,IAAI,CAAC,MAAM,CAAC,QAAQ,EAAE,CAAC,UAAU,CAAC;QAC7C,IAAI,MAAM,CAAC,IAAI,CAAC,MAAM,CAAC,SAAS,EAAE,CAAC,UAAU,CAAC;QAC9C,IAAI,MAAM,CAAC,IAAI,CAAC,MAAM,CAAC,SAAS,EAAE,CAAC,SAAS,CAAC;QAC7C,IAAI,MAAM,CAAC,IAAI,CAAC,MAAM,CAAC,SAAS,EAAE,CAAC,SAAS,CAAC;QAC7C,IAAI,MAAM,CAAC,IAAI,CAAC,MAAM,CAAC,SAAS,EAAE,CAAC,UAAU,CAAC;QAC9C,IAAI,MAAM,CAAC,IAAI,CAAC,MAAM,CAAC,SAAS,EAAE,CAAC,UAAU,CAAC;QAC9C,IAAI,MAAM,CAAC,IAAI,CAAC,MAAM,CAAC,SAAS,EAAE,CAAC,SAAS,CAAC;QAC7C,IAAI,MAAM,CAAC,IAAI,CAAC,MAAM,CAAC,SAAS,EAAE,CAAC,SAAS,CAAC;QAC7C,IAAI,MAAM,CAAC,IAAI,CAAC,MAAM,CAAC,SAAS,EAAE,CAAC,UAAU,CAAC;QAC9C,IAAI,MAAM,CAAC,IAAI,CAAC,MAAM,CAAC,SAAS,EAAE,CAAC,UAAU,CAAC;QAC9C,IAAI,MAAM,CAAC,IAAI,CAAC,MAAM,CAAC,OAAO,EAAE,CAAC,UAAU,CAAC;QAC5C,IAAI,MAAM,CAAC,IAAI,CAAC,MAAM,CAAC,SAAS,EAAE,CAAC,UAAU,CAAC;QAC9C,IAAI,MAAM,CAAC,IAAI,CAAC,MAAM,CAAC,SAAS,EAAE,CAAC,UAAU,CAAC;QAC9C,IAAI,MAAM,CAAC,IAAI,CAAC,MAAM,CAAC,SAAS,EAAE,CAAC,UAAU,CAAC;QAC9C,IAAI,MAAM,CAAC,IAAI,CAAC,MAAM,CAAC,SAAS,EAAE,CAAC,UAAU,CAAC;QAC9C,IAAI,MAAM,CAAC,IAAI,CAAC,MAAM,CAAC,SAAS,EAAE,CAAC,UAAU,CAAC;QAC9C,IAAI,MAAM,CAAC,IAAI,CAAC,MAAM,CAAC,SAAS,EAAE,CAAC,UAAU,CAAC;QAC9C,IAAI,MAAM,CAAC,IAAI,CAAC,MAAM,CAAC,SAAS,EAAE,CAAC,UAAU,CAAC;QAC9C,IAAI,MAAM,CAAC,IAAI,CAAC,MAAM,CAAC,SAAS,EAAE,CAAC,UAAU,CAAC;QAC9C,IAAI,MAAM,CAAC,IAAI,CAAC,MAAM,CAAC,SAAS,EAAE,CAAC,UAAU,CAAC;QAC9C,IAAI,MAAM,CAAC,IAAI,CAAC,MAAM,CAAC,SAAS,EAAE,CAAC,UAAU,CAAC;QAC9C,IAAI,MAAM,CAAC,IAAI,CAAC,MAAM,CAAC,SAAS,EAAE,CAAC,UAAU,CAAC;QAC9C,IAAI,MAAM,CAAC,IAAI,CAAC,MAAM,CAAC,SAAS,EAAE,CAAC,UAAU,CAAC;QAC9C,IAAI,MAAM,CAAC,IAAI,CAAC,MAAM,CAAC,SAAS,EAAE,CAAC,UAAU,CAAC;QAC9C,IAAI,MAAM,CAAC,IAAI,CAAC,MAAM,CAAC,SAAS,EAAE,CAAC,UAAU,CAAC;QAC9C,IAAI,MAAM,CAAC,IAAI,CAAC,MAAM,CAAC,SAAS,EAAE,CAAC,UAAU,CAAC;QAC9C,IAAI,MAAM,CAAC,IAAI,CAAC,MAAM,CAAC,SAAS,EAAE,CAAC,UAAU,CAAC;QAC9C,IAAI,MAAM,CAAC,IAAI,CAAC,MAAM,CAAC,SAAS,EAAE,CAAC,SAAS,CAAC;QAC7C,IAAI,MAAM,CAAC,IAAI,CAAC,MAAM,CAAC,SAAS,EAAE,CAAC,UAAU,CAAC;QAC9C,IAAI,MAAM,CAAC,IAAI,CAAC,MAAM,CAAC,SAAS,EAAE,CAAC,UAAU,CAAC;QAC9C,IAAI,MAAM,CAAC,IAAI,CAAC,MAAM,CAAC,SAAS,EAAE,CAAC,UAAU,CAAC;QAC9C,IAAI,MAAM,CAAC,IAAI,CAAC,MAAM,CAAC,SAAS,EAAE,CAAC,UAAU,CAAC;QAC9C,IAAI,MAAM,CAAC,IAAI,CAAC,MAAM,CAAC,SAAS,EAAE,CAAC,UAAU,CAAC;QAC9C,IAAI,MAAM,CAAC,IAAI,CAAC,MAAM,CAAC,SAAS,EAAE,CAAC,UAAU,CAAC;QAC9C,IAAI,MAAM,CAAC,IAAI,CAAC,MAAM,CAAC,SAAS,EAAE,CAAC,UAAU,CAAC;QAC9C,IAAI,MAAM,CAAC,IAAI,CAAC,MAAM,CAAC,SAAS,EAAE,CAAC,UAAU,CAAC;QAC9C,IAAI,MAAM,CAAC,IAAI,CAAC,MAAM,CAAC,SAAS,EAAE,CAAC,UAAU,CAAC;QAC9C,IAAI,MAAM,CAAC,IAAI,CAAC,MAAM,CAAC,SAAS,EAAE,CAAC,UAAU,CAAC;QAC9C,IAAI,MAAM,CAAC,IAAI,CAAC,MAAM,CAAC,SAAS,EAAE,CAAC,UAAU,CAAC;QAC9C,IAAI,MAAM,CAAC,IAAI,CAAC,MAAM,CAAC,SAAS,EAAE,CAAC,UAAU,CAAC;QAC9C,IAAI,MAAM,CAAC,IAAI,CAAC,MAAM,CAAC,SAAS,EAAE,CAAC,UAAU,CAAC;QAC9C,IAAI,MAAM,CAAC,IAAI,CAAC,MAAM,CAAC,SAAS,EAAE,CAAC,UAAU,CAAC;QAC9C,IAAI,MAAM,CAAC,IAAI,CAAC,MAAM,CAAC,SAAS,EAAE,CAAC,UAAU,CAAC;QAC9C,IAAI,MAAM,CAAC,IAAI,CAAC,MAAM,CAAC,SAAS,EAAE,CAAC,UAAU,CAAC;QAC9C,IAAI,MAAM,CAAC,IAAI,CAAC,MAAM,CAAC,SAAS,EAAE,CAAC,UAAU,CAAC;QAC9C,IAAI,MAAM,CAAC,IAAI,CAAC,MAAM,CAAC,SAAS,EAAE,CAAC,UAAU,CAAC;QAC9C,IAAI,MAAM,CAAC,IAAI,CAAC,MAAM,CAAC,SAAS,EAAE,CAAC,UAAU,CAAC;QAC9C,IAAI,MAAM,CAAC,IAAI,CAAC,MAAM,CAAC,SAAS,EAAE,CAAC,UAAU,CAAC;QAC9C,IAAI,MAAM,CAAC,IAAI,CAAC,MAAM,CAAC,SAAS,EAAE,CAAC,UAAU,CAAC;QAC9C,IAAI,MAAM,CAAC,IAAI,CAAC,MAAM,CAAC,SAAS,EAAE,CAAC,UAAU,CAAC;QAC9C,IAAI,MAAM,CAAC,IAAI,CAAC,MAAM,CAAC,SAAS,EAAE,CAAC,UAAU,CAAC;QAC9C,IAAI,MAAM,CAAC,IAAI,CAAC,MAAM,CAAC,SAAS,EAAE,CAAC,SAAS,CAAC;QAC7C,IAAI,MAAM,CAAC,IAAI,CAAC,MAAM,CAAC,SAAS,EAAE,CAAC,UAAU,CAAC;QAC9C,IAAI,MAAM,CAAC,IAAI,CAAC,MAAM,CAAC,SAAS,EAAE,CAAC,UAAU,CAAC;QAC9C,IAAI,MAAM,CAAC,IAAI,CAAC,MAAM,CAAC,SAAS,EAAE,CAAC,UAAU,CAAC;QAC9C,IAAI,MAAM,CAAC,IAAI,CAAC,MAAM,CAAC,SAAS,EAAE,CAAC,UAAU,CAAC;QAC9C,IAAI,MAAM,CAAC,IAAI,CAAC,MAAM,CAAC,SAAS,EAAE,CAAC,UAAU,CAAC;QAC9C,IAAI,MAAM,CAAC,IAAI,CAAC,MAAM,CAAC,OAAO,EAAE,CAAC,UAAU,CAAC;QAC5C,IAAI,MAAM,CAAC,IAAI,CAAC,MAAM,CAAC,SAAS,EAAE,CAAC,SAAS,CAAC;QAC7C,IAAI,MAAM,CAAC,IAAI,CAAC,MAAM,CAAC,SAAS,EAAE,CAAC,UAAU,CAAC;QAC9C,IAAI,MAAM,CAAC,IAAI,CAAC,MAAM,CAAC,SAAS,EAAE,CAAC,UAAU,CAAC;QAC9C,IAAI,MAAM,CAAC,IAAI,CAAC,MAAM,CAAC,QAAQ,EAAE,CAAC,UAAU,CAAC;QAC7C,IAAI,MAAM,CAAC,IAAI,CAAC,MAAM,CAAC,SAAS,EAAE,CAAC,UAAU,CAAC;QAC9C,IAAI,MAAM,CAAC,IAAI,CAAC,MAAM,CAAC,SAAS,EAAE,CAAC,UAAU,CAAC;QAC9C,IAAI,MAAM,CAAC,IAAI,CAAC,MAAM,CAAC,SAAS,EAAE,CAAC,UAAU,CAAC;QAC9C,IAAI,MAAM,CAAC,IAAI,CAAC,MAAM,CAAC,OAAO,EAAE,CAAC,UAAU,CAAC;QAC5C,IAAI,MAAM,CAAC,IAAI,CAAC,MAAM,CAAC,SAAS,EAAE,CAAC,UAAU,CAAC;QAC9C,IAAI,MAAM,CAAC,IAAI,CAAC,MAAM,CAAC,SAAS,EAAE,CAAC,UAAU,CAAC;QAC9C,IAAI,MAAM,CAAC,IAAI,CAAC,MAAM,CAAC,SAAS,EAAE,CAAC,UAAU,CAAC;QAC9C,IAAI,MAAM,CAAC,IAAI,CAAC,MAAM,CAAC,SAAS,EAAE,CAAC,UAAU,CAAC;QAC9C,IAAI,MAAM,CAAC,IAAI,CAAC,MAAM,CAAC,SAAS,EAAE,CAAC,UAAU,CAAC;QAC9C,IAAI,MAAM,CAAC,IAAI,CAAC,MAAM,CAAC,SAAS,EAAE,CAAC,UAAU,CAAC;QAC9C,IAAI,MAAM,CAAC,IAAI,CAAC,MAAM,CAAC,SAAS,EAAE,CAAC,UAAU,CAAC;QAC9C,IAAI,MAAM,CAAC,IAAI,CAAC,MAAM,CAAC,SAAS,EAAE,CAAC,UAAU,CAAC;QAC9C,IAAI,MAAM,CAAC,IAAI,CAAC,MAAM,CAAC,SAAS,EAAE,CAAC,UAAU,CAAC;QAC9C,IAAI,MAAM,CAAC,IAAI,CAAC,MAAM,CAAC,SAAS,EAAE,CAAC,UAAU,CAAC;QAC9C,IAAI,MAAM,CAAC,IAAI,CAAC,MAAM,CAAC,SAAS,EAAE,CAAC,UAAU,CAAC;QAC9C,IAAI,MAAM,CAAC,IAAI,CAAC,MAAM,CAAC,QAAQ,EAAE,CAAC,UAAU,CAAC;QAC7C,IAAI,MAAM,CAAC,IAAI,CAAC,MAAM,CAAC,SAAS,EAAE,CAAC,UAAU,CAAC;QAC9C,IAAI,MAAM,CAAC,IAAI,CAAC,MAAM,CAAC,QAAQ,EAAE,CAAC,UAAU,CAAC;QAC7C,IAAI,MAAM,CAAC,IAAI,CAAC,MAAM,CAAC,SAAS,EAAE,CAAC,UAAU,CAAC;QAC9C,IAAI,MAAM,CAAC,IAAI,CAAC,MAAM,CAAC,QAAQ,EAAE,CAAC,UAAU,CAAC;QAC7C,IAAI,MAAM,CAAC,IAAI,CAAC,MAAM,CAAC,SAAS,EAAE,CAAC,UAAU,CAAC;QAC9C,IAAI,MAAM,CAAC,IAAI,CAAC,MAAM,CAAC,SAAS,EAAE,CAAC,UAAU,CAAC;QAC9C,IAAI,MAAM,CAAC,IAAI,CAAC,MAAM,CAAC,SAAS,EAAE,CAAC,UAAU,CAAC;QAC9C,IAAI,MAAM,CAAC,IAAI,CAAC,MAAM,CAAC,SAAS,EAAE,CAAC,UAAU,CAAC;QAC9C,IAAI,MAAM,CAAC,IAAI,CAAC,MAAM,CAAC,SAAS,EAAE,CAAC,UAAU,CAAC;QAC9C,IAAI,MAAM,CAAC,IAAI,CAAC,MAAM,CAAC,SAAS,EAAE,CAAC,UAAU,CAAC;QAC9C,IAAI,MAAM,CAAC,IAAI,CAAC,MAAM,CAAC,SAAS,EAAE,CAAC,UAAU,CAAC;QAC9C,IAAI,MAAM,CAAC,IAAI,CAAC,MAAM,CAAC,SAAS,EAAE,CAAC,UAAU,CAAC;QAC9C,IAAI,MAAM,CAAC,IAAI,CAAC,MAAM,CAAC,SAAS,EAAE,CAAC,UAAU,CAAC;QAC9C,IAAI,MAAM,CAAC,IAAI,CAAC,MAAM,CAAC,SAAS,EAAE,CAAC,UAAU,CAAC;QAC9C,IAAI,MAAM,CAAC,IAAI,CAAC,MAAM,CAAC,SAAS,EAAE,CAAC,UAAU,CAAC;QAC9C,IAAI,MAAM,CAAC,IAAI,CAAC,MAAM,CAAC,QAAQ,EAAE,CAAC,UAAU,CAAC;QAC7C,IAAI,MAAM,CAAC,IAAI,CAAC,MAAM,CAAC,SAAS,EAAE,CAAC,SAAS,CAAC;QAC7C,IAAI,MAAM,CAAC,IAAI,CAAC,MAAM,CAAC,QAAQ,EAAE,CAAC,UAAU,CAAC;QAC7C,IAAI,MAAM,CAAC,IAAI,CAAC,MAAM,CAAC,SAAS,EAAE,CAAC,UAAU,CAAC;QAC9C,IAAI,MAAM,CAAC,IAAI,CAAC,MAAM,CAAC,SAAS,EAAE,CAAC,UAAU,CAAC;QAC9C,IAAI,MAAM,CAAC,IAAI,CAAC,MAAM,CAAC,SAAS,EAAE,CAAC,UAAU,CAAC;QAC9C,IAAI,MAAM,CAAC,IAAI,CAAC,MAAM,CAAC,SAAS,EAAE,CAAC,UAAU,CAAC;QAC9C,IAAI,MAAM,CAAC,IAAI,CAAC,MAAM,CAAC,SAAS,EAAE,CAAC,UAAU,CAAC;QAC9C,IAAI,MAAM,CAAC,IAAI,CAAC,MAAM,CAAC,SAAS,EAAE,CAAC,UAAU,CAAC;QAC9C,IAAI,MAAM,CAAC,IAAI,CAAC,MAAM,CAAC,SAAS,EAAE,CAAC,SAAS,CAAC;QAC7C,IAAI,MAAM,CAAC,IAAI,CAAC,MAAM,CAAC,SAAS,EAAE,CAAC,SAAS,CAAC;QAC7C,IAAI,MAAM,CAAC,IAAI,CAAC,MAAM,CAAC,SAAS,EAAE,CAAC,SAAS,CAAC;QAC7C,IAAI,MAAM,CAAC,IAAI,CAAC,MAAM,CAAC,SAAS,EAAE,CAAC,UAAU,CAAC;QAC9C,IAAI,MAAM,CAAC,IAAI,CAAC,MAAM,CAAC,SAAS,EAAE,CAAC,UAAU,CAAC;QAC9C,IAAI,MAAM,CAAC,IAAI,CAAC,MAAM,CAAC,QAAQ,EAAE,CAAC,UAAU,CAAC;QAC7C,IAAI,MAAM,CAAC,IAAI,CAAC,MAAM,CAAC,QAAQ,EAAE,CAAC,UAAU,CAAC;QAC7C,IAAI,MAAM,CAAC,IAAI,CAAC,MAAM,CAAC,SAAS,EAAE,CAAC,UAAU,CAAC;QAC9C,IAAI,MAAM,CAAC,IAAI,CAAC,MAAM,CAAC,SAAS,EAAE,CAAC,UAAU,CAAC;QAC9C,IAAI,MAAM,CAAC,IAAI,CAAC,MAAM,CAAC,SAAS,EAAE,CAAC,SAAS,CAAC;QAC7C,IAAI,MAAM,CAAC,IAAI,CAAC,MAAM,CAAC,SAAS,EAAE,CAAC,UAAU,CAAC;QAC9C,IAAI,MAAM,CAAC,IAAI,CAAC,MAAM,CAAC,SAAS,EAAE,CAAC,UAAU,CAAC;QAC9C,IAAI,MAAM,CAAC,IAAI,CAAC,MAAM,CAAC,SAAS,EAAE,CAAC,UAAU,CAAC;QAC9C,IAAI,MAAM,CAAC,IAAI,CAAC,MAAM,CAAC,SAAS,EAAE,CAAC,UAAU,CAAC;QAC9C,IAAI,MAAM,CAAC,IAAI,CAAC,MAAM,CAAC,SAAS,EAAE,CAAC,UAAU,CAAC;QAC9C,IAAI,MAAM,CAAC,IAAI,CAAC,MAAM,CAAC,SAAS,EAAE,CAAC,UAAU,CAAC;QAC9C,IAAI,MAAM,CAAC,IAAI,CAAC,MAAM,CAAC,QAAQ,EAAE,CAAC,SAAS,CAAC;QAC5C,IAAI,MAAM,CAAC,IAAI,CAAC,MAAM,CAAC,SAAS,EAAE,CAAC,UAAU,CAAC;QAC9C,IAAI,MAAM,CAAC,IAAI,CAAC,MAAM,CAAC,SAAS,EAAE,CAAC,SAAS,CAAC;QAC7C,IAAI,MAAM,CAAC,IAAI,CAAC,MAAM,CAAC,SAAS,EAAE,CAAC,UAAU,CAAC;QAC9C,IAAI,MAAM,CAAC,IAAI,CAAC,MAAM,CAAC,SAAS,EAAE,CAAC,UAAU,CAAC;QAC9C,IAAI,MAAM,CAAC,IAAI,CAAC,MAAM,CAAC,SAAS,EAAE,CAAC,UAAU,CAAC;QAC9C,IAAI,MAAM,CAAC,IAAI,CAAC,MAAM,CAAC,SAAS,EAAE,CAAC,UAAU,CAAC;QAC9C,IAAI,MAAM,CAAC,IAAI,CAAC,MAAM,CAAC,SAAS,EAAE,CAAC,UAAU,CAAC;QAC9C,IAAI,MAAM,CAAC,IAAI,CAAC,MAAM,CAAC,SAAS,EAAE,CAAC,UAAU,CAAC;QAC9C,IAAI,MAAM,CAAC,IAAI,CAAC,MAAM,CAAC,SAAS,EAAE,CAAC,UAAU,CAAC;QAC9C,IAAI,MAAM,CAAC,IAAI,CAAC,MAAM,CAAC,SAAS,EAAE,CAAC,UAAU,CAAC;QAC9C,IAAI,MAAM,CAAC,IAAI,CAAC,MAAM,CAAC,SAAS,EAAE,CAAC,UAAU,CAAC;QAC9C,IAAI,MAAM,CAAC,IAAI,CAAC,MAAM,CAAC,SAAS,EAAE,CAAC,UAAU,CAAC;QAC9C,IAAI,MAAM,CAAC,IAAI,CAAC,MAAM,CAAC,SAAS,EAAE,CAAC,UAAU,CAAC;QAC9C,IAAI,MAAM,CAAC,IAAI,CAAC,MAAM,CAAC,SAAS,EAAE,CAAC,UAAU,CAAC;QAC9C,IAAI,MAAM,CAAC,IAAI,CAAC,MAAM,CAAC,QAAQ,EAAE,CAAC,UAAU,CAAC;QAC7C,IAAI,MAAM,CAAC,IAAI,CAAC,MAAM,CAAC,SAAS,EAAE,CAAC,UAAU,CAAC;QAC9C,IAAI,MAAM,CAAC,IAAI,CAAC,MAAM,CAAC,SAAS,EAAE,CAAC,UAAU,CAAC;QAC9C,IAAI,MAAM,CAAC,IAAI,CAAC,MAAM,CAAC,SAAS,EAAE,CAAC,SAAS,CAAC;QAC7C,IAAI,MAAM,CAAC,IAAI,CAAC,MAAM,CAAC,SAAS,EAAE,CAAC,UAAU,CAAC;QAC9C,IAAI,MAAM,CAAC,IAAI,CAAC,MAAM,CAAC,SAAS,EAAE,CAAC,UAAU,CAAC;QAC9C,IAAI,MAAM,CAAC,IAAI,CAAC,MAAM,CAAC,SAAS,EAAE,CAAC,UAAU,CAAC;QAC9C,IAAI,MAAM,CAAC,IAAI,CAAC,MAAM,CAAC,SAAS,EAAE,CAAC,UAAU,CAAC;QAC9C,IAAI,MAAM,CAAC,IAAI,CAAC,MAAM,CAAC,SAAS,EAAE,CAAC,UAAU,CAAC;QAC9C,IAAI,MAAM,CAAC,IAAI,CAAC,MAAM,CAAC,SAAS,EAAE,CAAC,UAAU,CAAC;QAC9C,IAAI,MAAM,CAAC,IAAI,CAAC,MAAM,CAAC,QAAQ,EAAE,CAAC,UAAU,CAAC;QAC7C,IAAI,MAAM,CAAC,IAAI,CAAC,MAAM,CAAC,SAAS,EAAE,CAAC,UAAU,CAAC;QAC9C,IAAI,MAAM,CAAC,IAAI,CAAC,MAAM,CAAC,SAAS,EAAE,CAAC,UAAU,CAAC;QAC9C,IAAI,MAAM,CAAC,IAAI,CAAC,MAAM,CAAC,SAAS,EAAE,CAAC,UAAU,CAAC;QAC9C,IAAI,MAAM,CAAC,IAAI,CAAC,MAAM,CAAC,SAAS,EAAE,CAAC,UAAU,CAAC;QAC9C,IAAI,MAAM,CAAC,IAAI,CAAC,MAAM,CAAC,QAAQ,EAAE,CAAC,SAAS,CAAC;QAC5C,IAAI,MAAM,CAAC,IAAI,CAAC,MAAM,CAAC,SAAS,EAAE,CAAC,UAAU,CAAC;QAC9C,IAAI,MAAM,CAAC,IAAI,CAAC,MAAM,CAAC,SAAS,EAAE,CAAC,UAAU,CAAC;QAC9C,IAAI,MAAM,CAAC,IAAI,CAAC,MAAM,CAAC,SAAS,EAAE,CAAC,UAAU,CAAC;QAC9C,IAAI,MAAM,CAAC,IAAI,CAAC,MAAM,CAAC,SAAS,EAAE,CAAC,UAAU,CAAC;QAC9C,IAAI,MAAM,CAAC,IAAI,CAAC,MAAM,CAAC,SAAS,EAAE,CAAC,UAAU,CAAC;QAC9C,IAAI,MAAM,CAAC,IAAI,CAAC,MAAM,CAAC,SAAS,EAAE,CAAC,UAAU,CAAC;QAC9C,IAAI,MAAM,CAAC,IAAI,CAAC,MAAM,CAAC,SAAS,EAAE,CAAC,UAAU,CAAC;QAC9C,IAAI,MAAM,CAAC,IAAI,CAAC,MAAM,CAAC,SAAS,EAAE,CAAC,UAAU,CAAC;QAC9C,IAAI,MAAM,CAAC,IAAI,CAAC,MAAM,CAAC,SAAS,EAAE,CAAC,SAAS,CAAC;QAC7C,IAAI,MAAM,CAAC,IAAI,CAAC,MAAM,CAAC,SAAS,EAAE,CAAC,UAAU,CAAC;QAC9C,IAAI,MAAM,CAAC,IAAI,CAAC,MAAM,CAAC,SAAS,EAAE,CAAC,UAAU,CAAC;QAC9C,IAAI,MAAM,CAAC,IAAI,CAAC,MAAM,CAAC,SAAS,EAAE,CAAC,UAAU,CAAC;QAC9C,IAAI,MAAM,CAAC,IAAI,CAAC,MAAM,CAAC,SAAS,EAAE,CAAC,UAAU,CAAC;QAC9C,IAAI,MAAM,CAAC,IAAI,CAAC,MAAM,CAAC,SAAS,EAAE,CAAC,UAAU,CAAC;QAC9C,IAAI,MAAM,CAAC,IAAI,CAAC,MAAM,CAAC,SAAS,EAAE,CAAC,UAAU,CAAC;QAC9C,IAAI,MAAM,CAAC,IAAI,CAAC,MAAM,CAAC,OAAO,EAAE,CAAC,SAAS,CAAC;QAC3C,IAAI,MAAM,CAAC,IAAI,CAAC,MAAM,CAAC,QAAQ,EAAE,CAAC,UAAU,CAAC;QAC7C,IAAI,MAAM,CAAC,IAAI,CAAC,MAAM,CAAC,SAAS,EAAE,CAAC,UAAU,CAAC;QAC9C,IAAI,MAAM,CAAC,IAAI,CAAC,MAAM,CAAC,SAAS,EAAE,CAAC,UAAU,CAAC;QAC9C,IAAI,MAAM,CAAC,IAAI,CAAC,MAAM,CAAC,SAAS,EAAE,CAAC,UAAU,CAAC;QAC9C,IAAI,MAAM,CAAC,IAAI,CAAC,MAAM,CAAC,SAAS,EAAE,CAAC,SAAS,CAAC;QAC7C,IAAI,MAAM,CAAC,IAAI,CAAC,MAAM,CAAC,SAAS,EAAE,CAAC,UAAU,CAAC;QAC9C,IAAI,MAAM,CAAC,IAAI,CAAC,MAAM,CAAC,SAAS,EAAE,CAAC,UAAU,CAAC;QAC9C,IAAI,MAAM,CAAC,IAAI,CAAC,MAAM,CAAC,SAAS,EAAE,CAAC,UAAU,CAAC;QAC9C,IAAI,MAAM,CAAC,IAAI,CAAC,MAAM,CAAC,SAAS,EAAE,CAAC,UAAU,CAAC;QAC9C,IAAI,MAAM,CAAC,IAAI,CAAC,MAAM,CAAC,SAAS,EAAE,CAAC,UAAU,CAAC;QAC9C,IAAI,MAAM,CAAC,IAAI,CAAC,MAAM,CAAC,SAAS,EAAE,CAAC,UAAU,CAAC;QAC9C,IAAI,MAAM,CAAC,IAAI,CAAC,MAAM,CAAC,SAAS,EAAE,CAAC,UAAU,CAAC;QAC9C,IAAI,MAAM,CAAC,IAAI,CAAC,MAAM,CAAC,SAAS,EAAE,CAAC,UAAU,CAAC;QAC9C,IAAI,MAAM,CAAC,IAAI,CAAC,MAAM,CAAC,SAAS,EAAE,CAAC,UAAU,CAAC;QAC9C,IAAI,MAAM,CAAC,IAAI,CAAC,MAAM,CAAC,SAAS,EAAE,CAAC,UAAU,CAAC;QAC9C,IAAI,MAAM,CAAC,IAAI,CAAC,MAAM,CAAC,SAAS,EAAE,CAAC,SAAS,CAAC;QAC7C,IAAI,MAAM,CAAC,IAAI,CAAC,MAAM,CAAC,SAAS,EAAE,CAAC,UAAU,CAAC;QAC9C,IAAI,MAAM,CAAC,IAAI,CAAC,MAAM,CAAC,SAAS,EAAE,CAAC,UAAU,CAAC;QAC9C,IAAI,MAAM,CAAC,IAAI,CAAC,MAAM,CAAC,SAAS,EAAE,CAAC,UAAU,CAAC;QAC9C,IAAI,MAAM,CAAC,IAAI,CAAC,MAAM,CAAC,SAAS,EAAE,CAAC,UAAU,CAAC;QAC9C,IAAI,MAAM,CAAC,IAAI,CAAC,MAAM,CAAC,SAAS,EAAE,CAAC,UAAU,CAAC;QAC9C,IAAI,MAAM,CAAC,IAAI,CAAC,MAAM,CAAC,SAAS,EAAE,CAAC,UAAU,CAAC;QAC9C,IAAI,MAAM,CAAC,IAAI,CAAC,MAAM,CAAC,SAAS,EAAE,CAAC,SAAS,CAAC;QAC7C,IAAI,MAAM,CAAC,IAAI,CAAC,MAAM,CAAC,SAAS,EAAE,CAAC,UAAU,CAAC;QAC9C,IAAI,MAAM,CAAC,IAAI,CAAC,MAAM,CAAC,SAAS,EAAE,CAAC,UAAU,CAAC;QAC9C,IAAI,MAAM,CAAC,IAAI,CAAC,MAAM,CAAC,SAAS,EAAE,CAAC,UAAU,CAAC;QAC9C,IAAI,MAAM,CAAC,IAAI,CAAC,MAAM,CAAC,QAAQ,EAAE,CAAC,UAAU,CAAC;QAC7C,IAAI,MAAM,CAAC,IAAI,CAAC,MAAM,CAAC,SAAS,EAAE,CAAC,UAAU,CAAC;QAC9C,IAAI,MAAM,CAAC,IAAI,CAAC,MAAM,CAAC,SAAS,EAAE,CAAC,UAAU,CAAC;QAC9C,IAAI,MAAM,CAAC,IAAI,CAAC,MAAM,CAAC,SAAS,EAAE,CAAC,UAAU,CAAC;QAC9C,IAAI,MAAM,CAAC,IAAI,CAAC,MAAM,CAAC,SAAS,EAAE,CAAC,UAAU,CAAC;QAC9C,IAAI,MAAM,CAAC,IAAI,CAAC,MAAM,CAAC,SAAS,EAAE,CAAC,UAAU,CAAC;QAC9C,IAAI,MAAM,CAAC,IAAI,CAAC,MAAM,CAAC,SAAS,EAAE,CAAC,UAAU,CAAC;QAC9C,IAAI,MAAM,CAAC,IAAI,CAAC,MAAM,CAAC,QAAQ,EAAE,CAAC,UAAU,CAAC;QAC7C,IAAI,MAAM,CAAC,IAAI,CAAC,MAAM,CAAC,SAAS,EAAE,CAAC,UAAU,CAAC;QAC9C,IAAI,MAAM,CAAC,IAAI,CAAC,MAAM,CAAC,SAAS,EAAE,CAAC,UAAU,CAAC;QAC9C,IAAI,MAAM,CAAC,IAAI,CAAC,MAAM,CAAC,SAAS,EAAE,CAAC,UAAU,CAAC;QAC9C,IAAI,MAAM,CAAC,IAAI,CAAC,MAAM,CAAC,QAAQ,EAAE,CAAC,QAAQ,CAAC;QAC3C,IAAI,MAAM,CAAC,IAAI,CAAC,MAAM,CAAC,SAAS,EAAE,CAAC,UAAU,CAAC;QAC9C,IAAI,MAAM,CAAC,IAAI,CAAC,MAAM,CAAC,SAAS,EAAE,CAAC,UAAU,CAAC;QAC9C,IAAI,MAAM,CAAC,IAAI,CAAC,MAAM,CAAC,SAAS,EAAE,CAAC,UAAU,CAAC;QAC9C,IAAI,MAAM,CAAC,IAAI,CAAC,MAAM,CAAC,SAAS,EAAE,CAAC,UAAU,CAAC;QAC9C,IAAI,MAAM,CAAC,IAAI,CAAC,MAAM,CAAC,SAAS,EAAE,CAAC,UAAU,CAAC;QAC9C,IAAI,MAAM,CAAC,IAAI,CAAC,MAAM,CAAC,SAAS,EAAE,CAAC,UAAU,CAAC;QAC9C,IAAI,MAAM,CAAC,IAAI,CAAC,MAAM,CAAC,SAAS,EAAE,CAAC,UAAU,CAAC;QAC9C,IAAI,MAAM,CAAC,IAAI,CAAC,MAAM,CAAC,SAAS,EAAE,CAAC,UAAU,CAAC;QAC9C,IAAI,MAAM,CAAC,IAAI,CAAC,MAAM,CAAC,SAAS,EAAE,CAAC,UAAU,CAAC;QAC9C,IAAI,MAAM,CAAC,IAAI,CAAC,MAAM,CAAC,QAAQ,EAAE,CAAC,UAAU,CAAC;QAC7C,IAAI,MAAM,CAAC,IAAI,CAAC,MAAM,CAAC,SAAS,EAAE,CAAC,UAAU,CAAC;QAC9C,IAAI,MAAM,CAAC,IAAI,CAAC,MAAM,CAAC,SAAS,EAAE,CAAC,UAAU,CAAC;QAC9C,IAAI,MAAM,CAAC,IAAI,CAAC,MAAM,CAAC,SAAS,EAAE,CAAC,UAAU,CAAC;QAC9C,IAAI,MAAM,CAAC,IAAI,CAAC,MAAM,CAAC,SAAS,EAAE,CAAC,UAAU,CAAC;QAC9C,IAAI,MAAM,CAAC,IAAI,CAAC,MAAM,CAAC,SAAS,EAAE,CAAC,UAAU,CAAC;QAC9C,IAAI,MAAM,CAAC,IAAI,CAAC,MAAM,CAAC,SAAS,EAAE,CAAC,UAAU,CAAC;QAC9C,IAAI,MAAM,CAAC,IAAI,CAAC,MAAM,CAAC,QAAQ,EAAE,CAAC,QAAQ,CAAC;QAC3C,IAAI,MAAM,CAAC,IAAI,CAAC,MAAM,CAAC,SAAS,EAAE,CAAC,UAAU,CAAC;QAC9C,IAAI,MAAM,CAAC,IAAI,CAAC,MAAM,CAAC,SAAS,EAAE,CAAC,SAAS,CAAC;QAC7C,IAAI,MAAM,CAAC,IAAI,CAAC,MAAM,CAAC,SAAS,EAAE,CAAC,UAAU,CAAC;QAC9C,IAAI,MAAM,CAAC,IAAI,CAAC,MAAM,CAAC,SAAS,EAAE,CAAC,UAAU,CAAC;QAC9C,IAAI,MAAM,CAAC,IAAI,CAAC,MAAM,CAAC,SAAS,EAAE,CAAC,UAAU,CAAC;QAC9C,IAAI,MAAM,CAAC,IAAI,CAAC,MAAM,CAAC,SAAS,EAAE,CAAC,UAAU,CAAC;QAC9C,IAAI,MAAM,CAAC,IAAI,CAAC,MAAM,CAAC,SAAS,EAAE,CAAC,UAAU,CAAC;QAC9C,IAAI,MAAM,CAAC,IAAI,CAAC,MAAM,CAAC,SAAS,EAAE,CAAC,SAAS,CAAC;QAC7C,IAAI,MAAM,CAAC,IAAI,CAAC,MAAM,CAAC,SAAS,EAAE,CAAC,SAAS,CAAC;QAC7C,IAAI,MAAM,CAAC,IAAI,CAAC,MAAM,CAAC,SAAS,EAAE,CAAC,SAAS,CAAC;QAC7C,IAAI,MAAM,CAAC,IAAI,CAAC,MAAM,CAAC,SAAS,EAAE,CAAC,UAAU,CAAC;QAC9C,IAAI,MAAM,CAAC,IAAI,CAAC,MAAM,CAAC,SAAS,EAAE,CAAC,UAAU,CAAC;QAC9C,IAAI,MAAM,CAAC,IAAI,CAAC,MAAM,CAAC,SAAS,EAAE,CAAC,UAAU,CAAC;QAC9C,IAAI,MAAM,CAAC,IAAI,CAAC,MAAM,CAAC,SAAS,EAAE,CAAC,UAAU,CAAC;QAC9C,IAAI,MAAM,CAAC,IAAI,CAAC,MAAM,CAAC,SAAS,EAAE,CAAC,UAAU,CAAC;QAC9C,IAAI,MAAM,CAAC,IAAI,CAAC,MAAM,CAAC,SAAS,EAAE,CAAC,UAAU,CAAC;QAC9C,IAAI,MAAM,CAAC,IAAI,CAAC,MAAM,CAAC,SAAS,EAAE,CAAC,UAAU,CAAC;QAC9C,IAAI,MAAM,CAAC,IAAI,CAAC,MAAM,CAAC,SAAS,EAAE,CAAC,UAAU,CAAC;QAC9C,IAAI,MAAM,CAAC,IAAI,CAAC,MAAM,CAAC,SAAS,EAAE,CAAC,UAAU,CAAC;QAC9C,IAAI,MAAM,CAAC,IAAI,CAAC,MAAM,CAAC,SAAS,EAAE,CAAC,UAAU,CAAC;QAC9C,IAAI,MAAM,CAAC,IAAI,CAAC,MAAM,CAAC,SAAS,EAAE,CAAC,SAAS,CAAC;QAC7C,IAAI,MAAM,CAAC,IAAI,CAAC,MAAM,CAAC,SAAS,EAAE,CAAC,UAAU,CAAC;QAC9C,IAAI,MAAM,CAAC,IAAI,CAAC,MAAM,CAAC,SAAS,EAAE,CAAC,UAAU,CAAC;QAC9C,IAAI,MAAM,CAAC,IAAI,CAAC,MAAM,CAAC,SAAS,EAAE,CAAC,UAAU,CAAC;QAC9C,IAAI,MAAM,CAAC,IAAI,CAAC,MAAM,CAAC,SAAS,EAAE,CAAC,UAAU,CAAC;QAC9C,IAAI,MAAM,CAAC,IAAI,CAAC,MAAM,CAAC,SAAS,EAAE,CAAC,UAAU,CAAC;QAC9C,IAAI,MAAM,CAAC,IAAI,CAAC,MAAM,CAAC,SAAS,EAAE,CAAC,UAAU,CAAC;QAC9C,IAAI,MAAM,CAAC,IAAI,CAAC,MAAM,CAAC,SAAS,EAAE,CAAC,UAAU,CAAC;QAC9C,IAAI,MAAM,CAAC,IAAI,CAAC,MAAM,CAAC,SAAS,EAAE,CAAC,UAAU,CAAC;QAC9C,IAAI,MAAM,CAAC,IAAI,CAAC,MAAM,CAAC,SAAS,EAAE,CAAC,UAAU,CAAC;QAC9C,IAAI,MAAM,CAAC,IAAI,CAAC,MAAM,CAAC,SAAS,EAAE,CAAC,UAAU,CAAC;QAC9C,IAAI,MAAM,CAAC,IAAI,CAAC,MAAM,CAAC,SAAS,EAAE,CAAC,UAAU,CAAC;QAC9C,IAAI,MAAM,CAAC,IAAI,CAAC,MAAM,CAAC,SAAS,EAAE,CAAC,UAAU,CAAC;QAC9C,IAAI,MAAM,CAAC,IAAI,CAAC,MAAM,CAAC,QAAQ,EAAE,CAAC,UAAU,CAAC;QAC7C,IAAI,MAAM,CAAC,IAAI,CAAC,MAAM,CAAC,SAAS,EAAE,CAAC,UAAU,CAAC;QAC9C,IAAI,MAAM,CAAC,IAAI,CAAC,MAAM,CAAC,SAAS,EAAE,CAAC,UAAU,CAAC;QAC9C,IAAI,MAAM,CAAC,IAAI,CAAC,MAAM,CAAC,SAAS,EAAE,CAAC,UAAU,CAAC;QAC9C,IAAI,MAAM,CAAC,IAAI,CAAC,MAAM,CAAC,SAAS,EAAE,CAAC,UAAU,CAAC;QAC9C,IAAI,MAAM,CAAC,IAAI,CAAC,MAAM,CAAC,SAAS,EAAE,CAAC,UAAU,CAAC;QAC9C,IAAI,MAAM,CAAC,IAAI,CAAC,MAAM,CAAC,SAAS,EAAE,CAAC,UAAU,CAAC;QAC9C,IAAI,MAAM,CAAC,IAAI,CAAC,MAAM,CAAC,SAAS,EAAE,CAAC,UAAU,CAAC;QAC9C,IAAI,MAAM,CAAC,IAAI,CAAC,MAAM,CAAC,SAAS,EAAE,CAAC,UAAU,CAAC;QAC9C,IAAI,MAAM,CAAC,IAAI,CAAC,MAAM,CAAC,SAAS,EAAE,CAAC,UAAU,CAAC;QAC9C,IAAI,MAAM,CAAC,IAAI,CAAC,MAAM,CAAC,SAAS,EAAE,CAAC,UAAU,CAAC;QAC9C,IAAI,MAAM,CAAC,IAAI,CAAC,MAAM,CAAC,QAAQ,EAAE,CAAC,UAAU,CAAC;QAC7C,IAAI,MAAM,CAAC,IAAI,CAAC,MAAM,CAAC,SAAS,EAAE,CAAC,UAAU,CAAC;QAC9C,IAAI,MAAM,CAAC,IAAI,CAAC,MAAM,CAAC,SAAS,EAAE,CAAC,UAAU,CAAC;QAC9C,IAAI,MAAM,CAAC,IAAI,CAAC,MAAM,CAAC,SAAS,EAAE,CAAC,UAAU,CAAC;QAC9C,IAAI,MAAM,CAAC,IAAI,CAAC,MAAM,CAAC,SAAS,EAAE,CAAC,UAAU,CAAC;QAC9C,IAAI,MAAM,CAAC,IAAI,CAAC,MAAM,CAAC,SAAS,EAAE,CAAC,UAAU,CAAC;QAC9C,IAAI,MAAM,CAAC,IAAI,CAAC,MAAM,CAAC,SAAS,EAAE,CAAC,UAAU,CAAC;QAC9C,IAAI,MAAM,CAAC,IAAI,CAAC,MAAM,CAAC,SAAS,EAAE,CAAC,UAAU,CAAC;QAC9C,IAAI,MAAM,CAAC,IAAI,CAAC,MAAM,CAAC,SAAS,EAAE,CAAC,UAAU,CAAC;QAC9C,IAAI,MAAM,CAAC,IAAI,CAAC,MAAM,CAAC,SAAS,EAAE,CAAC,SAAS,CAAC;QAC7C,IAAI,MAAM,CAAC,IAAI,CAAC,MAAM,CAAC,SAAS,EAAE,CAAC,UAAU,CAAC;QAC9C,IAAI,MAA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"}
\ No newline at end of file
diff --git a/Birdmap.API/ClientApp/src/components/heatmap/heatmap.ts b/Birdmap.API/ClientApp/src/components/heatmap/heatmap.ts
new file mode 100644
index 0000000..183f6da
--- /dev/null
+++ b/Birdmap.API/ClientApp/src/components/heatmap/heatmap.ts
@@ -0,0 +1,561 @@
+import { Loader, LoaderOptions } from 'google-maps';
+
+let map: google.maps.Map, heatmap: google.maps.visualization.HeatmapLayer;
+
+function initMap(): void {
+ const options: LoaderOptions = {/* todo */ };
+ const loader = new Loader('AIzaSyCZ51VFfxqZ2GkCmVrcNZdUKsM0fuBQUCY', options);
+
+ loader.load().then(function (google) {
+ map = new google.maps.Map(document.getElementById("map") as HTMLElement, {
+ zoom: 13,
+ center: { lat: 37.775, lng: -122.434 },
+ mapTypeId: "satellite",
+ });
+
+ heatmap = new google.maps.visualization.HeatmapLayer({
+ data: getPoints(),
+ map: map,
+ });
+ });
+}
+
+function toggleHeatmap() {
+ heatmap.setMap(heatmap.getMap() ? null : map);
+}
+
+function changeGradient() {
+ const gradient = [
+ "rgba(0, 255, 255, 0)",
+ "rgba(0, 255, 255, 1)",
+ "rgba(0, 191, 255, 1)",
+ "rgba(0, 127, 255, 1)",
+ "rgba(0, 63, 255, 1)",
+ "rgba(0, 0, 255, 1)",
+ "rgba(0, 0, 223, 1)",
+ "rgba(0, 0, 191, 1)",
+ "rgba(0, 0, 159, 1)",
+ "rgba(0, 0, 127, 1)",
+ "rgba(63, 0, 91, 1)",
+ "rgba(127, 0, 63, 1)",
+ "rgba(191, 0, 31, 1)",
+ "rgba(255, 0, 0, 1)",
+ ];
+ heatmap.set("gradient", heatmap.get("gradient") ? null : gradient);
+}
+
+function changeRadius() {
+ heatmap.set("radius", heatmap.get("radius") ? null : 20);
+}
+
+function changeOpacity() {
+ heatmap.set("opacity", heatmap.get("opacity") ? null : 0.2);
+}
+
+// Heatmap data: 500 Points
+function getPoints() {
+ return [
+ new google.maps.LatLng(37.782551, -122.445368),
+ new google.maps.LatLng(37.782745, -122.444586),
+ new google.maps.LatLng(37.782842, -122.443688),
+ new google.maps.LatLng(37.782919, -122.442815),
+ new google.maps.LatLng(37.782992, -122.442112),
+ new google.maps.LatLng(37.7831, -122.441461),
+ new google.maps.LatLng(37.783206, -122.440829),
+ new google.maps.LatLng(37.783273, -122.440324),
+ new google.maps.LatLng(37.783316, -122.440023),
+ new google.maps.LatLng(37.783357, -122.439794),
+ new google.maps.LatLng(37.783371, -122.439687),
+ new google.maps.LatLng(37.783368, -122.439666),
+ new google.maps.LatLng(37.783383, -122.439594),
+ new google.maps.LatLng(37.783508, -122.439525),
+ new google.maps.LatLng(37.783842, -122.439591),
+ new google.maps.LatLng(37.784147, -122.439668),
+ new google.maps.LatLng(37.784206, -122.439686),
+ new google.maps.LatLng(37.784386, -122.43979),
+ new google.maps.LatLng(37.784701, -122.439902),
+ new google.maps.LatLng(37.784965, -122.439938),
+ new google.maps.LatLng(37.78501, -122.439947),
+ new google.maps.LatLng(37.78536, -122.439952),
+ new google.maps.LatLng(37.785715, -122.44003),
+ new google.maps.LatLng(37.786117, -122.440119),
+ new google.maps.LatLng(37.786564, -122.440209),
+ new google.maps.LatLng(37.786905, -122.44027),
+ new google.maps.LatLng(37.786956, -122.440279),
+ new google.maps.LatLng(37.800224, -122.43352),
+ new google.maps.LatLng(37.800155, -122.434101),
+ new google.maps.LatLng(37.80016, -122.43443),
+ new google.maps.LatLng(37.800378, -122.434527),
+ new google.maps.LatLng(37.800738, -122.434598),
+ new google.maps.LatLng(37.800938, -122.43465),
+ new google.maps.LatLng(37.801024, -122.434889),
+ new google.maps.LatLng(37.800955, -122.435392),
+ new google.maps.LatLng(37.800886, -122.435959),
+ new google.maps.LatLng(37.800811, -122.436275),
+ new google.maps.LatLng(37.800788, -122.436299),
+ new google.maps.LatLng(37.800719, -122.436302),
+ new google.maps.LatLng(37.800702, -122.436298),
+ new google.maps.LatLng(37.800661, -122.436273),
+ new google.maps.LatLng(37.800395, -122.436172),
+ new google.maps.LatLng(37.800228, -122.436116),
+ new google.maps.LatLng(37.800169, -122.43613),
+ new google.maps.LatLng(37.800066, -122.436167),
+ new google.maps.LatLng(37.784345, -122.422922),
+ new google.maps.LatLng(37.784389, -122.422926),
+ new google.maps.LatLng(37.784437, -122.422924),
+ new google.maps.LatLng(37.784746, -122.422818),
+ new google.maps.LatLng(37.785436, -122.422959),
+ new google.maps.LatLng(37.78612, -122.423112),
+ new google.maps.LatLng(37.786433, -122.423029),
+ new google.maps.LatLng(37.786631, -122.421213),
+ new google.maps.LatLng(37.78666, -122.421033),
+ new google.maps.LatLng(37.786801, -122.420141),
+ new google.maps.LatLng(37.786823, -122.420034),
+ new google.maps.LatLng(37.786831, -122.419916),
+ new google.maps.LatLng(37.787034, -122.418208),
+ new google.maps.LatLng(37.787056, -122.418034),
+ new google.maps.LatLng(37.787169, -122.417145),
+ new google.maps.LatLng(37.787217, -122.416715),
+ new google.maps.LatLng(37.786144, -122.416403),
+ new google.maps.LatLng(37.785292, -122.416257),
+ new google.maps.LatLng(37.780666, -122.390374),
+ new google.maps.LatLng(37.780501, -122.391281),
+ new google.maps.LatLng(37.780148, -122.392052),
+ new google.maps.LatLng(37.780173, -122.391148),
+ new google.maps.LatLng(37.780693, -122.390592),
+ new google.maps.LatLng(37.781261, -122.391142),
+ new google.maps.LatLng(37.781808, -122.39173),
+ new google.maps.LatLng(37.78234, -122.392341),
+ new google.maps.LatLng(37.782812, -122.393022),
+ new google.maps.LatLng(37.7833, -122.393672),
+ new google.maps.LatLng(37.783809, -122.394275),
+ new google.maps.LatLng(37.784246, -122.394979),
+ new google.maps.LatLng(37.784791, -122.395958),
+ new google.maps.LatLng(37.785675, -122.396746),
+ new google.maps.LatLng(37.786262, -122.39578),
+ new google.maps.LatLng(37.786776, -122.395093),
+ new google.maps.LatLng(37.787282, -122.394426),
+ new google.maps.LatLng(37.787783, -122.393767),
+ new google.maps.LatLng(37.788343, -122.393184),
+ new google.maps.LatLng(37.788895, -122.392506),
+ new google.maps.LatLng(37.789371, -122.391701),
+ new google.maps.LatLng(37.789722, -122.390952),
+ new google.maps.LatLng(37.790315, -122.390305),
+ new google.maps.LatLng(37.790738, -122.389616),
+ new google.maps.LatLng(37.779448, -122.438702),
+ new google.maps.LatLng(37.779023, -122.438585),
+ new google.maps.LatLng(37.778542, -122.438492),
+ new google.maps.LatLng(37.7781, -122.438411),
+ new google.maps.LatLng(37.777986, -122.438376),
+ new google.maps.LatLng(37.77768, -122.438313),
+ new google.maps.LatLng(37.777316, -122.438273),
+ new google.maps.LatLng(37.777135, -122.438254),
+ new google.maps.LatLng(37.776987, -122.438303),
+ new google.maps.LatLng(37.776946, -122.438404),
+ new google.maps.LatLng(37.776944, -122.438467),
+ new google.maps.LatLng(37.776892, -122.438459),
+ new google.maps.LatLng(37.776842, -122.438442),
+ new google.maps.LatLng(37.776822, -122.438391),
+ new google.maps.LatLng(37.776814, -122.438412),
+ new google.maps.LatLng(37.776787, -122.438628),
+ new google.maps.LatLng(37.776729, -122.43865),
+ new google.maps.LatLng(37.776759, -122.438677),
+ new google.maps.LatLng(37.776772, -122.438498),
+ new google.maps.LatLng(37.776787, -122.438389),
+ new google.maps.LatLng(37.776848, -122.438283),
+ new google.maps.LatLng(37.77687, -122.438239),
+ new google.maps.LatLng(37.777015, -122.438198),
+ new google.maps.LatLng(37.777333, -122.438256),
+ new google.maps.LatLng(37.777595, -122.438308),
+ new google.maps.LatLng(37.777797, -122.438344),
+ new google.maps.LatLng(37.77816, -122.438442),
+ new google.maps.LatLng(37.778414, -122.438508),
+ new google.maps.LatLng(37.778445, -122.438516),
+ new google.maps.LatLng(37.778503, -122.438529),
+ new google.maps.LatLng(37.778607, -122.438549),
+ new google.maps.LatLng(37.77867, -122.438644),
+ new google.maps.LatLng(37.778847, -122.438706),
+ new google.maps.LatLng(37.77924, -122.438744),
+ new google.maps.LatLng(37.779738, -122.438822),
+ new google.maps.LatLng(37.780201, -122.438882),
+ new google.maps.LatLng(37.7804, -122.438905),
+ new google.maps.LatLng(37.780501, -122.438921),
+ new google.maps.LatLng(37.780892, -122.438986),
+ new google.maps.LatLng(37.781446, -122.439087),
+ new google.maps.LatLng(37.781985, -122.439199),
+ new google.maps.LatLng(37.782239, -122.439249),
+ new google.maps.LatLng(37.782286, -122.439266),
+ new google.maps.LatLng(37.797847, -122.429388),
+ new google.maps.LatLng(37.797874, -122.42918),
+ new google.maps.LatLng(37.797885, -122.429069),
+ new google.maps.LatLng(37.797887, -122.42905),
+ new google.maps.LatLng(37.797933, -122.428954),
+ new google.maps.LatLng(37.798242, -122.42899),
+ new google.maps.LatLng(37.798617, -122.429075),
+ new google.maps.LatLng(37.798719, -122.429092),
+ new google.maps.LatLng(37.798944, -122.429145),
+ new google.maps.LatLng(37.79932, -122.429251),
+ new google.maps.LatLng(37.79959, -122.429309),
+ new google.maps.LatLng(37.799677, -122.429324),
+ new google.maps.LatLng(37.799966, -122.42936),
+ new google.maps.LatLng(37.800288, -122.42943),
+ new google.maps.LatLng(37.800443, -122.429461),
+ new google.maps.LatLng(37.800465, -122.429474),
+ new google.maps.LatLng(37.800644, -122.42954),
+ new google.maps.LatLng(37.800948, -122.42962),
+ new google.maps.LatLng(37.801242, -122.429685),
+ new google.maps.LatLng(37.801375, -122.429702),
+ new google.maps.LatLng(37.8014, -122.429703),
+ new google.maps.LatLng(37.801453, -122.429707),
+ new google.maps.LatLng(37.801473, -122.429709),
+ new google.maps.LatLng(37.801532, -122.429707),
+ new google.maps.LatLng(37.801852, -122.429729),
+ new google.maps.LatLng(37.802173, -122.429789),
+ new google.maps.LatLng(37.802459, -122.429847),
+ new google.maps.LatLng(37.802554, -122.429825),
+ new google.maps.LatLng(37.802647, -122.429549),
+ new google.maps.LatLng(37.802693, -122.429179),
+ new google.maps.LatLng(37.802729, -122.428751),
+ new google.maps.LatLng(37.766104, -122.409291),
+ new google.maps.LatLng(37.766103, -122.409268),
+ new google.maps.LatLng(37.766138, -122.409229),
+ new google.maps.LatLng(37.766183, -122.409231),
+ new google.maps.LatLng(37.766153, -122.409276),
+ new google.maps.LatLng(37.766005, -122.409365),
+ new google.maps.LatLng(37.765897, -122.40957),
+ new google.maps.LatLng(37.765767, -122.409739),
+ new google.maps.LatLng(37.765693, -122.410389),
+ new google.maps.LatLng(37.765615, -122.411201),
+ new google.maps.LatLng(37.765533, -122.412121),
+ new google.maps.LatLng(37.765467, -122.412939),
+ new google.maps.LatLng(37.765444, -122.414821),
+ new google.maps.LatLng(37.765444, -122.414964),
+ new google.maps.LatLng(37.765318, -122.415424),
+ new google.maps.LatLng(37.763961, -122.415296),
+ new google.maps.LatLng(37.763115, -122.415196),
+ new google.maps.LatLng(37.762967, -122.415183),
+ new google.maps.LatLng(37.762278, -122.415127),
+ new google.maps.LatLng(37.761675, -122.415055),
+ new google.maps.LatLng(37.760932, -122.414988),
+ new google.maps.LatLng(37.759337, -122.414862),
+ new google.maps.LatLng(37.773187, -122.421922),
+ new google.maps.LatLng(37.773043, -122.422118),
+ new google.maps.LatLng(37.773007, -122.422165),
+ new google.maps.LatLng(37.772979, -122.422219),
+ new google.maps.LatLng(37.772865, -122.422394),
+ new google.maps.LatLng(37.772779, -122.422503),
+ new google.maps.LatLng(37.772676, -122.422701),
+ new google.maps.LatLng(37.772606, -122.422806),
+ new google.maps.LatLng(37.772566, -122.42284),
+ new google.maps.LatLng(37.772508, -122.422852),
+ new google.maps.LatLng(37.772387, -122.423011),
+ new google.maps.LatLng(37.772099, -122.423328),
+ new google.maps.LatLng(37.771704, -122.423783),
+ new google.maps.LatLng(37.771481, -122.424081),
+ new google.maps.LatLng(37.7714, -122.424179),
+ new google.maps.LatLng(37.771352, -122.42422),
+ new google.maps.LatLng(37.771248, -122.424327),
+ new google.maps.LatLng(37.770904, -122.424781),
+ new google.maps.LatLng(37.77052, -122.425283),
+ new google.maps.LatLng(37.770337, -122.425553),
+ new google.maps.LatLng(37.770128, -122.425832),
+ new google.maps.LatLng(37.769756, -122.426331),
+ new google.maps.LatLng(37.7693, -122.426902),
+ new google.maps.LatLng(37.769132, -122.427065),
+ new google.maps.LatLng(37.769092, -122.427103),
+ new google.maps.LatLng(37.768979, -122.427172),
+ new google.maps.LatLng(37.768595, -122.427634),
+ new google.maps.LatLng(37.768372, -122.427913),
+ new google.maps.LatLng(37.768337, -122.427961),
+ new google.maps.LatLng(37.768244, -122.428138),
+ new google.maps.LatLng(37.767942, -122.428581),
+ new google.maps.LatLng(37.767482, -122.429094),
+ new google.maps.LatLng(37.767031, -122.429606),
+ new google.maps.LatLng(37.766732, -122.429986),
+ new google.maps.LatLng(37.76668, -122.430058),
+ new google.maps.LatLng(37.766633, -122.430109),
+ new google.maps.LatLng(37.76658, -122.430211),
+ new google.maps.LatLng(37.766367, -122.430594),
+ new google.maps.LatLng(37.76591, -122.431137),
+ new google.maps.LatLng(37.765353, -122.431806),
+ new google.maps.LatLng(37.764962, -122.432298),
+ new google.maps.LatLng(37.764868, -122.432486),
+ new google.maps.LatLng(37.764518, -122.432913),
+ new google.maps.LatLng(37.763435, -122.434173),
+ new google.maps.LatLng(37.762847, -122.434953),
+ new google.maps.LatLng(37.762291, -122.435935),
+ new google.maps.LatLng(37.762224, -122.436074),
+ new google.maps.LatLng(37.761957, -122.436892),
+ new google.maps.LatLng(37.761652, -122.438886),
+ new google.maps.LatLng(37.761284, -122.439955),
+ new google.maps.LatLng(37.76121, -122.440068),
+ new google.maps.LatLng(37.761064, -122.44072),
+ new google.maps.LatLng(37.76104, -122.441411),
+ new google.maps.LatLng(37.761048, -122.442324),
+ new google.maps.LatLng(37.760851, -122.443118),
+ new google.maps.LatLng(37.759977, -122.444591),
+ new google.maps.LatLng(37.759913, -122.444698),
+ new google.maps.LatLng(37.759623, -122.445065),
+ new google.maps.LatLng(37.758902, -122.445158),
+ new google.maps.LatLng(37.758428, -122.44457),
+ new google.maps.LatLng(37.757687, -122.44334),
+ new google.maps.LatLng(37.757583, -122.44324),
+ new google.maps.LatLng(37.757019, -122.442787),
+ new google.maps.LatLng(37.756603, -122.442322),
+ new google.maps.LatLng(37.75638, -122.441602),
+ new google.maps.LatLng(37.75579, -122.441382),
+ new google.maps.LatLng(37.754493, -122.442133),
+ new google.maps.LatLng(37.754361, -122.442206),
+ new google.maps.LatLng(37.753719, -122.44265),
+ new google.maps.LatLng(37.753096, -122.442915),
+ new google.maps.LatLng(37.751617, -122.443211),
+ new google.maps.LatLng(37.751496, -122.443246),
+ new google.maps.LatLng(37.750733, -122.443428),
+ new google.maps.LatLng(37.750126, -122.443536),
+ new google.maps.LatLng(37.750103, -122.443784),
+ new google.maps.LatLng(37.75039, -122.44401),
+ new google.maps.LatLng(37.750448, -122.444013),
+ new google.maps.LatLng(37.750536, -122.44404),
+ new google.maps.LatLng(37.750493, -122.444141),
+ new google.maps.LatLng(37.790859, -122.402808),
+ new google.maps.LatLng(37.790864, -122.402768),
+ new google.maps.LatLng(37.790995, -122.402539),
+ new google.maps.LatLng(37.791148, -122.402172),
+ new google.maps.LatLng(37.791385, -122.401312),
+ new google.maps.LatLng(37.791405, -122.400776),
+ new google.maps.LatLng(37.791288, -122.400528),
+ new google.maps.LatLng(37.791113, -122.400441),
+ new google.maps.LatLng(37.791027, -122.400395),
+ new google.maps.LatLng(37.791094, -122.400311),
+ new google.maps.LatLng(37.791211, -122.400183),
+ new google.maps.LatLng(37.79106, -122.399334),
+ new google.maps.LatLng(37.790538, -122.398718),
+ new google.maps.LatLng(37.790095, -122.398086),
+ new google.maps.LatLng(37.789644, -122.39736),
+ new google.maps.LatLng(37.789254, -122.396844),
+ new google.maps.LatLng(37.788855, -122.396397),
+ new google.maps.LatLng(37.788483, -122.395963),
+ new google.maps.LatLng(37.788015, -122.395365),
+ new google.maps.LatLng(37.787558, -122.394735),
+ new google.maps.LatLng(37.787472, -122.394323),
+ new google.maps.LatLng(37.78763, -122.394025),
+ new google.maps.LatLng(37.787767, -122.393987),
+ new google.maps.LatLng(37.787486, -122.394452),
+ new google.maps.LatLng(37.786977, -122.395043),
+ new google.maps.LatLng(37.786583, -122.395552),
+ new google.maps.LatLng(37.78654, -122.39561),
+ new google.maps.LatLng(37.786516, -122.395659),
+ new google.maps.LatLng(37.786378, -122.395707),
+ new google.maps.LatLng(37.786044, -122.395362),
+ new google.maps.LatLng(37.785598, -122.394715),
+ new google.maps.LatLng(37.785321, -122.394361),
+ new google.maps.LatLng(37.785207, -122.394236),
+ new google.maps.LatLng(37.785751, -122.394062),
+ new google.maps.LatLng(37.785996, -122.393881),
+ new google.maps.LatLng(37.786092, -122.39383),
+ new google.maps.LatLng(37.785998, -122.393899),
+ new google.maps.LatLng(37.785114, -122.394365),
+ new google.maps.LatLng(37.785022, -122.394441),
+ new google.maps.LatLng(37.784823, -122.394635),
+ new google.maps.LatLng(37.784719, -122.394629),
+ new google.maps.LatLng(37.785069, -122.394176),
+ new google.maps.LatLng(37.7855, -122.39365),
+ new google.maps.LatLng(37.78577, -122.393291),
+ new google.maps.LatLng(37.785839, -122.393159),
+ new google.maps.LatLng(37.782651, -122.400628),
+ new google.maps.LatLng(37.782616, -122.400599),
+ new google.maps.LatLng(37.782702, -122.40047),
+ new google.maps.LatLng(37.782915, -122.400192),
+ new google.maps.LatLng(37.783137, -122.399887),
+ new google.maps.LatLng(37.783414, -122.399519),
+ new google.maps.LatLng(37.783629, -122.399237),
+ new google.maps.LatLng(37.783688, -122.399157),
+ new google.maps.LatLng(37.783716, -122.399106),
+ new google.maps.LatLng(37.783798, -122.399072),
+ new google.maps.LatLng(37.783997, -122.399186),
+ new google.maps.LatLng(37.784271, -122.399538),
+ new google.maps.LatLng(37.784577, -122.399948),
+ new google.maps.LatLng(37.784828, -122.40026),
+ new google.maps.LatLng(37.784999, -122.400477),
+ new google.maps.LatLng(37.785113, -122.400651),
+ new google.maps.LatLng(37.785155, -122.400703),
+ new google.maps.LatLng(37.785192, -122.400749),
+ new google.maps.LatLng(37.785278, -122.400839),
+ new google.maps.LatLng(37.785387, -122.400857),
+ new google.maps.LatLng(37.785478, -122.40089),
+ new google.maps.LatLng(37.785526, -122.401022),
+ new google.maps.LatLng(37.785598, -122.401148),
+ new google.maps.LatLng(37.785631, -122.401202),
+ new google.maps.LatLng(37.78566, -122.401267),
+ new google.maps.LatLng(37.803986, -122.426035),
+ new google.maps.LatLng(37.804102, -122.425089),
+ new google.maps.LatLng(37.804211, -122.424156),
+ new google.maps.LatLng(37.803861, -122.423385),
+ new google.maps.LatLng(37.803151, -122.423214),
+ new google.maps.LatLng(37.802439, -122.423077),
+ new google.maps.LatLng(37.80174, -122.422905),
+ new google.maps.LatLng(37.801069, -122.422785),
+ new google.maps.LatLng(37.800345, -122.422649),
+ new google.maps.LatLng(37.799633, -122.422603),
+ new google.maps.LatLng(37.79975, -122.4217),
+ new google.maps.LatLng(37.799885, -122.420854),
+ new google.maps.LatLng(37.799209, -122.420607),
+ new google.maps.LatLng(37.795656, -122.400395),
+ new google.maps.LatLng(37.795203, -122.400304),
+ new google.maps.LatLng(37.778738, -122.415584),
+ new google.maps.LatLng(37.778812, -122.415189),
+ new google.maps.LatLng(37.778824, -122.415092),
+ new google.maps.LatLng(37.778833, -122.414932),
+ new google.maps.LatLng(37.778834, -122.414898),
+ new google.maps.LatLng(37.77874, -122.414757),
+ new google.maps.LatLng(37.778501, -122.414433),
+ new google.maps.LatLng(37.778182, -122.414026),
+ new google.maps.LatLng(37.777851, -122.413623),
+ new google.maps.LatLng(37.777486, -122.413166),
+ new google.maps.LatLng(37.777109, -122.412674),
+ new google.maps.LatLng(37.776743, -122.412186),
+ new google.maps.LatLng(37.77644, -122.4118),
+ new google.maps.LatLng(37.776295, -122.411614),
+ new google.maps.LatLng(37.776158, -122.41144),
+ new google.maps.LatLng(37.775806, -122.410997),
+ new google.maps.LatLng(37.775422, -122.410484),
+ new google.maps.LatLng(37.775126, -122.410087),
+ new google.maps.LatLng(37.775012, -122.409854),
+ new google.maps.LatLng(37.775164, -122.409573),
+ new google.maps.LatLng(37.775498, -122.40918),
+ new google.maps.LatLng(37.775868, -122.40873),
+ new google.maps.LatLng(37.776256, -122.40824),
+ new google.maps.LatLng(37.776519, -122.407928),
+ new google.maps.LatLng(37.776539, -122.407904),
+ new google.maps.LatLng(37.776595, -122.407854),
+ new google.maps.LatLng(37.776853, -122.407547),
+ new google.maps.LatLng(37.777234, -122.407087),
+ new google.maps.LatLng(37.777644, -122.406558),
+ new google.maps.LatLng(37.778066, -122.406017),
+ new google.maps.LatLng(37.778468, -122.405499),
+ new google.maps.LatLng(37.778866, -122.404995),
+ new google.maps.LatLng(37.779295, -122.404455),
+ new google.maps.LatLng(37.779695, -122.40395),
+ new google.maps.LatLng(37.779982, -122.403584),
+ new google.maps.LatLng(37.780295, -122.403223),
+ new google.maps.LatLng(37.780664, -122.402766),
+ new google.maps.LatLng(37.781043, -122.402288),
+ new google.maps.LatLng(37.781399, -122.401823),
+ new google.maps.LatLng(37.781727, -122.401407),
+ new google.maps.LatLng(37.781853, -122.401247),
+ new google.maps.LatLng(37.781894, -122.401195),
+ new google.maps.LatLng(37.782076, -122.400977),
+ new google.maps.LatLng(37.782338, -122.400603),
+ new google.maps.LatLng(37.782666, -122.400133),
+ new google.maps.LatLng(37.783048, -122.399634),
+ new google.maps.LatLng(37.78345, -122.399198),
+ new google.maps.LatLng(37.783791, -122.398998),
+ new google.maps.LatLng(37.784177, -122.398959),
+ new google.maps.LatLng(37.784388, -122.398971),
+ new google.maps.LatLng(37.784404, -122.399128),
+ new google.maps.LatLng(37.784586, -122.399524),
+ new google.maps.LatLng(37.784835, -122.399927),
+ new google.maps.LatLng(37.785116, -122.400307),
+ new google.maps.LatLng(37.785282, -122.400539),
+ new google.maps.LatLng(37.785346, -122.400692),
+ new google.maps.LatLng(37.765769, -122.407201),
+ new google.maps.LatLng(37.76579, -122.407414),
+ new google.maps.LatLng(37.765802, -122.407755),
+ new google.maps.LatLng(37.765791, -122.408219),
+ new google.maps.LatLng(37.765763, -122.408759),
+ new google.maps.LatLng(37.765726, -122.409348),
+ new google.maps.LatLng(37.765716, -122.409882),
+ new google.maps.LatLng(37.765708, -122.410202),
+ new google.maps.LatLng(37.765705, -122.410253),
+ new google.maps.LatLng(37.765707, -122.410369),
+ new google.maps.LatLng(37.765692, -122.41072),
+ new google.maps.LatLng(37.765699, -122.411215),
+ new google.maps.LatLng(37.765687, -122.411789),
+ new google.maps.LatLng(37.765666, -122.412373),
+ new google.maps.LatLng(37.765598, -122.412883),
+ new google.maps.LatLng(37.765543, -122.413039),
+ new google.maps.LatLng(37.765532, -122.413125),
+ new google.maps.LatLng(37.7655, -122.413553),
+ new google.maps.LatLng(37.765448, -122.414053),
+ new google.maps.LatLng(37.765388, -122.414645),
+ new google.maps.LatLng(37.765323, -122.41525),
+ new google.maps.LatLng(37.765303, -122.415847),
+ new google.maps.LatLng(37.765251, -122.416439),
+ new google.maps.LatLng(37.765204, -122.41702),
+ new google.maps.LatLng(37.765172, -122.417556),
+ new google.maps.LatLng(37.765164, -122.418075),
+ new google.maps.LatLng(37.765153, -122.418618),
+ new google.maps.LatLng(37.765136, -122.419112),
+ new google.maps.LatLng(37.765129, -122.419378),
+ new google.maps.LatLng(37.765119, -122.419481),
+ new google.maps.LatLng(37.7651, -122.419852),
+ new google.maps.LatLng(37.765083, -122.420349),
+ new google.maps.LatLng(37.765045, -122.42093),
+ new google.maps.LatLng(37.764992, -122.421481),
+ new google.maps.LatLng(37.76498, -122.421695),
+ new google.maps.LatLng(37.764993, -122.421843),
+ new google.maps.LatLng(37.764986, -122.422255),
+ new google.maps.LatLng(37.764975, -122.422823),
+ new google.maps.LatLng(37.764939, -122.423411),
+ new google.maps.LatLng(37.764902, -122.424014),
+ new google.maps.LatLng(37.764853, -122.424576),
+ new google.maps.LatLng(37.764826, -122.424922),
+ new google.maps.LatLng(37.764796, -122.425375),
+ new google.maps.LatLng(37.764782, -122.425869),
+ new google.maps.LatLng(37.764768, -122.426089),
+ new google.maps.LatLng(37.764766, -122.426117),
+ new google.maps.LatLng(37.764723, -122.426276),
+ new google.maps.LatLng(37.764681, -122.426649),
+ new google.maps.LatLng(37.782012, -122.4042),
+ new google.maps.LatLng(37.781574, -122.404911),
+ new google.maps.LatLng(37.781055, -122.405597),
+ new google.maps.LatLng(37.780479, -122.406341),
+ new google.maps.LatLng(37.779996, -122.406939),
+ new google.maps.LatLng(37.779459, -122.407613),
+ new google.maps.LatLng(37.778953, -122.408228),
+ new google.maps.LatLng(37.778409, -122.408839),
+ new google.maps.LatLng(37.777842, -122.409501),
+ new google.maps.LatLng(37.777334, -122.410181),
+ new google.maps.LatLng(37.776809, -122.410836),
+ new google.maps.LatLng(37.77624, -122.411514),
+ new google.maps.LatLng(37.775725, -122.412145),
+ new google.maps.LatLng(37.77519, -122.412805),
+ new google.maps.LatLng(37.774672, -122.413464),
+ new google.maps.LatLng(37.774084, -122.414186),
+ new google.maps.LatLng(37.773533, -122.413636),
+ new google.maps.LatLng(37.773021, -122.413009),
+ new google.maps.LatLng(37.772501, -122.412371),
+ new google.maps.LatLng(37.771964, -122.411681),
+ new google.maps.LatLng(37.771479, -122.411078),
+ new google.maps.LatLng(37.770992, -122.410477),
+ new google.maps.LatLng(37.770467, -122.409801),
+ new google.maps.LatLng(37.77009, -122.408904),
+ new google.maps.LatLng(37.769657, -122.408103),
+ new google.maps.LatLng(37.769132, -122.407276),
+ new google.maps.LatLng(37.768564, -122.406469),
+ new google.maps.LatLng(37.76798, -122.405745),
+ new google.maps.LatLng(37.76738, -122.405299),
+ new google.maps.LatLng(37.766604, -122.405297),
+ new google.maps.LatLng(37.765838, -122.4052),
+ new google.maps.LatLng(37.765139, -122.405139),
+ new google.maps.LatLng(37.764457, -122.405094),
+ new google.maps.LatLng(37.763716, -122.405142),
+ new google.maps.LatLng(37.762932, -122.405398),
+ new google.maps.LatLng(37.762126, -122.405813),
+ new google.maps.LatLng(37.761344, -122.406215),
+ new google.maps.LatLng(37.760556, -122.406495),
+ new google.maps.LatLng(37.759732, -122.406484),
+ new google.maps.LatLng(37.75891, -122.406228),
+ new google.maps.LatLng(37.758182, -122.405695),
+ new google.maps.LatLng(37.757676, -122.405118),
+ new google.maps.LatLng(37.757039, -122.404346),
+ new google.maps.LatLng(37.756335, -122.403719),
+ new google.maps.LatLng(37.755503, -122.403406),
+ new google.maps.LatLng(37.754665, -122.403242),
+ new google.maps.LatLng(37.753837, -122.403172),
+ new google.maps.LatLng(37.752986, -122.403112),
+ new google.maps.LatLng(37.751266, -122.403355),
+ ];
+}
+// [END maps_layer_heatmap]
+export { initMap };
diff --git a/Birdmap.API/ClientApp/src/components/heatmap/heatmap.tsx b/Birdmap.API/ClientApp/src/components/heatmap/heatmap.tsx
new file mode 100644
index 0000000..5d7a8b8
--- /dev/null
+++ b/Birdmap.API/ClientApp/src/components/heatmap/heatmap.tsx
@@ -0,0 +1,21 @@
+import { Map, GoogleApiWrapper } from 'google-maps-react';
+
+export function Heatmap() {
+ const mapStyles = {
+ width: '100%',
+ height: '100%',
+ };
+
+ return (
+
+ );
+}
+
+export default GoogleApiWrapper({
+ apiKey: 'AIzaSyCZ51VFfxqZ2GkCmVrcNZdUKsM0fuBQUCY'
+});
\ No newline at end of file
diff --git a/Birdmap.API/Controllers/AuthController.cs b/Birdmap.API/Controllers/AuthController.cs
index 76d6872..4105a9e 100644
--- a/Birdmap.API/Controllers/AuthController.cs
+++ b/Birdmap.API/Controllers/AuthController.cs
@@ -35,8 +35,7 @@ namespace Birdmap.Controllers
}
[AllowAnonymous]
- [HttpPost("authenticate")]
- [ProducesResponseType(typeof(object), StatusCodes.Status200OK)]
+ [HttpPost("authenticate"), ProducesResponseType(typeof(object), StatusCodes.Status200OK)]
public async Task AuthenticateAsync([FromBody] AuthenticateRequest model)
{
_logger.LogInformation($"Authenticating user [{model.Username}] with password [*******]...");
@@ -70,8 +69,7 @@ namespace Birdmap.Controllers
}
[AllowAnonymous]
- [HttpPost("register")]
- [ProducesResponseType(StatusCodes.Status204NoContent)]
+ [HttpPost("register"), ProducesResponseType(StatusCodes.Status204NoContent)]
public async Task RegisterAsync([FromBody] RegisterRequest model)
{
_logger.LogInformation($"Registering user [{model.Username}]...");
diff --git a/Birdmap.API/Controllers/DevicesController.cs b/Birdmap.API/Controllers/DevicesController.cs
new file mode 100644
index 0000000..2791598
--- /dev/null
+++ b/Birdmap.API/Controllers/DevicesController.cs
@@ -0,0 +1,144 @@
+using Birdmap.BLL.Interfaces;
+using Microsoft.AspNetCore.Mvc;
+using Microsoft.Extensions.Logging;
+using System;
+using System.Threading.Tasks;
+using System.Collections.Generic;
+using Microsoft.AspNetCore.Mvc.ModelBinding;
+using System.Linq;
+using Microsoft.AspNetCore.Authorization;
+
+namespace Birdmap.API.Controllers
+{
+ [Authorize]
+ [ApiController]
+ [Route("api/[controller]")]
+ public class DevicesController : ControllerBase
+ {
+ private readonly IDeviceService _service;
+ private readonly ILogger _logger;
+
+ public DevicesController(IDeviceService service, ILogger logger)
+ {
+ _service = service;
+ _logger = logger;
+ }
+
+ /// Get all device info
+ /// Array of devices
+ [HttpGet]
+ public async Task>> Getall()
+ {
+ _logger.LogInformation("Getting all devices...");
+
+ return (await _service.GetallAsync()).ToList();
+ }
+
+ /// Shut down all devices
+ /// Message sent
+ [HttpPost, Route("offline")]
+ public async Task Offlineall()
+ {
+ _logger.LogInformation("Turning off all devices and sensors...");
+
+ await _service.OfflineallAsync();
+
+ return Ok();
+ }
+
+ /// Bring all devices online
+ /// Message sent
+ [HttpPost, Route("online")]
+ public async Task Onlineall()
+ {
+ _logger.LogInformation("Turning on all devices and sensors...");
+
+ await _service.OnlineallAsync();
+
+ return Ok();
+ }
+
+ /// Get all device info
+ /// ID of device to query
+ /// Information about a particular device
+ [HttpGet, Route("{deviceID}")]
+ public async Task> Getdevice([BindRequired] Guid deviceID)
+ {
+ _logger.LogInformation($"Getting device [{deviceID}]...");
+
+ return await _service.GetdeviceAsync(deviceID);
+ }
+
+ /// Shut down device
+ /// ID of device to shut down
+ /// Message sent
+ [HttpPost, Route("{deviceID}/offline")]
+ public async Task Offlinedevice([BindRequired] Guid deviceID)
+ {
+ _logger.LogInformation($"Turning off device [{deviceID}]...");
+
+ await _service.OfflinedeviceAsync(deviceID);
+
+ return Ok();
+ }
+
+ /// Bring device online
+ /// ID of device to bring online
+ /// Message sent
+ [HttpPost, Route("{deviceID}/online")]
+ public async Task Onlinedevice([BindRequired] Guid deviceID)
+ {
+ _logger.LogInformation($"Turning on device [{deviceID}]...");
+
+ await _service.OnlinedeviceAsync(deviceID);
+
+ return Ok();
+ }
+
+ /// Get info about a particular device's sensor
+ /// ID of device to query
+ /// ID of sensor to query
+ /// Information about a sensor
+ [HttpGet, Route("{deviceID}/{sensorID}")]
+ public async Task> Getsensor([BindRequired] Guid deviceID, [BindRequired] Guid sensorID)
+ {
+ _logger.LogInformation($"Getting sensor [{sensorID}] of device [{deviceID}]...");
+
+ return await _service.GetsensorAsync(deviceID, sensorID);
+ }
+
+ /// Shut down sensor
+ /// ID of device to query
+ /// ID of sensor to query
+ /// Message sent
+ [HttpPost, Route("{deviceID}/{sensorID}/offline")]
+ public async Task Offlinesensor([BindRequired] Guid deviceID, [BindRequired] Guid sensorID)
+ {
+ _logger.LogInformation($"Turning off sensor [{sensorID}] of device [{deviceID}]...");
+
+ await _service.OfflinesensorAsync(deviceID, sensorID);
+
+ return Ok();
+ }
+
+ /// Bring sensor online
+ /// ID of device to query
+ /// ID of sensor to query
+ /// Message sent
+ [HttpPost, Route("{deviceID}/{sensorID}/online")]
+ public async Task Onlinesensor([BindRequired] Guid deviceID, [BindRequired] Guid sensorID)
+ {
+ _logger.LogInformation($"Turning on sensor [{sensorID}] of device [{deviceID}]...");
+
+ await _service.OnlinesensorAsync(deviceID, sensorID);
+
+ return Ok();
+ }
+ }
+}
+
+#pragma warning restore 1591
+#pragma warning restore 1573
+#pragma warning restore 472
+#pragma warning restore 114
+#pragma warning restore 108
\ No newline at end of file
diff --git a/Birdmap.API/Controllers/ServicesController.cs b/Birdmap.API/Controllers/ServicesController.cs
index d60e28c..6da1729 100644
--- a/Birdmap.API/Controllers/ServicesController.cs
+++ b/Birdmap.API/Controllers/ServicesController.cs
@@ -30,8 +30,7 @@ namespace Birdmap.API.Controllers
_logger = logger;
}
- [HttpGet]
- [ProducesResponseType(StatusCodes.Status200OK)]
+ [HttpGet, ProducesResponseType(StatusCodes.Status200OK)]
public async Task>> GetAsync()
{
_logger.LogInformation($"Getting all services from db...");
@@ -59,8 +58,7 @@ namespace Birdmap.API.Controllers
return serviceInfos.ToList();
}
- [HttpPost]
- [ProducesResponseType(StatusCodes.Status201Created)]
+ [HttpPost, ProducesResponseType(StatusCodes.Status201Created)]
public async Task> PostAsync(ServiceRequest request)
{
_logger.LogInformation($"Creating service [{request.Name}]...");
@@ -74,8 +72,7 @@ namespace Birdmap.API.Controllers
_mapper.Map(created));
}
- [HttpPut]
- [ProducesResponseType(StatusCodes.Status204NoContent)]
+ [HttpPut, ProducesResponseType(StatusCodes.Status204NoContent)]
public async Task PutAsync(ServiceRequest request)
{
_logger.LogInformation($"Updating service [{request.Name}]...");
@@ -87,8 +84,7 @@ namespace Birdmap.API.Controllers
return NoContent();
}
- [HttpDelete("{id}")]
- [ProducesResponseType(StatusCodes.Status204NoContent)]
+ [HttpDelete("{id}"), ProducesResponseType(StatusCodes.Status204NoContent)]
public async Task DeleteAsync(int id)
{
_logger.LogInformation($"Deleting service [{id}]...");
diff --git a/Birdmap.API/appsettings.json b/Birdmap.API/appsettings.json
index f774618..fe9b2e1 100644
--- a/Birdmap.API/appsettings.json
+++ b/Birdmap.API/appsettings.json
@@ -27,5 +27,6 @@
"Role": "User"
}
]
- }
+ },
+ "UseDummyServices": true
}
diff --git a/Birdmap.BLL/Interfaces/IDeviceService.cs b/Birdmap.BLL/Interfaces/IDeviceService.cs
new file mode 100644
index 0000000..047c619
--- /dev/null
+++ b/Birdmap.BLL/Interfaces/IDeviceService.cs
@@ -0,0 +1,279 @@
+namespace Birdmap.BLL.Interfaces
+{
+ [System.CodeDom.Compiler.GeneratedCode("NJsonSchema", "10.2.1.0 (Newtonsoft.Json v12.0.0.0)")]
+ public partial class ListOfDevices : System.Collections.ObjectModel.Collection
+ {
+
+ }
+
+ [System.CodeDom.Compiler.GeneratedCode("NJsonSchema", "10.2.1.0 (Newtonsoft.Json v12.0.0.0)")]
+ public partial class Device
+ {
+ [Newtonsoft.Json.JsonProperty("id", Required = Newtonsoft.Json.Required.Always)]
+ [System.ComponentModel.DataAnnotations.Required(AllowEmptyStrings = true)]
+ public System.Guid Id { get; set; }
+
+ [Newtonsoft.Json.JsonProperty("status", Required = Newtonsoft.Json.Required.Always)]
+ [System.ComponentModel.DataAnnotations.Required(AllowEmptyStrings = true)]
+ [Newtonsoft.Json.JsonConverter(typeof(Newtonsoft.Json.Converters.StringEnumConverter))]
+ public DeviceStatus Status { get; set; }
+
+ [Newtonsoft.Json.JsonProperty("url", Required = Newtonsoft.Json.Required.Always)]
+ [System.ComponentModel.DataAnnotations.Required(AllowEmptyStrings = true)]
+ public string Url { get; set; }
+
+ [Newtonsoft.Json.JsonProperty("coordinates", Required = Newtonsoft.Json.Required.AllowNull)]
+ [System.ComponentModel.DataAnnotations.Required]
+ public Coordinates Coordinates { get; set; } = new Coordinates();
+
+ [Newtonsoft.Json.JsonProperty("sensors", Required = Newtonsoft.Json.Required.Always)]
+ [System.ComponentModel.DataAnnotations.Required]
+ public ArrayofSensors Sensors { get; set; } = new ArrayofSensors();
+
+ private System.Collections.Generic.IDictionary _additionalProperties = new System.Collections.Generic.Dictionary();
+
+ [Newtonsoft.Json.JsonExtensionData]
+ public System.Collections.Generic.IDictionary AdditionalProperties
+ {
+ get { return _additionalProperties; }
+ set { _additionalProperties = value; }
+ }
+
+
+ }
+
+ [System.CodeDom.Compiler.GeneratedCode("NJsonSchema", "10.2.1.0 (Newtonsoft.Json v12.0.0.0)")]
+ public partial class ArrayofSensors : System.Collections.ObjectModel.Collection
+ {
+
+ }
+
+ [System.CodeDom.Compiler.GeneratedCode("NJsonSchema", "10.2.1.0 (Newtonsoft.Json v12.0.0.0)")]
+ public partial class Sensor
+ {
+ [Newtonsoft.Json.JsonProperty("id", Required = Newtonsoft.Json.Required.Always)]
+ [System.ComponentModel.DataAnnotations.Required(AllowEmptyStrings = true)]
+ public System.Guid Id { get; set; }
+
+ [Newtonsoft.Json.JsonProperty("status", Required = Newtonsoft.Json.Required.Always)]
+ [System.ComponentModel.DataAnnotations.Required(AllowEmptyStrings = true)]
+ [Newtonsoft.Json.JsonConverter(typeof(Newtonsoft.Json.Converters.StringEnumConverter))]
+ public SensorStatus Status { get; set; }
+
+ private System.Collections.Generic.IDictionary _additionalProperties = new System.Collections.Generic.Dictionary();
+
+ [Newtonsoft.Json.JsonExtensionData]
+ public System.Collections.Generic.IDictionary AdditionalProperties
+ {
+ get { return _additionalProperties; }
+ set { _additionalProperties = value; }
+ }
+
+
+ }
+
+ [System.CodeDom.Compiler.GeneratedCode("NJsonSchema", "10.2.1.0 (Newtonsoft.Json v12.0.0.0)")]
+ public partial class Coordinates
+ {
+ [Newtonsoft.Json.JsonProperty("latitude", Required = Newtonsoft.Json.Required.Always)]
+ public double Latitude { get; set; }
+
+ [Newtonsoft.Json.JsonProperty("longitude", Required = Newtonsoft.Json.Required.Always)]
+ public double Longitude { get; set; }
+
+ private System.Collections.Generic.IDictionary _additionalProperties = new System.Collections.Generic.Dictionary();
+
+ [Newtonsoft.Json.JsonExtensionData]
+ public System.Collections.Generic.IDictionary AdditionalProperties
+ {
+ get { return _additionalProperties; }
+ set { _additionalProperties = value; }
+ }
+
+
+ }
+
+ [System.CodeDom.Compiler.GeneratedCode("NJsonSchema", "10.2.1.0 (Newtonsoft.Json v12.0.0.0)")]
+ public enum DeviceStatus
+ {
+ [System.Runtime.Serialization.EnumMember(Value = @"online")]
+ Online = 0,
+
+ [System.Runtime.Serialization.EnumMember(Value = @"error")]
+ Error = 1,
+
+ [System.Runtime.Serialization.EnumMember(Value = @"offline")]
+ Offline = 2,
+
+ }
+
+ [System.CodeDom.Compiler.GeneratedCode("NJsonSchema", "10.2.1.0 (Newtonsoft.Json v12.0.0.0)")]
+ public enum SensorStatus
+ {
+ [System.Runtime.Serialization.EnumMember(Value = @"online")]
+ Online = 0,
+
+ [System.Runtime.Serialization.EnumMember(Value = @"unknown")]
+ Unknown = 1,
+
+ [System.Runtime.Serialization.EnumMember(Value = @"offline")]
+ Offline = 2,
+
+ }
+
+ [System.CodeDom.Compiler.GeneratedCode("NSwag", "13.8.2.0 (NJsonSchema v10.2.1.0 (Newtonsoft.Json v12.0.0.0))")]
+ public partial class ApiException : System.Exception
+ {
+ public int StatusCode { get; private set; }
+
+ public string Response { get; private set; }
+
+ public System.Collections.Generic.IReadOnlyDictionary> Headers { get; private set; }
+
+ public ApiException(string message, int statusCode, string response, System.Collections.Generic.IReadOnlyDictionary> headers, System.Exception innerException)
+ : base(message + "\n\nStatus: " + statusCode + "\nResponse: \n" + ((response == null) ? "(null)" : response.Substring(0, response.Length >= 512 ? 512 : response.Length)), innerException)
+ {
+ StatusCode = statusCode;
+ Response = response;
+ Headers = headers;
+ }
+
+ public override string ToString()
+ {
+ return string.Format("HTTP Response: \n\n{0}\n\n{1}", Response, base.ToString());
+ }
+ }
+
+ [System.CodeDom.Compiler.GeneratedCode("NSwag", "13.8.2.0 (NJsonSchema v10.2.1.0 (Newtonsoft.Json v12.0.0.0))")]
+ public partial class ApiException : ApiException
+ {
+ public TResult Result { get; private set; }
+
+ public ApiException(string message, int statusCode, string response, System.Collections.Generic.IReadOnlyDictionary> headers, TResult result, System.Exception innerException)
+ : base(message, statusCode, response, headers, innerException)
+ {
+ Result = result;
+ }
+ }
+
+ [System.CodeDom.Compiler.GeneratedCode("NSwag", "13.8.2.0 (NJsonSchema v10.2.1.0 (Newtonsoft.Json v12.0.0.0))")]
+ public partial interface IDeviceService
+ {
+ /// Get all device info
+ /// Array of devices
+ /// A server side error occurred.
+ System.Threading.Tasks.Task> GetallAsync();
+
+ /// A cancellation token that can be used by other objects or threads to receive notice of cancellation.
+ /// Get all device info
+ /// Array of devices
+ /// A server side error occurred.
+ System.Threading.Tasks.Task> GetallAsync(System.Threading.CancellationToken cancellationToken);
+
+ /// Shut down all devices
+ /// Message sent
+ /// A server side error occurred.
+ System.Threading.Tasks.Task OfflineallAsync();
+
+ /// A cancellation token that can be used by other objects or threads to receive notice of cancellation.
+ /// Shut down all devices
+ /// Message sent
+ /// A server side error occurred.
+ System.Threading.Tasks.Task OfflineallAsync(System.Threading.CancellationToken cancellationToken);
+
+ /// Bring all devices online
+ /// Message sent
+ /// A server side error occurred.
+ System.Threading.Tasks.Task OnlineallAsync();
+
+ /// A cancellation token that can be used by other objects or threads to receive notice of cancellation.
+ /// Bring all devices online
+ /// Message sent
+ /// A server side error occurred.
+ System.Threading.Tasks.Task OnlineallAsync(System.Threading.CancellationToken cancellationToken);
+
+ /// Get all device info
+ /// ID of device to query
+ /// Information about a particular device
+ /// A server side error occurred.
+ System.Threading.Tasks.Task GetdeviceAsync(System.Guid deviceID);
+
+ /// A cancellation token that can be used by other objects or threads to receive notice of cancellation.
+ /// Get all device info
+ /// ID of device to query
+ /// Information about a particular device
+ /// A server side error occurred.
+ System.Threading.Tasks.Task GetdeviceAsync(System.Guid deviceID, System.Threading.CancellationToken cancellationToken);
+
+ /// Shut down device
+ /// ID of device to shut down
+ /// Message sent
+ /// A server side error occurred.
+ System.Threading.Tasks.Task OfflinedeviceAsync(System.Guid deviceID);
+
+ /// A cancellation token that can be used by other objects or threads to receive notice of cancellation.
+ /// Shut down device
+ /// ID of device to shut down
+ /// Message sent
+ /// A server side error occurred.
+ System.Threading.Tasks.Task OfflinedeviceAsync(System.Guid deviceID, System.Threading.CancellationToken cancellationToken);
+
+ /// Bring device online
+ /// ID of device to bring online
+ /// Message sent
+ /// A server side error occurred.
+ System.Threading.Tasks.Task OnlinedeviceAsync(System.Guid deviceID);
+
+ /// A cancellation token that can be used by other objects or threads to receive notice of cancellation.
+ /// Bring device online
+ /// ID of device to bring online
+ /// Message sent
+ /// A server side error occurred.
+ System.Threading.Tasks.Task OnlinedeviceAsync(System.Guid deviceID, System.Threading.CancellationToken cancellationToken);
+
+ /// Get info about a particular device's sensor
+ /// ID of device to query
+ /// ID of sensor to query
+ /// Information about a sensor
+ /// A server side error occurred.
+ System.Threading.Tasks.Task GetsensorAsync(System.Guid deviceID, System.Guid sensorID);
+
+ /// A cancellation token that can be used by other objects or threads to receive notice of cancellation.
+ /// Get info about a particular device's sensor
+ /// ID of device to query
+ /// ID of sensor to query
+ /// Information about a sensor
+ /// A server side error occurred.
+ System.Threading.Tasks.Task GetsensorAsync(System.Guid deviceID, System.Guid sensorID, System.Threading.CancellationToken cancellationToken);
+
+ /// Shut down sensor
+ /// ID of device to query
+ /// ID of sensor to query
+ /// Message sent
+ /// A server side error occurred.
+ System.Threading.Tasks.Task OfflinesensorAsync(System.Guid deviceID, System.Guid sensorID);
+
+ /// A cancellation token that can be used by other objects or threads to receive notice of cancellation.
+ /// Shut down sensor
+ /// ID of device to query
+ /// ID of sensor to query
+ /// Message sent
+ /// A server side error occurred.
+ System.Threading.Tasks.Task OfflinesensorAsync(System.Guid deviceID, System.Guid sensorID, System.Threading.CancellationToken cancellationToken);
+
+ /// Bring sensor online
+ /// ID of device to query
+ /// ID of sensor to query
+ /// Message sent
+ /// A server side error occurred.
+ System.Threading.Tasks.Task OnlinesensorAsync(System.Guid deviceID, System.Guid sensorID);
+
+ /// A cancellation token that can be used by other objects or threads to receive notice of cancellation.
+ /// Bring sensor online
+ /// ID of device to query
+ /// ID of sensor to query
+ /// Message sent
+ /// A server side error occurred.
+ System.Threading.Tasks.Task OnlinesensorAsync(System.Guid deviceID, System.Guid sensorID, System.Threading.CancellationToken cancellationToken);
+ }
+}
\ No newline at end of file
diff --git a/Birdmap.BLL/Services/DeviceServiceBase.cs b/Birdmap.BLL/Services/DeviceServiceBase.cs
new file mode 100644
index 0000000..aeab79d
--- /dev/null
+++ b/Birdmap.BLL/Services/DeviceServiceBase.cs
@@ -0,0 +1,39 @@
+using Birdmap.BLL.Interfaces;
+using System;
+using System.Collections.Generic;
+using System.Threading;
+using System.Threading.Tasks;
+
+namespace Birdmap.BLL.Services
+{
+ public abstract class DeviceServiceBase : IDeviceService
+ {
+ public virtual Task> GetallAsync()
+ => GetallAsync(CancellationToken.None);
+ public abstract Task> GetallAsync(CancellationToken cancellationToken);
+ public virtual Task GetdeviceAsync(Guid deviceID)
+ => GetdeviceAsync(deviceID, CancellationToken.None);
+ public abstract Task GetdeviceAsync(Guid deviceID, CancellationToken cancellationToken);
+ public virtual Task GetsensorAsync(Guid deviceID, Guid sensorID)
+ => GetsensorAsync(deviceID, sensorID, CancellationToken.None);
+ public abstract Task GetsensorAsync(Guid deviceID, Guid sensorID, CancellationToken cancellationToken);
+ public virtual Task OfflineallAsync()
+ => OfflineallAsync(CancellationToken.None);
+ public abstract Task OfflineallAsync(CancellationToken cancellationToken);
+ public virtual Task OfflinedeviceAsync(Guid deviceID)
+ => OfflinedeviceAsync(deviceID, CancellationToken.None);
+ public abstract Task OfflinedeviceAsync(Guid deviceID, CancellationToken cancellationToken);
+ public virtual Task OfflinesensorAsync(Guid deviceID, Guid sensorID)
+ => OfflinesensorAsync(deviceID, sensorID, CancellationToken.None);
+ public abstract Task OfflinesensorAsync(Guid deviceID, Guid sensorID, CancellationToken cancellationToken);
+ public virtual Task OnlineallAsync()
+ => OnlineallAsync(CancellationToken.None);
+ public abstract Task OnlineallAsync(CancellationToken cancellationToken);
+ public virtual Task OnlinedeviceAsync(Guid deviceID)
+ => OnlinedeviceAsync(deviceID, CancellationToken.None);
+ public abstract Task OnlinedeviceAsync(Guid deviceID, CancellationToken cancellationToken);
+ public virtual Task OnlinesensorAsync(Guid deviceID, Guid sensorID)
+ => OnlinesensorAsync(deviceID, sensorID, CancellationToken.None);
+ public abstract Task OnlinesensorAsync(Guid deviceID, Guid sensorID, CancellationToken cancellationToken);
+ }
+}
diff --git a/Birdmap.BLL/Services/DummyDeviceService.cs b/Birdmap.BLL/Services/DummyDeviceService.cs
new file mode 100644
index 0000000..617a83a
--- /dev/null
+++ b/Birdmap.BLL/Services/DummyDeviceService.cs
@@ -0,0 +1,139 @@
+using Birdmap.BLL.Interfaces;
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Threading;
+using System.Threading.Tasks;
+
+namespace Birdmap.BLL.Services
+{
+ public class DummyDeviceService : DeviceServiceBase
+ {
+ private const double centerLong = 21.469640;
+ private const double centerLat = 48.275939;
+ private const double radius = 0.000200;
+
+ private readonly Lazy> _devices = new Lazy>(GenerateDevices);
+ private static ListOfDevices GenerateDevices()
+ {
+ var devices = new ListOfDevices();
+ var rand = new Random();
+
+ T GetRandomEnum()
+ {
+ var values = Enum.GetValues(typeof(T));
+ return (T)values.GetValue(rand.Next(values.Length));
+ }
+
+ double GetPlusMinus(double center, double radius)
+ {
+ return center - radius + rand.NextDouble() * radius * 2;
+ }
+
+ for (int d = 0; d < 15; d++)
+ {
+ var sensors = new ArrayofSensors();
+ for (int s = 0; s < rand.Next(1, 5); s++)
+ {
+ sensors.Add(new Sensor
+ {
+ Id = Guid.NewGuid(),
+ Status = GetRandomEnum(),
+ });
+ }
+
+ devices.Add(new Device
+ {
+ Id = Guid.NewGuid(),
+ Sensors = sensors,
+ Status = GetRandomEnum(),
+ Url = "dummyservice.device.url",
+ Coordinates = new Coordinates
+ {
+ Latitude = GetPlusMinus(centerLat, radius),
+ Longitude = GetPlusMinus(centerLong, radius),
+ }
+ });
+ }
+
+ return devices;
+ }
+
+ public override Task> GetallAsync(CancellationToken cancellationToken)
+ {
+ return Task.FromResult(_devices.Value);
+ }
+
+ public override Task GetdeviceAsync(Guid deviceID, CancellationToken cancellationToken)
+ {
+ return Task.FromResult(_devices.Value.SingleOrDefault(d => d.Id == deviceID));
+ }
+
+ public override Task GetsensorAsync(Guid deviceID, Guid sensorID, CancellationToken cancellationToken)
+ {
+ return Task.FromResult(_devices.Value.SingleOrDefault(d => d.Id == deviceID)?.Sensors.SingleOrDefault(s => s.Id == sensorID));
+ }
+
+ public override Task OfflineallAsync(CancellationToken cancellationToken)
+ {
+ SetStatus(DeviceStatus.Offline, SensorStatus.Offline);
+
+ return Task.CompletedTask;
+ }
+
+ public override Task OfflinedeviceAsync(Guid deviceID, CancellationToken cancellationToken)
+ {
+ SetDeviceStatus(deviceID, DeviceStatus.Offline);
+ return Task.CompletedTask;
+ }
+
+ public override Task OfflinesensorAsync(Guid deviceID, Guid sensorID, CancellationToken cancellationToken)
+ {
+ SetSensorStatus(deviceID, sensorID, SensorStatus.Offline);
+ return Task.CompletedTask;
+ }
+
+ public override Task OnlineallAsync(CancellationToken cancellationToken)
+ {
+ SetStatus(DeviceStatus.Online, SensorStatus.Online);
+
+ return Task.CompletedTask;
+ }
+
+ public override Task OnlinedeviceAsync(Guid deviceID, CancellationToken cancellationToken)
+ {
+ SetDeviceStatus(deviceID, DeviceStatus.Online);
+ return Task.CompletedTask;
+ }
+
+ public override Task OnlinesensorAsync(Guid deviceID, Guid sensorID, CancellationToken cancellationToken)
+ {
+ SetSensorStatus(deviceID, sensorID, SensorStatus.Online);
+ return Task.CompletedTask;
+ }
+
+ private void SetStatus(DeviceStatus deviceStatus, SensorStatus sensorStatus)
+ {
+ foreach (var device in _devices.Value)
+ {
+ device.Status = deviceStatus;
+ foreach (var sensor in device.Sensors)
+ {
+ sensor.Status = sensorStatus;
+ }
+ }
+ }
+
+ private void SetDeviceStatus(Guid deviceID, DeviceStatus status)
+ {
+ var device = GetdeviceAsync(deviceID).Result;
+ device.Status = status;
+ }
+
+ private void SetSensorStatus(Guid deviceId, Guid sensorID, SensorStatus status)
+ {
+ var sensor = GetsensorAsync(deviceId, sensorID).Result;
+ sensor.Status = status;
+ }
+ }
+}
diff --git a/Birdmap.BLL/Services/LiveDeviceService.cs b/Birdmap.BLL/Services/LiveDeviceService.cs
new file mode 100644
index 0000000..eb423c3
--- /dev/null
+++ b/Birdmap.BLL/Services/LiveDeviceService.cs
@@ -0,0 +1,902 @@
+//----------------------
+//
+// Generated using the NSwag toolchain v13.8.2.0 (NJsonSchema v10.2.1.0 (Newtonsoft.Json v12.0.0.0)) (http://NSwag.org)
+//
+//----------------------
+
+#pragma warning disable 108 // Disable "CS0108 '{derivedDto}.ToJson()' hides inherited member '{dtoBase}.ToJson()'. Use the new keyword if hiding was intended."
+#pragma warning disable 114 // Disable "CS0114 '{derivedDto}.RaisePropertyChanged(String)' hides inherited member 'dtoBase.RaisePropertyChanged(String)'. To make the current member override that implementation, add the override keyword. Otherwise add the new keyword."
+#pragma warning disable 472 // Disable "CS0472 The result of the expression is always 'false' since a value of type 'Int32' is never equal to 'null' of type 'Int32?'
+#pragma warning disable 1573 // Disable "CS1573 Parameter '...' has no matching param tag in the XML comment for ...
+#pragma warning disable 1591 // Disable "CS1591 Missing XML comment for publicly visible type or member ..."
+
+namespace Birdmap.BLL.Services
+{
+ using Birdmap.BLL.Interfaces;
+ using System = global::System;
+
+ [System.CodeDom.Compiler.GeneratedCode("NSwag", "13.8.2.0 (NJsonSchema v10.2.1.0 (Newtonsoft.Json v12.0.0.0))")]
+ public partial class LiveDummyService : IDeviceService
+ {
+ private string _baseUrl = "https://birb.k8s.kmlabz.com";
+ private System.Net.Http.HttpClient _httpClient;
+ private System.Lazy _settings;
+
+ public LiveDummyService(System.Net.Http.HttpClient httpClient)
+ {
+ _httpClient = httpClient;
+ _settings = new System.Lazy(CreateSerializerSettings);
+ }
+
+ private Newtonsoft.Json.JsonSerializerSettings CreateSerializerSettings()
+ {
+ var settings = new Newtonsoft.Json.JsonSerializerSettings();
+ UpdateJsonSerializerSettings(settings);
+ return settings;
+ }
+
+ public string BaseUrl
+ {
+ get { return _baseUrl; }
+ set { _baseUrl = value; }
+ }
+
+ protected Newtonsoft.Json.JsonSerializerSettings JsonSerializerSettings { get { return _settings.Value; } }
+
+ partial void UpdateJsonSerializerSettings(Newtonsoft.Json.JsonSerializerSettings settings);
+ partial void PrepareRequest(System.Net.Http.HttpClient client, System.Net.Http.HttpRequestMessage request, string url);
+ partial void PrepareRequest(System.Net.Http.HttpClient client, System.Net.Http.HttpRequestMessage request, System.Text.StringBuilder urlBuilder);
+ partial void ProcessResponse(System.Net.Http.HttpClient client, System.Net.Http.HttpResponseMessage response);
+
+ /// Get all device info
+ /// Array of devices
+ /// A server side error occurred.
+ public System.Threading.Tasks.Task> GetallAsync()
+ {
+ return GetallAsync(System.Threading.CancellationToken.None);
+ }
+
+ /// A cancellation token that can be used by other objects or threads to receive notice of cancellation.
+ /// Get all device info
+ /// Array of devices
+ /// A server side error occurred.
+ public async System.Threading.Tasks.Task> GetallAsync(System.Threading.CancellationToken cancellationToken)
+ {
+ var urlBuilder_ = new System.Text.StringBuilder();
+ urlBuilder_.Append(BaseUrl != null ? BaseUrl.TrimEnd('/') : "").Append("/devices");
+
+ var client_ = _httpClient;
+ var disposeClient_ = false;
+ try
+ {
+ using (var request_ = new System.Net.Http.HttpRequestMessage())
+ {
+ request_.Method = new System.Net.Http.HttpMethod("GET");
+ request_.Headers.Accept.Add(System.Net.Http.Headers.MediaTypeWithQualityHeaderValue.Parse("application/json"));
+
+ PrepareRequest(client_, request_, urlBuilder_);
+ var url_ = urlBuilder_.ToString();
+ request_.RequestUri = new System.Uri(url_, System.UriKind.RelativeOrAbsolute);
+ PrepareRequest(client_, request_, url_);
+
+ var response_ = await client_.SendAsync(request_, System.Net.Http.HttpCompletionOption.ResponseHeadersRead, cancellationToken).ConfigureAwait(false);
+ var disposeResponse_ = true;
+ try
+ {
+ var headers_ = System.Linq.Enumerable.ToDictionary(response_.Headers, h_ => h_.Key, h_ => h_.Value);
+ if (response_.Content != null && response_.Content.Headers != null)
+ {
+ foreach (var item_ in response_.Content.Headers)
+ headers_[item_.Key] = item_.Value;
+ }
+
+ ProcessResponse(client_, response_);
+
+ var status_ = (int)response_.StatusCode;
+ if (status_ == 200)
+ {
+ var objectResponse_ = await ReadObjectResponseAsync>(response_, headers_).ConfigureAwait(false);
+ if (objectResponse_.Object == null)
+ {
+ throw new ApiException("Response was null which was not expected.", status_, objectResponse_.Text, headers_, null);
+ }
+ return objectResponse_.Object;
+ }
+ else
+ if (status_ == 404)
+ {
+ string responseText_ = (response_.Content == null) ? string.Empty : await response_.Content.ReadAsStringAsync().ConfigureAwait(false);
+ throw new ApiException("No device found", status_, responseText_, headers_, null);
+ }
+ else
+ {
+ var responseData_ = response_.Content == null ? null : await response_.Content.ReadAsStringAsync().ConfigureAwait(false);
+ throw new ApiException("The HTTP status code of the response was not expected (" + status_ + ").", status_, responseData_, headers_, null);
+ }
+ }
+ finally
+ {
+ if (disposeResponse_)
+ response_.Dispose();
+ }
+ }
+ }
+ finally
+ {
+ if (disposeClient_)
+ client_.Dispose();
+ }
+ }
+
+ /// Shut down all devices
+ /// Message sent
+ /// A server side error occurred.
+ public System.Threading.Tasks.Task OfflineallAsync()
+ {
+ return OfflineallAsync(System.Threading.CancellationToken.None);
+ }
+
+ /// A cancellation token that can be used by other objects or threads to receive notice of cancellation.
+ /// Shut down all devices
+ /// Message sent
+ /// A server side error occurred.
+ public async System.Threading.Tasks.Task OfflineallAsync(System.Threading.CancellationToken cancellationToken)
+ {
+ var urlBuilder_ = new System.Text.StringBuilder();
+ urlBuilder_.Append(BaseUrl != null ? BaseUrl.TrimEnd('/') : "").Append("/devices/offline");
+
+ var client_ = _httpClient;
+ var disposeClient_ = false;
+ try
+ {
+ using (var request_ = new System.Net.Http.HttpRequestMessage())
+ {
+ request_.Content = new System.Net.Http.StringContent(string.Empty, System.Text.Encoding.UTF8, "application/json");
+ request_.Method = new System.Net.Http.HttpMethod("POST");
+
+ PrepareRequest(client_, request_, urlBuilder_);
+ var url_ = urlBuilder_.ToString();
+ request_.RequestUri = new System.Uri(url_, System.UriKind.RelativeOrAbsolute);
+ PrepareRequest(client_, request_, url_);
+
+ var response_ = await client_.SendAsync(request_, System.Net.Http.HttpCompletionOption.ResponseHeadersRead, cancellationToken).ConfigureAwait(false);
+ var disposeResponse_ = true;
+ try
+ {
+ var headers_ = System.Linq.Enumerable.ToDictionary(response_.Headers, h_ => h_.Key, h_ => h_.Value);
+ if (response_.Content != null && response_.Content.Headers != null)
+ {
+ foreach (var item_ in response_.Content.Headers)
+ headers_[item_.Key] = item_.Value;
+ }
+
+ ProcessResponse(client_, response_);
+
+ var status_ = (int)response_.StatusCode;
+ if (status_ == 200)
+ {
+ return;
+ }
+ else
+ if (status_ == 500)
+ {
+ string responseText_ = (response_.Content == null) ? string.Empty : await response_.Content.ReadAsStringAsync().ConfigureAwait(false);
+ throw new ApiException("Message sending unsuccessful", status_, responseText_, headers_, null);
+ }
+ else
+ {
+ var responseData_ = response_.Content == null ? null : await response_.Content.ReadAsStringAsync().ConfigureAwait(false);
+ throw new ApiException("The HTTP status code of the response was not expected (" + status_ + ").", status_, responseData_, headers_, null);
+ }
+ }
+ finally
+ {
+ if (disposeResponse_)
+ response_.Dispose();
+ }
+ }
+ }
+ finally
+ {
+ if (disposeClient_)
+ client_.Dispose();
+ }
+ }
+
+ /// Bring all devices online
+ /// Message sent
+ /// A server side error occurred.
+ public System.Threading.Tasks.Task OnlineallAsync()
+ {
+ return OnlineallAsync(System.Threading.CancellationToken.None);
+ }
+
+ /// A cancellation token that can be used by other objects or threads to receive notice of cancellation.
+ /// Bring all devices online
+ /// Message sent
+ /// A server side error occurred.
+ public async System.Threading.Tasks.Task OnlineallAsync(System.Threading.CancellationToken cancellationToken)
+ {
+ var urlBuilder_ = new System.Text.StringBuilder();
+ urlBuilder_.Append(BaseUrl != null ? BaseUrl.TrimEnd('/') : "").Append("/devices/online");
+
+ var client_ = _httpClient;
+ var disposeClient_ = false;
+ try
+ {
+ using (var request_ = new System.Net.Http.HttpRequestMessage())
+ {
+ request_.Content = new System.Net.Http.StringContent(string.Empty, System.Text.Encoding.UTF8, "application/json");
+ request_.Method = new System.Net.Http.HttpMethod("POST");
+
+ PrepareRequest(client_, request_, urlBuilder_);
+ var url_ = urlBuilder_.ToString();
+ request_.RequestUri = new System.Uri(url_, System.UriKind.RelativeOrAbsolute);
+ PrepareRequest(client_, request_, url_);
+
+ var response_ = await client_.SendAsync(request_, System.Net.Http.HttpCompletionOption.ResponseHeadersRead, cancellationToken).ConfigureAwait(false);
+ var disposeResponse_ = true;
+ try
+ {
+ var headers_ = System.Linq.Enumerable.ToDictionary(response_.Headers, h_ => h_.Key, h_ => h_.Value);
+ if (response_.Content != null && response_.Content.Headers != null)
+ {
+ foreach (var item_ in response_.Content.Headers)
+ headers_[item_.Key] = item_.Value;
+ }
+
+ ProcessResponse(client_, response_);
+
+ var status_ = (int)response_.StatusCode;
+ if (status_ == 200)
+ {
+ return;
+ }
+ else
+ if (status_ == 500)
+ {
+ string responseText_ = (response_.Content == null) ? string.Empty : await response_.Content.ReadAsStringAsync().ConfigureAwait(false);
+ throw new ApiException("Message sending unsuccessful", status_, responseText_, headers_, null);
+ }
+ else
+ {
+ var responseData_ = response_.Content == null ? null : await response_.Content.ReadAsStringAsync().ConfigureAwait(false);
+ throw new ApiException("The HTTP status code of the response was not expected (" + status_ + ").", status_, responseData_, headers_, null);
+ }
+ }
+ finally
+ {
+ if (disposeResponse_)
+ response_.Dispose();
+ }
+ }
+ }
+ finally
+ {
+ if (disposeClient_)
+ client_.Dispose();
+ }
+ }
+
+ /// Get all device info
+ /// ID of device to query
+ /// Information about a particular device
+ /// A server side error occurred.
+ public System.Threading.Tasks.Task GetdeviceAsync(System.Guid deviceID)
+ {
+ return GetdeviceAsync(deviceID, System.Threading.CancellationToken.None);
+ }
+
+ /// A cancellation token that can be used by other objects or threads to receive notice of cancellation.
+ /// Get all device info
+ /// ID of device to query
+ /// Information about a particular device
+ /// A server side error occurred.
+ public async System.Threading.Tasks.Task GetdeviceAsync(System.Guid deviceID, System.Threading.CancellationToken cancellationToken)
+ {
+ if (deviceID == null)
+ throw new System.ArgumentNullException("deviceID");
+
+ var urlBuilder_ = new System.Text.StringBuilder();
+ urlBuilder_.Append(BaseUrl != null ? BaseUrl.TrimEnd('/') : "").Append("/devices/{deviceID}");
+ urlBuilder_.Replace("{deviceID}", System.Uri.EscapeDataString(ConvertToString(deviceID, System.Globalization.CultureInfo.InvariantCulture)));
+
+ var client_ = _httpClient;
+ var disposeClient_ = false;
+ try
+ {
+ using (var request_ = new System.Net.Http.HttpRequestMessage())
+ {
+ request_.Method = new System.Net.Http.HttpMethod("GET");
+ request_.Headers.Accept.Add(System.Net.Http.Headers.MediaTypeWithQualityHeaderValue.Parse("application/json"));
+
+ PrepareRequest(client_, request_, urlBuilder_);
+ var url_ = urlBuilder_.ToString();
+ request_.RequestUri = new System.Uri(url_, System.UriKind.RelativeOrAbsolute);
+ PrepareRequest(client_, request_, url_);
+
+ var response_ = await client_.SendAsync(request_, System.Net.Http.HttpCompletionOption.ResponseHeadersRead, cancellationToken).ConfigureAwait(false);
+ var disposeResponse_ = true;
+ try
+ {
+ var headers_ = System.Linq.Enumerable.ToDictionary(response_.Headers, h_ => h_.Key, h_ => h_.Value);
+ if (response_.Content != null && response_.Content.Headers != null)
+ {
+ foreach (var item_ in response_.Content.Headers)
+ headers_[item_.Key] = item_.Value;
+ }
+
+ ProcessResponse(client_, response_);
+
+ var status_ = (int)response_.StatusCode;
+ if (status_ == 200)
+ {
+ var objectResponse_ = await ReadObjectResponseAsync(response_, headers_).ConfigureAwait(false);
+ if (objectResponse_.Object == null)
+ {
+ throw new ApiException("Response was null which was not expected.", status_, objectResponse_.Text, headers_, null);
+ }
+ return objectResponse_.Object;
+ }
+ else
+ if (status_ == 404)
+ {
+ string responseText_ = (response_.Content == null) ? string.Empty : await response_.Content.ReadAsStringAsync().ConfigureAwait(false);
+ throw new ApiException("Device not found", status_, responseText_, headers_, null);
+ }
+ else
+ {
+ var responseData_ = response_.Content == null ? null : await response_.Content.ReadAsStringAsync().ConfigureAwait(false);
+ throw new ApiException("The HTTP status code of the response was not expected (" + status_ + ").", status_, responseData_, headers_, null);
+ }
+ }
+ finally
+ {
+ if (disposeResponse_)
+ response_.Dispose();
+ }
+ }
+ }
+ finally
+ {
+ if (disposeClient_)
+ client_.Dispose();
+ }
+ }
+
+ /// Shut down device
+ /// ID of device to shut down
+ /// Message sent
+ /// A server side error occurred.
+ public System.Threading.Tasks.Task OfflinedeviceAsync(System.Guid deviceID)
+ {
+ return OfflinedeviceAsync(deviceID, System.Threading.CancellationToken.None);
+ }
+
+ /// A cancellation token that can be used by other objects or threads to receive notice of cancellation.
+ /// Shut down device
+ /// ID of device to shut down
+ /// Message sent
+ /// A server side error occurred.
+ public async System.Threading.Tasks.Task OfflinedeviceAsync(System.Guid deviceID, System.Threading.CancellationToken cancellationToken)
+ {
+ if (deviceID == null)
+ throw new System.ArgumentNullException("deviceID");
+
+ var urlBuilder_ = new System.Text.StringBuilder();
+ urlBuilder_.Append(BaseUrl != null ? BaseUrl.TrimEnd('/') : "").Append("/devices/{deviceID}/offline");
+ urlBuilder_.Replace("{deviceID}", System.Uri.EscapeDataString(ConvertToString(deviceID, System.Globalization.CultureInfo.InvariantCulture)));
+
+ var client_ = _httpClient;
+ var disposeClient_ = false;
+ try
+ {
+ using (var request_ = new System.Net.Http.HttpRequestMessage())
+ {
+ request_.Content = new System.Net.Http.StringContent(string.Empty, System.Text.Encoding.UTF8, "application/json");
+ request_.Method = new System.Net.Http.HttpMethod("POST");
+
+ PrepareRequest(client_, request_, urlBuilder_);
+ var url_ = urlBuilder_.ToString();
+ request_.RequestUri = new System.Uri(url_, System.UriKind.RelativeOrAbsolute);
+ PrepareRequest(client_, request_, url_);
+
+ var response_ = await client_.SendAsync(request_, System.Net.Http.HttpCompletionOption.ResponseHeadersRead, cancellationToken).ConfigureAwait(false);
+ var disposeResponse_ = true;
+ try
+ {
+ var headers_ = System.Linq.Enumerable.ToDictionary(response_.Headers, h_ => h_.Key, h_ => h_.Value);
+ if (response_.Content != null && response_.Content.Headers != null)
+ {
+ foreach (var item_ in response_.Content.Headers)
+ headers_[item_.Key] = item_.Value;
+ }
+
+ ProcessResponse(client_, response_);
+
+ var status_ = (int)response_.StatusCode;
+ if (status_ == 200)
+ {
+ return;
+ }
+ else
+ if (status_ == 500)
+ {
+ string responseText_ = (response_.Content == null) ? string.Empty : await response_.Content.ReadAsStringAsync().ConfigureAwait(false);
+ throw new ApiException("Message sending unsuccessful", status_, responseText_, headers_, null);
+ }
+ else
+ {
+ var responseData_ = response_.Content == null ? null : await response_.Content.ReadAsStringAsync().ConfigureAwait(false);
+ throw new ApiException("The HTTP status code of the response was not expected (" + status_ + ").", status_, responseData_, headers_, null);
+ }
+ }
+ finally
+ {
+ if (disposeResponse_)
+ response_.Dispose();
+ }
+ }
+ }
+ finally
+ {
+ if (disposeClient_)
+ client_.Dispose();
+ }
+ }
+
+ /// Bring device online
+ /// ID of device to bring online
+ /// Message sent
+ /// A server side error occurred.
+ public System.Threading.Tasks.Task OnlinedeviceAsync(System.Guid deviceID)
+ {
+ return OnlinedeviceAsync(deviceID, System.Threading.CancellationToken.None);
+ }
+
+ /// A cancellation token that can be used by other objects or threads to receive notice of cancellation.
+ /// Bring device online
+ /// ID of device to bring online
+ /// Message sent
+ /// A server side error occurred.
+ public async System.Threading.Tasks.Task OnlinedeviceAsync(System.Guid deviceID, System.Threading.CancellationToken cancellationToken)
+ {
+ if (deviceID == null)
+ throw new System.ArgumentNullException("deviceID");
+
+ var urlBuilder_ = new System.Text.StringBuilder();
+ urlBuilder_.Append(BaseUrl != null ? BaseUrl.TrimEnd('/') : "").Append("/devices/{deviceID}/online");
+ urlBuilder_.Replace("{deviceID}", System.Uri.EscapeDataString(ConvertToString(deviceID, System.Globalization.CultureInfo.InvariantCulture)));
+
+ var client_ = _httpClient;
+ var disposeClient_ = false;
+ try
+ {
+ using (var request_ = new System.Net.Http.HttpRequestMessage())
+ {
+ request_.Content = new System.Net.Http.StringContent(string.Empty, System.Text.Encoding.UTF8, "application/json");
+ request_.Method = new System.Net.Http.HttpMethod("POST");
+
+ PrepareRequest(client_, request_, urlBuilder_);
+ var url_ = urlBuilder_.ToString();
+ request_.RequestUri = new System.Uri(url_, System.UriKind.RelativeOrAbsolute);
+ PrepareRequest(client_, request_, url_);
+
+ var response_ = await client_.SendAsync(request_, System.Net.Http.HttpCompletionOption.ResponseHeadersRead, cancellationToken).ConfigureAwait(false);
+ var disposeResponse_ = true;
+ try
+ {
+ var headers_ = System.Linq.Enumerable.ToDictionary(response_.Headers, h_ => h_.Key, h_ => h_.Value);
+ if (response_.Content != null && response_.Content.Headers != null)
+ {
+ foreach (var item_ in response_.Content.Headers)
+ headers_[item_.Key] = item_.Value;
+ }
+
+ ProcessResponse(client_, response_);
+
+ var status_ = (int)response_.StatusCode;
+ if (status_ == 200)
+ {
+ return;
+ }
+ else
+ if (status_ == 500)
+ {
+ string responseText_ = (response_.Content == null) ? string.Empty : await response_.Content.ReadAsStringAsync().ConfigureAwait(false);
+ throw new ApiException("Message sending unsuccessful", status_, responseText_, headers_, null);
+ }
+ else
+ {
+ var responseData_ = response_.Content == null ? null : await response_.Content.ReadAsStringAsync().ConfigureAwait(false);
+ throw new ApiException("The HTTP status code of the response was not expected (" + status_ + ").", status_, responseData_, headers_, null);
+ }
+ }
+ finally
+ {
+ if (disposeResponse_)
+ response_.Dispose();
+ }
+ }
+ }
+ finally
+ {
+ if (disposeClient_)
+ client_.Dispose();
+ }
+ }
+
+ /// Get info about a particular device's sensor
+ /// ID of device to query
+ /// ID of sensor to query
+ /// Information about a sensor
+ /// A server side error occurred.
+ public System.Threading.Tasks.Task GetsensorAsync(System.Guid deviceID, System.Guid sensorID)
+ {
+ return GetsensorAsync(deviceID, sensorID, System.Threading.CancellationToken.None);
+ }
+
+ /// A cancellation token that can be used by other objects or threads to receive notice of cancellation.
+ /// Get info about a particular device's sensor
+ /// ID of device to query
+ /// ID of sensor to query
+ /// Information about a sensor
+ /// A server side error occurred.
+ public async System.Threading.Tasks.Task GetsensorAsync(System.Guid deviceID, System.Guid sensorID, System.Threading.CancellationToken cancellationToken)
+ {
+ if (deviceID == null)
+ throw new System.ArgumentNullException("deviceID");
+
+ if (sensorID == null)
+ throw new System.ArgumentNullException("sensorID");
+
+ var urlBuilder_ = new System.Text.StringBuilder();
+ urlBuilder_.Append(BaseUrl != null ? BaseUrl.TrimEnd('/') : "").Append("/devices/{deviceID}/{sensorID}");
+ urlBuilder_.Replace("{deviceID}", System.Uri.EscapeDataString(ConvertToString(deviceID, System.Globalization.CultureInfo.InvariantCulture)));
+ urlBuilder_.Replace("{sensorID}", System.Uri.EscapeDataString(ConvertToString(sensorID, System.Globalization.CultureInfo.InvariantCulture)));
+
+ var client_ = _httpClient;
+ var disposeClient_ = false;
+ try
+ {
+ using (var request_ = new System.Net.Http.HttpRequestMessage())
+ {
+ request_.Method = new System.Net.Http.HttpMethod("GET");
+ request_.Headers.Accept.Add(System.Net.Http.Headers.MediaTypeWithQualityHeaderValue.Parse("application/json"));
+
+ PrepareRequest(client_, request_, urlBuilder_);
+ var url_ = urlBuilder_.ToString();
+ request_.RequestUri = new System.Uri(url_, System.UriKind.RelativeOrAbsolute);
+ PrepareRequest(client_, request_, url_);
+
+ var response_ = await client_.SendAsync(request_, System.Net.Http.HttpCompletionOption.ResponseHeadersRead, cancellationToken).ConfigureAwait(false);
+ var disposeResponse_ = true;
+ try
+ {
+ var headers_ = System.Linq.Enumerable.ToDictionary(response_.Headers, h_ => h_.Key, h_ => h_.Value);
+ if (response_.Content != null && response_.Content.Headers != null)
+ {
+ foreach (var item_ in response_.Content.Headers)
+ headers_[item_.Key] = item_.Value;
+ }
+
+ ProcessResponse(client_, response_);
+
+ var status_ = (int)response_.StatusCode;
+ if (status_ == 200)
+ {
+ var objectResponse_ = await ReadObjectResponseAsync(response_, headers_).ConfigureAwait(false);
+ if (objectResponse_.Object == null)
+ {
+ throw new ApiException("Response was null which was not expected.", status_, objectResponse_.Text, headers_, null);
+ }
+ return objectResponse_.Object;
+ }
+ else
+ if (status_ == 404)
+ {
+ string responseText_ = (response_.Content == null) ? string.Empty : await response_.Content.ReadAsStringAsync().ConfigureAwait(false);
+ throw new ApiException("Device or sensor not found", status_, responseText_, headers_, null);
+ }
+ else
+ {
+ var responseData_ = response_.Content == null ? null : await response_.Content.ReadAsStringAsync().ConfigureAwait(false);
+ throw new ApiException("The HTTP status code of the response was not expected (" + status_ + ").", status_, responseData_, headers_, null);
+ }
+ }
+ finally
+ {
+ if (disposeResponse_)
+ response_.Dispose();
+ }
+ }
+ }
+ finally
+ {
+ if (disposeClient_)
+ client_.Dispose();
+ }
+ }
+
+ /// Shut down sensor
+ /// ID of device to query
+ /// ID of sensor to query
+ /// Message sent
+ /// A server side error occurred.
+ public System.Threading.Tasks.Task OfflinesensorAsync(System.Guid deviceID, System.Guid sensorID)
+ {
+ return OfflinesensorAsync(deviceID, sensorID, System.Threading.CancellationToken.None);
+ }
+
+ /// A cancellation token that can be used by other objects or threads to receive notice of cancellation.
+ /// Shut down sensor
+ /// ID of device to query
+ /// ID of sensor to query
+ /// Message sent
+ /// A server side error occurred.
+ public async System.Threading.Tasks.Task OfflinesensorAsync(System.Guid deviceID, System.Guid sensorID, System.Threading.CancellationToken cancellationToken)
+ {
+ if (deviceID == null)
+ throw new System.ArgumentNullException("deviceID");
+
+ if (sensorID == null)
+ throw new System.ArgumentNullException("sensorID");
+
+ var urlBuilder_ = new System.Text.StringBuilder();
+ urlBuilder_.Append(BaseUrl != null ? BaseUrl.TrimEnd('/') : "").Append("/devices/{deviceID}/{sensorID}/offline");
+ urlBuilder_.Replace("{deviceID}", System.Uri.EscapeDataString(ConvertToString(deviceID, System.Globalization.CultureInfo.InvariantCulture)));
+ urlBuilder_.Replace("{sensorID}", System.Uri.EscapeDataString(ConvertToString(sensorID, System.Globalization.CultureInfo.InvariantCulture)));
+
+ var client_ = _httpClient;
+ var disposeClient_ = false;
+ try
+ {
+ using (var request_ = new System.Net.Http.HttpRequestMessage())
+ {
+ request_.Content = new System.Net.Http.StringContent(string.Empty, System.Text.Encoding.UTF8, "application/json");
+ request_.Method = new System.Net.Http.HttpMethod("POST");
+
+ PrepareRequest(client_, request_, urlBuilder_);
+ var url_ = urlBuilder_.ToString();
+ request_.RequestUri = new System.Uri(url_, System.UriKind.RelativeOrAbsolute);
+ PrepareRequest(client_, request_, url_);
+
+ var response_ = await client_.SendAsync(request_, System.Net.Http.HttpCompletionOption.ResponseHeadersRead, cancellationToken).ConfigureAwait(false);
+ var disposeResponse_ = true;
+ try
+ {
+ var headers_ = System.Linq.Enumerable.ToDictionary(response_.Headers, h_ => h_.Key, h_ => h_.Value);
+ if (response_.Content != null && response_.Content.Headers != null)
+ {
+ foreach (var item_ in response_.Content.Headers)
+ headers_[item_.Key] = item_.Value;
+ }
+
+ ProcessResponse(client_, response_);
+
+ var status_ = (int)response_.StatusCode;
+ if (status_ == 200)
+ {
+ return;
+ }
+ else
+ if (status_ == 500)
+ {
+ string responseText_ = (response_.Content == null) ? string.Empty : await response_.Content.ReadAsStringAsync().ConfigureAwait(false);
+ throw new ApiException("Message sending unsuccessful", status_, responseText_, headers_, null);
+ }
+ else
+ {
+ var responseData_ = response_.Content == null ? null : await response_.Content.ReadAsStringAsync().ConfigureAwait(false);
+ throw new ApiException("The HTTP status code of the response was not expected (" + status_ + ").", status_, responseData_, headers_, null);
+ }
+ }
+ finally
+ {
+ if (disposeResponse_)
+ response_.Dispose();
+ }
+ }
+ }
+ finally
+ {
+ if (disposeClient_)
+ client_.Dispose();
+ }
+ }
+
+ /// Bring sensor online
+ /// ID of device to query
+ /// ID of sensor to query
+ /// Message sent
+ /// A server side error occurred.
+ public System.Threading.Tasks.Task OnlinesensorAsync(System.Guid deviceID, System.Guid sensorID)
+ {
+ return OnlinesensorAsync(deviceID, sensorID, System.Threading.CancellationToken.None);
+ }
+
+ /// A cancellation token that can be used by other objects or threads to receive notice of cancellation.
+ /// Bring sensor online
+ /// ID of device to query
+ /// ID of sensor to query
+ /// Message sent
+ /// A server side error occurred.
+ public async System.Threading.Tasks.Task OnlinesensorAsync(System.Guid deviceID, System.Guid sensorID, System.Threading.CancellationToken cancellationToken)
+ {
+ if (deviceID == null)
+ throw new System.ArgumentNullException("deviceID");
+
+ if (sensorID == null)
+ throw new System.ArgumentNullException("sensorID");
+
+ var urlBuilder_ = new System.Text.StringBuilder();
+ urlBuilder_.Append(BaseUrl != null ? BaseUrl.TrimEnd('/') : "").Append("/devices/{deviceID}/{sensorID}/online");
+ urlBuilder_.Replace("{deviceID}", System.Uri.EscapeDataString(ConvertToString(deviceID, System.Globalization.CultureInfo.InvariantCulture)));
+ urlBuilder_.Replace("{sensorID}", System.Uri.EscapeDataString(ConvertToString(sensorID, System.Globalization.CultureInfo.InvariantCulture)));
+
+ var client_ = _httpClient;
+ var disposeClient_ = false;
+ try
+ {
+ using (var request_ = new System.Net.Http.HttpRequestMessage())
+ {
+ request_.Content = new System.Net.Http.StringContent(string.Empty, System.Text.Encoding.UTF8, "application/json");
+ request_.Method = new System.Net.Http.HttpMethod("POST");
+
+ PrepareRequest(client_, request_, urlBuilder_);
+ var url_ = urlBuilder_.ToString();
+ request_.RequestUri = new System.Uri(url_, System.UriKind.RelativeOrAbsolute);
+ PrepareRequest(client_, request_, url_);
+
+ var response_ = await client_.SendAsync(request_, System.Net.Http.HttpCompletionOption.ResponseHeadersRead, cancellationToken).ConfigureAwait(false);
+ var disposeResponse_ = true;
+ try
+ {
+ var headers_ = System.Linq.Enumerable.ToDictionary(response_.Headers, h_ => h_.Key, h_ => h_.Value);
+ if (response_.Content != null && response_.Content.Headers != null)
+ {
+ foreach (var item_ in response_.Content.Headers)
+ headers_[item_.Key] = item_.Value;
+ }
+
+ ProcessResponse(client_, response_);
+
+ var status_ = (int)response_.StatusCode;
+ if (status_ == 200)
+ {
+ return;
+ }
+ else
+ if (status_ == 500)
+ {
+ string responseText_ = (response_.Content == null) ? string.Empty : await response_.Content.ReadAsStringAsync().ConfigureAwait(false);
+ throw new ApiException("Message sending unsuccessful", status_, responseText_, headers_, null);
+ }
+ else
+ {
+ var responseData_ = response_.Content == null ? null : await response_.Content.ReadAsStringAsync().ConfigureAwait(false);
+ throw new ApiException("The HTTP status code of the response was not expected (" + status_ + ").", status_, responseData_, headers_, null);
+ }
+ }
+ finally
+ {
+ if (disposeResponse_)
+ response_.Dispose();
+ }
+ }
+ }
+ finally
+ {
+ if (disposeClient_)
+ client_.Dispose();
+ }
+ }
+
+ protected struct ObjectResponseResult
+ {
+ public ObjectResponseResult(T responseObject, string responseText)
+ {
+ this.Object = responseObject;
+ this.Text = responseText;
+ }
+
+ public T Object { get; }
+
+ public string Text { get; }
+ }
+
+ public bool ReadResponseAsString { get; set; }
+
+ protected virtual async System.Threading.Tasks.Task> ReadObjectResponseAsync(System.Net.Http.HttpResponseMessage response, System.Collections.Generic.IReadOnlyDictionary> headers)
+ {
+ if (response == null || response.Content == null)
+ {
+ return new ObjectResponseResult(default(T), string.Empty);
+ }
+
+ if (ReadResponseAsString)
+ {
+ var responseText = await response.Content.ReadAsStringAsync().ConfigureAwait(false);
+ try
+ {
+ var typedBody = Newtonsoft.Json.JsonConvert.DeserializeObject(responseText, JsonSerializerSettings);
+ return new ObjectResponseResult(typedBody, responseText);
+ }
+ catch (Newtonsoft.Json.JsonException exception)
+ {
+ var message = "Could not deserialize the response body string as " + typeof(T).FullName + ".";
+ throw new ApiException(message, (int)response.StatusCode, responseText, headers, exception);
+ }
+ }
+ else
+ {
+ try
+ {
+ using (var responseStream = await response.Content.ReadAsStreamAsync().ConfigureAwait(false))
+ using (var streamReader = new System.IO.StreamReader(responseStream))
+ using (var jsonTextReader = new Newtonsoft.Json.JsonTextReader(streamReader))
+ {
+ var serializer = Newtonsoft.Json.JsonSerializer.Create(JsonSerializerSettings);
+ var typedBody = serializer.Deserialize(jsonTextReader);
+ return new ObjectResponseResult(typedBody, string.Empty);
+ }
+ }
+ catch (Newtonsoft.Json.JsonException exception)
+ {
+ var message = "Could not deserialize the response body stream as " + typeof(T).FullName + ".";
+ throw new ApiException(message, (int)response.StatusCode, string.Empty, headers, exception);
+ }
+ }
+ }
+
+ private string ConvertToString(object value, System.Globalization.CultureInfo cultureInfo)
+ {
+ if (value == null)
+ {
+ return null;
+ }
+
+ if (value is System.Enum)
+ {
+ var name = System.Enum.GetName(value.GetType(), value);
+ if (name != null)
+ {
+ var field = System.Reflection.IntrospectionExtensions.GetTypeInfo(value.GetType()).GetDeclaredField(name);
+ if (field != null)
+ {
+ var attribute = System.Reflection.CustomAttributeExtensions.GetCustomAttribute(field, typeof(System.Runtime.Serialization.EnumMemberAttribute))
+ as System.Runtime.Serialization.EnumMemberAttribute;
+ if (attribute != null)
+ {
+ return attribute.Value != null ? attribute.Value : name;
+ }
+ }
+
+ return System.Convert.ToString(System.Convert.ChangeType(value, System.Enum.GetUnderlyingType(value.GetType()), cultureInfo));
+ }
+ }
+ else if (value is bool)
+ {
+ return System.Convert.ToString((bool)value, cultureInfo).ToLowerInvariant();
+ }
+ else if (value is byte[])
+ {
+ return System.Convert.ToBase64String((byte[])value);
+ }
+ else if (value.GetType().IsArray)
+ {
+ var array = System.Linq.Enumerable.OfType