Kannst du mal in einem Browser Fenster folgendes testen:
http://192.168.0.119/relay/0?turn=on
Die IP natürlich durch die deines Shelly 1 ersetzen.
Dann sollte dein relay Schalten!
Kannst du mal in einem Browser Fenster folgendes testen:
http://192.168.0.119/relay/0?turn=on
Die IP natürlich durch die deines Shelly 1 ersetzen.
Dann sollte dein relay Schalten!
Success: BLU button scanner running
wird angezeigt, beim druck auf den blubutton tut sich am Relais nichts. Die Tipps habe ich ausgeführt. Danke schonmal dafür
aber laut deinem Code hast du die ID nicht angepasst in der Zeile 43.
wie kommst du auf diese ID:
Shelly.call("Switch.Set", {id:08b61fd11f38, on:true});
die ID ist die nummer des outputs, also vermutlich 0 bei dir , da der shelly 1 nur einen ausgang hat
Habe die Console gefunden. Wenn ich den Blubutton drücke ändert sich was aa auf aq bei einzeldruck, aber das Relais schaltet nicht.
shelly_bluetooth_rel:91 ADV 3c:2e:f5:6e:b2:21: mfd={}, svc={"fcd2":"RACsAWQ6AA=="} 16:46:34
shelly_bluetooth_rel:91 ADV 3c:2e:f5:6e:b2:21: mfd={}, svc={"fcd2":"RACvAWQ6AQ=="} 16:46:58
das ist aber eine andere mac als du in dem script angegeben hast!
geh mal auf die weboberfläche und dann auf settings, debug und aktiviere websocket debug
dann gehst du links auf scripts, auf dein script und siehst unten die konsolenausgabe
dann das script einmal stoppen und starten und dann solltest du in der konsole was sehen, wenn du auf einen button klickst.
sonst sind noch die settings wichtig:
p.s. nimm für das Posten von code die entsprechende Funktion </> im editor, sonst kann man es nicht lesen...
Hallo, ich suche auch eine Lösung um mit einem BluButton einen Shelly plus 1 schalten zu können. Habe das Script auf den shelly plus 1 übertragen und in Zeile 66 meine MAC des BluButton im gleichen Format eingetrgen. Leider funktioniert es so nicht. (Mit einer Szene in der Cloud funktioniert es mit meinen Komponenten, suche aber die Lösung ohne Cloud). Über einen Tipp währe ich sehr dankbar.
Poste mal dein Script…
So,
der Vollständigkeit halber noch das Script, das nicht per HTTP den output schaltet, sondern lokal per API Call, was aus meiner Sicht effizienter und fehlerfreier ist.
Das Scipt ist von hier angepasst worden:
pasted-from-clipboard.png
wurde ergänzt um die Abfrage auf 2 verschiedene Blu Buttons, Zeile 63-76.
und den Api call in Zeile 43.
Was ich noch gemerkt habe: die MAC-Adresse des Blu button muss KLEIN geschrieben werden. Keine Ahnung warum aber war so...
UND: Bluetooth RPC und Gateway ausschalten, auch hier fehlt mir das tiefere Verständnis, aber es tut...
/**
* 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 HERE
function onButtonPress(BTHparsed) {
print("Button pressed, emitting event");
Shelly.call("Switch.Set", {id:0, on:true});
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
let CONFIG = {
shelly_blu_name_prefix: "SBBT",
//shelly_blu_address: "bc:02:6e:c3:c8:b9",
actions: [
{
cond: {
addr: "3c:2e:f5:f9:ff:13",
Button: 1,
},
action: onButtonPress,
},
{
cond: {
addr: "b4:35:22:fe:47:8a",
Button: 1,
},
action: onButtonPress,
},
],
};
// 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);
}
Alles anzeigen
Vielen Dank für die Rückmeldung.
Aber leider nicht so wie es soll... Ich habe gerade gesehen, dass ich in "addr" ein "d" vergessen habe. Da steht "adr". Bitte in den Zeilen 185 und 190 aus "adr" ein "addr" machen und dann noch einmal testen
Jetzt gehts
Danke
Update:
Ich schick das weg und 2 sekunden geht zumindest das Scanner Script wieder...
Aber das script mit deinen Anpassungen leider nicht:
hier noch mal vollständig
/**
* This script lets you use your Gen2 device as a gateway between Shelly BLU button1 and other Shelly devices (no matter Gen1 or Gen2)
* by sending local requests by their local IP APIs.
*
* What you should change before using it:
* > bluButtonAddress -> You should put the mac address of your blu button here.
* This script will help you find the mac address: https://github.com/ALLTERCO/shelly-script-examples/blob/main/ble-shelly-scanner.js
*
* > actions -> You should put the urls here to be executed at the specified event. Urls that shoudl be called on single/short push
* of the button, must be placed in the singlePush object. This applies to the double and triple push as well. Example below.
*
* Limitations:
* > At the moment there is a limit of 5 RPC calls at the same time and because of this, the script will execute every 3 urls with a 1 second delay.
* Limitations can be check here: https://shelly-api-docs.shelly.cloud/gen2/Scripts/ShellyScriptLanguageFeatures#resource-limits
*
* > The order of the execution of the urls can't be guaranteed
*/
/** =============================== CHANGE HERE =============================== */
let bluButtonAddresses = ["3c:2e:f5:f9:ff:13", "B4:35:22:FE:47:8A"]
let CONFIG = {
actions: { //urls to be called on a event
//when adding urls you must separate them with commas and put them in quotation marks
singlePush: [ //urls that will be executed at singlePush event from the blu button1
"http://192.168.0.119/relay/0?turn=on"
],
doublePush: [ //urls that will be executed at doublePush event from the blu button1
"http://192.168.1.35/roller/0?go=close"
],
triplePush: [ //urls that will be executed at triplePush event from the blu button1
"http://192.168.1.38/color/0?turn=on&red=200&green=0&blue=0",
"http://192.168.1.38/light/0?turn=on",
"http://192.168.1.40/rpc/Switch.Set?id=0&on=false",
"http://192.168.1.40/rpc/Switch.Set?id=1&on=false"
],
longPush: [ //urls that will be executed at longPush event from the blu button1
"http://192.168.1.41/rpc/Cover.Close",
"http://192.168.1.42/rpc/Cover.Close"
]
}
};
/** =============================== STOP CHANGING HERE =============================== */
let urlsPerCall = 3;
let urlsQueue = [];
let callsCounter = 0;
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;
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 };
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;
},
};
function callQueue() {
if(callsCounter < 6 - urlsPerCall) {
for(let i = 0; i < urlsPerCall && i < urlsQueue.length; i++) {
let url = urlsQueue.splice(0, 1)[0];
callsCounter++;
Shelly.call("HTTP.GET", {
url: url,
timeout: 5
},
function(_, error_code, _, data) {
if(error_code !== 0) {
console.log("Calling", data.url, "failed");
}
else {
console.log("Calling", data.url, "successed");
}
callsCounter--;
},
{ url: url }
);
}
}
//if there are more urls in the queue
if(urlsQueue.length > 0) {
Timer.set(
1000, //the delay
false,
function() {
callQueue();
}
);
}
}
let lastPacketId = 0x100;
function bleScanCallback(event, result) {
//exit if the call is not for a received result
if (event !== BLE.Scanner.SCAN_RESULT) {
return;
}
//exit if the data is not coming from a Shelly Blu button1 and if the mac address doesn't match
if ( typeof result.local_name === "undefined" ||
typeof result.addr === "undefined" ||
result.local_name.indexOf("SBBT") !== 0 ||
bluButtonAddresses.indexOf(result.adr) == -1
) {
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"];
//getting and execuing the action
let actionType = ["", "singlePush", "doublePush", "triplePush", "longPush"][receivedData["Button"]];
let actionUrls = CONFIG.actions[actionType];
//exit if the event doesn't exist in the config
if(typeof actionType === "undefined") {
console.log("Unknown event type in the config");
return;
}
//save all urls into the queue for the current event
for(let i in actionUrls) {
urlsQueue.push(actionUrls[i]);
}
callQueue();
}
function bleScan() {
//check whether the bluethooth is enabled
let bleConfig = Shelly.getComponentConfig("ble");
//exit if the bluetooth is not enabled
if(bleConfig.enable === false) {
console.log("BLE is not enabled");
return;
}
//start the scanner
let bleScanner = BLE.Scanner.Start({
duration_ms: BLE.Scanner.INFINITE_SCAN,
active: true
});
//exist if the scanner can not be started
if(bleScanner === false) {
console.log("Error when starting the BLE scanner");
return;
}
BLE.Scanner.Subscribe(bleScanCallback);
console.log("BLE is successfully started");
}
function init() {
//exit if there isn't a config
if(typeof CONFIG === "undefined") {
console.log("Can't read the config");
return;
}
//exit if there isn't a blu button address
//if(typeof CONFIG.bluButtonAddress !== "string") {
// console.log("Error with the Shelly BLU button1's address");
// return;
//}
//exit if there isn't action object
if(typeof CONFIG.actions === "undefined") {
console.log("Can't find the actions object in the config");
return;
}
//start the ble scan
bleScan();
}
//init the script
init();
Alles anzeigen
Ich habs jetzt billig gelöst.
die MAC mit 2 variablen in der config angelegt und unten so abgefragt
(result.addr !== CONFIG.bluButtonAddress1 && result.addr !== CONFIG.bluButtonAddress2)
Danke dir Nordlicht_2023 ,
sehr nett!
Leider passiert auch nach RPC und Gateway ausschalten nichts mehr. Keine Reaktion im Script auf den klick.
in den diagnostics sehe ich den klick
shelly_bluetooth_rel:91 ADV 3c:2e:f5:f9:ff:13: mfd={"0ba9":"AQEACwEAChP/+fUuPA=="}, svc={"fcd2":"RADSAWQ6AQ=="}
in der web ui auch
aber das script reagiert nicht. (auch die anderen scripte nicht)
Echt verhext...
Ich habe auch das Script getestet, auch ohne reaktion.
/**
* This script uses the BLE scan functionality in scripting
* Will look for Shelly BLU devices fingerprints in BLE advertisements
* Prints device name and address
*/
// Shelly BLU devices:
// SBBT - Shelly BLU Button
// SBDW - Shelly BLU DoorWindow
let ALLTERCO_DEVICE_NAME_PREFIX = ["SBBT", "SBDW"];
let ALLTERCO_MFD_ID_STR = "0ba9";
let BTHOME_SVC_ID_STR = "fcd2";
let SCAN_DURATION = BLE.Scanner.INFINITE_SCAN;
let ACTIVE_SCAN = true;
let SHELLY_BLU_CACHE = {};
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 have already found this device
if (typeof SHELLY_BLU_CACHE[res.addr] !== 'undefined') return;
if (typeof res.local_name !== 'string') return;
let shellyBluNameIdx = 0;
for (shellyBluNameIdx in ALLTERCO_DEVICE_NAME_PREFIX) {
if (res.local_name.indexOf(ALLTERCO_DEVICE_NAME_PREFIX[shellyBluNameIdx]) === 0) {
console.log('New device found:');
console.log('Address: ', res.addr, ' Name: ', res.local_name);
SHELLY_BLU_CACHE[res.addr] = res.local_name;
}
}
}
BLE.Scanner.Start({ duration_ms: SCAN_DURATION, active: true }, scanCB);
Alles anzeigen
Ach, ich könnte kotzen,
jetzt hat das alles wunderbar funktioniert,
Jetzt reagiert er nicht mehr auf den Blu Button
Ich sehe in dem Diagnostics, das Bluetooth event und in der shelly cloud auch den Button-Druck, aber egal welches Bluetooth script reagiert nicht mehr.
Auch werksreset usw. bringt nix.
Hat dazu jemand ne Idee?
Settings sind so:
pasted-from-clipboard.png
aber nachdem es mit
Shelly.call("Switch.Set", {id:0, on:true});
funktioniert hat sich das THema je erledigt
jetzt muss nur der 2. Button rein, aber das find ich schon noch raus...
Danke Flutschi , hast du für meine Zusatzfrage auch eine Antwort?
Suche bitte in der Library einmal nach diesem Script:
Hallo Nordlicht_2023 ,
danke für deinen Hinweis.
leider gehts nicht
Ich beschreibe den Aufbau:
Uni Plus mit der IP 192.168.0.120
Ausgang 1 kann aus dem Browsermit
http://192.168.0.120/relay/0?turn=on problemlos geschaltet werden.
Auf dem Uni Plus habe ich das Script installiert und so angepasst:
let CONFIG = {
bluButtonAddress: "3c:2e:f5:f9:ff:13", //the mac address of shelly blu button1 that will trigger the actions
actions: { //urls to be called on a event
//when adding urls you must separate them with commas and put them in quotation marks
singlePush: [ //urls that will be executed at singlePush event from the blu button1
"http://192.168.0.120/relay/0?turn=on"
],
Das funktioniert leider nicht!
Wenn ich einen anderen shelly in dem script angebe, z.b. einen Shelly 1 auf der .119
http://192.168.0.119/relay/0?turn=on
funktioniert das problemlos.
--> er kann nicht an sich selbst ein http call schicken scheinbar.
dann habe ich das script ble-shelly-btn.js verwendet und hier den direkten API Call eingefügt
--> das geht.
Danke für den Hinweis, wieder was gelernt...
function onButtonPress(BTHparsed) {
print("Button pressed, emitting event");
Shelly.call("Switch.Set", {id:0, on:true});
Shelly.emitEvent("BLU_BUTTON", {
addr: BTHparsed.addr,
rssi: BTHparsed.rssi,
Button: BTHparsed.Button,
Battery: BTHparsed.Battery,
});
}
Alles anzeigen
Zusatzfrage:
So sieht aktuell die Abfrage auf einen spezifischen Blu button aus.
Wie müsste das aussehen um einen weiteren Blu Button zu erlauben?
DANKE
Szenario:
beim Drücken des Blu buttons, soll der Uni Plus Ausgang 1 (potentialfrei) schalten.
Wie lässt sich das über das eingebaute scripting lösen.
In der Library habe ich das gefunden:
pasted-from-clipboard.png
Leider fehlt mir hier das Wissen, wo genau steht dass Ausgang 1 geschaltet werden soll.
Vielleicht kann mich jemand auf die Spur setzen. Bin kein script König, aber fast-Learner
/**
* 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 HERE
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
let CONFIG = {
shelly_blu_name_prefix: "SBBT",
//shelly_blu_address: "bc:02:6e:c3:c8:b9",
actions: [
{
cond: {
addr: "bc:02:6e:c3:c8:b7",
Button: 1,
},
action: onButtonPress,
},
],
};
// 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);
}
Alles anzeigen
Ich poste das hier, da evtl. jemand anderes auch darüber stolpert.
Wenn man versucht den Ausgang (egal ob 1 oder 2) eines Uni Plus ein einer Szene ein oder auszuschalten passiert NICHTS!
Völlig unabhängig von Einstellungen, Eingängen usw. Manuell schalten funktioniert wunderbar aber nicht in einer Szene.
User apreick konnte das bestätigen, Ticket bei Shelly ist eröffnet.
Dann bleibt also nur ein Ticket beim Hersteller
Habe ich parallel schon gemacht, strange oder...
Wie würde das dann mit dem Shelly blue Button als trigger funktionieren?
Der funktioniert wunderbar in der Szene. Die Action telefonbenachrichtigung wird ausgeführt aber halt nicht das schalten des Ausgangs
Wäre scripting eine lösung:
wobei ich bei dem script nicht sehe wo der output geschaltet wird...
Sorry, aber ich bin nicht sicher ob du mein Problem verstanden hast.
Es geht darum dass ich den Ausgang nicht in einer Szene schalten kann.
Nur manuell.
Hat mit dem Eingang nichts zu tun.
Es ist auch egal welche Einstellungen ich verwende für den Eingang.
Ausgang 1 und 2 lassen sich manuell in der App schalten aber nicht in einer Szene!!