Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Sonoff service (over MQTT) #519

Merged
merged 34 commits into from Oct 25, 2019

Conversation

atrovato
Copy link
Contributor

@atrovato atrovato commented Aug 8, 2019

Pull Request check-list

To ensure your Pull Request can be accepted as fast as possible, make sure to review and check all of these items:

  • If your changes affects code, did your write the tests?
  • Are tests passing? (npm test on both front/server)
  • Is the linter passing? (npm run eslint on both front/server)
  • Did you run prettier? (npm run prettier on both front/server)
  • If your changes modify the API (REST or Node.js), did you modify the API documentation? (Documentation is based on comments in code)
  • If you are adding a new features/services which needs explanation, did you modify the user documentation? See the GitHub repo and the website.
  • Did you add fake requests data for the demo mode (front/src/config/demo.json) so that the demo website is working without a backend? (if needed) See https://demo.gladysassistant.com.

NOTE: these things are not required to open a PR and can be done afterwards / while the PR is open.

Description of change

Completes the MQTT service with Sonoff management according to V3 modules.

@atrovato atrovato changed the title Sonoff mqtt service Sonoff + owntracks MQTT service Aug 8, 2019
@atrovato
Copy link
Contributor Author

@Pierre-Gilles J'ai un problème de conception sur les "sous-services" MQTT.
J'ai complété le service MQTT "générique", mais par exemple pour Sonoff ou Owntracks, je reste un peu bloqué. Pour le moment j'ai fait le choix de garder un seul service MQTT et de prendre en compte les devices des "sous-services" avec un device.param particulier, mais cela pose un problème pour le listing des devices.
As-tu déjà penser à une solution pour ces cas la ?

Peut-être faut-il créer un service Sonoff, un service Owntracks... utilisant le service MQTT ?

Un point de réflexion reste ouvert.

@Pierre-Gilles
Copy link
Contributor

Pierre-Gilles commented Aug 13, 2019

@atrovato Je comprend le problème!

Partons de l'expérience utilisateur, pas de la tech

Côté front, ça fait sens d'avoir une interface dédié "Owntracks", et une interface dédié "Sonoff". Si je suis utilisateur, et que j'ai des périphériques Sonoff, j'ai envie de cliquer sur une icône "Sonoff" et d'avoir un bloc qui explique comment configurer tout ça. Pareil pour Owntracks: je suis utilisateur Owntracks, je m'attend à voir une intégration "Owntracks" dans l'interface, on est d'accord ? On ne doit pas présupposer que l'utilisateur sache comment ça marche sous le capot, du moins pas avant de lui avoir expliqué dans une intégration dédié au périphérique.

Côté back, à voir si on sépare ou non. Deux solutions pour moi:

  • Est-ce que c'est plus clair d'avoir côté back dans le service MQTT la liste de tous les topics qui sont écoutés, afin qu'on ait une vue d'ensemble et qu'on évite des nom de topic en doublon?

  • Est-ce que c'est plus clair de n'exposer que des fonctions où tu passe une callback, et donc tu n'écoutes que côté "sous-service".

Exemple:

Côté MQTT on expose une fonction "listen(topic, callback)", et côté service Sonoff on appelle cette fonction pour chaque topic qu'on écoute.

Chaque solution a ses avantages et ses inconvénients. Personnellement je pencherais plus pour la solution n°2, ça évite que le service MQTT deviennent énorme.

Dis moi ce que tu en penses :)

@atrovato
Copy link
Contributor Author

Je suis plutôt pour la solution 2 aussi, je dois alors revoir la PR #519 et celle que je prépare pour @VonOx sur zigbee2mqtt.

J'image qu'en disant

ça évite que le service Sonoff deviennent énorme

tu veux dire "le service MQTT" ?

@Pierre-Gilles
Copy link
Contributor

Je suis plutôt pour la solution 2 aussi, je dois alors revoir la PR #519 et celle que je prépare pour @VonOx sur zigbee2mqtt.

Cool. Si tu as des questions et que tu veux qu'on s'appelle n'hésite pas, je suis dispo !

tu veux dire "le service MQTT" ?

Oups pardon, oui MQTT! J'ai corrigé!

@atrovato
Copy link
Contributor Author

On dira que le point flou que je vois encore, c'est la gestion du start / stop du service MQTT par le sous-service Sonoff... Il faudra un stop "partiel" du service Sonoff (dans le cas où plusieurs protocoles seront gérés).
Mais je pense que pour le moment, j'ai déjà pas mal à faire.

@Pierre-Gilles
Copy link
Contributor

Il faudrait un moyen de retirer un listener. On pourrait avoir deux fonctions "addListener(topic, callback)" et "removeListener(topic)".

Après bon, pour certains services, le start/stop à moins de sens je trouve

@atrovato atrovato changed the title Sonoff + owntracks MQTT service Sonoff service (over MQTT) Aug 14, 2019
@atrovato
Copy link
Contributor Author

atrovato commented Aug 14, 2019

Based on #517 PR

Le service MQTT a été refactoré, afin de pouvoir y "connecter" d'autres services, dont celui-ci.

@atrovato atrovato marked this pull request as ready for review September 25, 2019 18:40
@atrovato
Copy link
Contributor Author

atrovato commented Oct 8, 2019

@Pierre-Gilles si tu as un peu de temps, peux-tu faire une review ?
Je considère ce service comme terminé.

Copy link
Contributor

@Pierre-Gilles Pierre-Gilles left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hey! Thanks for this great PR :)

On the code side, it's really good, I had a look and it seems all the best practices are here, good job 👏

I have a few UX feedbacks. I have absolutely no knowledge in how Sonoff works, so I was a good candidate to discover this integration with a fresh eye! Here are my feedbacks:

Screenshot 2019-10-08 at 20 51 30

When I arrive, everything is empty and I have no clue what's the difference between "Discover" and "Devices". How do peripherals appears in Discover? When I create a device in "Devices", what is the goal ? Why topics ? So it works with MQTT? So I have to configure the MQTT service first? What if MQTT is not configured yet? Am I able to configure this service even if MQTT is not working?

-> You should add more message explaining how things work :)
-> Maybe detect the configuration of the MQTT service ?

( btw, the question above are real question I'm asking myself :p )

Screenshot 2019-10-08 at 20 54 48

  1. A little explanation on what is a topic, rules, naming should be nice.

  2. I'm not able to modify the "topic" of a device, because you use the "topic" as the "external_id". I'm not sure this is the best place to save the topic. The external_id is meant to be something static that never changes and identify uniquely a device. Here it seems it's not the case. Maybe it should be saved elsewhere? Let's talk about this!

Screenshot 2019-10-08 at 20 54 48

When I create a device with the same name as another device, I have a generic error message.

-> This is because you don't provide a selector, and use an auto-generated one.
-> Should it be a good idea to have 2 devices with the same name in your integration? If yes, please provide a more unique selector, if no, please explain why this error happens.
-> In general, we should have a clear message based on the 409 error. I think we should create a generic error component to be able to handle HTTP errors everywhere the same way in the frontend, especially for devices :) (this is a more general feedback for Gladys 4 front)

Screenshot 2019-10-08 at 20 51 11

The description is a little long compared to other one, it doesn't look good on my screen. Is the second part of the desc necessary?

This is my first feedback! Again, good job for this service, well done 👏

@atrovato
Copy link
Contributor Author

atrovato commented Oct 9, 2019

First, thank you for you review, and your great approach as "not aware of Sonoff workflow". As I know how it works, it was clear enough for me, but your questions were very constuctive.

How do peripherals appears in Discover? When I create a device in "Devices", what is the goal ? Why topics ? So it works with MQTT? So I have to configure the MQTT service first? What if MQTT is not configured yet? Am I able to configure this service even if MQTT is not working?

I will not answer here, but I expect you will find answers in UX improvements.


-> You should add more message explaining how things work :)

On device tab :

  • title changed from Sonoff Devices to Sonoff devices in Gladys
  • if no device available, a message is displayed with "actions to create new devices" (new or discover)

On discover tab :

  • tab title changed from Discover to MQTT discover
  • title change from Sonoff Discover to Sonoff discover devices over MQTT
  • alert description component added to explain what happens here
  • link to "official Tasmota firmware update" tutorial

-> Maybe detect the configuration of the MQTT service ?

This point needed to change the already merged MQTT service and add a new "check status" API entry point and UI component.


  1. A little explanation on what is a topic, rules, naming should be nice.

The topic is a Sonoff (Tasmota) key word that can be found on Sonoff device UI.
The topic placeholder refers to this notion.

Please see
Tasmota-MQTT-configuration


I'm not able to modify the "topic" of a device, because you use the "topic" as the "external_id". I'm not sure this is the best place to save the topic. The external_id is meant to be something static that never changes and identify uniquely a device. Here it seems it's not the case. Maybe it should be saved elsewhere? Let's talk about this!

As the Topic is the unique device identifier on MQTT, I suppose that external_id was the most appropriate. Maybe we can disable the fact to modify its value and force user to recreate a new one if he changes its device own configuration.
But using the "external_id" allows to get the device faster when MQTT message is received.

Let's talk about this 😉


When I create a device with the same name as another device, I have a generic error message.

I managed the 409 case.


The description is a little long compared to other one, it doesn't look good on my screen. Is the second part of the desc necessary?

Description cutted 😃


I add 'sonoff:' prefix in external_id value from manual device creation.

And, as I just discover the device.model attribute, I replaced the usage of device.params to store the device model key in the appropriate attribute.

@atrovato
Copy link
Contributor Author

atrovato commented Oct 9, 2019

The build is not successful, but I think there is an issue with CircleCI.
I don't undestand what happens, and I found no information on resulted error.
CircleCI_fail

@VonOx
Copy link
Contributor

VonOx commented Oct 9, 2019

This is circle ci limitation on free plan 😣 ( 1000 minutes of build)

And 250/week

https://circleci.com/changelog#free-minutes-shift-to-250-week

@Pierre-Gilles
Copy link
Contributor

Pierre-Gilles commented Oct 11, 2019

@atrovato Seems CircleCI is limiting more strictly the time we can build per week. As an open-source project, we should be able to have additional build time. ( https://circleci.com/blog/building-open-source-projects-on-circleci/ )

I just sent a message to support to ask for free credit as open-source project, I'll let you know when they answer me!

@Pierre-Gilles
Copy link
Contributor

"Hi Pierregilles,

Thanks for contacting us. We'll be happy to help you with this. An account representative will be in touch soon.

Jun Ishioka
Support Engineer @ CircleCI"

Copy link
Contributor

@Pierre-Gilles Pierre-Gilles left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is my review on the UX side (waiting for CircleCI on the tech side)

  1. Good job for the MQTT status route, good for me 👍

  2. Good for me for the warning message for MQTT

  3. On the UX side, it's way better than before but I still don't understand how to configure Sonoff devices automatically if I buy some. So they are publishing MQTT messages by default? Why can I add them manually or automatically? Why not everything automatically? Should I flash my devices with a new firmware before? There needs to be a clear configuration step by step explanation when clicking on the integration. It can be a link to the external documentation if it's really too long to explain in Gladys.

  4. You need to add the MQTT status route to the demo.json file.

  5. Still one question about MQTT topics, are MQTT topics forced by Sonoff or can you use anything? It would be great if MQTT topics could be more in the naming convention of Gladys 4 ( see the MQTT documentation )

  6. You need to update your demo example with sonoff: external_id !

  7. I don't see the change on the selector for unique names

  8. I'm ok with not allowing users to change the MQTT topic, but before let me know about my question on automatic vs manual add (question 3)

@atrovato
Copy link
Contributor Author

Sonoff devices need to be flashed with the Sonoff-Tasmota firmware, according to the tutorial link in the discovery page.


So they are publishing MQTT messages by default?

They send a "discovery message". But they need to be configured first, according to the Sonoff-Tasmota link.


Why can I add them manually or automatically?

I first develop the manual creation workflow, to prepare the arrival on new devices.
But during the development, I found that they send the "discovery message".


Why not everything automatically?

To prepare Gladys before connecting it to MQTT broker, before geeting all devices...
If the discovery message is lost... To force the device creation.


Should I flash my devices with a new firmware before?

Yes, and it's not so easy to do... that's why I linked to the official firmware website.


It can be a link to the external documentation if it's really too long to explain in Gladys.

I don't think it's a good idea to copy / paste the official Sonoff-Tasmota tutorial. There is a lot a compatible devices, and for each, there is a way to flash it. The official website should be enough, but it's only in english.


You need to add the MQTT status route to the demo.json file.

Done.


Still one question about MQTT topics, are MQTT topics forced by Sonoff or can you use anything?

There is no way to change MQTT message format. Only a part of the MQTT topic is overridable, which defines the device identifier.


You need to update your demo example with sonoff: external_id !

Done.


I don't see the change on the selector for unique names

I did it.
See :


I'm ok with not allowing users to change the MQTT topic, but before let me know about my question on automatic vs manual add (question 3)

Ok to disable edition on topic (refers external_id), but it means that if I change the topic (refers device identifier) on the device, I will have to delete the existing device in Gladys and create (or discover) a new one.


So I think the main open question is about the documentation (how to flash device ? how to configure it ?).
As I said, I added the Offical Sonoff-Tasmota tutorial link, which is quite complete, and explain for each different devices.
Today, there is another tutorial on the community forum [TUTORIEL] Flasher et configurer un Sonoff, describing hardware only the one type of device.

I'm always listening for constructive remarks 😉

@atrovato
Copy link
Contributor Author

I will change the "tutorial" link to add a link to Gladys documentation, and in the document page, sowe could add the official link, and more specific Galdys documentation about Sonoff.

@Pierre-Gilles
Copy link
Contributor

I first develop the manual creation workflow, to prepare the arrival on new devices.
But during the development, I found that they send the "discovery message".

Ok, this should be explicit in the UI! How is the user supposed to know this? :)

I will change the "tutorial" link to add a link to Gladys documentation, and in the document page, sowe could add the official link, and more specific Galdys documentation about Sonoff.

I'm good with that! Let's link first to Gladys doc, then redirect when needed to different tutorials :)

FYI, I have a call with CircleCI today at 6:30pm to unlock this payment issue

@atrovato
Copy link
Contributor Author

At 6:30 pm french time ?

I will also add the "device.setValue" method, as it will come soon with Philips Hue service :)

@Pierre-Gilles
Copy link
Contributor

Yes french time!

I will also add the "device.setValue" method, as it will come soon with Philips Hue service :)

nice!

@Pierre-Gilles
Copy link
Contributor

Follow up on CircleCI call:

Good news: they should unlock us soon, and we shouldn't have to pay 15$/Github user/month (because it's an open-source project)

Can't wait to build & publish the work done here :)

@atrovato
Copy link
Contributor Author

Please review also documentation PR at https://github.com/GladysAssistant/gladys-4-docs/pull/2

@codecov
Copy link

codecov bot commented Oct 22, 2019

Codecov Report

Merging #519 into master will increase coverage by 0.14%.
The diff coverage is 97.47%.

Impacted file tree graph

@@            Coverage Diff             @@
##           master     #519      +/-   ##
==========================================
+ Coverage   91.78%   91.92%   +0.14%     
==========================================
  Files         383      396      +13     
  Lines        4700     4819     +119     
==========================================
+ Hits         4314     4430     +116     
- Misses        386      389       +3
Flag Coverage Δ
#server 91.92% <97.47%> (+0.14%) ⬆️
Impacted Files Coverage Δ
...r/services/mqtt/lib/handler/handleGladysMessage.js 100% <ø> (ø) ⬆️
server/services/mqtt/index.js 100% <ø> (ø) ⬆️
server/services/mqtt/api/mqtt.controller.js 100% <100%> (ø) ⬆️
server/services/sonoff/models/switch_basic.js 100% <100%> (ø)
server/services/sonoff/lib/handleMqttMessage.js 100% <100%> (ø)
server/services/sonoff/lib/setValue.js 100% <100%> (ø)
server/services/index.js 100% <100%> (ø) ⬆️
server/services/sonoff/lib/connect.js 100% <100%> (ø)
server/services/sonoff/models/plug_s2x.js 100% <100%> (ø)
server/services/mqtt/lib/disconnect.js 100% <100%> (ø) ⬆️
... and 24 more

Continue to review full report at Codecov.

Legend - Click here to learn more
Δ = absolute <relative> (impact), ø = not affected, ? = missing data
Powered by Codecov. Last update f08b1e4...a3fc2dd. Read the comment docs.

Copy link
Contributor

@Pierre-Gilles Pierre-Gilles left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hey! Just tested all this.

It's great, but I saw several little things to fix. After that I think we are good for a merge :)

I have a recurring bug in the UI: I create 2 devices manually, then I cannot access anymore the "devices" tab.

Screenshot 2019-10-24 at 13 39 28

Here are the two devices:

[{"id":"f9d61926-d42b-4e07-83b0-453852ec3f9d","service_id":"34c8c938-82b2-4dfb-8c0c-5d666d1ce017","room_id":"017a5f80-aa33-4e58-967a-37f6f733e0a2","name":"My device","selector":"sonoff-test-test","model":"sonoff-pow","external_id":"sonoff:test-test","should_poll":false,"poll_frequency":null,"created_at":"2019-10-24T11:34:50.924Z","updated_at":"2019-10-24T11:34:56.872Z","features":[{"id":"b240e50e-768d-4c0a-97fd-e9ff33079c02","device_id":"f9d61926-d42b-4e07-83b0-453852ec3f9d","name":"My device","selector":"sonoff-test-test-switch-binary","external_id":"sonoff:test-test:switch:binary","category":"switch","type":"binary","read_only":false,"keep_history":true,"has_feedback":true,"unit":null,"min":0,"max":1,"last_value":null,"last_value_string":null,"last_value_changed":null,"created_at":"2019-10-24T11:34:50.936Z","updated_at":"2019-10-24T11:34:56.889Z"},{"id":"7c925be2-1966-40e7-b69d-2aab6d6940a9","device_id":"f9d61926-d42b-4e07-83b0-453852ec3f9d","name":"My device - power","selector":"sonoff-test-test-switch-power","external_id":"sonoff:test-test:switch:power","category":"switch","type":"power","read_only":true,"keep_history":true,"has_feedback":false,"unit":"A","min":0,"max":10000,"last_value":null,"last_value_string":null,"last_value_changed":null,"created_at":"2019-10-24T11:34:56.881Z","updated_at":"2019-10-24T11:34:56.881Z"}],"params":[],"room":{"id":"017a5f80-aa33-4e58-967a-37f6f733e0a2","house_id":"0d0394e0-89dc-4921-a2c6-9bc8730ac11f","name":"room","selector":"room","created_at":"2019-10-18T14:42:55.167Z","updated_at":"2019-10-18T14:42:55.167Z"},"service":{"id":"34c8c938-82b2-4dfb-8c0c-5d666d1ce017","pod_id":null,"name":"sonoff","selector":"sonoff","version":"0.1.0","enabled":true,"has_message_feature":false,"created_at":"2019-10-24T11:19:46.943Z","updated_at":"2019-10-24T11:19:46.943Z"}},{"id":"5ff35f8b-8f1e-4053-963b-68b32fcdf8bd","service_id":"34c8c938-82b2-4dfb-8c0c-5d666d1ce017","room_id":"017a5f80-aa33-4e58-967a-37f6f733e0a2","name":"My device","selector":"sonoff-other-device","model":"sonoff-basic","external_id":"sonoff:other-device","should_poll":false,"poll_frequency":null,"created_at":"2019-10-24T11:37:10.473Z","updated_at":"2019-10-24T11:37:12.437Z","features":[{"id":"b572977d-2ca8-4ff2-b833-3aa0da184b9f","device_id":"5ff35f8b-8f1e-4053-963b-68b32fcdf8bd","name":"My device","selector":"sonoff-other-device-switch-binary","external_id":"sonoff:other-device:switch:binary","category":"switch","type":"binary","read_only":false,"keep_history":true,"has_feedback":true,"unit":null,"min":0,"max":1,"last_value":null,"last_value_string":null,"last_value_changed":null,"created_at":"2019-10-24T11:37:10.479Z","updated_at":"2019-10-24T11:37:12.444Z"}],"params":[],"room":{"id":"017a5f80-aa33-4e58-967a-37f6f733e0a2","house_id":"0d0394e0-89dc-4921-a2c6-9bc8730ac11f","name":"room","selector":"room","created_at":"2019-10-18T14:42:55.167Z","updated_at":"2019-10-18T14:42:55.167Z"},"service":{"id":"34c8c938-82b2-4dfb-8c0c-5d666d1ce017","pod_id":null,"name":"sonoff","selector":"sonoff","version":"0.1.0","enabled":true,"has_message_feature":false,"created_at":"2019-10-24T11:19:46.943Z","updated_at":"2019-10-24T11:19:46.943Z"}}]

front/src/config/i18n/en.json Outdated Show resolved Hide resolved
front/src/config/i18n/en.json Outdated Show resolved Hide resolved
front/src/config/i18n/en.json Outdated Show resolved Hide resolved
front/src/config/i18n/en.json Show resolved Hide resolved
front/src/config/i18n/en.json Show resolved Hide resolved
@Pierre-Gilles
Copy link
Contributor

Wait, the e.getInstance problem is on my side due to the React dev tools :p Not your fault !

My bad! :)

preactjs/preact#1877

So there are just the translations problem to fix.

@Pierre-Gilles Pierre-Gilles merged commit 5b64384 into GladysAssistant:master Oct 25, 2019
@atrovato atrovato deleted the sonoff-mqtt-service branch October 31, 2019 18:04
R6n0 pushed a commit to R6n0/Gladys that referenced this pull request Dec 2, 2020
* MQTT: sonoff (front/back) + owntracks

* MQTT: device creation by subService

* sonoff : scan for devices

* Sonoff: restructure MQTT service

* Sonoff: try to fix import

* Sonoff: improve model name

* Sonoff: complete demo mode

* Sonoff service: Fix typo

* Sonoff service: refactor models

* Run prettier :/

* Sonoff service: fix front impacts

* Sonoff service: fix model name

* Sonoff: limit integration description

* Sonoff: improve discover UX messages

* Sonoff: improve devices UX

* MQTT service status

* Sonoff: use device.model iso params

* Sonoff: use device.model iso params

* MQTT: fix status UX behavior

* Sonoff: improve error message

* Sonoff: topic help

* Sonoff: pushing to re-run circleCI

* Sonoff: update demo.json according to changes

* Mqtt/Sonoff: changing service client for device

* Sonoff: add ability to change value

* Sonoff: force 'sonoff:' topic prefix

* Sonoff: improve manual/auto device creation

* Sonoff: documentation link

* Sonoff: fix selector + clean

* Sonoff: forgot to adapt tests

* Sonoff: test coverage

* Sonoff: documentation link

* Sonoff: fix typos
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

3 participants