mesh debugging and control
This commit is contained in:
parent
4c40597cd3
commit
df6efbc8d5
11 changed files with 201 additions and 12 deletions
|
@ -4,7 +4,7 @@ from channels.db import database_sync_to_async
|
|||
from channels.generic.websocket import AsyncWebsocketConsumer
|
||||
|
||||
from c3nav.mesh import messages
|
||||
from c3nav.mesh.models import MeshNode, NodeMessage
|
||||
from c3nav.mesh.models import MeshNode, NodeMessage, Firmware
|
||||
|
||||
|
||||
class MeshConsumer(AsyncWebsocketConsumer):
|
||||
|
@ -69,6 +69,16 @@ class MeshConsumer(AsyncWebsocketConsumer):
|
|||
|
||||
await self.log_received_message(msg)
|
||||
|
||||
if isinstance(msg, messages.ConfigFirmwareMessage):
|
||||
await self._handle_config_firmware_msg(msg)
|
||||
return
|
||||
|
||||
@database_sync_to_async
|
||||
def _handle_config_firmware_msg(self, msg):
|
||||
self.firmware, created = Firmware.objects.get_or_create(**msg.to_model_data())
|
||||
self.node.firmware = self.firmware
|
||||
self.node.save()
|
||||
|
||||
@database_sync_to_async
|
||||
def get_node(self, address):
|
||||
return MeshNode.objects.get_or_create(address=address)
|
||||
|
@ -100,3 +110,8 @@ class MeshConsumer(AsyncWebsocketConsumer):
|
|||
@database_sync_to_async
|
||||
def remove_route_to_nodes(self, route_address, node_addresses):
|
||||
MeshNode.objects.filter(address__in=node_addresses, route_id=route_address).update(route_id=None)
|
||||
|
||||
@database_sync_to_async
|
||||
def set_node_firmware(self, firmware):
|
||||
self.node.firmware = firmware
|
||||
self.node.save()
|
|
@ -112,6 +112,8 @@ class ConfigDumpMessage(Message, msg_id=MessageType.CONFIG_DUMP):
|
|||
|
||||
@dataclass
|
||||
class ConfigFirmwareMessage(Message, msg_id=MessageType.CONFIG_FIRMWARE):
|
||||
chip: int = field(metadata={'format': SimpleFormat('H')})
|
||||
revision: int = field(metadata={'format': SimpleFormat('2B')})
|
||||
magic_word: int = field(metadata={'format': SimpleFormat('I')}, repr=False)
|
||||
secure_version: int = field(metadata={'format': SimpleFormat('I')})
|
||||
reserv1: list[int] = field(metadata={'format': SimpleFormat('2I')}, repr=False)
|
||||
|
@ -123,6 +125,15 @@ class ConfigFirmwareMessage(Message, msg_id=MessageType.CONFIG_FIRMWARE):
|
|||
app_elf_sha256: str = field(metadata={'format': HexFormat(32)})
|
||||
reserv2: list[int] = field(metadata={'format': SimpleFormat('20I')}, repr=False)
|
||||
|
||||
def to_model_data(self):
|
||||
return {
|
||||
'chip': self.chip,
|
||||
'project_name': self.project_name,
|
||||
'version': self.version,
|
||||
'idf_version': self.idf_version,
|
||||
'sha256_hash': self.app_elf_sha256,
|
||||
}
|
||||
|
||||
|
||||
@dataclass
|
||||
class ConfigPositionMessage(Message, msg_id=MessageType.CONFIG_POSITION):
|
||||
|
|
|
@ -0,0 +1,27 @@
|
|||
# Generated by Django 4.2.1 on 2023-10-02 19:44
|
||||
|
||||
from django.db import migrations, models
|
||||
import django.db.models.deletion
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
dependencies = [
|
||||
('mesh', '0001_initial'),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.AlterUniqueTogether(
|
||||
name='firmware',
|
||||
unique_together={('chip', 'project_name', 'version', 'idf_version', 'sha256_hash')},
|
||||
),
|
||||
migrations.AddField(
|
||||
model_name='meshnode',
|
||||
name='firmware',
|
||||
field=models.ForeignKey(null=True, on_delete=django.db.models.deletion.PROTECT, related_name='installed_on', to='mesh.firmware', verbose_name='firmware'),
|
||||
),
|
||||
migrations.RemoveField(
|
||||
model_name='firmware',
|
||||
name='compile_time',
|
||||
),
|
||||
]
|
18
src/c3nav/mesh/migrations/0003_meshnode_name.py
Normal file
18
src/c3nav/mesh/migrations/0003_meshnode_name.py
Normal file
|
@ -0,0 +1,18 @@
|
|||
# Generated by Django 4.2.1 on 2023-10-02 19:56
|
||||
|
||||
from django.db import migrations, models
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
dependencies = [
|
||||
('mesh', '0002_alter_firmware_unique_together_meshnode_firmware_and_more'),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.AddField(
|
||||
model_name='meshnode',
|
||||
name='name',
|
||||
field=models.CharField(blank=True, max_length=32, null=True, verbose_name='name'),
|
||||
),
|
||||
]
|
|
@ -11,13 +11,18 @@ class ChipID(models.IntegerChoices):
|
|||
|
||||
class MeshNode(models.Model):
|
||||
address = models.CharField(_('mac address'), max_length=17, primary_key=True)
|
||||
name = models.CharField(_('name'), max_length=32, null=True, blank=True)
|
||||
first_seen = models.DateTimeField(_('first seen'), auto_now_add=True)
|
||||
parent_node = models.ForeignKey('MeshNode', models.PROTECT, null=True,
|
||||
related_name='child_nodes', verbose_name=_('parent node'))
|
||||
route = models.ForeignKey('MeshNode', models.PROTECT, null=True,
|
||||
related_name='routed_nodes', verbose_name=_('route'))
|
||||
firmware = models.ForeignKey('Firmware', models.PROTECT, null=True,
|
||||
related_name='installed_on', verbose_name=_('firmware'))
|
||||
|
||||
def __str__(self):
|
||||
if self.name:
|
||||
return '%s (%s)' % (self.address, self.name)
|
||||
return self.address
|
||||
|
||||
|
||||
|
@ -38,11 +43,10 @@ class Firmware(models.Model):
|
|||
project_name = models.CharField(_('project name'), max_length=32)
|
||||
version = models.CharField(_('firmware version'), max_length=32)
|
||||
idf_version = models.CharField(_('IDF version'), max_length=32)
|
||||
compile_time = models.DateTimeField(_('compile time'))
|
||||
sha256_hash = models.CharField(_('SHA256 hash'), unique=True, max_length=64)
|
||||
binary = models.FileField(_('firmware file'), null=True)
|
||||
|
||||
class Meta:
|
||||
unique_together = [
|
||||
('chip', 'project_name', 'version', 'idf_version', 'compile_time', 'sha256_hash'),
|
||||
('chip', 'project_name', 'version', 'idf_version', 'sha256_hash'),
|
||||
]
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue