Shelly Blu in FHEM einbinden

Begonnen von Neeein, 28 Februar 2024, 21:21:52

Vorheriges Thema - Nächstes Thema

Kai-Alfonso

Zitat von: majestro84 am 13 März 2024, 14:38:58Hallo,

ich habe es nun wie folgt gelöst.
Schritt 1 und 2 bleiben wie bei Neeein seinem Beitrag.
In Schritt2 habe ich das Script beim MQTT Publish etwas angepasst so das im Topic nun auch die BtMac steht.
Zeile 161
MQTT.publish(SHELLY_ID + '/' + result.addr + '/events/ble', JSON.stringify(message));

Danke Alex, ich habe einen Shelly Blu Wall Switch 4 - wie muss ich denn das Skript umschreiben, das ich

1. übermittelt bekomme, welcher Button (1-4) gedrückt wurde und
2. wie der Payload ist (einmal gedrückt (1) zweimal gedrückt (2) dreimal gedrückt (3) und lang gedrückt (254)

Raspi2|nanoCul433|nanoCul868|CCU2
Energie-USBZähler|homebrew HM Devices
DBLog|DBRep|Homematic|Baumarktsteckdosen
Hue|Webcams mit DS-Station (Synology)|Bewegungsmelder|Rollladen|Schalter (IT|HM)

satprofi

warum verkauft shelly keine motion2 mehr, dafür die blu? um seine kostenpflichtige cloud zu fördern? motion2 nicht lieferbar, bei niemanden.
gruss
-----------------------------------------------------------------------
beelink miniPC - Fhem 6.x CUL 868, FS20, NetIO230 CUL 433
HMLAN, HM-CC-RT-DN,Homematic Actoren,LD382A,Telegram

satprofi

Zitat von: Neeein am 28 Februar 2024, 21:21:52Guten Abend liebe Foristen,


Ich möchte gerne die neuen Shelly Blu Fenster/Türkontakte in FHEM einbinden, aber meine Suche war bis jetzt nicht von Erfolg gekrönt.

Kann mir evtl. Jemand auf die Sprünge helfen?
Vielleicht gibt es das ja bereits als Modul in FHEM. Oder ein Script für die Plus/Pro Shelly's (Gatewayfunktion) die das übernehmen und an FHEM (In einen Dummy) übergeben... das selbst zu programmieren bin ich leider nicht fähig.

Freue mich auf eure konstruktiven Vorschläge und Ideen 😊

LG

bei amazon gibts gerade den bluetoith/wifi dongle um 12.-, hab ich mir bestellt. damit geht auch mqtt mit fhem , etc.
gruss
-----------------------------------------------------------------------
beelink miniPC - Fhem 6.x CUL 868, FS20, NetIO230 CUL 433
HMLAN, HM-CC-RT-DN,Homematic Actoren,LD382A,Telegram

WW

Zitatbei amazon gibts gerade den bluetoith/wifi dongle um 12.-, hab ich mir bestellt. damit geht auch mqtt mit fhem , etc.

Auch preislich interessant:

Shelly Smart Security Bundle Regular

Gibts immer mal für unter 45,-€
FHEM 6.x im Docker-Container (OMV4 auf ASRock J3455-ITX), FHEM 6.0 auf Raspi, Fritzbox 7490, CUL433, CUL868, Jeelink868, SIGNALduino, LaCrosseGateway, Shelly, Sonoff, ESP8266, ESP32, ESP32-Cam, LaCrosse, Revolt, OneWire, Zigbee (Sonoff, Blitzwolf, IKEA, Lidl), Azzurro-WR/Pylontech-Batterie

satprofi

Viiielen Dank an NEEEIN. Dein Script passt für meine motions. Dachte das Gateway übersetzt das zu Mqtt automatisch, in der App sehe ich die Motion´s alle, nur FHEM empfing nicht. das man scripte auch noch braucht, ist nicht sehr userfreundlich. 
gruss
-----------------------------------------------------------------------
beelink miniPC - Fhem 6.x CUL 868, FS20, NetIO230 CUL 433
HMLAN, HM-CC-RT-DN,Homematic Actoren,LD382A,Telegram

satprofi

noch eine Frage, werden keine Temperaturdaten mehr von den Blu mitgesendet?
gruss
-----------------------------------------------------------------------
beelink miniPC - Fhem 6.x CUL 868, FS20, NetIO230 CUL 433
HMLAN, HM-CC-RT-DN,Homematic Actoren,LD382A,Telegram

gvzdus

Moin, ich bin gerade am gleichen Thema:
https://forum.fhem.de/index.php?topic=139547.0

Nein, Temperatur kommt mit den Geräten nicht mit. Ich habe Shelly Motion, Shelly Button, Shelly WallSwitch 4 und Shelly Door&Window auf der Thread-Seite mit jeweiligem Output drauf.

Mein Ansatz ist - auch durch Rudis und Beta-Users Tipps - übrigens der Gleiche:
- Script auf den Shelly installieren (musste ich natürlich anpassen, u.a. auch für den Wallswitch 4 mit seinen 4 Buttons)
- auf MQTT-Topic posten
- "bridgeregex" neue Geräte anlegen lassen.

Ich nenne die Geräte aber beim Autocreate "bth_" (also z.B. "MQTT2_bth_<addresse>"), weil Bluetooth Home - gerade dank Shelly - sich als Standard ansieht (https://bthome.io).

Wo ich schon dabei bin:
Meine "bridgeRegex" für jeden Shelly, der Gateway sein soll:
.*:bthome/bth_([a-z_0-9_]+):.* "bth_$1"
Und "mein" Script für jeden Gateway-Shelly:
/******************* START CHANGE HERE *******************/
// Script for BThome->MQTT->FHEM, based on "ble-shelly-motion.js" from library
// version 0.1, 20241021

let CONFIG = {
  // When set to true, debug messages will be logged to the console
  debug: true,

  // When set to true and the script ownes the scanner, the scan will be active.
  // Active scan means the scanner will ping back the Bluetooth device to receive all its data, but it will drain the battery faster
  active: false,

  // When `allowedMacAddresses` is set to null, events from every bluetooth device are accepted.
  allowedMacAddresses: null,
  //allowedMacAddresses: [
  //  "aa:bc:12:34:56:78", // events only from these mac addresses are allowed.
  //  "11:22:33:45:5a:bc",
  //],

  /**
   * Called when packet from filtered Shelly BLU Motion devices is received.
   * @param {Object} eventData Object, containing all parameters received from the Shelly BLU Motion device. Example: {"encryption":false,"BTHome_version":2,"pid":16,"battery":100,"illuminance":109,"motion":1,"button":1,"rssi":-53,"address":"aa:bc:12:34:56:78"}
   */
  onStatusUpdate: function (eventData) {
    // Do nothing at the moment.
  }
};
/******************* STOP CHANGE HERE *******************/

let ALLTERCO_MFD_ID_STR = "0ba9";
let BTHOME_SVC_ID_STR = "fcd2";

let uint8 = 0;
let int8 = 1;
let uint16 = 2;
let int16 = 3;
let uint24 = 4;
let int24 = 5;

//Logs the provided message with an optional prefix to the console.
function logger(message, prefix) {
  //exit if the debug isn't enabled
  if (!CONFIG.debug) {
    return;
  }

  let finalText = "";

  //if the message is list loop over it
  if (Array.isArray(message)) {
    for (let i = 0; i < message.length; i++) {
      finalText = finalText + " " + JSON.stringify(message[i]);
    }
  } else {
    finalText = JSON.stringify(message);
  }

  //the prefix must be string
  if (typeof prefix !== "string") {
    prefix = "";
  } else {
    prefix = prefix + ":";
  }

  //log the result
  console.log(prefix, finalText);
}

// The BTH object defines the structure of the BTHome data
let BTH = {};
BTH[0x00] = { n: "pid", t: uint8 };
BTH[0x01] = { n: "batteryPercent", t: uint8, u: "%" };
BTH[0x02] = { n: "temperature", t: int16, f: 0.01, u: "tC" };
BTH[0x03] = { n: "humidity", t: uint16, f: 0.01, u: "%" };
BTH[0x05] = { n: "illuminance", t: uint24, f: 0.01 };
BTH[0x21] = { n: "motion", t: uint8 };
BTH[0x2d] = { n: "window", t: uint8 };
BTH[0x3a] = { n: "button", t: uint8 };
BTH[0x3f] = { n: "rotation", t: int16, f: 0.1 };

function getByteSize(type) {
  if (type === uint8 || type === int8) return 1;
  if (type === uint16 || type === int16) return 2;
  if (type === uint24 || type === int24) return 3;
  //impossible as advertisements are much smaller;
  return 255;
}

// functions for decoding and unpacking the service data from Shelly BLU devices
let BTHomeDecoder = {
  utoi: function (num, bitsz) {
    let mask = 1 << (bitsz - 1);
    return num & mask ? num - (1 << bitsz) : num;
  },
  getUInt8: function (buffer) {
    return buffer.at(0);
  },
  getInt8: function (buffer) {
    return this.utoi(this.getUInt8(buffer), 8);
  },
  getUInt16LE: function (buffer) {
    return 0xffff & ((buffer.at(1) << 8) | buffer.at(0));
  },
  getInt16LE: function (buffer) {
    return this.utoi(this.getUInt16LE(buffer), 16);
  },
  getUInt24LE: function (buffer) {
    return (
      0x00ffffff & ((buffer.at(2) << 16) | (buffer.at(1) << 8) | buffer.at(0))
    );
  },
  getInt24LE: function (buffer) {
    return this.utoi(this.getUInt24LE(buffer), 24);
  },
  getBufValue: function (type, buffer) {
    if (buffer.length < getByteSize(type)) return null;
    let res = null;
    if (type === uint8) res = this.getUInt8(buffer);
    if (type === int8) res = this.getInt8(buffer);
    if (type === uint16) res = this.getUInt16LE(buffer);
    if (type === int16) res = this.getInt16LE(buffer);
    if (type === uint24) res = this.getUInt24LE(buffer);
    if (type === int24) res = this.getInt24LE(buffer);
    return res;
  },

  // Unpacks the service data buffer from a Shelly BLU device
  unpack: function (buffer) {
    //beacons might not provide BTH service data
    if (typeof buffer !== "string" || buffer.length === 0) return null;
    let result = {};
    let _dib = buffer.at(0);
    result["encryption"] = _dib & 0x1 ? true : false;
    result["BTHome_version"] = _dib >> 5;
    if (result["BTHome_version"] !== 2) return null;
    //can not handle encrypted data
    if (result["encryption"]) return result;
    buffer = buffer.slice(1);

    let _bth;
    let _value;
    let _cntr = 0;
    while (buffer.length > 0) {
      _bth = BTH[buffer.at(0)];
      if (typeof _bth === "undefined") {
        logger("unknown type", "BTH");
        break;
      }
      buffer = buffer.slice(1);
      _value = this.getBufValue(_bth.t, buffer);
      if (_value === null) break;
      if (typeof _bth.f !== "undefined") _value = _value * _bth.f;
      // Added: BLU Wallswitch4 has multiple buttons
      if (typeof result[_bth.n] !== "undefined") {
        result[_bth.n + "_" + _cntr++] = result[_bth.n];
        delete result[_bth.n];
      }
      result[_cntr>0 ? _bth.n + "_" + _cntr++ : _bth.n] = _value;
      buffer = buffer.slice(getByteSize(_bth.t));
    }
    return result;
  },
};

function onReceivedPacket (data) {
  if(CONFIG._processedMacAddresses !== null) {
    if(CONFIG._processedMacAddresses.indexOf(data.address) < 0) {
      logger(["Received event from", data.address, "outside of the allowed addresses"], "Info");
      return;
    }
  }

  logger(["Shelly BTH packet: ", data], "Info");
  if (MQTT.isConnected()) {
    MQTT.publish("bthome/bth_" + data.address, JSON.stringify(data));
  }
}

//saving the id of the last packet, this is used to filter the duplicated packets
let lastPacketId = 0x100;

// Callback for the BLE scanner object
function BLEScanCallback(event, result) {
  //exit if not a result of a scan
  if (event !== BLE.Scanner.SCAN_RESULT) {
    return;
  }

  //exit if service_data member is missing
  if (
    typeof result.service_data === "undefined" ||
    typeof result.service_data[BTHOME_SVC_ID_STR] === "undefined"
  ) {
    return;
  }

  let unpackedData = BTHomeDecoder.unpack(
    result.service_data[BTHOME_SVC_ID_STR]
  );

  //exit if unpacked data is null or the device is encrypted
  if (
    unpackedData === null ||
    typeof unpackedData === "undefined" ||
    unpackedData["encryption"]
  ) {
    logger("Encrypted devices are not supported", "Error");
    return;
  }

  //exit if the event is duplicated
  if (lastPacketId === unpackedData.pid) {
    return;
  }

  lastPacketId = unpackedData.pid;

  unpackedData.rssi = result.rssi;
  unpackedData.address = result.addr;

  onReceivedPacket(unpackedData);
}

// Initializes the script and performs the necessary checks and configurations
function init() {
  //exit if can't find the config
  if (typeof CONFIG === "undefined") {
    console.log("Error: Undefined config");
    return;
  }

  //get the config of ble component
  let BLEConfig = Shelly.getComponentConfig("ble");

  //exit if the BLE isn't enabled
  if (!BLEConfig.enable) {
    console.log(
      "Error: The Bluetooth is not enabled, please enable it from settings"
    );
    return;
  }

  //check if the scanner is already running
  if (BLE.Scanner.isRunning()) {
    console.log("Info: The BLE gateway is running, the BLE scan configuration is managed by the device");
  }
  else {
    //start the scanner
    let bleScanner = BLE.Scanner.Start({
        duration_ms: BLE.Scanner.INFINITE_SCAN,
        active: CONFIG.active
    });

    if(!bleScanner) {
      console.log("Error: Can not start new scanner");
    }
  }

  if (
    typeof CONFIG.allowedMacAddresses !== "undefined"
  ) {
    if(CONFIG.allowedMacAddresses !== null) {
      // Process configured mac addresses all to lower case and remove duplicates.
      CONFIG._processedMacAddresses =
        CONFIG
          .allowedMacAddresses
          .map(function (mac) { return mac.toLowerCase(); })
          .filter(function (value, index, array) { return array.indexOf(value) === index; })
    }
    else {
      CONFIG._processedMacAddresses = null;
    }
  }

  //subscribe a callback to BLE scanner
  BLE.Scanner.Subscribe(BLEScanCallback);
}

init();

muc46

Guten Morgen,
code snippets laufen stabil auf shelly "gatewy" device und FHEM. Das verwendete BLU RC Button 4 device schickt nach click auf eine Taste zwei Pakete, wobei im ersten Pakete für die gedrückte Taste 0x0FE als Wert mitgegeben wird und im zweiten Pakete als Wert dann "button press event"(https://shelly-api-docs.shelly.cloud/docs-ble/Devices/wall_us/), z.B. bei einem kurzen Drücken 0x01. Werden zwei Tasten gleichzeitig gedrückt wird im ersten Paket aber nur für eine der gedrückten Tasten der Wert 0xFE gesendet, im zweiten Paket dann ein Wert für die jeweilige Taste.

Gibt es einen Grund, dass zwei Pakete geschickt werden, insbesondere dass es der Wert 0xFE ist?
Vielleicht aus Sicherheitsgründen, um ein weiteres, also das zweite, Paket mit den "echten" "button press events" anzukündigen?

Gibt es dasselbe Verhalten auf bei anderen Devices dieser Shelly Serie?

gvzdus

Für das 0xFE gibt es einen "guten Grund" (und ich kenne ein ähnliches Verhalten bei anderen Shelly-"Schaltern"):
Man will eine schnellstmögliche Reaktion. "Die Taste ist gedrückt" ist das erste, was der Shelly sagen kann. Ob es ein kurzer Click, langer Click oder Mehrfachclick war, kann dagegen erst nach einer Latenz beurteilt werden.
Daher kannst Du, wenn Du nicht lang/mehrfach unterschiedlich behandelst, z.B. das Licht schon beim 0xFE einschalten.
Was bei 2 Tasten gleichzeitig passiert, weiß ich nicht, und ich kann mir auch vorstellen, dass hier nicht ganz sichergestellt ist, dass alles sauber ankommt.

Ich habe mein Script oben übrigens noch überarbeitet, sodass es kompatibler zu Zigbee-Devices ist, und außerdem den Shelly BLU H&T unterstützt.

xypzo

#24
Hey guys,
I have my shelly blu gateway connected with mqtt to fhem, all values are readable and fine.
I also have a shelly blu TRV connected through this gateway.
Now what I really want to be able to do, is set the desired temperature in Fhem, which will be sent to the TRV via the gateway.
The only way this is possible for now is through HTTP RPC.
http://192.168.x.x/rpc/BluTrv.Call?id=200&method=%22TRV.SetTarget%22&params={"id":0,"target_C":22}
Is it possible to send such a command through FHEM? With HTTPAPI or HTTPMOD or something?
Or is there a more elegant way to communicate with the BLU stuff?

Thanks!

rudolfkoenig

HTTPAPI is not the right module, but one can use HTTPMOD for the task.
Or simply call
{ GetFileFromURL('http://192.168.x.x/rpc/BluTrv.Call?id=200&method=%22TRV.SetTarget%22&params={"id":0,"target_C":22}') }via notify/at/DOIF/etc.

satprofi

Hallo.
nach langer zeit einen zusätzlichen blumotion eingebunden. Die App findet das ding, und in FHEM auch autom. angelegt. Klappt wunderbar in FHEM, aber die app meint der ist offline.
was genau muss ich da machen das der online ist? die anderen zwei sind online, weiss aber nimmer wie ich das damals gemacht habe.
gruss
-----------------------------------------------------------------------
beelink miniPC - Fhem 6.x CUL 868, FS20, NetIO230 CUL 433
HMLAN, HM-CC-RT-DN,Homematic Actoren,LD382A,Telegram

piet_pit

Hallo,
wie hast du das konkret geschafft, dass der BlueMotion in FHEM automatisch angelegt wurde, über MQTT,
Vielen Dank und viele Grüße
Pit
FHEM Latest Revision: 29615
Raspberry Pi 3, Rasbian-Stretch
FRITZ!Box 7690
HM-Mod-RPI-PCB, JeeLink
CUNO 1.47

satprofi

Zitat von: piet_pit am 04 Februar 2025, 18:35:47Hallo,
wie hast du das konkret geschafft, dass der BlueMotion in FHEM automatisch angelegt wurde, über MQTT,
Vielen Dank und viele Grüße
Pit

Link
LG
gruss
-----------------------------------------------------------------------
beelink miniPC - Fhem 6.x CUL 868, FS20, NetIO230 CUL 433
HMLAN, HM-CC-RT-DN,Homematic Actoren,LD382A,Telegram

piet_pit

Hallo,
ganz vielen Dank den Link, habe deine gute Beschreibung auch schon umgesetzt. Das Notify ist auch angelegt worden, aber ich bekomme von Seiten des BluMotion noch keine Infos.
Muss ich eigentlich den Gateway-Shelly (ist bei mir ein 2PM) über diese MQTT-Templates anmelden? Aktuell habe ich den über das Shelly-Modul eingebunden, das ist wohl eher nicht richtig, oder?
LG
Pit
FHEM Latest Revision: 29615
Raspberry Pi 3, Rasbian-Stretch
FRITZ!Box 7690
HM-Mod-RPI-PCB, JeeLink
CUNO 1.47