Ankündigung

Einklappen
Keine Ankündigung bisher.

Shelly Blu Button 2 MQTT 2 HA 2 Alexa

Einklappen
X
 
  • Filter
  • Zeit
  • Anzeigen
Alles löschen
neue Beiträge

    Shelly Blu Button 2 MQTT 2 HA 2 Alexa

    Morgen allerseits!

    Ich habe eben einen Shelly Blu Button und ein Shelly BT Gateway in HA eingebunden, der mir einen Tastendruck mittels MQTT sendet.
    Die MQTT Nachricht löst eine Automatisierung aus und sendet eine Nachricht an alle Alexas.

    use case:
    Bei mir wird "Essen ist fertig!" ausgegeben, so muss ich später gegen 12.00 Uhr nicht mehr durchs Haus plärren

    Geht natürlich auch mit jedem anderen Input. In meinem Fall was es für mich das einfachste

    Hier das Script welches im BT Gateway eingetragen und gestartet werden muss ("Run on startup" sollte angehakt sein)
    Quelle https://haus-automatisierung.com/har...-button-1.html - danke dafür!
    Das Script sendet eine
    1 für 1x gedrückt
    2 für 2x gedrückt
    3 für 3x gedrückt
    4 für lang gedrückt

    In HA ist es egal wie oft gedrückt wird. Die Automatisierung wird ausgelöst, sobald irgendeine Nachricht empfangen wurde.
    Das liese sich natürlich auswerten und anderweitig verarbeiten.

    Code:
    // v0.1
    let BTHOME_SVC_ID_STR = "fcd2";
    
    let uint8 = 0;
    let int8 = 1;
    let uint16 = 2;
    let int16 = 3;
    let uint24 = 4;
    let int24 = 5;
    
    let BTH = {};
    let SHELLY_ID = undefined;
    
    BTH[0x00] = { n: "pid", t: uint8 };
    BTH[0x01] = { n: "Battery", t: uint8, u: "%" };
    BTH[0x3a] = { n: "Button", t: uint8 };
    
    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;
    }
    
    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;
        },
        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;
            while (buffer.length > 0) {
                _bth = BTH[buffer.at(0)];
                if (typeof _bth === "undefined") {
                    console.log("BTH: unknown type");
                    break;
                }
                buffer = buffer.slice(1);
                _value = this.getBufValue(_bth.t, buffer);
                if (_value === null) break;
                if (typeof _bth.f !== "undefined") _value = _value * _bth.f;
                result[_bth.n] = _value;
                buffer = buffer.slice(getByteSize(_bth.t));
            }
            return result;
        },
    };
    
    let lastPacketId = 0x100;
    
    function bleScanCallback(event, result) {
        if (event !== BLE.Scanner.SCAN_RESULT) {
            return;
        }
    
        if (typeof result.local_name === "undefined" || typeof result.addr === "undefined" || result.local_name.indexOf("SBBT") !== 0) {
            return;
        }
    
        let servData = result.service_data;
    
        // exit if service data is null/device is encrypted
        if (servData === null || typeof servData === "undefined" || typeof servData[BTHOME_SVC_ID_STR] === "undefined") {
            console.log("Can't handle encrypted devices");
            return;
        }
    
        let receivedData = BTHomeDecoder.unpack(servData[BTHOME_SVC_ID_STR]);
    
        // exit if unpacked data is null or the device is encrypted
        if (receivedData === null || typeof receivedData === "undefined" || receivedData["encryption"]) {
            console.log("Can't handle encrypted devices");
            return;
        }
    
        // exit if the event is duplicated
        if (lastPacketId === receivedData.pid) {
            return;
        }
    
        lastPacketId = receivedData["pid"];
    
        let message = {
            receiver: SHELLY_ID,
            sender: {
                type: result.local_name,
                mac: result.addr
            },
            event: receivedData
        };
    
        console.log("Publishing " + JSON.stringify(message));
    
        if (MQTT.isConnected()) {
            MQTT.publish("shellies/ble", JSON.stringify(message));
        }
    }
    
    function bleScan() {
        let bleScanner = BLE.Scanner.Start({
            duration_ms: BLE.Scanner.INFINITE_SCAN,
            active: true
        });
    
        if (bleScanner === false) {
            console.log("Error when starting the BLE scanner");
            return;
        }
    
        BLE.Scanner.Subscribe(bleScanCallback);
        console.log("BLE is successfully started");
    }
    
    Shelly.call("Mqtt.GetConfig", "", function (res, err_code, err_msg, ud) {
      SHELLY_ID = res["topic_prefix"];
    });
    
    // Check for BLE config and print a message if BLE is not enabled on the device
    let bleConfig = Shelly.getComponentConfig('ble');
    if (bleConfig.enable) {
        bleScan();
    }​
    Anschließend muss noch ein MQTT Sensor in der Configuration.yaml angelegt werden
    Code:
    mqtt:
      sensor:
        - name: "Essen ist fertig"
          unique_id: shelly_blu_button
          state_topic: "shellies/ble"
          value_template: "{{ value_json.event.Button }}"​
    Danach die Automatisierung anlegen, jenachdem wie man das möchte. Fertig!

    Vielleicht kann das ja der eine oder andere gebrauchen!

    Grüße...
    Katy Perry: Can you here me roar?
    Tatiana Shmailyuk: ... hold my beer!
Lädt...
X