Kannst du mal ein Debug von der Instanz posten?
Grüße,
Kai
Kannst du mal ein Debug von der Instanz posten?
Grüße,
Kai
Von welcher?
Bei dem eine Shelly kommt nichts und bei den anderen nur manchmal.
Gruß Burkhard
Hier von dem den nichts schickt.
Nach einem Geräteneustart schickt er das:
dump(1).txt (1,1 KB)
Danach ist Sendepause
Ach ja, Firmware ist bei beiden 0.14.1-g22a4cb7.
Hallo Kai,
ich habe den neuen ShellyBlue Door/Window am Bluetooth des Shelly Plus 1PM über die Shelly App angemeldet und möchte den Fensterkontakt auch in IPS auswerten. Im Debug ist vom Fensterkontakt nichts zu sehen.
Hast Du eine Idee ?
viele Grüße
Soweit ich das gelesen habe senden die ShellyBlue nur etwas an den Shelly Plus/Pro. Um dann etwas zu MQTT zu bekommen muss auf dem Plus/Pro entsprechende Skripte erstellt werden die das dann weiterreichen. Sprich out-of-the-box geht das nicht und es ist nicht standardisiert. Somit wäre es für Kai sehr Schwer da etwas zu integrieren.
Gruß
Dennis
Da gebe ich meinem Namensvetter recht, Du musst auf einem Deiner Shelly ein Script dauerhaft laufen lassen.
Ich habe das mal mit dem folgenden Script testweise implementiert (da sind bestimmt noch Fehler dabei), sodass mein BLU Door/Window über einen Plus i4 die Daten an den MQTT Server von Symcon überträgt.
/* ============================= Config CHANGE HERE =============================== */
let mqttID = "shellyBLU"; //MQTT Topic ID, (behind topicPrefix)
let sendMQTT = true; //send Button Data also per MQTT, true/false
let topicPrefix = ""; //Here you can set your own mqtt Topic Prefix
let vSwitch = false; // create MQTT virtual Switch states, true/false
let debug = false; //show debug msg in log, true/false, warning setting this to 'true' will delay reaktion speed a lot
/* ============================== STOP CHANGING HERE =============================== */
//========= Skript Setup =========
let activeScan = true; //active or passiv Bluetooth Scan, true/false
let _cid = "0ba9"; //Allterco, Company ID(MFD)
let uuid = "fcd2"; //BTHome, Service ID
let devID1 = "SBBT"; // BluButton1, deviceID, --> SBBT-002C evt. 002C = charge?
let devID2 = "SBDW"; // Blu Door/Window, deviceID
let bthObjectIDs = []; //Used BTHome Service.Payload ObjectID List for BluButton1,(here you can find a full List --> " https://bthome.io/format ")
bthObjectIDs[0x00] = { key: 'pid', dataType: 'uint8' };
bthObjectIDs[0x01] = { key: 'battery', dataType: 'uint8', unit: '%' };
bthObjectIDs[0x3a] = { key: 'buttonID', dataType: 'uint8' };
bthObjectIDs[0x05] = { key: 'illuminance', dataType: 'uint24', factor: 0.01 };
bthObjectIDs[0x1a] = { key: 'doorStateID', dataType: 'uint8' };
bthObjectIDs[0x20] = { key: 'moistureLvl', dataType: 'uint8' };
bthObjectIDs[0x2d] = { key: 'windowStateID', dataType: 'uint8' };
bthObjectIDs[0x3f] = { key: 'rotationLvl', dataType: 'int16', factor: 0.1 };
let vSwitchCache = {}, last_packet_id = 0x100, last_addr = 0, scanDuration = BLE.Scanner.INFINITE_SCAN;
//=========== End Setup ===========
function SendMQTTmsg(mac,event){
if(MQTT.isConnected()){
let mainTopic = mqttID +'-'+ mac + '/', inputID = JSON.stringify(event.info.data.inputID);
if(topicPrefix.length !== 0) mainTopic = topicPrefix +'/'+ mqttID +'-'+ mac + '/';
if(inputID !== '0' && inputID !== '254' && vSwitch){ // do not trigger virtual switch logik for beacon or hold events.
if(vSwitchCache['s'+inputID] === undefined || vSwitchCache['s'+inputID] === 'false'){
vSwitchCache['s'+inputID] = 'true';
}else{
vSwitchCache['s'+inputID] = 'false';
}
}
if(debug) print('MQTT Publishing: _Topic: ', mainTopic, 'events/rpc _Payload: ', JSON.stringify(event));
MQTT.publish(mainTopic + 'events/rpc', JSON.stringify(event), 1, false);
MQTT.publish(mainTopic + 'status/input:' + inputID, JSON.stringify(event.info.ts), 1, false);
if(inputID !== '0' && inputID !== '254' && vSwitch) MQTT.publish(mainTopic + 'status/switch:' + inputID, vSwitchCache['s'+inputID], 1, false);
MQTT.publish(mainTopic + 'info/battery', JSON.stringify(event.info.data.battery_value), 1, true);
MQTT.publish(mainTopic + 'info/rssi', JSON.stringify(event.info.data.rssi), 1, true);
MQTT.publish(mainTopic + 'info/lastTimeStamp', JSON.stringify(event.info.ts), 1, true);
MQTT.publish(mainTopic + 'info/lastAktion', event.info.event, 1, true);
MQTT.publish(mainTopic + 'info/lastAktionID', inputID, 1, true);
MQTT.publish(mainTopic + 'info/mac', event.info.data.mac, 1, true);
MQTT.publish(mainTopic + 'info/device', event.info.data.device, 1, true);
MQTT.publish(mainTopic + 'info/encryption', JSON.stringify(event.info.data.encryption), 1, true);
MQTT.publish(mainTopic + 'info/gateway', event.info.data.gateway, 1, true);
MQTT.publish(mainTopic + 'info/windowStateID', JSON.stringify(event.info.data.windowStateID), 1, true);
}else{
print('Error: MQTT is still not ready, cant send msg');
}
}
function FilterEvents(obj){
if(obj.info === undefined || obj.info.data === undefined || obj.info.data.generation !== 'BLU') return;
SendMQTTmsg(obj.info.data.mac,obj);
}
let BTHomeDecoder = {
UInt_To_Int: function (uint, bitsz) {
let mask = 1 << (bitsz - 1); //create mask to filter last bit
if (uint & mask) {
return uint - (1 << bitsz); //convert uint to negative int
} else {
return uint; //uint is positive, no change needed.
}
},
GetMaxBytes: function (dataType) {
if (dataType === 'uint8' || dataType === 'int8') return 1;
if (dataType === 'uint16' || dataType === 'int16') return 2;
if (dataType === 'uint24' || dataType === 'int24') return 3;
return 255;
},
GetValue: function (dataType, buffer) {
let maxBytes = this.GetMaxBytes(dataType);
if (buffer.length < maxBytes) {
print('Error: ValueBuffer has, ', buffer.length, ' Bytes with DataType, ', dataType);
return null;
}
let data = null;
let _1stByte = buffer.at(0); //get 1.Byte of Buffer
let _2ndByte = null;
if (maxBytes > 1) _2ndByte = buffer.at(1); //get 2.Byte of Buffer
let _3rdByte = null;
if (maxBytes > 2) _3rdByte = buffer.at(2); //get 3.Byte of Buffer
if (dataType === 'uint8') data = _1stByte;
if (dataType === 'int8') data = this.UInt_To_Int(_1stByte, 8);
if (dataType === 'uint16') data = 0xffff & ((_2ndByte << 8) | _1stByte);
if (dataType === 'int16') data = this.UInt_To_Int(0xffff & ((_2ndByte << 8) | _1stByte), 16);
if (dataType === 'uint24') data = 0x00ffffff & ((_3rdByte << 16) | (_2ndByte << 8) | _1stByte);
if (dataType === 'int24') data = this.UInt_To_Int(0x00ffffff & ((_3rdByte << 16) | (_2ndByte << 8) | _1stByte), 24);
return data;
},
Unpack: function (payload) {
if (typeof payload !== "string" || payload.length === 0) return null;
let btHomeObj = {}, byte = payload.at(0), value, objectID; //byte = payload.at(0) --> get 1.Byte of Payload
if (byte & 0x1) {
btHomeObj['encryption'] = true; //analyze 1. Bit and set btHomeObj encryption boolean
} else {
btHomeObj['encryption'] = false;
}
btHomeObj['version'] = byte >> 5; //cut,move to 6.Bit, save the rest as version
if (btHomeObj['version'] !== 2) return null; //analyse the rest Bits 6,7,8 inside version, exit if BTHome Version is not 2
if (btHomeObj['encryption']) return btHomeObj; //exit if payload is encrypted
payload = payload.slice(1); //remove used 1.Byte from payload
while (payload.length > 0) {
byte = payload.at(0); //get 1.Byte of Payload
objectID = bthObjectIDs[byte]; //compare 1.Byte with known BTHome objectIds list, add parameter if known object
if (typeof objectID === 'undefined') {
print('Error: Unknown BThome Object, decimal_ID: ', byte, ' convert to hex and compare hex_ID "0x.." with full objID list --> https://bthome.io/format');
break; //exit loop, if objectID is unknown
}
payload = payload.slice(1); //remove used 1.Byte from payload
value = this.GetValue(objectID.dataType, payload);
if (value === null) break; //exit loof, if value null
if (typeof objectID.factor !== 'undefined') value = (value * objectID.factor); //add factor
btHomeObj[objectID.key] = value;
if (typeof objectID.unit !== 'undefined') value = (JSON.stringify(value) + objectID.unit); //add unit
if (typeof objectID.unit !== 'undefined') btHomeObj[(objectID.key+"String")] = value;
payload = payload.slice(this.GetMaxBytes(objectID.dataType)); //remove used value Bytes from payload
}
return btHomeObj;
},
};
function ScanCB(status, response) {
if (status !== BLE.Scanner.SCAN_RESULT) return; //exit if Scan status is stopped or unknown
if (response.service_data === undefined || response.service_data[uuid] === undefined) return; //Filter only BThome Responses
let BTHomeObj = BTHomeDecoder.Unpack(response.service_data[uuid]); //decode Sevice Data
if (BTHomeObj === null) {print('Error: Failed to Unpack service_data of, ', response.addr); return;}
if (last_packet_id === BTHomeObj.pid && last_addr === response.addr) return; //exit if packet is already known.
if (debug) print('Received packet, raw Data:', JSON.stringify(response));
if (response.local_name !== undefined) BTHomeObj.device = 'Unknown-Device--> ' + response.local_name;
if (response.local_name !== undefined && response.local_name.indexOf(devID1) >= 0) BTHomeObj.device = 'Blu Button1'; //search for Blu Button1
if (response.local_name !== undefined && response.local_name.indexOf(devID2) >= 0) BTHomeObj.device = 'Blu Door/Window'; //search for Blu Door/Window
if (response.local_name === undefined) BTHomeObj.device = 'Hidden-Device';
last_packet_id = BTHomeObj.pid, last_addr = response.addr, BTHomeObj.addr = response.addr, BTHomeObj.rssi = response.rssi, BTHomeObj.gateway = Shelly.getDeviceInfo().id;
if (debug) print('Received BTHome packet: ', JSON.stringify(BTHomeObj));
if (typeof BTHomeObj.buttonID === 'number' && BTHomeObj.illuminance === undefined) { //somehow filter for blu Button
let buttonEventMap = ['wake_up','single_push','double_push','triple_push','long_push','pairing_push','default_reset_push'], buttonInput = BTHomeObj.buttonID;
if(buttonInput > 6 && buttonInput !== 254)buttonInput = 'unknown_push';
if(buttonInput < 7)buttonInput = buttonEventMap[buttonInput];
if(buttonInput === 254)buttonInput = 'hold_push';
Shelly.emitEvent(buttonInput, {
generation: 'BLU',
gateway: BTHomeObj.gateway,
device: BTHomeObj.device,
battery_value: BTHomeObj.battery,
battery_string: BTHomeObj.batteryString,
inputID: BTHomeObj.buttonID,
mac: BTHomeObj.addr,
rssi: BTHomeObj.rssi,
pid: BTHomeObj.pid,
encryption: BTHomeObj.encryption
});
}
if (typeof BTHomeObj.illuminance === 'number'){ //somehow, filter for blu door/window
Shelly.emitEvent('blu_DW_ChangedStatus', {
generation: 'BLU',
gateway: BTHomeObj.gateway,
device: BTHomeObj.device,
battery_value: BTHomeObj.battery,
battery_string: BTHomeObj.batteryString,
doorStateID: BTHomeObj.doorStateID,
windowStateID: BTHomeObj.windowStateID,
illuminance: BTHomeObj.illuminance,
moistureLvl: BTHomeObj.moistureLvl,
rotationLvl: BTHomeObj.rotationLvl,
buttonID: BTHomeObj.buttonID,
mac: BTHomeObj.addr,
rssi: BTHomeObj.rssi,
pid: BTHomeObj.pid,
encryption: BTHomeObj.encryption
});
}
}
function Start_BLE_Scan() {
let bleScanStarted = BLE.Scanner.Start({ duration_ms: scanDuration, active: activeScan }, ScanCB);
if (bleScanStarted === false) {
print('Error: BTHome Scanner could not be started, will try again in 5sek.');
Timer.set(5000, false, Start_BLE_Scan);
} else {
let scanType = 'Passiv';
if (activeScan) scanType = 'Active';
print('Success: BTHome ', scanType, ' Scanner running in Background');
}
}
//__Main__
Start_BLE_Scan();
if(sendMQTT) Shelly.addEventHandler(FilterEvents);
Ich könnte mir für das Modul vorstellen, dass Kai entweder vorgaben für die Struktur macht oder für diese Gerätekategorie die Konfiguration erweitert wird, sodass für jede Variable auch der MQTT-Topic bzw. zumindest der Suffix angegeben werden muss.
Beste Grüße
Dennis
Das sieht komisch aus, kannst du mal die MQTT Einstellungen vom Shelly als Screenshot posten?
Grüße,
Kai
Da ich selbst noch keine Bluetooth Geräte habe ist das sehr schwer nachzuvollziehen.
Ich finde die Idee mit einer vorgegebenen Struktur aber gar nicht so verkehrt.
Das Script habe ich gerade überflogen, du sendest dort also direkt per MQTT die Daten weiter?
„mainTopic + 'info/windowStateID“ ist also das Topic für den Status…
„mainTopic + ‚info/device‘“ hier sieht man also von welchem BLE Gerät das Payload kommt, das wiederum ist eher schlecht, denn wenn das BLE Gerät dann mal mit einem anderen Shelly verbunden ist, dann kommt der Status nicht mehr an der richtigen Stelle in Symcon an.
Also am geschicktesten wäre es, wenn das Topic irgendwie so in der Art aufgebaut wäre:
shelly/ble/%device%/%mac%/battery
shelly/ble/%device%/%mac%/rssi
shelly/ble/%device%/%mac%/lastAktion
shelly/ble/%device%/%mac%/lastAktionID
shelly/ble/%device%/%mac%/windowStateID
%deviced% und %max% sind Platzhalter für den tatsächlichen Namen bzw. die tatsächliche Mac Adresse der BLE Geräte.
Das ist nur eine Idee, ich habe mir die Doku noch nicht angeschaut.
Aber so könnte man dann für die BLE Geräte eine eigene Instanz erstellen, die dann immer die richtigen Daten auswertet, egal an welchem Shelly die BLE Geräte hängen?
Wäre das eine Idee?
Grüße,
Kai
Aktiviere mal bitte „Generic staus update over MQTT“ und teste es dann nochmal.
Grüße,
Kai
Leider funktioniert das auch nicht.
Anscheinend bin ich der einzige mit dem Problem.
Kann es an meinen Shellys liegen?
Denkst du ein Rücksetzen auf Werkseinstellungen könnte helfen?
Gibt es eine Möglichkeit dass ich das „alte“ Modul wieder installieren könnte?
Alle Shellys ohne PLUS funktionieren.
Gruß Burkhard
Bitte schalte das mal ein und poste dann ein Debug, der Haken muss definitiv gesetzt sen.
Grüße,
Kai
Kai,
das ist mir jetzt besonders peinlich und tut mir sehr leid.
Ich habe jetzt das Password für MQTT in den Shellys noch einmal neu eingegeben und jetzt läuft alles wie immer.
Keine Ahnung warum die Passwörter weg waren.
Gruß Burkhard
Alles gut, dass passiert schon mal.
Kannst du dann mal schauen, ob nun alle Variablen wie gewünscht in Symcon gefüllt werden, oder ob es noch Probleme mit einzelnen Variablen gibt?
Grüße,
Kai
Sehr gut, dann beobachte das bitte mal.
Grüße,
Kai
OK.
Wenn mir noch etwas auffällt prüfe ich vorher ob der Fehler nicht bei mir liegt.
Dankeschön für deine Mühe und Geduld.
Gruß Burkhard
Eine Frage habe ich noch.
Ich habe Firmware 0.14.1 auf den Shellys installiert.
Es gibt ein Update auf 1.0.3.
Würdest du die alte Version lassen oder die neue Installieren.
Mit der alten läuft alles und ich vermisse nichts.
Gruß Burkhard
Ich würde das Update machen.
Grüße,
Kai