change layout

This commit is contained in:
Hannes Klinckaert 2020-09-08 18:52:38 +02:00
parent 769f4ddd5d
commit 54c03165b0
3 changed files with 143 additions and 130 deletions

View file

@ -4,6 +4,7 @@ from time import sleep
from dataclasses import dataclass from dataclasses import dataclass
from datetime import datetime from datetime import datetime
import serial import serial
import random
app = Flask(__name__) app = Flask(__name__)
shared_message_log = [] shared_message_log = []
@ -41,30 +42,31 @@ class Message:
def parse_message(self): def parse_message(self):
sender_type = self.sender_type() sender_type = self.sender_type()
message_type = self.payload[0] message_type = self.payload[0]
if sender_type == 0b00: # controller try:
if message_type == 0: if sender_type == 0b00: # controller
return "ACK" if message_type == 0:
elif message_type == 1: return "ACK"
return "HELLO" elif message_type == 1:
elif message_type == 2: return "HELLO"
return "START " + self._parse_state_update() elif message_type == 2:
elif message_type == 3: return "START " + self._parse_state_update()
return "STATE " + self._parse_state_update() elif message_type == 3:
elif message_type == 4: return "STATE " + self._parse_state_update()
return "SOLVED " + self._parse_state_update() elif message_type == 4:
elif message_type == 5: return "SOLVED " + self._parse_state_update()
return "TIMEOUT " + self._parse_state_update() elif message_type == 5:
elif message_type == 6: return "TIMEOUT " + self._parse_state_update()
return "STRIKEOUT " + self._parse_state_update() elif message_type == 6:
elif sender_type == 0b01: # puzzle return "STRIKEOUT " + self._parse_state_update()
if message_type == 0: elif sender_type == 0b01: # puzzle
return "REGISTER" if message_type == 0:
elif message_type == 1: return "REGISTER"
return f"STRIKE {self.payload[1]}" elif message_type == 1:
elif message_type == 2: return f"STRIKE {self.payload[1]}"
return f"SOLVED" elif message_type == 2:
else: return f"SOLVED"
return f"PARSE ERROR {self.received_from:011b} {self.payload.hex(' ')}" finally:
return "PARSE ERROR"
def serialize(self): def serialize(self):
return { return {
@ -79,19 +81,25 @@ class Message:
def serial_reader(messagelog): def serial_reader(messagelog):
with serial.Serial('/dev/ttyACM0', 115200, timeout=10) as ser: # with serial.Serial('/dev/ttyACM0', 115200, timeout=10) as ser:
while True: # while True:
line = ser.readline() # line = ser.readline()
print(line.decode('ascii')) # print(line.decode('ascii'))
if line.startswith(b"message"): # if line.startswith(b"message"):
line = line.decode('ascii') # line = line.decode('ascii')
line = line.strip() # line = line.strip()
parts = line.split(' ') # parts = line.split(' ')
sender = int(parts[1]) # sender = int(parts[1])
message = bytes(int(p) for p in parts[2:]) # message = bytes(int(p) for p in parts[2:])
received = Message(message, sender, datetime.now(), len(messagelog)) # received = Message(message, sender, datetime.now(), len(messagelog))
messagelog.append(received.serialize()) # messagelog.append(received.serialize())
print(len(messagelog)) # print(len(messagelog))
for i in range(500):
sender = random.randrange(0, 0x800)
message = bytes(random.randrange(256) for i in range(random.randint(1, 8)))
received = Message(message, sender, datetime.now(), len(messagelog))
messagelog.append(received.serialize())
# sleep(5)
@app.route('/') @app.route('/')
def index(): def index():
@ -105,4 +113,4 @@ def api():
if __name__ == '__main__': if __name__ == '__main__':
thread = Thread(target=serial_reader, args=(shared_message_log, )) thread = Thread(target=serial_reader, args=(shared_message_log, ))
thread.start() thread.start()
app.run(debug=True, host='0.0.0.0') app.run(debug=True, host='0.0.0.0')

View file

@ -5,70 +5,71 @@
<meta charset="utf-8"> <meta charset="utf-8">
<title>CAN debugger</title> <title>CAN debugger</title>
<style> <style>
body {
@keyframes fadein { font-family: sans-serif;
from { opacity: 0; }
to { opacity: 1; }
} }
.message {
display: flex; .hide {
animation: fadein 1s;
}
.message > * {
margin-top: 0;
margin-bottom: 0;
padding: 0 1.5ch 0 1.5ch;
}
.hide_details .message .pretty_raw_sender_id {
display: none; display: none;
} }
.hide_details .message .raw_message {
display: none;
}
.human_readable_type {
order: -5;
}
.time {
order: 5;
}
.sender_id {
order: 1;
}
.parsed { .parsed {
order: 2;
flex: 1;
background: lightgreen; background: lightgreen;
} }
.pretty_raw_sender_id, .raw_message { td.raw {
font-family: monospace, monospace; font-family: monospace, monospace;
} }
.pretty_raw_sender_id { table {
order: 9998; border-collapse: collapse;
width: 100%;
} }
.raw_message { th, td {
order: 9999; border-left: 1px solid black;
border-right: 1px solid black;
padding: 5px;
} }
th {
background-color: gold;
border-bottom: 2px solid black;
border-top: 2px solid black;
height: 20px;
text-align: left;
}
tr:hover {
background-color: #aaa;
}
td[error] {
background-color: rgb(255, 71, 71);
}
.time, .raw_id, .sender_id {
text-align: right;
}
</style> </style>
</head> </head>
<body> <body>
<div> <button onclick="toggle_logging()" id="toggle_button">Start</button>
<input type="checkbox" id="show_raw" name="show_raw" checked onchange="updateShow()">
<input type="checkbox" id="show_raw" name="show_raw" checked autocomplete="off" onchange="updateShow()">
<label for="show_raw">Show raw address and payload</label> <label for="show_raw">Show raw address and payload</label>
<input type="checkbox" id="pause" name="pause">
<label for="pause">Pause</label> <table id="message_table">
</div> <tr>
<div id="messages"> <th>Human-readable type</th>
<th>Sender ID</th>
</div> <th>Parsed payload</th>
<th>Time</th>
<th class="raw">Raw Message</th>
<th class="raw">Raw ID</th>
</tr>
</table>
<script src="static/script.js"></script> <script src="static/script.js"></script>
</body> </body>
</html> </html>

View file

@ -1,10 +1,15 @@
maxseen = 0;
let maxseen = 0;
let paused = true;
let updaterID = null;
function updateShow() { function updateShow() {
if (document.getElementById('show_raw').checked) { for (let item of document.getElementsByClassName("raw")) {
document.getElementById('messages').classList = ''; if (document.getElementById('show_raw').checked) {
} else { item.classList.remove("hide");
document.getElementById('messages').classList = 'hide_details'; } else {
item.classList.add("hide");
}
} }
} }
@ -17,59 +22,58 @@ function updateMessages() {
return; return;
} }
response.json().then(function(data) { response.json().then(function(data) {
console.log(data);
if (data.length > maxseen) { if (data.length > maxseen) {
var messageContainer = document.getElementById('messages'); let messageTable = document.getElementById('message_table');
for (let i = maxseen; i < data.length; i++) {
var current = data[i]; for (let i = maxseen; i < data.length; i++) {
var time = document.createElement("p"); let row = messageTable.insertRow(1);
time.innerHTML = current['time']; let current = data[i];
time.className = 'time';
var parsed = document.createElement("p"); let human_readable_type = row.insertCell(0)
parsed.innerHTML = current['parsed']; human_readable_type.innerHTML = current['human_readable_type'];
parsed.className = 'parsed'; human_readable_type.className = 'human_readable_type';
var sender_id = document.createElement("p"); let sender_id = row.insertCell(-1)
sender_id.innerHTML = current['sender_id']; sender_id.innerHTML = current['sender_id'];
sender_id.className = 'sender_id'; sender_id.className = 'sender_id';
var pretty_raw_sender_id = document.createElement("p"); let parsed = row.insertCell(-1)
pretty_raw_sender_id.innerHTML = current['pretty_raw_sender_id']; if (current['parsed'].startsWith("PARSE ERROR")) {
pretty_raw_sender_id.className = 'pretty_raw_sender_id'; parsed.setAttribute("error", true);
var raw_message = document.createElement("p");
raw_message.innerHTML = current['raw_message'];
raw_message.className = 'raw_message';
var human_readable_type = document.createElement("p");
human_readable_type.innerHTML = current['human_readable_type'];
human_readable_type.className = 'human_readable_type';
var newNode = document.createElement("div");
newNode.className = "message";
newNode.append(time, parsed, sender_id, pretty_raw_sender_id, raw_message, human_readable_type);
messageContainer.prepend(newNode)
} }
maxseen = data.length; parsed.innerHTML = current['parsed'];
parsed.className += 'parsed';
let time = row.insertCell(-1)
time.innerHTML = current['time'];
time.className = 'time';
let raw_message = row.insertCell(-1);
raw_message.innerHTML = current['raw_message'];
raw_message.classList.add("raw");
raw_message.classList.add("raw_message");
let raw_id = row.insertCell(-1);
raw_id.innerHTML = current['pretty_raw_sender_id'];
raw_id.classList.add("raw");
raw_id.classList.add("raw_id");
}
maxseen = data.length;
} }
}); });
} }
) )
} }
function toggle_logging() {
if (paused) {
paused = false;
document.getElementById("toggle_button").innerHTML = "Pause";
updaterID = setInterval(updateMessages, 1000);
} else {
paused = true;
document.getElementById("toggle_button").innerHTML = "Start";
clearInterval(updaterID);
}
}
window.onload = function() {
updateShow()
console.log("loaded");
updateMessages();
setInterval(function() {
if (document.getElementById('pause').checked) {
return;
}
updateMessages()
}, 1000);
};