为了实现触介体感服的连接,Truegear_player会提供一个WebSocket服务端地址,即:ws://127.0.0.1:18233/v1/tact/。通过连接这个WebSocket链接,发送对应的请求可以使衣物产生震动或电刺激效果。
该链接所传输的信息采用JSON格式。
请求消息格式如下:
{
"Method": "play_effect_by_content",
"Body": "Body"
}
{
"Method": "play_effect_by_content",
"Result": "Body"
}
方法的主要参数包括:"play_no_registered"。请求体中Body和Result的数据需采用 base64 编码。
基本概念
EffectObject对象
struct EffectObject {
string eventName; 触发事件名称
vector<TrackObject> trackList; 动作集合
};
在本文中,我们将详细介绍一个名为EffectObject的结构体,它包含了两个成员变量:eventName和trackList。这两个成员变量分别表示触发事件名称和动作集合。
eventName,它是一个字符串类型的成员变量,用于触发事件名称。在实际应用中,我们可以根据不同的触发事件名称来执行相应的操作。
接下来,我们来看trackList,它是一个TrackObject类型的数组,用于存储动作集合。
TrackObject对象
TrackObject 类用于描述具有相同动作模式的对象,包含以下属性:
struct TrackObject {
ActionType action_type; 动作类型
IntensityMode intensity_mode; 强度模式
bool once; 是否单次(只有在电刺激使用)
int interval; 间隔(只有在电刺激使用)
int start_time; 起始时间
int end_time; 结束时间
int start_intensity; 起始强度
int end_intensity; 终止强度(当 强度模式是FadeInAndOut 时,为峰顶或谷底强度)
vector<int> index;(电机或电刺激的作用id)
};
● action_type:动作类型,用于表示对象的动作类别,如振动、电刺激等。
● intensity_mode:强度模式,用于表示对象强度的变化方式,如渐变、突变等。
● once:布尔类型,表示对象是否只执行一次动作,仅在使用电刺激时有效。
● interval:整数类型,表示对象动作之间的间隔时间,仅在电刺激使用时有效。
● start_time:整数类型,表示对象动作的起始时间。
● end_time:整数类型,表示对象动作的结束时间。
● start_intensity:整数类型,表示对象动作的起始强度。
● end_intensity:整数类型,表示对象动作的终止强度,当强度模式为 FadeInAndOut 时,该值表示峰顶或谷底强度。
● index:整数类型的向量,表示对象作用的相关 ID,如电机或电刺激的 ID。
enum ActionType {动作类型
Shake, 震动
Electrical 电刺激
};
enum IntensityMode { 强度模式
Const,常量
Fade, 淡入 或 淡出
FadeInAndOut 淡入再淡出或淡出再淡入
};
index对应的位置
连接WebSocket服务端的过程如下:
1.首先,需要在设备上安装支持WebSocket协议的客户端库。例如,在JavaScript中,可以使用浏览器内置的WebSocket对象;在Python中,可以使用WebSocket库,如websockets或websocket-client。
2.导入客户端库后,创建一个WebSocket对象,将服务端地址作为参数传入。例如,在JavaScript中,可以这样创建一个WebSocket对象:
const ws = new WebSocket('ws://127.0.0.1:18233/v1/tact/');
3.当WebSocket对象成功连接到服务端时,会触发’open’事件。说明连接已经建立,此时,可以发送对应请求来控制衣物的震动或电刺激效果。
以下是发送一个震动和电刺激的实例
发送的json体为:
{"Method":"play_no_registered","Body":"eyJuYW1lIjoiTGVmdEhhbmRQaWNrdXBJdGVtIiwidXVpZCI6IkxlZnRIYW5kUGlja3VwSXRlbSIsImtlZXAiOiJGYWxzZSIsInByaW9yaXR5IjowLCJ0cmFja3MiOlt7InN0YXJ0X3RpbWUiOjAsImVuZF90aW1lIjoxMDAsInN0b3BfbmFtZSI6IiIsInN0YXJ0X2ludGVuc2l0eSI6MzAsImVuZF9pbnRlbnNpdHkiOjUsImludGVuc2l0eV9tb2RlIjoiQ29uc3QiLCJhY3Rpb25fdHlwZSI6IlNoYWtlIiwib25jZSI6IkZhbHNlIiwiaW50ZXJ2YWwiOjAsImluZGV4IjpbMCw0XX0seyJzdGFydF90aW1lIjowLCJlbmRfdGltZSI6MjAwLCJzdG9wX25hbWUiOiIiLCJzdGFydF9pbnRlbnNpdHkiOjEwLCJlbmRfaW50ZW5zaXR5Ijo1LCJpbnRlbnNpdHlfbW9kZSI6IkNvbnN0IiwiYWN0aW9uX3R5cGUiOiJFbGVjdHJpY2FsIiwib25jZSI6IkZhbHNlIiwiaW50ZXJ2YWwiOjEwLCJpbmRleCI6WzAsMTAwXX1dfQ=="}
解开base64后可以得到具体数据为
{
"name": "LeftHandPickupItem",
"uuid": "LeftHandPickupItem",
"keep": "False",
"priority": 0,
"tracks": [
{
"start_time": 0,
"end_time": 100,
"stop_name": "",
"start_intensity": 30,
"end_intensity": 5,
"intensity_mode": "Const",
"action_type": "Shake",
"once": "False",
"interval": 0,
"index": [
0,
4
]
},
{
"start_time": 0,
"end_time": 200,
"stop_name": "",
"start_intensity": 10,
"end_intensity": 5,
"intensity_mode": "Const",
"action_type": "Electrical",
"once": "False",
"interval": 10,
"index": [
0,
100
]
}
]
}
4.当不再需要控制衣物时,可以关闭WebSocket连接。
测试代码可查看
// 需要安装ws模块,使用npm install ws
const WebSocket = require('ws');
const ws = new WebSocket('ws://127.0.0.1:18233/v1/tact');
ws.on('error', console.error);
ws.on('open', function open() {
console.log('ws open');
ws.send('{"Method":"play_no_registered","Body":"eyJuYW1lIjoiTGVmdEhhbmRQaWNrdXBJdGVtIiwidXVpZCI6IkxlZnRIYW5kUGlja3VwSXRlbSIsImtlZXAiOiJGYWxzZSIsInByaW9yaXR5IjowLCJ0cmFja3MiOlt7InN0YXJ0X3RpbWUiOjAsImVuZF90aW1lIjoxMDAsInN0b3BfbmFtZSI6IiIsInN0YXJ0X2ludGVuc2l0eSI6MzAsImVuZF9pbnRlbnNpdHkiOjUsImludGVuc2l0eV9tb2RlIjoiQ29uc3QiLCJhY3Rpb25fdHlwZSI6IlNoYWtlIiwib25jZSI6IkZhbHNlIiwiaW50ZXJ2YWwiOjAsImluZGV4IjpbMCw0XX0seyJzdGFydF90aW1lIjowLCJlbmRfdGltZSI6MjAwLCJzdG9wX25hbWUiOiIiLCJzdGFydF9pbnRlbnNpdHkiOjEwLCJlbmRfaW50ZW5zaXR5Ijo1LCJpbnRlbnNpdHlfbW9kZSI6IkNvbnN0IiwiYWN0aW9uX3R5cGUiOiJFbGVjdHJpY2FsIiwib25jZSI6IkZhbHNlIiwiaW50ZXJ2YWwiOjEwLCJpbmRleCI6WzAsMTAwXX1dfQ=="} ');
});
ws.on('message', function message(data) {
console.log('received: %s', data);
});