#include <Arduino.h>
#ifndef ZIGBEE_MODE_ZCZR
#error "Select Zigbee ZCZR mode in Tools -> Zigbee mode"
#endif
#include "Zigbee.h"
#define BUTTON_PIN BOOT_PIN
#define ACTION_SINGLE 1
#define ACTION_DOUBLE 2
#define ACTION_TRIPLE 3
#define ACTION_HOLD 4
ZigbeeMultistate buttonDevice(1);
bool lastState = HIGH;
uint32_t pressStart = 0;
uint32_t lastRelease = 0;
uint8_t clickCount = 0;
bool holdSent = false;
void sendAction(uint8_t action)
{
buttonDevice.setMultistateInput(action);
buttonDevice.reportMultistateInput();
Serial.printf("Action sent: %u\n", action);
}
void setup()
{
Serial.begin(115200);
pinMode(BUTTON_PIN, INPUT_PULLUP);
// Factory Reset: BOOT-Button beim Start gedrückt halten
delay(200);
if (digitalRead(BUTTON_PIN) == LOW) {
Serial.println("Factory reset triggered!");
Zigbee.factoryReset();
}
buttonDevice.setManufacturerAndModel("Custom", "ESP32-Zigbee-Button");
buttonDevice.addMultistateInput();
buttonDevice.setMultistateInputStates(4);
Zigbee.addEndpoint(&buttonDevice);
Serial.println("Starting Zigbee...");
if (!Zigbee.begin(ZIGBEE_ROUTER))
{
Serial.println("Zigbee start failed!");
ESP.restart();
}
// Timeout nach 30s – läuft auch ohne Verbindung weiter
uint32_t timeout = millis();
while (!Zigbee.connected() && millis() - timeout < 30000)
{
Serial.print(".");
delay(100);
}
if (Zigbee.connected()) {
Serial.println("\nConnected");
} else {
Serial.println("\nNot connected, running anyway...");
}
}
void loop()
{
bool state = digitalRead(BUTTON_PIN);
if (state == LOW && lastState == HIGH)
{
pressStart = millis();
holdSent = false;
}
if (state == LOW && !holdSent && millis() - pressStart > 1000)
{
sendAction(ACTION_HOLD);
holdSent = true;
clickCount = 0;
}
if (state == HIGH && lastState == LOW)
{
if (!holdSent)
{
clickCount++;
lastRelease = millis();
}
}
if (clickCount > 0 && millis() - lastRelease > 500)
{
if (clickCount == 1) sendAction(ACTION_SINGLE);
else if (clickCount == 2) sendAction(ACTION_DOUBLE);
else sendAction(ACTION_TRIPLE);
clickCount = 0;
}
lastState = state;
delay(10);
}const e = require('zigbee-herdsman-converters/lib/exposes');
const lastSeen = {};
const definition = {
zigbeeModel: ['ESP32-Zigbee-Button'],
model: 'ESP32-Zigbee-Button',
vendor: 'Custom',
description: 'ESP32-C6 Zigbee Button',
fromZigbee: [
{
cluster: 'genMultistateInput',
type: ['attributeReport', 'readResponse'],
convert: (model, msg, publish, options, meta) => {
const actionMap = {1: 'single', 2: 'double', 3: 'triple', 4: 'hold'};
const value = msg.data['presentValue'];
if (!actionMap[value]) return;
// Duplikat-Filter für Mesh-Routing
const key = `${meta.device.ieeeAddr}_${value}`;
const now = Date.now();
if (lastSeen[key] && now - lastSeen[key] < 1000) return;
lastSeen[key] = now;
return {action: actionMap[value]};
},
},
],
toZigbee: [],
exposes: [e.enum('action', e.access.STATE, ['single', 'double', 'triple', 'hold'])
.withDescription('Button action')],
configure: async (device, coordinatorEndpoint) => {
const endpoint = device.getEndpoint(1);
await endpoint.bind('genMultistateInput', coordinatorEndpoint);
await endpoint.configureReporting('genMultistateInput', [{
attribute: 'presentValue',
minimumReportInterval: 0,
maximumReportInterval: 0,
reportableChange: 1,
}]);
},
};
module.exports = definition;[17.6.2026, 16:33:38] z2m:mqtt: MQTT publish: topic 'zigbee2mqtt/0x543204fffe3d996c', payload '{"action":"single","linkquality":183}'
[17.6.2026, 16:33:40] z2m:mqtt: MQTT publish: topic 'zigbee2mqtt/0x543204fffe3d996c', payload '{"action":"double","linkquality":183}'
[17.6.2026, 16:33:42] z2m:mqtt: MQTT publish: topic 'zigbee2mqtt/0x543204fffe3d996c', payload '{"action":"triple","linkquality":122}'
[17.6.2026, 16:33:44] z2m:mqtt: MQTT publish: topic 'zigbee2mqtt/0x543204fffe3d996c', payload '{"action":"hold","linkquality":191}'
... ich fraue mich darauf!ZitatWoher die 16500 Wh kommen, ist mir rätselhaft.Achtung: Das ist eine Normierungsgrenze für die Erstellung von Trainingsdaten.
Normierungsgrenzen: PV=7788 Wh, Hausverbrauch: Min=0 Wh / Max=6290 Wh
Dieser Wert wird immer ein wenig höher liegen als das wahrscheinliche Maximum und ist die obere Normgrenze == 1.Zitat von: 300P am 16 Juni 2026, 17:08:04et voilà ! ->>> hier ist der Wert -> GrafikDa steht bei mir 16500 Wh, obwohl ich folgendes definiert habe:
attr mySolarForecast setupInverterDev01 myHuawei etotal=Accumulated_energy_yield:kWh capacity=15000 strings=PV1,PV3 asynchron=1 pvOut=Active_Power:W pvIn=PV_Input_Power:W(Die 16500 Wh sind lustigerweise die theoretische Maximalleistung meines WRs, der allerdings mittels "länderspezifischem Parametersatz" auf 15 kW limitiert ist.)attr mySolarForecast setupStringPeak PV1=8.46 PV3=8.46Das sind aber 16920 W in Summe.