matterbridge-roborock-vacuum-plugin
Version:
Matterbridge Roborock Vacuum Plugin
205 lines • 8.84 kB
JavaScript
import { randomInt } from 'node:crypto';
import { debugStringify } from 'matterbridge/logger';
import { CleanModeSetting } from '../../../behaviors/roborock.vacuum/core/CleanModeSetting.js';
import { CleanSequenceType } from '../../../behaviors/roborock.vacuum/enums/CleanSequenceType.js';
import { MapInfo } from '../../../core/application/models/index.js';
import { Q7CleanType, Q7ControlCode, Q7PropRequestCode, Q7RequestCode, Q7RequestMethod, } from '../../enums/Q7RequestCode.js';
import { B01VacuumModeResolver } from '../../helper/B01VacuumModeResolver.js';
import { RequestMessage } from '../../models/requestMessage.js';
export class Q7MessageDispatcher {
logger;
client;
dispatcherName = 'Q7MessageDispatcher';
lastB01Id;
// private readonly b01MapParser = new B01MapParser();
get messageId() {
let tmpMessageId = Date.now();
if (tmpMessageId <= this.lastB01Id) {
tmpMessageId = this.lastB01Id + 1;
}
this.lastB01Id = tmpMessageId;
return this.lastB01Id;
}
constructor(logger, client) {
this.logger = logger;
this.client = client;
this.lastB01Id = Date.now();
}
async getNetworkInfo(duid) {
// Q7 does not support getting network info, or maybe I just haven't found the right command yet.
return undefined;
}
async getSerialNumber(duid) {
return duid;
}
async getDeviceStatus(duid) {
const request = new RequestMessage({
dps: this.createDps(Q7RequestMethod.get_prop, {
property: [
Q7PropRequestCode.status,
Q7PropRequestCode.fault,
Q7PropRequestCode.sweep_type,
Q7PropRequestCode.mode,
Q7PropRequestCode.wind,
Q7PropRequestCode.water,
Q7PropRequestCode.clean_path_preference,
Q7PropRequestCode.quantity,
Q7PropRequestCode.cleaning_time,
Q7PropRequestCode.cleaning_area,
Q7PropRequestCode.clean_finish,
],
}),
});
await this.client.send(duid, request);
return undefined;
}
// #region Core Data Retrieval
async getHomeMap(duid) {
return {};
}
async getMapInfo(duid) {
const request = new RequestMessage({
messageId: this.messageId,
dps: this.createDps(Q7RequestMethod.get_map_list, {}),
});
const response = await this.client.get(duid, request);
this.logger.notice(`Get map info response for Q7 device ${duid}: ${response ? debugStringify(response) : 'no response'}`);
return new MapInfo({ max_multi_map: 0, max_bak_map: 0, multi_map_count: 0, map_info: [] });
}
async getRoomMap(duid, activeMap) {
const request = new RequestMessage({
messageId: this.messageId,
dps: this.createDps(Q7RequestMethod.get_room_mapping_backup_1, { map_id: activeMap, prefer_type: 1 }),
});
const response = (await this.client.get(duid, request)) ?? [];
this.logger.notice(`Get room map response for Q7 device ${duid}: ${response ? debugStringify(response) : 'no response'}`);
return response; // TODO: Implement proper room mapping retrieval for Q7
}
// public async getRoomMap(duid: string, activeMap: number): Promise<RawRoomMappingData> {
// const request = new RequestMessage({ messageId: this.messageId, dps: this.createDps(Q7RequestMethod.get_room_mapping, { force: 1, map_type: 0 }) });
// const response = await this.client.get<ResponseBody>(duid, request);
// if (!response) {
// this.logger.error(`Get room map for Q7 device: ${duid}: no response`);
// return [];
// }
// const responseData = response.get(Protocol.map_response) as Buffer;
// const parsed = this.b01MapParser.parseRooms(responseData);
// return parsed.rooms.map((x) => [x.roomId, x.roomName, x.roomTypeId ?? 0]);
// }
// #endregion Core Data Retrieval
// #region Cleaning Commands
async goHome(duid) {
const request = new RequestMessage({
messageId: this.messageId,
dps: this.createDps(Q7RequestMethod.app_charge, {}),
});
await this.client.send(duid, request);
}
async startCleaning(duid) {
await this.startRoomCleaning(duid, [], 1);
}
async startRoomCleaning(duid, roomIds, repeat) {
const request = new RequestMessage({
messageId: this.messageId,
dps: this.createDps(Q7RequestMethod.app_start_stop, {
clean_type: Q7CleanType.room_clean,
ctrl_value: Q7ControlCode.start,
room_ids: roomIds,
}),
});
await this.client.send(duid, request);
}
async pauseCleaning(duid) {
const request = new RequestMessage({
messageId: this.messageId,
dps: this.createDps(Q7RequestMethod.app_start_stop, {
clean_type: Q7CleanType.full_clean,
ctrl_value: Q7ControlCode.pause,
room_ids: [],
}),
});
await this.client.send(duid, request);
}
async resumeCleaning(duid) {
await this.startCleaning(duid);
}
async resumeRoomCleaning(duid) {
await this.startRoomCleaning(duid, [], 1);
}
async stopCleaning(duid) {
const request = new RequestMessage({
messageId: this.messageId,
dps: this.createDps(Q7RequestMethod.app_start_stop, {
clean_type: Q7CleanType.full_clean,
ctrl_value: Q7ControlCode.stop,
room_ids: [],
}),
});
await this.client.send(duid, request);
}
async findMyRobot(duid) {
const request = new RequestMessage({ messageId: this.messageId, dps: this.createDps(Q7RequestMethod.find_me, {}) });
await this.client.send(duid, request);
}
async sendCustomMessage(duid, def) {
const request = new RequestMessage({ ...def, messageId: this.messageId });
await this.client.send(duid, request);
}
async getCustomMessage(duid, def) {
const request = new RequestMessage({ ...def, messageId: this.messageId });
return this.client.get(duid, request);
}
async getCleanModeData(duid) {
return new CleanModeSetting(0, 0, 0, 0, CleanSequenceType.Persist); // TODO: Implement retrieval of clean mode data for Q7
}
async changeCleanMode(duid, setting) {
const { suctionPower, waterFlow, distance_off, mopRoute } = setting;
this.logger?.notice(`Change clean mode for ${duid} to suctionPower: ${suctionPower}, waterFlow: ${waterFlow}, mopRoute: ${mopRoute}, distance_off: ${distance_off}`);
await this.setCleanMode(duid, suctionPower, waterFlow);
if (suctionPower !== 0) {
await this.setVacuumMode(duid, suctionPower);
}
if (waterFlow !== 0) {
await this.setMopMode(duid, waterFlow);
}
}
// #endregion Cleaning Commands
// #region Private Helpers
createDps(method, params) {
const messageId = randomInt(100000000000, 999999999999).toString();
return { [Q7RequestCode.query]: { msgId: messageId, method: method, params: params } };
}
async setCleanMode(duid, suctionPower, waterFlow) {
const request = new RequestMessage({
messageId: this.messageId,
dps: this.createDps(Q7RequestMethod.set_prop, {
'mode': B01VacuumModeResolver.resolveQ7CleanMode(suctionPower, waterFlow),
}),
});
await this.client.send(duid, request);
}
async setVacuumMode(duid, suctionPower) {
const request = new RequestMessage({
messageId: this.messageId,
dps: this.createDps(Q7RequestMethod.set_prop, { 'wind': B01VacuumModeResolver.resolveVacuumMode(suctionPower) }),
});
await this.client.send(duid, request);
}
async setMopMode(duid, waterFlow) {
const request = new RequestMessage({
messageId: this.messageId,
dps: this.createDps(Q7RequestMethod.set_prop, { 'water': B01VacuumModeResolver.resolveMopMode(waterFlow) }),
});
await this.client.send(duid, request);
}
async setCleanRoute(duid, mopRoute) {
const request = new RequestMessage({
messageId: this.messageId,
dps: this.createDps(Q7RequestMethod.set_prop, {
'clean_path_preference': B01VacuumModeResolver.resolveCleanRoute(mopRoute),
}),
});
await this.client.send(duid, request);
}
}
//# sourceMappingURL=Q7MessageDispatcher.js.map