Shelly bluetooth

Désolé pour certains, c’est évident, mais ce script, est un script que l’on place où ?

Salut,

Gen1 première génération et ainsi de suite…
Sur les Gen3 il y a le wifi et le Bluetooth qui lui n’est pas sur certain module gen1-gen2.

Oui

Oui, mais pour le cloud il est possible de l’activer en parallèle, moi je ne l’utilise pas donc je ne pourrai pas te dire comment cela fonctionne avec

Le script s’installe sur le module directement. On est sur un forum d’entre-aide et il faut poser des questions pour appendre. Ce n’est pas evident pour moi également donc on apprend. :grinning:
Je viens de recevoir mes capteurs reste plus qu’à vous faire un tuto

Je commande un capteur d’ouverture BLU et un module gen3. Le temps que ça arrive j’aurais votre tuto :smiley: Je cois que le tuto est très désiré :smiley:

Matériel reçu…

bonjour,

j’ai mis en oeuvre le script qui marche bien. Par contre au bout d’un certain temps il plante (il s’arrete) et de temps en temps il loupe des des evenements.

Je me demande si cela ne vient pas du scan permanent. Il faudrait peut etre essayer de pouvoir entrer des adresses mac de capteurs et donc de ne pas faire le scan. J’ai trouvé un programme qui fait ca mais pas pour un capteur ouverture. j’ai tenté de l’appliquer au script de ce post dont le fonctionnement me va mais je n’ai pas reussi. Peut etre quelqu’un y arriverait. Je joint ce script trouvé.

/******************* START CHANGE HERE *******************/
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, evets from every bluetooth device are accepted. 
  // allowedMacAddresses: null, 
  allowedMacAddresses: [
    "3C:2E:F5:BC:DE:00", // events only from these mac addresses are allowed.
    "3C:2E:F5:E4:5C:DB", 
  ],

  /**
   * Called when motion is reported from the filtered Shelly BLU Motion devices.
   * @param {Boolean} motion true, when there is a motion, false otherwise. 
   * @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"} 
   */
  motionHandler: function (motion, eventData) {
    // Toggle the first replay ON/OFF based on the motion value.
    Shelly.call("Switch.Set", { id: 0, on: motion });
    console.log("Motion", motion);
  },

  /**
   * Called when illuminance is reported from the filtered Shelly BLU Motion devices.
   * @param {Number} illuminance Current illuminance value.
   * @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"}
   */
  illuminanceHandler: function (illuminance, eventData) {
    // Compile the topic based on the mac address of the reporter.
    let topic = eventData.address + "/illuminance";

    // Publush the data.
    MQTT.publish(topic, String(illuminance));
  },
  
  /**
   * 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: "battery", 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;
    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;
      result[_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;
    }
  }

  if (
  typeof CONFIG.motionHandler === "function" &&
  typeof data.motion !== "undefined"
  && !Shelly.getComponentStatus('input:0').state
) {
    CONFIG.motionHandler(data.motion === 1, data);
    logger("Motion handler called", "Info");
  }

  if (
    typeof CONFIG.illuminanceHandler === "function" &&
    typeof data.illuminance !== "undefined"
  ) {
    CONFIG.illuminanceHandler(data.illuminance, data);
    logger("Illuminance handler called", "Info");
  }

  if (typeof CONFIG.onStatusUpdate === "function") {
    CONFIG.onStatusUpdate(data);
    logger("New status update", "Info");
  }
}

//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();

le gars avait deja fait un modification pour fonctionner avec de adresses mac plutot que le scan.

peut etre une piste pour le plantage du script :

je suis entrain de tester

Salut

Je ne pense pas que ce soit du à ca.
La modif est est déja dans le fichier
J’ai jamais eu de plantage pour ma part

moi ca plantait regulierement et ce matin ca a tenu toute la nuit sans probleme avec cette modif :
Use if (typeof _bth === "undefined") { instead of if (_bth === "undefined")
A voir dans le temps.

Sinon le temps de resoudre ce probleme de plantage qui a lieu sur tous les shellies (gateway, mini plus, …), pour decoder les shellies blu j’ai utilisé OpenMQTTGateway ](https://docs.openmqttgateway.com/) sur un esp32 ca marche tres bien et ca s’installe en 2 minutes depuis un navigateur.

Un tuto ! un tuto ! un tuto ! :smiley: :smiley: