Kasutaja tarvikud

Lehe tööriistad


shelly:skriptid

See on dokumendi vana versioon!


BLU sensori script

// v0.1

/******************* START CHANGE HERE *******************/ let CONFIG = {

  // Specify the destination event where the decoded BLE data will be emitted. It allows for easy identification by other applications/scripts
  eventName: "shelly-blu",
  // When set to true, debug messages will be logged to the console
  debug: false,
  // 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,
  // The mac address of Shelly BLU Motion
  mac: "",
  onMotionChange: function(motion) {
      Shelly.call("Switch.set", { id: 0, on: motion });
      console.log("Motion", motion);
  },

}; /******************* STOP CHANGE HERE *******************/

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 = {};

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 };

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

}

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;
  },
  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;
  },

};

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"
  ) {
      logger("Missing service_data member", "Error");
      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;
  console.log("Received " + JSON.stringify(unpackedData));
  if (unpackedData.address === CONFIG.mac && typeof unpackedData.motion !== "undefined") {
      CONFIG.onMotionChange(unpackedData.motion === 1);
  }

}

// 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");
      }
  }
  //subscribe a callback to BLE scanner
  BLE.Scanner.Subscribe(bleScanCallback);

}

init();

shelly/skriptid.1737626952.txt.gz · Viimati muutnud: persoon sa