一.场景:
给公司做一个动态调参用的前端界面,是读取json文件动态的生成滑块和勾选框,然后测试将通过滑块或者勾选框进行参数调整,将调整后的参数发送给对应的节点,发送接收过程使用的是发布订阅模式.
二.遇到的问题:
1.前端的jsvascript如何使用protobuff?这个过程比较麻烦,需要进行两次的转换:.proto文件转换成node.js可以使用的js文件,然后在转换成前端js可以使用的js文件.
2.ipc_core使用的网络是用最底层的socket实现,前端是不可以直接将pb消息通过websocket将数据发送到ipc_core,因为socket通信和websocket是两种不同的协议,所以收发的数据一定会有问题,所以需要编写一个ipc_client将前端websocket的消息接收到以后通过ipc_client发送给ipc_core,其中ipc_client是由socket编写的.
3.我老大一直给我说定义发送一个topic,我一直不懂他说的topic究竟是什么,后来才发现是发送订阅模式中用来标记某一种类型数据的唯一标志.比如说发布者发布一种数据,定义这个数据的topic是
三.大概的解决过程:
问题一:
由于之前没有接触过前端的编写,不知道可以通过js循环的方式创建这些滑块,一开始自己去手动的生成这些滑块,后来经大佬的指导,写出了如下的代码:
for(var i = 0; i < value_array.length; i++){
cfg_name = getCfgName(i);
slider = cfg_name + "<input class = 'slider" + i + "' type = 'range' id = '" + i + "' name = '" + cfg_name + "' min = '" + getMin(i) + "' max = '" + getMax(i) + "' step = '0.0001' value = '" + getValue(i) + "' onchange = newValue(id) >";
input_text = "<input class = 'input_text" + i + "' type = 'number' id = '" + i + "' min = '" + getMin(i) + "' max = '" + getMax(i) + "' value = '" + getValue(i) + "' step = 0.0001 required = 'required' onchange = typedValue(id) >请输入" + getMin(i) + "~" + getMax(i) + "之间的值</br>";
document.write(slider);
document.write(input_text);
}
没错,他居然可以同字符串的拼接,然后通过write()将数据写在页面上,即可.吃惊!!!
问题二:
protobuff是谷歌的开源工具,可以自由的定义一些消息等,体积小,速度快,一般都用在后端的语言,这次却需要在前端使用,然后翻看了一些前辈的博客问题才能解决.基本过程如下:
- 假设我们的.proto文件叫做test.proto,在终端中输入一下命令,将这个proto文件生成node.js可以使用的test.js文件
protoc --js_out=import_style=commonjs,binary:. .\test.proto
2. npm install -g require
3. npm install -g browserify
4. 使用browserify对文件进行编译打包
var personProto = require('./proto_person_pb.js');
module.exports = {
DataProto: personProto
}
//注意exports中使用到的personProto一定是之前定义好的,这个名字无所谓叫啥
5.执行命令 browserify exports.js > prob.js 将test.js文件进行编译打包生成prob.js
6.在需要使用的js文件中引入prob.js即可
<script src="./prob.js"></script>
问题三:
如何发送和解析pb消息呢,先来看一下我proto文件中大概内容
syntax = "proto3";
message BoolParameter {
string name = 1;
bool value = 2;
}
message IntParameter {
string name = 1;
int32 value = 2;
}
message StrParameter {
string name = 1;
string value = 2;
}
message DoubleParameter {
string name = 1;
double value = 2;
}
message GroupState{
string name = 1;
bool state = 2;
int32 id = 3;
int32 parent = 4;
}
message Config {
repeated BoolParameter bools = 1;
repeated IntParameter ints = 2;
repeated StrParameter strs = 3;
repeated DoubleParameter doubles = 4;
repeated GroupState groups = 5;
}
我这里生成pb消息时,没有发送上面的五种消息格式,最后将各种消息放在Config这类型的消息中,其中需要注意的是repeated
是重复的意思,实际上就是数组的意思,也就是说类似 repeated BoolParameter bools = 1;是message BoolParameter 的数组,可以存放很多message BoolParameter 中类型的消息.
我们可以打开生成pb文件,直接查看他都有哪些接口。
使用PB---发送:
var config = new proto.Config();
for(var i = 0; i < changeValue_array.length; i++){
var double_value = new proto.DoubleParameter();
double_value.setName(slider[0].name);
double_value.setValue(slider[0].value);
config.addDoubles(double_value,i);
}
for(var i = 0; i < changeBool_array.length; i++){
var bool_value = new proto.BoolParameter();
bool_value.setName(radio[0].name);
bool_value.setValue(radio[0].value);
config.addBools(bool_value,i);
//bool_value是BoolParameter消息类型的一个对象,然后通过set方法后,将这个
//组装的好的pb消息塞到对应的数组里面,如addBools是放到repeated BoolParameter bools = 1;
//中去
}
console.log(config);
ws.send(config.serializeBinary());
//发送时需要将数据序列化为二进制的,才可以发送
使用PB---接收:
var pb = require('./dynamic_reconfigure_msgs_pb');
//dynamic_reconfigure_msgs_pb指的是我将proto文件经过转换后的xxx.js文件
var des_pb_message =pb.Config.deserializeBinary(message);
//message为接受到的pb消息,要先进行反序列化
var list = des_pb_message.getDoublesList();
//message中有很多的数组,因为他是config消息类型
//这里是需要将double类型的数组从config中提取出来
var len = list.length;
for(var i = 0;i<len;i++)
{
console.log(list[i]);
//输出double数组的内容
}
问题四:
使用pb+发布订阅完成消息的传递时,数据的格式为topic+数据实体.
问题五:
发布订阅模式的使用:
前端发布一个消息,消息的内容为原始的数据,然后将数据转发给ipc_client,ipc_client给数据设置一topic,然后发布给ipc_core,然后其他的节点去订阅这个topic,如果有消息,就会把这个消息发送给订阅这个topic的节点.