# Gladys V4 - Sensoren in der Oberfläche anzeigen

**URL:** <https://community.gladysassistant.com/t/gladys-v4-affichage-de-capteurs-dans-linterface/4939>\
**Category:** Présentations\
**Created:** [23. September 2019 um 07:32 UTC](https://community.gladysassistant.com/t/gladys-v4-affichage-de-capteurs-dans-linterface/4939 "2019-09-23T07:32:14Z")\
**Posts on this page:** 14\
**Page:** 1

<div class="post-metadata">

**Author:** ![damalgos](https://gladys-assistant-community.b-cdn.net/letter_avatar_proxy/v4/letter/d/e274bd/32.png) [@damalgos](https://community.gladysassistant.com/u/damalgos)\
**Post date:** [23. September 2019 um 07:32 UTC](https://community.gladysassistant.com/t/gladys-v4-affichage-de-capteurs-dans-linterface/4939/1 "2019-09-23T07:32:14Z")

</div>

Hallo zusammen,

Ich wollte eine Nachricht hinterlassen, weil ich ein Problem mit dem Xiaomi-Modul habe.

Wenn man einen Sensor abruft, wird dieser hinzugefügt und ist zum Beispiel in der Ansicht „Gerät“ sichtbar. Das Problem ist die Benennung dieser Sensoren. Der Name muss eindeutig sein. Es ist jedoch albern, einen eindeutigen Namen zu verwenden, wenn der Sensor in jedem Raum sehr gut „Temperatursensor“ heißen kann. Aber aktuell ist es ein eindeutiger Name, also wird daraus „Sensor im Maschinenraum“ oder „Sensor 1“ …

Wäre es nicht interessanter, eine automatische Benennung zu implementieren, die den Sensortyp berücksichtigt und eine spezifische Benennung anzeigt? So müsste man auf der Entwicklerseite nur das Gerät hinzufügen und den gewünschten Namen festlegen, und die Frontend-Schnittstelle würde die Benennung automatisch verwalten.

Was denkt ihr?

---

<div class="post-metadata">

**Author:** ![AlexTrovato](https://gladys-assistant-community.b-cdn.net/user_avatar/community.gladysassistant.com/alextrovato/32/10705_2.png) [@AlexTrovato](https://community.gladysassistant.com/u/AlexTrovato)\
**Post date:** [23. September 2019 um 08:41 UTC](https://community.gladysassistant.com/t/gladys-v4-affichage-de-capteurs-dans-linterface/4939/2 "2019-09-23T08:41:32Z")

</div>

Hallo,  
Ich finde den eindeutigen Namen auch sehr einschränkend, da ich ebenfalls mehrere Temperatursensoren habe.  
Dieser Name sollte vom Benutzer änderbar sein und nur als Beschriftung dienen, nicht als funktionaler Wert.  
Jetzt, da er automatisch generiert wird, denke ich, dass das zu absurd klingenden Namen führen wird.

---

<div class="post-metadata">

**Author:** ![damalgos](https://gladys-assistant-community.b-cdn.net/letter_avatar_proxy/v4/letter/d/e274bd/32.png) [@damalgos](https://community.gladysassistant.com/u/damalgos)\
**Post date:** [23. September 2019 um 09:16 UTC](https://community.gladysassistant.com/t/gladys-v4-affichage-de-capteurs-dans-linterface/4939/3 "2019-09-23T09:16:30Z")

</div>

Nein, ich glaube, du hast nicht ganz verstanden.

Logischerweise hast du in deinem Raum einen Temperatursensor. Da er sich in diesem Raum befindet, kann er den Namen „Temperatursensor“ tragen. Dieser Name kann mehrmals vorkommen, da er für jeden Raum einzigartig ist.

Falls du zwei Sensoren hast, benennst du sie 1 - 2.

Die Generierung erfolgt dynamisch und wird logischerweise nicht in der Datenbank gespeichert.

Die zweite Idee ist, eine neue Variable zu definieren, die weder der Name ist noch einzigartig. Diese ermöglicht es, mehrere „Temperatursensoren“ mit demselben Namen zu haben, falls der Benutzer dies wünscht.

Im Grunde genommen schaust du dir andere Systeme an, bei denen kein Name definiert wird, sondern einfach nur ein Gerät einem Raum hinzugefügt wird.

---

<div class="post-metadata">

**Author:** ![pierre-gilles](https://gladys-assistant-community.b-cdn.net/user_avatar/community.gladysassistant.com/pierre-gilles/32/5886_2.png) [@pierre-gilles](https://community.gladysassistant.com/u/pierre-gilles)\
**Post date:** [23. September 2019 um 15:06 UTC](https://community.gladysassistant.com/t/gladys-v4-affichage-de-capteurs-dans-linterface/4939/4 "2019-09-23T15:06:16Z")

</div>

@damalgos: Ich werde die Eindeutigkeitsbeschränkung für den Namen entfernen, das ergibt keinen Sinn 🙂 Auf jeden Fall, so wie wir mit der Entwicklung der Dienste in Gladys 4 begonnen haben, wird der «&nbsp;name&nbsp;» nicht benötigt und wird nicht verwendet 🙂

---

<div class="post-metadata">

**Author:** ![damalgos](https://gladys-assistant-community.b-cdn.net/letter_avatar_proxy/v4/letter/d/e274bd/32.png) [@damalgos](https://community.gladysassistant.com/u/damalgos)\
**Post date:** [23. September 2019 um 15:20 UTC](https://community.gladysassistant.com/t/gladys-v4-affichage-de-capteurs-dans-linterface/4939/5 "2019-09-23T15:20:01Z")

</div>

Und das ist eine gute Nachricht 😃

---

<div class="post-metadata">

**Author:** ![pierre-gilles](https://gladys-assistant-community.b-cdn.net/user_avatar/community.gladysassistant.com/pierre-gilles/32/5886_2.png) [@pierre-gilles](https://community.gladysassistant.com/u/pierre-gilles)\
**Post date:** [24. September 2019 um 07:29 UTC](https://community.gladysassistant.com/t/gladys-v4-affichage-de-capteurs-dans-linterface/4939/6 "2019-09-24T07:29:32Z")

</div>

Also, ich habe festgestellt, dass SQLite bei einer Migration keine eindeutigen Indizes entfernen kann, also ist es nicht so einfach wie gedacht ^^

Wenn wir in einer Produktionsversion wären, hätten wir:

1. Die Foreign Keys vorübergehend für die Migration deaktivieren
2. Die Tabelle t\_device in t\_device\_old umbenennen
3. Die neue Tabelle t\_device erstellen
4. Die Daten von der alten zur neuen Tabelle übertragen
5. Die alte Tabelle löschen
6. Die Foreign Keys wiederherstellen

Da wir aber noch in der Alpha-Phase sind und die Nutzer noch keine sensiblen Daten haben, ist der einfachste Ansatz für den Entwickler (um keine Zeit zu verlieren), die ursprünglichen Migrationsdateien direkt zu ändern. Das bedeutet, dass alle, die die Alpha installiert haben, ihre Daten verlieren und eine neue Datenbank erstellen müssen!

Ich werde die Gelegenheit nutzen, um die gesamte Datenbank zu überprüfen und zu sehen, ob es noch andere unnötige Einschränkungen gibt, die entfernt werden können. Ich habe gesehen, dass der Kalender und die Events das gleiche Problem haben, also entferne ich diese auch.

Nicht besonders lustig, aber es ist eine Alpha. Natürlich wird so eine Prozedur nie in der Produktion durchgeführt werden..

---

<div class="post-metadata">

**Author:** ![bertrandda](https://gladys-assistant-community.b-cdn.net/user_avatar/community.gladysassistant.com/bertrandda/32/5929_2.png) [@bertrandda](https://community.gladysassistant.com/u/bertrandda)\
**Post date:** [26. September 2019 um 20:30 UTC](https://community.gladysassistant.com/t/gladys-v4-affichage-de-capteurs-dans-linterface/4939/7 "2019-09-26T20:30:52Z")

</div>

Hallo @Pierre-Gilles, ich hatte das gleiche Problem wie du, um die Eindeutigkeit der Datenbank zu entfernen, aber es ist schließlich möglich. Schau dir den PR CalDAV an: [https://github.com/GladysAssistant/Gladys/pull/507/commits/24e95947bbad98c23856e7a36491102916b6c054#diff-875173103ade96e5af1bdede5b6ae683R3](https://github.com/GladysAssistant/Gladys/pull/507/commits/24e95947bbad98c23856e7a36491102916b6c054#diff-875173103ade96e5af1bdede5b6ae683R3)

---

<div class="post-metadata">

**Author:** ![pierre-gilles](https://gladys-assistant-community.b-cdn.net/user_avatar/community.gladysassistant.com/pierre-gilles/32/5886_2.png) [@pierre-gilles](https://community.gladysassistant.com/u/pierre-gilles)\
**Post date:** [27. September 2019 um 19:05 UTC](https://community.gladysassistant.com/t/gladys-v4-affichage-de-capteurs-dans-linterface/4939/8 "2019-09-27T19:05:20Z")

</div>

> [@bertrandda](#):
>
> Hallo @Pierre-Gilles, ich hatte dasselbe Problem wie du, um die Eindeutigkeit der Datenbank zu entfernen, aber es ist schließlich möglich. Sieh dir den PR CalDAV an:

Bist du sicher, dass das funktioniert? Nach meinen Recherchen und Tests erlaubt SQLite nicht, eine Eindeutigkeitsbeschränkung zu entfernen, man muss eine Tabelle neu erstellen und migrieren. Vielleicht liege ich aber auch falsch, sag mir Bescheid 🙂

---

<div class="post-metadata">

**Author:** ![bertrandda](https://gladys-assistant-community.b-cdn.net/user_avatar/community.gladysassistant.com/bertrandda/32/5929_2.png) [@bertrandda](https://community.gladysassistant.com/u/bertrandda)\
**Post date:** [27. September 2019 um 19:46 UTC](https://community.gladysassistant.com/t/gladys-v4-affichage-de-capteurs-dans-linterface/4939/9 "2019-09-27T19:46:14Z")

</div>

Ja, das funktioniert sehr gut. Ich hatte ein Problem mit der Eindeutigkeit der Namen wiederkehrender Ereignisse. Damit kann man jetzt so viele Ereignisse wie man möchte unter `Pepper's Geburtstag` speichern.

---

<div class="post-metadata">

**Author:** ![pierre-gilles](https://gladys-assistant-community.b-cdn.net/user_avatar/community.gladysassistant.com/pierre-gilles/32/5886_2.png) [@pierre-gilles](https://community.gladysassistant.com/u/pierre-gilles)\
**Post date:** [28. September 2019 um 12:37 UTC](https://community.gladysassistant.com/t/gladys-v4-affichage-de-capteurs-dans-linterface/4939/10 "2019-09-28T12:37:54Z")

</div>

Okay, danke für dein Feedback! Ich werde das mal testen 🙂

---

<div class="post-metadata">

**Author:** ![pierre-gilles](https://gladys-assistant-community.b-cdn.net/user_avatar/community.gladysassistant.com/pierre-gilles/32/5886_2.png) [@pierre-gilles](https://community.gladysassistant.com/u/pierre-gilles)\
**Post date:** [30. September 2019 um 09:09 UTC](https://community.gladysassistant.com/t/gladys-v4-affichage-de-capteurs-dans-linterface/4939/11 "2019-09-30T09:09:31Z")

</div>

@bertrandda leider funktioniert deine Lösung nicht zu 100 %, tatsächlich hast du einen Bug (oder ein Feature^^) von Sequelize entdeckt!

In SQLite gibt es kein ALTER TABLE. Die einzige Möglichkeit, eine Tabelle zu aktualisieren, besteht darin, sie umzubenennen, neu zu erstellen und die Daten zu migrieren.

Sequelize hat diesen Teil abstrahiert und tut dies, wenn du changeColumn ausführst:

```auto
Executing (default): PRAGMA TABLE_INFO(`t_device`);
Executing (default): CREATE TABLE IF NOT EXISTS `t_device_backup` (`id` UUID NOT NULL PRIMARY KEY, `service_id` UUID NOT NULL, `room_id` UUID, `name` VARCHAR(255) NOT NULL, `selector` VARCHAR(255) NOT NULL, `model` VARCHAR(255), `external_id` VARCHAR(255) NOT NULL, `should_poll` TINYINT(1) NOT NULL DEFAULT 0, `poll_frequency` INTEGER, `created_at` DATETIME NOT NULL, `updated_at` DATETIME NOT NULL);
Executing (default): INSERT INTO `t_device_backup` SELECT `id`, `service_id`, `room_id`, `name`, `selector`, `model`, `external_id`, `should_poll`, `poll_frequency`, `created_at`, `updated_at` FROM `t_device`;
Executing (default): DROP TABLE `t_device`;
Executing (default): CREATE TABLE IF NOT EXISTS `t_device` (`id` UUID NOT NULL PRIMARY KEY, `service_id` UUID NOT NULL, `room_id` UUID, `name` VARCHAR(255) NOT NULL, `selector` VARCHAR(255) NOT NULL, `model` VARCHAR(255), `external_id` VARCHAR(255) NOT NULL, `should_poll` TINYINT(1) NOT NULL DEFAULT 0, `poll_frequency` INTEGER, `created_at` DATETIME NOT NULL, `updated_at` DATETIME NOT NULL);
Executing (default): INSERT INTO `t_device` SELECT `id`, `service_id`, `room_id`, `name`, `selector`, `model`, `external_id`, `should_poll`, `poll_frequency`, `created_at`, `updated_at` FROM `t_device_backup`;
Executing (default): DROP TABLE `t_device_backup`;

```

Oder, wenn du den Code genau liest, gibt es einen Bug in dieser Implementierung: Die Foreign Keys und Constraints werden nicht migriert. Daher hat dein Name keine Constraints mehr: aber alle anderen Spalten haben ihre Constraints ebenfalls verloren, und die Tabelle hat keinen Schutz mehr. Der Selector ist nicht mehr eindeutig, die Foreign Keys sind weg, usw.

Siehe Code:

> <https://github.com/sequelize/sequelize/blob/efd2f40620107cef01e56856457ba1b607af79f5/lib/dialects/sqlite/query-interface.js#L46>

Nach einer Suche im Sequelize-GitHub gibt es ein Issue, das 2017 erstellt wurde und das Problem referenziert:

> <https://github.com/sequelize/sequelize/issues/7078>
>
> \## What you are doing?
> I'm trying to rename a column on an Sqlite db. I use \`re…nameColumn\` on the \`QueryInterface\` that, in the Sqlite case, is going to call \`renameColumn\` on the \`SQLiteQueryInterface\`.
> 
> \## What do you expect to happen?
> I expect that:
> 1) a temporary table is created equal to the first one (except the renamed column) including foreign key references.
> 2) data is copied over to the temporary table
> 3) old table is deleted
> 4) a new table is created equal to the first one (except the renamed column) including foreign key references.
> 5) data is copied over to the new table
> 
> \## What is actually happening?
> 1) a temporary table is created equal to the first one (except the renamed column) \*\*NOT including foreign key references\*\*.
> 2) data is copied over to the temporary table
> 3) old table is deleted
> 4) a new table is created equal to the first one (except the renamed column) \*\*NOT including foreign key references\*\*.
> 5) data is copied over to the new table
> 
> This is the original table:
> \`\`\`SQL
> CREATE TABLE \`matches\` (\`id\` INTEGER PRIMARY KEY AUTOINCREMENT, \`hash\` VARCHAR(200) NOT NULL UNIQUE, \`alertId\` INTEGER REFERENCES \`alerts\` (\`id\`) ON DELETE CASCADE ON UPDATE CASCADE)
> \`\`\`
> 
> This is the table after the renameColumn on 'hash' -\> 'foo'
> \`\`\`SQL
> CREATE TABLE \`matches\` (\`id\` INTEGER PRIMARY KEY AUTOINCREMENT, \`foo\` VARCHAR(200) NOT NULL, \`alertId\` INTEGER)
> \`\`\`
> 
> \_\_Dialect:\_\_ sqlite
> \_\_Database version:\_\_ 3.9.x
> \_\_Sequelize version:\_\_ 3.24.x

Aber anscheinend ist der Bug immer noch nicht behoben..

**Drei Optionen:**

- Wir verwenden einen „Hack“, der eine der Funktionen von Sequelize während dieser Migration überschreibt, um die Constraints wieder hinzuzufügen.
- Wir finden einen Weg, Sequelize zu beheben, und schlagen einen PR vor (allerdings bin ich mir nicht sicher, ob er vor unserem Bedarf gemerged wird)
- Wir vergessen, changeColumn zu verwenden, und bitten die Leute, die DB neu zu erstellen… was kurzfristig löst, aber wenn wir langfristig eine Spalte ändern wollen, ist das Problem immer noch da!

---

<div class="post-metadata">

**Author:** ![pierre-gilles](https://gladys-assistant-community.b-cdn.net/user_avatar/community.gladysassistant.com/pierre-gilles/32/5886_2.png) [@pierre-gilles](https://community.gladysassistant.com/u/pierre-gilles)\
**Post date:** [30. September 2019 um 10:00 UTC](https://community.gladysassistant.com/t/gladys-v4-affichage-de-capteurs-dans-linterface/4939/12 "2019-09-30T10:00:35Z")

</div>

Ich habe es geschafft, den Hack durchzuführen. Hier ist das Ergebnis:

```javascript
module.exports = {
  up: async (queryInterface, Sequelize) => {
    const backupDescribeTable = queryInterface.describeTable;
    queryInterface.describeTable = async (tableName, options) => {
      const tableDatas = await backupDescribeTable.call(queryInterface, tableName, options);
      // Hole Fremdschlüssel-Informationen
      const foreignKeyDatas = (await queryInterface.sequelize.query(`PRAGMA FOREIGN_KEY_LIST("${tableName}");`))[0];
      foreignKeyDatas.forEach((foreignKeyData) => {
        const tableData = tableDatas[foreignKeyData.from];
        tableData.references = { model: foreignKeyData.table, key: foreignKeyData.to };
        tableData.onDelete = foreignKeyData.on_delete;
        tableData.onUpdate = foreignKeyData.on_update;
      });
      if (tableName === 't_device') {
        tableDatas.selector.unique = true;
        tableDatas.external_id.unique = true;
      }
      return tableDatas;
    };
    await queryInterface.changeColumn('t_device', 'name', {
      allowNull: false,
      type: Sequelize.STRING,
      unique: false,
    });
    queryInterface.describeTable = backupDescribeTable;
  },

  down: async (queryInterface, Sequelize) => {
    const backupDescribeTable = queryInterface.describeTable;
    queryInterface.describeTable = async (tableName, options) => {
      const tableDatas = await backupDescribeTable.call(queryInterface, tableName, options);
      // Hole Fremdschlüssel-Informationen
      const foreignKeyDatas = (await queryInterface.sequelize.query(`PRAGMA FOREIGN_KEY_LIST("${tableName}");`))[0];
      foreignKeyDatas.forEach((foreignKeyData) => {
        const tableData = tableDatas[foreignKeyData.from];
        tableData.references = { model: foreignKeyData.table, key: foreignKeyData.to };
        tableData.onDelete = foreignKeyData.on_delete;
        tableData.onUpdate = foreignKeyData.on_update;
      });
      if (tableName === 't_device') {
        tableDatas.name.unique = true;
        tableDatas.selector.unique = true;
        tableDatas.external_id.unique = true;
      }
      return tableDatas;
    };
    await queryInterface.changeColumn('t_device', 'name', {
      allowNull: false,
      type: Sequelize.STRING,
      unique: true,
    });
    queryInterface.describeTable = backupDescribeTable;
  },
};

```

---

<div class="post-metadata">

**Author:** ![pierre-gilles](https://gladys-assistant-community.b-cdn.net/user_avatar/community.gladysassistant.com/pierre-gilles/32/5886_2.png) [@pierre-gilles](https://community.gladysassistant.com/u/pierre-gilles)\
**Post date:** [30. September 2019 um 12:19 UTC](https://community.gladysassistant.com/t/gladys-v4-affichage-de-capteurs-dans-linterface/4939/13 "2019-09-30T12:19:19Z")

</div>

Na gut, es ist nicht so einfach… Es ist sogar schlimmer, als ich dachte ^^

Mit «&nbsp;ON DELETE CASCADE&nbsp;» werden beim Migrieren der Tabelle `t_device` (Löschen + Neuerstellung) alle Einträge der Tabelle `t_device_feature` und folglich auch die von `t_device_feature_state` gelöscht… Nicht einfach!

Die einzige Lösung, die ich für unser Problem sehe, ist entweder:

- Wir machen etwas speziell für SQLite, indem wir die Migrationsskripte selbst in SQL schreiben, und verlieren die Idee, den Nutzern irgendwann die Verwendung von MySQL zu ermöglichen. Oder wir machen zwei Fälle: einen für MySQL und einen für SQLite (möglich, aber das ist Arbeit).

- Wir bleiben bei der ursprünglichen Idee, da es sich um eine Alpha-Version handelt, bitten wir die Nutzer, die Datenbank neu zu erstellen, und ändern die Migrationsskripte.

Ich denke ehrlich gesagt, dass wir, angesichts des Umfangs, die ursprünglichen Migrationsskripte ändern sollten (da wir noch «&nbsp;in Entwicklung&nbsp;» sind und das Produkt noch nicht veröffentlicht wurde) und uns die Frage stellen, wenn wir wirklich keine andere Wahl haben (das heißt, wenn wir wirklich eine Spalte ändern müssen). Dabei sollte man bedenken, dass dies sehr selten vorkommt (es muss wirklich einen Designfehler geben, wie hier). Normalerweise ist das Hinzufügen von Spalten am häufigsten, und das unterstützt SQLite.

---

<div class="post-metadata">

**Author:** ![AlexTrovato](https://gladys-assistant-community.b-cdn.net/user_avatar/community.gladysassistant.com/alextrovato/32/10705_2.png) [@AlexTrovato](https://community.gladysassistant.com/u/AlexTrovato)\
**Post date:** [30. September 2019 um 16:03 UTC](https://community.gladysassistant.com/t/gladys-v4-affichage-de-capteurs-dans-linterface/4939/14 "2019-09-30T16:03:15Z")

</div>

Wir sind noch in der Entwicklung, oder wir erstellen alles neu, was es uns auch ermöglichen wird, die Dienste erneut zu testen und die „Unvollkommenheiten“ zu notieren.
