Skip to content

Commit

Permalink
Fixes related to the issue:
Browse files Browse the repository at this point in the history
  • Loading branch information
ptvoinfo committed Aug 2, 2023
1 parent 3b11713 commit 799f0a6
Showing 1 changed file with 111 additions and 26 deletions.
137 changes: 111 additions & 26 deletions src/devices/custom_devices_diy.ts
Original file line number Diff line number Diff line change
Expand Up @@ -507,7 +507,7 @@ const definitions: Definition[] = [
zigbeeModel: ['ptvo.switch'],
model: 'ptvo.switch',
vendor: 'Custom devices (DiY)',
description: '[Multi-channel relay switch](https://ptvo.info/zigbee-switch-configurable-firmware-router-199/)',
description: '[Multi-functional device](https://ptvo.info/zigbee-configurable-firmware-features/)',
fromZigbee: [fz.on_off, fz.ptvo_multistate_action, legacy.fz.ptvo_switch_buttons, fz.ptvo_switch_uart,
fz.ptvo_switch_analog_input, fz.brightness, fz.ignore_basic_report, fz.temperature,
fzLocal.humidity2, fzLocal.pressure2, fzLocal.illuminance2],
Expand All @@ -516,9 +516,8 @@ const definitions: Definition[] = [
const expose: Expose[] = [];
const exposeDeviceOptions: KeyValue = {};
const deviceConfig = ptvoGetMetaOption(device, 'device_config', '');

if (deviceConfig === '') {
if ( (device != null) && device.endpoints ) {
if ((device != null) && device.endpoints) {
for (const endpoint of device.endpoints) {
const exposeEpOptions: KeyValue = {};
ptvoAddStandardExposes(endpoint, expose, exposeEpOptions, exposeDeviceOptions);
Expand All @@ -533,39 +532,118 @@ const definitions: Definition[] = [
}
}
} else {
for (let i = 0; i < deviceConfig.length; i++) {
const epConfig = deviceConfig.charCodeAt(i);
if (epConfig <= 0x20) {
// device configuration description from a device
const deviceConfigArray = deviceConfig.split(/[\r\n]+/);
let prevEp = -1;
for (let i = 0; i < deviceConfigArray.length; i++) {
const epConfig = deviceConfigArray[i];
const epId = parseInt(epConfig.substr(0, 1), 16);
if (epId <= 0) {
continue;
}
const epId = i + 1;
const epName = `l${epId}`;
const epValueAccessRights = epConfig.substr(1, 1);
const epStateType = ((epValueAccessRights === 'W') || (epValueAccessRights === '*'))?
ea.STATE_SET: ea.STATE;
let valueConfig = epConfig.substr(2);
valueConfig = valueConfig.split(',');
let valueId = (valueConfig[0])? valueConfig[0]: '';
let valueDescription = (valueConfig[1])? valueConfig[1]: '';
let valueUnit = (valueConfig[2] !== undefined)? valueConfig[2]: '';
const exposeEpOptions: KeyValue = {};
if ((epConfig & 0x01) != 0) {
// GPIO input
exposeEpOptions['expose_action'] = true;
}
if ((epConfig & 0x02) != 0) {
// GPIO output
if (valueId === '*') {
// GPIO output (Generic)
exposeEpOptions['exposed_onoff'] = true;
expose.push(e.switch().withEndpoint(epName));
}
if ((epConfig & 0x04) != 0) {
// reportable analog value
exposeEpOptions['exposed_analog'] = true;
expose.push(e.numeric(epName, ea.STATE).withDescription('State or sensor value'));
} else if ((epConfig & 0x08) != 0) {
// readable analog value
} else if (valueId === '#') {
// GPIO state (contact, gas, noise, occupancy, presence, smoke, sos, tamper, vibration, water leak)
exposeEpOptions['exposed_onoff'] = true;
let exposeObj = undefined;
switch (valueDescription) {
case 'g': exposeObj = e.gas(); break;

Check failure on line 563 in src/devices/custom_devices_diy.ts

View workflow job for this annotation

GitHub Actions / ci

Expected indentation of 24 spaces but found 28
case 'n': exposeObj = e.noise_detected(); break;

Check failure on line 564 in src/devices/custom_devices_diy.ts

View workflow job for this annotation

GitHub Actions / ci

Expected indentation of 24 spaces but found 28
case 'o': exposeObj = e.occupancy(); break;

Check failure on line 565 in src/devices/custom_devices_diy.ts

View workflow job for this annotation

GitHub Actions / ci

Expected indentation of 24 spaces but found 28
case 'p': exposeObj = e.presence(); break;

Check failure on line 566 in src/devices/custom_devices_diy.ts

View workflow job for this annotation

GitHub Actions / ci

Expected indentation of 24 spaces but found 28
case 'm': exposeObj = e.smoke(); break;

Check failure on line 567 in src/devices/custom_devices_diy.ts

View workflow job for this annotation

GitHub Actions / ci

Expected indentation of 24 spaces but found 28
case 's': exposeObj = e.sos(); break;

Check failure on line 568 in src/devices/custom_devices_diy.ts

View workflow job for this annotation

GitHub Actions / ci

Expected indentation of 24 spaces but found 28
case 't': exposeObj = e.tamper(); break;

Check failure on line 569 in src/devices/custom_devices_diy.ts

View workflow job for this annotation

GitHub Actions / ci

Expected indentation of 24 spaces but found 28
case 'v': exposeObj = e.vibration(); break;

Check failure on line 570 in src/devices/custom_devices_diy.ts

View workflow job for this annotation

GitHub Actions / ci

Expected indentation of 24 spaces but found 28
case 'w': exposeObj = e.water_leak(); break;

Check failure on line 571 in src/devices/custom_devices_diy.ts

View workflow job for this annotation

GitHub Actions / ci

Expected indentation of 24 spaces but found 28
default: // 'c'

Check failure on line 572 in src/devices/custom_devices_diy.ts

View workflow job for this annotation

GitHub Actions / ci

Expected indentation of 24 spaces but found 28
exposeObj = e.contact();
};
expose.push(exposeObj.withEndpoint(epName));
} else if (valueConfig) {
let valueName = undefined; // name in Z2M
let valueNumIndex = undefined;
const idxPos = valueId.search(/(\d+)$/);
if (valueId.startsWith('mcpm') || valueId.startsWith('ncpm')) {
const num = parseInt(valueId.substr(4, 1), 16);
valueName = valueId.substr(0, 4) + num;
} else if (idxPos >= 0) {
valueNumIndex = valueId.substr(idxPos);
valueId = valueId.substr(0, idxPos);
}

// analog value
// 1: value name (if empty, use the EP name)
// 2: description (if empty or undefined, use the value name)
// 3: units (if undefined, use the key name)
const infoLookup: any = {
'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_lux',
};
valueName = (valueName !== undefined)? valueName: infoLookup[valueId];

if ((valueName === undefined) && valueNumIndex) {
valueName = 'val' + valueNumIndex;
}

valueName = (valueName === undefined)? epName: valueName + '_' + epName;

if ((valueDescription === undefined) || (valueDescription === '')) {
if (infoLookup[valueId]) {
valueDescription = infoLookup[valueId].replace('_', ' ');
} else {
valueDescription = 'Sensor value';
}
}
valueDescription = valueDescription.substring(0, 1).toUpperCase() +
valueDescription.substring(1);

if (valueNumIndex) {
valueDescription = valueDescription + ' ' + valueNumIndex;
}

if (((valueUnit === undefined) || (valueUnit === '')) && infoLookup[valueId]) {
valueUnit = valueId;
}

exposeEpOptions['exposed_analog'] = true;
expose.push(e.numeric(epName, ea.STATE_SET)
expose.push(e.numeric(valueName, epStateType)
.withValueMin(-9999999).withValueMax(9999999).withValueStep(1)
.withDescription('State or sensor value'));
.withDescription(valueDescription)
.withUnit(valueUnit));
}
const endpoint = device.getEndpoint(epId);
if (!endpoint) {
continue;
}
ptvoAddStandardExposes(endpoint, expose, exposeEpOptions, exposeDeviceOptions);
if (prevEp !== epId) {
prevEp = epId;
ptvoAddStandardExposes(endpoint, expose, exposeEpOptions, exposeDeviceOptions);
}
}
}
if (exposeDeviceOptions['expose_action']) {
Expand All @@ -583,7 +661,7 @@ const definitions: Definition[] = [
const endpointList: any = [];
const deviceConfig = ptvoGetMetaOption(device, 'device_config', '');
if (deviceConfig === '') {
if ( (device != null) && device.endpoints ) {
if ((device != null) && device.endpoints) {
for (const endpoint of device.endpoints) {
const epId = endpoint.ID;
const epName = `l${epId}`;
Expand Down Expand Up @@ -614,8 +692,15 @@ const definitions: Definition[] = [
if (device != null) {
const controlEp = device.getEndpoint(1);
if (controlEp != null) {
ptvoSetMetaOption(device, 'device_config', (await controlEp.read('genBasic', ['locationDesc'])).locationDesc);
device.save();
try {
let deviceConfig = await controlEp.read('genBasic', [32768]);
if (deviceConfig) {
deviceConfig = deviceConfig['32768'];
ptvoSetMetaOption(device, 'device_config', deviceConfig);
device.save();
}
}
catch (err) { /* do nothing */ }
}
}
},
Expand Down

0 comments on commit 799f0a6

Please sign in to comment.