Add datalogger
This commit is contained in:
parent
4a69871468
commit
ee90fa861e
@ -1,85 +1,103 @@
|
|||||||
from mod_utils import chkDirTree
|
from flask import Flask, jsonify, request, send_file
|
||||||
from mod_db_manager import find_DBs
|
from flask_socketio import SocketIO
|
||||||
from mod_elm import ELM
|
from rendash_main import RenDash
|
||||||
from mod_scan_ecus import ScanEcus
|
from csv import writer, QUOTE_MINIMAL
|
||||||
from mod_optfile import optfile
|
from datetime import datetime
|
||||||
from mod_ecu import ECU
|
|
||||||
from mod_ply import Calc
|
|
||||||
|
|
||||||
from pickle import dump, load
|
import mod_globals
|
||||||
from time import sleep
|
mod_globals.opt_demo = True
|
||||||
|
|
||||||
from flask import Flask, make_response, request
|
dash = RenDash("/dev/tty1")
|
||||||
|
web = Flask(__name__)
|
||||||
|
socket = SocketIO(web)
|
||||||
|
|
||||||
from typing import List
|
watched_datarefs = []
|
||||||
|
watched_ecu = ""
|
||||||
|
should_log = False
|
||||||
|
freeze = 0
|
||||||
|
running = False
|
||||||
|
|
||||||
class RenDash:
|
bg_thread = None
|
||||||
def __init__(self,
|
|
||||||
elm_port,
|
|
||||||
elm_speed=38400,
|
|
||||||
model_number=58,
|
|
||||||
rescan=False) -> None:
|
|
||||||
chkDirTree()
|
|
||||||
find_DBs()
|
|
||||||
|
|
||||||
self.elm = ELM(elm_port, elm_speed, "")
|
def mainloop():
|
||||||
self.lang = optfile("Location/DiagOnCAN_GB.bqm", False)
|
global running, watched_datarefs, watched_ecu, should_log, freeze
|
||||||
self.ecus: List[ECU] = []
|
if should_log:
|
||||||
self.current_ecu = None
|
log_filename = f'{datetime.now().strftime("%m/%d/%Y, %H:%M:%S")}.csv'
|
||||||
|
print("Creating log on file: " + log_filename)
|
||||||
|
with open(log_filename, "w+") as file:
|
||||||
|
csv_writer = writer(file,delimiter=' ', quotechar='|', quoting=QUOTE_MINIMAL)
|
||||||
|
csv_writer.writerow(["freeze"].extend(watched_datarefs))
|
||||||
|
|
||||||
self.web = Flask(__name__)
|
print("Starting data loop")
|
||||||
|
while running:
|
||||||
|
frame = [dash.get_ecu_dataref(watched_ecu, dataref) for dataref in watched_datarefs]
|
||||||
|
socket.emit("frame", {"frame": frame})
|
||||||
|
if should_log:
|
||||||
|
csv_writer.writerow([freeze].extend(frame))
|
||||||
|
freeze = 0
|
||||||
|
print(frame)
|
||||||
|
|
||||||
if rescan is False:
|
@socket.on("freeze")
|
||||||
try:
|
def freeze_event():
|
||||||
self.ecus = load(open("frozen_ecus.p", "rb"))
|
global freeze
|
||||||
except Exception as e:
|
|
||||||
pass
|
|
||||||
if not self.ecus:
|
|
||||||
ecu_scanner = ScanEcus(self.elm)
|
|
||||||
ecu_scanner.chooseModel(model_number)
|
|
||||||
ecu_scanner.scanAllEcus()
|
|
||||||
for ecu in ecu_scanner.detectedEcus:
|
|
||||||
self.ecus.append(ECU(ecu, self.lang.dict))
|
|
||||||
dump(self.ecus, open("frozen_ecus.p", "wb+"))
|
|
||||||
|
|
||||||
for ecu in self.ecus:
|
freeze = 1
|
||||||
setattr(ecu, "calc", Calc())
|
|
||||||
|
|
||||||
def get_ecu_names(self):
|
@web.get("/ecus")
|
||||||
return [ecu.ecudata["doc"] for ecu in self.ecus]
|
def get_ecus():
|
||||||
|
ecus = dash.get_ecu_names()
|
||||||
|
return jsonify(ecus)
|
||||||
|
|
||||||
def get_ecu_by_doc(self, doc):
|
@web.get("/ecus/<ecu_doc>/states")
|
||||||
for ecu in self.ecus:
|
def get_ecu_states(ecu_doc):
|
||||||
if ecu.ecudata["doc"] == doc:
|
return jsonify(dash.get_ecu_states(ecu_doc))
|
||||||
if self.current_ecu is not ecu:
|
|
||||||
ecu.initELM(self.elm)
|
|
||||||
self.current_ecu = ecu
|
|
||||||
return ecu
|
|
||||||
|
|
||||||
def get_ecu_states(self, doc):
|
@web.get("/ecus/<ecu_doc>/parameters")
|
||||||
ecu = self.get_ecu_by_doc(doc)
|
def get_ecu_parameters(ecu_doc):
|
||||||
return ecu.Parameters
|
return jsonify(dash.get_ecu_parameters(ecu_doc))
|
||||||
|
|
||||||
def get_ecu_state(self, doc, state):
|
@web.post("/ecus/<ecu_doc>/watch")
|
||||||
ecu = self.get_ecu_by_doc(doc)
|
def ecu_watch(ecu_doc):
|
||||||
datastr = ecu.get_st(state)
|
global watched_ecu, watched_datarefs
|
||||||
return datastr
|
|
||||||
|
|
||||||
def get_ecu_param(self, doc, param):
|
datarefs = request.get_json()
|
||||||
ecu = self.get_ecu_by_doc(doc)
|
watched_datarefs = []
|
||||||
datastr = ecu.get_pr(param)
|
for dataref in datarefs:
|
||||||
return datastr
|
if dataref in dash.get_ecu_parameters(ecu_doc) \
|
||||||
|
or dataref in dash.get_ecu_states(ecu_doc):
|
||||||
|
watched_datarefs.append(dataref)
|
||||||
|
else:
|
||||||
|
watched_datarefs = []
|
||||||
|
raise ValueError("Invalid dataref")
|
||||||
|
watched_ecu = ecu_doc
|
||||||
|
|
||||||
|
return jsonify({"ecu": watched_ecu, "datarefs": watched_datarefs})
|
||||||
|
|
||||||
|
@web.get("/start")
|
||||||
|
def start():
|
||||||
|
global should_log, bg_thread, running
|
||||||
|
|
||||||
|
log = request.args.get("log")
|
||||||
|
if log == "true":
|
||||||
|
should_log = True
|
||||||
|
else:
|
||||||
|
should_log = False
|
||||||
|
|
||||||
|
running = True
|
||||||
|
bg_thread = socket.start_background_task(mainloop)
|
||||||
|
return jsonify({"success": True})
|
||||||
|
|
||||||
|
@web.get("/stop")
|
||||||
|
def stop():
|
||||||
|
global bg_thread, running
|
||||||
|
|
||||||
|
running = False
|
||||||
|
bg_thread.join()
|
||||||
|
return jsonify({"success": True})
|
||||||
|
|
||||||
|
@web.get("/")
|
||||||
|
def index():
|
||||||
|
return send_file("index.html")
|
||||||
|
|
||||||
if __name__ == "__main__":
|
if __name__ == "__main__":
|
||||||
rd = RenDash("/dev/tty0")
|
socket.run(web, "0.0.0.0", 5000)
|
||||||
while True:
|
|
||||||
clearScreen()
|
|
||||||
for ecu_doc, values in REQUIRED_ECU_STATES.items():
|
|
||||||
for val in values:
|
|
||||||
if val.startswith("E"):
|
|
||||||
print(rd.get_ecu_state(ecu_doc, val))
|
|
||||||
elif val.startswith("P"):
|
|
||||||
print(rd.get_ecu_param(ecu_doc, val))
|
|
||||||
sleep(0.1)
|
|
||||||
|
|
||||||
|
|
130
pyren3/index.html
Normal file
130
pyren3/index.html
Normal file
@ -0,0 +1,130 @@
|
|||||||
|
<!DOCTYPE html>
|
||||||
|
<html lang="en">
|
||||||
|
<head>
|
||||||
|
<meta charset="UTF-8" />
|
||||||
|
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
||||||
|
<title>Ecu Watcher</title>
|
||||||
|
<script src="https://cdn.jsdelivr.net/npm/vue@3"></script>
|
||||||
|
<script src="https://cdnjs.cloudflare.com/ajax/libs/socket.io/4.0.1/socket.io.js"></script>
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
<div id="app">
|
||||||
|
<h1>Ecu Watcher</h1>
|
||||||
|
<div v-if="!ecuSelected">
|
||||||
|
<h2>Select ECU</h2>
|
||||||
|
<select v-model="selectedEcu" @change="fetchStatesAndParameters">
|
||||||
|
<option v-for="ecu in ecuList" :value="ecu" :key="ecu">
|
||||||
|
{{ ecu }}
|
||||||
|
</option>
|
||||||
|
</select>
|
||||||
|
</div>
|
||||||
|
<div v-else-if="!watching">
|
||||||
|
<h2>Selected ECU: {{ selectedEcu }}</h2>
|
||||||
|
<div>
|
||||||
|
<h2>States and Parameters</h2>
|
||||||
|
<div v-for="(text, code) in statesAndParams" :key="code">
|
||||||
|
<input type="checkbox" v-model="selectedItems" :value="code" />{{
|
||||||
|
text }}
|
||||||
|
</div>
|
||||||
|
<button @click="watch">Watch</button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div v-if="watching">
|
||||||
|
<h2>Watching</h2>
|
||||||
|
<div v-for="item in selectedItems" :key="item">
|
||||||
|
{{ statesAndParams[item] }}: {{ itemValues[item] }}
|
||||||
|
</div>
|
||||||
|
<button @click="startWatch">Start</button>
|
||||||
|
<button @click="stopWatch">Stop</button>
|
||||||
|
<label>
|
||||||
|
Log:
|
||||||
|
<input type="checkbox" v-model="logging" />
|
||||||
|
</label>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
const socket = io();
|
||||||
|
const app = Vue.createApp({
|
||||||
|
data() {
|
||||||
|
return {
|
||||||
|
ecuList: [],
|
||||||
|
selectedEcu: "",
|
||||||
|
ecuSelected: false,
|
||||||
|
statesAndParams: {},
|
||||||
|
selectedItems: [],
|
||||||
|
itemValues: {},
|
||||||
|
watching: false,
|
||||||
|
logging: false,
|
||||||
|
};
|
||||||
|
},
|
||||||
|
methods: {
|
||||||
|
async fetchEcuList() {
|
||||||
|
try {
|
||||||
|
const response = await fetch("/ecus");
|
||||||
|
this.ecuList = await response.json();
|
||||||
|
} catch (error) {
|
||||||
|
console.error("Error fetching ECU list", error);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
async fetchStatesAndParameters() {
|
||||||
|
try {
|
||||||
|
const response = await fetch(`/ecus/${this.selectedEcu}/states`);
|
||||||
|
const states = await response.json();
|
||||||
|
this.statesAndParams = { ...states };
|
||||||
|
const paramResponse = await fetch(
|
||||||
|
`/ecus/${this.selectedEcu}/parameters`
|
||||||
|
);
|
||||||
|
const parameters = await paramResponse.json();
|
||||||
|
for (const param in parameters) {
|
||||||
|
this.statesAndParams[param] = parameters[param];
|
||||||
|
}
|
||||||
|
this.ecuSelected = true;
|
||||||
|
} catch (error) {
|
||||||
|
console.error("Error fetching states and parameters", error);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
async watch() {
|
||||||
|
try {
|
||||||
|
const response = await fetch(`/ecus/${this.selectedEcu}/watch`, {
|
||||||
|
method: "POST",
|
||||||
|
headers: {
|
||||||
|
"Content-Type": "application/json",
|
||||||
|
},
|
||||||
|
body: JSON.stringify(this.selectedItems),
|
||||||
|
});
|
||||||
|
if (response.ok) {
|
||||||
|
this.watching = true;
|
||||||
|
} else {
|
||||||
|
console.error("Error starting watch");
|
||||||
|
}
|
||||||
|
} catch (error) {
|
||||||
|
console.error("Error starting watch", error);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
async stopWatch() {
|
||||||
|
await fetch(`/stop`, {
|
||||||
|
method: "GET",
|
||||||
|
});
|
||||||
|
},
|
||||||
|
async startWatch() {
|
||||||
|
await fetch(`/start?log=${this.logging ? "true" : "false"}`, {
|
||||||
|
method: "GET",
|
||||||
|
});
|
||||||
|
},
|
||||||
|
},
|
||||||
|
mounted() {
|
||||||
|
this.fetchEcuList();
|
||||||
|
socket.on("frame", (msg) => {
|
||||||
|
const data = msg.frame;
|
||||||
|
for (let i = 0; i < this.selectedItems.length; i++) {
|
||||||
|
this.itemValues[this.selectedItems[i]] = data[i];
|
||||||
|
}
|
||||||
|
});
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
app.mount("#app");
|
||||||
|
</script>
|
||||||
|
</body>
|
||||||
|
</html>
|
@ -42,7 +42,7 @@ def get_parameter( pr, mn, se, elm, calc, dataids = {} ):
|
|||||||
tmpmin = ''
|
tmpmin = ''
|
||||||
tmpmax = ''
|
tmpmax = ''
|
||||||
|
|
||||||
return "%-6s %-50s %5s %10s %-10s %-5s"%(pr.codeMR,pr.label,tmpmin,pr.value,pr.unit,tmpmax), pr.helps, csv_data
|
return "%5s %10s %-10s %-5s"%(tmpmin,pr.value,pr.unit,tmpmax), pr.helps, csv_data
|
||||||
|
|
||||||
|
|
||||||
class ecu_parameter:
|
class ecu_parameter:
|
||||||
|
@ -29,7 +29,7 @@ def get_state( st, mn, se, elm, calc, dataids = {} ):
|
|||||||
csv_val = str(st.value)
|
csv_val = str(st.value)
|
||||||
|
|
||||||
st.value = " "*(16-len(st.value)//2) + str(st.value)
|
st.value = " "*(16-len(st.value)//2) + str(st.value)
|
||||||
return "%-6s %-50s %-20s"%(st.codeMR,st.label,st.value), st.helps, csv_val
|
return "%-20s"%(st.value), st.helps, csv_val
|
||||||
|
|
||||||
class ecu_state:
|
class ecu_state:
|
||||||
|
|
||||||
|
@ -64,21 +64,27 @@ class RenDash:
|
|||||||
|
|
||||||
def get_ecu_states(self, doc):
|
def get_ecu_states(self, doc):
|
||||||
ecu = self.get_ecu_by_doc(doc)
|
ecu = self.get_ecu_by_doc(doc)
|
||||||
return ecu.States
|
return {key: value.label for key,value in ecu.States.items()}
|
||||||
|
|
||||||
def get_ecu_parameters(self, doc):
|
def get_ecu_parameters(self, doc):
|
||||||
ecu = self.get_ecu_by_doc(doc)
|
ecu = self.get_ecu_by_doc(doc)
|
||||||
return ecu.Parameters
|
return {key: value.label for key,value in ecu.Parameters.items()}
|
||||||
|
|
||||||
def get_ecu_state(self, doc, state):
|
def get_ecu_state(self, doc, state):
|
||||||
ecu = self.get_ecu_by_doc(doc)
|
ecu = self.get_ecu_by_doc(doc)
|
||||||
datastr, help, csvd = get_state(ecu.States[state], ecu.Mnemonics, ecu.Services, self.elm, ecu.calc)
|
return ecu.get_st(state)
|
||||||
return datastr
|
|
||||||
|
|
||||||
def get_ecu_param(self, doc, param):
|
def get_ecu_param(self, doc, param):
|
||||||
ecu = self.get_ecu_by_doc(doc)
|
ecu = self.get_ecu_by_doc(doc)
|
||||||
datastr, help, csvd = get_parameter(ecu.Parameters[param], ecu.Mnemonics, ecu.Services, self.elm, ecu.calc)
|
return ecu.get_pr(param)
|
||||||
return datastr
|
|
||||||
|
def get_ecu_dataref(self, doc, dataref: str):
|
||||||
|
if dataref.startswith("E"):
|
||||||
|
return self.get_ecu_state(doc, dataref)
|
||||||
|
elif dataref.startswith("P"):
|
||||||
|
return self.get_ecu_param(doc, dataref)
|
||||||
|
else:
|
||||||
|
raise ValueError("Invalid dataref")
|
||||||
|
|
||||||
if __name__ == "__main__":
|
if __name__ == "__main__":
|
||||||
rd = RenDash("/dev/ttyS5")
|
rd = RenDash("/dev/ttyS5")
|
||||||
|
Loading…
x
Reference in New Issue
Block a user