手工具,汽保工具,工具箱,卷尺,螺丝刀,套筒,老虎钳,工具组套,工业手工具—史丹利STANLEY:
https://www.stanleytools.com/
http://www.stanleytools.cn
1 介绍
开放协议是用于构建控制器远程控制或数据订阅应用程序的接口。它是独立于平台的,可以在Linux、PLC、打印机和所有Windows平台上实现。
开放协议支持串行和以太网连接。
img1.3 术语
术语 | 定义 |
---|---|
控制器 | 开放协议支持 Power Focus 和 PowerMACS 控制器。看到:PF60001 .5 表99的限制。 |
集成器 | 例如,集成器硬件可以是PC、PLC或打印机。集成器应用程序在集成器硬件中使用开放协议。 |
消息 | 信息由三部分组成:标头、数据字段和消息结束,如"消息结构"部分所述。根据通信类型的不同,发送或接收的包包括消息之前和之后的消息和封装,如通信部分所述。 |
MID | 由四位数字表示的消息的消息ID,例如0052。MID0052是指车辆Id号上传。该ID始终包含在消息中。 |
MID修订版本 | MID可以有多个修订。如果未设置修订版本,则应用修订版1。MID通常会进行修订以包括更多数据,从而增加消息的长度。添加MID修订版本以确保向后兼容性。 |
订阅 | 订阅是控制器在每次生成特定数据时向集成器发送时使用的术语。 |
取消订阅 | 取消订阅是订阅取消订阅时使用的术语。数据将不再从控制器发送。 |
2.1 通信
使用开放协议
可以使用以太网或串行通信运行开放协议。
开放协议是全双工协议,这意味着可以同时发送和接收数据。每个通信伙伴必须能够同时操作发送和接收。
- Power Focus 控制器一次最多可接受5个连接,在串行和以太网之间共享。
- Power MACS 控制器一次可以为每个站接受两个以太网连接。没有支持用于串行连接。
2.1.1 以太网协议
集成器连接到控制器,控制器接受连接。
控制器是服务器,集成器应用程序是客户端。
使用的协议是TCP/IP。用于的默认端口通讯是4545。
2.2 消息结构
通过通信链路发送的所有信息都是ASCII格式。
消息由三部分组成; 标题,数据字段和消息结束。
以下部分描述了每个部分 部分详细。
2.2.2 数据字段
数据字段是表示数据的ASCII数据。 数据包含一系列参数,具体取决于 MID。 每个参数都用ID和参数值表示。 请注意,ID始终为2 字节。 数据字段可以为空或包含最多9979个字节。
表2数据字段内容
消息部分 | 字节 | 参数 | 值 |
---|---|---|---|
数据字段 | 21-22 | 01 | 参数ID(00 ... 99),长度为两个字节。 参数 ID在左侧填充,用ASCII字符为“0”。 |
数据字段 | 23- | 参数01值 | 参数值由参数选择定义(固定字节数)。 ASCII数字(“0”...“9”)或0x20之间的ASCII字符 和0x7F十六进制。 如果是数字, 左边填充“0”。 如果是字符, 右边填充space 。 如果不支持参数值,则为整体参数字段填充空格。 |
数据字段 | n- | 02 | 参数02 |
2.2.3数据字段实施规则
- 必须发送数据字段的所有参数
- 每条消息的数据字段都需要通过添加MID来处理 修订。 新版本可以包括新参数或增加数据字段的长度。
- 在实现具有多个版本的现有MID时,所有版本必须是 支持的
- 不支持的参数必须填充空格(hex 020)。 这特别适用于重用MID来购买新产品。
- 如果可以确定不支持的参数从不支持 ,则使用新的MID 必须定义这些参数被排除,从长远来看,这将给予更清洁 接口。 被发送到Open Protocol comitte。
- 所有MIDs描述都没有定义的“不支持”colomn 得到充分实施和支持。
- 数据部件中发送的所有扭矩和角度值均以Nm和度为单位发送,没有其他指定。 对于度数,转弯表示360度。
2.2.4消息结束
消息结束为空。
表3 消息结束内容
消息部分 | 字节 | 参数 | 值 |
---|---|---|---|
消息结束 | 0 | 消息结束 | 所有消息都是NUL终止的。 NUL 终止不包括在消息长度中。 在这手册用NUL,ASCII 0x00说明。 |
3.1建立联系
通讯实例,本节介绍如何设置通信
3.1.1 以太网连接
先决条件:控制器具有IP地址并侦听端口4545。
图9以太网连接示例
img
- 控制器监听端口 4545。
- 集成器连接到 控制器。
- 控制器接受连接。
- 集成器发送 MID 0001 沟通开始 。
- 控制器回答 MID 0002通讯开始,用Cell ID 0001 确认,通道ID 04和控制器 名为安全气囊
4 消息类别
大多数(但不是全部)消息可以分为两大类。 MID 0001通讯开始 或 MID 0003通讯停止,不属于任何这些类别。
类别是:
- 请求消息
- 活动消息
4.1 请求和请求回复消息
集成器向控制器发送请求,控制器以肯定或否定的答复者来响应请求 。
如果在响应超时之前未收到对请求的答复,则集成器应该重新发送请求最多三次。三次之后,连接被视为丢失并且是必须建立新的连接。
某些请求消息可用作Open Protocol命令禁用。这些命令是如果数字输入开放协议命令禁用数字输入有效,则拒绝。命令是表4中标记了可用消息。有关更多信息,另请参见禁用打开协议命令部分信息。
请求和请求回复消息的示例:
- 集成器发送
MID 0018
选择参数集- 控制器应答
MID 0005
命令已接受或MID 0004
命令错误
4.2 事件消息
事件消息可以分为三类:
- 事件订阅 - 取消订阅消息
- 活动消息
- 事件确认消息
事件订阅 - 取消订阅消息
订阅是使用subscribe - unsubscribe消息进行的。 订阅可以在取消 任何时候集成器通过发送取消订阅消息。
事件消息
控制器可以在诸如收紧或紧固等事件后自发地向集成器发送消息报警。此服务仅在订阅事件消息后启用。
事件消息确认
集成器应通过发送相应的确认MID来确认事件消息。如果在响应超时之前没有收到确认,则控制器将重新发送消息 三次。在三次尝试之后,控制器将认为连接丢失。
4.3 编程控制
某些命令MID需要对称为“编程控制”的控制器进行独占访问。可以将编程控制与执行编程任务所需的常规锁进行比较。
有关的MID要求编程控制可用(即锁定应解锁)为了执行,在执行命令期间进行编程控制(即它们锁定锁定),然后自动释放编程控制(即自动解锁)。
如果在发送这样的MID时没有编程控制(即锁已经锁定),则控制器以MID0004命令回答命令错误,未授予编程控制。
当命令MID需要编程控制时,这在MID中表示为警告规格。
4.4 消息列表
该部分列出了表4中的所有可用消息。看到PF60001.5
表99产品MID/Revision支持列表,其中MID在每个控制器中实现。
表 4可用消息
ID | 描述 | 由谁发送 | 请求信息 | 请求相应信息 | 事件订阅 | 事件 | 事件确认 | 开放协议命令 |
---|---|---|---|---|---|---|---|---|
0001 | 通讯开始 | 集成器 | ||||||
0002 | 通讯开始确认 | 控制器 | ||||||
0003 | 通讯停止 | 集成器 | ||||||
0004 | 命令错误 | 控制器 | ||||||
0005 | 命令被接受 | 控制器 | ||||||
0010 | 参数设置ID上传请求 | 集成器 | ||||||
0011 | 参数设置ID上传回复 | 控制器 | ||||||
0012 | 参数设置数据上传请求 | 集成器 | ||||||
0013 | 参数设置数据上传回复 | 控制器 | ||||||
0014 | 参数设置选择订阅 | 集成器 | ||||||
0015 | 选择参数组 | 控制器 | ||||||
0016 | 参数组选择确认 | 集成器 | ||||||
0017 | 参数设置选择取消订阅 | 集成器 | ||||||
0018 | 选择参数设置 | 集成器 | ||||||
0019 | 设置参数设置批量大小 | 集成器 | ||||||
0020 | 复位参数设置批处理计数器 | 集成器 | ||||||
0021 | 批量完成订阅锁定 | 集成器 | ||||||
0022 | 批量完成上传锁定 | 控制器 | ||||||
0023 | 批量锁定完成上传确认 | 集成器 | ||||||
0024 | 批量锁定完成取消订阅 | 集成器 | ||||||
0025 | 保留给福特 | 集成器 | ||||||
0030 | 作业ID上传请求 | 集成器 | ||||||
0031 | 作业ID上传回复 | 控制器 | ||||||
0032 | 作业数据上传请求 | 集成器 | ||||||
0033 | 作业数据上传回复 | 控制器 | ||||||
0034 | 工作信息订阅 | 集成器 | ||||||
0035 | 工作信息 | 控制器 | ||||||
0036 | 工作信息确认 | 集成器 | ||||||
0037 | 工作信息取消订阅 | 集成器 | ||||||
0038 | 选择作业 | 集成器 | ||||||
0039 | 作业重启 | 集成器 | ||||||
0040 | 工具数据上传请求 | 集成器 | ||||||
0041 | 工具数据上传回复 | 控制器 | ||||||
0042 | 禁用工具 | 集成器 | ||||||
0043 | 启用工具 | 集成器 | ||||||
0044 | 断开工具请求 | 集成器 | ||||||
0045 | 设置校准值请求 | 集成器 | ||||||
0046 | 设置主要工具请求 | 集成器 | ||||||
0047 | 配对处理 | 集成器 | ||||||
0048 | 配对状态 | 控制器 | ||||||
0049 | 配对状态确认 | 集成器 | ||||||
0050 | 车辆ID号下载请求 | 集成器 | ||||||
0051 | 车辆ID号订阅 | 集成器 | ||||||
0052 | 车辆ID号 | 控制器 | ||||||
0053 | 车辆ID号确认 | 集成器 | ||||||
0054 | 车辆ID号取消订阅 | 集成器 | ||||||
0060 | 最后收紧结果数据订阅 | 集成器 | ||||||
0061 | 最后收紧结果数据 | 控制器 | ||||||
0062 | 最后收紧结果数据确认 | 集成器 | ||||||
0063 | 最后收紧结果数据取消订阅 | 集成器 | ||||||
0064 | 旧收紧结果上传请求 | 集成器 | ||||||
0065 | 旧收紧结果上传回复 | 控制器 | ||||||
0070 | 报警订阅 | 集成器 | ||||||
0071 | 报警 | 控制器 | ||||||
0072 | 报警确认 | 集成器 | ||||||
0073 | 报警取消订阅 | 集成器 | ||||||
0074 | 控制器上确认报警 | 控制器 | ||||||
0075 | 控制器确认时确认报警 | 集成器 | ||||||
0076 | 报警状态 | 控制器 | ||||||
0077 | 报警状态确认 | 集成器 | ||||||
0078 | 在控制器上远程确认报警 | 集成器 | ||||||
0080 | 读取时间上传请求 | 集成器 | ||||||
0081 | 读取时间上传回复 | 控制器 | ||||||
0082 | 设定时间 | 集成器 | ||||||
0090 | 多轴状态订阅 | 集成器 | ||||||
0091 | 多轴状态 | 控制器 | ||||||
0092 | 多轴状态确认 | 集成器 | ||||||
0093 | 多轴状态取消订阅 | 集成器 | ||||||
0100 | 多轴结果订阅 | 集成器 | ||||||
0101 | 多轴结果 | 控制器 | ||||||
0102 | 多轴结果确认 | 集成器 | ||||||
0103 | 多轴结果取消订阅 | 集成器 | ||||||
0105 | 最后的PowerMACS拧紧结果数据订阅 | 集成器 | ||||||
0106 | 最后的PowerMACS拧紧结果站数据 | 控制器 | ||||||
0107 | 最后的PowerMACS拧紧结果螺栓数据 | 控制器 | ||||||
0108 | 最后的PowerMACS拧紧结果数据确认 | 集成器 | ||||||
0109 | 最后的PowerMACS拧紧结果数据取消订阅 | 集成器 | ||||||
0110 | 在compact上显示用户文本 | 集成器 | ||||||
0111 | 在图表上显示用户文本 | 集成器 | ||||||
0113 | 工具上闪烁绿灯 | 集成器 | ||||||
0120 | 作业行控制信息订阅 | 集成器 | ||||||
0121 | 作业线控制已开始 | 控制器 | ||||||
0122 | 作业线控制警报1 | 控制器 | ||||||
0123 | 作业线控制警报2 | 控制器 | ||||||
0124 | 完成作业线控制 | 控制器 | ||||||
0125 | 作业线控制信息确认 | 集成器 | ||||||
0126 | 作业行控制信息取消订阅 | 集成器 | ||||||
0127 | 中止工作 | 集成器 | ||||||
0128 | 作业批量增量 | 集成器 | ||||||
0129 | 作业批量减少 | 集成器 | ||||||
0130 | 工作休息 | 集成器 | ||||||
0131 | 设置作业线控制开始 | 集成器 | ||||||
0132 | 设置作业线控制警报1 | 集成器 | ||||||
0133 | 设置作业线控制警报2 | 集成器 | ||||||
0140 | 执行动态作业请求 | 集成器 | ||||||
0150 | 标识符下载请求 | 集成器 | ||||||
0151 | 多个标识符工作订单订阅 | 集成器 | ||||||
0152 | 多个标识符工单 | 控制器 | ||||||
0153 | 多个标识符工作单确认 | 集成器 | ||||||
0154 | 多个标识符工作订单取消订阅 | 集成器 | ||||||
0155 | 旁路标识符 | 集成器 | ||||||
0156 | 重置最新标识符 | 集成器 | ||||||
0157 | 重置所有标识符 | 集成器 | ||||||
0200 | 设置外部受控继电器 | 集成器 | ||||||
0210 | 状态外部监控输入订阅 | 集成器 | ||||||
0211 | 状态外部监控输入 | 控制器 | ||||||
0212 | 状态外部监控输入确认 | 集成器 | ||||||
0213 | 状态外部监控输入取消订阅 | 集成器 | ||||||
0214 | IO设备状态请求 | 集成器 | ||||||
0215 | IO设备状态回复 | 控制器 | ||||||
0216 | 继电器功能订阅 | 集成器 | ||||||
0217 | 继电器功能 | 控制器 | ||||||
0218 | 继电器功能确认 | 集成器 | ||||||
0219 | 继电器功能取消订阅 | 集成器 | ||||||
0220 | 数字输入功能订阅 | 集成器 | ||||||
0221 | 数字输入功能 | 控制器 | ||||||
0222 | 数字输入功能确认 | 集成器 | ||||||
0223 | Digin功能取消订阅 | 集成器 | ||||||
0224 | 设置数字输入功能 | 集成器 | ||||||
0225 | 复位数字输入功能 | 集成器 | ||||||
0240 | 用户数据下载 | 集成器 | ||||||
0241 | 订阅用户数据 | 集成器 | ||||||
0242 | 用户数据 | 控制器 | ||||||
0243 | 用户数据确认 | 集成器 | ||||||
0244 | 用户数据取消订阅 | 集成器 | ||||||
0250 | 选择器套接字信息订阅 | 集成器 | ||||||
0251 | 选择器插座信息 | 控制器 | ||||||
0252 | 选择器套接字信息确认 | 集成器 | ||||||
0253 | 选择器套接字信息取消订阅 | 集成器 | ||||||
0254 | 选择器控制绿灯 | 集成器 | ||||||
0255 | 选择器控制红灯 | 集成器 | ||||||
0260 | 工具标签ID请求 | 集成器 | ||||||
0261 | 工具标签ID订阅 | 集成器 | ||||||
0262 | 工具标签ID | 控制器 | ||||||
0263 | 工具标签ID确认 | 集成器 | ||||||
0264 | 工具标签ID取消订阅 | 集成器 | ||||||
0270 | 控制器重启请求 | 集成器 | ||||||
0300 | 直方图上传请求 | 集成器 | ||||||
0301 | 直方图上传回复 | 控制器 | ||||||
0400 | 自动/手动模式订阅 | 集成器 | ||||||
0401 | 自动/手动模式 | 控制器 | ||||||
0402 | 自动/手动模式确认 | 集成器 | ||||||
0403 | 自动/手动模式取消订阅 | 集成器 | ||||||
0410 | AutoDisable设置请求 | 集成器 | ||||||
0411 | AutoDisable设置回复 | 控制器 | ||||||
0420 | 开放协议命令已禁用订阅 | 集成器 | ||||||
0421 | 禁用开放协议命令 | 控制器 | ||||||
0422 | 开放协议命令禁用确认 | 集成器 | ||||||
0423 | 禁用取消订阅开放协议命令 | 集成器 | ||||||
0500 | 电机调谐结果数据订阅 | 集成器 | ||||||
0501 | 电机调谐结果数据 | 控制器 | ||||||
0502 | 电机调谐结果数据确认 | 集成器 | ||||||
0503 | 电机调谐结果数据取消订阅 | 集成器 | ||||||
0504 | 电机调谐请求 | 集成器 | ||||||
8000 | 奥迪紧急状态订阅 | 集成器 | ||||||
8001 | 奥迪紧急状态 | 控制器 | ||||||
8002 | 奥迪紧急状态确认 | 集成器 | ||||||
8003 | 奥迪紧急状态取消订阅 | 集成器 | ||||||
9999 | 保持开放的协议通信 | 集成器 |
实际使用
消息ID这么多,其实用到的就是几个
消息ID(MID,发送) | 含义 | 消息ID(MID,接收) | 含义 |
---|---|---|---|
0001 | 开始 | 0002 | 收到开始 |
9999 | 保持连接 | ||
0060 | 订阅 | 0062 | 收到订阅的消息 |
0001
img发送
00200001003 NUL
:
- 0020表示是20个字节
- 0001表示MID 0001(消息ID 0001)含义是通信开始
- 003表示MID 0002(消息ID 0002)的修订版本是003,不同修订版回复数据的结构不一样
- NUL是ASCII码的字符
0
,在Java中表示是"\0"
String start = "00200001003 ";
ctx.writeAndFlush(start + "\0");
接收
if("0002".equals(msg.toString().substring(4, 8))){
// 表示成功
}
if("0004".equals(msg.toString().substring(4, 8))){
// 表示错误
}
0002
img img0003
img0004
img0005
img0060
img0061
img img结果数据
img img img img img img代码
TorqueGunClient
import java.net.InetSocketAddress;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import io.netty.bootstrap.Bootstrap;
import io.netty.channel.Channel;
import io.netty.channel.ChannelInitializer;
import io.netty.channel.ChannelPipeline;
import io.netty.channel.nio.NioEventLoopGroup;
import io.netty.channel.socket.nio.NioSocketChannel;
import io.netty.handler.codec.DelimiterBasedFrameDecoder;
import io.netty.handler.codec.Delimiters;
import io.netty.handler.codec.string.StringDecoder;
import io.netty.handler.codec.string.StringEncoder;
@Component
public class TorqueGunClient {
private static Logger logger = LoggerFactory.getLogger(TorqueGunClient.class);
@Autowired
TorqueGunConfig torqueGunConfig;
public void start() {
logger.debug("开始,扭力枪通信");
// Bootstrap,且构造函数变化很大,这里用无参构造。
Bootstrap bootstrap = new Bootstrap();
// 指定channel[通道]类型
bootstrap.channel(NioSocketChannel.class);
// 指定Handler [操纵者]
bootstrap.handler(new ChannelInitializer<Channel>() {
@Override
protected void initChannel(Channel ch) throws Exception {
ChannelPipeline pipeline = ch.pipeline();
/*
* 这个地方的 必须和服务端对应上。否则无法正常解码和编码
*
*/
pipeline.addLast("framer", new DelimiterBasedFrameDecoder(8192, Delimiters.nulDelimiter()));
pipeline.addLast("decoder", new StringDecoder());
pipeline.addLast("encoder", new StringEncoder());
// 客户端的逻辑,自己对数据处理
pipeline.addLast(new TorqueGunClientHandler());
}
});
// 指定EventLoopGroup [事件组]
bootstrap.group(new NioEventLoopGroup());
// 连接到本地的8000端口的服务端
bootstrap.connect(new InetSocketAddress(torqueGunConfig.getIp(), torqueGunConfig.getPort()));
}
}
类TorqueGunClientHandler
import java.util.Timer;
import java.util.TimerTask;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import cn.com.tcb.uavpcs.datacenter.comm.desktop.process.WorkplaceClientInvotor;
import io.netty.channel.ChannelHandlerContext;
import io.netty.channel.ChannelInboundHandlerAdapter;
public class TorqueGunClientHandler extends ChannelInboundHandlerAdapter {
private static Logger logger = LoggerFactory.getLogger(TorqueGunClientHandler.class);
private String keepAlive = "00209999000 " + "\0";
private String start = "00200001003 " + "\0";
private String subscribe01 = "002000600031 01 " + "\0";
private String subscribe02 = "002000600031 02 " + "\0";
private String subscribe03 = "002000600031 03 " + "\0";
private String subscribe04 = "002000600031 04 " + "\0";
private String subscribe05 = "002000600031 05 " + "\0";
private String subscribe06 = "002000600031 06 " + "\0";
private String subscribe07 = "002000600031 07 " + "\0";
private String subscribe08 = "002000600031 08 " + "\0";
/*
* 监听 服务器 发送来的数据
*/
@Override
public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception {
logger.debug("say:" + msg);
if ("0002".equals(msg.toString().substring(4, 8))) {
// 握手成功,主动发送一次心跳消息
ctx.writeAndFlush(keepAlive);
} else if ("9999".equals(msg.toString().substring(4, 8))) {
Timer timer = new Timer();
timer.schedule(new TimerTask() {
@Override
public void run() {
ctx.writeAndFlush(keepAlive);
timer.cancel();
}
},10000);
} else if ("0061".equals(msg.toString().substring(4, 8))) {
logger.debug(msg.toString());
String val = msg.toString();
if(val.length()>57) {
String clientID = val.substring(55, 57).trim();
if(!clientID.equals("")) {
WorkplaceClientInvotor workplaceClientInvotor = new WorkplaceClientInvotor();
workplaceClientInvotor.reportTorqueData(msg.toString(), clientID);
}
}
}
}
/*
* 启动客户端 时触发
*/
@Override
public void channelActive(ChannelHandlerContext ctx) throws Exception {
logger.debug("Client active ");
ctx.writeAndFlush(start);
ctx.writeAndFlush(subscribe01);
ctx.writeAndFlush(subscribe02);
ctx.writeAndFlush(subscribe03);
ctx.writeAndFlush(subscribe04);
ctx.writeAndFlush(subscribe05);
ctx.writeAndFlush(subscribe06);
ctx.writeAndFlush(subscribe07);
ctx.writeAndFlush(subscribe08);
super.channelActive(ctx);
}
/*
* 关闭 客户端 触发
*/
@Override
public void channelInactive(ChannelHandlerContext ctx) throws Exception {
logger.debug("Client close ");
super.channelInactive(ctx);
}
}
网友评论