UNPKG

matterbridge-roborock-vacuum-plugin

Version:
108 lines (92 loc) 3.68 kB
import axios, { AxiosInstance } from 'axios'; import crypto from 'node:crypto'; import { AnsiLogger, debugStringify } from 'matterbridge/logger'; import { ApiResponse } from '../Zmodel/apiResponse.js'; import { Home } from '../Zmodel/home.js'; import { UserData } from '../Zmodel/userData.js'; import { Scene } from '../Zmodel/scene.js'; export class RoborockIoTApi { logger: AnsiLogger; private readonly api: AxiosInstance; constructor(userdata: UserData, logger: AnsiLogger) { this.logger = logger; this.api = axios.create({ baseURL: userdata.rriot.r.a }); this.api.interceptors.request.use((config) => { try { const timestamp = Math.floor(Date.now() / 1000); const nonce = crypto .randomBytes(6) .toString('base64') .substring(0, 6) .replace(/[+/]/g, (m) => (m === '+' ? 'X' : 'Y')); const url = this.api ? new URL(this.api.getUri(config)).pathname : ''; const data = [userdata.rriot.u, userdata.rriot.s, nonce, timestamp, crypto.createHash('md5').update(url).digest('hex'), '', ''].join(':'); const hmac = crypto.createHmac('sha256', userdata.rriot.h).update(data).digest('base64'); config.headers['Authorization'] = `Hawk id="${userdata.rriot.u}", s="${userdata.rriot.s}", ts="${timestamp}", nonce="${nonce}", mac="${hmac}"`; } catch (error) { this.logger.error(`Failed to initialize RESTAPI ${error ? debugStringify(error) : 'undefined'}`); } return config; }); } public async getHome(homeId: number): Promise<Home | undefined> { const result = await this.api.get(`user/homes/${homeId}`); const apiResponse: ApiResponse<Home> = result.data; if (apiResponse.result) { return apiResponse.result; } else { this.logger.error('Failed to retrieve the home data'); return undefined; } } public async getHomev2(homeId: number): Promise<Home | undefined> { const result = await this.api.get('v2/user/homes/' + homeId); const apiResponse: ApiResponse<Home> = result.data; if (apiResponse.result) { return apiResponse.result; } else { this.logger.error('Failed to retrieve the home data'); return undefined; } } public async getHomev3(homeId: number): Promise<Home | undefined> { const result = await this.api.get('v3/user/homes/' + homeId); // can be v3 also const apiResponse: ApiResponse<Home> = result.data; if (apiResponse.result) { return apiResponse.result; } else { this.logger.error('Failed to retrieve the home data'); return undefined; } } public async getScenes(homeId: number): Promise<Scene[] | undefined> { const result = await this.api.get('user/scene/home/' + homeId); const apiResponse: ApiResponse<Scene[]> = result.data; if (apiResponse.result) { return apiResponse.result; } else { this.logger.error('Failed to retrieve scene'); return undefined; } } public async startScene(sceneId: number): Promise<unknown> { const result = await this.api.post(`user/scene/${sceneId}/execute`); const apiResponse: ApiResponse<unknown> = result.data; if (apiResponse.result) { return apiResponse.result; } else { this.logger.error('Failed to execute scene'); return undefined; } } public async getCustom(url: string): Promise<unknown> { const result = await this.api.get(url); const apiResponse: ApiResponse<unknown> = result.data; if (apiResponse.result) { return apiResponse.result; } else { this.logger.error('Failed to execute scene'); return undefined; } } }