Created
August 13, 2025 02:45
-
-
Save ShadowBelmolve/8eac1e793c33985ade1cec7e44051115 to your computer and use it in GitHub Desktop.
Modified version of Z2M TS001F for use with Girier and Zbeacon versions
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| import * as tuya from 'zigbee-herdsman-converters/lib/tuya'; | |
| import * as fz from 'zigbee-herdsman-converters/converters/fromZigbee'; | |
| import * as reporting from 'zigbee-herdsman-converters/lib/reporting'; | |
| import * as utils from 'zigbee-herdsman-converters/lib/utils'; | |
| import * as globalStore from 'zigbee-herdsman-converters/lib/store'; | |
| const fzLocal = { | |
| TS011F_electrical_measurement: { | |
| ...fz.electrical_measurement, | |
| convert: (model, msg, publish, options, meta) => { | |
| const result = (fz.electrical_measurement.convert(model, msg, publish, options, meta) ) ?? {}; | |
| const lookup = { | |
| power: "activePower", | |
| current: "rmsCurrent", | |
| voltage: "rmsVoltage", | |
| }; | |
| // Wait 5 seconds before reporting a 0 value as this could be an invalid measurement. | |
| // https://github.com/Koenkk/zigbee2mqtt/issues/16709#issuecomment-1509599046 | |
| if (result) { | |
| for (const key of ["power", "current", "voltage"]) { | |
| if (key in result) { | |
| const value = result[key]; | |
| clearTimeout(globalStore.getValue(msg.endpoint, key)); | |
| if (value === 0) { | |
| const configuredReporting = msg.endpoint.configuredReportings.find( | |
| (c) => c.cluster.name === "haElectricalMeasurement" && c.attribute.name === lookup[key], | |
| ); | |
| const time = (configuredReporting ? configuredReporting.minimumReportInterval : 5) * 2 + 1; | |
| globalStore.putValue( | |
| msg.endpoint, | |
| key, | |
| setTimeout(() => { | |
| const payload = {[key]: value}; | |
| // Device takes a lot of time to report power 0 in some cases. When current == 0 we can assume power == 0 | |
| // https://github.com/Koenkk/zigbee2mqtt/discussions/19680#discussioncomment-7868445 | |
| if (key === "current") { | |
| payload.power = 0; | |
| } | |
| publish(payload); | |
| }, time * 1000), | |
| ); | |
| delete result[key]; | |
| } | |
| } | |
| } | |
| } | |
| // Device takes a lot of time to report power 0 in some cases. When the state is OFF we can assume power == 0 | |
| // https://github.com/Koenkk/zigbee2mqtt/discussions/19680#discussioncomment-7868445 | |
| if (meta.state.state === "OFF") { | |
| result.power = 0; | |
| } | |
| return result; | |
| }, | |
| } | |
| } | |
| export default { | |
| // Note: below you will find the TS011F_plug_2 and TS011F_plug_3. These are identified via a fingerprint and | |
| // thus preferred above the TS011F_plug_1 if the fingerprint matches | |
| zigbeeModel: ["TS011F"], | |
| model: "TS011F_plug_1", | |
| description: "Smart plug (with power monitoring)", | |
| vendor: "Tuya", | |
| whiteLabel: [ | |
| {vendor: "LELLKI", model: "TS011F_plug"}, | |
| {vendor: "Neo", model: "NAS-WR01B"}, | |
| {vendor: "BlitzWolf", model: "BW-SHP15"}, | |
| {vendor: "BlitzWolf", model: "BW-SHP13"}, | |
| {vendor: "MatSee Plus", model: "PJ-ZSW01"}, | |
| {vendor: "MODEMIX", model: "MOD037"}, | |
| {vendor: "MODEMIX", model: "MOD048"}, | |
| {vendor: "Coswall", model: "CS-AJ-DE2U-ZG-11"}, | |
| {vendor: "Aubess", model: "TS011F_plug_1"}, | |
| tuya.whitelabel("BSEED", "FK86ZEUSK1W", "Wall-mounted electrical socket", ["_TZ3000_4ux0ondb"]), | |
| tuya.whitelabel("Nous", "A1Z", "Smart plug (with power monitoring)", ["_TZ3000_2putqrmw", "_TZ3000_ksw8qtmt"]), | |
| tuya.whitelabel("Moes", "Moes_plug", "Smart plug (with power monitoring)", ["_TZ3000_yujkchbz"]), | |
| tuya.whitelabel("Moes", "ZK-EU", "Smart wallsocket (with power monitoring)", ["_TZ3000_ss98ec5d"]), | |
| tuya.whitelabel("Elivco", "LSPA9", "Smart plug (with power monitoring)", ["_TZ3000_okaz9tjs"]), | |
| tuya.whitelabel("PSMART", "T440", "Smart wallsocket (with power monitoring)", ["_TZ3000_y4ona9me"]), | |
| tuya.whitelabel("Nous", "A6Z", "Outdoor smart socket", ["_TZ3000_266azbg3"]), | |
| tuya.whitelabel("Nedis", "ZBPO130FWT", "Outdoor smart plug (with power monitoring)", ["_TZ3000_3ias4w4o"]), | |
| tuya.whitelabel("Nous", "A9Z", "Smart ZigBee Socket", ["_TZ3210_ddigca5n"]), | |
| tuya.whitelabel("Girier", "JR-ZPM01", "Smart Plug", ["_TZ3000_ww6drja5"]), | |
| tuya.whitelabel("Nous", "A7Z", "Smart ZigBee Socket", ["_TZ3210_rwmitwj4"]), | |
| tuya.whitelabel("Zbeacon", "TS011F_plug_1", "Smart plug (with power monitoring)", ["Zbeacon"]), | |
| ], | |
| ota: true, | |
| extend: [ | |
| tuya.modernExtend.tuyaOnOff({ | |
| electricalMeasurements: true, | |
| electricalMeasurementsFzConverter: fzLocal.TS011F_electrical_measurement, | |
| powerOutageMemory: true, | |
| indicatorMode: true, | |
| childLock: true, | |
| onOffCountdown: true, | |
| }), | |
| ], | |
| configure: async (device, coordinatorEndpoint) => { | |
| await tuya.configureMagicPacket(device, coordinatorEndpoint); | |
| const endpoint = device.getEndpoint(1); | |
| await reporting.bind(endpoint, coordinatorEndpoint, ["genOnOff", "haElectricalMeasurement", "seMetering"]); | |
| await reporting.rmsVoltage(endpoint, {change: 5}); | |
| await reporting.rmsCurrent(endpoint, {change: 50}); | |
| if (!["_TZ3000_0zfrhq4i", "_TZ3000_okaz9tjs", "_TZ3000_typdpbpg", "_TZ3000_ww6drja5", "Zbeacon"].includes(device.manufacturerName)) { | |
| // Gives INVALID_DATA_TYPE error for _TZ3000_0zfrhq4i (as well as a few others in issue 20028) | |
| // https://github.com/Koenkk/zigbee2mqtt/discussions/19680#discussioncomment-7667035 | |
| await reporting.activePower(endpoint, {change: 10}); | |
| } | |
| await reporting.currentSummDelivered(endpoint); | |
| const acCurrentDivisor = device.manufacturerName === "_TZ3000_typdpbpg" ? 2000 : 1000; | |
| endpoint.saveClusterAttributeKeyValue("haElectricalMeasurement", { | |
| acCurrentDivisor, | |
| acCurrentMultiplier: 1, | |
| }); | |
| endpoint.saveClusterAttributeKeyValue("seMetering", { | |
| divisor: 100, | |
| multiplier: 1, | |
| }); | |
| utils.attachOutputCluster(device, "genOta"); | |
| device.save(); | |
| }, | |
| } |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment