Shelly Blu Button 1 “Stand Alone” Løsning (Danish)

Shelly Blu Button 1 “Stand Alone” Løsning (Danish)

Shelly Blu Button 1 “stand-alone” løsning

Med dette script får du muligheden for at styre relæet i en Shelly Plus eller Pro enhed direkte ved hjælp af Shelly BLU Button 1, uden at skulle anvende internet, Wi-Fi eller en gateway. Det betyder, at du ikke er afhængig af, at dine enheder skal være tilsluttet et netværk. I denne vejledning tages der udgangspunkt i en Shelly Plus 1PM. Fremover vil Shelly BLU Button 1 blive omtalt som Blu Button.

Trin 1: BLU Button 1 forberedelse

Hent Shelly BLE Debug appen

Shelly Bluetooth enheder er endnu ikke 100% implementeret i Shelly Smart Control app og man bliver derfor nød til at bruge BLE Debug app.

 

 

Noter mac adressen for Shelly BLU Button

Bemærk: Bluetooth skal være tændt på din mobil/tablet.

  1. Åbn Shelly BLE Debug appen.
  2. Tryk på din BLU Button for at gøre den søbar.
  3. Når den dukker op, skal du trykke på den og skrive mac adressen ned.

Dan par med mobil/tablet

Nu skal du oprette forbindelse mellem BLU Button og din mobil/tablet.

  1. Tryk på “pair” og følg vejledningen.
  2. Du skal muligvis holde knappen nede i 10 sekunder.

Opdater firmware

Hvis den ikke allerede har forslået at opdatere til nyeste firmware efter paringen, så tryk på “OTA” for at søge efter og installere nyeste firmware.

Slå lyd fra

Hvis du gerne vil fjerne bip lyden, så tryk på “Mute”

Trin 2: Forbind din Shelly Plus/Pro til WiFI uden brug af appen og cloud

Log ind på Shelly's egen webserver og opdater firmware

Shelly-enheder laversit eget access point når de tilsluttes spænding første gang. Det access point kan man forbinde til og derved komme ind og ændre indstillinger.

Log på dette WiFi fra din mobil, tablet eller PC og tilgå webserveren ved at skrive 192.168.33.1 i din browser.

Forbind til WiFi

For at kunne opdatere til seneste firmware, skal enheden kobles op på et WiFi netværk med internet forbindelse.

Alt efter, hvor gammel firmwaren er på din enhed , så kan de have to forskellige brugerflader

Start med at gå ind  og forbind enheden med det eksisterende WiFi.

Gammel brugerflade
Tryk på “Networks”

Ny brugerflade
Tryk på tandhjulet og vælg “WiFi”

Forbind til dit WiFi og tryk Apply/Save settings.

Herefter vil der stå, at der er forbundet til et WiFi og hvilken IP adresse den har fået tildelt.

Gammel brugerflade

Ny brugerflade

Opdater firmware

Gå til indstillinger og opdatere firmwaren til den seneste.

Gammel brugerflade
Tryk på “Device” og vælg frimware version

Ny brugerflade
Tryk på tandhjulet og vælg Firmware

Trin 3: Klargør din Shelly enhed

Sæt input mode til button

  1. Tryk på hus-ikonet
  2. Tryk på “Input”
  3. Tryk på “See more” ved input mode
  4. Vælg “Button” under input mode
  5. Vælg “Momentary Switch”

Sørg for at Bluetooth er aktiveret

  1. Tryk på tandhjulet
  2. Tryk på Bluetooth
  3. Sæt hak i “Enable Bluetooth”

Trin 4: Indsæt og klargør script

Slå websocket debug til

For at vi kan se status i loggen, skal vi først slå Websocket debug til.

  1. Tryk på tandhjulet.
  2. Vælg “Debug”
  3. Sæt hak i “Enable Websocket Debug”
  4. Tryk “Save Settings”



Indsæt script

  1. Tryk på Script ikonet (<>).
  2. Tryk på “Create new script”
  3. Giv dit script et navn.

Nu kopieres hele det nedenstående script.
(Tryk på Copy oppe i højre hjørne af scriptet)

 /**
 * This script uses the BLE scan functionality in scripting
 * Selects Shelly BLU Buttons from the aired advertisements, decodes
 * the service data payload and toggles a relay on the device on
 * button push
 */

// Shelly BLU devices:
// SBBT - Shelly BLU Button
// SBDW - Shelly BLU DoorWindow

// BTHome data format: https://bthome.io/format/

// sample Shelly DW service_data payload
// 0x40 0x00 0x4E 0x01 0x64 0x05 0x00 0x00 0x00 0x2D 0x01 0x3F 0x00 0x00

// First byte: BTHome device info, 0x40 - no encryption, BTHome v.2
// bit 0: “Encryption flag”
// bit 1-4: “Reserved for future use”
// bit 5-7: “BTHome Version”

// AD 0: PID, 0x00
// Value: 0x4E

// AD 1: Battery, 0x01
// Value, 100%

// AD 2: Illuminance, 0x05
// Value: 0

// AD 3: Window, 0x2D
// Value: true, open

// AD 4: Rotation, 0x3F
// Value: 0

// Device name can be obtained if an active scan is performed
// You can rely only on the address filtering and forego device name matching

// CHANGE ID OUTPUT HERE. The Id of the output nuber is as follow: Output:1 = id:0,  Output:2 = id:1,  Output:3 = id:2.  Output:4 = id:3
function singlePush() {
  print("Button pushed");
  Shelly.call("Switch.toggle", { id: 0});
}
function doublePush() {
  print("Button double pushed");
  Shelly.call("Switch.toggle", { id: 0});
}  
function triplePush() {
  print("button triple pushed");
  Shelly.call("Switch.toggle", { id: 0});
}  
function longPush() {
  print("Button long pushed");
  Shelly.call("Switch.toggle", { id: 0});
}  

function onButtonPress(BTHparsed) {
  print("Button pressed, emitting event");
  Shelly.emitEvent("BLU_BUTTON", {
    addr: BTHparsed.addr,
    rssi: BTHparsed.rssi,
    Button: BTHparsed.Button,
    Battery: BTHparsed.Battery,
  });
}
// remove name prefix to not filter by device name
// remove address to not filter by address
// filtering early by address or device name allows for faster execution
// actions is an array objects containing condition and action property
// conditions would be checked for equality against the parsed advertisement packet
// e.g. if there is an addr property in condition and it matches the value of addr property
// in BTH parsed object then the condition is true
// Button number define type of push. 1 = Single push, 2 = Double push, 3 = Triple push, 4 = Long push
let CONFIG = {
  //shelly_blu_name_prefix: "SBBT",
  //shelly_blu_address: "bc:02:6e:c3:c8:b9",
  actions: [
    {
      cond: {
        Button: 1,
        addr: "3c:2e:f5:6f:77:9b",
       },
      action: singlePush,
    },
//  If You want to add a second Blu Button. Type in it's mac adress below and remove "/*", "*/" 
// You can add as many Buttons as You want. Just copy/paste in more sections and and change the mac adress.
// Add Ektra Singlepush Button 
/*    {
      cond: {
        Button: 1,
        addr: "3c:2e:f5:6f:77:9b",
      },
      action: singlePush,
    },  
*/    
// Doublepush
    {
      cond: {
        Button: 2,
        addr: "3c:2e:f5:6f:77:9b",
       },
      action: doublePush,
    },
//  If You want to add a second Blu Button. Type in it's mac adress below and remove "/*", "*/" 
// You can add as many Buttons as You want. Just copy/paste in more sections and and change the mac adress.
// Add Ektra Doublepush Button
/*    {
      cond: {
        Button: 2,
        addr: "3c:2e:f5:6f:77:9b",
       },
      action: doublePush,
    },  
*/    
// Triplepush
        {
      cond: {
        Button: 3,
        addr: "3c:2e:f5:6f:77:9b",
       },
      action: triplePush,
    },
//  If You want to add a second Blu Button. Type in it's mac adress below and remove "/*", "*/" 
// You can add as many Buttons as You want. Just copy/paste in more sections and and change the mac adress.
// Add Ektra Trilepush Button
/*    {
      cond: {
        Button: 3,
        addr: "3c:2e:f5:6f:77:9b",
        },
      action: triplePush,
    },  
*/        
// Longpush
        {
      cond: {
        Button: 4,
        addr: "3c:2e:f5:6f:77:9b",
      },
      action: longPush,
    },
//  If You want to add a second Blu Button. Type in it's mac adress below and remove "/*", "*/" 
// You can add as many Buttons as You want. Just copy/paste in more sections and and change the mac adress.
// Add Ektra Longpush Button
/*    {
      cond: {
        Button: 4,
        addr: "3c:2e:f5:6f:77:9b",
      },
      action: longPush,
    },  
*/        
  ],
};
// END OF CHANGE

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

let SCAN_DURATION = BLE.Scanner.INFINITE_SCAN;
let ACTIVE_SCAN =
  typeof CONFIG.shelly_blu_name_prefix !== "undefined" &&
  CONFIG.shelly_blu_name_prefix !== null;

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

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 BTH = [];
BTH[0x00] = { n: "pid", t: uint8 };
BTH[0x01] = { n: "Battery", t: uint8, u: "%" };
BTH[0x05] = { n: "Illuminance", t: uint24, f: 0.01 };
BTH[0x1a] = { n: "Door", t: uint8 };
BTH[0x20] = { n: "Moisture", t: uint8 };
BTH[0x2d] = { n: "Window", t: uint8 };
BTH[0x3a] = { n: "Button", t: uint8 };
BTH[0x3f] = { n: "Rotation", t: int16, f: 0.1 };

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 ShellyBLUParser = {
  getData: function (res) {
    let result = BTHomeDecoder.unpack(res.service_data[BTHOME_SVC_ID_STR]);
    result.addr = res.addr;
    result.rssi = res.rssi;
    return result;
  },
};

let last_packet_id = 0x100;
function scanCB(ev, res) {
  if (ev !== BLE.Scanner.SCAN_RESULT) return;
  // skip if there is no service_data member
  if (
    typeof res.service_data === "undefined" ||
    typeof res.service_data[BTHOME_SVC_ID_STR] === "undefined"
  )
    return;
  // skip if we are looking for name match but don't have active scan as we don't have name
  if (
    typeof CONFIG.shelly_blu_name_prefix !== "undefined" &&
    (typeof res.local_name === "undefined" ||
      res.local_name.indexOf(CONFIG.shelly_blu_name_prefix) !== 0)
  )
    return;
  // skip if we don't have address match
  if (
    typeof CONFIG.shelly_blu_address !== "undefined" &&
    CONFIG.shelly_blu_address !== res.addr
  )
    return;
  let BTHparsed = ShellyBLUParser.getData(res);
  // skip if parsing failed
  if (BTHparsed === null) {
    console.log("Failed to parse BTH data");
    return;
  }
  // skip, we are deduping results
  if (last_packet_id === BTHparsed.pid) return;
  last_packet_id = BTHparsed.pid;
  console.log("Shelly BTH packet: ", JSON.stringify(BTHparsed));
  // execute actions from CONFIG
  let aIdx = null;
  for (aIdx in CONFIG.actions) {
    // skip if no condition defined
    if (typeof CONFIG.actions[aIdx]["cond"] === "undefined") continue;
    let cond = CONFIG.actions[aIdx]["cond"];
    let cIdx = null;
    let run = true;
    for (cIdx in cond) {
      if (typeof BTHparsed[cIdx] === "undefined") run = false;
      if (BTHparsed[cIdx] !== cond[cIdx]) run = false;
    }
    // if all conditions evaluated to true then execute
    if (run) CONFIG.actions[aIdx]["action"](BTHparsed);
  }
}

// retry several times to start the scanner if script was started before
// BLE infrastructure was up in the Shelly
function startBLEScan() {
  let bleScanSuccess = BLE.Scanner.Start({ duration_ms: SCAN_DURATION, active: ACTIVE_SCAN }, scanCB);
  if( bleScanSuccess === false ) {
    Timer.set(1000, false, startBLEScan);
  } else {
    console.log('Success: BLU button scanner running');
  }
}

//Check for BLE config and print a message if BLE is not enabled on the device
let BLEConfig = Shelly.getComponentConfig('ble');
if(BLEConfig.enable === false) {
  console.log('Error: BLE not enabled');
} else {
  Timer.set(1000, false, startBLEScan);
}

Konfigurer script

Når Scriptet er kopieret ind, findes linje 82 med BLU Buttons mac adresse.

På linjen:
addr:  “3c:2e:f5:6f:77:9b”, (linje 82)

indsætter du den mac adressen på din BLUButton, som blev noteret i starten.


OBS!
Det er meget vigtigt der kun bruges små bogstaver.

let CONFIG = {
  //shelly_blu_name_prefix: "SBBT",
  //shelly_blu_address: "bc:02:6e:c3:c8:b9",
  actions: [
    {
      cond: {
        Button: 1,
        addr: "90:ab:96:9f:a9:fe",
       },
      action: singlePush,
    },

Trin 5: Afslutning

Gem script

  1. Her efter trykkes på save og start i toppen.
  2. Tryk igen på script ikonet.
  3. Ud for script navnet skal knappen til højre være aktiv, for at scriptet automatisk skal starte efter strømafbrydelse.

Deaktiver WiFi

Hvis man har lyst, kan man nu deaktivere WiFi.

Aktiver access point med password

Hvis man gerne vil have nem adgang til enheden og den ikke er på WiFi, kan det være en god ide at aktivere access pointet. Så vil man altid kunne få adgang til enheden.


OBS! Husk at sætte password på access point.

Trin 6: Ekstra script funktioner

Brug kort, dobbelt, trippel og langt tryk

Find linjen 
// Doublepush (Linie 97)

Og erstat mac adressen med mac adressen på din BLU Button.

Det samme kan man henholdsvis gøre ved:
// Triplepush/> (linje 116)
// Longpush (linje 135)

Før
// Doublepush
    {
      cond: {
        Button: 2,
        addr: "3c:2e:f5:6f:77:9b",
       },
      action: doublePush,
    },
Efter
// Doublepush
    {
      cond: {
        Button: 2,
        addr: "90:ab:96:9f:a9:fe",
       },
      action: doublePush,
    },

Tilføje flere BLU Button tryk

Der kan nemt tilføjes flere tryk. Find linien
// Add Ekstra Singlpush Button (linje 88)
Slet /* og */
Og erstat mac adressen med mac adressen på din BLU Button.

Det samme kan man henholdsvis gøre ved:
// Add Ekstra Doublpush Button (linje 107)
// Add Ekstra Triplepush Button (linje 126)
// Add Ekstra Longpush Button (linje 145)

Før
// Add Ektra Singlepush Button 
/*    {
      cond: {
        Button: 1,
        addr: "90:ab:96:9f:a9:fe",
      },
      action: singlePush,
    },  
*/    
Efter
// Add Ektra Singlepush Button 
    {
      cond: {
        Button: 1,
        addr: "5t:7ue:k95:0qf:33:1c",
      },
      action: singlePush,
    },  
    

Ændre hvilket output der skal tændes

Som standard tænder dette script altid for output 1 (Som I Shelly verdenen er id:0). Hvis du fx. har en Shelly Plus 2 og du vil have den til at tænde for udgang 2, så skal du finde
// CHANGE ID OUTPUT HERE  (linje 40)
Og ændre id: 0 til id 1 ud for de forskellige tryk typer.

Output 1 =id: 0
Output 2 =id: 1
Output 3 =id: 2 <
Output 4 =id: 3 <

Før
function singlePush() {
  print("Button pushed");
  Shelly.call("Switch.toggle", { id: 0});
}
Efter
function singlePush() {
  print("Button pushed");
  Shelly.call("Switch.toggle", { id: 1});
}