Skip to content
  • Home
  • Recent
  • Tags
  • 0 Unread 0
  • Categories
  • Unreplied
  • Popular
  • GitHub
  • Docu
  • Hilfe
Skins
  • Light
  • Brite
  • Cerulean
  • Cosmo
  • Flatly
  • Journal
  • Litera
  • Lumen
  • Lux
  • Materia
  • Minty
  • Morph
  • Pulse
  • Sandstone
  • Simplex
  • Sketchy
  • Spacelab
  • United
  • Yeti
  • Zephyr
  • Dark
  • Cyborg
  • Darkly
  • Quartz
  • Slate
  • Solar
  • Superhero
  • Vapor

  • Default (No Skin)
  • No Skin
Collapse
ioBroker Logo

Community Forum

donate donate
  1. ioBroker Community Home
  2. Deutsch
  3. ioBroker Allgemein
  4. [Vorlage] Einbinden des Xiaomi Mijia Bluetooth Thermo- und Hygrometer

NEWS

  • Monatsrückblick Januar/Februar 2026 ist online!
    BluefoxB
    Bluefox
    16
    1
    338

  • Jahresrückblick 2025 – unser neuer Blogbeitrag ist online! ✨
    BluefoxB
    Bluefox
    17
    1
    4.8k

  • Neuer Blogbeitrag: Monatsrückblick - Dezember 2025 🎄
    BluefoxB
    Bluefox
    13
    1
    1.3k

[Vorlage] Einbinden des Xiaomi Mijia Bluetooth Thermo- und Hygrometer

Scheduled Pinned Locked Moved ioBroker Allgemein
22 Posts 13 Posters 16.8k Views 12 Watching
  • Oldest to Newest
  • Newest to Oldest
  • Most Votes
Reply
  • Reply as topic
Log in to reply
This topic has been deleted. Only users with topic management privileges can see it.
  • Lenny.CBL Lenny.CB

    @Torsten-G schau dir mal die Anleitung an:
    https://forum.iobroker.net/topic/28388/xiaomi-temp-and-humidity-monitor-2-ble-adapter/97

    T Offline
    T Offline
    Torsten G.
    wrote on last edited by
    #21

    @Lenny-CB said in [Vorlage] Einbinden des Xiaomi Mijia Bluetooth Thermo- und Hygrometer:

    @Torsten-G schau dir mal die Anleitung an:
    https://forum.iobroker.net/topic/28388/xiaomi-temp-and-humidity-monitor-2-ble-adapter/97

    Vielen Dank hat geholfen. Ist Anfänger geeignet :)

    1 Reply Last reply
    0
    • S Soulforged

      Mir ist es endlich gelungen mein Bluetooth Thermo- und Hygrometer in ioBroker einzubinden. Nun möchte ich meine Lösung allen anderen natürlich auch zur Verfügung stellen. Ich Kürze das Gerät im folgenden mit TH ab.

      Fangen wir mit den Vorraussetzungen an: Wir benötigen auf unserem Host-System (in meinem Fall ein Raspi3) das Programm gatttool um auf die Bluetooth LE Schnittstelle zugreifen zu können. Wer den Bluetooth Adapter installier hat, wird diesen Schritt schon durchlaufen haben. Für alle anderen heißt es zunächt die Consolte zu öffnen

      sudo apt-get install bluetooth bluez libbluetooth-dev libudev-dev
      

      Als nächstes müsst ihr die MAC-Adresse eures TH herausbekommen. Ich habe hierzu eine Android-App namens nRF Connect benutzt. Diese wurde beim Bluetooth Adapter empfohlen und hat sehr gut funktoiniert https://play.google.com/store/apps/deta … ndroid.mcp

      Nun werden wir in einem kleinen JavaScript in ioBroker mit Hilfe des gatttools in regelmäßigen Abständen Messwerte vom TH anfordern. In den ersten 3 Zeilen des Scripts trag ihr bitte die MAC Adresse eures TH ein und wählt ein Abfrageintervall aus. Ich habe meines auf 5 Minuten gestellt, da Temperatur und Luftfeuchte in aller Regel sich sehr langsam verändernde größen sind. Je seltener man es durchführt umso schonender ist es für die Batterie in dem kleinen Gerät. die Sekunden bitte auf 0 stehen lassen sofern euer Intervall auch in Minuten angegeben wird.

      ! ````
      const pollrate_s = 0; //Abfrageintervall in Sekunden (bei nutzung der Minuten auf 0 Stellen)
      const pollrate_m = 5; //Abfrageintervall in Minuten (Empfehlung alle 5 Minuten / Temperaturänderung ist langsam / Schont die Batterie)
      const bluetooth_mac = '4C:65:A8:D0:13:83';
      ! const s_temp = "javascript.0.Bluetooth.XiaomiHygroTemp.Temperatur";
      const s_hygro = "javascript.0.Bluetooth.XiaomiHygroTemp.Luftfeuchte";
      ! createState(s_temp, 0,{unit: "°C", name: "Temperatur"});
      createState(s_hygro, 0,{unit: "%", name: "Luftfeuchte"});
      ! var cronstring;
      if (pollrate_s > 0) {
      cronstring = "*/" + pollrate_s + " * * * * ";
      }
      else {
      cronstring = "
      /" + pollrate_m + " * * * *";
      }
      ! schedule(cronstring, function () {
      poll_XiaomiHygroTemp(bluetooth_mac);
      });
      ! function poll_XiaomiHygroTemp(mac){
      var i = 1;
      var bluetooth_message = '';
      var messwerte;
      var temperatur;
      var feuchte;

      var spawn = require('child_process').spawn,
      gattool    = spawn('gatttool',['-b', mac , '--char-write-req', '-a', '0x10', '-n', '0100' ,'--listen']);
      
      gattool.stdout.on('data', function (data) {
        //console.log('stdout: ' + data.toString());
        bluetooth_message += data.toString();
        if(i==5) { //5 stdout nachrichten abfangen. Ergibt overhead + ca 1,5-2 mal einen Messwert.
            gattool.kill('SIGQUIT'); //gatttool in kommandozeile unsanft beenden
            //console.log('message:' + bluetooth_message);
            messwerte = bluetooth_message.substr(82,38); 
            stellen = bluetooth_message.substr(82,38).split(" "); //Messwerte extrahieren (stehen immer an der gleichen stelle der Ausgabe) und an leerzeichen auftrennen. 
            //Temperatur ist dann im Array an 2 (Zehner) 3 (Einer) 4 (Komma) und 5(Nachkommestelle) Stelle
            //Feuchte an Stelle 9 (Zehner) 10 (Einer) 11 (Komma) und 12 (Nachkommestelle) 
            //Ziffern ins ASCII sind 30+Ziffer. Also je 30 abziehen und mit der Zehnerpotenz multiplizieren
            temperatur = (stellen[2]-30)*10+(stellen[3]-30)+(stellen[5]-30)/10;
            feuchte = (stellen[9]-30)*10+(stellen[10]-30)+(stellen[12]-30)/10;
            //console.log('Temp:' + temperatur);
            //console.log('Feuchte:' + feuchte);
            setState(s_temp, temperatur, true);
            setState(s_hygro, feuchte, true);
        }
        i++;
      });
      
      gattool.stderr.on('data', function (data) {
        //console.log('stderr: ' + data.toString());
        log("Xiaomi hat nicht geantwortet. Warte auf nächsten Poll")
      });
      

      }

      
      Das Script erzeugt nach dem ersten Durchlauf zwei States in javascript.0.Bluetooth.XiaomiHygroTemp für Temperatur und Luftfeuchte.
      
      Diese kann man im vis z.B. in eine HTML-Tabelle packen:
      
      >! ````
      [{"tpl":"tplHtml","data":{"g_fixed":false,"g_visibility":false,"g_css_font_text":true,"g_css_background":false,"g_css_shadow_padding":true,"g_css_border":true,"g_gestures":false,"g_signals":false,"g_last_change":false,"visibility-cond":"==","visibility-val":1,"visibility-groups-action":"hide","refreshInterval":"0","signals-cond-0":"==","signals-val-0":true,"signals-icon-0":"/vis/signals/lowbattery.png","signals-icon-size-0":0,"signals-blink-0":false,"signals-horz-0":0,"signals-vert-0":0,"signals-hide-edit-0":false,"signals-cond-1":"==","signals-val-1":true,"signals-icon-1":"/vis/signals/lowbattery.png","signals-icon-size-1":0,"signals-blink-1":false,"signals-horz-1":0,"signals-vert-1":0,"signals-hide-edit-1":false,"signals-cond-2":"==","signals-val-2":true,"signals-icon-2":"/vis/signals/lowbattery.png","signals-icon-size-2":0,"signals-blink-2":false,"signals-horz-2":0,"signals-vert-2":0,"signals-hide-edit-2":false,"lc-type":"last-change","lc-is-interval":true,"lc-is-moment":false,"lc-format":"","lc-position-vert":"top","lc-position-horz":"right","lc-offset-vert":0,"lc-offset-horz":0,"lc-font-size":"12px","lc-font-family":"","lc-font-style":"","lc-bkg-color":"","lc-color":"","lc-border-width":"0","lc-border-style":"","lc-border-color":"","lc-border-radius":10,"lc-zindex":0,"html":"Klima\n\n    \n        \n        \n    \n    \n        \n        \n    \n
      >! | Temperatur: | {javascript.0.Bluetooth.XiaomiHygroTemp.Temperatur} °C |
      | Luftfeuchte: | {javascript.0.Bluetooth.XiaomiHygroTemp.Luftfeuchte}% |
      >! "},"style":{"left":"860px","top":"180px","color":"#EEEEEE","border-width":"2px","border-style":"solid","width":"227px","height":"85px","font-size":"larger","z-index":"0","line-height":"25px","border-radius":"10px","border-color":"#EEEEEE","padding-left":"6px","padding-top":"3px"},"widgetSet":"basic"}]
      
      M Offline
      M Offline
      Martin 5
      wrote on last edited by
      #22

      @soulforged Hallo, ich habe das Script etwas angepasst. Bei mir läuft es nun mit 6 Thermometern (die kleinen quadratischen Kästchen).

      const pollrate_m = 5; //Abfrageintervall in Minuten (Empfehlung alle 5 Minuten / Temperaturänderung ist langsam / Schont die Batterie)
      const bluetooth_macs = ['A4:C1:38:15:0D:18','A4:C1:38:19:34:B7','A4:C1:38:2B:A7:0C','A4:C1:38:5E:0B:9B','A4:C1:38:6A:F8:3C','A4:C1:38:FA:CC:07'];
      const bluetooth_str  = ['Bad','Schlafzimmer','Küche','Arbeitszimmer','Wohnzimmer','Gästezimmer'];
      const dpID = "javascript.0.Bluetooth.XiaomiHygroTemp";
      const s_temp  = "Temperatur";
      const s_hygro = "Luftfeuchte";
      const s_spann = "Spannung";
      for(let i = 0; i < bluetooth_str.length; i++){
          createState(dpID + "." + bluetooth_str[i] + "." + s_temp, 0,{unit: "°C", name: "Temperatur"});
          createState(dpID + "." + bluetooth_str[i] + "." + s_hygro, 0,{unit: "%", name: "Luftfeuchte"});
          createState(dpID + "." + bluetooth_str[i] + "." + s_spann, 0,{unit: "V", name: "Spannung"});
      }
      var cronstring = "*/" + pollrate_m + " * * * *";
      
      schedule(cronstring, async function () {
          for(let i = 0; i < bluetooth_macs.length; i++)
              poll_XiaomiHygroTemp(bluetooth_macs[i], i);
              await sleep(5000);
      });
      
      function poll_XiaomiHygroTemp(mac, i){
          var bluetooth_message = '';
          var temperatur;
          var feuchte;
          var spannung;
          var spawn = require('child_process').spawn,
          gattool = spawn('gatttool',['-b', mac , '--char-write-req', '-a', '0x0038', '-n', '0100' ,'--listen']);
          gattool.stdout.on('data', function (data) {
              bluetooth_message += data.toString();
              if(bluetooth_message.length > 96) {
                  gattool.kill(/*'SIGQUIT'*/'SIGKILL'); //gatttool in kommandozeile unsanft beenden
                  const pos1 = bluetooth_message.indexOf("value: ") + 7;
                  const tempStr = bluetooth_message.substring(pos1, pos1 + 15).split(" ");
                  temperatur = Math.round(parseInt(tempStr[1]+tempStr[0], 16)/10)/10;
                  spannung =   parseInt(tempStr[4]+tempStr[3], 16)/1000;
                  feuchte =    parseInt(tempStr[2], 16);
                  console.log(i + ": " + temperatur + ", " + feuchte + ", " + spannung + ", " + bluetooth_str[i]);
                  setState(dpID + "." + bluetooth_str[i] + "." + s_temp, temperatur, true);
                  setState(dpID + "." + bluetooth_str[i] + "." + s_hygro, feuchte, true);
                  setState(dpID + "." + bluetooth_str[i] + "." + s_spann, spannung, true);
      
              /*  Antwort: Characteristic value was written successfully
                           Notification handle = 0x0036 value: f8 07 4a d6 0b
                  Bescheibung:
                  f8 07 is the temperature as signed INT16 in little endian format. Divide it by 100 to get the temperature in degree Celsius. 
                  4a is the humidity. Only integer output.
                  d6 0b are the battery voltage in Millivolts in little endian format.
                  Terminal:
                  sudo hcitool lescan - Nach BLE Geräten suchen.
              */
              }
          });
       
          gattool.stderr.on('data', function (data) {
              //console.log('stderr: ' + data.toString());
              log(i + ": " + bluetooth_str[i] + " hat nicht geantwortet. Warte auf nächsten Poll")
          })
      };
      

      Grüße Martin

      1 Reply Last reply
      0
      Reply
      • Reply as topic
      Log in to reply
      • Oldest to Newest
      • Newest to Oldest
      • Most Votes


      Support us

      ioBroker
      Community Adapters
      Donate
      FAQ Cloud / IOT
      HowTo: Node.js-Update
      HowTo: Backup/Restore
      Downloads
      BLOG

      674

      Online

      32.7k

      Users

      82.5k

      Topics

      1.3m

      Posts
      Community
      Impressum | Datenschutz-Bestimmungen | Nutzungsbedingungen | Einwilligungseinstellungen
      ioBroker Community 2014-2025
      logo
      • Login

      • Don't have an account? Register

      • Login or register to search.
      • First post
        Last post
      0
      • Home
      • Recent
      • Tags
      • Unread 0
      • Categories
      • Unreplied
      • Popular
      • GitHub
      • Docu
      • Hilfe