doc/bms-ch8.sgml

Wed, 06 Dec 2023 20:26:00 +0100

author
Michiel Broek <mbroek@mbse.eu>
date
Wed, 06 Dec 2023 20:26:00 +0100
changeset 855
2d328a2a4025
parent 852
71f0fa38b634
permissions
-rw-r--r--

Fixed init scripts names in Makefile. Update crontasks to use the database to check the log entries for products.

<!-- 
  vim:syntax=docbksgml
-->

<chapter id="protocols">
<title>Protocollen.</title>
<para>
De netwerk protocollen.
</para>

<sect1 id="prototopic">
<title>MQTT topic formaat.</title>
<para>De topics zijn als volgt gedefinieerd:</para>
<programlisting>
mbv1.0/<code>group_id</code>/<code>message_type</code>/<code>edge_node</code>/<code>device_id</code>
</programlisting>

<itemizedlist>
<listitem><para><code>group_id</code> geeft het type apparaat aan zoals <code>fermenters</code>
en <code>brewcontrol</code>.</para></listitem>
<listitem><para><code>message_type</code> geeft het bericht type aan zoals
<code>NBIRTH</code>, <code>DDATA</code>.</para></listitem>
<listitem><para><code>edge_node</code> is de hostnaam van de node die het bericht stuurt. Dit is
de naam zonder domain toevoeging.</para></listitem>
<listitem><para><code>device_id</code> is de verkorte naam van het apparaat module waarvan dit
bericht komt zoals de naam van een vergisting controller. Dit is niet aanwezig met NODE berichten.</para></listitem>
</itemizedlist>

<para>
De volgende <code>group_id</code> namen zijn gedefinieerd:
</para>
<orderedlist>
<listitem><para><code>brewery</code> is voor de bms applicatie zelf. Nog uitwerken.</para></listitem>
<listitem><para><code>fermenters</code> is voor vergisting controllers.</para></listitem>
<listitem><para><code>co2meters</code> is een drukmeter om bijvoorbeeld hergisting op de fles
te monitoren.</para></listitem>
<listitem><para><code>ispindels</code> is een electronische hydrometer die in het gistvat drijft
en de temperatuur en sg verstuurt.</para></listitem>
</orderedlist>

<para>De volgende <code>message_type</code> namen zijn gedefinieerd:</para>
<orderedlist>
<listitem><para>NBIRTH geeft aan wanneer een node opstart en met het netwerk
verbonden is. Dit is een zogenaamd persistent bericht, het blijft voor nieuwe
MQTT clients altijd zichtbaar. Bij het starten van een node wordt er een payload
verzonden, zie het payload formaat voor een node. Als een node afsluit wordt juist geen
payload verzonden zodat het bericht verdwijnt.</para></listitem>
<listitem><para>NDEATH wordt verstuurd als een node offline gaat. Maar het kan ook
ontvangen worden als de MQTT verbinding verbroken wordt met een node, het NDEATH
bericht is ook het `last will' bericht van een node. Maar als het echt fout gaat
dan zal er mogenlijk nooit een NDEATH bericht gezien worden.</para></listitem>
<listitem><para>NCMD is een commando bestemd voor een node.
Dit kan bijvoorbeeld een reboot commando zijn.</para></listitem>
<listitem><para>NDATA wordt verstuurd als er veranderingen zijn voor de node,
maar ook regelmatig om aan te geven dat de node nog "levend" en aanwezig
is. Deze tijd is voor ieder node type verschillend. Indien twee maal de ingestelde
tijd plus enkele seconden geen NDATA bericht is gezien dan wordt de node als
offline beschouwd. Indien deze waarde niet aanwezig is wordt 300 seconden aangehouden.</para></listitem>

<listitem><para>DBIRTH is een of meer berichten van een apparaat wat online komt
en ingeschakeld is. Een apparaat is een deel van een node.
Bij het opstarten van de node is er geen <code>device_id</code>
omdat alle apparaten is een keer verstuurd worden. Indien er later een enkel apparaat
ingeschakeld wordt dan is er wel een geldige <code>device_id</code> aanwezig.
Hier ook weer, er is een payload bij opstarten en geen payload bij afsluiten om het
persistente bericht goed te houden.</para></listitem>
<listitem><para>DDEATH wordt verstuurd als een node offline gaat, of als het apparaat
uitgeschakelt wordt.</para></listitem>
<listitem><para>DDATA heeft altijd een payload, maar deze hoeft niet volledig te zijn,
enkel de gewijzigde data moet in het bericht zitten.</para></listitem>
<listitem><para>DLOG is een data log. Hier bestaat de payload uit gegevens die de
bms applicatie in de database zet.</para></listitem>
<listitem><para>DCMD is een commando voor een apparaat wat op een node geinstalleerd is.
Dit zullen voornamelijk instellingen voor dat enkele apparaat zijn.</para></listitem>
</orderedlist>

</sect1>


<sect1 id="payloadnode">
<title>Netwerk payload formaat voor een node</title>
<para>
De payload zoals die door een node verstuurd wordt. Het wordt in json formaat
verzonden zonder extra spaties en opmaak zoals hieronder is te zien. Het timestamp
is de unix tijd sinds 1 januari 1970. Niet alle controllers sturen een timestamp,
controllers zonder klok laten dit weg. De tijd wordt dan door <code>bmsd</code>
ingevuld en is de tijd dat het bericht ontvangen wordt.
Het `seq' nummer wordt met ieder bericht met 1 verhoogd.
Ook dit nummer is niet altijd aanwezig.</para>
<para>Deze payload wordt verstuurd als een node start, <code>message_type NBIRTH</code>.
Het wordt ook vertuurd als er iets wijzigd, bijvoorbeeld de temperatuur en op vaste
intervals. In die gevallen is het <code>message_type NDATA</code>.</para>
<para>In de `metric' groep is de `interval' optioneel. Dit wordt bijvoorbeeld
verstuurd door iSpindels en is de ingestelde update interval tijd in seconden.
Indien dit niet aanwezig is dan wordt 300 seconden als standaard waarde gebruikt.
Deze waarde wordt gebruikt om een apparaat als offline te markeren indien het langer
als twee maal deze tijd niet wordt gezien.</para>
<para>Alle object groepen binnen het metric object kunnen maar hoeven niet aanwezig te zijn.
Dit geld ook voor de diverse items in de groepen.</para>
<programlisting>
{
  "timestamp": 1532201089,
  "metric": {
    "uuid": "b508f01c-1f82-4e8b-b0d2-d88ecfb53031",
    "interval":300,
    "properties": {
      "hardwaremake": "Raspberry",
      "hardwaremodel": "Unknown",
      "os": "Linux",
      "os_version": "4.1.19+",
      "FW": "0.8.2"
    },
    "THB": {
      "temperature": 20.0,
      "humidity": 50.0,
      "barometer": 1002
    },
    "GPS": {
      "latitude": 1.2345,
      "longitude": 2.3456,
      "altitude": 20
    },
    "net": {
      "address": "10.126.151.11",
      "ifname": "eth0",
      "ssid":"WIFISSID",
      "rssi": 0
    }
  }
}
</programlisting>
</sect1>

<sect1 id="cmdnode">
<title>Netwerk kommando payload formaat voor nodes.</title>
<para>De volgende kommando's kunnen gestuurd worden naar nodes:</para>
<programlisting>
{
  "timestamp":1532201089,
  "metric": {
    "Node Control/Reboot":true
  }
}
</programlisting>
<para>Dit commando reboot niet de computer maar de applicatie die op een
computer zoals een Raspberry Pi geinstalleerd is. Een uitzondering zijn de
controllers zoals Arduino's en andere eenvoudige systemen.</para>
<programlisting>
{
  "timestamp":1532201089,
  "metric": {
    "Node Control/Rebirth":true
  }
}
</programlisting>
<para>Dit commando zorgt er voor dat alle NBIRTH en DBIRTH berichten opnieuw
verzonden worden alsof de computer net is opgestart. Dit kan nuttig zijn na
een herstart van de bms applicatie zelf zodat de juiste nodes informatie weer
beschikbaar is.</para>
</sect1>

<sect1 id="payloadfermdata">
<title>Netwerk payload data formaat voor vergisting controllers</title>
<para>
Dit is het meest uitgebreide formaat wat getoond is. Indien er bijvoorbeeld geen
chiller aanwezig is, dan wordt een `null' gestuurd in plaats van een json blok
met gegevens. De werkelijke uitvoering van de hardware en de configuratie daarvan
bepaald dus het uiteindelijke payload formaat.
</para>
<programlisting>
{
  "uuid": "48c9ae27-3f58-41c9-ae4b-1d57b249c45a",
  "alias": "unit1",
  "product": {
    "uuid": "1eb0c7bf-bf06-491c-a086-ac5478d521b9",
    "code": "CB0001",
    "name": "Hoppy Housebeer",
    "yeast_lo": 18.0,
    "yeast_hi": 24.0
  },
  "air": {
    "address": "70d60411-3ec8-40ab-998a-81fead83025f",
    "state": "OK",
    "temperature": 21.562
  },
  "beer": {
    "address": "8ec36f9d-f382-4e32-a47f-732642e1018d",
    "state": "OK",
    "temperature": 22.125
  },
  "chiller": {
    "address": "e81265b8-07f7-4b22-96c1-6f55a4b66a83",
    "state": "OK",
    "temperature": 12.437
  },
  "heater": {
    "address": "d2f2d6bc-4d12-4852-9462-95f4c2476034",
    "state": 0,
    "usage": 10710793
  },
  "cooler": {
    "address": "a9f30140-812c-4ec1-9e98-3a9d47deff7c",
    "state": 0,
    "usage": 920504
  },
  "fan": {
    "address": "ae9f9887-8209-4810-9f58-ddfb34ee142f",
    "state": 100,
    "usage": 62889739
  },
  "light": {
    "address": "cc6353cf-9c97-41b9-b6cf-00cea312e478",
    "state": 0,
    "usage": 29647290
  },
  "door": {
    "address": "ad8746d1-0549-485a-a215-41e5cdde9e75",
    "state": 1
  },
  "psu": {
    "address": "e1bb7182-883d-4977-a1c0-76e214072fc5",
    "state": 1
  },
  "stage": "PRIMARY",
  "mode": "BEER",
  "setpoint": {
    "low": 21.0,
    "high": 21.5
  },
  "alarm": 0,
  "profile": {
    "uuid": "c93ad1bb-0446-4788-9c43-83990c5f8b82",
    "name": "Witbier methode Cellis",
    "state": "OFF",
    "percent": 0,
    "inittemp": {
      "low": 17.9,
      "high": 18.1
    },
    "steps": [
      {
        "resttime": 2,
        "steptime": 0,
        "target": {
          "low": 18.0,
          "high": 18.0
        },
        "fridgemode": 0
      },
      {
        "resttime": 0,
        "steptime": 24,
        "target": {
          "low": 18.0,
          "high": 22.0
        },
        "fridgemode": 0
      },
      {
        "resttime": 48,
        "steptime": 96,
        "target": {
          "low": 26.0,
          "high": 26.0
        },
        "fridgemode": 0
      }
    ]
  }
}
</programlisting>
<para>Temperature states can be: OK, MISSING or ERROR.<para>
<para>The general `mode' can be: OFF, NONE, FRIDGE, BEER or PROFILE.</para>
<para>The profile `state' can be: OFF, PAUSE, RUN, DONE or ABORT.</para>
</sect1>


<sect1 id="payloadfermlog">
<title>Netwerk payload log formaat voor vergisting controllers</title>
<para>
Dit is het meest uitgebreide formaat wat getoond is. Indien er bijvoorbeeld geen
chiller aanwezig is, dan wordt geen data hiervoor verstuurd.
De werkelijke uitvoering van de hardware en de configuratie daarvan
bepaald dus het uiteindelijke payload formaat.
</para>
<programlisting>
{
  "timestamp": 1532201089,
  "metric": {
    "product": {
      "uuid": "1eb0c7bf-bf06-491c-a086-ac5478d521b9",
      "code": "CB0001",
      "name": "Hoppy Housebeer"     
    },
    "stage": "PRIMARY",
    "mode": "BEER",
    "temperature": {
      "air": 20.125,
      "beer": 20.062,
      "chiller": -3.000,
      "room": 20.1
    },
    "setpoint": {
      "low": 19.8,
      "high": 20.1
    },
    "heater": {
      "power": 100,
      "usage": 1234
    },
    "cooler": {
      "power": 0,
      "usage": 27273
    },
    "fan": {
      "power": 100,
      "usage": 8273772
    },
    "event": "Something to mark",
    "fermenter_uuid": "48c9ae27-3f58-41c9-ae4b-1d57b249c45a"
  }
}
</programlisting>
<para>
De ontvangen vergisting log gegevens worden niet opgeslagen in de SQL database
maar in platte tekst bestanden. Hierdoor is de gelogde informatie sneller toegankelijk.
Ieder brouw product heeft zijn eigen bestand.
De bestanden staan in <code>www/logs/fermentation/</code>.
De bestandsnamen zijn <code>product_code\ product_name.log</code>.
Het interne formaat is:</para>
<programlisting>
2014-11-15 18:39:12,BEER,PRIMARY,20.312,19.750,-1.500,20.5,18.6,18.8,35,12345,0,67890,Whatsup,Fermenter
            |         |     |      |      |      |      |    |    |   |   |   |   |      |        |
 0 datetime +         |     |      |      |      |      |    |    |   |   |   |   |      |        |
 1 werkwijze ---------+     |      |      |      |      |    |    |   |   |   |   |      |        |
 2 vergisting fase ---------+      |      |      |      |    |    |   |   |   |   |      |        |
 3 temperatuur lucht --------------+      |      |      |    |    |   |   |   |   |      |        |
 4 temperatuur bier ----------------------+      |      |    |    |   |   |   |   |      |        |
 5 temperatuur koeler ---------------------------+      |    |    |   |   |   |   |      |        |
 6 temperatuur ruimte ----------------------------------+    |    |   |   |   |   |      |        |
 7 instelwaarde laag ----------------------------------------+    |   |   |   |   |      |        |
 8 instelwaarde hoog ---------------------------------------------+   |   |   |   |      |        |
 9 verwarming vermogen -----------------------------------------------+   |   |   |      |        |
10 verwarming verbruik ---------------------------------------------------+   |   |      |        |
11 koeler vermogen -----------------------------------------------------------+   |      |        |
12 koeler verbruik ---------------------------------------------------------------+      |        |
13 gebeurtenis --------------------------------------------------------------------------+        |
14 vergister uuid --------------------------------------------------------------------------------+
</programlisting>
</sect1>

<sect1 id="payloadco2data">
<title>Netwerk payload data formaat voor CO2 meters.</title>
<para>De co2meters zijn simpele units gebouwd rond een ESP32 computer. Deze units
hebben een klein scherm en een rotary knop voor de bediening. Dit is voldoende
om alle instellingen te doen. Deze computer is ook voorzien van WiFi. Via
WiFi worden de meetgegevens verstuurd als MQTT berichten. Op iedere co2meter
kunnen drie drukmeters worden aangesloten.</para>
<para>De uuid codes worden niet eenmalig gegenereerd, maar deze worden samengesteld
uit een vast patroon en het mac adres. In deze uuid code is ook een volgnummer
voor het unit nummer verwerkt.</para>
<programlisting>
{
  "metric":{
    "units":[
      {
        "uuid":"c0ffeeee-dead-beef-caf0-3c71bffe4054",
        "alias":"unit1",
        "mode":"ON",
        "alarm":0,
        "temperature":{
          "state":"OK",
          "address":"e001191420732a28",
          "temperature":20.250
        },
        "pressure":{
          "state":"OK",
          "channel":7,
          "voltage":0.322,
          "zero":0.110,
          "bar":0.00
        }
      },
      {
        "uuid":"c0ffeeee-dead-beef-caf1-3c71bffe4054",
        "alias":"unit2",
        "mode":"OFF",
        "alarm":1,
        "temperature":{
          "state":"OK",
          "address":"e001191420732a28",
          "temperature":20.250
        },
        "pressure":{
          "state":"OK",
          "channel":6,
          "voltage":0.075,
          "zero":0.109,
          "bar":0.00
        }
      }
    ]
  }
}
</programlisting>
</sect1>

<sect1 id="payloadco2log">
<title>Netwerk payload log formaat voor CO2 meters.</title>
<para>
Voor iedere actieve CO2 meter wordt bij iedere systeemstart en iedere vijf
minuten  een logbericht gestuurd. Omdat de CO2 meters eenvoudige
controllers zijn is er geen tijd en product informatie beschikbaar. Deze
ontbrekende gegevens worden aangevuld door <command>bmsd</command>
</para>
<programlisting>
{
  "metric":{
    "uuid":"c0ffeeee-dead-beef-caf0-3c71bffe4054",
    "temperature":21.125,
    "pressure":0.000
  }
}
</programlisting>
<para>
De ontvangen CO2 log gegevens worden niet opgeslagen in de SQL database
maar in platte tekst bestanden. Hierdoor is de gelogde informatie sneller toegankelijk.
Ieder brouw product heeft zijn eigen bestand.
De bestanden staan in <code>www/logs/co2pressure/</code>.
De bestandsnamen zijn <code>product_code\ product_name.log</code>.
Het interne formaat is:</para>
<programlisting>
   2019-10-11 16:13:33,22.250,5.964,c0ffeeee-dead-beef-caf0-3c71bffe4054
            |            |      |                  |
 0 datetime +            |      |                  |
 1 temperatuur ----------+      |                  |
 2 CO2 flesdruk in bar ---------+                  |
 3 meter uuid -------------------------------------+
</programlisting>
</sect1>


<sect1 id="payloadispindeldata">
<title>Netwerk payload data formaat voor iSpindels.</title>
<para>
Iedere actieve iSpindel stuurt bij iedere systeemstart een bericht.
Daarna na iedere <code>interval</code> tijd in seconden een volgend bericht.
Omdat de iSpindel eenvoudige controllers zijn is er geen tijd en product
informatie beschikbaar. De instellingen voor <code>bmsd</code> in de iSpindel zijn:
</para>

<orderedlist>
<listitem><para>Unit of temperature: Celsius</para></listitem>
<listitem><para>Service Type: HTTP</para></listitem>
<listitem><para>Token: leeg laten</para></listitem>
<listitem><para>Server Address: het server IP adres</para></listitem>
<listitem><para>Server Port: 80</para></listitem>
<listitem><para>Path / URI: /ispindel/index.php</para></listitem>
</orderedlist>

<informaltable frame="none" rowsep="0" colsep="0">
<tgroup cols="2">
<tbody>
<row>
<entry>
<para>
<figure><title>iSpindel menu.</title>
<mediaobject>
<imageobject>
<imagedata valign="top" fileref="bms-ispindel-1.png" scale="15" format="png">
</imageobject>
</mediaobject>
</figure>
</para>
</entry>
<entry>
<para>
<figure><title>iSpindel configuratie.</title>
<mediaobject>
<imageobject>
<imagedata valign="top" fileref="bms-ispindel-2.png" scale="15" format="png">
</imageobject>
</mediaobject>
</figure>
</para>
</entry>
</row>
</tbody>
</tgroup>
</informaltable>

<para>
De iSpindel stuurt de data in een http post commando naar het script <code>/ispindel/index.php</code>.
Dit script zet de ontvangen data om in twee MQTT berichten die verwerkt zullen worden door <command>bmsd</command>.
Eerst het bericht zoals het ontvangen wordt van de iSpindel:
</para>
<programlisting>
{
  "name":"ispindel000",
  "ID":"13962697",
  "angle":"42.96722",
  "temperature":"25.5625",
  "temp_units":"C",
  "battery":"4.254432",
  "gravity":"9.306425",
  "interval":"900",
  "RSSI":"-37"
}
</programlisting>

<para>
De densiteit wordt door de iSpindel in graden Plato gegeven maar wordt sinds server versie 0.3.44 niet
meer gebruikt. De server heeft nu zelf per iSpindel een calibratie tabel en gebruikt die om graden Plato
te berekenen. Hiervoor wordt alleen de 'angle' gebruikt om de gravity in Plato te berekenen.
Hierdoor is het dus zelfs mogelijk online de calibratie aan te passen.
Het script <code>/ispindel/index.php</code> verzorgd de omzetting van de iSpindel POST data naar MQTT
data.
Eerst wordt het node bericht gemaakt:</para>
<programlisting>
mbv1.0/ispindels/NBIRTH/ispindel-d50dc9
{
  "metric":{
    "uuid":"c0ffeeee-cafe-dead-beef-2af236d50dc9",
    "interval":900,
    "properties":{
      "hardwaremake":"Wemos",
      "hardwaremodel":"D1 mini",
      "os":"Unknown",
      "os_version":"Unknown",
      "FW":"Unknown"
    },
    "net":{
      "address":"192.168.1.65",
      "ifname":"sta",
      "rssi":-37
    }
  }
}
</programlisting>
<para>En vervolgens het unit data bericht:</para>
<programlisting>
mbv1.0/ispindels/DBIRTH/ispindel-d50dc9
{
  "unit":{
    "uuid":"c0ffeeee-cafe-dead-bee0-2af236d50dc9",
    "alias":"iSpindel000",
    "alarm":0,
    "interval":900,
    "angle":42.96722,
    "temperature":25.5625,
    "battery":4.254432,
    "gravity":9.306425
  }
}
</programlisting>

<para>
De iSpindel stuurt geen aparte log informatie, alle informatie voor de logfile
wordt uit het standaard unit data bericht gehaald.
Ook wordt het Plato en SG door <code>bmsd</code> berekend uit de ontvangen <code>angle</code> waarde.
De log gegevens worden niet opgeslagen in de SQL database
maar weggeschreven in platte tekst bestanden. Hierdoor is de gelogde informatie sneller toegankelijk.
Ieder brouw product heeft zijn eigen bestand.
De bestanden staan in <code>www/logs/ispindel/</code>.
De bestandsnamen zijn <code>product_code\ product_name.log</code>.
Het interne formaat is:</para>
<programlisting>
   2020-01-05 14:01:53,19.3750,7.08093,1.02806,3.34724,38.78126,900,c0ffeeee-cafe-dead-bee0-2af236d50dc9
            |             |       |       |       |       |      |                 |
 0 datetime +             |       |       |       |       |      |                 |
 1 temperatuur -----------+       |       |       |       |      |                 |
 2 densiteit plato ---------------+       |       |       |      |                 |
 3 densiteit SG --------------------------+       |       |      |                 |
 4 batterij voltage ------------------------------+       |      |                 |
 5 tilt hoek ---------------------------------------------+      |                 |
 6 update interval ----------------------------------------------+                 |
 7 ispindel uuid ------------------------------------------------------------------+
</programlisting>
<para>
De data staat tegenwoordig ook in de database in de tabel <code>log_ispindel</code>. Door
verbeteringen in de MySQL database is dit nu voldoende snel.
</para>
</sect1>


</chapter>

mercurial