diff --git a/README.md b/README.md index bb514dd..de85c0d 100755 --- a/README.md +++ b/README.md @@ -125,6 +125,7 @@ States: ### **WORK IN PROGRESS** * (copilot) **BREAKING**: Commands now correctly use cmnd/ prefix instead of tele/ prefix - Fix regex bug causing MQTT commands to use "tele" instead of "cmnd" topics +* (copilot) Fix IRHVAC Power, Light and Mode fields showing NULL instead of actual string values * (copilot) Add Zigbee device control support for Tasmota coordinators - users can now control Zigbee devices (Power/Dimmer) through ioBroker states via automatic ZbSend command generation * (copilot) Added configuration for advanced MQTT settings * (copilot) Add support for Tasmota tele/MARGINS messages enabling integration of PowerLow, PowerHigh, and PowerDelta limits diff --git a/lib/datapoints.js b/lib/datapoints.js index 3edfc06..5f324ec 100644 --- a/lib/datapoints.js +++ b/lib/datapoints.js @@ -284,4 +284,22 @@ module.exports = { VEML6075_UvIndexText: { type: 'string', role: 'state', read: true, write: false }, VEML6075_UvLevel: { type: 'number', role: 'value', read: true, write: false }, VEML6075_UvPower: { type: 'number', role: 'value', read: true, write: false, unit: 'W/m²' }, + // IRHVAC specific datapoints to avoid conflicts with general Tasmota fields + IrReceived_IRHVAC_Power: { type: 'string', role: 'state', read: true, write: false }, + IrReceived_IRHVAC_Light: { type: 'string', role: 'state', read: true, write: false }, + IrReceived_IRHVAC_Mode: { type: 'string', role: 'state', read: true, write: false }, + IrReceived_IRHVAC_Vendor: { type: 'string', role: 'state', read: true, write: false }, + IrReceived_IRHVAC_Model: { type: 'number', role: 'value', read: true, write: false }, + IrReceived_IRHVAC_Temp: { type: 'number', role: 'value.temperature', read: true, write: false, unit: '°C' }, + IrReceived_IRHVAC_FanSpeed: { type: 'string', role: 'state', read: true, write: false }, + IrReceived_IRHVAC_SwingV: { type: 'string', role: 'state', read: true, write: false }, + IrReceived_IRHVAC_SwingH: { type: 'string', role: 'state', read: true, write: false }, + IrReceived_IRHVAC_Quiet: { type: 'string', role: 'state', read: true, write: false }, + IrReceived_IRHVAC_Turbo: { type: 'string', role: 'state', read: true, write: false }, + IrReceived_IRHVAC_Econo: { type: 'string', role: 'state', read: true, write: false }, + IrReceived_IRHVAC_Filter: { type: 'string', role: 'state', read: true, write: false }, + IrReceived_IRHVAC_Clean: { type: 'string', role: 'state', read: true, write: false }, + IrReceived_IRHVAC_Beep: { type: 'string', role: 'state', read: true, write: false }, + IrReceived_IRHVAC_Sleep: { type: 'number', role: 'value', read: true, write: false }, + IrReceived_IRHVAC_Celsius: { type: 'string', role: 'state', read: true, write: false }, }; diff --git a/lib/server.js b/lib/server.js index 3937ff9..09fc868 100644 --- a/lib/server.js +++ b/lib/server.js @@ -1029,15 +1029,17 @@ function MQTTServer(adapter) { } } - function addObject(attr, client, prefix, path) { - let replaceAttr = types[attr].replace || attr; + function addObject(typeKey, client, prefix, path) { + // Extract the actual attribute name for the state ID construction + const attr = typeKey.includes('_') && path.length > 0 ? typeKey.split('_').pop() : typeKey; + let replaceAttr = types[typeKey].replace || attr; let id = `${adapter.namespace}.${client.iobId}.${prefix ? `${prefix}.` : ''}${path.length ? `${path.join('_')}_` : ''}${replaceAttr.replace(FORBIDDEN_CHARS, '_')}`; let obj = { type: 'addObject', id: id, data: { _id: id, - common: Object.assign({}, types[attr]), + common: Object.assign({}, types[typeKey]), native: {}, type: 'state', }, @@ -1126,12 +1128,16 @@ function MQTTServer(adapter) { } nPath = undefined; } - } else if (types[attr]) { + } else if (types[attr] || (path.length > 0 && types[`${path.join('_')}_${attr}`])) { let allowReadColors; + // Check for path-based type definition first, then fallback to simple attr type + const typeKey = + path.length > 0 && types[`${path.join('_')}_${attr}`] ? `${path.join('_')}_${attr}` : attr; + // create object - const obj = addObject(attr, client, prefix, path); - let replaceAttr = types[attr].replace || attr; + const obj = addObject(typeKey, client, prefix, path); + let replaceAttr = types[typeKey].replace || attr; if (obj.data.common.storeMap) { delete obj.data.common.storeMap; diff --git a/test/testServer.js b/test/testServer.js index 653db0a..2258868 100644 --- a/test/testServer.js +++ b/test/testServer.js @@ -66,6 +66,7 @@ const rules = { 'tele/HomeMonitor/STATE': {send: '{"Time":"2018-01-19T20:15:16","Uptime":0,"Vcc":3.170,"Wifi":{"AP":1,"SSId":"SmartHOME","RSSI":100,"APMac":"60:31:97:3E:74:B4"}}', expect: {Vcc: 3.170, Wifi_RSSI: 100}}, 'tele/HomeMonitor/SENSOR': {send: '{"Time":"2018-01-19T20:15:16","Temperature":20.0,"Humidity":16.0,"Light":10,"Noise":60,"AirQuality":90,"TempUnit":"C"}', expect: {Temperature: 20.0, Humidity: 16.0, Light: 10, Noise: 60, AirQuality: 90}}, 'tele/esp32_shutter/STATE': {send: '{"Time":"2025-01-07T10:00:00","Uptime":"0T01:00:00","SHUTTER1":0,"SHUTTER2":25,"SHUTTER3":50,"SHUTTER4":75,"SHUTTER5":100,"SHUTTER6":0,"SHUTTER7":25,"SHUTTER8":50,"SHUTTER9":75,"SHUTTER10":100,"SHUTTER11":0,"SHUTTER12":25,"SHUTTER13":50,"SHUTTER14":75,"SHUTTER15":100,"SHUTTER16":33}', expect: {SHUTTER1: 0, SHUTTER2: 25, SHUTTER3: 50, SHUTTER4: 75, SHUTTER5: 100, SHUTTER6: 0, SHUTTER7: 25, SHUTTER8: 50, SHUTTER9: 75, SHUTTER10: 100, SHUTTER11: 0, SHUTTER12: 25, SHUTTER13: 50, SHUTTER14: 75, SHUTTER15: 100, SHUTTER16: 33}}, + 'tele/tasmota/RESULT': {send: '{"IrReceived":{"Protocol":"FUJITSU_AC","Bits":128,"Data":"0x1463001010FE0930210000000000208F","Repeat":0,"IRHVAC":{"Vendor":"FUJITSU_AC","Model":1,"Mode":"Auto","Power":"On","Celsius":"On","Temp":18,"FanSpeed":"Auto","SwingV":"Off","SwingH":"Off","Quiet":"Off","Turbo":"Off","Econo":"Off","Light":"Off","Filter":"Off","Clean":"Off","Beep":"Off","Sleep":-1}}}', expect: {'IrReceived_IRHVAC_Power': 'On', 'IrReceived_IRHVAC_Light': 'Off', 'IrReceived_IRHVAC_Mode': 'Auto', 'IrReceived_IRHVAC_Vendor': 'FUJITSU_AC', 'IrReceived_IRHVAC_Temp': 18}}, // Zigbee bulb test case from issue #265 'tele/Zigbee_Coordinator_CC2530/SENSOR': {send: '{"Time":"2022-05-05T20:49:08","ZbReceived":{"0x0856":{"Device":"0x0856","Name":"E14 Bulb","Power":1,"Dimmer":20,"Endpoint":1,"LinkQuality":65}}}', expect: {'ZbReceived_0x0856_Power': 1, 'ZbReceived_0x0856_Dimmer': 20, 'ZbReceived_0x0856_Device': '0x0856', 'ZbReceived_0x0856_Name': 'E14 Bulb'}}, // This rule must be last to ensure Emitter_1 maps to tasmota_0912A7 for the existing test