@realsee/vr-signals
v2.0.0
Published
vr 信号器
Keywords
Readme
@realsee/vr-signals
VR 信号通信库,用于在 VR 应用和父窗口之间建立双向通信。
特性
- 🔄 自动握手和连接管理
- 📡 双向消息通信
- 🚀 智能重试策略(指数退避 + 抖动)
- 🔌 自动重连机制
- 📝 详细的日志记录
- 🎯 类型安全的 API
- 🛡️ 企业级安全特性
- ✨ 开箱即用的核心类型 - 无需传入泛型参数
🆕 核心类型支持
SDK 现在提供了核心类型支持,包含了必要的 Action 和 Event。这意味着你可以直接使用 SDK,无需定义自己的类型映射:
🚀 动态 Action 注册系统
SDK 现在支持动态注册和移除 Actions,无需在初始化时传入完整的 actionMap:
Remote 端动态管理
import { RealseeVRSignalsRemote } from '@realsee/vr-signals'
const remote = new RealseeVRSignalsRemote({
logLevel: 'INFO'
})
// 动态注册单个 Action
remote.registerAction('setState', async (data) => {
console.log('setState 被调用:', data)
// data 包含 mode, longitude, latitude, fov 等 Five SDK 状态
return { success: true, message: '状态已设置' }
})
// 批量注册 Actions
remote.registerActions({
'updateCamera': async (data) => {
console.log('updateCamera 被调用:', data)
// data.state 包含 longitude, latitude, fov, offset 等 Five SDK 相机状态
return { success: true, message: '相机已更新' }
},
'tag.changeData': async (data) => {
console.log('tag.changeData 被调用:', data)
return { success: true, message: '标签已更新' }
}
})
// 移除 Action
remote.unregisterAction('tag.changeData')
// 监听 Action 变化
remote.onActionChange((event) => {
console.log('Action 变化:', event)
})
// 获取统计信息
const stats = remote.getActionStats()
console.log('已注册 Actions:', stats.registered)Client 端智能检查
import { RealseeVRSignalsClient } from '@realsee/vr-signals'
const client = new RealseeVRSignalsClient({
vrLink: 'http://localhost:3000/vr-app',
element: iframeElement
})
// 检查 Action 是否可用
if (client.isActionAvailable('setState')) {
// 安全调用
const result = await client.send('setState', {
mode: 'panorama',
longitude: 0,
latitude: 0,
fov: 90
})
console.log('结果:', result)
} else {
console.log('setState 不可用')
}
// 监听 Action 可用性变化
client.onActionAvailabilityChange('setState', (available) => {
if (available) {
console.log('setState 现在可用了!')
} else {
console.log('setState 不可用了')
}
})
// 等待特定 Action 可用
try {
await client.waitForAction('setState', 5000)
console.log('setState 可用,开始调用...')
await client.send('setState', {
mode: 'panorama',
longitude: 0,
latitude: 0,
fov: 90
})
} catch (error) {
console.log('等待超时:', error.message)
}
// 获取可用 Actions 列表
const availableActions = client.getAvailableActions()
console.log('可用的 Actions:', availableActions)无需泛型的简单用法
import { RealseeVRSignalsClient, RealseeVRSignalsRemote } from '@realsee/vr-signals'
// 客户端 - 无需泛型
const client = new RealseeVRSignalsClient({
vrLink: 'http://localhost:3000/vr-app',
element: document.getElementById('vr-container') as HTMLDivElement,
logLevel: 'INFO'
})
// 服务端 - 无需泛型
const remote = new RealseeVRSignalsRemote({
logLevel: 'INFO',
actionMap: {
setState(data) {
console.log('State update:', data)
// data 包含 mode, longitude, latitude, fov 等 Five SDK 状态
return { success: true }
},
updateCamera({ state }) {
console.log('Camera update:', state)
// state 包含 longitude, latitude, fov, offset 等 Five SDK 相机状态
return { success: true }
}
}
})
// 直接使用预定义的事件和动作
client.on('stateSynced', (data) => {
console.log('State synced:', data)
// data 包含 mode, longitude, latitude, fov 等 Five SDK 状态
})
client.on('cameraUpdate', (data) => {
console.log('Camera updated:', data.state)
// data.state 包含 longitude, latitude, fov, offset 等 Five SDK 相机状态
})
client.on('tag.click', (data) => {
console.log('Tag clicked:', data.data.title)
})
client.on('monitor.open', (data) => {
console.log('Monitor opened:', data.data.name)
})
client.on('monitor.close', (data) => {
console.log('Monitor closed:', data.data.name)
})
client.on('overlay.visible', (data) => {
console.log('Overlay visibility:', data.visible)
})
// 发送动作
client.send('setState', {
mode: 'panorama',
longitude: 0,
latitude: 0,
fov: 90
})
client.send('updateCamera', {
state: {
longitude: 0,
latitude: 0,
fov: 90,
offset: { x: 0, y: 0, z: 0 }
}
})
// 发送事件
remote.sendEvent('stateSynced', { mode: 'editing', view: 'panorama' })
remote.sendEvent('cameraUpdate', {
state: {
longitude: 0,
latitude: 0,
fov: 90,
offset: { x: 0, y: 0, z: 0 }
},
userAction: false
})已实现的核心功能
SDK 包含了以下核心功能:
🎮 Actions(动作)
- 状态管理:
setState- 设置应用状态 - 相机控制:
updateCamera- 更新相机状态
📡 Events(事件)
- 状态同步:
stateSynced- 状态同步事件 - 相机事件:
cameraUpdate- 相机更新事件 - 标签事件:
tag.click- 标签点击事件 - 监控事件:
monitor.open,monitor.close- 监控开启/关闭事件 - 覆盖层事件:
overlay.visible- 覆盖层显示/隐藏事件
高级用法 - 扩展核心类型
如果你需要添加自定义功能,仍然可以使用泛型:
import { RealseeVRSignalsClient, DefaultActionMap, DefaultEventMap } from '@realsee/vr-signals'
// 扩展核心类型
interface CustomActionMap extends DefaultActionMap {
'custom.action': (data: { message: string }) => Promise<{ result: string }>
}
interface CustomEventMap extends DefaultEventMap {
'custom.event': (data: { message: string }) => void
}
// 使用扩展的类型
const customClient = new RealseeVRSignalsClient<CustomActionMap, CustomEventMap>({
vrLink: 'http://localhost:3000/vr-app',
element: document.getElementById('vr-container') as HTMLDivElement
})
// 使用核心功能
customClient.on('cameraUpdate', (data) => {
console.log('Camera updated:', data.state)
})
// 使用自定义功能
customClient.on('custom.event', (data) => {
console.log('Custom event:', data.message)
})
customClient.send('custom.action', { message: 'Hello' })安全特性
🚨 安全风险提醒
重要:为了兼容 1.x 版本,2.x 版本默认禁用了严格的安全模式:
- 默认允许所有域名的跨域通信
- 这提供了与 1.x 版本的最大兼容性
- 在生产环境中建议启用安全模式以提高安全性
🛡️ 内置安全机制
- Origin 验证:验证消息来源域名
- 消息结构验证:验证消息格式和必需字段
- 时间戳验证:防止重放攻击
- 消息签名:可选的数字签名验证
- 严格模式:限制只允许可信域名
- 🆕 自适应策略:智能识别 iframe 和父级窗口的域名关系
🔄 自适应安全策略
自适应策略是 vr-signals 的核心安全特性,能够智能识别和适应不同的域名关系:
自动识别的场景
- 同源环境:
http://localhost:3000↔http://localhost:3000✅ - 同域名不同端口:
http://localhost:3000↔http://localhost:1234✅ - 同域名不同协议:
http://example.com↔https://example.com✅ - 子域名关系:
https://app.example.com↔https://vr.example.com✅ - 恶意域名:
https://app.example.com↔https://malicious-site.com❌
自适应策略优势
- 🎯 零配置:开发环境无需手动配置域名白名单
- 🔧 自动适应:自动处理 localhost 不同端口的情况
- 🌐 智能识别:自动识别同域名下的子域名关系
- 🛡️ 安全可靠:完全避免使用危险的通配符
- ⚡ 开箱即用:减少配置错误和安全漏洞
🔒 安全配置示例
完全自适应模式(推荐用于所有环境)
const adaptiveClient = new RealseeVRSignalsClient({
vrLink: 'http://localhost:1234/vr-app',
element: iframeElement,
// 安全配置:完全自适应
security: {
strictMode: true, // 启用严格模式
validateOrigin: true, // 验证消息来源
validateSignature: false, // 开发环境不启用签名验证
signatureKey: undefined
}
})生产环境配置(自适应 + 签名验证)
const productionClient = new RealseeVRSignalsClient({
vrLink: 'https://vr-app.example.com',
element: iframeElement,
// 安全配置:自适应 + 签名验证
security: {
strictMode: true,
validateOrigin: true,
validateSignature: true, // 启用消息签名验证
signatureKey: 'your-secret-key' // 签名密钥
}
})安装
npm install @realsee/vr-signals基本用法
🆕 客户端(父窗口)- 使用核心类型
import { RealseeVRSignalsClient } from '@realsee/vr-signals'
// 无需泛型参数,直接使用核心类型
const client = new RealseeVRSignalsClient({
vrLink: 'http://localhost:3000/vr-app',
element: iframeElement,
logLevel: 'INFO',
// 自定义握手重试策略
handshakeRetryStrategy: {
baseDelay: 500, // 基础延迟 500ms
maxDelay: 5000, // 最大延迟 5s
jitterRange: [0.85, 1.15] // 抖动因子范围
},
// 自定义重连策略
reconnectStrategy: {
baseDelay: 2000, // 基础重连延迟 2s
maxDelay: 30000, // 最大重连延迟 30s
jitterRange: [0.8, 1.2] // 抖动因子范围
},
shakehandRetryTimes: 10, // 握手重试次数
enableAutoReconnect: true, // 启用自动重连
maxReconnectAttempts: 5 // 最大重连次数
})
// 监听连接状态
client.onConnectionStatusChange((status) => {
console.log('Connection status:', status)
})
// 等待连接就绪
client.onReady(() => {
console.log('Client is ready!')
})
// 发送核心动作(无需类型声明)
client.send('setState', {
mode: 'panorama',
longitude: 0,
latitude: 0,
fov: 90
})
client.send('updateCamera', {
state: {
longitude: 0,
latitude: 0,
fov: 90,
offset: { x: 0, y: 0, z: 0 }
}
})
// 监听核心事件(无需类型声明)
client.on('stateSynced', (data) => {
console.log('State synced:', data)
// data 包含 mode, longitude, latitude, fov 等 Five SDK 状态
})
client.on('cameraUpdate', (data) => {
console.log('Camera updated:', data.state)
// data.state 包含 longitude, latitude, fov, offset 等 Five SDK 相机状态
})
client.on('tag.click', (data) => {
console.log('Tag clicked:', data.data.title)
})
client.on('monitor.open', (data) => {
console.log('Monitor opened:', data.data.name)
})
client.on('monitor.close', (data) => {
console.log('Monitor closed:', data.data.name)
})
client.on('overlay.visible', (data) => {
console.log('Overlay visibility:', data.visible)
})🆕 服务端(VR 应用)- 使用核心类型
import { RealseeVRSignalsRemote } from '@realsee/vr-signals'
// 无需泛型参数,直接使用核心类型
const remote = new RealseeVRSignalsRemote({
logLevel: 'INFO',
actionMap: {
// 处理来自父窗口的核心请求
setState(data) {
console.log('Received state update request:', data)
// data 包含 mode, longitude, latitude, fov 等 Five SDK 状态
// 执行状态更新逻辑
return { success: true }
},
updateCamera({ state }) {
console.log('Received camera update request:', state)
// state 包含 longitude, latitude, fov, offset 等 Five SDK 相机状态
// 执行相机更新逻辑
return { success: true }
}
}
})
// 等待连接就绪
remote.onReady(() => {
console.log('Remote is ready!')
})
// 发送核心事件到父窗口(无需类型声明)
remote.sendEvent('stateSynced', {
mode: 'panorama',
longitude: 0,
latitude: 0,
fov: 90
})
remote.sendEvent('cameraUpdate', {
state: {
longitude: 0,
latitude: 0,
fov: 90,
offset: { x: 0, y: 0, z: 0 }
},
userAction: false
})
remote.sendEvent('tag.click', {
id: 'tag1',
data: {
id: 'tag1',
title: '标签标题',
description: '标签描述',
type: 'info',
extraData: '额外数据'
}
})
remote.sendEvent('monitor.open', {
id: 'monitor1',
data: {
id: 'monitor1',
name: '监控1号',
videoSrc: 'http://example.com/video1.mp4',
type: 'camera',
extraData: '监控数据'
}
})
remote.sendEvent('monitor.close', {
id: 'monitor1',
data: {
id: 'monitor1',
name: '监控1号',
videoSrc: 'http://example.com/video1.mp4',
type: 'camera',
extraData: '监控数据'
}
})
remote.sendEvent('overlay.visible', { visible: true })🔧 传统用法 - 自定义类型(仍然支持)
如果你需要自定义类型,仍然可以使用泛型:
// 定义自定义类型
type CustomActionMap = {
'custom.method': (data: { message: string }) => Promise<{ result: string }>
}
type CustomEventMap = {
'custom.event': (data: { message: string }) => void
}
// 使用自定义类型
const customClient = new RealseeVRSignalsClient<CustomActionMap, CustomEventMap>({
vrLink: 'http://localhost:3000/vr-app',
element: iframeElement
})
const customRemote = new RealseeVRSignalsRemote<CustomActionMap, CustomEventMap>({
logLevel: 'INFO',
actionMap: {
'custom.method': async (data) => {
return { result: `Processed: ${data.message}` }
}
}
})重试策略配置
握手重试策略
握手重试使用指数退避策略,避免频繁重试:
handshakeRetryStrategy: {
baseDelay: 500, // 基础延迟时间(毫秒)
maxDelay: 5000, // 最大延迟时间(毫秒)
jitterRange: [0.85, 1.15] // 抖动因子范围
}延迟计算示例:
- 第1次重试:500ms × 2⁰ = 500ms
- 第2次重试:500ms × 2¹ = 1000ms
- 第3次重试:500ms × 2² = 2000ms
- 第4次重试:500ms × 2³ = 4000ms
- 第5次重试:500ms × 2⁴ = 5000ms(达到最大值)
重连策略
重连也使用指数退避策略:
reconnectStrategy: {
baseDelay: 2000, // 基础重连延迟时间(毫秒)
maxDelay: 30000, // 最大重连延迟时间(毫秒)
jitterRange: [0.8, 1.2] // 抖动因子范围
}延迟计算示例:
- 第1次重连:2000ms × 2⁰ = 2000ms
- 第2次重连:2000ms × 2¹ = 4000ms
- 第3次重连:2000ms × 2² = 8000ms
- 第4次重连:2000ms × 2³ = 16000ms
- 第5次重连:2000ms × 2⁴ = 30000ms(达到最大值)
抖动策略
抖动策略用于避免多个客户端同时重试,减少网络拥塞:
- 握手抖动:0.85-1.15 倍随机因子
- 重连抖动:0.8-1.2 倍随机因子
安全最佳实践
🚨 生产环境安全要求
- 必须启用严格模式:
strictMode: true - 必须验证消息来源:
validateOrigin: true - 建议启用消息签名:
validateSignature: true - 无需配置域名白名单:系统自动适应
🔧 开发环境配置
security: {
strictMode: true,
validateOrigin: true,
validateSignature: false // 开发环境可选
}🧪 测试环境配置
security: {
strictMode: true, // 测试环境建议启用
validateOrigin: true, // 建议验证来源
validateSignature: false // 测试环境可选
}🌟 自适应策略优势
- 🎯 零配置:无需手动配置域名白名单
- 🔧 自动适应:自动处理 localhost 不同端口
- 🌐 智能识别:自动识别同域名下的子域名关系
- 🛡️ 安全可靠:完全避免使用危险的通配符
- ⚡ 开箱即用:减少配置错误和安全漏洞
API 参考
RealseeVRSignalsClient
构造函数选项
| 选项 | 类型 | 默认值 | 描述 |
|------|------|--------|------|
| vrLink | string | - | VR 应用链接(可选) |
| element | HTMLElement | - | iframe 或容器元素(可选) |
| logLevel | LogLevel | 'NONE' | 日志级别 |
| handshakeRetryStrategy | object | 见下方 | 握手重试策略 |
| reconnectStrategy | object | 见下方 | 重连策略 |
| shakehandRetryTimes | number | 10 | 握手重试次数 |
| enableAutoReconnect | boolean | true | 是否启用自动重连 |
| maxReconnectAttempts | number | 5 | 最大重连次数 |
| security | object | 见下方 | 安全配置 |
握手重试策略选项
| 选项 | 类型 | 默认值 | 描述 |
|------|------|--------|------|
| baseDelay | number | 500 | 基础延迟时间(毫秒) |
| maxDelay | number | 5000 | 最大延迟时间(毫秒) |
| jitterRange | [number, number] | [0.85, 1.15] | 抖动因子范围 |
重连策略选项
| 选项 | 类型 | 默认值 | 描述 |
|------|------|--------|------|
| baseDelay | number | 2000 | 基础重连延迟时间(毫秒) |
| maxDelay | number | 30000 | 最大重连延迟时间(毫秒) |
| jitterRange | [number, number] | [0.8, 1.2] | 抖动因子范围 |
安全配置选项
| 选项 | 类型 | 默认值 | 描述 |
|------|------|--------|------|
| strictMode | boolean | false | 是否启用严格模式(兼容 1.x 版本) |
| validateOrigin | boolean | false | 是否验证消息来源(兼容 1.x 版本) |
| validateSignature | boolean | false | 是否验证消息签名 |
| signatureKey | string | - | 消息签名密钥 |
🆕 核心类型支持
SDK 现在提供了核心类型支持,包含以下功能:
预定义的 Actions
- 状态管理:
setState- 设置应用状态 - 相机控制:
updateCamera- 更新相机状态
预定义的 Events
- 状态同步:
stateSynced- 状态同步事件 - 相机事件:
cameraUpdate- 相机更新事件 - 标签事件:
tag.click- 标签点击事件 - 监控事件:
monitor.open,monitor.close- 监控开启/关闭事件 - 覆盖层事件:
overlay.visible- 覆盖层显示/隐藏事件
🔄 兼容性说明
重要:本版本 (2.0.0-beta.3) 完全向后兼容旧版本,但建议迁移到新的 API。
🚨 1.x 版本兼容性问题
如果你正在使用 1.x 版本的 SDK,可能会遇到通信失败的问题。这是因为 2.x 版本默认启用了严格的安全模式。
问题原因
- 1.x 版本使用通配符
*进行跨域通信 - 2.x 版本默认启用严格的安全验证
- 安全机制会拒绝来自不可信域名的消息
解决方案
方案 1:使用兼容性配置(推荐)
import { RealseeVRSignalsClient, getV1CompatibilityConfig } from '@realsee/vr-signals'
const client = new RealseeVRSignalsClient({
vrLink: 'http://localhost:3000/vr-app',
element: iframeElement,
security: getV1CompatibilityConfig() // 自动配置 1.x 兼容性
})方案 2:手动禁用安全验证
const client = new RealseeVRSignalsClient({
vrLink: 'http://localhost:3000/vr-app',
element: iframeElement,
security: {
strictMode: false, // 禁用严格模式
validateOrigin: false, // 禁用来源验证
validateSignature: false // 禁用签名验证
}
})方案 3:自动检测环境
import { RealseeVRSignalsClient, getAutoCompatibilityConfig } from '@realsee/vr-signals'
const client = new RealseeVRSignalsClient({
vrLink: 'http://localhost:3000/vr-app',
element: iframeElement,
security: getAutoCompatibilityConfig() // 自动检测并配置
})兼容性工具函数
import {
getV1CompatibilityConfig, // 获取 1.x 兼容配置
getAutoCompatibilityConfig, // 自动检测环境配置
isV1Environment // 检测是否为 1.x 环境
} from '@realsee/vr-signals'
// 检测环境
if (isV1Environment()) {
console.log('检测到 1.x 版本环境,使用兼容配置')
}主要变化
- 方法名变化:
callAction()→send()(旧方法仍可用,但会显示警告) - 属性变化:
subscribe→ 直接使用 Client 实例(旧属性仍可用,但会显示警告) - 构造函数参数:
vrLink和element在类型定义中变为可选(运行时验证仍然存在) - 核心类型支持:无需泛型参数即可使用核心功能
快速迁移
// 旧用法(仍然支持)
const result = await client.callAction('setState', { mode: 'editing' })
client.subscribe.on('cameraUpdate', handler)
// 新用法(推荐)
const result = await client.send('setState', { mode: 'editing' })
client.on('cameraUpdate', handler)迁移指南
从旧版本迁移
如果你正在使用旧版本的 VR Signals SDK,迁移到新版本非常简单:
1. 更新依赖
npm install @realsee/vr-signals@latest2. 简化客户端代码
旧版本(需要泛型)
interface MyActionMap {
setState: (data: any) => void
updateCamera: (data: { state: any }) => void
}
const client = new RealseeVRSignalsClient<MyActionMap>({
vrLink: 'http://localhost:3000/vr-app',
element: iframeElement
})新版本(无需泛型)
const client = new RealseeVRSignalsClient({
vrLink: 'http://localhost:3000/vr-app',
element: iframeElement
})3. 简化服务端代码
旧版本(需要泛型)
interface MyActionMap {
setState: (data: any) => void
updateCamera: (data: { state: any }) => void
}
const remote = new RealseeVRSignalsRemote<MyActionMap>({
logLevel: 'INFO',
actionMap: {
setState(data) {
return { success: true }
},
updateCamera({ state }) {
return { success: true }
}
}
})新版本(无需泛型)
const remote = new RealseeVRSignalsRemote({
logLevel: 'INFO',
actionMap: {
setState(data) {
return { success: true }
},
updateCamera({ state }) {
return { success: true }
}
}
})迁移检查清单
- [ ] 更新依赖到最新版本
- [ ] 移除不必要的类型定义
- [ ] 简化客户端初始化代码
- [ ] 简化服务端初始化代码
- [ ] 测试核心的事件和动作
- [ ] 验证类型安全
注意事项
- 向后兼容: 旧版本的泛型用法仍然完全支持
- 类型安全: 新版本提供完整的类型安全,无需额外配置
- 性能: 核心类型不会影响运行时性能
- 扩展性: 仍然可以使用泛型来扩展核心类型
🔄 版本兼容性
1.x ↔ 2.x 兼容性
好消息! 2.0 版本默认兼容 1.x 版本,无需特殊配置。
兼容性矩阵
| Client 版本 | Remote 版本 | 兼容性 | 配置要求 | |------------|------------|--------|---------| | 1.x | 1.x | ✅ 完全兼容 | 默认配置 | | 1.x | 2.x | ✅ 兼容 | 默认配置即可(无需特殊配置) | | 2.x | 1.x | ✅ 兼容 | 默认配置即可 | | 2.x | 2.x | ✅ 完全兼容 | 可使用严格安全配置 |
使用 2.0 Remote 兼容 1.0 Client
import { RealseeVRSignalsRemote } from '@realsee/vr-signals'
// 默认配置已兼容 1.x Client,无需特殊配置
const remote = new RealseeVRSignalsRemote({
logLevel: 'INFO',
actionMap: {
setState(data) {
return { success: true }
}
}
})显式使用兼容配置(可选)
import { RealseeVRSignalsRemote, getV1CompatibilityConfig } from '@realsee/vr-signals'
const remote = new RealseeVRSignalsRemote({
security: getV1CompatibilityConfig(), // 显式声明兼容 1.x
actionMap: { /* ... */ }
})2.x 高安全模式(仅用于 2.x Client + 2.x Remote)
import { RealseeVRSignalsRemote, getV2DefaultConfig } from '@realsee/vr-signals'
const remote = new RealseeVRSignalsRemote({
security: getV2DefaultConfig('my-secret-key'), // 启用签名验证等高级安全特性
actionMap: { /* ... */ }
})📚 API 文档
本项目使用 TypeDoc 自动生成 API 文档,并通过 npm 包发布。
本地预览
# 生成文档
npm run docs
# 启动本地服务器预览
npm run docs:serve
# 监听文件变化并自动重新生成
npm run docs:watch在线文档
- API 文档: https://unpkg.com/@realsee/vr-signals@latest/docs/
- 文档说明: 查看 DOCS.md 了解详细的文档生成和发布流程
许可证
MIT
