NEWS
CC2530/CC2531 als Custom-Zigbee-Aktor/Sensor
-
@skvarel sagte in CC2530/CC2531 als Custom-Zigbee-Aktor/Sensor:
@asgothian .. puhh, das klingt doch schon kompliziert.
Es ist einfacher als du denkst. Ich hatte bei der Beschreibung aber auch einen Denkfehler. Versuch mal so:
const fzlocal = { ptvo_switch_analog_to_boolean: { cluster: 'genAnalogInput', type: ['attributeReport', 'readResponse'], convert: (model, msg, publish, options, meta) => { const value =( msg.data['presentValue'] > 300 ); const action = (value ? 'occupied':'free'); return {action: postfixWithEndpointName(action, msg, model, meta)}; }, }; const device = { zigbeeModel: ['CC2531.US100'], model: 'CC2531.US100', vendor: 'inventwo', description: '[CC2531 w. US-100 Sensor](https://github.com/inventwo/custom-zigbee)', fromZigbee: [fz.ignore_basic_report, fz.ptvo_switch_uart, fz.ptvo_switch_analog_input,fzlocal.ptvo_switch_analog_to_boolean], toZigbee: [tz.ptvo_switch_trigger, tz.ptvo_switch_uart,], exposes: [ exposes.numeric('l1', ea.STATE).withDescription('Innenraummessung').withUnit('mm'), exposes.action(['occupied'].withDescription('Innenraum belegt'), exposes.action(['free'].withDescription('Innenraum frei'), ], meta: { multiEndpoint: true, }, endpoint: (device) => { return { l1: 1, }; }, configure: async (device, coordinatorEndpoint, logger) => { const endpoint = device.getEndpoint(1); await endpoint.read('genBasic', ['modelId', 'swBuildId', 'powerSource']); }, };
A.
Nachtrag: ich hab das icon aus dem code genommen, und den Kopf nicht mit angegeben - das sollte aber kein problem für Dich sein
Nachtrag2: ich hatte noch einen Denkfehler - ist jetzt korrigiert.
-
@asgothian .. teste ich!
-
@asgothian .. das funktioniert leider überhaupt nicht
Sobald ich deine Teile einsetze, kommt gar nichts mehr an. Bei dir waren noch ein paar Klammern offen. Die habe ich geschlossen.
So hatte ich den Code verwendet:
const fzlocal = { ptvo_switch_analog_to_boolean: { cluster: 'genAnalogInput', type: ['attributeReport', 'readResponse'], convert: (model, msg, publish, options, meta) => { const value =( msg.data['presentValue'] > 300 ); const action = (value ? 'occupied':'free'); return {action: postfixWithEndpointName(action, msg, model, meta)}; }, } }; const device = { zigbeeModel: ['CC2531.US100'], model: 'CC2531.US100', vendor: 'inventwo', description: '[CC2531 w. US-100 Sensor](https://github.com/inventwo/custom-zigbee)', fromZigbee: [fz.ignore_basic_report, fz.ptvo_switch_uart, fz.ptvo_switch_analog_input, fzlocal.ptvo_switch_analog_to_boolean], toZigbee: [tz.ptvo_switch_trigger, tz.ptvo_switch_uart,], exposes: [ exposes.numeric('l1', ea.STATE).withDescription('Innenraummessung').withUnit('mm'), exposes.action(['occupied']).withDescription('Innenraum belegt'), exposes.action(['free']).withDescription('Innenraum frei'), ], meta: { multiEndpoint: true, }, endpoint: (device) => { return { l1: 1, }; }, configure: async (device, coordinatorEndpoint, logger) => { const endpoint = device.getEndpoint(1); await endpoint.read('genBasic', ['modelId', 'swBuildId', 'powerSource']); }, };
-
@skvarel gibt es Meldungen im log ? Ich bin wieder unterwegs und schau mal wenn ich wieder zu Hause bin
-
@skvarel ich hab nochmal was angepasst. Versuch bitte mal so:
const zigbeeHerdsmanConverters = require('zigbee-herdsman-converters'); const zigbeeHerdsmanUtils = require('zigbee-herdsman-converters/lib/utils'); const exposes = zigbeeHerdsmanConverters['exposes'] || require("zigbee-herdsman-converters/lib/exposes"); const ea = exposes.access; const e = exposes.presets; const modernExposes = (e.hasOwnProperty('illuminance_lux'))? false: true; const fz = zigbeeHerdsmanConverters.fromZigbeeConverters || zigbeeHerdsmanConverters.fromZigbee; const tz = zigbeeHerdsmanConverters.toZigbeeConverters || zigbeeHerdsmanConverters.toZigbee; const ptvo_switch = (zigbeeHerdsmanConverters.findByModel)?zigbeeHerdsmanConverters.findByModel('ptvo.switch'):zigbeeHerdsmanConverters.findByDevice({modelID: 'ptvo.switch'}); fz.legacy = ptvo_switch.meta.tuyaThermostatPreset; fz.ptvo_on_off = { cluster: 'genOnOff', type: ['attributeReport', 'readResponse'], convert: (model, msg, publish, options, meta) => { if (msg.data.hasOwnProperty('onOff')) { const channel = msg.endpoint.ID; const endpointName = `l${channel}`; const binaryEndpoint = model.meta && model.meta.binaryEndpoints && model.meta.binaryEndpoints[endpointName]; const prefix = (binaryEndpoint) ? model.meta.binaryEndpoints[endpointName] : 'state'; const property = `${prefix}_${endpointName}`; if (binaryEndpoint) { return {[property]: msg.data['onOff'] === 1}; } return {[property]: msg.data['onOff'] === 1 ? 'ON' : 'OFF'}; } }, }; const fzlocal = { local_analog_switch: { cluster: 'genAnalogInput', type: ['attributeReport', 'readResponse'], convert: (model, msg, publish, options, meta) => { const payload = {}; const channel = msg.endpoint.ID; const name = `l${channel}`; const endpoint = msg.endpoint; payload[name] = precisionRound(msg.data['presentValue'], 3); payload[`contact_${channel}`] = (msg.data['presentValue'] < 300) const cluster = 'genLevelCtrl'; if (endpoint && (endpoint.supportsInputCluster(cluster) || endpoint.supportsOutputCluster(cluster))) { payload['brightness_' + name] = msg.data['presentValue']; } else if (msg.data.description !== undefined) { const data1 = msg.data['description']; if (data1) { const data2 = data1.split(','); const devid = data2[1]; const unit = data2[0]; if (devid) { payload['device_' + name] = devid; } const valRaw = msg.data['presentValue']; if (unit) { let val = precisionRound(valRaw, 1); const nameLookup = { C: 'temperature', '%': 'humidity', m: 'altitude', Pa: 'pressure', ppm: 'quality', psize: 'particle_size', V: 'voltage', A: 'current', Wh: 'energy', W: 'power', Hz: 'frequency', pf: 'power_factor', lx: 'illuminance', }; let nameAlt = ''; if (unit === 'A' || unit === 'pf') { if (valRaw < 1) { val = precisionRound(valRaw, 3); } } if (unit.startsWith('mcpm') || unit.startsWith('ncpm')) { const num = unit.substr(4, 1); nameAlt = num === 'A' ? unit.substr(0, 4) + '10' : unit; val = precisionRound(valRaw, 2); } else { nameAlt = nameLookup[unit]; } if (nameAlt === undefined) { const valueIndex = parseInt(unit, 10); if (!isNaN(valueIndex)) { nameAlt = 'val' + unit; } } if (nameAlt !== undefined) { payload[nameAlt + '_' + name] = val; } } } } return payload; }, }, } const device = { zigbeeModel: ['CC2531.US100'], model: 'CC2531.US100', vendor: 'inventwo', description: '[CC2531 w. US-100 Sensor](https://github.com/inventwo/custom-zigbee)', fromZigbee: [fz.ignore_basic_report, fz.ptvo_switch_uart, fzlocal.local_analog_switch,], toZigbee: [tz.ptvo_switch_trigger, tz.ptvo_switch_uart,], exposes: [ exposes.numeric('l1', ea.STATE).withDescription('Innenraummessung').withUnit('mm'), e.contact().withEndpoint('l1'), ], meta: { multiEndpoint: true, }, endpoint: (device) => { return { l1: 1, }; }, configure: async (device, coordinatorEndpoint, logger) => { const endpoint = device.getEndpoint(1); await endpoint.read('genBasic', ['modelId', 'swBuildId', 'powerSource']); }, }; module.exports = device;
(wieder ohne icon)
-
@asgothian .. Meldungen im Log:
z2m: Exception while calling fromZigbee converter: precisionRound is not defined}
So sieht es beim neuen Code aus:
-
@skvarel das ist nachdem du die Fehlermeldung eliminiert hast oder vorher ? einfach den Aufruf zu precisionRound entfernen und den Wert direkt nutzen
aus
precisionRound(msg.data['presentValue'], 3);
wird
msg.data['presentValue'];
A.
-
@asgothian sagte in CC2530/CC2531 als Custom-Zigbee-Aktor/Sensor:
msg.data['presentValue'];
Der Fehler ist jetzt weg! Die Änderung hat geholfen.
Es bleibt aber bei N/A
-
@skvarel Du bist doch auf dem ioBroker discord. Wollen wir uns da kurz zusammen hängen - geht einfacher als hier per posts.
Ich bin einfach mal im '2 user only' channel
A.
-
@asgothian .. heute schaffe ich es leider nicht mehr. Morgen hätte ich Zeit.
-
@skvarel morgen tuts. Wann ?
-
@asgothian .. ab späten Vormittag. Uhrzeit ist mir egal. Ich habe nichts weiter vor!
-
@skvarel sagte in CC2530/CC2531 als Custom-Zigbee-Aktor/Sensor:
@asgothian .. ab späten Vormittag. Uhrzeit ist mir egal. Ich habe nichts weiter vor!
sagen wir 11 ?
-
@asgothian .. das passt! Vielen Dank nochmal, bis morgen
-
@asgothian .. vielen Dank! Ich bin begeistert
Jetzt gehe ich an die anderen Konverter. Da müssen die Namen noch angepasst werden.
Das wichtigste wäre mir beim Gewächshaus, direkt Fenster und Tür sowie Heizung und Licht .. anstatt Kontakt und State
-
-
Sooo, nächster Konverter angepasst. @jkvarel hat mir geholfen
Gefällt mir aber wegen der fehlenden Icons bei den Temperaturen noch nicht.
-
@Asgothian .. ich könnte noch mal deine Hilfe gebrauchen
Ich möchte gern das Icon davor haben.
Hier mal mein Konverter, den ich mit @jkvarel gemacht habe:
const precisionRound = zigbeeHerdsmanUtils.precisionRound; const fzlocal = { local_analog_switch: { cluster: 'genAnalogInput', type: ['attributeReport', 'readResponse'], convert: (model, msg, publish, options, meta) => { const payload = {}; const channel = msg.endpoint.ID; const mapping = { 1: 'Vorlauftemperatur', 2: 'Ruecklauftemperatur' } if(mapping[channel] === undefined) return payload payload[mapping[channel]] = precisionRound(msg.data['presentValue'], 1) return payload } } } const device = { zigbeeModel: ['CC2531.DS18B20'], model: 'CC2531.DS18B20', vendor: 'inventwo', description: '[CC2531 w. DS18B20 Sensor](https://github.com/inventwo/custom-zigbee)', fromZigbee: [fz.ignore_basic_report, fz.ptvo_switch_analog_input, fzlocal.local_analog_switch], toZigbee: [tz.ptvo_switch_trigger,], exposes: [ exposes.numeric('Vorlauftemperatur', ea.STATE).withUnit('°C'), exposes.numeric('Ruecklauftemperatur', ea.STATE).withUnit('°C'), ], meta: { multiEndpoint: true, }, endpoint: (device) => { return { Vorlauftemperatur: 1, Ruecklauftemperatur: 2, };
-
@skvarel Ich fürchte da läufst du auf die Grenzen des Möglichen. Soweit ich das korrekt erkannt habe wird das Icon aus der Benennung des Payloads gemacht - genau das was du da gerade 'umbenannt' hast.
Was du versuchen kannst:
- 'Vorlauftemperatur' durch 'temperatur_vorlauf' ersetzen (überall wo es auftritt)
- 'Ruecklauftemperatur' durch 'temperatur_ruecklauf' ersetzen (überall wo es auftritt)
- hoffen
A.
-
@asgothian .. das teste ich morgen direkt. Dann habe ich aber nicht mehr meine Wunschnamen in der Zigbee-Kachel. Einen Tod muss ich da wohl sterben.