UNPKG

@di-zed/yandex-smart-home

Version:

The Yandex Smart Home skills for the different device types.

221 lines (220 loc) 11 kB
"use strict"; var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) { function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); } return new (P || (P = Promise))(function (resolve, reject) { function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } } function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } } function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); } step((generator = generator.apply(thisArg, _arguments || [])).next()); }); }; var __importDefault = (this && this.__importDefault) || function (mod) { return (mod && mod.__esModule) ? mod : { "default": mod }; }; Object.defineProperty(exports, "__esModule", { value: true }); const configProvider_1 = __importDefault(require("../../providers/configProvider")); const mqttProvider_1 = __importDefault(require("../../providers/mqttProvider")); const deviceService_1 = __importDefault(require("../../services/deviceService")); const mqttService_1 = __importDefault(require("../../services/mqttService")); const topicService_1 = __importDefault(require("../../services/topicService")); const deviceHelper_1 = __importDefault(require("../../helpers/deviceHelper")); const restUserDevicesAfterEvent_1 = __importDefault(require("../../events/restUserDevicesAfterEvent")); const appError_1 = __importDefault(require("../../errors/appError")); /** * REST User Controller. */ class RestUserController { /** * POST Method. * Notification of unlinked accounts. * https://yandex.ru/dev/dialogs/smart-home/doc/reference/unlink.html?lang=en * * @param req * @param res * @returns Response */ unlink(req, res) { return __awaiter(this, void 0, void 0, function* () { console.log(res.__("The user's provider account (#%s) and Yandex account (#%s) were unlinked (the link between them was deleted by the user).", String(req.currentUser.id), String(req.currentClient.id))); const callbackRestUserUnlinkAction = configProvider_1.default.getConfigOption('callbackRestUserUnlinkAction'); if (typeof callbackRestUserUnlinkAction === 'function') { yield callbackRestUserUnlinkAction(req, res); } return res.status(200).json({ request_id: req.requestId, }); }); } /** * GET Method. * Information about user devices. * https://yandex.ru/dev/dialogs/smart-home/doc/reference/get-devices.html?lang=en * * @param req * @param res * @returns Response */ devices(req, res) { return __awaiter(this, void 0, void 0, function* () { var _a, _b; const devices = yield deviceService_1.default.getUserDevices(req.currentUser.id); const updatedDevices = []; const response = { request_id: req.requestId, payload: { user_id: String(req.currentUser.id), devices: [], }, }; for (const device of devices) { const updatedDevice = yield deviceService_1.default.updateUserDevice(req.currentUser, device); updatedDevices.push(structuredClone(updatedDevice)); (_a = updatedDevice.capabilities) === null || _a === void 0 ? void 0 : _a.forEach((capability) => { delete capability.state; }); (_b = updatedDevice.properties) === null || _b === void 0 ? void 0 : _b.forEach((property) => { delete property.state; }); response.payload.devices.push(updatedDevice); } restUserDevicesAfterEvent_1.default.execute(req.currentUser, updatedDevices).catch((err) => { console.log('ERROR! REST User Devices After Event.', err instanceof Error ? err.message : err); }); return res.status(200).json(response); }); } /** * POST Method. * Information about the states of user devices. * https://yandex.ru/dev/dialogs/smart-home/doc/reference/post-devices-query.html?lang=en * * @param req * @param res * @param next * @returns Response */ devicesQuery(req, res, next) { return __awaiter(this, void 0, void 0, function* () { if (typeof req.body.devices !== 'object') { return next(new appError_1.default(res.__('The parameter "%s" is required.', 'devices'), 400)); } const response = { request_id: req.requestId, payload: { devices: JSON.parse(JSON.stringify(req.body.devices)), }, }; for (const payloadDevice of response.payload.devices) { const userDevice = yield deviceService_1.default.getUserDeviceById(req.currentUser.id, payloadDevice.id); if (userDevice === undefined) { payloadDevice.error_code = 'DEVICE_UNREACHABLE'; // DEVICE_NOT_FOUND payloadDevice.error_message = res.__('The device "%s" can not be found.', payloadDevice.id); continue; } const updatedDevice = yield deviceService_1.default.updateUserDevice(req.currentUser, userDevice); if (updatedDevice.error_code) { payloadDevice.error_code = updatedDevice.error_code; payloadDevice.error_message = updatedDevice.error_message || res.__('Something went wrong!'); continue; } payloadDevice.capabilities = []; for (const capability of updatedDevice.capabilities || []) { payloadDevice.capabilities.push({ type: capability.type, state: capability.state, }); } payloadDevice.properties = []; for (const property of updatedDevice.properties || []) { payloadDevice.properties.push({ type: property.type, state: property.state, }); } } return res.status(200).json(response); }); } /** * POST Method. * Change device state. * https://yandex.ru/dev/dialogs/smart-home/doc/reference/post-action.html?lang=en * * @param req * @param res * @param next * @returns Response | void */ devicesAction(req, res, next) { return __awaiter(this, void 0, void 0, function* () { var _a; if (typeof req.body.payload !== 'object' || typeof req.body.payload.devices !== 'object') { return next(new appError_1.default(res.__('The parameter "%s" is required.', 'devices'), 400)); } const response = { request_id: req.requestId, payload: { devices: JSON.parse(JSON.stringify(req.body.payload.devices)), }, }; for (const payloadDevice of response.payload.devices) { const userDevice = yield deviceService_1.default.getUserDeviceById(req.currentUser.id, payloadDevice.id); if (userDevice === undefined) { continue; } const updatedDevice = yield deviceService_1.default.updateUserDevice(req.currentUser, userDevice); const payloadCapabilities = payloadDevice.capabilities || []; for (const payloadCapability of payloadCapabilities) { let actionResult = { status: 'ERROR', error_code: 'DEVICE_UNREACHABLE', // INVALID_ACTION error_message: res.__('Capability "%s" for the device "%s" can not be changed.', payloadCapability.type, userDevice.id), }; const capabilityState = payloadCapability.state; if (updatedDevice.error_code) { delete capabilityState.value; actionResult.error_message = updatedDevice.error_message || actionResult.error_message; capabilityState.action_result = actionResult; continue; } const topicNames = yield mqttService_1.default.getTopicNames({ user: req.currentUser, deviceId: userDevice.id, capabilityType: payloadCapability.type, capabilityStateInstance: capabilityState.instance, }); try { if (topicNames.commandTopic) { let value = capabilityState.value; let topicData = undefined; if (updatedDevice.type) { topicData = yield mqttService_1.default.getCommandTopicData(topicNames.commandTopic, updatedDevice.type, { capabilityType: payloadCapability.type, capabilityStateInstance: capabilityState.instance, }); } if (topicData !== undefined && topicData.capabilityType === 'devices.capabilities.range') { const rangeState = JSON.parse(JSON.stringify(capabilityState)); if (rangeState.relative) { const deviceCapability = deviceHelper_1.default.getDeviceCapability(updatedDevice, payloadCapability.type, capabilityState.instance); if (deviceCapability !== undefined) { value += ((_a = deviceCapability.state) === null || _a === void 0 ? void 0 : _a.value) || 0; } } } yield mqttProvider_1.default.publish(topicNames.commandTopic, yield topicService_1.default.convertAliceValueToMqttMessage(value, topicData)); actionResult = { status: 'DONE' }; } } catch (err) { console.log('ERROR! User Devices Action.', { err, actionResult }); } delete capabilityState.value; capabilityState.action_result = actionResult; } } return res.status(200).json(response); }); } } exports.default = RestUserController;