Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Enforce no floating promises with eslint. #7583

Merged
merged 2 commits into from
May 31, 2024
Merged
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
3 changes: 2 additions & 1 deletion .eslintignore
Original file line number Diff line number Diff line change
Expand Up @@ -3,4 +3,5 @@ test/*
index.*
converters/*
devices/*
lib/*
lib/*
scripts/*
4 changes: 2 additions & 2 deletions .eslintrc.json
Original file line number Diff line number Diff line change
Expand Up @@ -11,8 +11,7 @@
],
"root": true,
"parserOptions": {
"ecmaVersion": 2020,
"sourceType": "module"
"project": "./tsconfig.json"
},
"rules": {
"require-jsdoc": "off",
Expand All @@ -22,6 +21,7 @@
"@typescript-eslint/no-empty-function": "off",
"@typescript-eslint/ban-ts-comment": "off",
"@typescript-eslint/no-unused-vars": "off",
"@typescript-eslint/no-floating-promises": "error",
"tsdoc/syntax": "warn",
"valid-jsdoc": "off"
},
Expand Down
10 changes: 0 additions & 10 deletions jest.config.js

This file was deleted.

8 changes: 8 additions & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -67,5 +67,13 @@
"ts-jest": "^29.1.2",
"ts-morph": "^22.0.0",
"typescript": "^5.4.5"
},
"jest": {
"preset": "ts-jest",
"testEnvironment": "node",
"roots": [
"test/",
"src/"
]
}
}
8 changes: 4 additions & 4 deletions src/converters/toZigbee.ts
Original file line number Diff line number Diff line change
Expand Up @@ -1262,9 +1262,9 @@ const converters2 = {
const transition = meta.message.transition ?? 15;
utils.assertNumber(transition, 'transition');
const speed = Math.min(255, Math.max(1, Math.round(255 / transition)));
converters2.light_hue_saturation_move.convertSet(entity, 'hue_move', speed, meta);
await converters2.light_hue_saturation_move.convertSet(entity, 'hue_move', speed, meta);
} else if (value === 'stop_colorloop') {
converters2.light_hue_saturation_move.convertSet(entity, 'hue_move', 'stop', meta);
await converters2.light_hue_saturation_move.convertSet(entity, 'hue_move', 'stop', meta);
} else {
const payload = {effectid: utils.getFromLookup(value, lookup), effectvariant: 0};
await entity.command('genIdentify', 'triggerEffect', payload, utils.getOptions(meta.mapped, entity));
Expand Down Expand Up @@ -4189,7 +4189,7 @@ const converters2 = {
convertSet: async (entity, key, value, meta) => {
utils.assertEndpoint(entity);
const keypadLockout = utils.getKey(constants.keypadLockoutMode, value, value, Number);
entity.write('hvacUserInterfaceCfg', {keypadLockout});
await entity.write('hvacUserInterfaceCfg', {keypadLockout});
entity.saveClusterAttributeKeyValue('hvacUserInterfaceCfg', {keypadLockout});
return {state: {keypad_lockout: value}};
},
Expand Down Expand Up @@ -4275,7 +4275,7 @@ const converters2 = {
key: ['local_temperature_calibration'],
convertSet: async (entity, key, value, meta) => {
utils.assertNumber(value);
entity.write('hvacThermostat', {localTemperatureCalibration: Math.round(value * 10)},
await entity.write('hvacThermostat', {localTemperatureCalibration: Math.round(value * 10)},
{srcEndpoint: 11, disableDefaultResponse: true});
return {state: {local_temperature_calibration: value}};
},
Expand Down
2 changes: 1 addition & 1 deletion src/devices/danfoss.ts
Original file line number Diff line number Diff line change
Expand Up @@ -215,7 +215,7 @@ const definitions: Definition[] = [
const time = Math.round(((new Date()).getTime() - constants.OneJanuary2000) / 1000);
// Time-master + synchronised
const values = {timeStatus: 3, time: time, timeZone: ((new Date()).getTimezoneOffset() * -1) * 60};
endpoint.write('genTime', values);
await endpoint.write('genTime', values);
},
},
{
Expand Down
2 changes: 1 addition & 1 deletion src/devices/heiman.ts
Original file line number Diff line number Diff line change
Expand Up @@ -539,7 +539,7 @@ const definitions: Definition[] = [
const time = Math.round(((new Date()).getTime() - constants.OneJanuary2000) / 1000);
// Time-master + synchronised
const values = {timeStatus: 3, time: time, timeZone: ((new Date()).getTimezoneOffset() * -1) * 60};
endpoint.write('genTime', values);
await endpoint.write('genTime', values);
},
exposes: [e.battery(), e.temperature(), e.humidity(), e.pm25(), e.hcho(), e.voc(), e.aqi(), e.pm10(),
e.enum('battery_state', ea.STATE, ['not_charging', 'charging', 'charged'])],
Expand Down
4 changes: 2 additions & 2 deletions src/devices/shinasystem.ts
Original file line number Diff line number Diff line change
Expand Up @@ -46,10 +46,10 @@ const fzLocal = {
GCM300Z_valve_status: {
cluster: 'genOnOff',
type: ['attributeReport', 'readResponse'],
convert: (model, msg, publish, options, meta) => {
convert: async (model, msg, publish, options, meta) => {
if (msg.data.hasOwnProperty('onOff')) {
const endpoint = meta.device.getEndpoint(1);
endpoint.read('genOnOff', [0x9007]); // for update : close_remain_timeout
await endpoint.read('genOnOff', [0x9007]); // for update : close_remain_timeout
return {gas_valve_state: msg.data['onOff'] === 1 ? 'OPEN' : 'CLOSE'};
}
},
Expand Down
4 changes: 2 additions & 2 deletions src/devices/sunricher.ts
Original file line number Diff line number Diff line change
Expand Up @@ -448,7 +448,7 @@ const definitions: Definition[] = [
const endpoint = device.getEndpoint(1);
const hours24 = 1000 * 60 * 60 * 24;
// Device does not ask for the time with binding, therefore we write the time every 24 hours
const interval = setInterval(async () => syncTime(endpoint), hours24);
const interval = setInterval(async () => await syncTime(endpoint), hours24);
globalStore.putValue(device, 'time', interval);
}
},
Expand Down Expand Up @@ -648,7 +648,7 @@ const definitions: Definition[] = [
);

// Device does not asks for the time with binding, we need to write time during configure
syncTime(endpoint);
await syncTime(endpoint);

// Trigger initial read
await endpoint.read('hvacThermostat', ['systemMode', 'runningState', 'occupiedHeatingSetpoint']);
Expand Down
2 changes: 1 addition & 1 deletion src/devices/tuya.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6677,7 +6677,7 @@ const definitions: Definition[] = [
configure: async (device, coordinatorEndpoint) => {
await tuya.configureMagicPacket(device, coordinatorEndpoint);
const endpoint = device.getEndpoint(1);
endpoint.command('genBasic', 'tuyaSetup', {});
await endpoint.command('genBasic', 'tuyaSetup', {});
await reporting.bind(endpoint, coordinatorEndpoint, ['msTemperatureMeasurement']);
await reporting.bind(endpoint, coordinatorEndpoint, ['genOnOff', 'haElectricalMeasurement', 'seMetering']);
await reporting.rmsVoltage(endpoint, {change: 5});
Expand Down
6 changes: 3 additions & 3 deletions src/devices/ubisys.ts
Original file line number Diff line number Diff line change
Expand Up @@ -229,7 +229,7 @@ const ubisys = {
await sleepSeconds(2);
// re-read and dump all relevant attributes
log(' Done - will now read back the results.');
ubisys.tz.configure_j1.convertGet(entity, key, meta);
await ubisys.tz.configure_j1.convertGet(entity, key, meta);
}
},
convertGet: async (entity, key, meta) => {
Expand Down Expand Up @@ -287,7 +287,7 @@ const ubisys = {
await entity.write('manuSpecificUbisysDimmerSetup',
{'mode': utils.getFromLookup(phaseControl, phaseControlValues)}, manufacturerOptions.ubisysNull);
}
ubisys.tz.dimmer_setup.convertGet(entity, key, meta);
await ubisys.tz.dimmer_setup.convertGet(entity, key, meta);
},
convertGet: async (entity, key, meta) => {
await entity.read('manuSpecificUbisysDimmerSetup', ['capabilities'], manufacturerOptions.ubisysNull);
Expand All @@ -301,7 +301,7 @@ const ubisys = {
if (key === 'minimum_on_level') {
await entity.write('genLevelCtrl', {'ubisysMinimumOnLevel': value}, manufacturerOptions.ubisys);
}
ubisys.tz.dimmer_setup_genLevelCtrl.convertGet(entity, key, meta);
await ubisys.tz.dimmer_setup_genLevelCtrl.convertGet(entity, key, meta);
},
convertGet: async (entity, key, meta) => {
await entity.read('genLevelCtrl', ['ubisysMinimumOnLevel'], manufacturerOptions.ubisys);
Expand Down
6 changes: 3 additions & 3 deletions src/lib/ikea.ts
Original file line number Diff line number Diff line change
Expand Up @@ -45,11 +45,11 @@ const bulbOnEvent: OnEvent = async (type, data, device, options, state: KeyValue
// we only restore if true, to save unneeded network writes
const colorOptions = state.color_options as KeyValue;
if (colorOptions?.execute_if_off === true) {
device.endpoints[0].write('lightingColorCtrl', {'options': 1});
await device.endpoints[0].write('lightingColorCtrl', {'options': 1});
}
const levelConfig = state.level_config as KeyValue;
if (levelConfig?.execute_if_off === true) {
device.endpoints[0].write('genLevelCtrl', {'options': 1});
await device.endpoints[0].write('genLevelCtrl', {'options': 1});
}
if (levelConfig?.on_level !== undefined) {
const onLevelRaw = levelConfig.on_level;
Expand All @@ -62,7 +62,7 @@ const bulbOnEvent: OnEvent = async (type, data, device, options, state: KeyValue
if (onLevel > 255) onLevel = 254;
if (onLevel < 1) onLevel = 1;

device.endpoints[0].write('genLevelCtrl', {onLevel: onLevel});
await device.endpoints[0].write('genLevelCtrl', {onLevel: onLevel});
}
}
};
Expand Down
6 changes: 3 additions & 3 deletions src/lib/lumi.ts
Original file line number Diff line number Diff line change
Expand Up @@ -1501,7 +1501,7 @@ export const lumiModernExtend = {
const fromZigbee: Fz.Converter[] = [{
cluster: 'manuSpecificLumi',
type: ['attributeReport', 'readResponse'],
convert: (model, msg, publish, options, meta) => {
convert: async (model, msg, publish, options, meta) => {
// At least the Aqara TVOC sensor does not send a deviceAnnounce after comming back online.
// The reconfigureReportingsOnDeviceAnnounce modernExtend is not usable because of this,
// there is however an outage counter published in the 'special' buffer data reported
Expand All @@ -1520,12 +1520,12 @@ export const lumiModernExtend = {
for (const endpoint of meta.device.endpoints) {
// restore bindings
for (const b of endpoint.binds) {
endpoint.bind(b.cluster.name, b.target);
await endpoint.bind(b.cluster.name, b.target);
}

// restore reporting
for (const c of endpoint.configuredReportings) {
endpoint.configureReporting(c.cluster.name, [{
await endpoint.configureReporting(c.cluster.name, [{
attribute: c.attribute.name, minimumReportInterval: c.minimumReportInterval,
maximumReportInterval: c.maximumReportInterval, reportableChange: c.reportableChange,
}]);
Expand Down
94 changes: 53 additions & 41 deletions src/lib/ota/common.ts
Original file line number Diff line number Diff line change
Expand Up @@ -535,52 +535,64 @@ export async function updateToLatest(device: Zh.Device, onProgress: Ota.OnProgre

const answerNextImageRequest = () => {
waiters.nextImageRequest = endpoint.waitForCommand('genOta', 'queryNextImageRequest', null, maxTimeout);
waiters.nextImageRequest.promise.then((payload) => {
answerNextImageRequest();
sendQueryNextImageResponse(endpoint, image, payload.header.transactionSequenceNumber);
});
waiters.nextImageRequest.promise.then(
(payload) => {
answerNextImageRequest();
sendQueryNextImageResponse(endpoint, image, payload.header.transactionSequenceNumber);
},
() => {
cancelWaiters(waiters);
reject(new Error(`OTA: Failed queryNextImageRequest`));
}
);
};

// No need to timeout here, will already be done in answerNextImageBlockRequest
waiters.upgradeEndRequest = endpoint.waitForCommand('genOta', 'upgradeEndRequest', null, maxTimeout);
waiters.upgradeEndRequest.promise.then((data) => {
logger.debug(`Got upgrade end request for '${device.ieeeAddr}' (${device.modelID}): ${JSON.stringify(data.payload)}`, NS);
cancelWaiters(waiters);

if (data.payload.status === 0) {
const payload = {
manufacturerCode: image.header.manufacturerCode, imageType: image.header.imageType,
fileVersion: image.header.fileVersion, currentTime: 0, upgradeTime: 1,
};

endpoint.commandResponse('genOta', 'upgradeEndResponse', payload, null, data.header.transactionSequenceNumber).then(
() => {
logger.debug(`Update succeeded, waiting for device announce`, NS);
onProgress(100, null);

let timer: ReturnType<typeof setTimeout> = null;
const cb = () => {
logger.debug(`Got device announce or timed out, call resolve`, NS);
clearInterval(timer);
device.removeListener('deviceAnnounce', cb);
resolve(image.header.fileVersion);
};
timer = setTimeout(cb, 120 * 1000); // timeout after 2 minutes
device.once('deviceAnnounce', cb);
},
(e) => {
const message = `OTA: Upgrade end response failed (${e.message})`;
logger.debug(message, NS);
reject(new Error(message));
},
);
} else {
// @ts-expect-error
const error = `Update failed with reason: '${endRequestCodeLookup[data.payload.status]}'`;
logger.debug(error, NS);
reject(new Error(error));
waiters.upgradeEndRequest.promise.then(
(data) => {
logger.debug(`Got upgrade end request for '${device.ieeeAddr}' (${device.modelID}): ${JSON.stringify(data.payload)}`, NS);
cancelWaiters(waiters);

if (data.payload.status === 0) {
const payload = {
manufacturerCode: image.header.manufacturerCode, imageType: image.header.imageType,
fileVersion: image.header.fileVersion, currentTime: 0, upgradeTime: 1,
};

endpoint.commandResponse('genOta', 'upgradeEndResponse', payload, null, data.header.transactionSequenceNumber).then(
() => {
logger.debug(`Update succeeded, waiting for device announce`, NS);
onProgress(100, null);

let timer: ReturnType<typeof setTimeout> = null;
const cb = () => {
logger.debug(`Got device announce or timed out, call resolve`, NS);
clearInterval(timer);
device.removeListener('deviceAnnounce', cb);
resolve(image.header.fileVersion);
};
timer = setTimeout(cb, 120 * 1000); // timeout after 2 minutes
device.once('deviceAnnounce', cb);
},
(e) => {
const message = `OTA: Upgrade end response failed (${e.message})`;
logger.debug(message, NS);
reject(new Error(message));
},
);
} else {
// @ts-expect-error
const error = `Update failed with reason: '${endRequestCodeLookup[data.payload.status]}'`;
logger.debug(error, NS);
reject(new Error(error));
}
},
() => {
cancelWaiters(waiters);
reject(new Error(`OTA: Failed upgradeEndRequest`));
}
});
);

logger.debug(`Starting upgrade`, NS);
answerNextImageBlockOrPageRequest();
Expand Down
32 changes: 16 additions & 16 deletions tsconfig.json
Original file line number Diff line number Diff line change
@@ -1,21 +1,21 @@
{
"compilerOptions": {
"allowSyntheticDefaultImports": true,
"module": "commonjs",
"esModuleInterop": true,
"target": "ES2022",
"lib": ["ES2022"],
"noImplicitAny": true,
"noImplicitThis": true,
"moduleResolution": "node",
"sourceMap": true,
"declaration": true,
"declarationMap": true,
"outDir": ".",
"baseUrl": ".",
"resolveJsonModule": true,
"incremental": true
"allowSyntheticDefaultImports": true,
"module": "commonjs",
"esModuleInterop": true,
"target": "ES2022",
"lib": ["ES2022"],
"noImplicitAny": true,
"noImplicitThis": true,
"moduleResolution": "node",
"sourceMap": true,
"declaration": true,
"declarationMap": true,
"outDir": ".",
"baseUrl": ".",
"resolveJsonModule": true,
"incremental": true
},
"include": ["./src/"],
"exclude": []
}
}
Loading