import json from datetime import timedelta from django.utils.translation import gettext_lazy as _ from django_resized import ResizedImageField from django_celery_beat.models import PeriodicTask from django.dispatch import receiver from django.utils.text import slugify from django.utils.safestring import mark_safe from django.db.models.signals import post_save from django.db import models from modules import utils class DeviceType(models.Model): name = models.CharField(_("Nom du capteur"), max_length=64, null=True) code = models.SlugField(_("Type de capteur"), help_text=_("Max 16 caractères"), unique=True, max_length=16, null=True, blank=True) class Meta: ordering = ['name'] verbose_name = _("Type de capteur") verbose_name_plural = _("Types de capteurs") def save(self, *args, **kwargs): self.code = slugify(self.code) super().save(*args, **kwargs) def __str__(self): return f'{self.name}' class Device(models.Model): label = models.CharField(_("Capteur"), max_length=100, null=True) uuid = models.SlugField(_("Uuid"), help_text=_('Uuid iot clef unique'), unique=True, max_length=32, null=True, blank=True) device_type = models.ForeignKey(DeviceType, verbose_name=_("Type de capteur"), on_delete=models.CASCADE, null=True, blank=True, ) index = models.SmallIntegerField(_("Index"), help_text=_("Numéro d'index"), default=0) pin_active = models.BooleanField(_("Broche"), help_text=_("Broche active à l'initialisation"), default=True) image = ResizedImageField(_("Image"), help_text=_("Image du capteur"), size=[320, 240], upload_to='devices/', null=True, blank=True, default = 'devices/vanne.png') task = models.ForeignKey( PeriodicTask, verbose_name=_("Tâche périodique"), help_text=_("Tâche de démarrage périodique de ce capteur (optionnel)"), on_delete=models.CASCADE, null=True, blank=False ) lifetime = models.DurationField(_("Durée"), help_text=_("Durée de l'évènement. Jours hh:mm:ss format"), blank=True, null=True, default=timedelta(hours=1, minutes=15)) heartbeat = models.IntegerField (_("Battement"), help_text=_("Interrogation du capteur en secondes"), default=1) active = models.BooleanField(_("Actif"), default=True) def image_tag(self): return mark_safe(f'') image_tag.short_description = _("Image") image_tag.allow_tags = True def to_register(self): return dict( dev_type=self.device_type.code if self.device_type else 'None', index=self.index, key=self.uuid, label=self.label, status=0, active=1 if self.pin_active else 0, ) class Meta: ordering = ['index', ] verbose_name = _("Capteur") verbose_name_plural = _("Capteurs") @classmethod def all_devices(cls): return Device.objects.filter(active=True).all().order_by('index') @classmethod def all_devices_json(cls): devices = Device.objects.filter(active=True).all().order_by('index') buf = [] for dev in devices: buf.append({ "uuid": dev.uuid, "index": dev.index, }) return json.dumps(buf) def save(self, *args, **kwargs): if not self.uuid: self.uuid = utils.get_device_uuid(12) super().save(*args, **kwargs) def __str__(self): return f'{self.label}' @receiver(post_save, sender=Device) def create_device(sender, instance, created, **kwargs): name = f'{instance.uuid}' t = PeriodicTask.objects.filter(name__exact=name).first() if not t: p = PeriodicTask.objects.create( name=name, task='relay status', description=_('Pas encore programmé'), interval_id=1, args=json.dumps([instance.uuid]) ) instance.task_id = p.id instance.save() else: PeriodicTask.objects.filter(id=instance.task.id).update( name=name, args=json.dumps([instance.uuid]) ) instance.task.save()