@di-zed/yandex-smart-home
Version:
The Yandex Smart Home skills for the different device types.
248 lines (247 loc) • 11.1 kB
JavaScript
;
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 mqttRepository_1 = __importDefault(require("../repositories/mqttRepository"));
const deviceService_1 = __importDefault(require("./deviceService"));
/**
* MQTT Service.
*/
class MqttService {
/**
* Get Topic Names.
*
* @param input
* @returns Promise<MqttOutputTopicNames>
*/
getTopicNames(input) {
return __awaiter(this, void 0, void 0, function* () {
const topicNames = {
stateTopic: '',
configTopic: '',
availableTopic: '',
commandTopic: '',
};
let deviceType = '';
(yield deviceService_1.default.getUserDevices(input.user.id)).forEach((userDevice) => {
if (userDevice.id === input.deviceId) {
deviceType = userDevice.type ? userDevice.type : '';
}
});
(yield mqttRepository_1.default.getConfigTopics()).forEach((topicData) => {
if (topicData.deviceType === deviceType) {
topicNames.stateTopic = this.handleTopicName(topicData.stateTopic, input.user, input.deviceId);
topicNames.configTopic = this.handleTopicName(topicData.configTopic, input.user, input.deviceId);
topicNames.availableTopic = this.handleTopicName(topicData.availableTopic, input.user, input.deviceId);
topicData.commandTopics.forEach((commandTopicData) => {
const typeState = {
capabilityType: input.capabilityType,
capabilityStateInstance: input.capabilityStateInstance,
propertyType: input.propertyType,
propertyStateInstance: input.propertyStateInstance,
};
if (this.matchTopicTypeState(commandTopicData, typeState)) {
topicNames.commandTopic = this.handleTopicName(commandTopicData.topic, input.user, input.deviceId);
}
});
}
});
return topicNames;
});
}
/**
* Get Data from the Topic.
*
* @param topic
* @param typeState
* @returns Promise<TopicData | undefined>
*/
getTopicData(topic, typeState) {
return __awaiter(this, void 0, void 0, function* () {
let result = undefined;
const configTopics = yield mqttRepository_1.default.getConfigTopics();
configTopics.every((item) => {
const stateTopic = this.parseTopicName(item.stateTopic, topic);
if (stateTopic !== undefined) {
result = Object.assign(Object.assign({}, stateTopic), { topicType: 'stateTopic' });
return false;
}
const configTopic = this.parseTopicName(item.configTopic, topic);
if (configTopic !== undefined) {
result = Object.assign(Object.assign({}, configTopic), { topicType: 'configTopic' });
return false;
}
const availableTopic = this.parseTopicName(item.availableTopic, topic);
if (availableTopic !== undefined) {
result = Object.assign(Object.assign({}, availableTopic), { topicType: 'availableTopic' });
return false;
}
let isCommandTopic = false;
item.commandTopics.every((itemCommandTopic) => {
const commandTopic = this.parseTopicName(itemCommandTopic.topic, topic);
if (commandTopic !== undefined) {
if (typeState && !this.matchTopicTypeState(itemCommandTopic, typeState)) {
return true;
}
result = Object.assign(Object.assign({}, commandTopic), { topicType: 'commandTopic' });
isCommandTopic = true;
return false;
}
return true;
});
return !isCommandTopic;
});
return result;
});
}
/**
* Get Data from the Command Topic.
*
* @param topic
* @param deviceType
* @param typeState
* @returns Promise<CommandTopicData | undefined>
*/
getCommandTopicData(topic, deviceType, typeState) {
return __awaiter(this, void 0, void 0, function* () {
let result = undefined;
const configTopics = yield mqttRepository_1.default.getConfigTopics();
configTopics.forEach((configTopic) => {
if (configTopic.deviceType === deviceType) {
configTopic.commandTopics.every((commandTopic) => {
var _a, _b, _c, _d;
const parsedTopicName = this.parseTopicName(commandTopic.topic, topic);
if (parsedTopicName !== undefined) {
if (typeState && !this.matchTopicTypeState(commandTopic, typeState)) {
return true;
}
result = {
deviceId: parsedTopicName.deviceId,
deviceType: configTopic.deviceType,
capabilityType: ((_a = commandTopic.capability) === null || _a === void 0 ? void 0 : _a.type) ? commandTopic.capability.type : '',
capabilityStateInstance: ((_b = commandTopic.capability) === null || _b === void 0 ? void 0 : _b.stateInstance) ? commandTopic.capability.stateInstance : '',
propertyType: ((_c = commandTopic.property) === null || _c === void 0 ? void 0 : _c.type) ? commandTopic.property.type : '',
propertyStateInstance: ((_d = commandTopic.property) === null || _d === void 0 ? void 0 : _d.stateInstance) ? commandTopic.property.stateInstance : '',
topicConfigKey: commandTopic.topicConfigKey || '',
topicStateKeys: commandTopic.topicStateKeys || [],
messageValueMapping: commandTopic.messageValueMapping || {},
userName: parsedTopicName.userName,
};
return false;
}
return true;
});
}
});
return result;
});
}
/**
* Check the Topic Type.
*
* @param topic
* @param expectedType
* @returns Promise<boolean>
*/
isTopicType(topic, expectedType) {
return __awaiter(this, void 0, void 0, function* () {
let result = false;
const configTopics = yield mqttRepository_1.default.getConfigTopics();
configTopics.every((item) => __awaiter(this, void 0, void 0, function* () {
if (expectedType === 'commandTopic') {
item.commandTopics.every((commandItem) => __awaiter(this, void 0, void 0, function* () {
const commandTopicName = this.parseTopicName(commandItem.topic, topic);
if (commandTopicName !== undefined) {
result = true;
return false;
}
return true;
}));
return !result;
}
else {
const topicName = this.parseTopicName(item[expectedType], topic);
if (topicName !== undefined) {
result = true;
return false;
}
}
return true;
}));
return result;
});
}
/**
* Get Parsed Information from the Topic Name.
*
* @param patternTopic
* @param topic
* @returns ParsedTopicName | undefined
*/
parseTopicName(patternTopic, topic) {
const pattern = patternTopic.replace('<user_name>', '([^/]*)').replace('<device_id>', '([^/]*)');
const re = new RegExp('^' + pattern + '$', 'g');
const match = re.exec(topic);
if (match) {
return {
userName: match[1],
deviceId: match[2],
};
}
return undefined;
}
/**
* Get Username for the MQTT Topic.
*
* @param user
* @returns string
*/
getTopicUserName(user) {
// return user.fullName ? user.fullName.replace(/\s/g, '_') : user.email;
return user.email;
}
/**
* Handle Topic Name.
*
* @param topicName
* @param user
* @param deviceId
* @returns string
*/
handleTopicName(topicName, user, deviceId) {
return topicName.replace('<user_name>', this.getTopicUserName(user)).replace('<device_id>', deviceId);
}
/**
* Match Type & State Instance.
*
* @param commandTopic
* @param typeState
* @returns boolean
*/
matchTopicTypeState(commandTopic, typeState) {
var _a, _b, _c, _d;
if (typeState.capabilityType && typeState.capabilityStateInstance) {
if (((_a = commandTopic.capability) === null || _a === void 0 ? void 0 : _a.type) === typeState.capabilityType &&
((_b = commandTopic.capability) === null || _b === void 0 ? void 0 : _b.stateInstance) === typeState.capabilityStateInstance) {
return true;
}
}
if (typeState.propertyType && typeState.propertyStateInstance) {
if (((_c = commandTopic.property) === null || _c === void 0 ? void 0 : _c.type) === typeState.propertyType && ((_d = commandTopic.property) === null || _d === void 0 ? void 0 : _d.stateInstance) === typeState.propertyStateInstance) {
return true;
}
}
return false;
}
}
exports.default = new MqttService();