Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions src/devices/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -194,6 +194,7 @@
import {definitions as makegood} from "./makegood";
import {definitions as matcallBv} from "./matcall_bv";
import {definitions as mazda} from "./mazda";
import me202z = require("./me202z");
import {definitions as meazon} from "./meazon";
import {definitions as mercator} from "./mercator";
import {definitions as miboxer} from "./miboxer";
Expand Down Expand Up @@ -356,7 +357,7 @@
import {definitions as zigbeetlc} from "./zigbeetlc";
import {definitions as zipato} from "./zipato";

const definitions: DefinitionWithExtend[] = [

Check failure on line 360 in src/devices/index.ts

View workflow job for this annotation

GitHub Actions / ci

Type '(({ zigbeeModel: string[]; fingerprint?: Fingerprint[]; } & DefinitionBase & DefinitionConfig & DefinitionFeatures) | ({ ...; } & ... 2 more ... & DefinitionFeatures) | ({ ...; } & ... 3 more ... & Partial<...>) | { ...; } | { ...; })[]' is not assignable to type 'DefinitionWithExtend[]'.
...acova,
...acuityBrandsLighting,
...adeo,
Expand Down Expand Up @@ -550,6 +551,7 @@
...makegood,
...matcallBv,
...mazda,
...me202z,
...meazon,
...mercator,
...miboxer,
Expand Down
106 changes: 106 additions & 0 deletions src/devices/me202z.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,106 @@
import * as tuya from 'zigbee-herdsman-converters/lib/tuya';

Check failure on line 1 in src/devices/me202z.ts

View workflow job for this annotation

GitHub Actions / ci

Cannot find module 'zigbee-herdsman-converters/lib/tuya' or its corresponding type declarations.
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Could you move this to tuya.ts?

import * as exposes from 'zigbee-herdsman-converters/lib/exposes';

Check failure on line 2 in src/devices/me202z.ts

View workflow job for this annotation

GitHub Actions / ci

Cannot find module 'zigbee-herdsman-converters/lib/exposes' or its corresponding type declarations.
const ea = exposes.access;

// Data points
const dp = {
distance: 2, // liquid height (cm)
cfg_threshold: 21, // tank depth (mm)
power_level_v: 5, // power voltage (raw)
};

// Helper to round 1 decimal
function round1(v: number): number { return Math.round(v * 10) / 10; }

// Safely parse data point values
function getDataValue(datatype: any, data: any): number {
try {
if (Buffer.isBuffer(data)) return data.readUIntBE(0, data.length);
if (Array.isArray(data)) return data.reduce((acc, b) => (acc << 8) + b, 0);
return Number(data);
} catch { return Number(data); }
}

// Cache last known tank depth per device
const lastKnown: Record<string, { depthMm?: number }> = {};

// FromZigbee converter
const fzLocal = {
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please use tuyaDatapoints instead of this converter, you can find examples in tuya.ts

me202z_report_all: {
cluster: 'manuSpecificTuya',
type: ['commandDataReport', 'commandDataResponse'],
convert: (model: any, msg: any, publish: any, options: any, meta: any) => {
const out: Record<string, any> = {};
const items = msg.data?.dpValues || [];
const deviceId = meta.device.ieeeAddr;

let distanceCm: number | undefined;
let depthMm = lastKnown[deviceId]?.depthMm;

for (const { dp: id, datatype, data } of items) {
if (id === dp.distance) {
distanceCm = getDataValue(datatype, data);
out.liquid_height = distanceCm;
} else if (id === dp.cfg_threshold) {
depthMm = getDataValue(datatype, data);
lastKnown[deviceId] = { depthMm };
out.cfg_threshold_mm = depthMm;
} else if (id === dp.power_level_v) {
const val = getDataValue(datatype, data);
out.power_level_v = round1(val / 10);
}
}

if (distanceCm != null && depthMm != null && depthMm > 0) {
out.level_percent = round1((distanceCm / (depthMm / 10)) * 100);
}

return out;
},
},
};

// ToZigbee converter
const tzLocal = {
cfg_threshold_mm: {
key: ['cfg_threshold_mm'],
convertSet: async (entity: any, key: any, value: any, meta: any) => {
const val = Number(value);
await tuya.sendDataPointValue(entity, dp.cfg_threshold, val);
lastKnown[meta.device.ieeeAddr] = { depthMm: val };
return { state: { cfg_threshold_mm: val } };
},
},
};

export = [{
fingerprint: [{ modelID: 'TS0601', manufacturerName: '_TZE284_mxujdmxo' }],
model: 'ME202Z-TS0601',
vendor: 'Tuya',
description: 'ME202Z submersible liquid level sensor (range 10–400 cm)',
fromZigbee: [fzLocal.me202z_report_all],
toZigbee: [tzLocal.cfg_threshold_mm],
exposes: [
exposes.numeric('liquid_height', ea.STATE)
.withUnit('cm')
.withDescription('Measured liquid height in centimeters'),
exposes.numeric('level_percent', ea.STATE)
.withUnit('%')
.withDescription('Liquid level as % of configured tank depth'),
exposes.numeric('cfg_threshold_mm', ea.ALL)
.withUnit('mm')
.withValueMin(100)
.withValueMax(4000)
.withDescription('Configured tank depth in millimeters'),
exposes.numeric('power_level_v', ea.STATE)
.withUnit('V')
.withDescription('Power supply voltage'),
],
onEvent: async (type: string, data: any, device: any) => {
if (['deviceAnnounce', 'deviceInterview'].includes(type)) {
const ep = device.getEndpoint(1);
try { await tuya.sendDataPointQuery(ep, dp.distance); } catch {}
try { await tuya.sendDataPointQuery(ep, dp.cfg_threshold); } catch {}
}
},
}];
Loading