Bugfix: Fix client-side Brain.js crashes
This commit is contained in:
parent
623af65aef
commit
dea7940b2e
10 changed files with 119 additions and 43 deletions
12
build
12
build
|
@ -139,7 +139,8 @@ task_server-ttn() {
|
|||
# ██████ ███████ ██ ███████ ██ ████ ██
|
||||
task_client() {
|
||||
task_begin "Packaging Javascript";
|
||||
execute node_modules/rollup/bin/rollup --sourcemap --config rollup.config.js;
|
||||
execute node_modules/rollup/bin/rollup --sourcemap --config rollup.main.config.js;
|
||||
execute node_modules/rollup/bin/rollup --sourcemap --config rollup.worker.config.js;
|
||||
task_end $? "Error: rollup packing failed!";
|
||||
|
||||
task_begin "Copying html";
|
||||
|
@ -150,17 +151,22 @@ task_client() {
|
|||
task_client-watch() {
|
||||
set_title "Client Watcher";
|
||||
|
||||
execute node_modules/rollup/bin/rollup --watch --sourcemap --config rollup.config.js &
|
||||
|
||||
# execute node_modules/rollup/bin/rollup --watch --sourcemap --config rollup.config.js &
|
||||
|
||||
echo -e "Watching for changes.";
|
||||
while :; do # : = infinite loop
|
||||
# Wait for an update
|
||||
# inotifywait's non-0 exit code forces an exit for some reason :-/
|
||||
inotifywait -qr --event modify --format '%:e %f' client_src rollup.config.js;
|
||||
inotifywait -qr --event modify --format '%:e %f' client_src rollup.*.config.js;
|
||||
|
||||
task_begin "Copying html";
|
||||
execute cp client_src/index.html "app/";
|
||||
task_end $?;
|
||||
|
||||
stage_begin "Rebuilding client code";
|
||||
set +e; tasks_run client; set -e;
|
||||
stage_end $?;
|
||||
done
|
||||
}
|
||||
|
||||
|
|
|
@ -1,5 +1,7 @@
|
|||
"use strict";
|
||||
|
||||
import path from 'path';
|
||||
|
||||
import L from 'leaflet';
|
||||
import chroma from 'chroma-js';
|
||||
|
||||
|
@ -65,6 +67,10 @@ class LayerAI {
|
|||
);
|
||||
console.log(this.index);
|
||||
|
||||
for(let gateway of this.index.index) {
|
||||
gateway.frozen_net = JSON.parse(await GetFromUrl(`${window.location.href}/${path.dirname(Config.ai_index_file)}/${gateway.filename}`))
|
||||
}
|
||||
|
||||
// Figure out the bounds of the map we're going to generate
|
||||
this.map_bounds = this.gateway_bounds;
|
||||
this.map_bounds.north += Config.border.lat;
|
||||
|
|
|
@ -32,5 +32,6 @@ async function handle_message(event) {
|
|||
self.addEventListener("message", (event) => {
|
||||
handle_message(event).catch((error) => {
|
||||
console.error(error);
|
||||
throw error;
|
||||
});
|
||||
});
|
||||
|
|
|
@ -1,6 +1,5 @@
|
|||
"use strict";
|
||||
|
||||
import path from 'path';
|
||||
|
||||
import brain from 'brain.js';
|
||||
import haversine from 'haversine-distance';
|
||||
|
@ -13,7 +12,6 @@ import {
|
|||
unnormalise_rssi
|
||||
} from '../../../common/Normalisers.mjs';
|
||||
|
||||
import GetFromUrl from '../Helpers/GetFromUrl.mjs';
|
||||
|
||||
class AIWrapper {
|
||||
constructor() {
|
||||
|
@ -36,15 +34,14 @@ class AIWrapper {
|
|||
// WebGL isn't available inside WebWorkers yet :-(
|
||||
|
||||
for(let gateway of this.index.index) {
|
||||
let net = new brain.NeuralNetwork();
|
||||
let net = new brain.NeuralNetwork(/*gateway.net_settings*/);
|
||||
net.fromJSON(
|
||||
// TODO: Move this to the UI thread & do it only once?
|
||||
await GetFromUrl(`${path.dirname(self.location.href)}/${path.dirname(this.Config.ai_index_file)}/${gateway.filename}`)
|
||||
gateway.frozen_net
|
||||
);
|
||||
|
||||
this.gateways.set(
|
||||
gateway.id,
|
||||
net
|
||||
{ ai: net, latitude: gateway.latitude, longitude: gateway.longitude }
|
||||
);
|
||||
}
|
||||
console.log("Model setup complete.");
|
||||
|
@ -64,21 +61,27 @@ class AIWrapper {
|
|||
for(let lng = this.map_bounds.west; lng < this.map_bounds.east; lng += this.Config.step.lng) {
|
||||
let max_predicted_rssi = -Infinity;
|
||||
|
||||
for(let [gateway_id, ai] of this.gateways) {
|
||||
for(let [gateway_id, gateway] of this.gateways) {
|
||||
let distance_from_gateway = haversine(
|
||||
{ latitude: lat, longitude: lng },
|
||||
this.gateways.get(gateway_id)
|
||||
gateway
|
||||
);
|
||||
|
||||
max_predicted_rssi = Math.max(
|
||||
max_predicted_rssi,
|
||||
ai.run({
|
||||
let next_value = gateway.ai.run({
|
||||
latitude: normalise_lat(lat),
|
||||
longitude: normalise_lng(lng),
|
||||
distance: normalise_gateway_distance(
|
||||
distance_from_gateway
|
||||
),
|
||||
})[0]
|
||||
});
|
||||
if(isNaN(next_value[0])) {
|
||||
console.log(next_value);
|
||||
throw new Error("Error: Neural Network returned NaN");
|
||||
}
|
||||
|
||||
// console.log(next_value);
|
||||
max_predicted_rssi = Math.max(
|
||||
max_predicted_rssi,
|
||||
next_value[0]
|
||||
);
|
||||
}
|
||||
|
||||
|
|
43
package-lock.json
generated
43
package-lock.json
generated
|
@ -3712,6 +3712,43 @@
|
|||
"rollup-pluginutils": "^2.8.1"
|
||||
}
|
||||
},
|
||||
"rollup-plugin-node-globals": {
|
||||
"version": "1.4.0",
|
||||
"resolved": "https://registry.npmjs.org/rollup-plugin-node-globals/-/rollup-plugin-node-globals-1.4.0.tgz",
|
||||
"integrity": "sha512-xRkB+W/m1KLIzPUmG0ofvR+CPNcvuCuNdjVBVS7ALKSxr3EDhnzNceGkGi1m8MToSli13AzKFYH4ie9w3I5L3g==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"acorn": "^5.7.3",
|
||||
"buffer-es6": "^4.9.3",
|
||||
"estree-walker": "^0.5.2",
|
||||
"magic-string": "^0.22.5",
|
||||
"process-es6": "^0.11.6",
|
||||
"rollup-pluginutils": "^2.3.1"
|
||||
},
|
||||
"dependencies": {
|
||||
"acorn": {
|
||||
"version": "5.7.3",
|
||||
"resolved": "https://registry.npmjs.org/acorn/-/acorn-5.7.3.tgz",
|
||||
"integrity": "sha512-T/zvzYRfbVojPWahDsE5evJdHb3oJoQfFbsrKM7w5Zcs++Tr257tia3BmMP8XYVjp1S9RZXQMh7gao96BlqZOw==",
|
||||
"dev": true
|
||||
},
|
||||
"estree-walker": {
|
||||
"version": "0.5.2",
|
||||
"resolved": "https://registry.npmjs.org/estree-walker/-/estree-walker-0.5.2.tgz",
|
||||
"integrity": "sha512-XpCnW/AE10ws/kDAs37cngSkvgIR8aN3G0MS85m7dUpuK2EREo9VJ00uvw6Dg/hXEpfsE1I1TvJOJr+Z+TL+ig==",
|
||||
"dev": true
|
||||
},
|
||||
"magic-string": {
|
||||
"version": "0.22.5",
|
||||
"resolved": "https://registry.npmjs.org/magic-string/-/magic-string-0.22.5.tgz",
|
||||
"integrity": "sha512-oreip9rJZkzvA8Qzk9HFs8fZGF/u7H/gtrE8EN6RjKJ9kh2HlC+yQ2QezifqTZfGyiuAV0dRv5a+y/8gBb1m9w==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"vlq": "^0.2.2"
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"rollup-plugin-node-resolve": {
|
||||
"version": "5.2.0",
|
||||
"resolved": "https://registry.npmjs.org/rollup-plugin-node-resolve/-/rollup-plugin-node-resolve-5.2.0.tgz",
|
||||
|
@ -4444,6 +4481,12 @@
|
|||
"integrity": "sha512-fOi47nsJP5Wqefa43kyWSg80qF+Q3XA6MUkgi7Hp1HQaKDQW4cQrK2D0P7mmbFtsV1N89am55Yru/nyEwRubcw==",
|
||||
"dev": true
|
||||
},
|
||||
"vlq": {
|
||||
"version": "0.2.3",
|
||||
"resolved": "https://registry.npmjs.org/vlq/-/vlq-0.2.3.tgz",
|
||||
"integrity": "sha512-DRibZL6DsNhIgYQ+wNdWDL2SL3bKPlVrRiBqV5yuMm++op8W4kGFtaQfCs4KEJn0wBZcHVHJ3eoywX8983k1ow==",
|
||||
"dev": true
|
||||
},
|
||||
"websocket-stream": {
|
||||
"version": "5.5.0",
|
||||
"resolved": "https://registry.npmjs.org/websocket-stream/-/websocket-stream-5.5.0.tgz",
|
||||
|
|
|
@ -41,6 +41,7 @@
|
|||
"@types/leaflet": "^1.4.6",
|
||||
"rollup": "^1.17.0",
|
||||
"rollup-plugin-commonjs": "^10.0.1",
|
||||
"rollup-plugin-node-globals": "^1.4.0",
|
||||
"rollup-plugin-node-resolve": "^5.2.0",
|
||||
"rollup-plugin-postcss": "^2.0.3",
|
||||
"rollup-plugin-replace": "^2.2.0",
|
||||
|
|
12
rollup.main.config.js
Normal file
12
rollup.main.config.js
Normal file
|
@ -0,0 +1,12 @@
|
|||
import plugins from './rollup.plugins.config.js';
|
||||
|
||||
export default {
|
||||
input: {
|
||||
"app": 'client_src/js/index.mjs',
|
||||
},
|
||||
output: {
|
||||
dir: 'app/',
|
||||
format: 'esm'
|
||||
},
|
||||
plugins
|
||||
};
|
|
@ -8,6 +8,7 @@ import postcss from 'rollup-plugin-postcss';
|
|||
import { terser } from "rollup-plugin-terser";
|
||||
import replace from 'rollup-plugin-replace';
|
||||
import builtins from '@joseph184/rollup-plugin-node-builtins';
|
||||
import globals from 'rollup-plugin-node-globals';
|
||||
// import json from 'rollup-plugin-json';
|
||||
|
||||
import postcss_import from 'postcss-import';
|
||||
|
@ -15,6 +16,7 @@ import postcss_copy from 'postcss-copy';
|
|||
|
||||
let plugins = [
|
||||
builtins(),
|
||||
globals(),
|
||||
|
||||
resolve({
|
||||
mainFields: [
|
||||
|
@ -87,14 +89,4 @@ if(process.env.NODE_ENV == "production") {
|
|||
}));
|
||||
}
|
||||
|
||||
export default {
|
||||
input: {
|
||||
"app": 'client_src/js/index.mjs',
|
||||
"worker": 'client_src/js/Worker/AI.worker.mjs'
|
||||
},
|
||||
output: {
|
||||
dir: 'app/',
|
||||
format: 'esm'
|
||||
},
|
||||
plugins
|
||||
};
|
||||
export default plugins;
|
12
rollup.worker.config.js
Normal file
12
rollup.worker.config.js
Normal file
|
@ -0,0 +1,12 @@
|
|||
import plugins from './rollup.plugins.config.js';
|
||||
|
||||
export default {
|
||||
input: {
|
||||
"worker": 'client_src/js/Worker/AI.worker.mjs'
|
||||
},
|
||||
output: {
|
||||
dir: 'app/',
|
||||
format: 'esm'
|
||||
},
|
||||
plugins
|
||||
};
|
|
@ -15,16 +15,6 @@ class AITrainer {
|
|||
this.repo_gateway = GatewayRepo;
|
||||
}
|
||||
|
||||
generate_neural_net() {
|
||||
let net = new brain.NeuralNetwork({
|
||||
hiddenLayers: this.settings.ai.network_arch,
|
||||
activation: "sigmoid"
|
||||
});
|
||||
|
||||
|
||||
return net;
|
||||
}
|
||||
|
||||
async train_all() {
|
||||
let index = [];
|
||||
for(let gateway of this.repo_gateway.iterate()) {
|
||||
|
@ -34,7 +24,8 @@ class AITrainer {
|
|||
if(!fs.existsSync(path.dirname(filepath)))
|
||||
await fs.promises.mkdir(path.dirname(filepath), { recursive: true });
|
||||
|
||||
if(!await this.train_gateway(gateway.id, filepath)) {
|
||||
let result = await this.train_gateway(gateway.id, filepath);
|
||||
if(!result || result.success === false) {
|
||||
this.l.warn(`Warning: Failed to train AI for ${gateway.id}.`);
|
||||
continue;
|
||||
}
|
||||
|
@ -43,7 +34,8 @@ class AITrainer {
|
|||
id: gateway.id,
|
||||
filename: path.basename(filepath),
|
||||
latitude: gateway.latitude,
|
||||
longitude: gateway.longitude
|
||||
longitude: gateway.longitude,
|
||||
net_settings: result.net_settings
|
||||
});
|
||||
}
|
||||
|
||||
|
@ -71,7 +63,12 @@ class AITrainer {
|
|||
*/
|
||||
async train_gateway(gateway_id, destination_filename) {
|
||||
this.l.log(`${this.a.fgreen}${this.a.hicol}Training AI for gateway ${gateway_id}${this.a.reset}`);
|
||||
let net = this.generate_neural_net();
|
||||
|
||||
let net_settings = {
|
||||
hiddenLayers: this.settings.ai.network_arch,
|
||||
activation: "sigmoid"
|
||||
};
|
||||
let net = new brain.NeuralNetwork(net_settings);
|
||||
|
||||
let dataset = this.dataset_fetcher.fetch_all(gateway_id);
|
||||
|
||||
|
@ -91,7 +88,10 @@ class AITrainer {
|
|||
await fs.promises.writeFile(destination_filename, JSON.stringify(net.toJSON()));
|
||||
// console.log(result);
|
||||
|
||||
return true;
|
||||
return {
|
||||
success: true,
|
||||
net_settings
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in a new issue