Add datalogger
This commit is contained in:
parent
4a69871468
commit
ee90fa861e
@ -1,85 +1,103 @@
|
||||
from mod_utils import chkDirTree
|
||||
from mod_db_manager import find_DBs
|
||||
from mod_elm import ELM
|
||||
from mod_scan_ecus import ScanEcus
|
||||
from mod_optfile import optfile
|
||||
from mod_ecu import ECU
|
||||
from mod_ply import Calc
|
||||
from flask import Flask, jsonify, request, send_file
|
||||
from flask_socketio import SocketIO
|
||||
from rendash_main import RenDash
|
||||
from csv import writer, QUOTE_MINIMAL
|
||||
from datetime import datetime
|
||||
|
||||
from pickle import dump, load
|
||||
from time import sleep
|
||||
import mod_globals
|
||||
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:
|
||||
def __init__(self,
|
||||
elm_port,
|
||||
elm_speed=38400,
|
||||
model_number=58,
|
||||
rescan=False) -> None:
|
||||
chkDirTree()
|
||||
find_DBs()
|
||||
bg_thread = None
|
||||
|
||||
self.elm = ELM(elm_port, elm_speed, "")
|
||||
self.lang = optfile("Location/DiagOnCAN_GB.bqm", False)
|
||||
self.ecus: List[ECU] = []
|
||||
self.current_ecu = None
|
||||
def mainloop():
|
||||
global running, watched_datarefs, watched_ecu, should_log, freeze
|
||||
if should_log:
|
||||
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:
|
||||
try:
|
||||
self.ecus = load(open("frozen_ecus.p", "rb"))
|
||||
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+"))
|
||||
@socket.on("freeze")
|
||||
def freeze_event():
|
||||
global freeze
|
||||
|
||||
for ecu in self.ecus:
|
||||
setattr(ecu, "calc", Calc())
|
||||
freeze = 1
|
||||
|
||||
def get_ecu_names(self):
|
||||
return [ecu.ecudata["doc"] for ecu in self.ecus]
|
||||
@web.get("/ecus")
|
||||
def get_ecus():
|
||||
ecus = dash.get_ecu_names()
|
||||
return jsonify(ecus)
|
||||
|
||||
@web.get("/ecus/<ecu_doc>/states")
|
||||
def get_ecu_states(ecu_doc):
|
||||
return jsonify(dash.get_ecu_states(ecu_doc))
|
||||
|
||||
@web.get("/ecus/<ecu_doc>/parameters")
|
||||
def get_ecu_parameters(ecu_doc):
|
||||
return jsonify(dash.get_ecu_parameters(ecu_doc))
|
||||
|
||||
@web.post("/ecus/<ecu_doc>/watch")
|
||||
def ecu_watch(ecu_doc):
|
||||
global watched_ecu, watched_datarefs
|
||||
|
||||
datarefs = request.get_json()
|
||||
watched_datarefs = []
|
||||
for dataref in datarefs:
|
||||
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
|
||||
|
||||
def get_ecu_by_doc(self, doc):
|
||||
for ecu in self.ecus:
|
||||
if ecu.ecudata["doc"] == doc:
|
||||
if self.current_ecu is not ecu:
|
||||
ecu.initELM(self.elm)
|
||||
self.current_ecu = ecu
|
||||
return ecu
|
||||
|
||||
def get_ecu_states(self, doc):
|
||||
ecu = self.get_ecu_by_doc(doc)
|
||||
return ecu.Parameters
|
||||
|
||||
def get_ecu_state(self, doc, state):
|
||||
ecu = self.get_ecu_by_doc(doc)
|
||||
datastr = ecu.get_st(state)
|
||||
return datastr
|
||||
|
||||
def get_ecu_param(self, doc, param):
|
||||
ecu = self.get_ecu_by_doc(doc)
|
||||
datastr = ecu.get_pr(param)
|
||||
return datastr
|
||||
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__":
|
||||
rd = RenDash("/dev/tty0")
|
||||
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)
|
||||
|
||||
|
||||
socket.run(web, "0.0.0.0", 5000)
|
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 = ''
|
||||
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:
|
||||
|
@ -29,7 +29,7 @@ def get_state( st, mn, se, elm, calc, dataids = {} ):
|
||||
csv_val = 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:
|
||||
|
||||
|
@ -64,21 +64,27 @@ class RenDash:
|
||||
|
||||
def get_ecu_states(self, 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):
|
||||
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):
|
||||
ecu = self.get_ecu_by_doc(doc)
|
||||
datastr, help, csvd = get_state(ecu.States[state], ecu.Mnemonics, ecu.Services, self.elm, ecu.calc)
|
||||
return datastr
|
||||
return ecu.get_st(state)
|
||||
|
||||
def get_ecu_param(self, doc, param):
|
||||
ecu = self.get_ecu_by_doc(doc)
|
||||
datastr, help, csvd = get_parameter(ecu.Parameters[param], ecu.Mnemonics, ecu.Services, self.elm, ecu.calc)
|
||||
return datastr
|
||||
return ecu.get_pr(param)
|
||||
|
||||
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__":
|
||||
rd = RenDash("/dev/ttyS5")
|
||||
|
Loading…
x
Reference in New Issue
Block a user