Parlons de Gladys V4

Encore une fois je suis très surpris par la puissance de Sequelize!

Imaginons que je veuille aller chercher toutes les “locations” avec leur utiliateur associé.

Je fais:

j’obtiens:

Mais ce qui est intéressant c’est pas ça! C’est la manière dont Sequelize fait ça sous le capot.

Certains ORMs dans ce genre de situation font X requêtes:

  • Un SELECT * pour aller chercher toutes les lignes
  • Puis un SELECT par foreign key pour aller chercher l’attribut nested

Ici, Sequelize fait une seule requête

SELECT `t_location`.`id`, `t_location`.`user_id`, `t_location`.`latitude`, `t_location`.`longitude`, `t_location`.`altitude`, `t_location`.`accuracy`, `t_location`.`created_at`, `t_location`.`updated_at`, 
`user`.`id` AS `user.id`, `user`.`firstname` AS `user.firstname`, `user`.`lastname` AS `user.lastname`, `user`.`email` AS `user.email`, `user`.`birthdate` AS `user.birthdate`, `user`.`language` AS `user.language`, `user`.`password_hash` AS `user.password_hash`, `user`.`role` AS `user.role`, `user`.`created_at` AS `user.created_at`, `user`.`updated_at` AS `user.updated_at`
FROM `t_location` AS `t_location`
LEFT OUTER JOIN `t_user` AS `user` ON `t_location`.`user_id` = `user`.`id`;

Puis il recompose l’objet nested à l’aide de son format “table.attribut” dans les “AS”

C’est super perf!

Comme je disais plus haut c’était work in progress, je viens de pousser les index :slight_smile:

Ok je comprends l’idée!

C’est plus une question de nommage en fait + une finesse dans la granularité des types en fait.

J’aime bien l’idée des types assez fin.

Ce que j’arrive pas à comprendre chez toi, prenons ton exemple par exemple:

category: "light"
sub-category": "dimmable"

Qu’est ce que ça veut dire pour toi? Dans l’UI qu’est ce qu’on affiche?

Après j’aime bien l’idée des types plus fin que juste « binary », « multilevel » et « color ».

Si dans l’idée on prend une catégorie assez général + une sous catégorie (à voir pour le nommage, je trouve que nommer ça « type » est plus cohérent), que dis-tu de ce schéma ? (je viens de le dessiner)

(désolé si c’est dur à lire, de gauche à droite « light », « sensor », « switch », « fan », « door lock »)

Ce qu’il faut juste faire après, c’est que pour chaque couple (categorie/type) on ait une fonction qui retourne le genre de bouton à afficher, mais bon c’est pas très compliqué ça.

1 « J'aime »

Tu n’as pas dis ce que tu pensais de mon schéma!

Je t’avoue que je ne comprends plus totalement tout par contre là ^^

Parameters c’est pas redondant avec subcategory?

Pour revenir à notre modélisation pour qu’on parte sur des bonnes bases.

Est-ce qu’on est d’accord que:

  • Un Device c’est un périphérique physique, un objet.
  • Une Feature (qu’on appelle “DeviceFeature” pour que ça soit plus facilement compréhensible dans la DB, mais en gros c’est une feature), c’est une fonctionnalité d’un device.

?

Exemple:

Mon périphérique “Ampoule 1 Philips Hue” possède 3 fonctionnalités:

  • On/Off
  • Faire varier la luminosité
  • Faire varier la couleur

On pourrait donc représenter ce périphérique:

{
  "name": "Ampoule 1",
  "service_id": "1ec7966f-e3ef-47d7-9aef-083a59956a68",
  "features": [{
      "category": "light",
      "type/sub_category": "binary"
    },
    {
      "category": "light",
      "type/sub_category": "brightness"
    },
    {
      "category": "light",
      "type/sub_category": "color"
    }
  ]
}

Il y a de l’idée dans ton excel mais est-ce que tu pourrais un peu me donner des exemples de ce que tu vois? (à la manière de ce que j’ai fais là).

Je ne comprends pas la hiérarchie et la logique derrière chaque entité/attribut que tu me présentes.

J’aime bien la notion de paramètres qui est hyper utile pour le Z-wave, mais comment on stocke ça?

Je me rappelle qu’on en avait déjà parlé avec @MathieuA, ça pourrait être un attribut “parameters” boolean dans un deviceFeature ce qui permettrait de dire si un DeviceFeature est un paramètres où un vrai fonctionnalité.

1 « J'aime »

Salut à tous!

Je continue mes réflexions, cette fois-ci sur le style de code que va avoir la partie script/voir le core et les modules.

1/ Première approche, très orientée-objet:

Contrôler un périphérique:

const kitchenLight = await gladys.device.findOneBySelector('kitchen-main-light');
await kitchenLight.turnOn();
await kitchenLight.setBrightness(10);
await gladys.helpers.wait(100);
await kitchenLight.setBrightness(20);

Contrôler un ensemble de périphériques:

const kitchenLightGroup = await gladys.device.find('kitchen.light'); // ROOM_SELECTOR.CATEGORY
await kitchenLightGroup.turnOn();
await kitchenLightGroup.addBrightness(10);

2/ Deuxième approche, plus fonctionnelle comme on a actuellement:

await gladys.device.turnOn('kitchen-main-light');
await gladys.device.setBrightness('kitchen-main-light', 10);
await gladys.helpers.wait(100);
await gladys.device.setBrightness('kitchen-main-light', 20);
await gladys.device.turnOn('kitchen.light');
await gladys.device.addBrightness('kitchen.light', 10);

Petite analyse

Les deux approchent sont très différentes et ont des implications très différentes.

1/ Dans le premier cas, après réception des données de la BDD il faudra construire ces objets en fonction de chaque catégorie de périphérique, et rajouter toute cette couche objet. C’est assez proche de l’approche que tu avais mis sur ce channel @piznel avec le repo abstract-things.

J’aime bien visuellement ce que ça donne, ça fait propre et c’est assez sexy pour attirer des devs. Donc sur l’aspect syntaxe et communication c’est un + pour moi.

Après ma crainte c’est qu’on souhaite étendre cette logique à plein d’endroits, et ça peut être une lourdeur là où nous aimerait un soft plutôt léger et simple d’utilisation. Je suis pas persuadé qu’une approche objet ait un sens dans un backend. Un backend pour moi c’est avant tout juste un bridge qui fait du CRUD entre la DB et le frontend, pas forcément besoin de créer des objets qui peuvent être lourd en mémoire et apporte une complexité de développement.

2/ J’aime moins visuellement ce que ça donne, c’est moins sexy c’est sûr.

Après on sait clairement ce qui se passe, et en terme de management de la mémoire le boulot est donné au core: on appelle la fonction, la fonction fait son boulot, et hop c’est fini.

Conclusion

Je sais pas si c’est un choix entre l’un ou l’autre, on peut avoir une approche hybride.

J’aimerais avoir votre avis, c’est clairement un petit débat sympa :slight_smile:

Mmm la par contre je ne suis pas d’accord, on stockerait de l’information trop spécialisée et dupliquée du coup.

1/

light_dimmable: je ne comprends pas l’objectif d’avoir ça. Tu stockes 2 informations dans un champ: que c’est un périphérique qui gère de la lumière + que ce périphérique est dimmable. Là dessus je te renvoie aux dépendances fonctionnelles en base de donnée :smiley:

Si je demande à Gladys “Allume la lumière du salon”, il faut que Gladys ait un moyen d’identifier tous les périphériques gérant de la lumière (que ce soit dimmable ou non n’a peu d’importance dans cette question, c’est une information secondaire).

2/ En revanche la question de remonter la category au device est une vraie question. Pour l’instant elle est dans DeviceFeature parce-que certains périphériques (je pense au Z-Wave notamment) font un peu tout, et du coup on avait mis la category dans le deviceType pour gérer ces device “hybrides”.

Après la question se pose. Si tu as une caméra de surveillance qui fait aussi capteur de température et capteur de mouvement? Si tu as une porte qui remonte aussi des données de température et d’humidité? Comment on les classifie?

Si vous avez des exemples de périphériques bizarre je suis preneur!

Personnellement je suis pour remonter la category au device, c’est plus clair.

Je pense que le mieux pour définir tout ça, ça reste de voir des vrais cas!

Excellent cas!

Du coup, quelle category aurait ce périphérique si on se dit qu’on remonte category dans device?

1/ Je suis pas fan de séparer un périphérique en 3 périphériques, c’est pas logique par notre définition « un device est un périphérique physique ».

2/ Si on lui donne comme catégorie « bridge » par exemple.

Un deviceFeature de type « binary » n’a plus de sens: est-ce que c’est pour allumer le gateway (on/off?) ou allumer la lumière du gateway?

Du coup on en revient à devoir remettre côté deviceFeature une category supplémentaire pour dire « cette feature c’est de la gestion de la lumière »

PS: quand je vous disais que la partie modélisation c’est 80% du travail, je rigolais pas :stuck_out_tongue: Le code c’est rien!

En périphérique “bizarre” il y a aussi le Fibaro FGMS-001 (en Zwave) qui agit comme détecteur de mouvement, capteur de température, capteur de luminosité et capteur de vibration il me semble :slight_smile:

Mmm ok :stuck_out_tongue:

Dommage j’aimais bien l’idée de mettre la category sur le device, mais bon ça nous restreint trop…

Donc on est d’accord, on garde la category + le type sur le DeviceFeature?

Je t’avoue qu’en terme de nommage je préfère “type” à “sub-category”.

Je suis d’accord que c’est cool d’avoir des types plus fin par contre!

Donc au lieu d’avoir:

  • binary
  • multilevel
  • color

On aurait des types plus riches:

  • binary
  • brightness
  • temperature
  • color

comme mon schéma plus haut! Petit rappel:

1 « J'aime »

Un autre point dont on a pas parlé, c’est les fameux paramètres des device/deviceFeature!

Z-wave a des paramètres par périphérique, et actuellement c’est mélangé avec les deviceFeature (pas terrible)

On pourrait rajouter un attribut dans deviceFeature pour indiquer que la feature est un paramètre.

Problème: si le paramètre est un string on fait comment?

Exemple: si on veut stocker l’URL d’une caméra dans Device/DeviceFeature par ex.

ça pourrait être une autre table…

Autre idée qui n’a rien à voir: Mettre un booléen dans DeviceFeature pour activer l’historisation des valeurs ou pas (très pratique pour certain détecteur qui envoie de la valeur et dont on veut pas forcément historiser les valeurs)

(je dump mes idées comme ça)

Petite modélisation de ce que ça pourrait donner:

J’y ai pensé mais ça marche pas dans le cas du z-wave! il envoie les paramètres un par un comme si c’était des features, et du coup il faudrait faire une opération lourde de:

  • SELECT Device
  • Ajouter dans le JSON la valeur
  • UPDATE device

Alors que là c’est en une opération!

Et surtout, j’aime mieux l’aspect relationnel pour tout ce qui est exposé aux développeurs, ça doit être strict en DB sinon c’est le zouk en 30 secondes ^^

Les rares endroits ou on va faire du JSON dans la DB gladys c’est pour des raisons très précises!

J’ai pas trop d’avis car pas beaucoup d’expérience dans tout ça mais votre réflexion est très intéressante les gars.

3 « J'aime »

Ce matin j’ai pas mal travaillé sur le sujet des « modules » qui deviennent des « services » dans Gladys 4.

J’ai écris une documentation + codé un service example de bout en bout (tests inclus), afin de montrer à quoi ressemble un service dans Gladys 4.

Ce n’est qu’un premier jet, je ferais sûrement des révisions en fonction de vos retours :slight_smile:

Le README et le code est disponible ici =>

https://github.com/GladysAssistant/gladys-4-playground/tree/master/server/services/example

Merci @VonOx! :slight_smile:

1 « J'aime »

Bon je suis passé en mode wireframe, j’ai bossé sur le process d’onboarding.

Pour l’instant j’ai identifié 6 étapes:

1/ Bienvenue: Gladys accueille l’utilisateur. Petit rappel de la philosophie du projet, des valeurs et l’historique.

2/ Création du compte local: nom, email, mot de passe & répétition du mot de passe

3/ Configuration du logement: Enregistrement du nom de la maison, et ajout des pièces

**4/ Ajout des périphériques: ** L’utilisateur ajoute ses périphérique. Il a une search box et il peut sélectionner les intégrations qu’il veut configurer. (Optionnel)

5/ Configuration des notifications: Pour rester en contact avec Gladys, Gladys propose de configurer les services de communications: Telegram, SMS free, etc… (Optionnel)

6/ Connexion au compte Gladys Gateway: Présentation du Gateway, et connexion. (Optionnel)

Si vous pensez à d’autres étapes, ,n’hésitez pas!

2 « J'aime »

Salut à tous!

J’espère que vous avez passé un bon week-end.

Hier et ce matin j’ai travaillé sur la définition des états / des transitions entre états. Cela peut paraître un sujet tout bête, mais c’est une vraie réflexion.

Chaque entité dans Gladys est un automate fini avec plusieurs états et des transitions entre chaque état. Ces états et ces transitions il faut les définir et les nommer.

Le sommeil d’un utilisateur

4 états:

  • Réveillé
  • Endormi
  • Doit se réveiller
  • Doit se coucher

Voilà le schéma des transitions. Chaque transition correspond à un événement dans Gladys, un “trigger” sur lequel n’importe quel scène peut se brancher.

L’alarme de la maison

Dans Gladys 4, j’amène la notion d’alarme pour la maison afin que Gladys puisse enfin est une centrale d’alarme propre et clair.

Comme le sommeil, 4 états:

  • Armée
  • Désarmée
  • En cours de tentative d’armement
  • En cours de tentative de désarmement

La présence à la maison des utilisateurs

L’exécution d’une scène

L’état du soleil

La présence au travail

Enfin exemple d’un périphérique de category "light"

Si ces exemples vous parle/vous font réagir, n’hésitez pas, rien n’est figé :slight_smile:

Oui tu parles de scenario, les graphes c’est le Flow entre les états.

Et il y’a bien l’état armed pour l’alarme.

En fait dans ce diagramme effectivement j’avais assumé que la partie « activation » de l’alarme était plus côté scénario, après je pense que tu as raison, ça vaudrait le coup de le mettre là, au moins pour définir les noms des différentes transitions :slight_smile:

Merci du retour!

Salut à tous!

Aujourd’hui gros boulot sur le frontend, je suis dans le dur du sujet :slight_smile:

Voilà un petit preview, vous avez des retours/idées pour l’organisation de la barre de navigation je suis preneur!

Pour le login j’hésite entre deux version…

Dites moi ce que vous en pensez!

1 « J'aime »

Avec logo pour le login pour moi. :stuck_out_tongue:
D’ailleurs, tu renommes pas Gladys Assistant également dans le dashboard ?

Je pense partir sur ça, sur Twitter tout le monde est unanime :stuck_out_tongue:

Bien vu! :slight_smile:

Nouvelle page, les integrations:

Hello @piznel! :slight_smile: Top tout ça!

Chaque périphérique Z-Wave a des paramètres (ex: fréquence de rafraichissement, sensibilité du capteur luminosité, seuil de détection d’un intru, etc…) que tu peux régler. J’ai proposé un DeviceParam pour pouvoir stocker ces paramètres, qui pour moi ne sont pas vraiment des features, ce sont des paramètres.

Ce DeviceParam pourrait servir à stocker d’autres choses, exemple: les credentials d’une caméra IP, ou autre.

Tu vois l’idée?

ça y est Philippe la machine est de retour :smiley:

ça se rapproche de ce qu’on s’est dit je trouve non? une category + un type?

A la différence de quelques différences de nommage, mais l’idée est la même!

Je suis 100% d’accord pour harmoniser!

Il faut qu’on fasse un choix qui ratisse assez large pour pas perdre d’information sur les périphériques qui permettent des valeurs fines, et il faudra convertir la couleur avant de l’enregistrer dans Gladys.

Le module hue c’est compliqué, tu as 3 deviceType: hue et saturation et brightness, c’est du HSL si je me trompe pas.

Milight j’ai l’impression qu’ils font du RGV mais il y a des fonctions de conversions HSL dans ce module par exemple => https://www.npmjs.com/package/node-milight-promise (rapide recherche)

A nous de décider quel format on préfère dans Gladys, et à coder les différents getters/setters dans Gladys 4 pour que le module puisse juste envoyer ses data

1 « J'aime »