Compare commits
10
Commits
3b6f5e7c1f
...
7006e8ccc6
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
7006e8ccc6 | ||
|
|
85845da0b8 | ||
|
|
5fe201182a | ||
|
|
de15de87a9 | ||
|
|
b1257da48d | ||
|
|
9f20458b19 | ||
|
|
f984a5c241 | ||
|
|
9081853a6f | ||
|
|
e9296b44be | ||
|
|
146816184c |
@@ -6,15 +6,18 @@ const express = require('express');
|
||||
const app_conf = require("../config/app.conf.js");
|
||||
const map_conf = require("../config/map.conf.js");
|
||||
const messages = require("../config/messages.conf.js");
|
||||
const socket = require("../utils/socket.util.js");
|
||||
|
||||
const map = require("../utils/map.util.js");
|
||||
|
||||
const router = express.Router();
|
||||
|
||||
// Gets an Express response object an emoji code and a string message and renders as error message
|
||||
function errorPageRenderer(res, emoji, message) {
|
||||
res.render("error", {
|
||||
page_title: app_conf.name,
|
||||
program: app_conf.program,
|
||||
app_url: app_conf.app_url,
|
||||
css_path: path.join(app_conf.paths.css.web, "stylesheet.css"),
|
||||
js_path: path.join(app_conf.paths.js.web, "error.js"),
|
||||
error_emoji: emoji,
|
||||
@@ -22,14 +25,17 @@ function errorPageRenderer(res, emoji, message) {
|
||||
})
|
||||
}
|
||||
|
||||
// Disable map endpoint
|
||||
router.get("/disable", async (req, res) => {
|
||||
logger.info(`${req.method}: "${req.url}" => ${req.get("User-Agent")}`);
|
||||
|
||||
fs.writeFileSync(path.join(path.dirname(require.main.filename), map_conf.map_storage_path, "selected"), "");
|
||||
socket.broadcastMap(null);
|
||||
|
||||
res.status(200).send();
|
||||
});
|
||||
|
||||
// Enable map endpoint
|
||||
router.get("/enable", async (req, res) => {
|
||||
logger.info(`${req.method}: "${req.url}" => ${req.get("User-Agent")}`);
|
||||
|
||||
@@ -37,6 +43,7 @@ router.get("/enable", async (req, res) => {
|
||||
|
||||
if (requested_map && map.mapExists(requested_map)) {
|
||||
fs.writeFileSync(path.join(path.dirname(require.main.filename), map_conf.map_storage_path, "selected"), requested_map);
|
||||
socket.broadcastMap(requested_map);
|
||||
|
||||
res.status(200).send();
|
||||
} else {
|
||||
@@ -44,12 +51,23 @@ router.get("/enable", async (req, res) => {
|
||||
}
|
||||
});
|
||||
|
||||
// Remove map endpoint
|
||||
router.delete("/remove", async (req, res) => {
|
||||
logger.info(`${req.method}: "${req.url}" => ${req.get("User-Agent")}`);
|
||||
|
||||
if (req.query["element"]) {
|
||||
// Get map name
|
||||
var element = req.query["element"];
|
||||
if (element) {
|
||||
try {
|
||||
fs.unlinkSync(path.join(path.dirname(require.main.filename), map_conf.map_storage_path, req.query["element"]));
|
||||
// Delete map file and check if the map was selected - to disable it
|
||||
fs.unlinkSync(path.join(path.dirname(require.main.filename), map_conf.map_storage_path, element));
|
||||
if (fs.existsSync(path.join(path.dirname(require.main.filename), map_conf.map_storage_path, "selected"))) {
|
||||
selected_map_name = fs.readFileSync(path.join(path.dirname(require.main.filename), map_conf.map_storage_path, "selected"), "utf-8");
|
||||
if (selected_map_name == element) {
|
||||
fs.writeFileSync(path.join(path.dirname(require.main.filename), map_conf.map_storage_path, "selected"), "");
|
||||
socket.broadcastMap(null);
|
||||
}
|
||||
}
|
||||
res.status(200).send();
|
||||
} catch (error) {
|
||||
res.status(500).send();
|
||||
@@ -60,6 +78,7 @@ router.delete("/remove", async (req, res) => {
|
||||
}
|
||||
});
|
||||
|
||||
// Upload map file
|
||||
router.post("/upload", async (req, res) => {
|
||||
logger.info(`${req.method}: "${req.url}" => ${req.get("User-Agent")}`);
|
||||
|
||||
@@ -79,6 +98,7 @@ router.post("/upload", async (req, res) => {
|
||||
}
|
||||
});
|
||||
|
||||
// Download map
|
||||
router.get("/download", async (req, res) => {
|
||||
logger.info(`${req.method}: "${req.url}" => ${req.get("User-Agent")}`);
|
||||
|
||||
@@ -89,9 +109,11 @@ router.get("/download", async (req, res) => {
|
||||
}
|
||||
});
|
||||
|
||||
// Add new map
|
||||
router.post("/add", async (req, res) => {
|
||||
logger.info(`${req.method}: "${req.url}" => ${req.get("User-Agent")}`);
|
||||
|
||||
// Get new map data and write it to csv
|
||||
if (req.body) {
|
||||
await map.addMap(`${map_conf.prefix}_${uuid.v4()}.${map_conf.extension}`, req.body["meta"], req.body["throttle"], req.body["motor"]);
|
||||
|
||||
@@ -101,11 +123,14 @@ router.post("/add", async (req, res) => {
|
||||
}
|
||||
});
|
||||
|
||||
// Edit map data
|
||||
router.post("/edit", async (req, res) => {
|
||||
logger.info(`${req.method}: "${req.url}" => ${req.get("User-Agent")}`);
|
||||
|
||||
// Check if a map name and data have been received
|
||||
if (req.query["element"] && req.body) {
|
||||
try {
|
||||
// Update the map file
|
||||
await map.updateMap(req.query["element"], req.body["meta"], req.body["throttle"], req.body["motor"]);
|
||||
|
||||
res.status(200).send();
|
||||
@@ -118,12 +143,14 @@ router.post("/edit", async (req, res) => {
|
||||
}
|
||||
});
|
||||
|
||||
// Add map page
|
||||
router.get("/add", async (req, res) => {
|
||||
logger.info(`${req.method}: "${req.url}" => ${req.get("User-Agent")}`);
|
||||
|
||||
res.render("add", {
|
||||
page_title: app_conf.name,
|
||||
program: app_conf.program,
|
||||
app_url: app_conf.app_url,
|
||||
css_path: path.join(app_conf.paths.css.web, "stylesheet.css"),
|
||||
js_path: path.join(app_conf.paths.js.web, "add.js"),
|
||||
chartjs: app_conf.paths.chartjs.web + "/chart.umd.js",
|
||||
@@ -133,6 +160,7 @@ router.get("/add", async (req, res) => {
|
||||
});
|
||||
});
|
||||
|
||||
// Edit map page
|
||||
router.get("/edit", async (req, res) => {
|
||||
logger.info(`${req.method}: "${req.url}" => ${req.get("User-Agent")}`);
|
||||
|
||||
@@ -143,6 +171,7 @@ router.get("/edit", async (req, res) => {
|
||||
res.render("edit", {
|
||||
page_title: app_conf.name,
|
||||
program: app_conf.program,
|
||||
app_url: app_conf.app_url,
|
||||
css_path: path.join(app_conf.paths.css.web, "stylesheet.css"),
|
||||
js_path: path.join(app_conf.paths.js.web, "edit.js"),
|
||||
chartjs: app_conf.paths.chartjs.web + "/chart.umd.js",
|
||||
@@ -164,17 +193,15 @@ router.get("/edit", async (req, res) => {
|
||||
}
|
||||
});
|
||||
|
||||
// Main page
|
||||
router.get("/", async (req, res) => {
|
||||
logger.info(`${req.method}: "${req.url}" => ${req.get("User-Agent")}`);
|
||||
|
||||
try {
|
||||
const maps = await map.getAvailableMaps();
|
||||
var selected_map_name = "";
|
||||
|
||||
if (fs.existsSync(path.join(path.dirname(require.main.filename), map_conf.map_storage_path, "selected"))) {
|
||||
selected_map_name = fs.readFileSync(path.join(path.dirname(require.main.filename), map_conf.map_storage_path, "selected"), "utf-8");
|
||||
}
|
||||
var selected_map_name = map.getSelectedMap();
|
||||
|
||||
// Construct the maps table
|
||||
var table_data = "";
|
||||
if (Object.keys(maps).length) {
|
||||
for (m of Object.keys(maps)) {
|
||||
@@ -203,6 +230,7 @@ router.get("/", async (req, res) => {
|
||||
res.render("index", {
|
||||
page_title: app_conf.name,
|
||||
program: app_conf.program,
|
||||
app_url: app_conf.app_url,
|
||||
css_path: path.join(app_conf.paths.css.web, "stylesheet.css"),
|
||||
js_path: path.join(app_conf.paths.js.web, "index.js"),
|
||||
map_name_msg: (selected_map_name != "" ? "Using: " + selected_map_name : ""),
|
||||
@@ -218,10 +246,12 @@ router.get("/", async (req, res) => {
|
||||
}
|
||||
});
|
||||
|
||||
// About page
|
||||
router.get("/about", (req, res) => {
|
||||
res.render("about", {
|
||||
page_title: app_conf.name,
|
||||
program: app_conf.program,
|
||||
app_url: app_conf.app_url,
|
||||
css_path: path.join(app_conf.paths.css.web, "stylesheet.css"),
|
||||
version: app_conf.version
|
||||
});
|
||||
|
||||
@@ -9,18 +9,11 @@ router.use(app_conf.paths.js.web, express.static(path.join(path.dirname(require.
|
||||
router.use(app_conf.paths.chartjs.web, express.static(path.join(path.dirname(require.main.filename), app_conf.paths.chartjs.src)));
|
||||
|
||||
/*
|
||||
* Main endpoint - might implement authentication step here...
|
||||
* Main endpoint - authentication happens here
|
||||
* Rewritting the whole url to fix logout bug
|
||||
*/
|
||||
router.get("/", (req, res) => {
|
||||
res.render("auth", {
|
||||
page_title: app_conf.name,
|
||||
|
||||
program: app_conf.program,
|
||||
css_path: path.join(app_conf.paths.css.web, "stylesheet.css"),
|
||||
protocol: app_conf.protocol,
|
||||
host: app_conf.host,
|
||||
port: app_conf.port
|
||||
});
|
||||
res.redirect(`${app_conf.protocol}://${app_conf.host}:${app_conf.port}${app_conf.app_url}`);
|
||||
});
|
||||
|
||||
module.exports = router;
|
||||
+27
-3
@@ -5,10 +5,24 @@ const uuid = require("uuid");
|
||||
const map_conf = require("../config/map.conf");
|
||||
const logger = require("./logger.util");
|
||||
|
||||
// Returns map filename or ""
|
||||
function getSelectedMap() {
|
||||
var selected_map_name = "";
|
||||
|
||||
// Check if a map has been selected to show it
|
||||
if (fs.existsSync(path.join(path.dirname(require.main.filename), map_conf.map_storage_path, "selected"))) {
|
||||
selected_map_name = fs.readFileSync(path.join(path.dirname(require.main.filename), map_conf.map_storage_path, "selected"), "utf-8");
|
||||
}
|
||||
|
||||
return(selected_map_name);
|
||||
}
|
||||
|
||||
// Creates new map
|
||||
async function addMap(filename, meta, throttle, motor) {
|
||||
var total = "";
|
||||
var map = [[[]]];
|
||||
|
||||
// Get the new map metadata
|
||||
if (meta) {
|
||||
if ("name" in meta) {
|
||||
total += `#name:${meta["name"]}\n`;
|
||||
@@ -21,7 +35,9 @@ async function addMap(filename, meta, throttle, motor) {
|
||||
}
|
||||
}
|
||||
|
||||
// Check if the required data has been received
|
||||
if (throttle && motor && ("0" in motor) && ("1" in motor)) {
|
||||
// Creating csv and storing it
|
||||
const throttle_values = Object.values(throttle);
|
||||
const current_values = Object.values(motor["0"]);
|
||||
const brake_values = Object.values(motor["1"]);
|
||||
@@ -39,10 +55,13 @@ async function addMap(filename, meta, throttle, motor) {
|
||||
}
|
||||
}
|
||||
|
||||
// Update current map file
|
||||
async function updateMap(filename, meta, throttle, motor) {
|
||||
// Get merged map comments and data
|
||||
var total = await generateComments(filename, meta);
|
||||
const map = await generateData(filename, throttle, motor);
|
||||
|
||||
// Create and store file
|
||||
try {
|
||||
await csv.writeToString(map).then(data => total += data);
|
||||
fs.writeFileSync(path.join(path.dirname(require.main.filename), map_conf.map_storage_path, filename), total);
|
||||
@@ -55,6 +74,7 @@ async function updateMap(filename, meta, throttle, motor) {
|
||||
}
|
||||
}
|
||||
|
||||
// Merges data from a stored map and a new map
|
||||
async function generateData(filename, throttle, motor) {
|
||||
const map = await parseMap(filename, 0);
|
||||
|
||||
@@ -80,6 +100,7 @@ async function generateData(filename, throttle, motor) {
|
||||
return map;
|
||||
}
|
||||
|
||||
// Merges comments from stored map and new map
|
||||
async function generateComments(filename, meta) {
|
||||
const comments = await parseMapJson(filename, 1);
|
||||
var comment_string = "";
|
||||
@@ -105,6 +126,7 @@ async function generateComments(filename, meta) {
|
||||
return comment_string;
|
||||
}
|
||||
|
||||
// Check if a map exists
|
||||
function mapExists(filename) {
|
||||
if (path.extname(filename) != ".csv") {
|
||||
return false;
|
||||
@@ -112,7 +134,7 @@ function mapExists(filename) {
|
||||
return fs.existsSync(path.join(path.dirname(require.main.filename), map_conf.map_storage_path, filename));
|
||||
}
|
||||
|
||||
// mode: comments 1 or data 0
|
||||
// Parse a map and returns it as array. On 1 returns comments on 0 returns data
|
||||
function parseMap(filename, mode) {
|
||||
var result = [];
|
||||
|
||||
@@ -131,6 +153,7 @@ function parseMap(filename, mode) {
|
||||
});
|
||||
}
|
||||
|
||||
// Parse map data as JSON
|
||||
async function parseMapJson(filename, mode) {
|
||||
const map = await parseMap(filename, mode);
|
||||
var json_map = {};
|
||||
@@ -150,8 +173,8 @@ async function parseMapJson(filename, mode) {
|
||||
return json_map
|
||||
}
|
||||
|
||||
// Get available map names in storage directory
|
||||
async function getAvailableMaps() {
|
||||
// path in app_conf
|
||||
var available_maps = {};
|
||||
|
||||
try {
|
||||
@@ -190,5 +213,6 @@ module.exports = {
|
||||
parseMapJson,
|
||||
mapExists,
|
||||
updateMap,
|
||||
addMap
|
||||
addMap,
|
||||
getSelectedMap
|
||||
};
|
||||
@@ -0,0 +1,65 @@
|
||||
const net = require("net");
|
||||
const fs = require("fs");
|
||||
const path = require("path");
|
||||
const map_conf = require("../config/map.conf");
|
||||
const map = require("../utils/map.util");
|
||||
const logger = require("../utils/logger.util");
|
||||
const can_conf = require("../config/can.conf")
|
||||
|
||||
const SOCKET_PATH = path.join(path.dirname(require.main.filename), map_conf.map_storage_path, can_conf.socket_filename);
|
||||
var clients = [];
|
||||
|
||||
if (fs.existsSync(SOCKET_PATH)) {
|
||||
logger.info("Removing existing map socket...");
|
||||
fs.unlinkSync(SOCKET_PATH);
|
||||
}
|
||||
|
||||
function broadcastMap(filename) {
|
||||
logger.info("Map updated. Broadcasting new filename to map socket...");
|
||||
|
||||
let message = JSON.stringify({ "map": filename });
|
||||
|
||||
for (c of clients) {
|
||||
c.write(message);
|
||||
}
|
||||
}
|
||||
|
||||
function closeSocket() {
|
||||
for (c of clients) {
|
||||
c.end();
|
||||
}
|
||||
|
||||
logger.info("Closing map socket.");
|
||||
server.close();
|
||||
}
|
||||
|
||||
const server = net.createServer((client) => {
|
||||
// send selected map
|
||||
logger.info("Client connected to map socket.");
|
||||
|
||||
var map_filename = map.getSelectedMap();
|
||||
if (map_filename === "") {
|
||||
map_filename = null;
|
||||
}
|
||||
|
||||
client.write(JSON.stringify({"map": map_filename}));
|
||||
|
||||
// client array
|
||||
clients.push(client);
|
||||
client.on("end", () => {
|
||||
logger.info("Client disconnected from map socket.");
|
||||
const index = clients.indexOf(client);
|
||||
if (index !== -1) {
|
||||
clients.splice(index, 1);
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
server.listen(SOCKET_PATH, () => {
|
||||
logger.info("Started map socket");
|
||||
});
|
||||
|
||||
module.exports = {
|
||||
broadcastMap,
|
||||
closeSocket
|
||||
}
|
||||
+1
-1
@@ -30,7 +30,7 @@
|
||||
style="font-size: 150%;">GitHub</a>
|
||||
</center>
|
||||
<br>
|
||||
<a href="/app"><span>🢀 </span>Return</a>
|
||||
<a href="<%= app_url %>"><span>🢀 </span>Return</a>
|
||||
</div>
|
||||
</body>
|
||||
|
||||
|
||||
+3
-3
@@ -16,7 +16,7 @@
|
||||
<script src="<%= js_path %>" defer></script>
|
||||
<script src="<%= chartjs %>"></script>
|
||||
<script defer>
|
||||
var steps = '<%= steps %>', max_rpm = '<%= max_rpm %>', max_throttle = '<%= max_throttle %>';
|
||||
var steps = '<%= steps %>', max_rpm = '<%= max_rpm %>', max_throttle = '<%= max_throttle %>', app_url = '<%= app_url %>';
|
||||
</script>
|
||||
</head>
|
||||
|
||||
@@ -55,12 +55,12 @@
|
||||
<table id="motor_table" style="text-align: center;"></table>
|
||||
</div>
|
||||
<div style="display: flex; flex-direction: row; justify-content: space-between;">
|
||||
<a href="/app"><span>🢀 </span>Return</a>
|
||||
<a href="<%= app_url %>"><span>🢀 </span>Return</a>
|
||||
<label id="commit" style="cursor: pointer;"><span>✅ </span>Commit</label>
|
||||
</div>
|
||||
</div>
|
||||
<div class="about_div">
|
||||
<center><a href="/app/about">About</label></center>
|
||||
<center><a href="<%= app_url %>/about">About</label></center>
|
||||
</div>
|
||||
</body>
|
||||
|
||||
|
||||
@@ -1,33 +0,0 @@
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
|
||||
<head>
|
||||
<title>
|
||||
<%= page_title %>
|
||||
</title>
|
||||
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=0" />
|
||||
<link rel="preconnect" href="https://fonts.googleapis.com">
|
||||
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
|
||||
<link
|
||||
href="https://fonts.googleapis.com/css2?family=Ubuntu:ital,wght@0,300;0,400;0,500;0,700;1,300;1,400;1,500;1,700&display=swap"
|
||||
rel="stylesheet">
|
||||
<link rel="stylesheet" href="<%= css_path %>">
|
||||
</head>
|
||||
|
||||
<body>
|
||||
<div class="control_div">
|
||||
<label
|
||||
style='font-family: "Ubuntu", sans-serif; font-weight: 500; font-style: normal; font-size: 200%;'>Centaurus
|
||||
Racing Team</label>
|
||||
</div>
|
||||
<div class="main_div"
|
||||
style="display: flex; flex-direction: column; justify-content: space-between; font-size: 150%; margin-top: 15px; margin-bottom: 15px;">
|
||||
<div style="display: flex; flex-direction: row; justify-content: space-evenly;">
|
||||
<label><%= page_title %> <%= program %></label>
|
||||
<a href="<%= protocol %>://<%= host %>:<%= port %>/app">Enter</a>
|
||||
</div>
|
||||
</div>
|
||||
</body>
|
||||
|
||||
</html>
|
||||
+3
-3
@@ -16,7 +16,7 @@
|
||||
<script type="module" src="<%= js_path %>" defer></script>
|
||||
<script src="<%= chartjs %>"></script>
|
||||
<script defer>
|
||||
var map = '<%- map %>', map_meta = '<%- map_meta %>', steps = '<%= steps %>', max_rpm = '<%= max_rpm %>', max_throttle = '<%= max_throttle %>';
|
||||
var map = '<%- map %>', map_meta = '<%- map_meta %>', steps = '<%= steps %>', max_rpm = '<%= max_rpm %>', max_throttle = '<%= max_throttle %>', app_url = '<%= app_url %>';
|
||||
</script>
|
||||
</head>
|
||||
|
||||
@@ -60,12 +60,12 @@
|
||||
<table id="motor_table" style="text-align: center;"></table>
|
||||
</div>
|
||||
<div style="display: flex; flex-direction: row; justify-content: space-between;">
|
||||
<a href="/app"><span>🢀 </span>Return</a>
|
||||
<a href="<%= app_url %>"><span>🢀 </span>Return</a>
|
||||
<label id="commit" style="cursor: pointer;"><span>✅ </span>Commit</label>
|
||||
</div>
|
||||
</div>
|
||||
<div class="about_div">
|
||||
<center><a href="/app/about">About</label></center>
|
||||
<center><a href="<%= app_url %>/about">About</label></center>
|
||||
</div>
|
||||
</body>
|
||||
|
||||
|
||||
+4
-1
@@ -14,6 +14,9 @@
|
||||
rel="stylesheet">
|
||||
<link rel="stylesheet" href="<%= css_path %>">
|
||||
<script src="<%= js_path %>" defer></script>
|
||||
<script defer>
|
||||
var app_url = '<%= app_url %>';
|
||||
</script>
|
||||
</head>
|
||||
|
||||
<body>
|
||||
@@ -38,7 +41,7 @@
|
||||
<%= error_message %>
|
||||
</label>
|
||||
<br>
|
||||
<a href="/app"><span>🢀 </span>Return</a>
|
||||
<a href="<%= app_url %>"><span>🢀 </span>Return</a>
|
||||
</div>
|
||||
</body>
|
||||
|
||||
|
||||
+4
-1
@@ -14,6 +14,9 @@
|
||||
rel="stylesheet">
|
||||
<link rel="stylesheet" href="<%= css_path %>">
|
||||
<script src="<%= js_path %>" defer></script>
|
||||
<script defer>
|
||||
var app_url = '<%= app_url %>';
|
||||
</script>
|
||||
</head>
|
||||
|
||||
<body>
|
||||
@@ -47,7 +50,7 @@
|
||||
</table>
|
||||
</div>
|
||||
<div class="about_div">
|
||||
<center><a href="/app/about">About</label></center>
|
||||
<center><a href="<%= app_url %>/about">About</label></center>
|
||||
</div>
|
||||
</body>
|
||||
|
||||
|
||||
@@ -1,22 +1,28 @@
|
||||
const can = require("socketcan");
|
||||
const csv = require("fast-csv");
|
||||
const fs = require("fs");
|
||||
const net = require('net');
|
||||
|
||||
const can_conf = require("./app/config/can.conf");
|
||||
const map_conf = require("./app/config/map.conf");
|
||||
const path = require("path");
|
||||
|
||||
const SOCKET_PATH = path.join(__dirname, map_conf.map_storage_path, can_conf.socket_filename);
|
||||
|
||||
var map_rpm = [];
|
||||
var map_throttle = [];
|
||||
|
||||
var loaded_map_name = "";
|
||||
var loaded_map_name = null;
|
||||
var loaded_map_data = [];
|
||||
|
||||
var throttle_output = 0;
|
||||
var ERPM = 0;
|
||||
|
||||
var enabled = false;
|
||||
|
||||
var channel = can.createRawChannel(can_conf.network_id, true);
|
||||
|
||||
// Some test messages...
|
||||
// 404#0000245E00710186
|
||||
// 019#02
|
||||
// 050#9702
|
||||
@@ -26,13 +32,14 @@ const brake_current_id = (0x02 << 5) | can_conf.controller.id;
|
||||
const erpm_id = (0x20 << 5) | can_conf.controller.id;
|
||||
|
||||
function parseMap(filename) {
|
||||
loaded_map_data = [];
|
||||
let name = "";
|
||||
let map = [];
|
||||
|
||||
return new Promise((resolve, reject) => {
|
||||
csv.parseFile(`app/storage/${filename}`, { comment: "#" })
|
||||
csv.parseFile((filename), { comment: "#" })
|
||||
.on('error', error => reject(error))
|
||||
.on('data', row => loaded_map_data.push(row))
|
||||
.on('end', () => { loaded_map_name = filename; resolve() });
|
||||
.on('data', row => map.push(row))
|
||||
.on('end', () => { name = filename; resolve([name, map]) });
|
||||
});
|
||||
}
|
||||
|
||||
@@ -65,85 +72,98 @@ function getMapIndex(array, input) {
|
||||
return Math.abs(array[left] - input) < Math.abs(array[right] - input) ? left : right;
|
||||
}
|
||||
|
||||
function connect() {
|
||||
console.log("Connecting...");
|
||||
if (fs.existsSync(SOCKET_PATH)) {
|
||||
const client = net.createConnection(SOCKET_PATH, () => {
|
||||
console.log("Connected");
|
||||
});
|
||||
|
||||
client.on("data", async (data) => {
|
||||
let enabled_map_name = JSON.parse(data)["map"];
|
||||
console.log(`Received: ${enabled_map_name}`);
|
||||
if (enabled_map_name === null) {
|
||||
console.log("Purging memory");
|
||||
loaded_map_name = null;
|
||||
loaded_map_data = [];
|
||||
} else if (enabled_map_name != loaded_map_name) {
|
||||
console.log("Parsing map");
|
||||
[loaded_map_name, loaded_map_data] = await parseMap(path.join(__dirname, map_conf.map_storage_path, enabled_map_name));
|
||||
}
|
||||
});
|
||||
|
||||
client.on("end", () => {
|
||||
console.log("Disconnected");
|
||||
setTimeout(connect, can_conf.socket_connect_wait);
|
||||
});
|
||||
|
||||
client.on("error", (err) => {
|
||||
console.log(`Error: ${err.message}`);
|
||||
setTimeout(connect, can_conf.socket_connect_wait);
|
||||
});
|
||||
|
||||
} else {
|
||||
setTimeout(connect, can_conf.socket_connect_wait);
|
||||
}
|
||||
}
|
||||
|
||||
(async () => {
|
||||
for (let i = 0; i <= map_conf.steps; i++) {
|
||||
map_rpm[i] = i * (map_conf.max_rpm / map_conf.steps);
|
||||
map_throttle[i] = i * (map_conf.max_throttle / map_conf.steps);
|
||||
}
|
||||
|
||||
if (fs.existsSync(map_conf.selected_map_path)) {
|
||||
const enabled_map_name = fs.readFileSync(map_conf.selected_map_path);
|
||||
|
||||
if (enabled_map_name != "") {
|
||||
if (loaded_map_name != enabled_map_name) {
|
||||
await parseMap(enabled_map_name);
|
||||
}
|
||||
}
|
||||
}
|
||||
connect();
|
||||
})();
|
||||
|
||||
channel.addListener("onMessage", async function (message) {
|
||||
switch (message.id) {
|
||||
case can_conf.selector.id:
|
||||
console.log("==INVOKE SELECTOR==");
|
||||
if (Buffer.compare(message.data, can_conf.selector.command) == 0) {
|
||||
console.log("enable");
|
||||
console.log("Enable")
|
||||
enabled = true;
|
||||
} else {
|
||||
console.log("disable");
|
||||
console.log("Disable");
|
||||
enabled = false;
|
||||
}
|
||||
|
||||
break;
|
||||
case can_conf.apps_id:
|
||||
console.log("==INVOKE APPS==");
|
||||
const apps_percentage = ((message.data[1] << 8) | message.data[0]) / 1000;
|
||||
var max_current = 0;
|
||||
throttle_output = 0;
|
||||
|
||||
if (loaded_map_name !== null) {
|
||||
throttle_output = loaded_map_data[getMapIndex(map_throttle, apps_percentage)][2];
|
||||
console.log(throttle_output);
|
||||
|
||||
break;
|
||||
case erpm_id:
|
||||
console.log("==INVOKE ERPM==");
|
||||
if (enabled) {
|
||||
console.log("enabled");
|
||||
if (fs.existsSync(map_conf.selected_map_path)) {
|
||||
const enabled_map_name = fs.readFileSync(map_conf.selected_map_path);
|
||||
|
||||
if (enabled_map_name != "") {
|
||||
console.log("map selected");
|
||||
if (loaded_map_name != enabled_map_name) {
|
||||
await parseMap(enabled_map_name);
|
||||
max_current = loaded_map_data[getMapIndex(map_rpm, ERPM / can_conf.motor_poles)][(throttle_output > 0) ? 0 : 1];
|
||||
}
|
||||
|
||||
const ERPM = message.data[0] << 3 * 8 | message.data[1] << 2 * 8 | message.data[2] << 8 | message.data[3];
|
||||
|
||||
let max_current = loaded_map_data[getMapIndex(map_rpm, ERPM / can_conf.motor_poles)][(throttle_output > 0) ? 0 : 1];
|
||||
let current = throttle_output * max_current * 10;
|
||||
console.log(max_current);
|
||||
console.log(current);
|
||||
channel.send({
|
||||
id: (throttle_output > 0) ? current_id : brake_current_id,
|
||||
ext: false,
|
||||
data: Buffer.from([(current >> 8) & 0xFF, current & 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF])
|
||||
});
|
||||
} else {
|
||||
console.log("map not selected");
|
||||
channel.send({
|
||||
id: brake_current_id,
|
||||
ext: false,
|
||||
data: Buffer.from([0, 0, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF])
|
||||
});
|
||||
}
|
||||
} else {
|
||||
channel.send({
|
||||
id: brake_current_id,
|
||||
ext: false,
|
||||
data: Buffer.from([0, 0, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF])
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
break;
|
||||
case erpm_id:
|
||||
if ((enabled == true) && (loaded_map_name !== null)) {
|
||||
ERPM = message.data[0] << 3 * 8 | message.data[1] << 2 * 8 | message.data[2] << 8 | message.data[3];
|
||||
|
||||
let max_current = loaded_map_data[getMapIndex(map_rpm, ERPM / can_conf.motor_poles)][(throttle_output > 0) ? 0 : 1];
|
||||
let current = throttle_output * max_current * 10;
|
||||
channel.send({
|
||||
id: (throttle_output > 0) ? current_id : brake_current_id,
|
||||
ext: false,
|
||||
data: Buffer.from([(current >> 8) & 0xFF, current & 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF])
|
||||
});
|
||||
} else if ((enabled == true) && (loaded_map_name === null)) {
|
||||
channel.send({
|
||||
id: brake_current_id,
|
||||
ext: false,
|
||||
data: Buffer.from([0, 0, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF])
|
||||
});
|
||||
}
|
||||
break;
|
||||
default: {
|
||||
break;
|
||||
|
||||
Generated
+1
-345
@@ -4,14 +4,13 @@
|
||||
"requires": true,
|
||||
"packages": {
|
||||
"": {
|
||||
"name": "throttle_motor_mapping",
|
||||
"dependencies": {
|
||||
"better-sqlite3": "^11.10.0",
|
||||
"chart.js": "^4.4.9",
|
||||
"ejs": "^3.1.10",
|
||||
"express": "^5.1.0",
|
||||
"express-basic-auth": "^1.2.1",
|
||||
"express-fileupload": "^1.5.1",
|
||||
"expressjs": "^1.0.1",
|
||||
"fast-csv": "^5.0.2",
|
||||
"socketcan": "^4.0.6",
|
||||
"uuid": "^11.1.0",
|
||||
@@ -195,25 +194,6 @@
|
||||
"resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz",
|
||||
"integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw=="
|
||||
},
|
||||
"node_modules/base64-js": {
|
||||
"version": "1.5.1",
|
||||
"resolved": "https://registry.npmjs.org/base64-js/-/base64-js-1.5.1.tgz",
|
||||
"integrity": "sha512-AKpaYlHn8t4SVbOHCy+b5+KKgvR4vrsD8vbvrbiQJps7fKDTkjkDry6ji0rUJjC0kzbNePLwzxq8iypo41qeWA==",
|
||||
"funding": [
|
||||
{
|
||||
"type": "github",
|
||||
"url": "https://github.com/sponsors/feross"
|
||||
},
|
||||
{
|
||||
"type": "patreon",
|
||||
"url": "https://www.patreon.com/feross"
|
||||
},
|
||||
{
|
||||
"type": "consulting",
|
||||
"url": "https://feross.org/support"
|
||||
}
|
||||
]
|
||||
},
|
||||
"node_modules/basic-auth": {
|
||||
"version": "2.0.1",
|
||||
"resolved": "https://registry.npmjs.org/basic-auth/-/basic-auth-2.0.1.tgz",
|
||||
@@ -230,35 +210,6 @@
|
||||
"resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz",
|
||||
"integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g=="
|
||||
},
|
||||
"node_modules/better-sqlite3": {
|
||||
"version": "11.10.0",
|
||||
"resolved": "https://registry.npmjs.org/better-sqlite3/-/better-sqlite3-11.10.0.tgz",
|
||||
"integrity": "sha512-EwhOpyXiOEL/lKzHz9AW1msWFNzGc/z+LzeB3/jnFJpxu+th2yqvzsSWas1v9jgs9+xiXJcD5A8CJxAG2TaghQ==",
|
||||
"hasInstallScript": true,
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"bindings": "^1.5.0",
|
||||
"prebuild-install": "^7.1.1"
|
||||
}
|
||||
},
|
||||
"node_modules/bindings": {
|
||||
"version": "1.5.0",
|
||||
"resolved": "https://registry.npmjs.org/bindings/-/bindings-1.5.0.tgz",
|
||||
"integrity": "sha512-p2q/t/mhvuOj/UeLlV6566GD/guowlr0hHxClI0W9m7MWYkL1F0hLo+0Aexs9HSPCtR1SXQ0TD3MMKrXZajbiQ==",
|
||||
"dependencies": {
|
||||
"file-uri-to-path": "1.0.0"
|
||||
}
|
||||
},
|
||||
"node_modules/bl": {
|
||||
"version": "4.1.0",
|
||||
"resolved": "https://registry.npmjs.org/bl/-/bl-4.1.0.tgz",
|
||||
"integrity": "sha512-1W07cM9gS6DcLperZfFSj+bWLtaPGSOHWhPiGzXmvVJbRLdG82sH/Kn8EtW1VqWVA54AKf2h5k5BbnIbwF3h6w==",
|
||||
"dependencies": {
|
||||
"buffer": "^5.5.0",
|
||||
"inherits": "^2.0.4",
|
||||
"readable-stream": "^3.4.0"
|
||||
}
|
||||
},
|
||||
"node_modules/body-parser": {
|
||||
"version": "2.2.0",
|
||||
"resolved": "https://registry.npmjs.org/body-parser/-/body-parser-2.2.0.tgz",
|
||||
@@ -286,29 +237,6 @@
|
||||
"balanced-match": "^1.0.0"
|
||||
}
|
||||
},
|
||||
"node_modules/buffer": {
|
||||
"version": "5.7.1",
|
||||
"resolved": "https://registry.npmjs.org/buffer/-/buffer-5.7.1.tgz",
|
||||
"integrity": "sha512-EHcyIPBQ4BSGlvjB16k5KgAJ27CIsHY/2JBmCRReo48y9rQ3MaUzWX3KVlBa4U7MyX02HdVj0K7C3WaB3ju7FQ==",
|
||||
"funding": [
|
||||
{
|
||||
"type": "github",
|
||||
"url": "https://github.com/sponsors/feross"
|
||||
},
|
||||
{
|
||||
"type": "patreon",
|
||||
"url": "https://www.patreon.com/feross"
|
||||
},
|
||||
{
|
||||
"type": "consulting",
|
||||
"url": "https://feross.org/support"
|
||||
}
|
||||
],
|
||||
"dependencies": {
|
||||
"base64-js": "^1.3.1",
|
||||
"ieee754": "^1.1.13"
|
||||
}
|
||||
},
|
||||
"node_modules/busboy": {
|
||||
"version": "1.6.0",
|
||||
"resolved": "https://registry.npmjs.org/busboy/-/busboy-1.6.0.tgz",
|
||||
@@ -572,28 +500,6 @@
|
||||
}
|
||||
}
|
||||
},
|
||||
"node_modules/decompress-response": {
|
||||
"version": "6.0.0",
|
||||
"resolved": "https://registry.npmjs.org/decompress-response/-/decompress-response-6.0.0.tgz",
|
||||
"integrity": "sha512-aW35yZM6Bb/4oJlZncMH2LCoZtJXTRxES17vE3hoRiowU2kWHaJKFkSBDnDR+cm9J+9QhXmREyIfv0pji9ejCQ==",
|
||||
"dependencies": {
|
||||
"mimic-response": "^3.1.0"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=10"
|
||||
},
|
||||
"funding": {
|
||||
"url": "https://github.com/sponsors/sindresorhus"
|
||||
}
|
||||
},
|
||||
"node_modules/deep-extend": {
|
||||
"version": "0.6.0",
|
||||
"resolved": "https://registry.npmjs.org/deep-extend/-/deep-extend-0.6.0.tgz",
|
||||
"integrity": "sha512-LOHxIOaPYdHlJRtCQfDIVZtfw/ufM8+rVj649RIHzcm/vGwQRXFt6OPqIFWsm2XEMrNIEtWR64sY1LEKD2vAOA==",
|
||||
"engines": {
|
||||
"node": ">=4.0.0"
|
||||
}
|
||||
},
|
||||
"node_modules/depd": {
|
||||
"version": "2.0.0",
|
||||
"resolved": "https://registry.npmjs.org/depd/-/depd-2.0.0.tgz",
|
||||
@@ -602,14 +508,6 @@
|
||||
"node": ">= 0.8"
|
||||
}
|
||||
},
|
||||
"node_modules/detect-libc": {
|
||||
"version": "2.0.4",
|
||||
"resolved": "https://registry.npmjs.org/detect-libc/-/detect-libc-2.0.4.tgz",
|
||||
"integrity": "sha512-3UDv+G9CsCKO1WKMGw9fwq/SWJYbI0c5Y7LU1AXYoDdbhE2AHQ6N6Nb34sG8Fj7T5APy8qXDCKuuIHd1BR0tVA==",
|
||||
"engines": {
|
||||
"node": ">=8"
|
||||
}
|
||||
},
|
||||
"node_modules/dunder-proto": {
|
||||
"version": "1.0.1",
|
||||
"resolved": "https://registry.npmjs.org/dunder-proto/-/dunder-proto-1.0.1.tgz",
|
||||
@@ -675,14 +573,6 @@
|
||||
"iconv-lite": "^0.6.2"
|
||||
}
|
||||
},
|
||||
"node_modules/end-of-stream": {
|
||||
"version": "1.4.4",
|
||||
"resolved": "https://registry.npmjs.org/end-of-stream/-/end-of-stream-1.4.4.tgz",
|
||||
"integrity": "sha512-+uw1inIHVPQoaVuHzRyXd21icM+cnt4CzD5rW+NC1wjOUSTOs+Te7FOv7AhN7vS9x/oIyhLP5PR1H+phQAHu5Q==",
|
||||
"dependencies": {
|
||||
"once": "^1.4.0"
|
||||
}
|
||||
},
|
||||
"node_modules/env-paths": {
|
||||
"version": "2.2.1",
|
||||
"resolved": "https://registry.npmjs.org/env-paths/-/env-paths-2.2.1.tgz",
|
||||
@@ -736,14 +626,6 @@
|
||||
"node": ">= 0.6"
|
||||
}
|
||||
},
|
||||
"node_modules/expand-template": {
|
||||
"version": "2.0.3",
|
||||
"resolved": "https://registry.npmjs.org/expand-template/-/expand-template-2.0.3.tgz",
|
||||
"integrity": "sha512-XYfuKMvj4O35f/pOXLObndIRvyQ+/+6AhODh+OKWj9S9498pHHn/IMszH+gt0fBCRWMNfk1ZSp5x3AifmnI2vg==",
|
||||
"engines": {
|
||||
"node": ">=6"
|
||||
}
|
||||
},
|
||||
"node_modules/exponential-backoff": {
|
||||
"version": "3.1.2",
|
||||
"resolved": "https://registry.npmjs.org/exponential-backoff/-/exponential-backoff-3.1.2.tgz",
|
||||
@@ -809,12 +691,6 @@
|
||||
"node": ">=12.0.0"
|
||||
}
|
||||
},
|
||||
"node_modules/expressjs": {
|
||||
"version": "1.0.1",
|
||||
"resolved": "https://registry.npmjs.org/expressjs/-/expressjs-1.0.1.tgz",
|
||||
"integrity": "sha512-eFnQ5bMJxTZ29XwRJPV8ee/OURBBMS6Fm+b5rvMMEyz6u2IxPEh2SRzMZt9WvgnV+SMLmnzkALE1DnGG1HxJCw==",
|
||||
"deprecated": "This is a typosquat on the popular Express package. This is not maintained nor is the original Express package."
|
||||
},
|
||||
"node_modules/fast-csv": {
|
||||
"version": "5.0.2",
|
||||
"resolved": "https://registry.npmjs.org/fast-csv/-/fast-csv-5.0.2.tgz",
|
||||
@@ -846,11 +722,6 @@
|
||||
"resolved": "https://registry.npmjs.org/fecha/-/fecha-4.2.3.tgz",
|
||||
"integrity": "sha512-OP2IUU6HeYKJi3i0z4A19kHMQoLVs4Hc+DPqqxI2h/DPZHTm/vjsfC6P0b4jCMy14XizLBqvndQ+UilD7707Jw=="
|
||||
},
|
||||
"node_modules/file-uri-to-path": {
|
||||
"version": "1.0.0",
|
||||
"resolved": "https://registry.npmjs.org/file-uri-to-path/-/file-uri-to-path-1.0.0.tgz",
|
||||
"integrity": "sha512-0Zt+s3L7Vf1biwWZ29aARiVYLx7iMGnEUl9x33fbB/j3jR81u/O2LbqK+Bm1CDSNDKVtJ/YjwY7TUd5SkeLQLw=="
|
||||
},
|
||||
"node_modules/filelist": {
|
||||
"version": "1.0.4",
|
||||
"resolved": "https://registry.npmjs.org/filelist/-/filelist-1.0.4.tgz",
|
||||
@@ -924,11 +795,6 @@
|
||||
"node": ">= 0.8"
|
||||
}
|
||||
},
|
||||
"node_modules/fs-constants": {
|
||||
"version": "1.0.0",
|
||||
"resolved": "https://registry.npmjs.org/fs-constants/-/fs-constants-1.0.0.tgz",
|
||||
"integrity": "sha512-y6OAwoSIf7FyjMIv94u+b5rdheZEjzR63GTyZJm5qh4Bi+2YgwLCcI/fPFZkL5PSixOt6ZNKm+w+Hfp/Bciwow=="
|
||||
},
|
||||
"node_modules/fs-minipass": {
|
||||
"version": "3.0.3",
|
||||
"resolved": "https://registry.npmjs.org/fs-minipass/-/fs-minipass-3.0.3.tgz",
|
||||
@@ -983,11 +849,6 @@
|
||||
"node": ">= 0.4"
|
||||
}
|
||||
},
|
||||
"node_modules/github-from-package": {
|
||||
"version": "0.0.0",
|
||||
"resolved": "https://registry.npmjs.org/github-from-package/-/github-from-package-0.0.0.tgz",
|
||||
"integrity": "sha512-SyHy3T1v2NUXn29OsWdxmK6RwHD+vkj3v8en8AOBZ1wBQ/hCAQ5bAQTD02kW4W9tUp/3Qh6J8r9EvntiyCmOOw=="
|
||||
},
|
||||
"node_modules/glob": {
|
||||
"version": "10.4.5",
|
||||
"resolved": "https://registry.npmjs.org/glob/-/glob-10.4.5.tgz",
|
||||
@@ -1109,25 +970,6 @@
|
||||
"node": ">=0.10.0"
|
||||
}
|
||||
},
|
||||
"node_modules/ieee754": {
|
||||
"version": "1.2.1",
|
||||
"resolved": "https://registry.npmjs.org/ieee754/-/ieee754-1.2.1.tgz",
|
||||
"integrity": "sha512-dcyqhDvX1C46lXZcVqCpK+FtMRQVdIMN6/Df5js2zouUsqG7I6sFxitIC+7KYK29KdXOLHdu9zL4sFnoVQnqaA==",
|
||||
"funding": [
|
||||
{
|
||||
"type": "github",
|
||||
"url": "https://github.com/sponsors/feross"
|
||||
},
|
||||
{
|
||||
"type": "patreon",
|
||||
"url": "https://www.patreon.com/feross"
|
||||
},
|
||||
{
|
||||
"type": "consulting",
|
||||
"url": "https://feross.org/support"
|
||||
}
|
||||
]
|
||||
},
|
||||
"node_modules/imurmurhash": {
|
||||
"version": "0.1.4",
|
||||
"resolved": "https://registry.npmjs.org/imurmurhash/-/imurmurhash-0.1.4.tgz",
|
||||
@@ -1141,11 +983,6 @@
|
||||
"resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz",
|
||||
"integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ=="
|
||||
},
|
||||
"node_modules/ini": {
|
||||
"version": "1.3.8",
|
||||
"resolved": "https://registry.npmjs.org/ini/-/ini-1.3.8.tgz",
|
||||
"integrity": "sha512-JV/yugV2uzW5iMRSiZAyDtQd+nxtUnjeLt0acNdw98kKLrvuRVyB80tsREOE7yvGVgalhZ6RNXCmEHkUKBKxew=="
|
||||
},
|
||||
"node_modules/ip-address": {
|
||||
"version": "9.0.5",
|
||||
"resolved": "https://registry.npmjs.org/ip-address/-/ip-address-9.0.5.tgz",
|
||||
@@ -1404,17 +1241,6 @@
|
||||
"node": ">= 0.6"
|
||||
}
|
||||
},
|
||||
"node_modules/mimic-response": {
|
||||
"version": "3.1.0",
|
||||
"resolved": "https://registry.npmjs.org/mimic-response/-/mimic-response-3.1.0.tgz",
|
||||
"integrity": "sha512-z0yWI+4FDrrweS8Zmt4Ej5HdJmky15+L2e6Wgn3+iK5fWzb6T3fhNFq2+MeTRb064c6Wr4N/wv0DzQTjNzHNGQ==",
|
||||
"engines": {
|
||||
"node": ">=10"
|
||||
},
|
||||
"funding": {
|
||||
"url": "https://github.com/sponsors/sindresorhus"
|
||||
}
|
||||
},
|
||||
"node_modules/minimatch": {
|
||||
"version": "9.0.5",
|
||||
"resolved": "https://registry.npmjs.org/minimatch/-/minimatch-9.0.5.tgz",
|
||||
@@ -1429,14 +1255,6 @@
|
||||
"url": "https://github.com/sponsors/isaacs"
|
||||
}
|
||||
},
|
||||
"node_modules/minimist": {
|
||||
"version": "1.2.8",
|
||||
"resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.8.tgz",
|
||||
"integrity": "sha512-2yyAR8qBkN3YuheJanUpWC5U3bb5osDywNB8RzDVlDwDHbocAJveqqj1u8+SVD7jkWT4yvsHCpWqqWqAxb0zCA==",
|
||||
"funding": {
|
||||
"url": "https://github.com/sponsors/ljharb"
|
||||
}
|
||||
},
|
||||
"node_modules/minipass": {
|
||||
"version": "7.1.2",
|
||||
"resolved": "https://registry.npmjs.org/minipass/-/minipass-7.1.2.tgz",
|
||||
@@ -1578,11 +1396,6 @@
|
||||
"url": "https://github.com/sponsors/isaacs"
|
||||
}
|
||||
},
|
||||
"node_modules/mkdirp-classic": {
|
||||
"version": "0.5.3",
|
||||
"resolved": "https://registry.npmjs.org/mkdirp-classic/-/mkdirp-classic-0.5.3.tgz",
|
||||
"integrity": "sha512-gKLcREMhtuZRwRAfqP3RFW+TK4JqApVBtOIftVgjuABpAtpxhPGaDcfvbhNvD0B8iD1oUr/txX35NjcaY6Ns/A=="
|
||||
},
|
||||
"node_modules/ms": {
|
||||
"version": "2.1.3",
|
||||
"resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz",
|
||||
@@ -1593,11 +1406,6 @@
|
||||
"resolved": "https://registry.npmjs.org/nan/-/nan-2.22.2.tgz",
|
||||
"integrity": "sha512-DANghxFkS1plDdRsX0X9pm0Z6SJNN6gBdtXfanwoZ8hooC5gosGFSBGRYHUVPz1asKA/kMRqDRdHrluZ61SpBQ=="
|
||||
},
|
||||
"node_modules/napi-build-utils": {
|
||||
"version": "2.0.0",
|
||||
"resolved": "https://registry.npmjs.org/napi-build-utils/-/napi-build-utils-2.0.0.tgz",
|
||||
"integrity": "sha512-GEbrYkbfF7MoNaoh2iGG84Mnf/WZfB0GdGEsM8wz7Expx/LlWf5U8t9nvJKXSp3qr5IsEbK04cBGhol/KwOsWA=="
|
||||
},
|
||||
"node_modules/negotiator": {
|
||||
"version": "1.0.0",
|
||||
"resolved": "https://registry.npmjs.org/negotiator/-/negotiator-1.0.0.tgz",
|
||||
@@ -1606,17 +1414,6 @@
|
||||
"node": ">= 0.6"
|
||||
}
|
||||
},
|
||||
"node_modules/node-abi": {
|
||||
"version": "3.75.0",
|
||||
"resolved": "https://registry.npmjs.org/node-abi/-/node-abi-3.75.0.tgz",
|
||||
"integrity": "sha512-OhYaY5sDsIka7H7AtijtI9jwGYLyl29eQn/W623DiN/MIv5sUqc4g7BIDThX+gb7di9f6xK02nkp8sdfFWZLTg==",
|
||||
"dependencies": {
|
||||
"semver": "^7.3.5"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=10"
|
||||
}
|
||||
},
|
||||
"node_modules/node-gyp": {
|
||||
"version": "11.2.0",
|
||||
"resolved": "https://registry.npmjs.org/node-gyp/-/node-gyp-11.2.0.tgz",
|
||||
@@ -1758,31 +1555,6 @@
|
||||
"url": "https://github.com/sponsors/jonschlinkert"
|
||||
}
|
||||
},
|
||||
"node_modules/prebuild-install": {
|
||||
"version": "7.1.3",
|
||||
"resolved": "https://registry.npmjs.org/prebuild-install/-/prebuild-install-7.1.3.tgz",
|
||||
"integrity": "sha512-8Mf2cbV7x1cXPUILADGI3wuhfqWvtiLA1iclTDbFRZkgRQS0NqsPZphna9V+HyTEadheuPmjaJMsbzKQFOzLug==",
|
||||
"dependencies": {
|
||||
"detect-libc": "^2.0.0",
|
||||
"expand-template": "^2.0.3",
|
||||
"github-from-package": "0.0.0",
|
||||
"minimist": "^1.2.3",
|
||||
"mkdirp-classic": "^0.5.3",
|
||||
"napi-build-utils": "^2.0.0",
|
||||
"node-abi": "^3.3.0",
|
||||
"pump": "^3.0.0",
|
||||
"rc": "^1.2.7",
|
||||
"simple-get": "^4.0.0",
|
||||
"tar-fs": "^2.0.0",
|
||||
"tunnel-agent": "^0.6.0"
|
||||
},
|
||||
"bin": {
|
||||
"prebuild-install": "bin.js"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=10"
|
||||
}
|
||||
},
|
||||
"node_modules/proc-log": {
|
||||
"version": "5.0.0",
|
||||
"resolved": "https://registry.npmjs.org/proc-log/-/proc-log-5.0.0.tgz",
|
||||
@@ -1815,15 +1587,6 @@
|
||||
"node": ">= 0.10"
|
||||
}
|
||||
},
|
||||
"node_modules/pump": {
|
||||
"version": "3.0.2",
|
||||
"resolved": "https://registry.npmjs.org/pump/-/pump-3.0.2.tgz",
|
||||
"integrity": "sha512-tUPXtzlGM8FE3P0ZL6DVs/3P58k9nk8/jZeQCurTJylQA8qFYzHFfhBJkuqyE0FifOsQ0uKWekiZ5g8wtr28cw==",
|
||||
"dependencies": {
|
||||
"end-of-stream": "^1.1.0",
|
||||
"once": "^1.3.1"
|
||||
}
|
||||
},
|
||||
"node_modules/qs": {
|
||||
"version": "6.14.0",
|
||||
"resolved": "https://registry.npmjs.org/qs/-/qs-6.14.0.tgz",
|
||||
@@ -1860,20 +1623,6 @@
|
||||
"node": ">= 0.8"
|
||||
}
|
||||
},
|
||||
"node_modules/rc": {
|
||||
"version": "1.2.8",
|
||||
"resolved": "https://registry.npmjs.org/rc/-/rc-1.2.8.tgz",
|
||||
"integrity": "sha512-y3bGgqKj3QBdxLbLkomlohkvsA8gdAiUQlSBJnBhfn+BPxg4bc62d8TcBW15wavDfgexCgccckhcZvywyQYPOw==",
|
||||
"dependencies": {
|
||||
"deep-extend": "^0.6.0",
|
||||
"ini": "~1.3.0",
|
||||
"minimist": "^1.2.0",
|
||||
"strip-json-comments": "~2.0.1"
|
||||
},
|
||||
"bin": {
|
||||
"rc": "cli.js"
|
||||
}
|
||||
},
|
||||
"node_modules/readable-stream": {
|
||||
"version": "3.6.2",
|
||||
"resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.2.tgz",
|
||||
@@ -2096,49 +1845,6 @@
|
||||
"url": "https://github.com/sponsors/isaacs"
|
||||
}
|
||||
},
|
||||
"node_modules/simple-concat": {
|
||||
"version": "1.0.1",
|
||||
"resolved": "https://registry.npmjs.org/simple-concat/-/simple-concat-1.0.1.tgz",
|
||||
"integrity": "sha512-cSFtAPtRhljv69IK0hTVZQ+OfE9nePi/rtJmw5UjHeVyVroEqJXP1sFztKUy1qU+xvz3u/sfYJLa947b7nAN2Q==",
|
||||
"funding": [
|
||||
{
|
||||
"type": "github",
|
||||
"url": "https://github.com/sponsors/feross"
|
||||
},
|
||||
{
|
||||
"type": "patreon",
|
||||
"url": "https://www.patreon.com/feross"
|
||||
},
|
||||
{
|
||||
"type": "consulting",
|
||||
"url": "https://feross.org/support"
|
||||
}
|
||||
]
|
||||
},
|
||||
"node_modules/simple-get": {
|
||||
"version": "4.0.1",
|
||||
"resolved": "https://registry.npmjs.org/simple-get/-/simple-get-4.0.1.tgz",
|
||||
"integrity": "sha512-brv7p5WgH0jmQJr1ZDDfKDOSeWWg+OVypG99A/5vYGPqJ6pxiaHLy8nxtFjBA7oMa01ebA9gfh1uMCFqOuXxvA==",
|
||||
"funding": [
|
||||
{
|
||||
"type": "github",
|
||||
"url": "https://github.com/sponsors/feross"
|
||||
},
|
||||
{
|
||||
"type": "patreon",
|
||||
"url": "https://www.patreon.com/feross"
|
||||
},
|
||||
{
|
||||
"type": "consulting",
|
||||
"url": "https://feross.org/support"
|
||||
}
|
||||
],
|
||||
"dependencies": {
|
||||
"decompress-response": "^6.0.0",
|
||||
"once": "^1.3.1",
|
||||
"simple-concat": "^1.0.0"
|
||||
}
|
||||
},
|
||||
"node_modules/simple-swizzle": {
|
||||
"version": "0.2.2",
|
||||
"resolved": "https://registry.npmjs.org/simple-swizzle/-/simple-swizzle-0.2.2.tgz",
|
||||
@@ -2332,14 +2038,6 @@
|
||||
"node": ">=8"
|
||||
}
|
||||
},
|
||||
"node_modules/strip-json-comments": {
|
||||
"version": "2.0.1",
|
||||
"resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-2.0.1.tgz",
|
||||
"integrity": "sha512-4gB8na07fecVVkOI6Rs4e7T6NOTki5EmL7TUduTs6bu3EdnSycntVJ4re8kgZA+wx9IueI2Y11bfbgwtzuE0KQ==",
|
||||
"engines": {
|
||||
"node": ">=0.10.0"
|
||||
}
|
||||
},
|
||||
"node_modules/supports-color": {
|
||||
"version": "7.2.0",
|
||||
"resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz",
|
||||
@@ -2368,37 +2066,6 @@
|
||||
"node": ">=18"
|
||||
}
|
||||
},
|
||||
"node_modules/tar-fs": {
|
||||
"version": "2.1.2",
|
||||
"resolved": "https://registry.npmjs.org/tar-fs/-/tar-fs-2.1.2.tgz",
|
||||
"integrity": "sha512-EsaAXwxmx8UB7FRKqeozqEPop69DXcmYwTQwXvyAPF352HJsPdkVhvTaDPYqfNgruveJIJy3TA2l+2zj8LJIJA==",
|
||||
"dependencies": {
|
||||
"chownr": "^1.1.1",
|
||||
"mkdirp-classic": "^0.5.2",
|
||||
"pump": "^3.0.0",
|
||||
"tar-stream": "^2.1.4"
|
||||
}
|
||||
},
|
||||
"node_modules/tar-fs/node_modules/chownr": {
|
||||
"version": "1.1.4",
|
||||
"resolved": "https://registry.npmjs.org/chownr/-/chownr-1.1.4.tgz",
|
||||
"integrity": "sha512-jJ0bqzaylmJtVnNgzTeSOs8DPavpbYgEr/b0YL8/2GO3xJEhInFmhKMUnEJQjZumK7KXGFhUy89PrsJWlakBVg=="
|
||||
},
|
||||
"node_modules/tar-stream": {
|
||||
"version": "2.2.0",
|
||||
"resolved": "https://registry.npmjs.org/tar-stream/-/tar-stream-2.2.0.tgz",
|
||||
"integrity": "sha512-ujeqbceABgwMZxEJnk2HDY2DlnUZ+9oEcb1KzTVfYHio0UE6dG71n60d8D2I4qNvleWrrXpmjpt7vZeF1LnMZQ==",
|
||||
"dependencies": {
|
||||
"bl": "^4.0.3",
|
||||
"end-of-stream": "^1.4.1",
|
||||
"fs-constants": "^1.0.0",
|
||||
"inherits": "^2.0.3",
|
||||
"readable-stream": "^3.1.1"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=6"
|
||||
}
|
||||
},
|
||||
"node_modules/text-hex": {
|
||||
"version": "1.0.0",
|
||||
"resolved": "https://registry.npmjs.org/text-hex/-/text-hex-1.0.0.tgz",
|
||||
@@ -2435,17 +2102,6 @@
|
||||
"node": ">= 14.0.0"
|
||||
}
|
||||
},
|
||||
"node_modules/tunnel-agent": {
|
||||
"version": "0.6.0",
|
||||
"resolved": "https://registry.npmjs.org/tunnel-agent/-/tunnel-agent-0.6.0.tgz",
|
||||
"integrity": "sha512-McnNiV1l8RYeY8tBgEpuodCC1mLUdbSN+CYBL7kJsJNInOP8UjDDEwdk6Mw60vdLLrr5NHKZhMAOSrR2NZuQ+w==",
|
||||
"dependencies": {
|
||||
"safe-buffer": "^5.0.1"
|
||||
},
|
||||
"engines": {
|
||||
"node": "*"
|
||||
}
|
||||
},
|
||||
"node_modules/type-is": {
|
||||
"version": "2.0.1",
|
||||
"resolved": "https://registry.npmjs.org/type-is/-/type-is-2.0.1.tgz",
|
||||
|
||||
@@ -1,12 +1,10 @@
|
||||
{
|
||||
"dependencies": {
|
||||
"better-sqlite3": "^11.10.0",
|
||||
"chart.js": "^4.4.9",
|
||||
"ejs": "^3.1.10",
|
||||
"express": "^5.1.0",
|
||||
"express-basic-auth": "^1.2.1",
|
||||
"express-fileupload": "^1.5.1",
|
||||
"expressjs": "^1.0.1",
|
||||
"fast-csv": "^5.0.2",
|
||||
"socketcan": "^4.0.6",
|
||||
"uuid": "^11.1.0",
|
||||
|
||||
@@ -4,7 +4,8 @@ module.exports = {
|
||||
program: "Throttle & Motor Mapping",
|
||||
host: "localhost",
|
||||
protocol: "http",
|
||||
port: 8080,
|
||||
port: 8081,
|
||||
app_url: "/app",
|
||||
username: "admin",
|
||||
password: "password",
|
||||
logger: {
|
||||
|
||||
@@ -1,7 +1,8 @@
|
||||
module.exports = {
|
||||
prefix: "map",
|
||||
extension: "csv",
|
||||
steps: 10,
|
||||
max_rpm: 6500,
|
||||
max_throttle: 1,
|
||||
selected_map_path: "app/storage/selected"
|
||||
map_storage_path: "/app/storage"
|
||||
}
|
||||
@@ -9,6 +9,7 @@ const public_routes = require('./app/routes/public_routes');
|
||||
const private_routes = require('./app/routes/private_routes');
|
||||
|
||||
const logger = require("./app/utils/logger.util.js");
|
||||
const map_socket = require("./app/utils/socket.util.js");
|
||||
|
||||
const app = express();
|
||||
var shutting_down = false;
|
||||
@@ -17,6 +18,7 @@ var shutting_down = false;
|
||||
* Static middleware - serve css and js files to public
|
||||
*/
|
||||
app.use(express.json());
|
||||
// Set temp directory and upload size limit
|
||||
app.use(fileUpload({
|
||||
limits: { fileSize: 102400 },
|
||||
useTempFiles: true,
|
||||
@@ -25,7 +27,7 @@ app.use(fileUpload({
|
||||
|
||||
app.use("/", public_routes);
|
||||
|
||||
app.use("/app", basicAuth({
|
||||
app.use(`${app_conf.app_url}`, basicAuth({
|
||||
users: {
|
||||
[app_conf.username]: app_conf.password
|
||||
},
|
||||
@@ -39,8 +41,7 @@ app.use("/app", basicAuth({
|
||||
app.set("view engine", "ejs");
|
||||
app.set("views", path.join(__dirname, app_conf.views_directory));
|
||||
const server = app.listen(app_conf.port, (error) => {
|
||||
logger.info("Starting Database Editor.");
|
||||
|
||||
logger.info(`Starting ${app_conf.name} ${app_conf.program}.`);
|
||||
|
||||
fs.rm(path.join(__dirname, app_conf.temp_directory, "/."), { recursive: true }, (error) => {
|
||||
if (error == null) {
|
||||
@@ -77,6 +78,7 @@ process.on("SIGINT", () => {
|
||||
*/
|
||||
function shutdown() {
|
||||
shutting_down = true;
|
||||
map_socket.closeSocket();
|
||||
|
||||
server.close(() => {
|
||||
logger.info("Shutting down server.");
|
||||
|
||||
+16
-3
@@ -25,6 +25,7 @@ function setEventListeners(element, cb) {
|
||||
};
|
||||
}
|
||||
|
||||
// Creates a request body with all data to add new map
|
||||
setEventListeners(commit, async () => {
|
||||
if (changes) {
|
||||
let req_body = {};
|
||||
@@ -33,33 +34,40 @@ setEventListeners(commit, async () => {
|
||||
req_body["throttle"] = {};
|
||||
req_body["motor"] = { 0: {}, 1: {} };
|
||||
|
||||
// blue color means the value has been changed
|
||||
if (map_name.style.backgroundColor == "blue") {
|
||||
// Write the map name metadata
|
||||
req_body["meta"]["name"] = map_name.value;
|
||||
}
|
||||
if (map_id.style.backgroundColor == "blue") {
|
||||
// Write the map id metadata
|
||||
req_body["meta"]["id"] = map_id.value;
|
||||
}
|
||||
if (map_description.style.backgroundColor == "blue") {
|
||||
// Write the map description metadata
|
||||
req_body["meta"]["description"] = map_description.value;
|
||||
}
|
||||
|
||||
// Write the throttle output data for each step
|
||||
for (let i = 1; i < throttle_table.rows[1].cells.length; i++) {
|
||||
let e = throttle_table.rows[1].cells[i].firstChild;
|
||||
req_body["throttle"][i - 1] = (e.value ? e.value : e.placeholder);
|
||||
}
|
||||
|
||||
// Write the motor current data for each step
|
||||
for (let i = 1; i < motor_table.rows[1].cells.length; i++) {
|
||||
let e = motor_table.rows[1].cells[i].firstChild;
|
||||
req_body["motor"][0][i - 1] = (e.value ? e.value : e.placeholder);
|
||||
}
|
||||
|
||||
// Write the motor brake current data for each step
|
||||
for (let i = 1; i < motor_table.rows[2].cells.length; i++) {
|
||||
let e = motor_table.rows[2].cells[i].firstChild;
|
||||
req_body["motor"][1][i - 1] = (e.value ? e.value : e.placeholder);
|
||||
}
|
||||
|
||||
try {
|
||||
const response = await fetch("/app/add", {
|
||||
const response = await fetch(`${app_url}/add`, {
|
||||
method: "POST",
|
||||
body: JSON.stringify(req_body),
|
||||
headers: {
|
||||
@@ -69,17 +77,17 @@ setEventListeners(commit, async () => {
|
||||
if (!response.ok) {
|
||||
throw new Error(`Response status: ${response.status}`);
|
||||
} else {
|
||||
window.location.href = "/app";
|
||||
window.location.href = app_url;
|
||||
}
|
||||
} catch (error) {
|
||||
alert(`Add unsuccessful. ${error.message}`);
|
||||
console.error(error.message);
|
||||
}
|
||||
} else {
|
||||
alert("Nothing to commit.");
|
||||
}
|
||||
});
|
||||
|
||||
// Handles the throttle chart and table
|
||||
(function () {
|
||||
let data = [];
|
||||
|
||||
@@ -90,6 +98,7 @@ setEventListeners(commit, async () => {
|
||||
throttle_output_row.appendChild(Object.assign(document.createElement("th"), { textContent: "Throttle output" }));
|
||||
|
||||
for (let i = 0; i <= steps; i++) {
|
||||
// Initialize throttle table
|
||||
let c_percentage = i * ((max_throttle * 100) / steps);
|
||||
let c_output = 0;
|
||||
|
||||
@@ -107,6 +116,7 @@ setEventListeners(commit, async () => {
|
||||
placeholder: c_output
|
||||
})
|
||||
|
||||
// onchange event, tracks number of changes, checks the value and changes color to blue
|
||||
input.onchange = async function () {
|
||||
if (this.value) {
|
||||
let value = parseFloat(this.value);
|
||||
@@ -136,6 +146,7 @@ setEventListeners(commit, async () => {
|
||||
this.style.backgroundColor = "";
|
||||
changes--;
|
||||
|
||||
// Update chart
|
||||
throttle_chart.data.datasets[0].data[this.parentElement.cellIndex - 1] = this.placeholder;
|
||||
throttle_chart.update();
|
||||
}
|
||||
@@ -149,6 +160,7 @@ setEventListeners(commit, async () => {
|
||||
throttle_table.appendChild(throttle_percentage_row);
|
||||
throttle_table.appendChild(throttle_output_row);
|
||||
|
||||
// Chart class object
|
||||
const throttle_chart = new Chart(
|
||||
throttle_plot,
|
||||
{
|
||||
@@ -170,6 +182,7 @@ setEventListeners(commit, async () => {
|
||||
);
|
||||
})();
|
||||
|
||||
// Same as throttle but for motor current and motor brake current
|
||||
(function () {
|
||||
let data = [];
|
||||
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
// Same as map add.js with minor changes
|
||||
const commit = document.getElementById("commit");
|
||||
const enable = document.getElementById("enable");
|
||||
const download = document.getElementById("download");
|
||||
@@ -32,13 +33,13 @@ setEventListeners(enable, async () => {
|
||||
const map_filename = (new URLSearchParams(window.location.search)).get("element");
|
||||
|
||||
try {
|
||||
const response = await fetch(`/app/enable?element=${map_filename}`, {
|
||||
const response = await fetch(`${app_url}/enable?element=${map_filename}`, {
|
||||
method: "GET"
|
||||
});
|
||||
if (!response.ok) {
|
||||
throw new Error(`Response status: ${response.status}`);
|
||||
} else {
|
||||
window.location.href = "/app";
|
||||
window.location.href = app_url;
|
||||
}
|
||||
} catch (error) {
|
||||
alert(`Could not enable map. ${error.message}`);
|
||||
@@ -49,17 +50,16 @@ setEventListeners(remove, async () => {
|
||||
const map_filename = (new URLSearchParams(window.location.search)).get("element");
|
||||
|
||||
try {
|
||||
const response = await fetch(`/app/remove?element=${map_filename}`, {
|
||||
const response = await fetch(`${app_url}/remove?element=${map_filename}`, {
|
||||
method: "DELETE"
|
||||
});
|
||||
if (!response.ok) {
|
||||
throw new Error(`Response status: ${response.status}`);
|
||||
} else {
|
||||
window.location.href = "/app";
|
||||
window.location.href = app_url;
|
||||
}
|
||||
} catch (error) {
|
||||
alert(`Remove unsuccessful. ${error.message}`);
|
||||
console.error(error.message);
|
||||
}
|
||||
});
|
||||
|
||||
@@ -101,7 +101,7 @@ setEventListeners(commit, async () => {
|
||||
}
|
||||
|
||||
try {
|
||||
const response = await fetch(`/app/edit?element=${map_filename}`, {
|
||||
const response = await fetch(`${app_url}/edit?element=${map_filename}`, {
|
||||
method: "POST",
|
||||
body: JSON.stringify(req_body),
|
||||
headers: {
|
||||
@@ -111,11 +111,10 @@ setEventListeners(commit, async () => {
|
||||
if (!response.ok) {
|
||||
throw new Error(`Response status: ${response.status}`);
|
||||
} else {
|
||||
window.location.href = "/app";
|
||||
window.location.href = app_url;
|
||||
}
|
||||
} catch (error) {
|
||||
alert(`Edit unsuccessful. ${error.message}`);
|
||||
console.error(error.message);
|
||||
}
|
||||
} else {
|
||||
alert("Nothing to commit.");
|
||||
@@ -125,7 +124,7 @@ setEventListeners(commit, async () => {
|
||||
setEventListeners(download, () => {
|
||||
const map_filename = (new URLSearchParams(window.location.search)).get("element");
|
||||
|
||||
window.location.href = `/app/download?element=${map_filename}`;
|
||||
window.location.href = `${app_url}/download?element=${map_filename}`;
|
||||
});
|
||||
|
||||
var parsed_map = JSON.parse(map);
|
||||
|
||||
@@ -18,7 +18,7 @@ function setEventListeners(element, cb) {
|
||||
}
|
||||
|
||||
setEventListeners(add, () => {
|
||||
window.location.href = "/app/add";
|
||||
window.location.href = `${app_url}/add`;
|
||||
});
|
||||
|
||||
setEventListeners(upload, async () => {
|
||||
@@ -27,7 +27,7 @@ setEventListeners(upload, async () => {
|
||||
const formData = new FormData();
|
||||
formData.append('file', file);
|
||||
|
||||
fetch('/app/upload', {
|
||||
fetch(`${app_url}/upload`, {
|
||||
method: 'POST',
|
||||
body: formData
|
||||
}).then((response) => {
|
||||
|
||||
@@ -22,13 +22,13 @@ function setEventListeners(element, cb) {
|
||||
|
||||
setEventListeners(disable, async () => {
|
||||
try {
|
||||
const response = await fetch(`/app/disable`, {
|
||||
const response = await fetch(`${app_url}/disable`, {
|
||||
method: "GET"
|
||||
});
|
||||
if (!response.ok) {
|
||||
throw new Error(`Response status: ${response.status}`);
|
||||
} else {
|
||||
window.location.href = "/app";
|
||||
window.location.href = app_url;
|
||||
}
|
||||
} catch (error) {
|
||||
alert(`Could not disable map. ${error.message}`);
|
||||
@@ -41,7 +41,7 @@ setEventListeners(upload, async () => {
|
||||
const formData = new FormData();
|
||||
formData.append('file', file);
|
||||
|
||||
fetch('/app/upload', {
|
||||
fetch(`${app_url}/upload`, {
|
||||
method: 'POST',
|
||||
body: formData
|
||||
}).then((response) => {
|
||||
@@ -58,7 +58,7 @@ setEventListeners(upload, async () => {
|
||||
});
|
||||
|
||||
setEventListeners(add, () => {
|
||||
window.location.href = "/app/add";
|
||||
window.location.href = `${app_url}/add`;
|
||||
});
|
||||
|
||||
setEventListeners(logout, () => {
|
||||
@@ -69,6 +69,6 @@ const map_rows = map_table.rows;
|
||||
|
||||
for (let i = 1; i < map_rows.length; i++) {
|
||||
setEventListeners(map_rows[i], () => {
|
||||
window.location.href = `/app/edit?element=${map_rows[i].cells[0].innerText}`;
|
||||
window.location.href = `${app_url}/edit?element=${map_rows[i].cells[0].innerText}`;
|
||||
});
|
||||
}
|
||||
@@ -0,0 +1,66 @@
|
||||
const can = require("socketcan");
|
||||
|
||||
var channel = can.createRawChannel("vcan0", true);
|
||||
|
||||
const INVR_ID = 0x04;
|
||||
const ERPM_ID = (0x20 << 5) | INVR_ID;
|
||||
const APPS_ID = 0x50;
|
||||
const SELC_ID = 0x19;
|
||||
const MXCU_ID = (0x01 << 5) | INVR_ID;
|
||||
const MXBC_ID = (0x02 << 5) | INVR_ID;
|
||||
|
||||
var APPS = 0;
|
||||
var ERPM = 0;
|
||||
|
||||
// SELECT
|
||||
(function sendSELC() {
|
||||
channel.send({
|
||||
id: SELC_ID,
|
||||
ext: false,
|
||||
data: Buffer.from([0x02]) // ENABLE CONTROL BY TELEMETRY
|
||||
});
|
||||
})();
|
||||
|
||||
// APPS
|
||||
function sendAPPS() {
|
||||
APPS = Math.floor(Math.random() * 1000);
|
||||
console.log(`APPS: ${APPS / 10}%`);
|
||||
channel.send({
|
||||
id: APPS_ID,
|
||||
ext: false,
|
||||
data: Buffer.from([APPS & 0xFF, APPS >> 8]) // SEND APPS PERCENTAGE
|
||||
});
|
||||
|
||||
setTimeout(sendAPPS, Math.floor(Math.random() * 5000));
|
||||
}
|
||||
|
||||
// ERPM
|
||||
(function sendERPM() {
|
||||
ERPM = Math.floor(Math.random() * 65000);
|
||||
console.log(`ERPM: ${ERPM}`);
|
||||
|
||||
channel.send({
|
||||
id: ERPM_ID,
|
||||
ext: false,
|
||||
data: Buffer.from([(ERPM >> 8 * 3) & 0xFF, (ERPM >> 8 * 2) & 0xFF, (ERPM >> 8) & 0xFF, ERPM & 0xFF, 0x00, 0x71, 0x01, 0x86]) // SEND ERPM
|
||||
});
|
||||
|
||||
setTimeout(sendERPM, Math.floor(Math.random() * 10000));
|
||||
})();
|
||||
|
||||
sendAPPS();
|
||||
|
||||
channel.addListener("onMessage", async function (message) {
|
||||
switch (message.id) {
|
||||
case MXCU_ID:
|
||||
console.log(`CURRENT: ${message.data[0] << 8 | message.data[1]}`);
|
||||
break;
|
||||
case MXBC_ID:
|
||||
console.log(`BRAKE: ${message.data[0] << 8 | message.data[1]}`);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
});
|
||||
|
||||
channel.start();
|
||||
Reference in New Issue
Block a user