使用
拦截器为实验性功能,非内置的拦截器后续 API 可能会存在破坏性变更,使用前须注意
SDM 的拦截器(interceptors)受 NextJS、Axios、Redux 等框架或类库启发,使得以下功能可通过拦截器实现:
- 在请求执行前或执行后增加额外的功能逻辑
- 修改数据返回值
- 在特定场景下完全重写功能逻辑
起步
根据 SDM 内部的方法或事件类型,我们将拦截器分为了 request interceptor 和 response interceptor,下方我们提供了一个最简单的自定义配置拦截器的示例以供参考。
// src/devices/index.ts
import { SmartDeviceModel, logger } from '@ray-js/panel-sdk';
export const devices = {} as SmartDevices;
const options = {
interceptors: {
request: {
publishDps: [logger],
},
response: {
onDpDataChange: [logger],
},
},
};
SmartDeviceModel.init<SmartDeviceSchema>(options).then((device) => {
/**
* 此处建议以智能设备的名称作为键名赋值
*/
devices.robot = device;
});
内置拦截器
logger
描述
日志 console 打印拦截器,类似 redux-logger,当前所有 request 方法及 response 事件均默认配置了 logger 拦截器,如需取消或自定义可通过 SmartDeviceModel.init 方法 的 options.interceptors
进行自定义,详见 logger。
示例
dp-kit
描述
轻量的设备面板 DP 功能点处理工具库,内置支持解析 & 反解析复杂类型 DP 功能点,下发节流、防抖、过滤等功能,详见 dp-kit。
示例
👉 立即免费领取开发资源,体验涂鸦 MiniApp 小程序开发。
自定义拦截器
类型定义
当前拦截器共分为以下几种类型,如需自定义可根据需要自行选择 TS 定义进行约束实现
Interceptor
: 通用拦截器,可支持所有类型PublishDpsInterceptor
: 下发 DP 功能点专用拦截器OnDpDataChangeInterceptor
: 智能设备 DP 功能点变更事件专用拦截器OnDeviceOnlineStatusUpdateInterceptor
: 智能设备上下线状态变更事件专用拦截器OnDeviceInfoUpdatedInterceptor
: 智能设备信息变更事件专用拦截器OnNetworkStatusChangeInterceptor
: 网络状态变化事件专用拦截器OnBluetoothAdapterStateChangeInterceptor
: 蓝牙适配器状态变化事件专用拦截器
import {
kit,
SmartDeviceModel,
ReadonlyDpSchemaList,
DpDataChangeParams,
DeviceOnlineStatusUpdateParams,
DeviceInfoUpdatedParams,
NetworkStatusChangeParams,
BluetoothAdapterStatusChangeParams,
logger
} from '@ray-js/panel-sdk';
declare type Context<S extends ReadonlyDpSchemaList> = {
type: string;
log: typeof log;
instance: SmartDeviceModel<S>;
};
export declare type Interceptor<
S extends ReadonlyDpSchemaList = any,
P extends any = any,
NP extends any = P,
> = (context: Context<S>) => (next: (params: P) => any) => (data: NP) => any;
export declare type PublishDpsInterceptor<
S extends ReadonlyDpSchemaList = any,
P extends any[] = Parameters<typeof kit.publishDps>,
> = (
context: Context<S>,
) => (
next: (...params: P) => any,
) => (...params: Parameters<typeof kit.publishDps>) => any;
export declare type OnDpDataChangeInterceptor<
S extends ReadonlyDpSchemaList = any,
P = DpDataChangeParams,
> = Interceptor<S, P, DpDataChangeParams>;
export declare type OnDeviceOnlineStatusUpdateInterceptor<
S extends ReadonlyDpSchemaList = any,
P = DeviceOnlineStatusUpdateParams,
> = Interceptor<S, P, DeviceOnlineStatusUpdateParams>;
export declare type OnDeviceInfoUpdatedInterceptor<
S extends ReadonlyDpSchemaList = any,
P = DeviceInfoUpdatedParams,
> = Interceptor<S, P, DeviceInfoUpdatedParams>;
export declare type OnNetworkStatusChangeInterceptor<
S extends ReadonlyDpSchemaList = any,
P = NetworkStatusChangeParams,
> = Interceptor<S, P, NetworkStatusChangeParams>;
export declare type OnBluetoothAdapterStateChangeInterceptor<
S extends ReadonlyDpSchemaList = any,
P = BluetoothAdapterStatusChangeParams,
> = Interceptor<S, P, BluetoothAdapterStatusChangeParams>;
执行上下文
参数 | 数据类型 | 说明 |
---|---|---|
type | string | 当前拦截器拦截的请求方法或回调事件,如 publishDps 、onDpDataChange 等 |
log | typeof log | log 对象,支持 log.info、log.warn、log.fatal 等,log 的最后一个入参可自定义带上当前拦截器的名称 |
instance | SmartDeviceMode<S> | 智能设备实例对象,详见智能设备模型 API |
import SmartDeviceModel from '../SmartDeviceModel';
import { ReadonlyDpSchemaList } from './SmartDeviceModel';
import { log } from '../utils/logger';
declare type Context<S extends ReadonlyDpSchemaList> = {
type: string;
log: typeof log;
instance: SmartDeviceModel<S>;
};
自定义拦截器示例
第一个回调参数
ctx
为当前拦截器的执行上下文
第二个回调参数next
为下一个拦截器方法
第三个回调参数data
为当前 request 请求方法的入参或 response 事件的回调数据
1. 在请求执行前或执行后增加额外的功能逻辑
import { kit, PublishDpsInterceptor } from '@ray-js/panel-sdk';
type PublishDpsParams = Parameters<typeof kit.publishDps>;
type ExtendPublishDpsParams = [
PublishDpsParams[0],
PublishDpsParams[1] & { a: number },
];
export const append: PublishDpsInterceptor<
SmartDeviceSchema,
ExtendPublishDpsParams
> = (ctx) => (next) => (data, options) => {
ctx.log.info('=== 下发 DP 前,插入其他 DP 点', data, options, 'append');
const newDpState = { ...data, power_go: !ctx.instance.getDpState().power_go };
const result = next(newDpState, { ...options, mode: 0, a: 1 });
return result;
};
2. 修改数据返回值
import { DpState, DpValue, OnDpDataChangeInterceptor } from '@ray-js/panel-sdk';
export const Dps2DpState: OnDpDataChangeInterceptor<
SmartDeviceSchema,
DpState
> = (ctx) => (next) => (data) => {
ctx.log.info('=== DpsMap to DpStateMap');
const devInfo = ctx.instance.getDevInfo();
const dpState = {} as DpState;
Object.keys(data.dps).forEach((dpId) => {
dpState[devInfo.idCodes[dpId]] = data.dps[dpId] as DpValue;
});
return next(dpState);
};
3. 在特定场景下完全重写功能逻辑
import { Interceptor } from '@ray-js/panel-sdk';
export const skip: Interceptor<SmartDeviceSchema> =
(ctx) => (next) => (data) => {
ctx.log.info('=== 在某某场景下,忽略请求或接受事件');
const someCondition = true;
if (someCondition) {
return null;
}
return next(data);
};
👉 立即免费领取开发资源,体验涂鸦 MiniApp 小程序开发。