UNPKG

@maxsaber/homebridge-govee

Version:

Homebridge plugin to integrate Govee devices into HomeKit.

118 lines (99 loc) 3.04 kB
import { Buffer } from 'node:buffer' import fs from 'node:fs' import NodeRSA from 'node-rsa' import pem from 'pem' const base64ToHex = base64 => Buffer.from(base64, 'base64').toString('hex') const hexToBase64 = hex => Buffer.from(hex, 'hex').toString('base64') const cenToFar = temp => Math.round(((temp * 9) / 5 + 32) * 10) / 10 const farToCen = temp => Math.round(((temp - 32) * 5) / 9) function generateCodeFromHexValues(hexValues, returnAsHexBuffer = false) { const cmdSection = Buffer.from(hexValues.flat()) const padSection = Buffer.from(Array.from({ length: 19 - cmdSection.length }).fill(0)) const noXSection = Buffer.concat([cmdSection, padSection]) let checksum = 0 Object.values(noXSection).forEach((i) => { checksum ^= i }) const chkSection = Buffer.from([checksum]) const finalBuffer = Buffer.concat([noXSection, chkSection]) return returnAsHexBuffer ? finalBuffer : finalBuffer.toString('base64') } function generateRandomString(length) { const chars = 'abcdefghijklmnopqrstuvwxyz0123456789' let nonce = '' while (nonce.length < length) { nonce += chars.charAt(Math.floor(Math.random() * chars.length)) } return nonce } const getTwoItemPosition = (array, part) => array[part - 1] const hasProperty = (obj, prop) => Object.prototype.hasOwnProperty.call(obj, prop) const hexToDecimal = hex => Number.parseInt(hex, 16) const hexToTwoItems = hex => hex.match(/.{1,2}/g) const nearestHalf = num => Math.round(num * 2) / 2 function parseDeviceId(deviceId) { return deviceId .toString() .toUpperCase() .replace(/[^A-F0-9_:]+/g, '') } function parseError(err, hideStack = []) { let toReturn = err.message if (err?.stack?.length > 0 && !hideStack.includes(err.message)) { const stack = err.stack.split('\n') if (stack[1]) { toReturn += stack[1].replace(' ', '') } } return toReturn } async function pfxToCertAndKey(pfxPath, p12Password) { return new Promise((resolve, reject) => { pem.readPkcs12(fs.readFileSync(pfxPath), { p12Password }, (err, cert) => { if (err) { reject(err) } try { const key = new NodeRSA(cert.key) resolve({ cert: cert.cert, key: key.exportKey('pkcs8'), }) } catch (error) { reject(error) } }) }) } function sleep(ms) { return new Promise((resolve) => { setTimeout(resolve, ms) }) } function statusToActionCode(statusCode) { const choppedCode = `33${statusCode.slice(2, -2)}` const choppedArray = hexToTwoItems(choppedCode) const hexValues = choppedArray.map(byte => `0x${byte}`) const generatedCode = generateCodeFromHexValues(hexValues) return Buffer.from(generatedCode, 'base64').toString('hex') } export { base64ToHex, cenToFar, farToCen, generateCodeFromHexValues, generateRandomString, getTwoItemPosition, hasProperty, hexToBase64, hexToDecimal, hexToTwoItems, nearestHalf, parseDeviceId, parseError, pfxToCertAndKey, sleep, statusToActionCode, }