/** * 获取关联设备的结构化功能点状态,需配合 dp-kit 拦截器使用 * @public * @since @ray-js/panel-sdk 1.16.0 * @param selector - 选择器函数,入参为所有关联设备的结构化 props 集合。 * key 为设备标识,value 为该设备经 dp-kit 解析后的结构化功能点数据 * @typeOverride selector (structuredDevicesProps: { [key: string]: Record }) => any; * @param equalityFn - 自定义比较函数,返回 true 则不触发重渲染,默认 shallow equal * @typeOverride equalityFn (prev: any, next: any) => boolean; * @returns 匹配选择器的结构化功能点值 * @typeOverride returns any * @remarks * 使用前需同时满足: * 1. 挂载 SdmDevicesProvider 并配置关联设备映射 * 2. 各设备初始化时已配置 dp-kit 拦截器(createDpKit) * 性能优化(最佳实践): * 1. 强烈建议始终将 selector 的颗粒度精确到具体的功能点,例如 `useStructuredDevicesProps(props => props.main?.colour_data)`,避免全量订阅导致无关设备或无关功能点改变时引发无效的重渲染。 * 2. 如果 selector 必须返回包含多个字段的对象,由于默认使用浅比较(shallow equal),只要提取的值未发生改变就不会触发重渲染。必要时也可传入 `equalityFn` 进行深度定制。 * @example 仅订阅单台设备的特定状态 * ```tsx * import { useStructuredDevicesProps } from '@ray-js/panel-sdk'; * * export default function MainDeviceColour() { * // 精确选取 main 设备的 colour_data,仅在它改变时才重渲染 * const colourData = useStructuredDevicesProps( * props => props.main?.colour_data * ); * return H: {colourData?.h}, S: {colourData?.s}, V: {colourData?.v}; * } * ``` * @example 配置 dp-kit 并使用结构化状态(完整接入链路) * ```tsx * // ---- 1. Parser:自定义 Transformer 示例(以 colour_data 为例) ---- * type TColorData = { hue: number; saturation: number; value: number }; * class ColourTransformer implements Transformer { * defaultValue = { hue: 10, saturation: 1000, value: 1000 }; * uuid = 'colour_data'; * parser(value: string): TColorData { * if (value.length !== 12) return this.defaultValue; * const step = generateDpStrStep(value); * return { hue: step(4).value, saturation: step(4).value, value: step(4).value }; * } * formatter(data: TColorData) { * const { hue, saturation, value } = data; * return `${decimalToHex(hue, 4)}${decimalToHex(saturation, 4)}${decimalToHex(value, 4)}`; * } * } * * // ---- 2. 配置 dpKit 并注入 SmartDevicesManager ---- * import { createDpKit, SmartDevicesManager, useStructuredDevicesProps } from '@ray-js/panel-sdk'; * import { lampSchemaMap } from '@/devices/schema'; * * const dpKit = createDpKit({ * protocols: { * [lampSchemaMap.colour_data.code]: new ColourTransformer(), * } * }); * const deviceManager = new SmartDevicesManager(); * * // batchAdd 时注入 dp-kit 拦截器 * deviceManager.batchAdd([ * { key: 'lamp1', deviceId: 'xxx_device_id_1', interceptors: dpKit.interceptors }, * { key: 'lamp2', deviceId: 'xxx_device_id_2', interceptors: dpKit.interceptors }, * ]); * * // ---- 3. 页面组件消费结构化数据 ---- * export default function ColourDataList() { * // 推荐:精确选用需要的状态,例如 p => p.lamp1?.colour_data * const structured = useStructuredDevicesProps(p => p); * * return ( * * {Object.keys(structured ?? {}).map(key => ( * * {key} colour_data: hue={structured[key]?.colour_data?.hue} * * ))} * * ); * } * ``` * @example 自定义 rerender * ```tsx * // useStructuredDevicesProps 内部已针对 selector 返回值做 shallow equal 浅比较,无特殊场景时无需传入 equalityFn。 * import { useStructuredDevicesProps } from '@ray-js/panel-sdk'; * * export default function WorkModeMap() { * const workModeMap = useStructuredDevicesProps( * p => { * const map: Record = {}; * Object.keys(p ?? {}).forEach(k => { map[k] = p[k]?.work_mode; }); * return map; * }, * (prev, next) => JSON.stringify(prev) === JSON.stringify(next) * ); * * return ( * * {Object.keys(workModeMap).map(k => ( * {k}: {workModeMap[k]} * ))} * * ); * } * ``` */ export declare function useStructuredDevicesProps(selector: (structuredDevicesProps: Record) => V, equalityFn?: (a: V, b: V) => boolean): V;