Heeft iemand al een oplossing om een zigbee mini dim van Sonoff toe te voegen aan de homey pro?
Je zou de Sonoff ZBBridge kunnen proberen, deze is via de eWeLink app te integreren met Homey.
Naast de ZBBridge kan je met een Sonoff iHost met Homeyscrpt gegevens uitwisselen*, ook kan je met Zigbee2MQTT en een Rasberry Pi Zigbee devices delen.
Deze methodes vrijwaren je van de notoire Zigbee problemen met Homey.
- Script voorbeeld functie voor iHost communicatie via http (let oResp = await fetch(IHOST_URL … :
// setVirtualDevic
async function setVirtualDevices() {
let bResult = false; // default return
let iSuccessCount = 0;
let uValue = NO_VALUE;
let aResult = [];
try {
// Only process specific capabilities;
const oCapMapping = new Map([
['temperature', 'Temp'],
['humidity', 'Hum'],
['illumination', 'Lux'],
['smoke', 'Smoke'],
['power', 'Power']
]);
// HomeyScript - Write iHost values to Device Capabilities Virtual Devices (direct mutation)
let oResp = await fetch(IHOST_URL, {
headers: {
'Authorization': 'Bearer ' + TOKEN,
'Content-Type': 'application/json'
}
});
let oResult = await oResp.json();
let aDevices = oResult.data.device_list || [];
// sort
aDevices.sort(); // Alphabetical order
if (DO_LOG)
log('Found ' + aDevices.length + ' iHost devices');
for (let iDevice = 0; iDevice < aDevices.length; iDevice++) {
let oDevice = aDevices[iDevice];
let sDeviceName = oDevice.name || 'Unknown';
if (DEV_SKIP.includes(sDeviceName)) {
/* if (DO_LOG)
log(`DEV_SKIP found and skipped:${sDeviceName}`);*/
continue; // skip this device
}
uValue = NO_VALUE; // (re)set
if (DO_LOG_X)
log('--- Processing iHost Device: ' + sDeviceName + ' --- ' + JSON.stringify(oDevice.capabilities));
// Find Virtual Device by EXACT name match using global
const oVirtualDevice = VIRTUALDEVICES.find(device =>
device.name === sDeviceName.trim()
) || null;
if (!oVirtualDevice || !oVirtualDevice.id || !oVirtualDevice.capabilitiesObj) {
// if (DO_LOG)
log(' No matching Virtual Device found: ' + sDeviceName);
continue;
}
if (DO_LOG_X)
log(` Found Virtual Device: ${oVirtualDevice.name} (${oVirtualDevice.id})`);
let aCapabilities = oDevice.capabilities || [];
let oState = oDevice.state || {};
for (let iCap = 0; iCap < aCapabilities.length; iCap++) {
let oCap = aCapabilities[iCap];
let sOriginalCapName = oCap.capability; // iHost: 'temperature' 'humidity' 'illumination' 'smoke' 'power'
if (!oCapMapping.has(sOriginalCapName)) { // skip not supported Capability
/* if (DO_LOG)
log(`EXIT - CAPABILITY not found: ${sOriginalCapName}`);*/
continue;
}
// Extract value from iHost state using ORIGINAL iHost name
if (oState[sOriginalCapName]) {
if (typeof oState[sOriginalCapName] === 'object' &&
oState[sOriginalCapName][sOriginalCapName] !== undefined) {
uValue = oState[sOriginalCapName][sOriginalCapName];
} else {
uValue = oState[sOriginalCapName];
}
}
// log(`sDeviceName: ${sDeviceName} ${JSON.stringify(uValue)}`);
//-!-!-!-!-!-!-!-!-!-!-!-!-!-!-!-!-!-!-!-!-!-!-!-!-!-!-!-!-!-!
// TOGGLE
//-!-!-!-!-!-!-!-!-!-!-!-!-!-!-!-!-!-!-!-!-!-!-!-!-!-!-!-!-!-!
const oChannels = Object.keys(uValue).filter(key => {
// Numeric key 1-4 AND has toggleState property
return !isNaN(key) && key >= "1" && key <= "4" &&
uValue[key] &&
typeof uValue[key] === 'object' &&
uValue[key].hasOwnProperty('toggleState');
});
// log(`oChannels:${oChannels}`)
let oAllToggles = {};
// power
if ((sOriginalCapName === 'toggle' || sOriginalCapName === 'power')) {
// uValue === NO_VALUE && || sOriginalCapName === 'onoff'
uValue = (oState?.power?.powerState === 'on');
/*if (DO_LOG)
log(`0 POWER ... uValue:${uValue} sOriginalCapName:${sOriginalCapName} sDeviceName:${sDeviceName}`);*/
}
else if (sOriginalCapName === 'toggle' && oChannels) {
// console.log(`channels: ${oChannels}`); // ["1", "2", "3", "4"]
oAllToggles = Object.values(uValue).map(item => item.toggleState);
uValue = oAllToggles.join(';');
if (uValue !== ';' && DO_LOG_X)
log(`1 TOGGLE ... uValue:${JSON.stringify(uValue)} sOriginalCapName:${sOriginalCapName} sDeviceName:${sDeviceName}`);
}
//-!-!-!-!-!-!-!-!-!-!-!-!-!-!-!-!-!-!-!-!-!-!-!-!-!-!-!-!-!-!
// END TOGGLE
//-!-!-!-!-!-!-!-!-!-!-!-!-!-!-!-!-!-!-!-!-!-!-!-!-!-!-!-!-!-!
// Handle uValue
if (sDeviceName.startsWith('$net') && DO_LOG) { // NET -- && variablename includes _Power'
log(`NET - sDeviceName:${sDeviceName} uValue:${uValue}`);
}
const sType = typeof uValue;
// Handle missing binary states → default false
if (uValue === NO_VALUE && ['smoke', 'motion'].includes(sOriginalCapName)) {
uValue = false; // might be NO_VALUE No smoke No motion
}
else if (['toggle', 'power'].includes(sOriginalCapName)) { // 'onoff', uValue === NO_VALUE &&
// log(`$$$$$$$$$$$$$ toggle sDeviceName:${sDeviceName} uValue:${uValue}`)
uValue = isBool(uValue); // Boolean
} else if (sType === 'boolean') { // Boolean
// Do nothing - Keep boolean as-is (true/false)
} else if (sType === 'number') {
uValue = parseFloat(uValue); // Number
} else {
uValue = String(uValue); // String
}
if (uValue === NO_VALUE) {
// sendPush(`${DATE} ${TIME} - iHostGet1: ${sDeviceName} with capability:${sOriginalCapName}: STILL NOTHING FOUND: "${uValue}"`)
continue; // STILL NOTHING FOUND
}
// sDeviceNameCap is sDeviceName + capability extension as sCapIdentifier see: iHostGet1Help
const sDeviceNameCap = `${sDeviceName}_${sOriginalCapName[0].toLowerCase()}`; // + _h, _t, _s, _i, _o, _p
// Get ID first
const sVarId = getVarId(sDeviceNameCap);
if (DO_LOG_X)
log(`sDeviceNameCap:${sDeviceNameCap} sOriginalCapName:${sOriginalCapName[0].toLowerCase()} sVarId: ${sVarId} uValue: ${uValue};`);
if (sVarId !== null) { // && uValue !== NO_VALUE
try {
// SET VARIABLE BY ID FROM DEVICE NAME . VAR_MAP . getVarId
if (DO_LOG_X)
log(`SET VARIABLE BY DEVICE ${sDeviceName} = ${uValue}`);
bResult = await setVariable(sVarId, uValue);
if (bResult) {
iSuccessCount++;
if (DO_LOG_X)
log(` ${sOriginalCapName}: ${uValue}`);
} else {
log(` ${sOriginalCapName} failed`);
}
} catch (oError) {
log(`${sOriginalCapName}: ${oError.message}`);
}
} else {
log(`${sOriginalCapName}: No variable Found for sDeviceNameCap:${sDeviceNameCap} uValue:"${uValue}"`);
// sendPush(`${DATE} ${TIME} - iHostGet1: ${sOriginalCapName}: invalid value: "${uValue}"`)
}
}
// bResult = true;
// MESSAGE BLOCK
if (sDeviceName.startsWith('rook') && uValue === true) { // Rook ALARM
log(`ALARM - sDeviceName:${sDeviceName} uValue:${uValue}`);
// sendPush(`${DATE} ${TIME} - iHostGet1 - ROOK ALARM - sDeviceName:${sDeviceName} uValue:${uValue}`);
}
else if (sDeviceName.startsWith('$net') && uValue === false) { // Error NET'
log(`NET - sDeviceName:${sDeviceName} uValue:${uValue}`);
// sendPush(`${DATE} ${TIME} - iHostGet1 - NET ALARM - sDeviceName:${sDeviceName} uValue:${uValue}`);
}
aResult.push(`--- Done: ${sDeviceName} --- ${uValue}`);
}
} catch (oError) {
log(`setVirtualDevices failed: ${oError.message}`);
return false;
}
aResult = aResult.sort();
if (DO_LOG)
log(aResult.join('\n'));
return true; // bResult;
}
1 Like
Of eWeLink CUBE op een Raspberry Pi met ZigBee dongle (iHost werkt op hetzelfde OS voor zover ik weet)