ota controls… hopefully nearly complete

This commit is contained in:
Laura Klünder 2023-12-01 16:23:17 +01:00
parent bef3db6841
commit a3f763ad35
3 changed files with 84 additions and 8 deletions

View file

@ -16,7 +16,7 @@ from django.utils import timezone
from c3nav.mesh import messages
from c3nav.mesh.messages import (MESH_BROADCAST_ADDRESS, MESH_NONE_ADDRESS, MESH_ROOT_ADDRESS, OTA_CHUNK_SIZE,
MeshMessage, MeshMessageType)
MeshMessage, MeshMessageType, OTASettingMessage, OTAApplyMessage)
from c3nav.mesh.models import MeshNode, MeshUplink, NodeMessage, OTARecipientStatus, OTAUpdate, OTAUpdateRecipient
from c3nav.mesh.utils import MESH_ALL_OTA_GROUP, MESH_ALL_UPLINKS_GROUP, UPLINK_PING, get_mesh_uplink_group
from c3nav.routing.rangelocator import RangeLocator
@ -618,6 +618,28 @@ class MeshUIConsumer(AsyncJsonWebsocketConsumer):
await self.dump_newest_messages(MeshMessageType.OTA_STATUS)
for recipient in await self._qs_as_list(OTAUpdateRecipient.objects.filter(update_id=update_id)):
await self.send_json(recipient.get_status_json())
if "ota_auto" in content:
data = content["ota_auto"]
recipient = await OTAUpdateRecipient.objects.aget(pk=content["recipient"])
await OTASettingMessage(
dst=recipient.node_id,
src=MESH_ROOT_ADDRESS,
update_id=recipient.update_id,
auto_apply=data["apply"],
auto_reboot=data["reboot"],
).send()
if "ota" in content:
ota = content["ota"]
recipient = await OTAUpdateRecipient.objects.aget(pk=content["recipient"])
if ota in ("apply", "reboot"):
await OTAApplyMessage(
dst=recipient.node_id,
src=MESH_ROOT_ADDRESS,
update_id=recipient.update_id,
reboot=(ota == "reboot"),
).send()
if "send_msg" in content:
msg_to_send = self.scope["session"].pop("mesh_msg_%s" % content["send_msg"], None)
if not msg_to_send:
@ -681,6 +703,9 @@ class MeshUIConsumer(AsyncJsonWebsocketConsumer):
data["position"] = None if not location else (int(location.x*100), int(location.y*100), int(location.z*100))
await self.send_json(data)
async def mesh_ota_recipient_status(self, data):
await self.send_json(data)
@database_sync_to_async
def locator(self, msg, orig_addr=None):
locator = RangeLocator.load()

View file

@ -15,13 +15,49 @@
const nodes_xyz = JSON.parse(document.getElementById('nodes-xyz').textContent);
const nodes_distances = {};
{% endif %}
var ws;
{% if update %}
const update_id = {{ update.pk }};
for (const apply_link of document.querySelectorAll('.auto-apply a')) {
apply_link.addEventListener("click", function(e) {
e.preventDefault();
ws.send(JSON.stringify({
ota_auto: {
apply: (e.target.innerHTML == 'no'),
reboot: (e.target.parentElement.parentElement.querySelector('.auto-reboot a').innerText == 'yes'),
},
recipient: parseInt(e.target.parentElement.parentElement.parentElement.dataset.recipient),
}));
});
}
for (const apply_link of document.querySelectorAll('.auto-reboot a')) {
apply_link.addEventListener("click", function(e) {
e.preventDefault();
ws.send(JSON.stringify({
ota_auto: {
apply: (e.target.parentElement.parentElement.querySelector('.auto-apply a').innerText == 'yes'),
reboot: (e.target.innerHTML == 'no'),
},
recipient: parseInt(e.target.parentElement.parentElement.parentElement.dataset.recipient),
}));
});
}
for (const apply_link of document.querySelectorAll('[id^=ota-recipient-] button')) {
apply_link.addEventListener("click", function(e) {
e.preventDefault();
ws.send(JSON.stringify({
ota: e.target.name,
recipient: parseInt(e.target.parentElement.parentElement.dataset.recipient),
}));
});
}
{% endif %}
function connect() {
console.log('reconnecting websocket...');
var ws = new WebSocket((window.location.protocol=="https:"?"wss:":"ws:")+window.location.host+"/mesh/ui/ws", []);
ws = new WebSocket((window.location.protocol=="https:"?"wss:":"ws:")+window.location.host+"/mesh/ui/ws", []);
ws.onopen = (event) => {
console.log('websocket connected.');
{% if send_uuid %}
@ -108,7 +144,13 @@ function connect() {
var row = document.querySelector(`[id="ota-recipient-${data.update}-${data.node}"]`);
if (!row) break;
row.querySelector('.status').innerText = data.status;
if (data.status !== 'running') {
row.querySelectorAll('.auto-apply').forEach(x => x.remove());
row.querySelectorALL('.auto-reboot').forEach(x => x.remove());
row.querySelectorAll('button').forEach(x => x.remove());
}
{% endif %}
break;
case 'mesh.msg_received':
{% if ranging_form %}
@ -170,10 +212,17 @@ function connect() {
{% if update %}
var row = document.querySelector(`[id="ota-recipient-${data.msg.update_id}-${data.msg.src}"]`);
if (!row) break;
var total = parseInt(row.querySelector('.total_bytes').innerText);
row.querySelector('.received_bytes').innerText = data.msg.received_bytes;
row.querySelector('progress').value = data.msg.received_bytes;
row.querySelector('.auto-apply span').innerText = data.msg.auto_apply ? 'yes' : 'no';
row.querySelector('.auto-reboot span').innerText = data.msg.auto_reboot ? 'yes' : 'no';
row.querySelectorAll('.auto-apply a').forEach(x => x.innerText = data.msg.auto_apply ? 'yes' : 'no');
row.querySelectorAll('.auto-reboot a').forEach(x => x.innerText = data.msg.auto_reboot ? 'yes' : 'no');
row.querySelectorAll('button[name=apply]').forEach(
x => x.style.display = (received_bytes >= total && data.msg.status === "STARTED") ? 'inline-block' : 'none'
);
row.querySelectorAll('button[name=reboot]').forEach(
x => x.style.display = ((received_bytes >= total && data.msg.status === "STARTED") || data.msg.status === "APPLIED") ? 'inline-block' : 'none'
);
{% endif %}
{% if send_uuid and msg_type == "MESH_ROUTE_REQUEST" %}
if (data.msg.route) {

View file

@ -25,17 +25,19 @@
<th>{% trans 'Progress' %}</th>
</tr>
{% for recipient in update.recipients.all %}
<tr id="ota-recipient-{{ update.pk }}-{{ recipient.node_id }}">
<tr id="ota-recipient-{{ update.pk }}-{{ recipient.node_id }}" data-recipient="{{ recipient.pk }}">
<td>{% mesh_node recipient.node %}</td>
<td>
<span class="status"></span><br>
<span class="auto-apply"><strong>auto apply:</strong> <span></span><br></span>
<span class="auto-reboot"><strong>auto reboot:</strong> <span></span><br></span>
<span class="auto-apply"><strong>auto apply:</strong> <a href="#"></a><br></span>
<span class="auto-reboot"><strong>auto reboot:</strong> <a href="#"></a><br></span>
</td>
<td>
<span class="received_bytes">??</span> of {{ update.build.binary.size }} bytes
<span class="received_bytes">??</span> of <span class="total_bytes">{{ update.build.binary.size }}</span> bytes
<br>
<progress id="file" max="{{ update.build.binary.size }}" value="0"></progress>
<br>
<button name="cancel">cancel</button> <button name="apply">apply</button> <button name="reboot">apply &amp; reboot</button>
</td>
</tr>
{% endfor %}