add possibility to set LED_CONFIG message
This commit is contained in:
parent
c5ac3ceb76
commit
e0961c16c1
5 changed files with 137 additions and 36 deletions
|
@ -17,19 +17,41 @@
|
||||||
</div>
|
</div>
|
||||||
<div>
|
<div>
|
||||||
<h4>Uplink</h4>
|
<h4>Uplink</h4>
|
||||||
<strong>Enabled:</strong> {{ node.last_messages.CONFIG_UPLINK.parsed.enabled }},
|
<p>
|
||||||
<strong>SSID:</strong> {{ node.last_messages.CONFIG_UPLINK.parsed.ssid }},
|
<strong>Enabled:</strong> {{ node.last_messages.CONFIG_UPLINK.parsed.enabled }},
|
||||||
<strong>Channel:</strong> {{ node.last_messages.CONFIG_UPLINK.parsed.channel }}<br>
|
<strong>SSID:</strong> {{ node.last_messages.CONFIG_UPLINK.parsed.ssid }},
|
||||||
<strong>Host:</strong> {{ node.last_messages.CONFIG_UPLINK.parsed.host }},
|
<strong>Channel:</strong> {{ node.last_messages.CONFIG_UPLINK.parsed.channel }}<br>
|
||||||
<strong>Port:</strong> {{ node.last_messages.CONFIG_UPLINK.parsed.port }},
|
<strong>Host:</strong> {{ node.last_messages.CONFIG_UPLINK.parsed.host }},
|
||||||
<strong>UDP:</strong> {{ node.last_messages.CONFIG_UPLINK.parsed.udp }},
|
<strong>Port:</strong> {{ node.last_messages.CONFIG_UPLINK.parsed.port }},
|
||||||
<strong>SSL:</strong> {{ node.last_messages.CONFIG_UPLINK.parsed.ssl }}
|
<strong>UDP:</strong> {{ node.last_messages.CONFIG_UPLINK.parsed.udp }},
|
||||||
|
<strong>SSL:</strong> {{ node.last_messages.CONFIG_UPLINK.parsed.ssl }}<br>
|
||||||
|
</p>
|
||||||
|
<p>
|
||||||
|
<a class="button" href="{% url "control.mesh_message.send" recipient=node.address msg_type="CONFIG_UPLINK" %}">
|
||||||
|
{% trans 'Change' %}
|
||||||
|
</a>
|
||||||
|
</p>
|
||||||
|
|
||||||
|
|
||||||
<h4>Position</h4>
|
<h4>Position</h4>
|
||||||
<strong>X=</strong>{{ node.last_messages.CONFIG_POSITION.parsed.x_pos }}, <strong>Y=</strong>{{ node.last_messages.CONFIG_POSITION.parsed.y_pos }}, <strong>Z=</strong>{{ node.last_messages.CONFIG_POSITION.parsed.z_pos }}
|
<p>
|
||||||
|
<strong>X=</strong>{{ node.last_messages.CONFIG_POSITION.parsed.x_pos }}, <strong>Y=</strong>{{ node.last_messages.CONFIG_POSITION.parsed.y_pos }}, <strong>Z=</strong>{{ node.last_messages.CONFIG_POSITION.parsed.z_pos }}
|
||||||
|
</p>
|
||||||
|
<p>
|
||||||
|
<a class="button" href="{% url "control.mesh_message.send" recipient=node.address msg_type="CONFIG_POSITION" %}">
|
||||||
|
{% trans 'Change' %}
|
||||||
|
</a>
|
||||||
|
</p>
|
||||||
|
|
||||||
<h4>LED config</h4>
|
<h4>LED config</h4>
|
||||||
{{ node.last_messages.CONFIG_LED.parsed.led_config }}
|
<p>
|
||||||
|
{{ node.last_messages.CONFIG_LED.parsed.led_config }}
|
||||||
|
</p>
|
||||||
|
<p>
|
||||||
|
<a class="button" href="{% url "control.mesh_message.send" recipient=node.address msg_type="CONFIG_LED" %}">
|
||||||
|
{% trans 'Change' %}
|
||||||
|
</a>
|
||||||
|
</p>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
{% endblock %}
|
{% endblock %}
|
||||||
|
|
|
@ -109,7 +109,7 @@ class MeshConsumer(WebsocketConsumer):
|
||||||
def add_dst_nodes(self, addresses):
|
def add_dst_nodes(self, addresses):
|
||||||
for address in addresses:
|
for address in addresses:
|
||||||
# create group name for this address
|
# create group name for this address
|
||||||
group = self.comm_address_group(address)
|
group = get_mesh_comm_group(address)
|
||||||
|
|
||||||
# if we aren't handling this address yet, join the group
|
# if we aren't handling this address yet, join the group
|
||||||
if address not in self.dst_nodes:
|
if address not in self.dst_nodes:
|
||||||
|
@ -140,7 +140,7 @@ class MeshConsumer(WebsocketConsumer):
|
||||||
def remove_dst_nodes(self, addresses):
|
def remove_dst_nodes(self, addresses):
|
||||||
for address in tuple(addresses):
|
for address in tuple(addresses):
|
||||||
# create group name for this address
|
# create group name for this address
|
||||||
group = self.comm_address_group(address)
|
group = get_mesh_comm_group(address)
|
||||||
|
|
||||||
# leave the group
|
# leave the group
|
||||||
if address in self.dst_nodes:
|
if address in self.dst_nodes:
|
||||||
|
|
|
@ -138,14 +138,3 @@ class LedConfigFormat:
|
||||||
else:
|
else:
|
||||||
raise ValueError
|
raise ValueError
|
||||||
return value, data[4:]
|
return value, data[4:]
|
||||||
|
|
||||||
def from_json(self, value):
|
|
||||||
if value is None:
|
|
||||||
return None
|
|
||||||
|
|
||||||
type_ = value.pop('type')
|
|
||||||
if type_ == 'serial':
|
|
||||||
return SerialLedConfig(**value)
|
|
||||||
elif type_ == 'multipin':
|
|
||||||
return MultipinLedConfig(**value)
|
|
||||||
raise ValueError
|
|
||||||
|
|
|
@ -1,7 +1,11 @@
|
||||||
|
from dataclasses import fields as dataclass_fields
|
||||||
|
|
||||||
from django import forms
|
from django import forms
|
||||||
|
from django.core.exceptions import ValidationError
|
||||||
from django.http import Http404
|
from django.http import Http404
|
||||||
from django.utils.translation import gettext_lazy as _
|
from django.utils.translation import gettext_lazy as _
|
||||||
|
|
||||||
|
from c3nav.mesh.dataformats import LedConfig
|
||||||
from c3nav.mesh.messages import MeshMessageType, MeshMessage, ROOT_ADDRESS
|
from c3nav.mesh.messages import MeshMessageType, MeshMessage, ROOT_ADDRESS
|
||||||
from c3nav.mesh.models import MeshNode
|
from c3nav.mesh.models import MeshNode
|
||||||
|
|
||||||
|
@ -54,6 +58,29 @@ class MeshMessageForm(forms.Form):
|
||||||
def get_recipient_display(self):
|
def get_recipient_display(self):
|
||||||
return self.recipient_choices[self.recipient]
|
return self.recipient_choices[self.recipient]
|
||||||
|
|
||||||
|
def get_cleaned_msg_data(self):
|
||||||
|
msg_data = self.cleaned_data.copy()
|
||||||
|
msg_data.pop('recipients', None)
|
||||||
|
return msg_data
|
||||||
|
|
||||||
|
def send(self):
|
||||||
|
if not self.is_valid():
|
||||||
|
raise Exception('nope')
|
||||||
|
|
||||||
|
msg_data = {
|
||||||
|
'msg_id': self.msg_type,
|
||||||
|
'src': ROOT_ADDRESS,
|
||||||
|
**self.get_cleaned_msg_data(),
|
||||||
|
}
|
||||||
|
|
||||||
|
recipients = [self.recipient] if self.recipient else self.cleaned_data['recipients']
|
||||||
|
for recipient in recipients:
|
||||||
|
print('sending to ', recipient)
|
||||||
|
MeshMessage.fromjson({
|
||||||
|
'dst': recipient,
|
||||||
|
**msg_data,
|
||||||
|
}).send()
|
||||||
|
|
||||||
|
|
||||||
class ConfigUplinkMessageForm(MeshMessageForm):
|
class ConfigUplinkMessageForm(MeshMessageForm):
|
||||||
msg_type = MeshMessageType.CONFIG_UPLINK
|
msg_type = MeshMessageType.CONFIG_UPLINK
|
||||||
|
@ -67,20 +94,76 @@ class ConfigUplinkMessageForm(MeshMessageForm):
|
||||||
host = forms.CharField(required=False, label=_('host'), max_length=63)
|
host = forms.CharField(required=False, label=_('host'), max_length=63)
|
||||||
port = forms.IntegerField(min_value=1, max_value=65535, label=_('port'))
|
port = forms.IntegerField(min_value=1, max_value=65535, label=_('port'))
|
||||||
|
|
||||||
def send(self):
|
|
||||||
if not self.is_valid():
|
|
||||||
raise Exception('nope')
|
|
||||||
|
|
||||||
msg_data = {
|
class ConfigLedMessageForm(MeshMessageForm):
|
||||||
'msg_id': self.msg_type,
|
msg_type = MeshMessageType.CONFIG_LED
|
||||||
'src': ROOT_ADDRESS,
|
|
||||||
**self.cleaned_data,
|
led_type = forms.ChoiceField(choices=(
|
||||||
|
('', _('no LED')),
|
||||||
|
(1, _('serial LED')),
|
||||||
|
(2, _('multipin LED'))
|
||||||
|
))
|
||||||
|
gpio = forms.IntegerField(min_value=0, max_value=48, required=False,
|
||||||
|
label=_('gpio pin'), help_text=_('serial only'))
|
||||||
|
rmt = forms.IntegerField(min_value=0, max_value=7, required=False,
|
||||||
|
label=_('rmt'), help_text=_('serial only'))
|
||||||
|
gpio_r = forms.IntegerField(min_value=0, max_value=48, required=False,
|
||||||
|
label=_('gpio red'), help_text=_('multipin only'))
|
||||||
|
gpio_g = forms.IntegerField(min_value=0, max_value=48, required=False,
|
||||||
|
label=_('gpio green'), help_text=_('multipin only'))
|
||||||
|
gpio_b = forms.IntegerField(min_value=0, max_value=48, required=False,
|
||||||
|
label=_('gpio blue'), help_text=_('multipin only'))
|
||||||
|
|
||||||
|
def clean(self):
|
||||||
|
cleaned_data = super().clean()
|
||||||
|
|
||||||
|
led_type = int(cleaned_data["led_type"])
|
||||||
|
if led_type:
|
||||||
|
required_fields = set(field.name for field in dataclass_fields(LedConfig.ledconfig_types[led_type]))
|
||||||
|
else:
|
||||||
|
required_fields = set()
|
||||||
|
|
||||||
|
errors = {}
|
||||||
|
led_config = {
|
||||||
|
"led_type": led_type
|
||||||
}
|
}
|
||||||
|
|
||||||
recipients = [self.recipient] if self.recipient else self.cleaned_data['recipients']
|
for key, value in cleaned_data.items():
|
||||||
for recipient in recipients:
|
if key == "recipients":
|
||||||
print('sending to ', recipient)
|
continue
|
||||||
MeshMessage.fromjson({
|
if value and key not in required_fields:
|
||||||
'dst': recipient,
|
errors[key] = _("this field is not allowed for this LED type")
|
||||||
**msg_data,
|
|
||||||
}).send()
|
for key in required_fields:
|
||||||
|
value = cleaned_data.pop(key, "")
|
||||||
|
if value == "":
|
||||||
|
errors[key] = _("this field is required for this LED type")
|
||||||
|
led_config[key] = value
|
||||||
|
|
||||||
|
cleaned_data["led_config"] = led_config
|
||||||
|
|
||||||
|
if errors:
|
||||||
|
raise ValidationError(errors)
|
||||||
|
|
||||||
|
return cleaned_data
|
||||||
|
|
||||||
|
def get_cleaned_msg_data(self):
|
||||||
|
msg_data = super().get_cleaned_msg_data().copy()
|
||||||
|
msg_data = {
|
||||||
|
"led_config": msg_data["led_config"],
|
||||||
|
}
|
||||||
|
return msg_data
|
||||||
|
|
||||||
|
def __init__(self, *args, initial=None, **kwargs):
|
||||||
|
if initial:
|
||||||
|
initial.update(initial.pop('led_config'))
|
||||||
|
super().__init__(*args, initial=initial, **kwargs)
|
||||||
|
|
||||||
|
|
||||||
|
class ConfigPositionMessageForm(MeshMessageForm):
|
||||||
|
msg_type = MeshMessageType.CONFIG_POSITION
|
||||||
|
|
||||||
|
x_pos = forms.IntegerField(min_value=0, max_value=2**16-1, label=_('X'))
|
||||||
|
y_pos = forms.IntegerField(min_value=0, max_value=2 ** 16 - 1, label=_('Y'))
|
||||||
|
z_pos = forms.IntegerField(min_value=0, max_value=2 ** 16 - 1, label=_('Z'))
|
||||||
|
|
||||||
|
|
|
@ -1351,3 +1351,10 @@ button + button {
|
||||||
.material-icons {
|
.material-icons {
|
||||||
text-transform: none !important;
|
text-transform: none !important;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.helptext {
|
||||||
|
display: block;
|
||||||
|
margin-top: -1.5rem;
|
||||||
|
font-style: italic;
|
||||||
|
margin-bottom: 1.5rem;
|
||||||
|
}
|
Loading…
Add table
Add a link
Reference in a new issue