Compare commits

...

6 Commits

Author SHA1 Message Date
fc6b51cc24 [bug]信号机电路系统逻辑没有正确处理驱动状态
All checks were successful
local-test分支打包构建docker并发布运行 / Docker-Build (push) Successful in 5m29s
2024-08-01 14:25:45 +08:00
5433ae43d6 [重写]计轴的组件、实体、系统、预复位/复位逻辑 2024-07-31 17:08:54 +08:00
afaf9d64c7 [修改]北京12号线连锁rsd、sse、ssr编解码算法及交互流程 2024-07-29 13:53:46 +08:00
tiger_zhou
8a34935d0f 列车车载应答器调试初始 2024-07-25 14:55:46 +08:00
72ca826be2 Merge remote-tracking branch 'origin/develop' into develop 2024-07-24 18:27:51 +08:00
7e38a912d4 [修改]crc32校验逻辑 2024-07-24 18:27:41 +08:00
33 changed files with 1245 additions and 1029 deletions

View File

@ -844,7 +844,7 @@ func baliseTelegramReset(c *gin.Context) {
} }
simulation := checkDeviceDataAndReturn(req.SimulationId) simulation := checkDeviceDataAndReturn(req.SimulationId)
slog.Info("传入状态参数", req) slog.Info("传入状态参数", req)
var err *sys_error.BusinessError = memory.BaliseTelegramReset(simulation, req) var err = memory.BaliseTelegramReset(simulation, req)
if err != nil { if err != nil {
panic(err) panic(err)
} }
@ -931,7 +931,7 @@ func baliseReset(c *gin.Context) {
//} //}
simulationId := c.Query("simulationId") simulationId := c.Query("simulationId")
simulation := checkDeviceDataAndReturn(simulationId) simulation := checkDeviceDataAndReturn(simulationId)
err := memory.BaliseReset(simulation) err := memory.AllBaliseTelegramReset(simulation)
if err != nil { if err != nil {
panic(sys_error.New(fmt.Sprintf("应答器状态重置操作失败,%s", err.Error()), err)) panic(sys_error.New(fmt.Sprintf("应答器状态重置操作失败,%s", err.Error()), err))
} }

View File

@ -120,10 +120,10 @@ type VobcConfig struct {
Open bool `json:"open" description:"是否开启"` Open bool `json:"open" description:"是否开启"`
} }
type InterlockConfig struct { type InterlockConfig struct {
Open bool `json:"open" description:"是否开启"`
Ip string `json:"ip" description:"IP配置"` Ip string `json:"ip" description:"IP配置"`
LocalPort int `json:"localPort" description:"本机监听接收端口"` LocalPort int `json:"localPort" description:"本机监听接收端口"`
RemotePort int `json:"remotePort" description:"远端接收采集信息端口"` RemotePort int `json:"remotePort" description:"远端接收采集信息端口"`
Open bool `json:"open" description:"是否开启"`
Code string `json:"code" description:"所属集中站"` Code string `json:"code" description:"所属集中站"`
Line string `json:"line" description:"联锁通信协议所属线路"` Line string `json:"line" description:"联锁通信协议所属线路"`
} }

View File

@ -3043,10 +3043,11 @@ type BTMState struct {
DataSerialNumber uint32 `protobuf:"varint,1,opt,name=dataSerialNumber,proto3" json:"dataSerialNumber,omitempty"` //数据流水号0~255变化每次加一 DataSerialNumber uint32 `protobuf:"varint,1,opt,name=dataSerialNumber,proto3" json:"dataSerialNumber,omitempty"` //数据流水号0~255变化每次加一
BaliseCount uint32 `protobuf:"varint,2,opt,name=baliseCount,proto3" json:"baliseCount,omitempty"` //应答器计数(每过一个应答器加一,在同一个应答器内不变)0~255 BaliseCount uint32 `protobuf:"varint,2,opt,name=baliseCount,proto3" json:"baliseCount,omitempty"` //应答器计数(每过一个应答器加一,在同一个应答器内不变)0~255
MessageCounter uint32 `protobuf:"varint,3,opt,name=messageCounter,proto3" json:"messageCounter,omitempty"` //报文计数器 (每解出一个报文加一)0~255 MessageCounter uint32 `protobuf:"varint,3,opt,name=messageCounter,proto3" json:"messageCounter,omitempty"` //报文计数器 (每解出一个报文加一)0~255
Telegram string `protobuf:"bytes,4,opt,name=telegram,proto3" json:"telegram,omitempty"` //报文16进制字符串 Telegram string `protobuf:"bytes,4,opt,name=telegram,proto3" json:"telegram,omitempty"` //应答器用户报文16进制字符串
Distance int64 `protobuf:"varint,5,opt,name=distance,proto3" json:"distance,omitempty"` //BTM天线中心到应答器的距离mm Distance int64 `protobuf:"varint,5,opt,name=distance,proto3" json:"distance,omitempty"` //BTM天线中心到应答器的距离mm
AboveBalise bool `protobuf:"varint,6,opt,name=aboveBalise,proto3" json:"aboveBalise,omitempty"` //BTM天线即将经过应答器 AboveBalise bool `protobuf:"varint,6,opt,name=aboveBalise,proto3" json:"aboveBalise,omitempty"` //BTM天线即将经过应答器
BaliseTelegramForPcSimResend string `protobuf:"bytes,7,opt,name=baliseTelegramForPcSimResend,proto3" json:"baliseTelegramForPcSimResend,omitempty"` //列车pc仿真暂存应答器回复数据 BaliseTelegramForPcSimResend string `protobuf:"bytes,7,opt,name=baliseTelegramForPcSimResend,proto3" json:"baliseTelegramForPcSimResend,omitempty"` //列车pc仿真暂存应答器回复数据
Telegram128 string `protobuf:"bytes,8,opt,name=telegram128,proto3" json:"telegram128,omitempty"` //应答器报文12816进制字符串
} }
func (x *BTMState) Reset() { func (x *BTMState) Reset() {
@ -3130,6 +3131,13 @@ func (x *BTMState) GetBaliseTelegramForPcSimResend() string {
return "" return ""
} }
func (x *BTMState) GetTelegram128() string {
if x != nil {
return x.Telegram128
}
return ""
}
// 动力学相关参数返回数据因golang float类型数据序列化后丢失精度故使用string // 动力学相关参数返回数据因golang float类型数据序列化后丢失精度故使用string
// 此类型需要与 common_data 中的 TrainDynamicConfig类型属性保持一致 // 此类型需要与 common_data 中的 TrainDynamicConfig类型属性保持一致
type TrainDynamicConfigMqtt struct { type TrainDynamicConfigMqtt struct {
@ -6154,7 +6162,7 @@ var file_device_state_proto_rawDesc = []byte{
0x61, 0x74, 0x65, 0x12, 0x33, 0x0a, 0x09, 0x63, 0x6f, 0x6e, 0x6e, 0x53, 0x74, 0x61, 0x74, 0x65, 0x61, 0x74, 0x65, 0x12, 0x33, 0x0a, 0x09, 0x63, 0x6f, 0x6e, 0x6e, 0x53, 0x74, 0x61, 0x74, 0x65,
0x18, 0x46, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x15, 0x2e, 0x73, 0x74, 0x61, 0x74, 0x65, 0x2e, 0x54, 0x18, 0x46, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x15, 0x2e, 0x73, 0x74, 0x61, 0x74, 0x65, 0x2e, 0x54,
0x72, 0x61, 0x69, 0x6e, 0x43, 0x6f, 0x6e, 0x6e, 0x53, 0x74, 0x61, 0x74, 0x65, 0x52, 0x09, 0x63, 0x72, 0x61, 0x69, 0x6e, 0x43, 0x6f, 0x6e, 0x6e, 0x53, 0x74, 0x61, 0x74, 0x65, 0x52, 0x09, 0x63,
0x6f, 0x6e, 0x6e, 0x53, 0x74, 0x61, 0x74, 0x65, 0x22, 0x9e, 0x02, 0x0a, 0x08, 0x42, 0x54, 0x4d, 0x6f, 0x6e, 0x6e, 0x53, 0x74, 0x61, 0x74, 0x65, 0x22, 0xc0, 0x02, 0x0a, 0x08, 0x42, 0x54, 0x4d,
0x53, 0x74, 0x61, 0x74, 0x65, 0x12, 0x2a, 0x0a, 0x10, 0x64, 0x61, 0x74, 0x61, 0x53, 0x65, 0x72, 0x53, 0x74, 0x61, 0x74, 0x65, 0x12, 0x2a, 0x0a, 0x10, 0x64, 0x61, 0x74, 0x61, 0x53, 0x65, 0x72,
0x69, 0x61, 0x6c, 0x4e, 0x75, 0x6d, 0x62, 0x65, 0x72, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x69, 0x61, 0x6c, 0x4e, 0x75, 0x6d, 0x62, 0x65, 0x72, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0d, 0x52,
0x10, 0x64, 0x61, 0x74, 0x61, 0x53, 0x65, 0x72, 0x69, 0x61, 0x6c, 0x4e, 0x75, 0x6d, 0x62, 0x65, 0x10, 0x64, 0x61, 0x74, 0x61, 0x53, 0x65, 0x72, 0x69, 0x61, 0x6c, 0x4e, 0x75, 0x6d, 0x62, 0x65,
@ -6172,377 +6180,379 @@ var file_device_state_proto_rawDesc = []byte{
0x65, 0x6c, 0x65, 0x67, 0x72, 0x61, 0x6d, 0x46, 0x6f, 0x72, 0x50, 0x63, 0x53, 0x69, 0x6d, 0x52, 0x65, 0x6c, 0x65, 0x67, 0x72, 0x61, 0x6d, 0x46, 0x6f, 0x72, 0x50, 0x63, 0x53, 0x69, 0x6d, 0x52,
0x65, 0x73, 0x65, 0x6e, 0x64, 0x18, 0x07, 0x20, 0x01, 0x28, 0x09, 0x52, 0x1c, 0x62, 0x61, 0x6c, 0x65, 0x73, 0x65, 0x6e, 0x64, 0x18, 0x07, 0x20, 0x01, 0x28, 0x09, 0x52, 0x1c, 0x62, 0x61, 0x6c,
0x69, 0x73, 0x65, 0x54, 0x65, 0x6c, 0x65, 0x67, 0x72, 0x61, 0x6d, 0x46, 0x6f, 0x72, 0x50, 0x63, 0x69, 0x73, 0x65, 0x54, 0x65, 0x6c, 0x65, 0x67, 0x72, 0x61, 0x6d, 0x46, 0x6f, 0x72, 0x50, 0x63,
0x53, 0x69, 0x6d, 0x52, 0x65, 0x73, 0x65, 0x6e, 0x64, 0x22, 0xe4, 0x04, 0x0a, 0x16, 0x54, 0x72, 0x53, 0x69, 0x6d, 0x52, 0x65, 0x73, 0x65, 0x6e, 0x64, 0x12, 0x20, 0x0a, 0x0b, 0x74, 0x65, 0x6c,
0x61, 0x69, 0x6e, 0x44, 0x79, 0x6e, 0x61, 0x6d, 0x69, 0x63, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x65, 0x67, 0x72, 0x61, 0x6d, 0x31, 0x32, 0x38, 0x18, 0x08, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0b,
0x4d, 0x71, 0x74, 0x74, 0x12, 0x20, 0x0a, 0x0b, 0x64, 0x61, 0x76, 0x69, 0x73, 0x50, 0x61, 0x72, 0x74, 0x65, 0x6c, 0x65, 0x67, 0x72, 0x61, 0x6d, 0x31, 0x32, 0x38, 0x22, 0xe4, 0x04, 0x0a, 0x16,
0x61, 0x6d, 0x41, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0b, 0x64, 0x61, 0x76, 0x69, 0x73, 0x54, 0x72, 0x61, 0x69, 0x6e, 0x44, 0x79, 0x6e, 0x61, 0x6d, 0x69, 0x63, 0x43, 0x6f, 0x6e, 0x66,
0x50, 0x61, 0x72, 0x61, 0x6d, 0x41, 0x12, 0x20, 0x0a, 0x0b, 0x64, 0x61, 0x76, 0x69, 0x73, 0x50, 0x69, 0x67, 0x4d, 0x71, 0x74, 0x74, 0x12, 0x20, 0x0a, 0x0b, 0x64, 0x61, 0x76, 0x69, 0x73, 0x50,
0x61, 0x72, 0x61, 0x6d, 0x42, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0b, 0x64, 0x61, 0x76, 0x61, 0x72, 0x61, 0x6d, 0x41, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0b, 0x64, 0x61, 0x76,
0x69, 0x73, 0x50, 0x61, 0x72, 0x61, 0x6d, 0x42, 0x12, 0x20, 0x0a, 0x0b, 0x64, 0x61, 0x76, 0x69, 0x69, 0x73, 0x50, 0x61, 0x72, 0x61, 0x6d, 0x41, 0x12, 0x20, 0x0a, 0x0b, 0x64, 0x61, 0x76, 0x69,
0x73, 0x50, 0x61, 0x72, 0x61, 0x6d, 0x43, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0b, 0x64, 0x73, 0x50, 0x61, 0x72, 0x61, 0x6d, 0x42, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0b, 0x64,
0x61, 0x76, 0x69, 0x73, 0x50, 0x61, 0x72, 0x61, 0x6d, 0x43, 0x12, 0x36, 0x0a, 0x16, 0x63, 0x75, 0x61, 0x76, 0x69, 0x73, 0x50, 0x61, 0x72, 0x61, 0x6d, 0x42, 0x12, 0x20, 0x0a, 0x0b, 0x64, 0x61,
0x76, 0x69, 0x73, 0x50, 0x61, 0x72, 0x61, 0x6d, 0x43, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52,
0x0b, 0x64, 0x61, 0x76, 0x69, 0x73, 0x50, 0x61, 0x72, 0x61, 0x6d, 0x43, 0x12, 0x36, 0x0a, 0x16,
0x63, 0x75, 0x72, 0x76, 0x65, 0x52, 0x65, 0x73, 0x69, 0x73, 0x74, 0x61, 0x6e, 0x63, 0x65, 0x50,
0x61, 0x72, 0x61, 0x6d, 0x52, 0x31, 0x18, 0x04, 0x20, 0x01, 0x28, 0x09, 0x52, 0x16, 0x63, 0x75,
0x72, 0x76, 0x65, 0x52, 0x65, 0x73, 0x69, 0x73, 0x74, 0x61, 0x6e, 0x63, 0x65, 0x50, 0x61, 0x72, 0x72, 0x76, 0x65, 0x52, 0x65, 0x73, 0x69, 0x73, 0x74, 0x61, 0x6e, 0x63, 0x65, 0x50, 0x61, 0x72,
0x61, 0x6d, 0x52, 0x31, 0x18, 0x04, 0x20, 0x01, 0x28, 0x09, 0x52, 0x16, 0x63, 0x75, 0x72, 0x76, 0x61, 0x6d, 0x52, 0x31, 0x12, 0x36, 0x0a, 0x16, 0x63, 0x75, 0x72, 0x76, 0x65, 0x52, 0x65, 0x73,
0x65, 0x52, 0x65, 0x73, 0x69, 0x73, 0x74, 0x61, 0x6e, 0x63, 0x65, 0x50, 0x61, 0x72, 0x61, 0x6d, 0x69, 0x73, 0x74, 0x61, 0x6e, 0x63, 0x65, 0x50, 0x61, 0x72, 0x61, 0x6d, 0x52, 0x32, 0x18, 0x05,
0x52, 0x31, 0x12, 0x36, 0x0a, 0x16, 0x63, 0x75, 0x72, 0x76, 0x65, 0x52, 0x65, 0x73, 0x69, 0x73, 0x20, 0x01, 0x28, 0x09, 0x52, 0x16, 0x63, 0x75, 0x72, 0x76, 0x65, 0x52, 0x65, 0x73, 0x69, 0x73,
0x74, 0x61, 0x6e, 0x63, 0x65, 0x50, 0x61, 0x72, 0x61, 0x6d, 0x52, 0x32, 0x18, 0x05, 0x20, 0x01, 0x74, 0x61, 0x6e, 0x63, 0x65, 0x50, 0x61, 0x72, 0x61, 0x6d, 0x52, 0x32, 0x12, 0x36, 0x0a, 0x16,
0x28, 0x09, 0x52, 0x16, 0x63, 0x75, 0x72, 0x76, 0x65, 0x52, 0x65, 0x73, 0x69, 0x73, 0x74, 0x61, 0x63, 0x75, 0x72, 0x76, 0x65, 0x52, 0x65, 0x73, 0x69, 0x73, 0x74, 0x61, 0x6e, 0x63, 0x65, 0x50,
0x6e, 0x63, 0x65, 0x50, 0x61, 0x72, 0x61, 0x6d, 0x52, 0x32, 0x12, 0x36, 0x0a, 0x16, 0x63, 0x75, 0x61, 0x72, 0x61, 0x6d, 0x52, 0x33, 0x18, 0x06, 0x20, 0x01, 0x28, 0x09, 0x52, 0x16, 0x63, 0x75,
0x72, 0x76, 0x65, 0x52, 0x65, 0x73, 0x69, 0x73, 0x74, 0x61, 0x6e, 0x63, 0x65, 0x50, 0x61, 0x72, 0x72, 0x76, 0x65, 0x52, 0x65, 0x73, 0x69, 0x73, 0x74, 0x61, 0x6e, 0x63, 0x65, 0x50, 0x61, 0x72,
0x61, 0x6d, 0x52, 0x33, 0x18, 0x06, 0x20, 0x01, 0x28, 0x09, 0x52, 0x16, 0x63, 0x75, 0x72, 0x76, 0x61, 0x6d, 0x52, 0x33, 0x12, 0x36, 0x0a, 0x16, 0x63, 0x75, 0x72, 0x76, 0x65, 0x52, 0x65, 0x73,
0x65, 0x52, 0x65, 0x73, 0x69, 0x73, 0x74, 0x61, 0x6e, 0x63, 0x65, 0x50, 0x61, 0x72, 0x61, 0x6d, 0x69, 0x73, 0x74, 0x61, 0x6e, 0x63, 0x65, 0x50, 0x61, 0x72, 0x61, 0x6d, 0x52, 0x34, 0x18, 0x07,
0x52, 0x33, 0x12, 0x36, 0x0a, 0x16, 0x63, 0x75, 0x72, 0x76, 0x65, 0x52, 0x65, 0x73, 0x69, 0x73, 0x20, 0x01, 0x28, 0x09, 0x52, 0x16, 0x63, 0x75, 0x72, 0x76, 0x65, 0x52, 0x65, 0x73, 0x69, 0x73,
0x74, 0x61, 0x6e, 0x63, 0x65, 0x50, 0x61, 0x72, 0x61, 0x6d, 0x52, 0x34, 0x18, 0x07, 0x20, 0x01, 0x74, 0x61, 0x6e, 0x63, 0x65, 0x50, 0x61, 0x72, 0x61, 0x6d, 0x52, 0x34, 0x12, 0x2e, 0x0a, 0x12,
0x28, 0x09, 0x52, 0x16, 0x63, 0x75, 0x72, 0x76, 0x65, 0x52, 0x65, 0x73, 0x69, 0x73, 0x74, 0x61, 0x72, 0x65, 0x76, 0x6f, 0x6c, 0x76, 0x69, 0x6e, 0x67, 0x4d, 0x61, 0x73, 0x73, 0x50, 0x61, 0x72,
0x6e, 0x63, 0x65, 0x50, 0x61, 0x72, 0x61, 0x6d, 0x52, 0x34, 0x12, 0x2e, 0x0a, 0x12, 0x72, 0x65, 0x61, 0x6d, 0x18, 0x08, 0x20, 0x01, 0x28, 0x09, 0x52, 0x12, 0x72, 0x65, 0x76, 0x6f, 0x6c, 0x76,
0x76, 0x6f, 0x6c, 0x76, 0x69, 0x6e, 0x67, 0x4d, 0x61, 0x73, 0x73, 0x50, 0x61, 0x72, 0x61, 0x6d, 0x69, 0x6e, 0x67, 0x4d, 0x61, 0x73, 0x73, 0x50, 0x61, 0x72, 0x61, 0x6d, 0x12, 0x12, 0x0a, 0x04,
0x18, 0x08, 0x20, 0x01, 0x28, 0x09, 0x52, 0x12, 0x72, 0x65, 0x76, 0x6f, 0x6c, 0x76, 0x69, 0x6e, 0x6a, 0x75, 0x6d, 0x70, 0x18, 0x09, 0x20, 0x01, 0x28, 0x08, 0x52, 0x04, 0x6a, 0x75, 0x6d, 0x70,
0x67, 0x4d, 0x61, 0x73, 0x73, 0x50, 0x61, 0x72, 0x61, 0x6d, 0x12, 0x12, 0x0a, 0x04, 0x6a, 0x75, 0x12, 0x14, 0x0a, 0x05, 0x73, 0x6c, 0x69, 0x70, 0x41, 0x18, 0x0a, 0x20, 0x01, 0x28, 0x09, 0x52,
0x6d, 0x70, 0x18, 0x09, 0x20, 0x01, 0x28, 0x08, 0x52, 0x04, 0x6a, 0x75, 0x6d, 0x70, 0x12, 0x14, 0x05, 0x73, 0x6c, 0x69, 0x70, 0x41, 0x12, 0x14, 0x0a, 0x05, 0x73, 0x6c, 0x69, 0x70, 0x52, 0x18,
0x0a, 0x05, 0x73, 0x6c, 0x69, 0x70, 0x41, 0x18, 0x0a, 0x20, 0x01, 0x28, 0x09, 0x52, 0x05, 0x73, 0x0b, 0x20, 0x01, 0x28, 0x09, 0x52, 0x05, 0x73, 0x6c, 0x69, 0x70, 0x52, 0x12, 0x14, 0x0a, 0x05,
0x6c, 0x69, 0x70, 0x41, 0x12, 0x14, 0x0a, 0x05, 0x73, 0x6c, 0x69, 0x70, 0x52, 0x18, 0x0b, 0x20, 0x73, 0x6c, 0x69, 0x70, 0x44, 0x18, 0x0c, 0x20, 0x01, 0x28, 0x05, 0x52, 0x05, 0x73, 0x6c, 0x69,
0x01, 0x28, 0x09, 0x52, 0x05, 0x73, 0x6c, 0x69, 0x70, 0x52, 0x12, 0x14, 0x0a, 0x05, 0x73, 0x6c, 0x70, 0x44, 0x12, 0x18, 0x0a, 0x07, 0x69, 0x64, 0x6c, 0x69, 0x6e, 0x67, 0x41, 0x18, 0x0e, 0x20,
0x69, 0x70, 0x44, 0x18, 0x0c, 0x20, 0x01, 0x28, 0x05, 0x52, 0x05, 0x73, 0x6c, 0x69, 0x70, 0x44, 0x01, 0x28, 0x09, 0x52, 0x07, 0x69, 0x64, 0x6c, 0x69, 0x6e, 0x67, 0x41, 0x12, 0x18, 0x0a, 0x07,
0x12, 0x18, 0x0a, 0x07, 0x69, 0x64, 0x6c, 0x69, 0x6e, 0x67, 0x41, 0x18, 0x0e, 0x20, 0x01, 0x28, 0x69, 0x64, 0x6c, 0x69, 0x6e, 0x67, 0x52, 0x18, 0x0f, 0x20, 0x01, 0x28, 0x09, 0x52, 0x07, 0x69,
0x09, 0x52, 0x07, 0x69, 0x64, 0x6c, 0x69, 0x6e, 0x67, 0x41, 0x12, 0x18, 0x0a, 0x07, 0x69, 0x64, 0x64, 0x6c, 0x69, 0x6e, 0x67, 0x52, 0x12, 0x18, 0x0a, 0x07, 0x69, 0x64, 0x6c, 0x69, 0x6e, 0x67,
0x6c, 0x69, 0x6e, 0x67, 0x52, 0x18, 0x0f, 0x20, 0x01, 0x28, 0x09, 0x52, 0x07, 0x69, 0x64, 0x6c, 0x44, 0x18, 0x10, 0x20, 0x01, 0x28, 0x05, 0x52, 0x07, 0x69, 0x64, 0x6c, 0x69, 0x6e, 0x67, 0x44,
0x69, 0x6e, 0x67, 0x52, 0x12, 0x18, 0x0a, 0x07, 0x69, 0x64, 0x6c, 0x69, 0x6e, 0x67, 0x44, 0x18, 0x12, 0x1a, 0x0a, 0x08, 0x73, 0x74, 0x6f, 0x70, 0x53, 0x69, 0x67, 0x6e, 0x18, 0x11, 0x20, 0x01,
0x10, 0x20, 0x01, 0x28, 0x05, 0x52, 0x07, 0x69, 0x64, 0x6c, 0x69, 0x6e, 0x67, 0x44, 0x12, 0x1a, 0x28, 0x05, 0x52, 0x08, 0x73, 0x74, 0x6f, 0x70, 0x53, 0x69, 0x67, 0x6e, 0x12, 0x14, 0x0a, 0x05,
0x0a, 0x08, 0x73, 0x74, 0x6f, 0x70, 0x53, 0x69, 0x67, 0x6e, 0x18, 0x11, 0x20, 0x01, 0x28, 0x05, 0x73, 0x6c, 0x69, 0x64, 0x65, 0x18, 0x12, 0x20, 0x01, 0x28, 0x09, 0x52, 0x05, 0x73, 0x6c, 0x69,
0x52, 0x08, 0x73, 0x74, 0x6f, 0x70, 0x53, 0x69, 0x67, 0x6e, 0x12, 0x14, 0x0a, 0x05, 0x73, 0x6c, 0x64, 0x65, 0x22, 0xa8, 0x03, 0x0a, 0x12, 0x54, 0x72, 0x61, 0x69, 0x6e, 0x45, 0x6e, 0x64, 0x73,
0x69, 0x64, 0x65, 0x18, 0x12, 0x20, 0x01, 0x28, 0x09, 0x52, 0x05, 0x73, 0x6c, 0x69, 0x64, 0x65, 0x53, 0x74, 0x61, 0x74, 0x65, 0x4d, 0x71, 0x74, 0x74, 0x12, 0x2e, 0x0a, 0x12, 0x73, 0x70, 0x65,
0x22, 0xa8, 0x03, 0x0a, 0x12, 0x54, 0x72, 0x61, 0x69, 0x6e, 0x45, 0x6e, 0x64, 0x73, 0x53, 0x74, 0x65, 0x64, 0x53, 0x65, 0x6e, 0x73, 0x6f, 0x72, 0x45, 0x6e, 0x61, 0x62, 0x6c, 0x65, 0x41, 0x18,
0x61, 0x74, 0x65, 0x4d, 0x71, 0x74, 0x74, 0x12, 0x2e, 0x0a, 0x12, 0x73, 0x70, 0x65, 0x65, 0x64, 0x01, 0x20, 0x01, 0x28, 0x08, 0x52, 0x12, 0x73, 0x70, 0x65, 0x65, 0x64, 0x53, 0x65, 0x6e, 0x73,
0x53, 0x65, 0x6e, 0x73, 0x6f, 0x72, 0x45, 0x6e, 0x61, 0x62, 0x6c, 0x65, 0x41, 0x18, 0x01, 0x20, 0x6f, 0x72, 0x45, 0x6e, 0x61, 0x62, 0x6c, 0x65, 0x41, 0x12, 0x2e, 0x0a, 0x12, 0x73, 0x70, 0x65,
0x01, 0x28, 0x08, 0x52, 0x12, 0x73, 0x70, 0x65, 0x65, 0x64, 0x53, 0x65, 0x6e, 0x73, 0x6f, 0x72, 0x65, 0x64, 0x53, 0x65, 0x6e, 0x73, 0x6f, 0x72, 0x45, 0x6e, 0x61, 0x62, 0x6c, 0x65, 0x42, 0x18,
0x45, 0x6e, 0x61, 0x62, 0x6c, 0x65, 0x41, 0x12, 0x2e, 0x0a, 0x12, 0x73, 0x70, 0x65, 0x65, 0x64, 0x02, 0x20, 0x01, 0x28, 0x08, 0x52, 0x12, 0x73, 0x70, 0x65, 0x65, 0x64, 0x53, 0x65, 0x6e, 0x73,
0x53, 0x65, 0x6e, 0x73, 0x6f, 0x72, 0x45, 0x6e, 0x61, 0x62, 0x6c, 0x65, 0x42, 0x18, 0x02, 0x20, 0x6f, 0x72, 0x45, 0x6e, 0x61, 0x62, 0x6c, 0x65, 0x42, 0x12, 0x20, 0x0a, 0x0b, 0x72, 0x61, 0x64,
0x01, 0x28, 0x08, 0x52, 0x12, 0x73, 0x70, 0x65, 0x65, 0x64, 0x53, 0x65, 0x6e, 0x73, 0x6f, 0x72, 0x61, 0x72, 0x45, 0x6e, 0x61, 0x62, 0x6c, 0x65, 0x18, 0x03, 0x20, 0x01, 0x28, 0x08, 0x52, 0x0b,
0x45, 0x6e, 0x61, 0x62, 0x6c, 0x65, 0x42, 0x12, 0x20, 0x0a, 0x0b, 0x72, 0x61, 0x64, 0x61, 0x72, 0x72, 0x61, 0x64, 0x61, 0x72, 0x45, 0x6e, 0x61, 0x62, 0x6c, 0x65, 0x12, 0x30, 0x0a, 0x13, 0x72,
0x45, 0x6e, 0x61, 0x62, 0x6c, 0x65, 0x18, 0x03, 0x20, 0x01, 0x28, 0x08, 0x52, 0x0b, 0x72, 0x61, 0x61, 0x64, 0x61, 0x72, 0x43, 0x68, 0x65, 0x63, 0x6b, 0x53, 0x70, 0x65, 0x65, 0x64, 0x44, 0x69,
0x64, 0x61, 0x72, 0x45, 0x6e, 0x61, 0x62, 0x6c, 0x65, 0x12, 0x30, 0x0a, 0x13, 0x72, 0x61, 0x64, 0x66, 0x66, 0x18, 0x04, 0x20, 0x01, 0x28, 0x09, 0x52, 0x13, 0x72, 0x61, 0x64, 0x61, 0x72, 0x43,
0x61, 0x72, 0x43, 0x68, 0x65, 0x63, 0x6b, 0x53, 0x70, 0x65, 0x65, 0x64, 0x44, 0x69, 0x66, 0x66, 0x68, 0x65, 0x63, 0x6b, 0x53, 0x70, 0x65, 0x65, 0x64, 0x44, 0x69, 0x66, 0x66, 0x12, 0x26, 0x0a,
0x18, 0x04, 0x20, 0x01, 0x28, 0x09, 0x52, 0x13, 0x72, 0x61, 0x64, 0x61, 0x72, 0x43, 0x68, 0x65, 0x0e, 0x72, 0x61, 0x64, 0x61, 0x72, 0x43, 0x68, 0x65, 0x63, 0x6b, 0x54, 0x69, 0x6d, 0x65, 0x18,
0x63, 0x6b, 0x53, 0x70, 0x65, 0x65, 0x64, 0x44, 0x69, 0x66, 0x66, 0x12, 0x26, 0x0a, 0x0e, 0x72, 0x05, 0x20, 0x01, 0x28, 0x05, 0x52, 0x0e, 0x72, 0x61, 0x64, 0x61, 0x72, 0x43, 0x68, 0x65, 0x63,
0x61, 0x64, 0x61, 0x72, 0x43, 0x68, 0x65, 0x63, 0x6b, 0x54, 0x69, 0x6d, 0x65, 0x18, 0x05, 0x20, 0x6b, 0x54, 0x69, 0x6d, 0x65, 0x12, 0x1c, 0x0a, 0x09, 0x61, 0x63, 0x63, 0x45, 0x6e, 0x61, 0x62,
0x01, 0x28, 0x05, 0x52, 0x0e, 0x72, 0x61, 0x64, 0x61, 0x72, 0x43, 0x68, 0x65, 0x63, 0x6b, 0x54, 0x6c, 0x65, 0x18, 0x06, 0x20, 0x01, 0x28, 0x08, 0x52, 0x09, 0x61, 0x63, 0x63, 0x45, 0x6e, 0x61,
0x69, 0x6d, 0x65, 0x12, 0x1c, 0x0a, 0x09, 0x61, 0x63, 0x63, 0x45, 0x6e, 0x61, 0x62, 0x6c, 0x65, 0x62, 0x6c, 0x65, 0x12, 0x2c, 0x0a, 0x11, 0x61, 0x63, 0x63, 0x43, 0x68, 0x65, 0x63, 0x6b, 0x53,
0x18, 0x06, 0x20, 0x01, 0x28, 0x08, 0x52, 0x09, 0x61, 0x63, 0x63, 0x45, 0x6e, 0x61, 0x62, 0x6c, 0x70, 0x65, 0x65, 0x64, 0x44, 0x69, 0x66, 0x66, 0x18, 0x07, 0x20, 0x01, 0x28, 0x09, 0x52, 0x11,
0x65, 0x12, 0x2c, 0x0a, 0x11, 0x61, 0x63, 0x63, 0x43, 0x68, 0x65, 0x63, 0x6b, 0x53, 0x70, 0x65, 0x61, 0x63, 0x63, 0x43, 0x68, 0x65, 0x63, 0x6b, 0x53, 0x70, 0x65, 0x65, 0x64, 0x44, 0x69, 0x66,
0x65, 0x64, 0x44, 0x69, 0x66, 0x66, 0x18, 0x07, 0x20, 0x01, 0x28, 0x09, 0x52, 0x11, 0x61, 0x63, 0x66, 0x12, 0x22, 0x0a, 0x0c, 0x61, 0x63, 0x63, 0x43, 0x68, 0x65, 0x63, 0x6b, 0x54, 0x69, 0x6d,
0x63, 0x43, 0x68, 0x65, 0x63, 0x6b, 0x53, 0x70, 0x65, 0x65, 0x64, 0x44, 0x69, 0x66, 0x66, 0x12, 0x65, 0x18, 0x08, 0x20, 0x01, 0x28, 0x05, 0x52, 0x0c, 0x61, 0x63, 0x63, 0x43, 0x68, 0x65, 0x63,
0x22, 0x0a, 0x0c, 0x61, 0x63, 0x63, 0x43, 0x68, 0x65, 0x63, 0x6b, 0x54, 0x69, 0x6d, 0x65, 0x18, 0x6b, 0x54, 0x69, 0x6d, 0x65, 0x12, 0x20, 0x0a, 0x0b, 0x61, 0x63, 0x63, 0x4f, 0x75, 0x74, 0x53,
0x08, 0x20, 0x01, 0x28, 0x05, 0x52, 0x0c, 0x61, 0x63, 0x63, 0x43, 0x68, 0x65, 0x63, 0x6b, 0x54, 0x70, 0x65, 0x65, 0x64, 0x18, 0x09, 0x20, 0x01, 0x28, 0x05, 0x52, 0x0b, 0x61, 0x63, 0x63, 0x4f,
0x69, 0x6d, 0x65, 0x12, 0x20, 0x0a, 0x0b, 0x61, 0x63, 0x63, 0x4f, 0x75, 0x74, 0x53, 0x70, 0x65, 0x75, 0x74, 0x53, 0x70, 0x65, 0x65, 0x64, 0x12, 0x24, 0x0a, 0x0d, 0x72, 0x61, 0x64, 0x61, 0x72,
0x65, 0x64, 0x18, 0x09, 0x20, 0x01, 0x28, 0x05, 0x52, 0x0b, 0x61, 0x63, 0x63, 0x4f, 0x75, 0x74, 0x4f, 0x75, 0x74, 0x53, 0x70, 0x65, 0x65, 0x64, 0x18, 0x0a, 0x20, 0x01, 0x28, 0x05, 0x52, 0x0d,
0x53, 0x70, 0x65, 0x65, 0x64, 0x12, 0x24, 0x0a, 0x0d, 0x72, 0x61, 0x64, 0x61, 0x72, 0x4f, 0x75, 0x72, 0x61, 0x64, 0x61, 0x72, 0x4f, 0x75, 0x74, 0x53, 0x70, 0x65, 0x65, 0x64, 0x22, 0x56, 0x0a,
0x74, 0x53, 0x70, 0x65, 0x65, 0x64, 0x18, 0x0a, 0x20, 0x01, 0x28, 0x05, 0x52, 0x0d, 0x72, 0x61, 0x0a, 0x52, 0x65, 0x70, 0x6c, 0x79, 0x53, 0x74, 0x61, 0x74, 0x65, 0x12, 0x0e, 0x0a, 0x02, 0x69,
0x64, 0x61, 0x72, 0x4f, 0x75, 0x74, 0x53, 0x70, 0x65, 0x65, 0x64, 0x22, 0x56, 0x0a, 0x0a, 0x52, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x02, 0x69, 0x64, 0x12, 0x0e, 0x0a, 0x02, 0x78,
0x65, 0x70, 0x6c, 0x79, 0x53, 0x74, 0x61, 0x74, 0x65, 0x12, 0x0e, 0x0a, 0x02, 0x69, 0x64, 0x18, 0x68, 0x18, 0x02, 0x20, 0x01, 0x28, 0x08, 0x52, 0x02, 0x78, 0x68, 0x12, 0x12, 0x0a, 0x04, 0x63,
0x01, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x02, 0x69, 0x64, 0x12, 0x0e, 0x0a, 0x02, 0x78, 0x68, 0x18, 0x6f, 0x64, 0x65, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x63, 0x6f, 0x64, 0x65, 0x12,
0x02, 0x20, 0x01, 0x28, 0x08, 0x52, 0x02, 0x78, 0x68, 0x12, 0x12, 0x0a, 0x04, 0x63, 0x6f, 0x64, 0x14, 0x0a, 0x05, 0x66, 0x6f, 0x72, 0x63, 0x65, 0x18, 0x04, 0x20, 0x01, 0x28, 0x08, 0x52, 0x05,
0x65, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x63, 0x6f, 0x64, 0x65, 0x12, 0x14, 0x0a, 0x66, 0x6f, 0x72, 0x63, 0x65, 0x22, 0x49, 0x0a, 0x0b, 0x42, 0x75, 0x74, 0x74, 0x6f, 0x6e, 0x53,
0x05, 0x66, 0x6f, 0x72, 0x63, 0x65, 0x18, 0x04, 0x20, 0x01, 0x28, 0x08, 0x52, 0x05, 0x66, 0x6f, 0x74, 0x61, 0x74, 0x65, 0x12, 0x0e, 0x0a, 0x02, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0d,
0x72, 0x63, 0x65, 0x22, 0x49, 0x0a, 0x0b, 0x42, 0x75, 0x74, 0x74, 0x6f, 0x6e, 0x53, 0x74, 0x61, 0x52, 0x02, 0x69, 0x64, 0x12, 0x12, 0x0a, 0x04, 0x64, 0x6f, 0x77, 0x6e, 0x18, 0x02, 0x20, 0x01,
0x74, 0x65, 0x12, 0x0e, 0x0a, 0x02, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x02, 0x28, 0x08, 0x52, 0x04, 0x64, 0x6f, 0x77, 0x6e, 0x12, 0x16, 0x0a, 0x06, 0x61, 0x63, 0x74, 0x69,
0x69, 0x64, 0x12, 0x12, 0x0a, 0x04, 0x64, 0x6f, 0x77, 0x6e, 0x18, 0x02, 0x20, 0x01, 0x28, 0x08, 0x76, 0x65, 0x18, 0x03, 0x20, 0x01, 0x28, 0x08, 0x52, 0x06, 0x61, 0x63, 0x74, 0x69, 0x76, 0x65,
0x52, 0x04, 0x64, 0x6f, 0x77, 0x6e, 0x12, 0x16, 0x0a, 0x06, 0x61, 0x63, 0x74, 0x69, 0x76, 0x65, 0x22, 0x34, 0x0a, 0x0a, 0x41, 0x6c, 0x61, 0x72, 0x6d, 0x53, 0x74, 0x61, 0x74, 0x65, 0x12, 0x0e,
0x18, 0x03, 0x20, 0x01, 0x28, 0x08, 0x52, 0x06, 0x61, 0x63, 0x74, 0x69, 0x76, 0x65, 0x22, 0x34, 0x0a, 0x02, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x02, 0x69, 0x64, 0x12, 0x16,
0x0a, 0x0a, 0x41, 0x6c, 0x61, 0x72, 0x6d, 0x53, 0x74, 0x61, 0x74, 0x65, 0x12, 0x0e, 0x0a, 0x02, 0x0a, 0x06, 0x61, 0x63, 0x74, 0x69, 0x76, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x08, 0x52, 0x06,
0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x02, 0x69, 0x64, 0x12, 0x16, 0x0a, 0x06, 0x61, 0x63, 0x74, 0x69, 0x76, 0x65, 0x22, 0x34, 0x0a, 0x0a, 0x4c, 0x69, 0x67, 0x68, 0x74, 0x53,
0x61, 0x63, 0x74, 0x69, 0x76, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x08, 0x52, 0x06, 0x61, 0x63, 0x74, 0x61, 0x74, 0x65, 0x12, 0x0e, 0x0a, 0x02, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0d,
0x74, 0x69, 0x76, 0x65, 0x22, 0x34, 0x0a, 0x0a, 0x4c, 0x69, 0x67, 0x68, 0x74, 0x53, 0x74, 0x61, 0x52, 0x02, 0x69, 0x64, 0x12, 0x16, 0x0a, 0x06, 0x61, 0x63, 0x74, 0x69, 0x76, 0x65, 0x18, 0x02,
0x74, 0x65, 0x12, 0x0e, 0x0a, 0x02, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x02, 0x20, 0x01, 0x28, 0x08, 0x52, 0x06, 0x61, 0x63, 0x74, 0x69, 0x76, 0x65, 0x22, 0x96, 0x01, 0x0a,
0x69, 0x64, 0x12, 0x16, 0x0a, 0x06, 0x61, 0x63, 0x74, 0x69, 0x76, 0x65, 0x18, 0x02, 0x20, 0x01, 0x08, 0x50, 0x73, 0x64, 0x53, 0x74, 0x61, 0x74, 0x65, 0x12, 0x0e, 0x0a, 0x02, 0x69, 0x64, 0x18,
0x28, 0x08, 0x52, 0x06, 0x61, 0x63, 0x74, 0x69, 0x76, 0x65, 0x22, 0x96, 0x01, 0x0a, 0x08, 0x50, 0x01, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x02, 0x69, 0x64, 0x12, 0x2d, 0x0a, 0x09, 0x61, 0x73, 0x64,
0x73, 0x64, 0x53, 0x74, 0x61, 0x74, 0x65, 0x12, 0x0e, 0x0a, 0x02, 0x69, 0x64, 0x18, 0x01, 0x20, 0x53, 0x74, 0x61, 0x74, 0x65, 0x73, 0x18, 0x02, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x0f, 0x2e, 0x73,
0x01, 0x28, 0x0d, 0x52, 0x02, 0x69, 0x64, 0x12, 0x2d, 0x0a, 0x09, 0x61, 0x73, 0x64, 0x53, 0x74, 0x74, 0x61, 0x74, 0x65, 0x2e, 0x41, 0x73, 0x64, 0x53, 0x74, 0x61, 0x74, 0x65, 0x52, 0x09, 0x61,
0x61, 0x74, 0x65, 0x73, 0x18, 0x02, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x0f, 0x2e, 0x73, 0x74, 0x61, 0x73, 0x64, 0x53, 0x74, 0x61, 0x74, 0x65, 0x73, 0x12, 0x10, 0x0a, 0x03, 0x6d, 0x67, 0x6a, 0x18,
0x74, 0x65, 0x2e, 0x41, 0x73, 0x64, 0x53, 0x74, 0x61, 0x74, 0x65, 0x52, 0x09, 0x61, 0x73, 0x64, 0x03, 0x20, 0x01, 0x28, 0x08, 0x52, 0x03, 0x6d, 0x67, 0x6a, 0x12, 0x27, 0x0a, 0x05, 0x70, 0x61,
0x53, 0x74, 0x61, 0x74, 0x65, 0x73, 0x12, 0x10, 0x0a, 0x03, 0x6d, 0x67, 0x6a, 0x18, 0x03, 0x20, 0x72, 0x61, 0x6d, 0x18, 0x04, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x11, 0x2e, 0x72, 0x65, 0x71, 0x75,
0x01, 0x28, 0x08, 0x52, 0x03, 0x6d, 0x67, 0x6a, 0x12, 0x27, 0x0a, 0x05, 0x70, 0x61, 0x72, 0x61, 0x65, 0x73, 0x74, 0x2e, 0x50, 0x73, 0x64, 0x50, 0x61, 0x72, 0x61, 0x6d, 0x52, 0x05, 0x70, 0x61,
0x6d, 0x18, 0x04, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x11, 0x2e, 0x72, 0x65, 0x71, 0x75, 0x65, 0x73, 0x72, 0x61, 0x6d, 0x12, 0x10, 0x0a, 0x03, 0x7a, 0x61, 0x77, 0x18, 0x05, 0x20, 0x01, 0x28, 0x08,
0x74, 0x2e, 0x50, 0x73, 0x64, 0x50, 0x61, 0x72, 0x61, 0x6d, 0x52, 0x05, 0x70, 0x61, 0x72, 0x61, 0x52, 0x03, 0x7a, 0x61, 0x77, 0x22, 0x80, 0x01, 0x0a, 0x08, 0x41, 0x73, 0x64, 0x53, 0x74, 0x61,
0x6d, 0x12, 0x10, 0x0a, 0x03, 0x7a, 0x61, 0x77, 0x18, 0x05, 0x20, 0x01, 0x28, 0x08, 0x52, 0x03, 0x74, 0x65, 0x12, 0x12, 0x0a, 0x04, 0x63, 0x6f, 0x64, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x05,
0x7a, 0x61, 0x77, 0x22, 0x80, 0x01, 0x0a, 0x08, 0x41, 0x73, 0x64, 0x53, 0x74, 0x61, 0x74, 0x65, 0x52, 0x04, 0x63, 0x6f, 0x64, 0x65, 0x12, 0x12, 0x0a, 0x04, 0x6b, 0x6d, 0x64, 0x77, 0x18, 0x02,
0x12, 0x12, 0x0a, 0x04, 0x63, 0x6f, 0x64, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x05, 0x52, 0x04, 0x20, 0x01, 0x28, 0x08, 0x52, 0x04, 0x6b, 0x6d, 0x64, 0x77, 0x12, 0x12, 0x0a, 0x04, 0x67, 0x6d,
0x63, 0x6f, 0x64, 0x65, 0x12, 0x12, 0x0a, 0x04, 0x6b, 0x6d, 0x64, 0x77, 0x18, 0x02, 0x20, 0x01, 0x64, 0x77, 0x18, 0x03, 0x20, 0x01, 0x28, 0x08, 0x52, 0x04, 0x67, 0x6d, 0x64, 0x77, 0x12, 0x10,
0x28, 0x08, 0x52, 0x04, 0x6b, 0x6d, 0x64, 0x77, 0x12, 0x12, 0x0a, 0x04, 0x67, 0x6d, 0x64, 0x77, 0x0a, 0x03, 0x6d, 0x67, 0x6a, 0x18, 0x04, 0x20, 0x01, 0x28, 0x08, 0x52, 0x03, 0x6d, 0x67, 0x6a,
0x18, 0x03, 0x20, 0x01, 0x28, 0x08, 0x52, 0x04, 0x67, 0x6d, 0x64, 0x77, 0x12, 0x10, 0x0a, 0x03, 0x12, 0x10, 0x0a, 0x03, 0x7a, 0x61, 0x77, 0x18, 0x05, 0x20, 0x01, 0x28, 0x08, 0x52, 0x03, 0x7a,
0x6d, 0x67, 0x6a, 0x18, 0x04, 0x20, 0x01, 0x28, 0x08, 0x52, 0x03, 0x6d, 0x67, 0x6a, 0x12, 0x10, 0x61, 0x77, 0x12, 0x14, 0x0a, 0x05, 0x66, 0x6f, 0x72, 0x63, 0x65, 0x18, 0x06, 0x20, 0x01, 0x28,
0x0a, 0x03, 0x7a, 0x61, 0x77, 0x18, 0x05, 0x20, 0x01, 0x28, 0x08, 0x52, 0x03, 0x7a, 0x61, 0x77, 0x08, 0x52, 0x05, 0x66, 0x6f, 0x72, 0x63, 0x65, 0x22, 0x2e, 0x0a, 0x08, 0x4b, 0x65, 0x79, 0x53,
0x12, 0x14, 0x0a, 0x05, 0x66, 0x6f, 0x72, 0x63, 0x65, 0x18, 0x06, 0x20, 0x01, 0x28, 0x08, 0x52, 0x74, 0x61, 0x74, 0x65, 0x12, 0x0e, 0x0a, 0x02, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0d,
0x05, 0x66, 0x6f, 0x72, 0x63, 0x65, 0x22, 0x2e, 0x0a, 0x08, 0x4b, 0x65, 0x79, 0x53, 0x74, 0x61, 0x52, 0x02, 0x69, 0x64, 0x12, 0x12, 0x0a, 0x04, 0x67, 0x65, 0x61, 0x72, 0x18, 0x02, 0x20, 0x01,
0x74, 0x65, 0x12, 0x0e, 0x0a, 0x02, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x02, 0x28, 0x05, 0x52, 0x04, 0x67, 0x65, 0x61, 0x72, 0x22, 0x52, 0x0a, 0x09, 0x4d, 0x6b, 0x78, 0x4a,
0x69, 0x64, 0x12, 0x12, 0x0a, 0x04, 0x67, 0x65, 0x61, 0x72, 0x18, 0x02, 0x20, 0x01, 0x28, 0x05, 0x53, 0x74, 0x61, 0x74, 0x65, 0x12, 0x12, 0x0a, 0x04, 0x63, 0x6f, 0x64, 0x65, 0x18, 0x01, 0x20,
0x52, 0x04, 0x67, 0x65, 0x61, 0x72, 0x22, 0x52, 0x0a, 0x09, 0x4d, 0x6b, 0x78, 0x4a, 0x53, 0x74, 0x01, 0x28, 0x09, 0x52, 0x04, 0x63, 0x6f, 0x64, 0x65, 0x12, 0x31, 0x0a, 0x0a, 0x72, 0x65, 0x70,
0x61, 0x74, 0x65, 0x12, 0x12, 0x0a, 0x04, 0x63, 0x6f, 0x64, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x6c, 0x79, 0x53, 0x74, 0x61, 0x74, 0x65, 0x18, 0x02, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x11, 0x2e,
0x09, 0x52, 0x04, 0x63, 0x6f, 0x64, 0x65, 0x12, 0x31, 0x0a, 0x0a, 0x72, 0x65, 0x70, 0x6c, 0x79, 0x73, 0x74, 0x61, 0x74, 0x65, 0x2e, 0x52, 0x65, 0x70, 0x6c, 0x79, 0x53, 0x74, 0x61, 0x74, 0x65,
0x53, 0x74, 0x61, 0x74, 0x65, 0x18, 0x02, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x11, 0x2e, 0x73, 0x74, 0x52, 0x0a, 0x72, 0x65, 0x70, 0x6c, 0x79, 0x53, 0x74, 0x61, 0x74, 0x65, 0x22, 0x93, 0x02, 0x0a,
0x61, 0x74, 0x65, 0x2e, 0x52, 0x65, 0x70, 0x6c, 0x79, 0x53, 0x74, 0x61, 0x74, 0x65, 0x52, 0x0a, 0x0b, 0x42, 0x61, 0x6c, 0x69, 0x73, 0x65, 0x53, 0x74, 0x61, 0x74, 0x65, 0x12, 0x0e, 0x0a, 0x02,
0x72, 0x65, 0x70, 0x6c, 0x79, 0x53, 0x74, 0x61, 0x74, 0x65, 0x22, 0x93, 0x02, 0x0a, 0x0b, 0x42, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x02, 0x69, 0x64, 0x12, 0x2c, 0x0a, 0x02,
0x61, 0x6c, 0x69, 0x73, 0x65, 0x53, 0x74, 0x61, 0x74, 0x65, 0x12, 0x0e, 0x0a, 0x02, 0x69, 0x64, 0x6b, 0x6d, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1c, 0x2e, 0x67, 0x72, 0x61, 0x70, 0x68,
0x18, 0x01, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x02, 0x69, 0x64, 0x12, 0x2c, 0x0a, 0x02, 0x6b, 0x6d, 0x69, 0x63, 0x44, 0x61, 0x74, 0x61, 0x2e, 0x4b, 0x69, 0x6c, 0x6f, 0x6d, 0x65, 0x74, 0x65, 0x72,
0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1c, 0x2e, 0x67, 0x72, 0x61, 0x70, 0x68, 0x69, 0x63, 0x53, 0x79, 0x73, 0x74, 0x65, 0x6d, 0x52, 0x02, 0x6b, 0x6d, 0x12, 0x24, 0x0a, 0x0d, 0x66, 0x69,
0x44, 0x61, 0x74, 0x61, 0x2e, 0x4b, 0x69, 0x6c, 0x6f, 0x6d, 0x65, 0x74, 0x65, 0x72, 0x53, 0x79, 0x78, 0x65, 0x64, 0x54, 0x65, 0x6c, 0x65, 0x67, 0x72, 0x61, 0x6d, 0x18, 0x03, 0x20, 0x01, 0x28,
0x73, 0x74, 0x65, 0x6d, 0x52, 0x02, 0x6b, 0x6d, 0x12, 0x24, 0x0a, 0x0d, 0x66, 0x69, 0x78, 0x65, 0x09, 0x52, 0x0d, 0x66, 0x69, 0x78, 0x65, 0x64, 0x54, 0x65, 0x6c, 0x65, 0x67, 0x72, 0x61, 0x6d,
0x64, 0x54, 0x65, 0x6c, 0x65, 0x67, 0x72, 0x61, 0x6d, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x12, 0x2c, 0x0a, 0x11, 0x66, 0x69, 0x78, 0x65, 0x64, 0x55, 0x73, 0x65, 0x72, 0x54, 0x65, 0x6c,
0x0d, 0x66, 0x69, 0x78, 0x65, 0x64, 0x54, 0x65, 0x6c, 0x65, 0x67, 0x72, 0x61, 0x6d, 0x12, 0x2c, 0x65, 0x67, 0x72, 0x61, 0x6d, 0x18, 0x04, 0x20, 0x01, 0x28, 0x09, 0x52, 0x11, 0x66, 0x69, 0x78,
0x0a, 0x11, 0x66, 0x69, 0x78, 0x65, 0x64, 0x55, 0x73, 0x65, 0x72, 0x54, 0x65, 0x6c, 0x65, 0x67, 0x65, 0x64, 0x55, 0x73, 0x65, 0x72, 0x54, 0x65, 0x6c, 0x65, 0x67, 0x72, 0x61, 0x6d, 0x12, 0x2a,
0x72, 0x61, 0x6d, 0x18, 0x04, 0x20, 0x01, 0x28, 0x09, 0x52, 0x11, 0x66, 0x69, 0x78, 0x65, 0x64, 0x0a, 0x10, 0x76, 0x61, 0x72, 0x69, 0x61, 0x62, 0x6c, 0x65, 0x54, 0x65, 0x6c, 0x65, 0x67, 0x72,
0x55, 0x73, 0x65, 0x72, 0x54, 0x65, 0x6c, 0x65, 0x67, 0x72, 0x61, 0x6d, 0x12, 0x2a, 0x0a, 0x10, 0x61, 0x6d, 0x18, 0x05, 0x20, 0x01, 0x28, 0x09, 0x52, 0x10, 0x76, 0x61, 0x72, 0x69, 0x61, 0x62,
0x76, 0x61, 0x72, 0x69, 0x61, 0x62, 0x6c, 0x65, 0x54, 0x65, 0x6c, 0x65, 0x67, 0x72, 0x61, 0x6d, 0x6c, 0x65, 0x54, 0x65, 0x6c, 0x65, 0x67, 0x72, 0x61, 0x6d, 0x12, 0x32, 0x0a, 0x14, 0x76, 0x61,
0x18, 0x05, 0x20, 0x01, 0x28, 0x09, 0x52, 0x10, 0x76, 0x61, 0x72, 0x69, 0x61, 0x62, 0x6c, 0x65, 0x72, 0x69, 0x61, 0x62, 0x6c, 0x65, 0x55, 0x73, 0x65, 0x72, 0x54, 0x65, 0x6c, 0x65, 0x67, 0x72,
0x54, 0x65, 0x6c, 0x65, 0x67, 0x72, 0x61, 0x6d, 0x12, 0x32, 0x0a, 0x14, 0x76, 0x61, 0x72, 0x69, 0x61, 0x6d, 0x18, 0x06, 0x20, 0x01, 0x28, 0x09, 0x52, 0x14, 0x76, 0x61, 0x72, 0x69, 0x61, 0x62,
0x61, 0x62, 0x6c, 0x65, 0x55, 0x73, 0x65, 0x72, 0x54, 0x65, 0x6c, 0x65, 0x67, 0x72, 0x61, 0x6d, 0x6c, 0x65, 0x55, 0x73, 0x65, 0x72, 0x54, 0x65, 0x6c, 0x65, 0x67, 0x72, 0x61, 0x6d, 0x12, 0x12,
0x18, 0x06, 0x20, 0x01, 0x28, 0x09, 0x52, 0x14, 0x76, 0x61, 0x72, 0x69, 0x61, 0x62, 0x6c, 0x65, 0x0a, 0x04, 0x77, 0x6f, 0x72, 0x6b, 0x18, 0x07, 0x20, 0x01, 0x28, 0x08, 0x52, 0x04, 0x77, 0x6f,
0x55, 0x73, 0x65, 0x72, 0x54, 0x65, 0x6c, 0x65, 0x67, 0x72, 0x61, 0x6d, 0x12, 0x12, 0x0a, 0x04, 0x72, 0x6b, 0x22, 0xb0, 0x01, 0x0a, 0x09, 0x53, 0x74, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x51, 0x63,
0x77, 0x6f, 0x72, 0x6b, 0x18, 0x07, 0x20, 0x01, 0x28, 0x08, 0x52, 0x04, 0x77, 0x6f, 0x72, 0x6b, 0x12, 0x32, 0x0a, 0x08, 0x71, 0x64, 0x53, 0x74, 0x61, 0x74, 0x65, 0x73, 0x18, 0x01, 0x20, 0x03,
0x22, 0xb0, 0x01, 0x0a, 0x09, 0x53, 0x74, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x51, 0x63, 0x12, 0x32, 0x28, 0x0b, 0x32, 0x16, 0x2e, 0x73, 0x74, 0x61, 0x74, 0x65, 0x2e, 0x53, 0x74, 0x61, 0x74, 0x69,
0x0a, 0x08, 0x71, 0x64, 0x53, 0x74, 0x61, 0x74, 0x65, 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, 0x6f, 0x6e, 0x51, 0x63, 0x2e, 0x53, 0x74, 0x61, 0x74, 0x65, 0x52, 0x08, 0x71, 0x64, 0x53, 0x74,
0x32, 0x16, 0x2e, 0x73, 0x74, 0x61, 0x74, 0x65, 0x2e, 0x53, 0x74, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x61, 0x74, 0x65, 0x73, 0x12, 0x32, 0x0a, 0x08, 0x63, 0x6a, 0x53, 0x74, 0x61, 0x74, 0x65, 0x73,
0x51, 0x63, 0x2e, 0x53, 0x74, 0x61, 0x74, 0x65, 0x52, 0x08, 0x71, 0x64, 0x53, 0x74, 0x61, 0x74, 0x18, 0x02, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x16, 0x2e, 0x73, 0x74, 0x61, 0x74, 0x65, 0x2e, 0x53,
0x65, 0x73, 0x12, 0x32, 0x0a, 0x08, 0x63, 0x6a, 0x53, 0x74, 0x61, 0x74, 0x65, 0x73, 0x18, 0x02, 0x74, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x51, 0x63, 0x2e, 0x53, 0x74, 0x61, 0x74, 0x65, 0x52, 0x08,
0x20, 0x03, 0x28, 0x0b, 0x32, 0x16, 0x2e, 0x73, 0x74, 0x61, 0x74, 0x65, 0x2e, 0x53, 0x74, 0x61, 0x63, 0x6a, 0x53, 0x74, 0x61, 0x74, 0x65, 0x73, 0x1a, 0x3b, 0x0a, 0x05, 0x53, 0x74, 0x61, 0x74,
0x74, 0x69, 0x6f, 0x6e, 0x51, 0x63, 0x2e, 0x53, 0x74, 0x61, 0x74, 0x65, 0x52, 0x08, 0x63, 0x6a, 0x65, 0x12, 0x10, 0x0a, 0x03, 0x72, 0x6f, 0x77, 0x18, 0x01, 0x20, 0x01, 0x28, 0x05, 0x52, 0x03,
0x53, 0x74, 0x61, 0x74, 0x65, 0x73, 0x1a, 0x3b, 0x0a, 0x05, 0x53, 0x74, 0x61, 0x74, 0x65, 0x12, 0x72, 0x6f, 0x77, 0x12, 0x10, 0x0a, 0x03, 0x63, 0x6f, 0x6c, 0x18, 0x02, 0x20, 0x01, 0x28, 0x05,
0x10, 0x0a, 0x03, 0x72, 0x6f, 0x77, 0x18, 0x01, 0x20, 0x01, 0x28, 0x05, 0x52, 0x03, 0x72, 0x6f, 0x52, 0x03, 0x63, 0x6f, 0x6c, 0x12, 0x0e, 0x0a, 0x02, 0x6f, 0x6e, 0x18, 0x03, 0x20, 0x01, 0x28,
0x77, 0x12, 0x10, 0x0a, 0x03, 0x63, 0x6f, 0x6c, 0x18, 0x02, 0x20, 0x01, 0x28, 0x05, 0x52, 0x03, 0x08, 0x52, 0x02, 0x6f, 0x6e, 0x22, 0x7f, 0x0a, 0x08, 0x43, 0x6b, 0x6d, 0x53, 0x74, 0x61, 0x74,
0x63, 0x6f, 0x6c, 0x12, 0x0e, 0x0a, 0x02, 0x6f, 0x6e, 0x18, 0x03, 0x20, 0x01, 0x28, 0x08, 0x52,
0x02, 0x6f, 0x6e, 0x22, 0x7f, 0x0a, 0x08, 0x43, 0x6b, 0x6d, 0x53, 0x74, 0x61, 0x74, 0x65, 0x12,
0x0e, 0x0a, 0x02, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x02, 0x69, 0x64, 0x12,
0x10, 0x0a, 0x03, 0x6d, 0x67, 0x6a, 0x18, 0x02, 0x20, 0x01, 0x28, 0x08, 0x52, 0x03, 0x6d, 0x67,
0x6a, 0x12, 0x27, 0x0a, 0x05, 0x70, 0x61, 0x72, 0x61, 0x6d, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0b,
0x32, 0x11, 0x2e, 0x72, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x2e, 0x43, 0x6b, 0x6d, 0x50, 0x61,
0x72, 0x61, 0x6d, 0x52, 0x05, 0x70, 0x61, 0x72, 0x61, 0x6d, 0x12, 0x14, 0x0a, 0x05, 0x6c, 0x6f,
0x63, 0x61, 0x6c, 0x18, 0x04, 0x20, 0x01, 0x28, 0x08, 0x52, 0x05, 0x6c, 0x6f, 0x63, 0x61, 0x6c,
0x12, 0x12, 0x0a, 0x04, 0x6d, 0x70, 0x6c, 0x6a, 0x18, 0x05, 0x20, 0x01, 0x28, 0x08, 0x52, 0x04,
0x6d, 0x70, 0x6c, 0x6a, 0x22, 0xf1, 0x01, 0x0a, 0x08, 0x58, 0x63, 0x6a, 0x53, 0x74, 0x61, 0x74,
0x65, 0x12, 0x0e, 0x0a, 0x02, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x02, 0x69, 0x65, 0x12, 0x0e, 0x0a, 0x02, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x02, 0x69,
0x64, 0x12, 0x27, 0x0a, 0x05, 0x70, 0x61, 0x72, 0x61, 0x6d, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x64, 0x12, 0x10, 0x0a, 0x03, 0x6d, 0x67, 0x6a, 0x18, 0x02, 0x20, 0x01, 0x28, 0x08, 0x52, 0x03,
0x32, 0x11, 0x2e, 0x72, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x2e, 0x58, 0x63, 0x6a, 0x50, 0x61, 0x6d, 0x67, 0x6a, 0x12, 0x27, 0x0a, 0x05, 0x70, 0x61, 0x72, 0x61, 0x6d, 0x18, 0x03, 0x20, 0x01,
0x72, 0x61, 0x6d, 0x52, 0x05, 0x70, 0x61, 0x72, 0x61, 0x6d, 0x12, 0x10, 0x0a, 0x03, 0x78, 0x71, 0x28, 0x0b, 0x32, 0x11, 0x2e, 0x72, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x2e, 0x43, 0x6b, 0x6d,
0x6a, 0x18, 0x03, 0x20, 0x01, 0x28, 0x08, 0x52, 0x03, 0x78, 0x71, 0x6a, 0x12, 0x18, 0x0a, 0x07, 0x50, 0x61, 0x72, 0x61, 0x6d, 0x52, 0x05, 0x70, 0x61, 0x72, 0x61, 0x6d, 0x12, 0x14, 0x0a, 0x05,
0x74, 0x77, 0x6a, 0x4c, 0x69, 0x73, 0x74, 0x18, 0x04, 0x20, 0x03, 0x28, 0x08, 0x52, 0x07, 0x74, 0x6c, 0x6f, 0x63, 0x61, 0x6c, 0x18, 0x04, 0x20, 0x01, 0x28, 0x08, 0x52, 0x05, 0x6c, 0x6f, 0x63,
0x77, 0x6a, 0x4c, 0x69, 0x73, 0x74, 0x12, 0x12, 0x0a, 0x04, 0x74, 0x67, 0x71, 0x6a, 0x18, 0x05, 0x61, 0x6c, 0x12, 0x12, 0x0a, 0x04, 0x6d, 0x70, 0x6c, 0x6a, 0x18, 0x05, 0x20, 0x01, 0x28, 0x08,
0x20, 0x01, 0x28, 0x08, 0x52, 0x04, 0x74, 0x67, 0x71, 0x6a, 0x12, 0x14, 0x0a, 0x05, 0x78, 0x63, 0x52, 0x04, 0x6d, 0x70, 0x6c, 0x6a, 0x22, 0xf1, 0x01, 0x0a, 0x08, 0x58, 0x63, 0x6a, 0x53, 0x74,
0x6a, 0x78, 0x6a, 0x18, 0x06, 0x20, 0x01, 0x28, 0x08, 0x52, 0x05, 0x78, 0x63, 0x6a, 0x78, 0x6a, 0x61, 0x74, 0x65, 0x12, 0x0e, 0x0a, 0x02, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0d, 0x52,
0x12, 0x14, 0x0a, 0x05, 0x78, 0x63, 0x79, 0x78, 0x6a, 0x18, 0x07, 0x20, 0x01, 0x28, 0x08, 0x52, 0x02, 0x69, 0x64, 0x12, 0x27, 0x0a, 0x05, 0x70, 0x61, 0x72, 0x61, 0x6d, 0x18, 0x02, 0x20, 0x01,
0x05, 0x78, 0x63, 0x79, 0x78, 0x6a, 0x12, 0x18, 0x0a, 0x07, 0x63, 0x66, 0x6a, 0x4c, 0x69, 0x73, 0x28, 0x0b, 0x32, 0x11, 0x2e, 0x72, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x2e, 0x58, 0x63, 0x6a,
0x74, 0x18, 0x08, 0x20, 0x03, 0x28, 0x08, 0x52, 0x07, 0x63, 0x66, 0x6a, 0x4c, 0x69, 0x73, 0x74, 0x50, 0x61, 0x72, 0x61, 0x6d, 0x52, 0x05, 0x70, 0x61, 0x72, 0x61, 0x6d, 0x12, 0x10, 0x0a, 0x03,
0x12, 0x10, 0x0a, 0x03, 0x6a, 0x74, 0x6a, 0x18, 0x09, 0x20, 0x01, 0x28, 0x08, 0x52, 0x03, 0x6a, 0x78, 0x71, 0x6a, 0x18, 0x03, 0x20, 0x01, 0x28, 0x08, 0x52, 0x03, 0x78, 0x71, 0x6a, 0x12, 0x18,
0x74, 0x6a, 0x12, 0x14, 0x0a, 0x05, 0x74, 0x67, 0x79, 0x78, 0x6a, 0x18, 0x0a, 0x20, 0x01, 0x28, 0x0a, 0x07, 0x74, 0x77, 0x6a, 0x4c, 0x69, 0x73, 0x74, 0x18, 0x04, 0x20, 0x03, 0x28, 0x08, 0x52,
0x08, 0x52, 0x05, 0x74, 0x67, 0x79, 0x78, 0x6a, 0x22, 0xa1, 0x02, 0x0a, 0x0f, 0x56, 0x61, 0x72, 0x07, 0x74, 0x77, 0x6a, 0x4c, 0x69, 0x73, 0x74, 0x12, 0x12, 0x0a, 0x04, 0x74, 0x67, 0x71, 0x6a,
0x69, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x12, 0x38, 0x0a, 0x0c, 0x18, 0x05, 0x20, 0x01, 0x28, 0x08, 0x52, 0x04, 0x74, 0x67, 0x71, 0x6a, 0x12, 0x14, 0x0a, 0x05,
0x75, 0x70, 0x64, 0x61, 0x74, 0x65, 0x64, 0x54, 0x72, 0x61, 0x69, 0x6e, 0x18, 0x01, 0x20, 0x03, 0x78, 0x63, 0x6a, 0x78, 0x6a, 0x18, 0x06, 0x20, 0x01, 0x28, 0x08, 0x52, 0x05, 0x78, 0x63, 0x6a,
0x28, 0x0b, 0x32, 0x14, 0x2e, 0x73, 0x74, 0x61, 0x74, 0x65, 0x2e, 0x54, 0x72, 0x61, 0x69, 0x6e, 0x78, 0x6a, 0x12, 0x14, 0x0a, 0x05, 0x78, 0x63, 0x79, 0x78, 0x6a, 0x18, 0x07, 0x20, 0x01, 0x28,
0x4d, 0x61, 0x70, 0x53, 0x74, 0x61, 0x74, 0x65, 0x52, 0x0c, 0x75, 0x70, 0x64, 0x61, 0x74, 0x65, 0x08, 0x52, 0x05, 0x78, 0x63, 0x79, 0x78, 0x6a, 0x12, 0x18, 0x0a, 0x07, 0x63, 0x66, 0x6a, 0x4c,
0x64, 0x54, 0x72, 0x61, 0x69, 0x6e, 0x12, 0x26, 0x0a, 0x0e, 0x72, 0x65, 0x6d, 0x6f, 0x76, 0x65, 0x69, 0x73, 0x74, 0x18, 0x08, 0x20, 0x03, 0x28, 0x08, 0x52, 0x07, 0x63, 0x66, 0x6a, 0x4c, 0x69,
0x64, 0x54, 0x72, 0x61, 0x69, 0x6e, 0x49, 0x64, 0x18, 0x02, 0x20, 0x03, 0x28, 0x09, 0x52, 0x0e, 0x73, 0x74, 0x12, 0x10, 0x0a, 0x03, 0x6a, 0x74, 0x6a, 0x18, 0x09, 0x20, 0x01, 0x28, 0x08, 0x52,
0x72, 0x65, 0x6d, 0x6f, 0x76, 0x65, 0x64, 0x54, 0x72, 0x61, 0x69, 0x6e, 0x49, 0x64, 0x12, 0x38, 0x03, 0x6a, 0x74, 0x6a, 0x12, 0x14, 0x0a, 0x05, 0x74, 0x67, 0x79, 0x78, 0x6a, 0x18, 0x0a, 0x20,
0x0a, 0x0d, 0x75, 0x70, 0x64, 0x61, 0x74, 0x65, 0x64, 0x53, 0x77, 0x69, 0x74, 0x63, 0x68, 0x18, 0x01, 0x28, 0x08, 0x52, 0x05, 0x74, 0x67, 0x79, 0x78, 0x6a, 0x22, 0xa1, 0x02, 0x0a, 0x0f, 0x56,
0x03, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x12, 0x2e, 0x73, 0x74, 0x61, 0x74, 0x65, 0x2e, 0x53, 0x77, 0x61, 0x72, 0x69, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x12, 0x38,
0x69, 0x74, 0x63, 0x68, 0x53, 0x74, 0x61, 0x74, 0x65, 0x52, 0x0d, 0x75, 0x70, 0x64, 0x61, 0x74, 0x0a, 0x0c, 0x75, 0x70, 0x64, 0x61, 0x74, 0x65, 0x64, 0x54, 0x72, 0x61, 0x69, 0x6e, 0x18, 0x01,
0x65, 0x64, 0x53, 0x77, 0x69, 0x74, 0x63, 0x68, 0x12, 0x3b, 0x0a, 0x0e, 0x75, 0x70, 0x64, 0x61, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x14, 0x2e, 0x73, 0x74, 0x61, 0x74, 0x65, 0x2e, 0x54, 0x72, 0x61,
0x74, 0x65, 0x64, 0x53, 0x65, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x18, 0x04, 0x20, 0x03, 0x28, 0x0b, 0x69, 0x6e, 0x4d, 0x61, 0x70, 0x53, 0x74, 0x61, 0x74, 0x65, 0x52, 0x0c, 0x75, 0x70, 0x64, 0x61,
0x32, 0x13, 0x2e, 0x73, 0x74, 0x61, 0x74, 0x65, 0x2e, 0x53, 0x65, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x74, 0x65, 0x64, 0x54, 0x72, 0x61, 0x69, 0x6e, 0x12, 0x26, 0x0a, 0x0e, 0x72, 0x65, 0x6d, 0x6f,
0x53, 0x74, 0x61, 0x74, 0x65, 0x52, 0x0e, 0x75, 0x70, 0x64, 0x61, 0x74, 0x65, 0x64, 0x53, 0x65, 0x76, 0x65, 0x64, 0x54, 0x72, 0x61, 0x69, 0x6e, 0x49, 0x64, 0x18, 0x02, 0x20, 0x03, 0x28, 0x09,
0x63, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x35, 0x0a, 0x0c, 0x75, 0x70, 0x64, 0x61, 0x74, 0x65, 0x64, 0x52, 0x0e, 0x72, 0x65, 0x6d, 0x6f, 0x76, 0x65, 0x64, 0x54, 0x72, 0x61, 0x69, 0x6e, 0x49, 0x64,
0x52, 0x65, 0x70, 0x6c, 0x79, 0x18, 0x05, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x11, 0x2e, 0x73, 0x74, 0x12, 0x38, 0x0a, 0x0d, 0x75, 0x70, 0x64, 0x61, 0x74, 0x65, 0x64, 0x53, 0x77, 0x69, 0x74, 0x63,
0x61, 0x74, 0x65, 0x2e, 0x52, 0x65, 0x70, 0x6c, 0x79, 0x53, 0x74, 0x61, 0x74, 0x65, 0x52, 0x0c, 0x68, 0x18, 0x03, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x12, 0x2e, 0x73, 0x74, 0x61, 0x74, 0x65, 0x2e,
0x75, 0x70, 0x64, 0x61, 0x74, 0x65, 0x64, 0x52, 0x65, 0x70, 0x6c, 0x79, 0x22, 0xc5, 0x06, 0x0a, 0x53, 0x77, 0x69, 0x74, 0x63, 0x68, 0x53, 0x74, 0x61, 0x74, 0x65, 0x52, 0x0d, 0x75, 0x70, 0x64,
0x10, 0x41, 0x6c, 0x6c, 0x44, 0x65, 0x76, 0x69, 0x63, 0x65, 0x73, 0x53, 0x74, 0x61, 0x74, 0x75, 0x61, 0x74, 0x65, 0x64, 0x53, 0x77, 0x69, 0x74, 0x63, 0x68, 0x12, 0x3b, 0x0a, 0x0e, 0x75, 0x70,
0x73, 0x12, 0x34, 0x0a, 0x0a, 0x74, 0x72, 0x61, 0x69, 0x6e, 0x53, 0x74, 0x61, 0x74, 0x65, 0x18, 0x64, 0x61, 0x74, 0x65, 0x64, 0x53, 0x65, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x18, 0x04, 0x20, 0x03,
0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x14, 0x2e, 0x73, 0x74, 0x61, 0x74, 0x65, 0x2e, 0x54, 0x72, 0x28, 0x0b, 0x32, 0x13, 0x2e, 0x73, 0x74, 0x61, 0x74, 0x65, 0x2e, 0x53, 0x65, 0x63, 0x74, 0x69,
0x61, 0x69, 0x6e, 0x4d, 0x61, 0x70, 0x53, 0x74, 0x61, 0x74, 0x65, 0x52, 0x0a, 0x74, 0x72, 0x61, 0x6f, 0x6e, 0x53, 0x74, 0x61, 0x74, 0x65, 0x52, 0x0e, 0x75, 0x70, 0x64, 0x61, 0x74, 0x65, 0x64,
0x69, 0x6e, 0x53, 0x74, 0x61, 0x74, 0x65, 0x12, 0x34, 0x0a, 0x0b, 0x73, 0x77, 0x69, 0x74, 0x63, 0x53, 0x65, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x35, 0x0a, 0x0c, 0x75, 0x70, 0x64, 0x61, 0x74,
0x68, 0x53, 0x74, 0x61, 0x74, 0x65, 0x18, 0x02, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x12, 0x2e, 0x73, 0x65, 0x64, 0x52, 0x65, 0x70, 0x6c, 0x79, 0x18, 0x05, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x11, 0x2e,
0x74, 0x61, 0x74, 0x65, 0x2e, 0x53, 0x77, 0x69, 0x74, 0x63, 0x68, 0x53, 0x74, 0x61, 0x74, 0x65, 0x73, 0x74, 0x61, 0x74, 0x65, 0x2e, 0x52, 0x65, 0x70, 0x6c, 0x79, 0x53, 0x74, 0x61, 0x74, 0x65,
0x52, 0x0b, 0x73, 0x77, 0x69, 0x74, 0x63, 0x68, 0x53, 0x74, 0x61, 0x74, 0x65, 0x12, 0x37, 0x0a, 0x52, 0x0c, 0x75, 0x70, 0x64, 0x61, 0x74, 0x65, 0x64, 0x52, 0x65, 0x70, 0x6c, 0x79, 0x22, 0xc5,
0x0c, 0x73, 0x65, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x53, 0x74, 0x61, 0x74, 0x65, 0x18, 0x03, 0x20, 0x06, 0x0a, 0x10, 0x41, 0x6c, 0x6c, 0x44, 0x65, 0x76, 0x69, 0x63, 0x65, 0x73, 0x53, 0x74, 0x61,
0x03, 0x28, 0x0b, 0x32, 0x13, 0x2e, 0x73, 0x74, 0x61, 0x74, 0x65, 0x2e, 0x53, 0x65, 0x63, 0x74, 0x74, 0x75, 0x73, 0x12, 0x34, 0x0a, 0x0a, 0x74, 0x72, 0x61, 0x69, 0x6e, 0x53, 0x74, 0x61, 0x74,
0x69, 0x6f, 0x6e, 0x53, 0x74, 0x61, 0x74, 0x65, 0x52, 0x0c, 0x73, 0x65, 0x63, 0x74, 0x69, 0x6f, 0x65, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x14, 0x2e, 0x73, 0x74, 0x61, 0x74, 0x65, 0x2e,
0x6e, 0x53, 0x74, 0x61, 0x74, 0x65, 0x12, 0x31, 0x0a, 0x0a, 0x72, 0x65, 0x70, 0x6c, 0x79, 0x53, 0x54, 0x72, 0x61, 0x69, 0x6e, 0x4d, 0x61, 0x70, 0x53, 0x74, 0x61, 0x74, 0x65, 0x52, 0x0a, 0x74,
0x74, 0x61, 0x74, 0x65, 0x18, 0x04, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x11, 0x2e, 0x73, 0x74, 0x61, 0x72, 0x61, 0x69, 0x6e, 0x53, 0x74, 0x61, 0x74, 0x65, 0x12, 0x34, 0x0a, 0x0b, 0x73, 0x77, 0x69,
0x74, 0x65, 0x2e, 0x52, 0x65, 0x70, 0x6c, 0x79, 0x53, 0x74, 0x61, 0x74, 0x65, 0x52, 0x0a, 0x72, 0x74, 0x63, 0x68, 0x53, 0x74, 0x61, 0x74, 0x65, 0x18, 0x02, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x12,
0x65, 0x70, 0x6c, 0x79, 0x53, 0x74, 0x61, 0x74, 0x65, 0x12, 0x34, 0x0a, 0x0b, 0x73, 0x69, 0x67, 0x2e, 0x73, 0x74, 0x61, 0x74, 0x65, 0x2e, 0x53, 0x77, 0x69, 0x74, 0x63, 0x68, 0x53, 0x74, 0x61,
0x6e, 0x61, 0x6c, 0x53, 0x74, 0x61, 0x74, 0x65, 0x18, 0x05, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x12, 0x74, 0x65, 0x52, 0x0b, 0x73, 0x77, 0x69, 0x74, 0x63, 0x68, 0x53, 0x74, 0x61, 0x74, 0x65, 0x12,
0x2e, 0x73, 0x74, 0x61, 0x74, 0x65, 0x2e, 0x53, 0x69, 0x67, 0x6e, 0x61, 0x6c, 0x53, 0x74, 0x61, 0x37, 0x0a, 0x0c, 0x73, 0x65, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x53, 0x74, 0x61, 0x74, 0x65, 0x18,
0x74, 0x65, 0x52, 0x0b, 0x73, 0x69, 0x67, 0x6e, 0x61, 0x6c, 0x53, 0x74, 0x61, 0x74, 0x65, 0x12, 0x03, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x13, 0x2e, 0x73, 0x74, 0x61, 0x74, 0x65, 0x2e, 0x53, 0x65,
0x34, 0x0a, 0x0b, 0x62, 0x75, 0x74, 0x74, 0x6f, 0x6e, 0x53, 0x74, 0x61, 0x74, 0x65, 0x18, 0x06, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x53, 0x74, 0x61, 0x74, 0x65, 0x52, 0x0c, 0x73, 0x65, 0x63, 0x74,
0x20, 0x03, 0x28, 0x0b, 0x32, 0x12, 0x2e, 0x73, 0x74, 0x61, 0x74, 0x65, 0x2e, 0x42, 0x75, 0x74, 0x69, 0x6f, 0x6e, 0x53, 0x74, 0x61, 0x74, 0x65, 0x12, 0x31, 0x0a, 0x0a, 0x72, 0x65, 0x70, 0x6c,
0x74, 0x6f, 0x6e, 0x53, 0x74, 0x61, 0x74, 0x65, 0x52, 0x0b, 0x62, 0x75, 0x74, 0x74, 0x6f, 0x6e, 0x79, 0x53, 0x74, 0x61, 0x74, 0x65, 0x18, 0x04, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x11, 0x2e, 0x73,
0x53, 0x74, 0x61, 0x74, 0x65, 0x12, 0x31, 0x0a, 0x0a, 0x41, 0x6c, 0x61, 0x72, 0x6d, 0x53, 0x74, 0x74, 0x61, 0x74, 0x65, 0x2e, 0x52, 0x65, 0x70, 0x6c, 0x79, 0x53, 0x74, 0x61, 0x74, 0x65, 0x52,
0x61, 0x74, 0x65, 0x18, 0x07, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x11, 0x2e, 0x73, 0x74, 0x61, 0x74, 0x0a, 0x72, 0x65, 0x70, 0x6c, 0x79, 0x53, 0x74, 0x61, 0x74, 0x65, 0x12, 0x34, 0x0a, 0x0b, 0x73,
0x65, 0x2e, 0x41, 0x6c, 0x61, 0x72, 0x6d, 0x53, 0x74, 0x61, 0x74, 0x65, 0x52, 0x0a, 0x41, 0x6c, 0x69, 0x67, 0x6e, 0x61, 0x6c, 0x53, 0x74, 0x61, 0x74, 0x65, 0x18, 0x05, 0x20, 0x03, 0x28, 0x0b,
0x61, 0x72, 0x6d, 0x53, 0x74, 0x61, 0x74, 0x65, 0x12, 0x31, 0x0a, 0x0a, 0x4c, 0x69, 0x67, 0x68, 0x32, 0x12, 0x2e, 0x73, 0x74, 0x61, 0x74, 0x65, 0x2e, 0x53, 0x69, 0x67, 0x6e, 0x61, 0x6c, 0x53,
0x74, 0x53, 0x74, 0x61, 0x74, 0x65, 0x18, 0x08, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x11, 0x2e, 0x73, 0x74, 0x61, 0x74, 0x65, 0x52, 0x0b, 0x73, 0x69, 0x67, 0x6e, 0x61, 0x6c, 0x53, 0x74, 0x61, 0x74,
0x74, 0x61, 0x74, 0x65, 0x2e, 0x4c, 0x69, 0x67, 0x68, 0x74, 0x53, 0x74, 0x61, 0x74, 0x65, 0x52, 0x65, 0x12, 0x34, 0x0a, 0x0b, 0x62, 0x75, 0x74, 0x74, 0x6f, 0x6e, 0x53, 0x74, 0x61, 0x74, 0x65,
0x0a, 0x4c, 0x69, 0x67, 0x68, 0x74, 0x53, 0x74, 0x61, 0x74, 0x65, 0x12, 0x2b, 0x0a, 0x08, 0x70, 0x18, 0x06, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x12, 0x2e, 0x73, 0x74, 0x61, 0x74, 0x65, 0x2e, 0x42,
0x73, 0x64, 0x53, 0x74, 0x61, 0x74, 0x65, 0x18, 0x09, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x0f, 0x2e, 0x75, 0x74, 0x74, 0x6f, 0x6e, 0x53, 0x74, 0x61, 0x74, 0x65, 0x52, 0x0b, 0x62, 0x75, 0x74, 0x74,
0x73, 0x74, 0x61, 0x74, 0x65, 0x2e, 0x50, 0x73, 0x64, 0x53, 0x74, 0x61, 0x74, 0x65, 0x52, 0x08, 0x6f, 0x6e, 0x53, 0x74, 0x61, 0x74, 0x65, 0x12, 0x31, 0x0a, 0x0a, 0x41, 0x6c, 0x61, 0x72, 0x6d,
0x70, 0x73, 0x64, 0x53, 0x74, 0x61, 0x74, 0x65, 0x12, 0x2b, 0x0a, 0x08, 0x4b, 0x65, 0x79, 0x53, 0x53, 0x74, 0x61, 0x74, 0x65, 0x18, 0x07, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x11, 0x2e, 0x73, 0x74,
0x74, 0x61, 0x74, 0x65, 0x18, 0x0a, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x0f, 0x2e, 0x73, 0x74, 0x61, 0x61, 0x74, 0x65, 0x2e, 0x41, 0x6c, 0x61, 0x72, 0x6d, 0x53, 0x74, 0x61, 0x74, 0x65, 0x52, 0x0a,
0x74, 0x65, 0x2e, 0x4b, 0x65, 0x79, 0x53, 0x74, 0x61, 0x74, 0x65, 0x52, 0x08, 0x4b, 0x65, 0x79, 0x41, 0x6c, 0x61, 0x72, 0x6d, 0x53, 0x74, 0x61, 0x74, 0x65, 0x12, 0x31, 0x0a, 0x0a, 0x4c, 0x69,
0x53, 0x74, 0x61, 0x74, 0x65, 0x12, 0x3a, 0x0a, 0x0d, 0x70, 0x6c, 0x61, 0x74, 0x66, 0x6f, 0x72, 0x67, 0x68, 0x74, 0x53, 0x74, 0x61, 0x74, 0x65, 0x18, 0x08, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x11,
0x6d, 0x53, 0x74, 0x61, 0x74, 0x65, 0x18, 0x0b, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x14, 0x2e, 0x73, 0x2e, 0x73, 0x74, 0x61, 0x74, 0x65, 0x2e, 0x4c, 0x69, 0x67, 0x68, 0x74, 0x53, 0x74, 0x61, 0x74,
0x74, 0x61, 0x74, 0x65, 0x2e, 0x50, 0x6c, 0x61, 0x74, 0x66, 0x6f, 0x72, 0x6d, 0x53, 0x74, 0x61, 0x65, 0x52, 0x0a, 0x4c, 0x69, 0x67, 0x68, 0x74, 0x53, 0x74, 0x61, 0x74, 0x65, 0x12, 0x2b, 0x0a,
0x74, 0x65, 0x52, 0x0d, 0x70, 0x6c, 0x61, 0x74, 0x66, 0x6f, 0x72, 0x6d, 0x53, 0x74, 0x61, 0x74, 0x08, 0x70, 0x73, 0x64, 0x53, 0x74, 0x61, 0x74, 0x65, 0x18, 0x09, 0x20, 0x03, 0x28, 0x0b, 0x32,
0x65, 0x12, 0x34, 0x0a, 0x0b, 0x62, 0x61, 0x6c, 0x69, 0x73, 0x65, 0x53, 0x74, 0x61, 0x74, 0x65, 0x0f, 0x2e, 0x73, 0x74, 0x61, 0x74, 0x65, 0x2e, 0x50, 0x73, 0x64, 0x53, 0x74, 0x61, 0x74, 0x65,
0x18, 0x0c, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x12, 0x2e, 0x73, 0x74, 0x61, 0x74, 0x65, 0x2e, 0x42, 0x52, 0x08, 0x70, 0x73, 0x64, 0x53, 0x74, 0x61, 0x74, 0x65, 0x12, 0x2b, 0x0a, 0x08, 0x4b, 0x65,
0x61, 0x6c, 0x69, 0x73, 0x65, 0x53, 0x74, 0x61, 0x74, 0x65, 0x52, 0x0b, 0x62, 0x61, 0x6c, 0x69, 0x79, 0x53, 0x74, 0x61, 0x74, 0x65, 0x18, 0x0a, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x0f, 0x2e, 0x73,
0x73, 0x65, 0x53, 0x74, 0x61, 0x74, 0x65, 0x12, 0x2e, 0x0a, 0x09, 0x73, 0x74, 0x61, 0x74, 0x69, 0x74, 0x61, 0x74, 0x65, 0x2e, 0x4b, 0x65, 0x79, 0x53, 0x74, 0x61, 0x74, 0x65, 0x52, 0x08, 0x4b,
0x6f, 0x6e, 0x51, 0x63, 0x18, 0x0d, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x10, 0x2e, 0x73, 0x74, 0x61, 0x65, 0x79, 0x53, 0x74, 0x61, 0x74, 0x65, 0x12, 0x3a, 0x0a, 0x0d, 0x70, 0x6c, 0x61, 0x74, 0x66,
0x74, 0x65, 0x2e, 0x53, 0x74, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x51, 0x63, 0x52, 0x09, 0x73, 0x74, 0x6f, 0x72, 0x6d, 0x53, 0x74, 0x61, 0x74, 0x65, 0x18, 0x0b, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x14,
0x61, 0x74, 0x69, 0x6f, 0x6e, 0x51, 0x63, 0x12, 0x2d, 0x0a, 0x09, 0x63, 0x6b, 0x6d, 0x53, 0x74, 0x2e, 0x73, 0x74, 0x61, 0x74, 0x65, 0x2e, 0x50, 0x6c, 0x61, 0x74, 0x66, 0x6f, 0x72, 0x6d, 0x53,
0x61, 0x74, 0x65, 0x73, 0x18, 0x0e, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x0f, 0x2e, 0x73, 0x74, 0x61, 0x74, 0x61, 0x74, 0x65, 0x52, 0x0d, 0x70, 0x6c, 0x61, 0x74, 0x66, 0x6f, 0x72, 0x6d, 0x53, 0x74,
0x74, 0x65, 0x2e, 0x43, 0x6b, 0x6d, 0x53, 0x74, 0x61, 0x74, 0x65, 0x52, 0x09, 0x63, 0x6b, 0x6d, 0x61, 0x74, 0x65, 0x12, 0x34, 0x0a, 0x0b, 0x62, 0x61, 0x6c, 0x69, 0x73, 0x65, 0x53, 0x74, 0x61,
0x53, 0x74, 0x61, 0x74, 0x65, 0x73, 0x12, 0x2d, 0x0a, 0x09, 0x66, 0x79, 0x6d, 0x53, 0x74, 0x61, 0x74, 0x65, 0x18, 0x0c, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x12, 0x2e, 0x73, 0x74, 0x61, 0x74, 0x65,
0x74, 0x65, 0x73, 0x18, 0x0f, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x0f, 0x2e, 0x73, 0x74, 0x61, 0x74, 0x2e, 0x42, 0x61, 0x6c, 0x69, 0x73, 0x65, 0x53, 0x74, 0x61, 0x74, 0x65, 0x52, 0x0b, 0x62, 0x61,
0x65, 0x2e, 0x43, 0x6b, 0x6d, 0x53, 0x74, 0x61, 0x74, 0x65, 0x52, 0x09, 0x66, 0x79, 0x6d, 0x53, 0x6c, 0x69, 0x73, 0x65, 0x53, 0x74, 0x61, 0x74, 0x65, 0x12, 0x2e, 0x0a, 0x09, 0x73, 0x74, 0x61,
0x74, 0x61, 0x74, 0x65, 0x73, 0x12, 0x2d, 0x0a, 0x09, 0x78, 0x63, 0x6a, 0x53, 0x74, 0x61, 0x74, 0x74, 0x69, 0x6f, 0x6e, 0x51, 0x63, 0x18, 0x0d, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x10, 0x2e, 0x73,
0x65, 0x73, 0x18, 0x10, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x0f, 0x2e, 0x73, 0x74, 0x61, 0x74, 0x65, 0x74, 0x61, 0x74, 0x65, 0x2e, 0x53, 0x74, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x51, 0x63, 0x52, 0x09,
0x2e, 0x58, 0x63, 0x6a, 0x53, 0x74, 0x61, 0x74, 0x65, 0x52, 0x09, 0x78, 0x63, 0x6a, 0x53, 0x74, 0x73, 0x74, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x51, 0x63, 0x12, 0x2d, 0x0a, 0x09, 0x63, 0x6b, 0x6d,
0x61, 0x74, 0x65, 0x73, 0x22, 0x94, 0x01, 0x0a, 0x13, 0x50, 0x75, 0x73, 0x68, 0x65, 0x64, 0x44, 0x53, 0x74, 0x61, 0x74, 0x65, 0x73, 0x18, 0x0e, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x0f, 0x2e, 0x73,
0x65, 0x76, 0x69, 0x63, 0x65, 0x73, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x12, 0x10, 0x0a, 0x03, 0x74, 0x61, 0x74, 0x65, 0x2e, 0x43, 0x6b, 0x6d, 0x53, 0x74, 0x61, 0x74, 0x65, 0x52, 0x09, 0x63,
0x61, 0x6c, 0x6c, 0x18, 0x01, 0x20, 0x01, 0x28, 0x08, 0x52, 0x03, 0x61, 0x6c, 0x6c, 0x12, 0x34, 0x6b, 0x6d, 0x53, 0x74, 0x61, 0x74, 0x65, 0x73, 0x12, 0x2d, 0x0a, 0x09, 0x66, 0x79, 0x6d, 0x53,
0x0a, 0x09, 0x76, 0x61, 0x72, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x18, 0x02, 0x20, 0x01, 0x28, 0x74, 0x61, 0x74, 0x65, 0x73, 0x18, 0x0f, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x0f, 0x2e, 0x73, 0x74,
0x0b, 0x32, 0x16, 0x2e, 0x73, 0x74, 0x61, 0x74, 0x65, 0x2e, 0x56, 0x61, 0x72, 0x69, 0x61, 0x74, 0x61, 0x74, 0x65, 0x2e, 0x43, 0x6b, 0x6d, 0x53, 0x74, 0x61, 0x74, 0x65, 0x52, 0x09, 0x66, 0x79,
0x69, 0x6f, 0x6e, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x52, 0x09, 0x76, 0x61, 0x72, 0x53, 0x74, 0x6d, 0x53, 0x74, 0x61, 0x74, 0x65, 0x73, 0x12, 0x2d, 0x0a, 0x09, 0x78, 0x63, 0x6a, 0x53, 0x74,
0x61, 0x74, 0x75, 0x73, 0x12, 0x35, 0x0a, 0x09, 0x61, 0x6c, 0x6c, 0x53, 0x74, 0x61, 0x74, 0x75, 0x61, 0x74, 0x65, 0x73, 0x18, 0x10, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x0f, 0x2e, 0x73, 0x74, 0x61,
0x73, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x17, 0x2e, 0x73, 0x74, 0x61, 0x74, 0x65, 0x2e, 0x74, 0x65, 0x2e, 0x58, 0x63, 0x6a, 0x53, 0x74, 0x61, 0x74, 0x65, 0x52, 0x09, 0x78, 0x63, 0x6a,
0x41, 0x6c, 0x6c, 0x44, 0x65, 0x76, 0x69, 0x63, 0x65, 0x73, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x53, 0x74, 0x61, 0x74, 0x65, 0x73, 0x22, 0x94, 0x01, 0x0a, 0x13, 0x50, 0x75, 0x73, 0x68, 0x65,
0x52, 0x09, 0x61, 0x6c, 0x6c, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x22, 0xc2, 0x01, 0x0a, 0x10, 0x64, 0x44, 0x65, 0x76, 0x69, 0x63, 0x65, 0x73, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x12, 0x10,
0x53, 0x69, 0x6d, 0x75, 0x6c, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x0a, 0x03, 0x61, 0x6c, 0x6c, 0x18, 0x01, 0x20, 0x01, 0x28, 0x08, 0x52, 0x03, 0x61, 0x6c, 0x6c,
0x12, 0x22, 0x0a, 0x0c, 0x73, 0x69, 0x6d, 0x75, 0x6c, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x49, 0x64, 0x12, 0x34, 0x0a, 0x09, 0x76, 0x61, 0x72, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x18, 0x02, 0x20,
0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0c, 0x73, 0x69, 0x6d, 0x75, 0x6c, 0x61, 0x74, 0x69, 0x01, 0x28, 0x0b, 0x32, 0x16, 0x2e, 0x73, 0x74, 0x61, 0x74, 0x65, 0x2e, 0x56, 0x61, 0x72, 0x69,
0x6f, 0x6e, 0x49, 0x64, 0x12, 0x3d, 0x0a, 0x05, 0x73, 0x74, 0x61, 0x74, 0x65, 0x18, 0x02, 0x20, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x52, 0x09, 0x76, 0x61, 0x72,
0x01, 0x28, 0x0e, 0x32, 0x27, 0x2e, 0x73, 0x74, 0x61, 0x74, 0x65, 0x2e, 0x53, 0x69, 0x6d, 0x75, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x12, 0x35, 0x0a, 0x09, 0x61, 0x6c, 0x6c, 0x53, 0x74, 0x61,
0x6c, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x2e, 0x53, 0x69, 0x6d, 0x74, 0x75, 0x73, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x17, 0x2e, 0x73, 0x74, 0x61, 0x74,
0x75, 0x6c, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x53, 0x74, 0x61, 0x74, 0x65, 0x52, 0x05, 0x73, 0x74, 0x65, 0x2e, 0x41, 0x6c, 0x6c, 0x44, 0x65, 0x76, 0x69, 0x63, 0x65, 0x73, 0x53, 0x74, 0x61, 0x74,
0x61, 0x74, 0x65, 0x22, 0x4b, 0x0a, 0x0f, 0x53, 0x69, 0x6d, 0x75, 0x6c, 0x61, 0x74, 0x69, 0x6f, 0x75, 0x73, 0x52, 0x09, 0x61, 0x6c, 0x6c, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x22, 0xc2, 0x01,
0x6e, 0x53, 0x74, 0x61, 0x74, 0x65, 0x12, 0x08, 0x0a, 0x04, 0x49, 0x6e, 0x69, 0x74, 0x10, 0x00, 0x0a, 0x10, 0x53, 0x69, 0x6d, 0x75, 0x6c, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x53, 0x74, 0x61, 0x74,
0x12, 0x0b, 0x0a, 0x07, 0x52, 0x75, 0x6e, 0x6e, 0x69, 0x6e, 0x67, 0x10, 0x01, 0x12, 0x09, 0x0a, 0x75, 0x73, 0x12, 0x22, 0x0a, 0x0c, 0x73, 0x69, 0x6d, 0x75, 0x6c, 0x61, 0x74, 0x69, 0x6f, 0x6e,
0x05, 0x50, 0x61, 0x75, 0x73, 0x65, 0x10, 0x02, 0x12, 0x09, 0x0a, 0x05, 0x45, 0x72, 0x72, 0x6f, 0x49, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0c, 0x73, 0x69, 0x6d, 0x75, 0x6c, 0x61,
0x72, 0x10, 0x03, 0x12, 0x0b, 0x0a, 0x07, 0x44, 0x65, 0x73, 0x74, 0x72, 0x6f, 0x79, 0x10, 0x04, 0x74, 0x69, 0x6f, 0x6e, 0x49, 0x64, 0x12, 0x3d, 0x0a, 0x05, 0x73, 0x74, 0x61, 0x74, 0x65, 0x18,
0x22, 0xd2, 0x01, 0x0a, 0x1e, 0x53, 0x69, 0x6d, 0x75, 0x6c, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x54, 0x02, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x27, 0x2e, 0x73, 0x74, 0x61, 0x74, 0x65, 0x2e, 0x53, 0x69,
0x68, 0x69, 0x72, 0x64, 0x50, 0x61, 0x72, 0x74, 0x79, 0x41, 0x70, 0x69, 0x53, 0x65, 0x72, 0x76, 0x6d, 0x75, 0x6c, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x2e, 0x53,
0x69, 0x63, 0x65, 0x12, 0x42, 0x0a, 0x06, 0x73, 0x74, 0x61, 0x74, 0x65, 0x73, 0x18, 0x01, 0x20, 0x69, 0x6d, 0x75, 0x6c, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x53, 0x74, 0x61, 0x74, 0x65, 0x52, 0x05,
0x03, 0x28, 0x0b, 0x32, 0x2a, 0x2e, 0x73, 0x74, 0x61, 0x74, 0x65, 0x2e, 0x53, 0x69, 0x6d, 0x75, 0x73, 0x74, 0x61, 0x74, 0x65, 0x22, 0x4b, 0x0a, 0x0f, 0x53, 0x69, 0x6d, 0x75, 0x6c, 0x61, 0x74,
0x69, 0x6f, 0x6e, 0x53, 0x74, 0x61, 0x74, 0x65, 0x12, 0x08, 0x0a, 0x04, 0x49, 0x6e, 0x69, 0x74,
0x10, 0x00, 0x12, 0x0b, 0x0a, 0x07, 0x52, 0x75, 0x6e, 0x6e, 0x69, 0x6e, 0x67, 0x10, 0x01, 0x12,
0x09, 0x0a, 0x05, 0x50, 0x61, 0x75, 0x73, 0x65, 0x10, 0x02, 0x12, 0x09, 0x0a, 0x05, 0x45, 0x72,
0x72, 0x6f, 0x72, 0x10, 0x03, 0x12, 0x0b, 0x0a, 0x07, 0x44, 0x65, 0x73, 0x74, 0x72, 0x6f, 0x79,
0x10, 0x04, 0x22, 0xd2, 0x01, 0x0a, 0x1e, 0x53, 0x69, 0x6d, 0x75, 0x6c, 0x61, 0x74, 0x69, 0x6f,
0x6e, 0x54, 0x68, 0x69, 0x72, 0x64, 0x50, 0x61, 0x72, 0x74, 0x79, 0x41, 0x70, 0x69, 0x53, 0x65,
0x72, 0x76, 0x69, 0x63, 0x65, 0x12, 0x42, 0x0a, 0x06, 0x73, 0x74, 0x61, 0x74, 0x65, 0x73, 0x18,
0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x2a, 0x2e, 0x73, 0x74, 0x61, 0x74, 0x65, 0x2e, 0x53, 0x69,
0x6d, 0x75, 0x6c, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x54, 0x68, 0x69, 0x72, 0x64, 0x50, 0x61, 0x72,
0x74, 0x79, 0x41, 0x70, 0x69, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x53, 0x74, 0x61, 0x74,
0x65, 0x52, 0x06, 0x73, 0x74, 0x61, 0x74, 0x65, 0x73, 0x22, 0x4c, 0x0a, 0x04, 0x54, 0x79, 0x70,
0x65, 0x12, 0x0d, 0x0a, 0x09, 0x55, 0x6e, 0x64, 0x65, 0x66, 0x69, 0x6e, 0x65, 0x64, 0x10, 0x00,
0x12, 0x0c, 0x0a, 0x08, 0x44, 0x79, 0x6e, 0x61, 0x6d, 0x69, 0x63, 0x73, 0x10, 0x01, 0x12, 0x15,
0x0a, 0x11, 0x53, 0x65, 0x6d, 0x69, 0x50, 0x68, 0x79, 0x73, 0x69, 0x63, 0x61, 0x6c, 0x54, 0x72,
0x61, 0x69, 0x6e, 0x10, 0x02, 0x12, 0x10, 0x0a, 0x0c, 0x54, 0x72, 0x61, 0x69, 0x6e, 0x5f, 0x70,
0x63, 0x5f, 0x73, 0x69, 0x6d, 0x10, 0x03, 0x22, 0x1e, 0x0a, 0x05, 0x53, 0x74, 0x61, 0x74, 0x65,
0x12, 0x0a, 0x0a, 0x06, 0x4e, 0x6f, 0x72, 0x6d, 0x61, 0x6c, 0x10, 0x00, 0x12, 0x09, 0x0a, 0x05,
0x45, 0x72, 0x72, 0x6f, 0x72, 0x10, 0x01, 0x22, 0xca, 0x01, 0x0a, 0x23, 0x53, 0x69, 0x6d, 0x75,
0x6c, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x54, 0x68, 0x69, 0x72, 0x64, 0x50, 0x61, 0x72, 0x74, 0x79, 0x6c, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x54, 0x68, 0x69, 0x72, 0x64, 0x50, 0x61, 0x72, 0x74, 0x79,
0x41, 0x70, 0x69, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x53, 0x74, 0x61, 0x74, 0x65, 0x52, 0x41, 0x70, 0x69, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x53, 0x74, 0x61, 0x74, 0x65, 0x12,
0x06, 0x73, 0x74, 0x61, 0x74, 0x65, 0x73, 0x22, 0x4c, 0x0a, 0x04, 0x54, 0x79, 0x70, 0x65, 0x12, 0x3e, 0x0a, 0x04, 0x74, 0x79, 0x70, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x2a, 0x2e,
0x0d, 0x0a, 0x09, 0x55, 0x6e, 0x64, 0x65, 0x66, 0x69, 0x6e, 0x65, 0x64, 0x10, 0x00, 0x12, 0x0c, 0x73, 0x74, 0x61, 0x74, 0x65, 0x2e, 0x53, 0x69, 0x6d, 0x75, 0x6c, 0x61, 0x74, 0x69, 0x6f, 0x6e,
0x0a, 0x08, 0x44, 0x79, 0x6e, 0x61, 0x6d, 0x69, 0x63, 0x73, 0x10, 0x01, 0x12, 0x15, 0x0a, 0x11, 0x54, 0x68, 0x69, 0x72, 0x64, 0x50, 0x61, 0x72, 0x74, 0x79, 0x41, 0x70, 0x69, 0x53, 0x65, 0x72,
0x53, 0x65, 0x6d, 0x69, 0x50, 0x68, 0x79, 0x73, 0x69, 0x63, 0x61, 0x6c, 0x54, 0x72, 0x61, 0x69, 0x76, 0x69, 0x63, 0x65, 0x2e, 0x54, 0x79, 0x70, 0x65, 0x52, 0x04, 0x74, 0x79, 0x70, 0x65, 0x12,
0x6e, 0x10, 0x02, 0x12, 0x10, 0x0a, 0x0c, 0x54, 0x72, 0x61, 0x69, 0x6e, 0x5f, 0x70, 0x63, 0x5f, 0x41, 0x0a, 0x05, 0x73, 0x74, 0x61, 0x74, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x2b,
0x73, 0x69, 0x6d, 0x10, 0x03, 0x22, 0x1e, 0x0a, 0x05, 0x53, 0x74, 0x61, 0x74, 0x65, 0x12, 0x0a, 0x2e, 0x73, 0x74, 0x61, 0x74, 0x65, 0x2e, 0x53, 0x69, 0x6d, 0x75, 0x6c, 0x61, 0x74, 0x69, 0x6f,
0x0a, 0x06, 0x4e, 0x6f, 0x72, 0x6d, 0x61, 0x6c, 0x10, 0x00, 0x12, 0x09, 0x0a, 0x05, 0x45, 0x72, 0x6e, 0x54, 0x68, 0x69, 0x72, 0x64, 0x50, 0x61, 0x72, 0x74, 0x79, 0x41, 0x70, 0x69, 0x53, 0x65,
0x72, 0x6f, 0x72, 0x10, 0x01, 0x22, 0xca, 0x01, 0x0a, 0x23, 0x53, 0x69, 0x6d, 0x75, 0x6c, 0x61, 0x72, 0x76, 0x69, 0x63, 0x65, 0x2e, 0x53, 0x74, 0x61, 0x74, 0x65, 0x52, 0x05, 0x73, 0x74, 0x61,
0x74, 0x69, 0x6f, 0x6e, 0x54, 0x68, 0x69, 0x72, 0x64, 0x50, 0x61, 0x72, 0x74, 0x79, 0x41, 0x70, 0x74, 0x65, 0x12, 0x20, 0x0a, 0x0b, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x4e, 0x61, 0x6d,
0x69, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x53, 0x74, 0x61, 0x74, 0x65, 0x12, 0x3e, 0x0a, 0x65, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0b, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65,
0x04, 0x74, 0x79, 0x70, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x2a, 0x2e, 0x73, 0x74, 0x4e, 0x61, 0x6d, 0x65, 0x22, 0x9a, 0x07, 0x0a, 0x11, 0x54, 0x72, 0x61, 0x69, 0x6e, 0x43, 0x6f,
0x61, 0x74, 0x65, 0x2e, 0x53, 0x69, 0x6d, 0x75, 0x6c, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x54, 0x68, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x53, 0x74, 0x61, 0x74, 0x65, 0x12, 0x3f, 0x0a, 0x07, 0x62, 0x75,
0x69, 0x72, 0x64, 0x50, 0x61, 0x72, 0x74, 0x79, 0x41, 0x70, 0x69, 0x53, 0x65, 0x72, 0x76, 0x69, 0x74, 0x74, 0x6f, 0x6e, 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x25, 0x2e, 0x73, 0x74,
0x63, 0x65, 0x2e, 0x54, 0x79, 0x70, 0x65, 0x52, 0x04, 0x74, 0x79, 0x70, 0x65, 0x12, 0x41, 0x0a,
0x05, 0x73, 0x74, 0x61, 0x74, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x2b, 0x2e, 0x73,
0x74, 0x61, 0x74, 0x65, 0x2e, 0x53, 0x69, 0x6d, 0x75, 0x6c, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x54,
0x68, 0x69, 0x72, 0x64, 0x50, 0x61, 0x72, 0x74, 0x79, 0x41, 0x70, 0x69, 0x53, 0x65, 0x72, 0x76,
0x69, 0x63, 0x65, 0x2e, 0x53, 0x74, 0x61, 0x74, 0x65, 0x52, 0x05, 0x73, 0x74, 0x61, 0x74, 0x65,
0x12, 0x20, 0x0a, 0x0b, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x4e, 0x61, 0x6d, 0x65, 0x18,
0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0b, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x4e, 0x61,
0x6d, 0x65, 0x22, 0x9a, 0x07, 0x0a, 0x11, 0x54, 0x72, 0x61, 0x69, 0x6e, 0x43, 0x6f, 0x6e, 0x74,
0x72, 0x6f, 0x6c, 0x53, 0x74, 0x61, 0x74, 0x65, 0x12, 0x3f, 0x0a, 0x07, 0x62, 0x75, 0x74, 0x74,
0x6f, 0x6e, 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x25, 0x2e, 0x73, 0x74, 0x61, 0x74,
0x65, 0x2e, 0x54, 0x72, 0x61, 0x69, 0x6e, 0x43, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x53, 0x74,
0x61, 0x74, 0x65, 0x2e, 0x42, 0x75, 0x74, 0x74, 0x6f, 0x6e, 0x73, 0x45, 0x6e, 0x74, 0x72, 0x79,
0x52, 0x07, 0x62, 0x75, 0x74, 0x74, 0x6f, 0x6e, 0x73, 0x12, 0x46, 0x0a, 0x09, 0x64, 0x72, 0x69,
0x76, 0x65, 0x72, 0x4b, 0x65, 0x79, 0x18, 0x02, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x28, 0x2e, 0x73,
0x74, 0x61, 0x74, 0x65, 0x2e, 0x54, 0x72, 0x61, 0x69, 0x6e, 0x43, 0x6f, 0x6e, 0x74, 0x72, 0x6f,
0x6c, 0x53, 0x74, 0x61, 0x74, 0x65, 0x2e, 0x44, 0x72, 0x69, 0x76, 0x65, 0x72, 0x4b, 0x65, 0x79,
0x53, 0x77, 0x69, 0x74, 0x63, 0x68, 0x52, 0x09, 0x64, 0x72, 0x69, 0x76, 0x65, 0x72, 0x4b, 0x65,
0x79, 0x12, 0x43, 0x0a, 0x06, 0x64, 0x69, 0x72, 0x4b, 0x65, 0x79, 0x18, 0x03, 0x20, 0x01, 0x28,
0x0b, 0x32, 0x2b, 0x2e, 0x73, 0x74, 0x61, 0x74, 0x65, 0x2e, 0x54, 0x72, 0x61, 0x69, 0x6e, 0x43,
0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x53, 0x74, 0x61, 0x74, 0x65, 0x2e, 0x44, 0x69, 0x72, 0x65,
0x63, 0x74, 0x69, 0x6f, 0x6e, 0x4b, 0x65, 0x79, 0x53, 0x77, 0x69, 0x74, 0x63, 0x68, 0x52, 0x06,
0x64, 0x69, 0x72, 0x4b, 0x65, 0x79, 0x12, 0x46, 0x0a, 0x0b, 0x70, 0x75, 0x73, 0x68, 0x48, 0x61,
0x6e, 0x64, 0x6c, 0x65, 0x72, 0x18, 0x04, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x24, 0x2e, 0x73, 0x74,
0x61, 0x74, 0x65, 0x2e, 0x54, 0x72, 0x61, 0x69, 0x6e, 0x43, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x61, 0x74, 0x65, 0x2e, 0x54, 0x72, 0x61, 0x69, 0x6e, 0x43, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c,
0x53, 0x74, 0x61, 0x74, 0x65, 0x2e, 0x50, 0x75, 0x73, 0x68, 0x48, 0x61, 0x6e, 0x64, 0x6c, 0x65, 0x53, 0x74, 0x61, 0x74, 0x65, 0x2e, 0x42, 0x75, 0x74, 0x74, 0x6f, 0x6e, 0x73, 0x45, 0x6e, 0x74,
0x72, 0x52, 0x0b, 0x70, 0x75, 0x73, 0x68, 0x48, 0x61, 0x6e, 0x64, 0x6c, 0x65, 0x72, 0x12, 0x45, 0x72, 0x79, 0x52, 0x07, 0x62, 0x75, 0x74, 0x74, 0x6f, 0x6e, 0x73, 0x12, 0x46, 0x0a, 0x09, 0x64,
0x0a, 0x09, 0x6c, 0x69, 0x67, 0x68, 0x74, 0x4d, 0x61, 0x70, 0x73, 0x18, 0x05, 0x20, 0x03, 0x28, 0x72, 0x69, 0x76, 0x65, 0x72, 0x4b, 0x65, 0x79, 0x18, 0x02, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x28,
0x0b, 0x32, 0x27, 0x2e, 0x73, 0x74, 0x61, 0x74, 0x65, 0x2e, 0x54, 0x72, 0x61, 0x69, 0x6e, 0x43,
0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x53, 0x74, 0x61, 0x74, 0x65, 0x2e, 0x4c, 0x69, 0x67, 0x68,
0x74, 0x4d, 0x61, 0x70, 0x73, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x52, 0x09, 0x6c, 0x69, 0x67, 0x68,
0x74, 0x4d, 0x61, 0x70, 0x73, 0x12, 0x30, 0x0a, 0x13, 0x6c, 0x69, 0x6e, 0x65, 0x49, 0x6e, 0x69,
0x74, 0x54, 0x69, 0x6d, 0x65, 0x53, 0x74, 0x61, 0x6d, 0x70, 0x31, 0x32, 0x18, 0x06, 0x20, 0x01,
0x28, 0x03, 0x52, 0x13, 0x6c, 0x69, 0x6e, 0x65, 0x49, 0x6e, 0x69, 0x74, 0x54, 0x69, 0x6d, 0x65,
0x53, 0x74, 0x61, 0x6d, 0x70, 0x31, 0x32, 0x12, 0x24, 0x0a, 0x0d, 0x6c, 0x69, 0x6e, 0x65, 0x31,
0x32, 0x43, 0x6f, 0x6e, 0x6e, 0x45, 0x72, 0x72, 0x18, 0x07, 0x20, 0x01, 0x28, 0x08, 0x52, 0x0d,
0x6c, 0x69, 0x6e, 0x65, 0x31, 0x32, 0x43, 0x6f, 0x6e, 0x6e, 0x45, 0x72, 0x72, 0x1a, 0x62, 0x0a,
0x0c, 0x42, 0x75, 0x74, 0x74, 0x6f, 0x6e, 0x73, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x12, 0x10, 0x0a,
0x03, 0x6b, 0x65, 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x03, 0x6b, 0x65, 0x79, 0x12,
0x3c, 0x0a, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x26,
0x2e, 0x73, 0x74, 0x61, 0x74, 0x65, 0x2e, 0x54, 0x72, 0x61, 0x69, 0x6e, 0x43, 0x6f, 0x6e, 0x74, 0x2e, 0x73, 0x74, 0x61, 0x74, 0x65, 0x2e, 0x54, 0x72, 0x61, 0x69, 0x6e, 0x43, 0x6f, 0x6e, 0x74,
0x72, 0x6f, 0x6c, 0x53, 0x74, 0x61, 0x74, 0x65, 0x2e, 0x43, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x72, 0x6f, 0x6c, 0x53, 0x74, 0x61, 0x74, 0x65, 0x2e, 0x44, 0x72, 0x69, 0x76, 0x65, 0x72, 0x4b,
0x42, 0x75, 0x74, 0x74, 0x6f, 0x6e, 0x52, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x3a, 0x02, 0x38, 0x65, 0x79, 0x53, 0x77, 0x69, 0x74, 0x63, 0x68, 0x52, 0x09, 0x64, 0x72, 0x69, 0x76, 0x65, 0x72,
0x01, 0x1a, 0x63, 0x0a, 0x0e, 0x4c, 0x69, 0x67, 0x68, 0x74, 0x4d, 0x61, 0x70, 0x73, 0x45, 0x6e, 0x4b, 0x65, 0x79, 0x12, 0x43, 0x0a, 0x06, 0x64, 0x69, 0x72, 0x4b, 0x65, 0x79, 0x18, 0x03, 0x20,
0x74, 0x72, 0x79, 0x12, 0x10, 0x0a, 0x03, 0x6b, 0x65, 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x01, 0x28, 0x0b, 0x32, 0x2b, 0x2e, 0x73, 0x74, 0x61, 0x74, 0x65, 0x2e, 0x54, 0x72, 0x61, 0x69,
0x52, 0x03, 0x6b, 0x65, 0x79, 0x12, 0x3b, 0x0a, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x02, 0x6e, 0x43, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x53, 0x74, 0x61, 0x74, 0x65, 0x2e, 0x44, 0x69,
0x20, 0x01, 0x28, 0x0b, 0x32, 0x25, 0x2e, 0x73, 0x74, 0x61, 0x74, 0x65, 0x2e, 0x54, 0x72, 0x61, 0x72, 0x65, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x4b, 0x65, 0x79, 0x53, 0x77, 0x69, 0x74, 0x63, 0x68,
0x69, 0x6e, 0x43, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x53, 0x74, 0x61, 0x74, 0x65, 0x2e, 0x43, 0x52, 0x06, 0x64, 0x69, 0x72, 0x4b, 0x65, 0x79, 0x12, 0x46, 0x0a, 0x0b, 0x70, 0x75, 0x73, 0x68,
0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x4c, 0x69, 0x67, 0x68, 0x74, 0x52, 0x05, 0x76, 0x61, 0x6c, 0x48, 0x61, 0x6e, 0x64, 0x6c, 0x65, 0x72, 0x18, 0x04, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x24, 0x2e,
0x75, 0x65, 0x3a, 0x02, 0x38, 0x01, 0x1a, 0x37, 0x0a, 0x0d, 0x43, 0x6f, 0x6e, 0x74, 0x72, 0x6f,
0x6c, 0x42, 0x75, 0x74, 0x74, 0x6f, 0x6e, 0x12, 0x0e, 0x0a, 0x02, 0x69, 0x64, 0x18, 0x01, 0x20,
0x01, 0x28, 0x0d, 0x52, 0x02, 0x69, 0x64, 0x12, 0x16, 0x0a, 0x06, 0x70, 0x61, 0x73, 0x73, 0x65,
0x64, 0x18, 0x03, 0x20, 0x01, 0x28, 0x08, 0x52, 0x06, 0x70, 0x61, 0x73, 0x73, 0x65, 0x64, 0x1a,
0x33, 0x0a, 0x0f, 0x44, 0x72, 0x69, 0x76, 0x65, 0x72, 0x4b, 0x65, 0x79, 0x53, 0x77, 0x69, 0x74,
0x63, 0x68, 0x12, 0x0e, 0x0a, 0x02, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x02,
0x69, 0x64, 0x12, 0x10, 0x0a, 0x03, 0x76, 0x61, 0x6c, 0x18, 0x02, 0x20, 0x01, 0x28, 0x08, 0x52,
0x03, 0x76, 0x61, 0x6c, 0x1a, 0x36, 0x0a, 0x12, 0x44, 0x69, 0x72, 0x65, 0x63, 0x74, 0x69, 0x6f,
0x6e, 0x4b, 0x65, 0x79, 0x53, 0x77, 0x69, 0x74, 0x63, 0x68, 0x12, 0x0e, 0x0a, 0x02, 0x69, 0x64,
0x18, 0x01, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x02, 0x69, 0x64, 0x12, 0x10, 0x0a, 0x03, 0x76, 0x61,
0x6c, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x03, 0x76, 0x61, 0x6c, 0x1a, 0x2f, 0x0a, 0x0b,
0x50, 0x75, 0x73, 0x68, 0x48, 0x61, 0x6e, 0x64, 0x6c, 0x65, 0x72, 0x12, 0x0e, 0x0a, 0x02, 0x69,
0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x02, 0x69, 0x64, 0x12, 0x10, 0x0a, 0x03, 0x76,
0x61, 0x6c, 0x18, 0x02, 0x20, 0x01, 0x28, 0x05, 0x52, 0x03, 0x76, 0x61, 0x6c, 0x1a, 0x30, 0x0a,
0x0c, 0x43, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x4c, 0x69, 0x67, 0x68, 0x74, 0x12, 0x0e, 0x0a,
0x02, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x02, 0x69, 0x64, 0x12, 0x10, 0x0a,
0x03, 0x76, 0x61, 0x6c, 0x18, 0x02, 0x20, 0x01, 0x28, 0x08, 0x52, 0x03, 0x76, 0x61, 0x6c, 0x22,
0xec, 0x02, 0x0a, 0x14, 0x54, 0x72, 0x61, 0x69, 0x6e, 0x43, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c,
0x53, 0x74, 0x61, 0x74, 0x65, 0x4d, 0x73, 0x67, 0x12, 0x40, 0x0a, 0x07, 0x62, 0x75, 0x74, 0x74,
0x6f, 0x6e, 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x26, 0x2e, 0x73, 0x74, 0x61, 0x74,
0x65, 0x2e, 0x54, 0x72, 0x61, 0x69, 0x6e, 0x43, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x53, 0x74,
0x61, 0x74, 0x65, 0x2e, 0x43, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x42, 0x75, 0x74, 0x74, 0x6f,
0x6e, 0x52, 0x07, 0x62, 0x75, 0x74, 0x74, 0x6f, 0x6e, 0x73, 0x12, 0x46, 0x0a, 0x09, 0x64, 0x72,
0x69, 0x76, 0x65, 0x72, 0x4b, 0x65, 0x79, 0x18, 0x02, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x28, 0x2e,
0x73, 0x74, 0x61, 0x74, 0x65, 0x2e, 0x54, 0x72, 0x61, 0x69, 0x6e, 0x43, 0x6f, 0x6e, 0x74, 0x72, 0x73, 0x74, 0x61, 0x74, 0x65, 0x2e, 0x54, 0x72, 0x61, 0x69, 0x6e, 0x43, 0x6f, 0x6e, 0x74, 0x72,
0x6f, 0x6c, 0x53, 0x74, 0x61, 0x74, 0x65, 0x2e, 0x44, 0x72, 0x69, 0x76, 0x65, 0x72, 0x4b, 0x65, 0x6f, 0x6c, 0x53, 0x74, 0x61, 0x74, 0x65, 0x2e, 0x50, 0x75, 0x73, 0x68, 0x48, 0x61, 0x6e, 0x64,
0x79, 0x53, 0x77, 0x69, 0x74, 0x63, 0x68, 0x52, 0x09, 0x64, 0x72, 0x69, 0x76, 0x65, 0x72, 0x4b, 0x6c, 0x65, 0x72, 0x52, 0x0b, 0x70, 0x75, 0x73, 0x68, 0x48, 0x61, 0x6e, 0x64, 0x6c, 0x65, 0x72,
0x65, 0x79, 0x12, 0x43, 0x0a, 0x06, 0x64, 0x69, 0x72, 0x4b, 0x65, 0x79, 0x18, 0x03, 0x20, 0x01, 0x12, 0x45, 0x0a, 0x09, 0x6c, 0x69, 0x67, 0x68, 0x74, 0x4d, 0x61, 0x70, 0x73, 0x18, 0x05, 0x20,
0x28, 0x0b, 0x32, 0x2b, 0x2e, 0x73, 0x74, 0x61, 0x74, 0x65, 0x2e, 0x54, 0x72, 0x61, 0x69, 0x6e, 0x03, 0x28, 0x0b, 0x32, 0x27, 0x2e, 0x73, 0x74, 0x61, 0x74, 0x65, 0x2e, 0x54, 0x72, 0x61, 0x69,
0x43, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x53, 0x74, 0x61, 0x74, 0x65, 0x2e, 0x44, 0x69, 0x72, 0x6e, 0x43, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x53, 0x74, 0x61, 0x74, 0x65, 0x2e, 0x4c, 0x69,
0x65, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x4b, 0x65, 0x79, 0x53, 0x77, 0x69, 0x74, 0x63, 0x68, 0x52, 0x67, 0x68, 0x74, 0x4d, 0x61, 0x70, 0x73, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x52, 0x09, 0x6c, 0x69,
0x06, 0x64, 0x69, 0x72, 0x4b, 0x65, 0x79, 0x12, 0x46, 0x0a, 0x0b, 0x70, 0x75, 0x73, 0x68, 0x48, 0x67, 0x68, 0x74, 0x4d, 0x61, 0x70, 0x73, 0x12, 0x30, 0x0a, 0x13, 0x6c, 0x69, 0x6e, 0x65, 0x49,
0x61, 0x6e, 0x64, 0x6c, 0x65, 0x72, 0x18, 0x04, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x24, 0x2e, 0x73, 0x6e, 0x69, 0x74, 0x54, 0x69, 0x6d, 0x65, 0x53, 0x74, 0x61, 0x6d, 0x70, 0x31, 0x32, 0x18, 0x06,
0x74, 0x61, 0x74, 0x65, 0x2e, 0x54, 0x72, 0x61, 0x69, 0x6e, 0x43, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x20, 0x01, 0x28, 0x03, 0x52, 0x13, 0x6c, 0x69, 0x6e, 0x65, 0x49, 0x6e, 0x69, 0x74, 0x54, 0x69,
0x6c, 0x53, 0x74, 0x61, 0x74, 0x65, 0x2e, 0x50, 0x75, 0x73, 0x68, 0x48, 0x61, 0x6e, 0x64, 0x6c, 0x6d, 0x65, 0x53, 0x74, 0x61, 0x6d, 0x70, 0x31, 0x32, 0x12, 0x24, 0x0a, 0x0d, 0x6c, 0x69, 0x6e,
0x65, 0x72, 0x52, 0x0b, 0x70, 0x75, 0x73, 0x68, 0x48, 0x61, 0x6e, 0x64, 0x6c, 0x65, 0x72, 0x12, 0x65, 0x31, 0x32, 0x43, 0x6f, 0x6e, 0x6e, 0x45, 0x72, 0x72, 0x18, 0x07, 0x20, 0x01, 0x28, 0x08,
0x3d, 0x0a, 0x06, 0x6c, 0x69, 0x67, 0x68, 0x74, 0x73, 0x18, 0x05, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x52, 0x0d, 0x6c, 0x69, 0x6e, 0x65, 0x31, 0x32, 0x43, 0x6f, 0x6e, 0x6e, 0x45, 0x72, 0x72, 0x1a,
0x25, 0x2e, 0x73, 0x74, 0x61, 0x74, 0x65, 0x2e, 0x54, 0x72, 0x61, 0x69, 0x6e, 0x43, 0x6f, 0x6e, 0x62, 0x0a, 0x0c, 0x42, 0x75, 0x74, 0x74, 0x6f, 0x6e, 0x73, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x12,
0x74, 0x72, 0x6f, 0x6c, 0x53, 0x74, 0x61, 0x74, 0x65, 0x2e, 0x43, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x10, 0x0a, 0x03, 0x6b, 0x65, 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x03, 0x6b, 0x65,
0x6c, 0x4c, 0x69, 0x67, 0x68, 0x74, 0x52, 0x06, 0x6c, 0x69, 0x67, 0x68, 0x74, 0x73, 0x2a, 0x37, 0x79, 0x12, 0x3c, 0x0a, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b,
0x0a, 0x0b, 0x53, 0x65, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x54, 0x79, 0x70, 0x65, 0x12, 0x07, 0x0a, 0x32, 0x26, 0x2e, 0x73, 0x74, 0x61, 0x74, 0x65, 0x2e, 0x54, 0x72, 0x61, 0x69, 0x6e, 0x43, 0x6f,
0x03, 0x41, 0x6e, 0x79, 0x10, 0x00, 0x12, 0x08, 0x0a, 0x04, 0x41, 0x78, 0x6c, 0x65, 0x10, 0x01, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x53, 0x74, 0x61, 0x74, 0x65, 0x2e, 0x43, 0x6f, 0x6e, 0x74, 0x72,
0x12, 0x09, 0x0a, 0x05, 0x4c, 0x6f, 0x67, 0x69, 0x63, 0x10, 0x02, 0x12, 0x0a, 0x0a, 0x06, 0x50, 0x6f, 0x6c, 0x42, 0x75, 0x74, 0x74, 0x6f, 0x6e, 0x52, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x3a,
0x68, 0x79, 0x73, 0x69, 0x63, 0x10, 0x03, 0x42, 0x67, 0x0a, 0x25, 0x63, 0x6c, 0x75, 0x62, 0x2e, 0x02, 0x38, 0x01, 0x1a, 0x63, 0x0a, 0x0e, 0x4c, 0x69, 0x67, 0x68, 0x74, 0x4d, 0x61, 0x70, 0x73,
0x6a, 0x6f, 0x79, 0x6c, 0x69, 0x6e, 0x6b, 0x2e, 0x62, 0x6a, 0x72, 0x74, 0x73, 0x73, 0x2e, 0x61, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x12, 0x10, 0x0a, 0x03, 0x6b, 0x65, 0x79, 0x18, 0x01, 0x20, 0x01,
0x74, 0x73, 0x2e, 0x76, 0x65, 0x72, 0x69, 0x66, 0x79, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x73, 0x28, 0x09, 0x52, 0x03, 0x6b, 0x65, 0x79, 0x12, 0x3b, 0x0a, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65,
0x42, 0x10, 0x44, 0x65, 0x76, 0x69, 0x63, 0x65, 0x53, 0x74, 0x61, 0x74, 0x65, 0x50, 0x72, 0x6f, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x25, 0x2e, 0x73, 0x74, 0x61, 0x74, 0x65, 0x2e, 0x54,
0x74, 0x6f, 0x5a, 0x2c, 0x6a, 0x6f, 0x79, 0x6c, 0x69, 0x6e, 0x6b, 0x2e, 0x63, 0x6c, 0x75, 0x62, 0x72, 0x61, 0x69, 0x6e, 0x43, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x53, 0x74, 0x61, 0x74, 0x65,
0x2f, 0x62, 0x6a, 0x2d, 0x72, 0x74, 0x73, 0x74, 0x73, 0x2d, 0x73, 0x65, 0x72, 0x76, 0x65, 0x72, 0x2e, 0x43, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x4c, 0x69, 0x67, 0x68, 0x74, 0x52, 0x05, 0x76,
0x2f, 0x64, 0x74, 0x6f, 0x2f, 0x73, 0x74, 0x61, 0x74, 0x65, 0x5f, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x61, 0x6c, 0x75, 0x65, 0x3a, 0x02, 0x38, 0x01, 0x1a, 0x37, 0x0a, 0x0d, 0x43, 0x6f, 0x6e, 0x74,
0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33, 0x72, 0x6f, 0x6c, 0x42, 0x75, 0x74, 0x74, 0x6f, 0x6e, 0x12, 0x0e, 0x0a, 0x02, 0x69, 0x64, 0x18,
0x01, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x02, 0x69, 0x64, 0x12, 0x16, 0x0a, 0x06, 0x70, 0x61, 0x73,
0x73, 0x65, 0x64, 0x18, 0x03, 0x20, 0x01, 0x28, 0x08, 0x52, 0x06, 0x70, 0x61, 0x73, 0x73, 0x65,
0x64, 0x1a, 0x33, 0x0a, 0x0f, 0x44, 0x72, 0x69, 0x76, 0x65, 0x72, 0x4b, 0x65, 0x79, 0x53, 0x77,
0x69, 0x74, 0x63, 0x68, 0x12, 0x0e, 0x0a, 0x02, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0d,
0x52, 0x02, 0x69, 0x64, 0x12, 0x10, 0x0a, 0x03, 0x76, 0x61, 0x6c, 0x18, 0x02, 0x20, 0x01, 0x28,
0x08, 0x52, 0x03, 0x76, 0x61, 0x6c, 0x1a, 0x36, 0x0a, 0x12, 0x44, 0x69, 0x72, 0x65, 0x63, 0x74,
0x69, 0x6f, 0x6e, 0x4b, 0x65, 0x79, 0x53, 0x77, 0x69, 0x74, 0x63, 0x68, 0x12, 0x0e, 0x0a, 0x02,
0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x02, 0x69, 0x64, 0x12, 0x10, 0x0a, 0x03,
0x76, 0x61, 0x6c, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x03, 0x76, 0x61, 0x6c, 0x1a, 0x2f,
0x0a, 0x0b, 0x50, 0x75, 0x73, 0x68, 0x48, 0x61, 0x6e, 0x64, 0x6c, 0x65, 0x72, 0x12, 0x0e, 0x0a,
0x02, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x02, 0x69, 0x64, 0x12, 0x10, 0x0a,
0x03, 0x76, 0x61, 0x6c, 0x18, 0x02, 0x20, 0x01, 0x28, 0x05, 0x52, 0x03, 0x76, 0x61, 0x6c, 0x1a,
0x30, 0x0a, 0x0c, 0x43, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x4c, 0x69, 0x67, 0x68, 0x74, 0x12,
0x0e, 0x0a, 0x02, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x02, 0x69, 0x64, 0x12,
0x10, 0x0a, 0x03, 0x76, 0x61, 0x6c, 0x18, 0x02, 0x20, 0x01, 0x28, 0x08, 0x52, 0x03, 0x76, 0x61,
0x6c, 0x22, 0xec, 0x02, 0x0a, 0x14, 0x54, 0x72, 0x61, 0x69, 0x6e, 0x43, 0x6f, 0x6e, 0x74, 0x72,
0x6f, 0x6c, 0x53, 0x74, 0x61, 0x74, 0x65, 0x4d, 0x73, 0x67, 0x12, 0x40, 0x0a, 0x07, 0x62, 0x75,
0x74, 0x74, 0x6f, 0x6e, 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x26, 0x2e, 0x73, 0x74,
0x61, 0x74, 0x65, 0x2e, 0x54, 0x72, 0x61, 0x69, 0x6e, 0x43, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c,
0x53, 0x74, 0x61, 0x74, 0x65, 0x2e, 0x43, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x42, 0x75, 0x74,
0x74, 0x6f, 0x6e, 0x52, 0x07, 0x62, 0x75, 0x74, 0x74, 0x6f, 0x6e, 0x73, 0x12, 0x46, 0x0a, 0x09,
0x64, 0x72, 0x69, 0x76, 0x65, 0x72, 0x4b, 0x65, 0x79, 0x18, 0x02, 0x20, 0x03, 0x28, 0x0b, 0x32,
0x28, 0x2e, 0x73, 0x74, 0x61, 0x74, 0x65, 0x2e, 0x54, 0x72, 0x61, 0x69, 0x6e, 0x43, 0x6f, 0x6e,
0x74, 0x72, 0x6f, 0x6c, 0x53, 0x74, 0x61, 0x74, 0x65, 0x2e, 0x44, 0x72, 0x69, 0x76, 0x65, 0x72,
0x4b, 0x65, 0x79, 0x53, 0x77, 0x69, 0x74, 0x63, 0x68, 0x52, 0x09, 0x64, 0x72, 0x69, 0x76, 0x65,
0x72, 0x4b, 0x65, 0x79, 0x12, 0x43, 0x0a, 0x06, 0x64, 0x69, 0x72, 0x4b, 0x65, 0x79, 0x18, 0x03,
0x20, 0x01, 0x28, 0x0b, 0x32, 0x2b, 0x2e, 0x73, 0x74, 0x61, 0x74, 0x65, 0x2e, 0x54, 0x72, 0x61,
0x69, 0x6e, 0x43, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x53, 0x74, 0x61, 0x74, 0x65, 0x2e, 0x44,
0x69, 0x72, 0x65, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x4b, 0x65, 0x79, 0x53, 0x77, 0x69, 0x74, 0x63,
0x68, 0x52, 0x06, 0x64, 0x69, 0x72, 0x4b, 0x65, 0x79, 0x12, 0x46, 0x0a, 0x0b, 0x70, 0x75, 0x73,
0x68, 0x48, 0x61, 0x6e, 0x64, 0x6c, 0x65, 0x72, 0x18, 0x04, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x24,
0x2e, 0x73, 0x74, 0x61, 0x74, 0x65, 0x2e, 0x54, 0x72, 0x61, 0x69, 0x6e, 0x43, 0x6f, 0x6e, 0x74,
0x72, 0x6f, 0x6c, 0x53, 0x74, 0x61, 0x74, 0x65, 0x2e, 0x50, 0x75, 0x73, 0x68, 0x48, 0x61, 0x6e,
0x64, 0x6c, 0x65, 0x72, 0x52, 0x0b, 0x70, 0x75, 0x73, 0x68, 0x48, 0x61, 0x6e, 0x64, 0x6c, 0x65,
0x72, 0x12, 0x3d, 0x0a, 0x06, 0x6c, 0x69, 0x67, 0x68, 0x74, 0x73, 0x18, 0x05, 0x20, 0x03, 0x28,
0x0b, 0x32, 0x25, 0x2e, 0x73, 0x74, 0x61, 0x74, 0x65, 0x2e, 0x54, 0x72, 0x61, 0x69, 0x6e, 0x43,
0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x53, 0x74, 0x61, 0x74, 0x65, 0x2e, 0x43, 0x6f, 0x6e, 0x74,
0x72, 0x6f, 0x6c, 0x4c, 0x69, 0x67, 0x68, 0x74, 0x52, 0x06, 0x6c, 0x69, 0x67, 0x68, 0x74, 0x73,
0x2a, 0x37, 0x0a, 0x0b, 0x53, 0x65, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x54, 0x79, 0x70, 0x65, 0x12,
0x07, 0x0a, 0x03, 0x41, 0x6e, 0x79, 0x10, 0x00, 0x12, 0x08, 0x0a, 0x04, 0x41, 0x78, 0x6c, 0x65,
0x10, 0x01, 0x12, 0x09, 0x0a, 0x05, 0x4c, 0x6f, 0x67, 0x69, 0x63, 0x10, 0x02, 0x12, 0x0a, 0x0a,
0x06, 0x50, 0x68, 0x79, 0x73, 0x69, 0x63, 0x10, 0x03, 0x42, 0x67, 0x0a, 0x25, 0x63, 0x6c, 0x75,
0x62, 0x2e, 0x6a, 0x6f, 0x79, 0x6c, 0x69, 0x6e, 0x6b, 0x2e, 0x62, 0x6a, 0x72, 0x74, 0x73, 0x73,
0x2e, 0x61, 0x74, 0x73, 0x2e, 0x76, 0x65, 0x72, 0x69, 0x66, 0x79, 0x2e, 0x70, 0x72, 0x6f, 0x74,
0x6f, 0x73, 0x42, 0x10, 0x44, 0x65, 0x76, 0x69, 0x63, 0x65, 0x53, 0x74, 0x61, 0x74, 0x65, 0x50,
0x72, 0x6f, 0x74, 0x6f, 0x5a, 0x2c, 0x6a, 0x6f, 0x79, 0x6c, 0x69, 0x6e, 0x6b, 0x2e, 0x63, 0x6c,
0x75, 0x62, 0x2f, 0x62, 0x6a, 0x2d, 0x72, 0x74, 0x73, 0x74, 0x73, 0x2d, 0x73, 0x65, 0x72, 0x76,
0x65, 0x72, 0x2f, 0x64, 0x74, 0x6f, 0x2f, 0x73, 0x74, 0x61, 0x74, 0x65, 0x5f, 0x70, 0x72, 0x6f,
0x74, 0x6f, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33,
} }
var ( var (

2
go.mod
View File

@ -100,3 +100,5 @@ require (
gopkg.in/ini.v1 v1.67.0 // indirect gopkg.in/ini.v1 v1.67.0 // indirect
gopkg.in/yaml.v3 v3.0.1 // indirect gopkg.in/yaml.v3 v3.0.1 // indirect
) )
require github.com/yousifnimah/Cryptx v1.0.1

2
go.sum
View File

@ -222,6 +222,8 @@ github.com/ugorji/go/codec v1.2.11 h1:BMaWp1Bb6fHwEtbplGBGJ498wD+LKlNSl25MjdZY4d
github.com/ugorji/go/codec v1.2.11/go.mod h1:UNopzCgEMSXjBc6AOMqYvWC1ktqTAfzJZUZgYf6w6lg= github.com/ugorji/go/codec v1.2.11/go.mod h1:UNopzCgEMSXjBc6AOMqYvWC1ktqTAfzJZUZgYf6w6lg=
github.com/yohamta/donburi v1.3.9 h1:sYAPaelSnxmoTGjgH9ZlYt4pUKrnwvAv4YGXxLZCK6E= github.com/yohamta/donburi v1.3.9 h1:sYAPaelSnxmoTGjgH9ZlYt4pUKrnwvAv4YGXxLZCK6E=
github.com/yohamta/donburi v1.3.9/go.mod h1:5QkyraUjkzbMVTD2b8jaPFy1Uwjm/zdFN1c1lZGaezg= github.com/yohamta/donburi v1.3.9/go.mod h1:5QkyraUjkzbMVTD2b8jaPFy1Uwjm/zdFN1c1lZGaezg=
github.com/yousifnimah/Cryptx v1.0.1 h1:oZbB6CjvqOzkmoghsncb3/4sV2As8nqOJCjZPd08Xdw=
github.com/yousifnimah/Cryptx v1.0.1/go.mod h1:vmpiwqtg+fR+KaAisCdz2+6k30jWb+/X7EyUysDKh0U=
github.com/yuin/goldmark v1.4.13/go.mod h1:6yULJ656Px+3vBD8DxQVa3kxgyrAnzto9xy5taEt/CY= github.com/yuin/goldmark v1.4.13/go.mod h1:6yULJ656Px+3vBD8DxQVa3kxgyrAnzto9xy5taEt/CY=
go.uber.org/atomic v1.9.0 h1:ECmE8Bn/WFTYwEW/bpKD3M8VtR/zQVbavAoalC1PYyE= go.uber.org/atomic v1.9.0 h1:ECmE8Bn/WFTYwEW/bpKD3M8VtR/zQVbavAoalC1PYyE=
go.uber.org/atomic v1.9.0/go.mod h1:fEN4uk6kAWBTFdckzkM89CLk9XfWZrxpCo0nPH17wJc= go.uber.org/atomic v1.9.0/go.mod h1:fEN4uk6kAWBTFdckzkM89CLk9XfWZrxpCo0nPH17wJc=

View File

@ -275,23 +275,16 @@ func handlerSectionState(w ecs.World, uid string) *state_proto.SectionState {
//fmt.Printf("id=%s的信号机不存在", uid) //fmt.Printf("id=%s的信号机不存在", uid)
return nil return nil
} }
if entry.HasComponent(component.PhysicalSectionStateType) { //计轴区段 if entry.HasComponent(component.AxleManagerType) { //计轴区段
sectionState := &state_proto.SectionState{} axleManager := component.AxleManagerType.Get(entry)
axleState := component.PhysicalSectionStateType.Get(entry) sectionState := &state_proto.SectionState{
sectionState.Occupied = axleState.Occ Occupied: axleManager.Occupied,
sectionState.AxleFault = entry.HasComponent(component.AxleSectionFaultTag) AxleFault: entry.HasComponent(component.AxleSectionForceOccupied),
AxleDrst: false,
wd := entity.GetWorldData(w) AxlePdrst: axleManager.PDRST,
sectionModel := wd.Repo.FindPhysicalSection(uid)
faDcAxleDeviceEntry := entity.FindAxleManageDevice(wd, sectionModel.CentralizedStation())
if faDcAxleDeviceEntry != nil {
faDcAxleDevice := component.AxleManageDeviceType.Get(faDcAxleDeviceEntry)
axleRuntime := faDcAxleDevice.FindAdr(uid)
if axleRuntime != nil {
sectionState.AxleDrst = axleRuntime.Drst
sectionState.AxlePdrst = axleRuntime.Pdrst
}
} }
sectionState.Occupied = axleManager.Occupied
sectionState.AxleFault = entry.HasComponent(component.AxleSectionForceOccupied)
return sectionState return sectionState
} else if entry.HasComponent(component.TrackCircuitType) { //轨道电路 } else if entry.HasComponent(component.TrackCircuitType) { //轨道电路
sectionState := &state_proto.SectionState{ sectionState := &state_proto.SectionState{

@ -1 +1 @@
Subproject commit ef7e469175d27182823461972998049692fb425f Subproject commit 3182e867c12d73bd4c75182459d3b9fae670653c

@ -1 +1 @@
Subproject commit 2f5d8c3cfdf06ced1a0b0a50f47f9353c441e196 Subproject commit 0c2a7613104f859e83091d1f6379e6e2fa1990ad

View File

@ -37,6 +37,7 @@ type serviceContext struct {
client udp.UdpClient client udp.UdpClient
cancelFunc context.CancelFunc cancelFunc context.CancelFunc
ciSectionIndexConfigs []*proto.CiSectionCodePoint ciSectionIndexConfigs []*proto.CiSectionCodePoint
sectionStateMap map[string]*fi.AxleSectionState //存储预复位/复位请求的返回结果
remoteAddr uint16 //联锁地址 从配置中的16进制字符串转来的 remoteAddr uint16 //联锁地址 从配置中的16进制字符串转来的
localAddr uint16 //计轴地址 从配置中的16进制字符串转来的 localAddr uint16 //计轴地址 从配置中的16进制字符串转来的
@ -175,8 +176,10 @@ func initServiceContext(rsspConfig config.RsspAxleConfig, ref *proto.Centralized
sim: simulation, sim: simulation,
config: rsspConfig, config: rsspConfig,
ciSectionIndexConfigs: ref.SectionCodePoints, ciSectionIndexConfigs: ref.SectionCodePoints,
remoteAddr: uint16(sourceAddr), sectionStateMap: make(map[string]*fi.AxleSectionState),
localAddr: uint16(targetAddr),
remoteAddr: uint16(sourceAddr),
localAddr: uint16(targetAddr),
remoteSid1: uint32(remoteSid1), remoteSid1: uint32(remoteSid1),
remoteSid2: uint32(remoteSid2), remoteSid2: uint32(remoteSid2),
@ -260,23 +263,26 @@ func (s *serviceContext) runCollectTask(ctx context.Context) {
func (s *serviceContext) collect() *msg.RsdMsgBuilder { func (s *serviceContext) collect() *msg.RsdMsgBuilder {
worldData := entity.GetWorldData(s.sim.World) worldData := entity.GetWorldData(s.sim.World)
amdEntry := entity.FindAxleManageDevice(worldData, s.config.StationCode)
amd := component.AxleManageDeviceType.Get(amdEntry)
stateInfos := msg.StateInfos{} stateInfos := msg.StateInfos{}
for _, cfg := range s.ciSectionIndexConfigs { for _, cfg := range s.ciSectionIndexConfigs {
sectionRuntime := amd.Adrs[cfg.SectionId] entry := worldData.EntityMap[cfg.SectionId]
sectionEntry, ok := entity.GetEntityByUid(s.sim.World, cfg.SectionId) if entry == nil {
sectionState := component.PhysicalSectionStateType.Get(sectionEntry) logger().Error(fmt.Sprintf("没有id[%s]的区段实体", cfg.SectionId))
if !ok { }
continue am := component.AxleManagerType.Get(entry)
stateInfo := &msg.StateInfo{
CLR: !am.Occupied,
OCC: am.Occupied,
}
stateInfos = append(stateInfos, stateInfo)
//预复位/复位驱动反馈状态
state := s.sectionStateMap[cfg.SectionId]
delete(s.sectionStateMap, cfg.SectionId)
if state != nil {
stateInfo.RAC = state.Rac
stateInfo.RJO = state.Rjo
stateInfo.RJT = state.Rjt
} }
stateInfos = append(stateInfos, &msg.StateInfo{
CLR: !sectionState.Occ,
OCC: sectionState.Occ,
RAC: sectionRuntime.Rac,
RJO: sectionRuntime.Rjo,
RJT: sectionRuntime.Rjt,
})
} }
userData := []byte{0x00} //检查字节 userData := []byte{0x00} //检查字节
userData = append(userData, stateInfos.Encode()...) userData = append(userData, stateInfos.Encode()...)
@ -317,6 +323,9 @@ func (s *serviceContext) runHandleMsgTask(ctx context.Context) {
} }
}() }()
for { for {
if len(s.msgChan) > 10 {
logger().Warn(fmt.Sprintf("消息处理耗时过长,消息队列长度:%d", len(s.msgChan)))
}
select { select {
case <-ctx.Done(): case <-ctx.Done():
return return
@ -369,13 +378,19 @@ func (s *serviceContext) handleRsdMsg(data []byte) {
//驱动 //驱动
for i, cmdInfo := range cmdInfos { for i, cmdInfo := range cmdInfos {
sectionIndexConfig := s.ciSectionIndexConfigs[i] sectionIndexConfig := s.ciSectionIndexConfigs[i]
err := fi.AxleSectionDrstDrive(s.sim.World, sectionIndexConfig.SectionId, cmdInfo.DRST) if cmdInfo.PDRST {
if err != nil { state, err := fi.AxleSectionPdrstDrive(s.sim.World, sectionIndexConfig.SectionId)
logger().Error("驱动计轴直接复位出错", "error", err) if err != nil {
logger().Error("计轴预复位驱动出错", "error", err)
}
s.sectionStateMap[sectionIndexConfig.SectionId] = state
} }
err = fi.AxleSectionPdrstDrive(s.sim.World, sectionIndexConfig.SectionId, cmdInfo.PDRST) if cmdInfo.DRST {
if err != nil { state, err := fi.AxleSectionDrstDrive(s.sim.World, sectionIndexConfig.SectionId)
logger().Error("驱动计轴预复位出错", "error", err) if err != nil {
logger().Error("计轴复位驱动出错", "error", err)
}
s.sectionStateMap[sectionIndexConfig.SectionId] = state
} }
} }
} }

View File

@ -59,11 +59,14 @@ func (s *btmCanetClient) GetState() state_proto.BTMState {
detector := s.baliseDetector detector := s.baliseDetector
var telegram string var telegram string
var tel128 string
info := detector.eq[len(detector.eq)-1] info := detector.eq[len(detector.eq)-1]
if /*detector.aboveBalise &&*/ info != nil && len(info.telegram) != 0 { if /*detector.aboveBalise &&*/ info != nil && len(info.telegram) != 0 {
telegram = fmt.Sprintf("%X", info.telegram) telegram = fmt.Sprintf("%X", info.telegram)
tel128 = fmt.Sprintf("%X", info.telegram128)
} else { } else {
telegram = strings.Repeat("00", balise_const.UserTelegramByteLen) telegram = strings.Repeat("00", balise_const.UserTelegramByteLen)
tel128 = strings.Repeat("00", balise_const.TelegramByteLen)
} }
var dis int64 var dis int64
if info != nil { if info != nil {
@ -74,6 +77,7 @@ func (s *btmCanetClient) GetState() state_proto.BTMState {
BaliseCount: uint32(detector.baliseCounter), BaliseCount: uint32(detector.baliseCounter),
MessageCounter: uint32(detector.messageCounter), MessageCounter: uint32(detector.messageCounter),
Telegram: telegram, Telegram: telegram,
Telegram128: tel128,
Distance: dis, Distance: dis,
AboveBalise: detector.aboveBalise, AboveBalise: detector.aboveBalise,
} }
@ -163,7 +167,7 @@ func (s *btmCanetClient) handleCanetFrames(cfs []byte) {
dms := make([]*message.CanetFrame, 0, 16) //13个应答器报文数据帧+TimeA帧+TimeB帧+结束帧 dms := make([]*message.CanetFrame, 0, 16) //13个应答器报文数据帧+TimeA帧+TimeB帧+结束帧
for cfi := 0; cfi < cfSum; cfi++ { for cfi := 0; cfi < cfSum; cfi++ {
cfStart := cfi * 13 cfStart := cfi * 13
cf := message.NewCanetFrame(cfs[cfStart:cfStart+13], false) cf := message.NewCanetFrame(cfs[cfStart : cfStart+13])
// //
switch cf.CanFrameType() { switch cf.CanFrameType() {
case message.CfReq: case message.CfReq:
@ -263,7 +267,7 @@ func (s *btmCanetClient) rspResendToAtp() {
// 当未收到应答器报文时响应:时间同步帧、状态应答帧 // 当未收到应答器报文时响应:时间同步帧、状态应答帧
func (s *btmCanetClient) rspToAtp(sb *BtmAntennaScanningBaliseInfo) { func (s *btmCanetClient) rspToAtp(sb *BtmAntennaScanningBaliseInfo) {
//BTM状态 //BTM状态
statusF := message.NewBtmStatusRspFrame(s.atpReqSn, false) statusF := message.NewBtmStatusRspFrame(s.atpReqSn)
btmStatus := s.createTrainBtmStatus() btmStatus := s.createTrainBtmStatus()
statusF.AntennaFault = btmStatus.AntennaFault statusF.AntennaFault = btmStatus.AntennaFault
@ -284,9 +288,9 @@ func (s *btmCanetClient) rspToAtp(sb *BtmAntennaScanningBaliseInfo) {
//true-收到应答器报文 //true-收到应答器报文
isRcvTelegram := sb != nil && len(sb.telegram) > 0 isRcvTelegram := sb != nil && len(sb.telegram) > 0
if isRcvTelegram { //当收到应答器报文时响应:时间同步帧、状态应答帧、数据帧 if isRcvTelegram { //当收到应答器报文时响应:时间同步帧、状态应答帧、数据帧
statusDataCf, statusDataCfOk := message.CreateBtmRspFramesData(statusF, sb.telegram, false, s.btmTime.TkNow(), s.btmTime.TkNow(), s.btmTime.TkNow(), false) statusDataCf, statusDataCfOk := message.CreateBtmRspFramesData(statusF, sb.telegram, false, s.btmTime.TkNow(), s.btmTime.TkNow(), s.btmTime.TkNow())
if statusDataCfOk { if statusDataCfOk {
timeSyncF := message.NewBtmTimeSyncCheckFrame(s.atpReqSn, false) timeSyncF := message.NewBtmTimeSyncCheckFrame(s.atpReqSn)
timeSyncF.T2 = s.btmTime.BtmTk timeSyncF.T2 = s.btmTime.BtmTk
timeSyncF.T3 = s.btmTime.TkNow() timeSyncF.T3 = s.btmTime.TkNow()
s.sendCanetFrame(timeSyncF.Encode().Encode()) s.sendCanetFrame(timeSyncF.Encode().Encode())
@ -297,7 +301,7 @@ func (s *btmCanetClient) rspToAtp(sb *BtmAntennaScanningBaliseInfo) {
slog.Warn("BtmCanetClient应答帧、数据帧编码失败") slog.Warn("BtmCanetClient应答帧、数据帧编码失败")
} }
} else { //当未收到应答器报文时响应:时间同步帧、状态应答帧 } else { //当未收到应答器报文时响应:时间同步帧、状态应答帧
timeSyncF := message.NewBtmTimeSyncCheckFrame(s.atpReqSn, false) timeSyncF := message.NewBtmTimeSyncCheckFrame(s.atpReqSn)
timeSyncF.T2 = s.btmTime.BtmTk timeSyncF.T2 = s.btmTime.BtmTk
timeSyncF.T3 = s.btmTime.TkNow() timeSyncF.T3 = s.btmTime.TkNow()
s.sendCanetFrame(timeSyncF.Encode().Encode()) s.sendCanetFrame(timeSyncF.Encode().Encode())

View File

@ -39,12 +39,13 @@ type BtmAntennaToBaliseInfo struct {
BaliseType proto.Transponder_Type //应答器类型 BaliseType proto.Transponder_Type //应答器类型
} }
type BtmAntennaScanningBaliseInfo struct { type BtmAntennaScanningBaliseInfo struct {
BaliseId string //应答器id BaliseId string //应答器id
Time time.Time //应答器预计被BTM天线激活的时刻 Time time.Time //应答器预计被BTM天线激活的时刻
active bool //true-激活过,即列车扫过 active bool //true-激活过,即列车扫过
telegram []byte //应答器报文 telegram []byte //应答器用户报文
Distance int64 //BTM天线中心到应答器的距离mm telegram128 []byte //应答器报文
BaliseType proto.Transponder_Type //应答器类型 Distance int64 //BTM天线中心到应答器的距离mm
BaliseType proto.Transponder_Type //应答器类型
} }
// BaliseDetector 车载BTM天线应答器探测器 // BaliseDetector 车载BTM天线应答器探测器
@ -88,7 +89,7 @@ func (t *BaliseDetector) detect(wd *component.WorldData, repo *repository.Reposi
if curExpect != nil && curExpect.Time.UnixMilli()-curTime.UnixMilli() < 20 { //20ms if curExpect != nil && curExpect.Time.UnixMilli()-curTime.UnixMilli() < 20 { //20ms
//slog.Debug("将要激活应答器", "BaliseId", curExpect.BaliseId, "ActiveTime", dt) //slog.Debug("将要激活应答器", "BaliseId", curExpect.BaliseId, "ActiveTime", dt)
telegram := t.rcvTelegram(wd, curExpect.BaliseId) telegram, utel := t.rcvTelegram(wd, curExpect.BaliseId)
if curExpect.Distance <= 50 { if curExpect.Distance <= 50 {
btm_vobc.Default().AppendBaliseMsgForTrain(vobcBtm, curExpect.BaliseId, telegram, curTime.UnixMilli()) btm_vobc.Default().AppendBaliseMsgForTrain(vobcBtm, curExpect.BaliseId, telegram, curTime.UnixMilli())
@ -97,7 +98,8 @@ func (t *BaliseDetector) detect(wd *component.WorldData, repo *repository.Reposi
if t.addExpectedBalise(curExpect) { if t.addExpectedBalise(curExpect) {
t.baliseCounterAdd1() //应答器计数器 t.baliseCounterAdd1() //应答器计数器
if len(telegram) > 0 { if len(telegram) > 0 {
curExpect.telegram = telegram curExpect.telegram = utel
curExpect.telegram128 = telegram
t.baliseMessageCounterAdd1() //报文计数器 t.baliseMessageCounterAdd1() //报文计数器
} }
@ -137,14 +139,17 @@ func (t *BaliseDetector) baliseMessageCounterAdd1() {
} }
// BTM天线接收应答器报文(线程不安全) // BTM天线接收应答器报文(线程不安全)
func (t *BaliseDetector) rcvTelegram(wd *component.WorldData, baliseId string) []byte { func (t *BaliseDetector) rcvTelegram(wd *component.WorldData, baliseId string) ([]byte, []byte) {
entry, ok := wd.EntityMap[baliseId] entry, ok := wd.EntityMap[baliseId]
if ok { if ok {
if component.BaliseWorkStateType.Get(entry).Work { if component.BaliseWorkStateType.Get(entry).Work {
return component.BaliseFixedTelegramType.Get(entry).Telegram tel := component.BaliseFixedTelegramType.Get(entry).Telegram
utel := component.BaliseFixedTelegramType.Get(entry).UserTelegram
return tel, utel
//return component.BaliseFixedTelegramType.Get(entry).Telegram
} }
} }
return nil return nil, nil
} }
// true-新增false-更新 // true-新增false-更新

View File

@ -2,9 +2,14 @@
package beijing12 package beijing12
import ( import (
"bytes"
"context" "context"
"fmt" "fmt"
"joylink.club/bj-rtsts-server/sys_error"
"joylink.club/bj-rtsts-server/third_party/tcp" "joylink.club/bj-rtsts-server/third_party/tcp"
"joylink.club/bj-rtsts-server/ts/simulation/wayside/memory"
"joylink.club/rtsssimulation/fi"
"joylink.club/rtsssimulation/repository"
"log/slog" "log/slog"
"runtime/debug" "runtime/debug"
"sync" "sync"
@ -14,7 +19,11 @@ import (
"joylink.club/bj-rtsts-server/third_party/message" "joylink.club/bj-rtsts-server/third_party/message"
) )
const logTag = "[北京12号线联锁通信]" var ( //日志
logTag = "[北京12号线联锁通信]"
privateLogger *slog.Logger
loggerInit sync.Once
)
// 联锁代理通信接口 // 联锁代理通信接口
type InterlockMessageManager interface { type InterlockMessageManager interface {
@ -22,15 +31,15 @@ type InterlockMessageManager interface {
HandleInterlockDriverInfo(code string, b []byte) HandleInterlockDriverInfo(code string, b []byte)
} }
// 联锁接口 //// 联锁接口
type InterlockProxy interface { //type InterlockProxy interface {
// 启动联锁消息功能 // // 启动联锁消息功能
Start(manager InterlockMessageManager) // Start(manager InterlockMessageManager)
// 停止联锁消息功能 // // 停止联锁消息功能
Stop() // Stop()
} //}
var interlockMap = make(map[string]InterlockProxy) var interlockMap = make(map[string]*interlockProxy)
var initMutex sync.Mutex var initMutex sync.Mutex
//func Default(c *config.InterlockConfig) InterlockProxy { //func Default(c *config.InterlockConfig) InterlockProxy {
@ -42,9 +51,25 @@ var initMutex sync.Mutex
// return interlockMap[c.Code] // return interlockMap[c.Code]
//} //}
func Start(c *config.InterlockConfig, manager InterlockMessageManager) { func Start(c *config.InterlockConfig, simulation *memory.VerifySimulation, baliseList []*repository.Transponder) {
proxy := &interlockProxy{runConfig: c} initMutex.Lock()
proxy.Start(manager) defer initMutex.Unlock()
proxy := &interlockProxy{
runConfig: c,
indexBalise: make(map[byte]map[byte]*repository.Transponder),
fromCIBytes: make([]byte, 0, fromCIBytesLen),
}
for _, balise := range simulation.Repo.TransponderList() {
if balise.LeuIndex() == 0 {
continue
}
leuIndex := byte(balise.LeuIndex())
if proxy.indexBalise[leuIndex] == nil {
proxy.indexBalise[leuIndex] = make(map[byte]*repository.Transponder)
}
proxy.indexBalise[leuIndex][byte(balise.IndexInLeu())] = balise
}
proxy.Start(simulation)
interlockMap[c.Code] = proxy interlockMap[c.Code] = proxy
} }
@ -58,49 +83,43 @@ func Stop(c *config.InterlockConfig) {
type interlockProxy struct { type interlockProxy struct {
tcpClient *tcp.TcpClient tcpClient *tcp.TcpClient
manager InterlockMessageManager simulation *memory.VerifySimulation
collectInfoTaskCancel context.CancelFunc collectInfoTaskCancel context.CancelFunc
runConfig *config.InterlockConfig runConfig *config.InterlockConfig
// 按索引存储的应答器leu索引-leu内索引
indexBalise map[byte]map[byte]*repository.Transponder
// 联锁发送的数据过长,多个包才能凑成完成报文
fromCIBytes []byte
// 序列号
serialNumber uint8
} }
// 驱动信息进行转发 func (i *interlockProxy) Start(simulation *memory.VerifySimulation) {
func (i *interlockProxy) handleDriverInfo(b []byte) {
slog.Info(fmt.Sprintf("%s收到联锁驱动继电器数据%x", logTag, b))
handler := i.manager
if handler != nil {
handler.HandleInterlockDriverInfo(i.runConfig.Code, b)
}
}
func (i *interlockProxy) Start(manager InterlockMessageManager) {
if i.runConfig == nil || i.runConfig.Ip == "" || !i.runConfig.Open { if i.runConfig == nil || i.runConfig.Ip == "" || !i.runConfig.Open {
return return
} }
if manager == nil { if simulation == nil {
panic(fmt.Sprintf("%s启动联锁消息服务错误: InterlockMessageManager不能为nil", logTag)) panic(fmt.Sprintf("%s启动联锁消息服务错误: InterlockMessageManager不能为nil", logTag))
} }
if i.manager != nil { if i.simulation != nil {
panic(fmt.Sprintf("%s启动联锁消息服务错误: 存在正在运行的任务", logTag)) panic(fmt.Sprintf("%s启动联锁消息服务错误: 存在正在运行的任务", logTag))
} }
i.initInterlockProxy() i.initInterlockProxy()
ctx, cancel := context.WithCancel(context.Background()) ctx, cancel := context.WithCancel(context.Background())
go i.collectInfoStateTask(ctx) go i.collectInfoStateTask(ctx)
i.collectInfoTaskCancel = cancel i.collectInfoTaskCancel = cancel
i.manager = manager i.simulation = simulation
} }
// 采集电路状态发送间隔,单位ms // 采集电路状态发送间隔,单位ms
const InterlockMessageSendInterval = 300 const InterlockMessageSendInterval = 300
// 序列号
var serialNumber uint8
// 定时发送采集电路状态任务 // 定时发送采集电路状态任务
func (i *interlockProxy) collectInfoStateTask(ctx context.Context) { func (i *interlockProxy) collectInfoStateTask(ctx context.Context) {
defer func() { defer func() {
if err := recover(); err != nil { if err := recover(); err != nil {
slog.Error(logTag+"定时发送道岔状态任务异常", "error", err, "stack", string(debug.Stack())) logger().Error(logTag+"定时发送道岔状态任务异常", "error", err, "stack", string(debug.Stack()))
debug.PrintStack()
} }
}() }()
for { for {
@ -109,15 +128,15 @@ func (i *interlockProxy) collectInfoStateTask(ctx context.Context) {
return return
default: default:
} }
collectInfoState := i.manager.CollectInterlockRelayInfo(i.runConfig.Code) collectInfoState := i.simulation.CollectInterlockRelayInfo(i.runConfig.Code)
if collectInfoState != nil { if collectInfoState != nil {
serialNumber++ i.serialNumber++
collectInfoState.SetSerialNumber(serialNumber) collectInfoState.SetSerialNumber(i.serialNumber)
err := i.tcpClient.Send(collectInfoState.Encode()) err := i.tcpClient.Send(collectInfoState.Encode())
if err != nil { if err != nil {
slog.Error(fmt.Sprintf("%s向联锁发送继电器状态失败:%s", logTag, err)) logger().Error(fmt.Sprintf("向联锁发送继电器状态失败:%s", err))
} else { } else {
slog.Info(fmt.Sprintf("%s向联锁发送继电器数据成功:%x", logTag, collectInfoState.Encode())) logger().Info(fmt.Sprintf("向联锁发送继电器数据成功:%x", collectInfoState.Encode()))
} }
} }
time.Sleep(time.Millisecond * InterlockMessageSendInterval) time.Sleep(time.Millisecond * InterlockMessageSendInterval)
@ -135,24 +154,70 @@ func (i *interlockProxy) Stop() {
if i.collectInfoTaskCancel != nil { if i.collectInfoTaskCancel != nil {
i.collectInfoTaskCancel() i.collectInfoTaskCancel()
} }
i.manager = nil i.simulation = nil
} }
func (i *interlockProxy) initInterlockProxy() { func (i *interlockProxy) initInterlockProxy() {
client, err := tcp.StartTcpClient(fmt.Sprintf("%s:%d", i.runConfig.Ip, i.runConfig.RemotePort), i.handleDriveInfo, func(err error) { client, err := tcp.StartTcpClient(fmt.Sprintf("%s:%d", i.runConfig.Ip, i.runConfig.RemotePort), i.handleFromCiData, func(err error) {
slog.Error(fmt.Sprintf("%sTCP客户端读取数据出错终止通信服务%s", logTag, err)) logger().Error(fmt.Sprintf("TCP客户端读取数据出错终止通信服务%s", err))
i.Stop() i.Stop()
}) })
if err != nil { if err != nil {
panic(fmt.Sprintf("%s启动TCP客户端失败%s", logTag, err)) panic(sys_error.New(fmt.Sprintf("%s启动TCP客户端失败", logTag), err))
} }
i.tcpClient = client i.tcpClient = client
} }
func (i *interlockProxy) handleDriveInfo(n int, data []byte) { func (i *interlockProxy) handleFromCiData(n int, data []byte) {
data = data[:n] data = data[:n]
slog.Info(fmt.Sprintf("%s收到联锁驱动继电器数据%x", logTag, data)) logger().Info(fmt.Sprintf("收到联锁驱动及应答器报文数据,长度%d", n))
if i.manager != nil { if len(i.fromCIBytes) != 0 { //报文头已经存进去了
i.manager.HandleInterlockDriverInfo(i.runConfig.Code, data) i.fromCIBytes = append(i.fromCIBytes, data...)
if len(i.fromCIBytes) < fromCIBytesLen { //当存储的报文长度不足预期长度
return
}
} else if bytes.HasPrefix(data, []byte{0xff, 0xff}) { //判断是否是报文头
i.fromCIBytes = append(i.fromCIBytes, data...)
return
} else {
return
}
//处理联锁报文
msg := &fromCiMsg{}
err := msg.decode(i.fromCIBytes)
logger().Info(fmt.Sprintf("解析完整联锁驱动及应答器报文数据:%x", i.fromCIBytes))
i.fromCIBytes = i.fromCIBytes[:0] //清空联锁报文存储
if err != nil {
logger().Error(fmt.Sprintf("解析来自CI的数据出错%s", err.Error()))
return
}
//处理驱动数据
if i.simulation != nil {
logger().Info(fmt.Sprintf("解析出的驱动数据:%x", msg.driveData))
i.simulation.HandleInterlockDriverInfo(i.runConfig.Code, msg.driveData)
}
//处理应答器数据
for _, datum := range msg.baliseTelegramData {
indexBalise2 := i.indexBalise[datum.leuIndex]
if indexBalise2 == nil {
logger().Error(fmt.Sprintf("没有leuIndex[%d]的应答器", datum.leuIndex))
continue
}
balise := indexBalise2[datum.index]
if balise == nil {
logger().Error(fmt.Sprintf("没有leuIndex[%d]leu内索引[%d]的应答器", datum.leuIndex, datum.index))
continue
}
err := fi.BaliseUpdateVariableTelegram(i.simulation.World, balise.Id(), datum.telegram, false)
if err != nil {
logger().Error(fmt.Sprintf("更新leuIndex[%d]leu内索引[%d]的应答器数据出错:%s", datum.leuIndex, datum.index, err.Error()))
}
} }
} }
func logger() *slog.Logger {
loggerInit.Do(func() {
privateLogger = slog.Default().With("tag", logTag)
})
return privateLogger
}

79
third_party/interlock/beijing12/msg.go vendored Normal file
View File

@ -0,0 +1,79 @@
package beijing12
import (
"errors"
"fmt"
"joylink.club/bj-rtsts-server/sys_error"
"joylink.club/bj-rtsts-server/util/myreader"
)
// 后续如果有其它线路还用此协议,需要将这些常量做成配置
const (
syncZoneStateLen = 1289 //同步区状态字节数
driveDataLen = 14 //驱动数据长度
baliseTelegramDataSize = 28 //应答器报文数据个数
baliseTelegramMsgLen = 131 //应答器报文数据长度
)
// 来自联锁的报文字节长度
var fromCIBytesLen = 8 + syncZoneStateLen + driveDataLen + baliseTelegramMsgLen*baliseTelegramDataSize
// fromCiMsg 来自联锁的消息
type fromCiMsg struct {
head1 byte // 包头1 0xFF
head2 byte // 包头2 0xFF
typeCode byte // 类型码
seqNum byte // 序列号
reserve []byte // 预留2字节
syncZoneState []byte // 同步区状态(目前不用处理)
driveData []byte // 驱动数据
baliseTelegramData []*baliseTelegramMsg // 应答器报文数据
tail []byte // 包尾 0x0000
}
// driveDataLen 表示驱动数据字节数baliseTelegramDataLen 表示应答器报文数据个数
func (f *fromCiMsg) decode(data []byte) error {
if len(data) != fromCIBytesLen {
return errors.New(fmt.Sprintf("%s联锁数据长度期望值[%d],实际值[%d]", logTag, fromCIBytesLen, len(data)))
}
reader := myreader.NewReader(data)
f.head1 = reader.ReadByte()
f.head2 = reader.ReadByte()
f.typeCode = reader.ReadByte()
f.seqNum = reader.ReadByte()
f.reserve = reader.ReadBytes(2)
f.syncZoneState = reader.ReadBytes(syncZoneStateLen)
f.driveData = reader.ReadBytes(driveDataLen)
for i := 0; i < baliseTelegramDataSize; i++ {
baliseBytes := reader.ReadBytes(baliseTelegramMsgLen)
baliseMsg := &baliseTelegramMsg{}
err := baliseMsg.decode(baliseBytes)
if err != nil {
return err
}
f.baliseTelegramData = append(f.baliseTelegramData, baliseMsg)
}
f.tail = reader.ReadBytes(2)
if reader.Err != nil {
return errors.New(fmt.Sprintf("读取字节出错:%s", reader.Err))
}
return nil
}
type baliseTelegramMsg struct {
leuIndex byte // LEU索引
index byte // LEU内部应答器的索引
reserve byte // 预留
telegram []byte // 应答器报文 128字节
}
func (b *baliseTelegramMsg) decode(data []byte) error {
if len(data) != 131 {
return sys_error.New(fmt.Sprintf("%s应答器报文数据长度不对%d", logTag, len(data)))
}
b.leuIndex = data[0]
b.index = data[1]
b.reserve = data[2]
b.telegram = data[3:]
return nil
}

File diff suppressed because one or more lines are too long

View File

@ -67,7 +67,7 @@ func (acc *Accelerometer) BuildCanData() []byte {
appData = append(appData, accData...) appData = append(appData, accData...)
appData = append(appData, byte(0)) appData = append(appData, byte(0))
canId := CanFrameId{ID1: 0xff, ID2: 0xff, ID3: 0xff, ID4: 0xff} canId := CanFrameId{ID1: 0xff, ID2: 0xff, ID3: 0xff, ID4: 0xff}
canNet := &CanetFrame{FF: false, RTR: false, CanLen: 7, CanId: canId, CanData: appData, IsTrainPcSim: false} canNet := &CanetFrame{FF: false, RTR: false, CanLen: 7, CanId: canId, CanData: appData}
return canNet.Encode() return canNet.Encode()
} }
func (acc *Accelerometer) Encode() []byte { func (acc *Accelerometer) Encode() []byte {

94
third_party/message/btm_data.go vendored Normal file
View File

@ -0,0 +1,94 @@
package message
import "encoding/binary"
//数据帧0x80+扩展类型),一个CAN帧只能存储8个字节对于一个应答器报文分片到多个CAN数据帧中
// BtmDataMessageFrame 数据帧-应答器报文
// offset = [0x00,0x0c] 共13个即可用于存储应答器报文的共104个字节
// BtmDataMessageTimeAFrame 数据帧-时间戳A
// offset = 0x0d
// BtmDataMessageTimeBFrame 数据帧-时间戳B
// offset = 0x0e
// BtmDataMessageEndFrame 数据帧-结束
// offset = 0x7f
const (
DATA_TIME_A_OFFSET = 0x0d
DATA_TIME_B_OFFSET = 0x0e
DATA_END_OFFSET = 0x7f
)
type BtmDataMessageAtpFrame struct {
//帧ID
FId CanFrameId
//8字节,应答器报文片段
Message []byte
}
type BtmDataMessageAtpTimeAndEndFrame struct {
//帧ID
FId CanFrameId
//时间戳A
Time uint32
//CRC
Crc32 uint32
}
func CreateBtmDataMessageDataAtpFrame(sn byte, offset byte) *BtmDataMessageAtpFrame {
return &BtmDataMessageAtpFrame{
FId: *NewCanFrameId(CAN_ADDR_RSP_ATP, CAN_ADDR_RSP_BTM, 0x80+offset, sn),
}
}
func (f *BtmDataMessageAtpFrame) Encode() *BtmHeadFrame {
cf := &BtmHeadFrame{}
cf.CanId = f.FId
cf.CanLen = 8
dataBuf := make([]byte, 0, 8)
for _, data := range f.Message {
dataBuf = append(dataBuf, data)
}
cf.CanData = dataBuf
return cf
}
func (f *BtmDataMessageAtpFrame) Decode(cf *BtmHeadFrame) bool {
f.FId = cf.CanId
//
reader := NewCanBitsReader(cf.CanData, 8)
//
f.Message = make([]byte, 0, 8)
for c := 0; c < 8; c++ {
data, ok := reader.ReadByte()
if !ok {
return false
}
f.Message = append(f.Message, data)
}
//
return true
}
/////////////////////////////////////////////////////
func (atp *BtmDataMessageAtpTimeAndEndFrame) Encode() *BtmHeadFrame {
cf := &BtmHeadFrame{}
cf.CanId = atp.FId
cf.CanLen = 8
data := make([]byte, 0)
data = binary.BigEndian.AppendUint32(data, atp.Time)
data = binary.BigEndian.AppendUint32(data, atp.Crc32)
cf.CanData = data
return cf
}
func CreateBtmDataMessageTimeAtpFrame(sn byte, offset byte) *BtmDataMessageAtpTimeAndEndFrame {
return &BtmDataMessageAtpTimeAndEndFrame{FId: *NewCanFrameId(CAN_ADDR_RSP_ATP, CAN_ADDR_RSP_BTM, 0x80+offset, sn)}
}
////////////////////////////////////////////////////////////
func BtmDataMessageEndAtpFrame(sn byte) *BtmDataMessageAtpTimeAndEndFrame {
return &BtmDataMessageAtpTimeAndEndFrame{
FId: *NewCanFrameId(CAN_ADDR_RSP_ATP, CAN_ADDR_RSP_BTM, 0xff, sn),
}
}

67
third_party/message/btm_net.go vendored Normal file
View File

@ -0,0 +1,67 @@
package message
import (
"bytes"
"encoding/binary"
"fmt"
"strings"
)
// CanetFrame USR-CANET200_V1.0.7 设备 以太网-CAN 透传协议帧(12字节)
type BtmHeadFrame struct {
CanLen byte //CAN帧数据长度[0,8]CanData中有效数据字节数
CanId CanFrameId //CAN帧ID
CanData []byte //CAN帧数据8字节
}
func NewBtmHeadFrame(buf []byte) *BtmHeadFrame {
cf := &BtmHeadFrame{}
cf.Decode(buf)
return cf
}
func (p *BtmHeadFrame) Encode() []byte {
buf := make([]byte, 0)
//CAN 帧ID
frameId := uint32(p.CanId.ID1)<<21 | uint32(p.CanId.ID2)<<13 | uint32(p.CanId.ID3)<<5 | uint32(p.CanId.ID4)
buf = binary.BigEndian.AppendUint32(buf, frameId)
//CAN 帧数据
if len(p.CanData) != 8 {
panic(fmt.Sprintf("len(p.CanData)!=8 datalen:%v", len(p.CanData)))
}
buf = append(buf, p.CanData...)
return buf
}
func (p *BtmHeadFrame) Decode(buf []byte) {
bb := bytes.NewBuffer(buf)
var idSource uint32
binary.Read(bb, binary.BigEndian, &idSource)
data := make([]byte, bb.Len())
_, err := bb.Read(data)
if err != nil {
fmt.Println(err)
return
}
b1 := byte((idSource >> 21) & 0xFF)
b2 := byte((idSource >> 13) & 0xFF)
b3 := byte((idSource >> 5) & 0xFF)
b4 := byte(idSource & 0x1F)
p.CanId.ID1 = b1
p.CanId.ID2 = b2
p.CanId.ID3 = b3
p.CanId.ID4 = b4
p.CanData = data
}
func (p *BtmHeadFrame) String() string {
sb := strings.Builder{}
sb.WriteString(fmt.Sprintf("CanetFrame CanLen = %d, ID1 = 0x%0x, ID2 = 0x%0x, ID3 = 0x%0x, ID4 = 0x%0x", p.CanLen,
p.CanId.ID1, p.CanId.ID2, p.CanId.ID3, p.CanId.ID4))
sb.WriteString("CanData = ")
for _, d := range p.CanData {
sb.WriteString(fmt.Sprintf(" 0x%0x ", d))
}
return sb.String()
}

View File

@ -1,6 +1,8 @@
package message package message
import ( import (
"bytes"
"encoding/binary"
"fmt" "fmt"
"log/slog" "log/slog"
"strings" "strings"
@ -68,7 +70,7 @@ type AtpRequestFrame struct {
Crc16 uint16 Crc16 uint16
//解码时CRC16校验结果,true-校验通过 //解码时CRC16校验结果,true-校验通过
Crc16CheckOk bool Crc16CheckOk bool
IsTrainPcSim bool //IsTrainPcSim bool
} }
// NewAtpRequestFrame 创建ATP查询帧 // NewAtpRequestFrame 创建ATP查询帧
@ -90,6 +92,38 @@ func (f *AtpRequestFrame) String() string {
sb.WriteString(fmt.Sprintf(",Crc16CheckOk = %t", f.Crc16CheckOk)) sb.WriteString(fmt.Sprintf(",Crc16CheckOk = %t", f.Crc16CheckOk))
return sb.String() return sb.String()
} }
func (f *AtpRequestFrame) Decode2(cf *BtmHeadFrame) bool {
f.FId = cf.CanId
buf := bytes.NewBuffer(cf.CanData)
if d, err := buf.ReadByte(); err == nil {
f.Speed = uint16(d << 4)
f.ResendRequest = GetBit(d, 5)>>5 | GetBit(d, 4)>>6
f.PowerAmplifierControlledByAtp = true
f.PowerAmplifierTurnOn = true
} else {
return false
}
if d, err := buf.ReadByte(); err == nil {
f.Speed |= uint16(d)
}
var time uint32
binary.Read(buf, binary.BigEndian, &time)
f.Time = time
var crc uint16
binary.Read(buf, binary.BigEndian, &crc)
f.Crc16 = crc
timeArr := make([]byte, 4)
binary.BigEndian.PutUint32(timeArr, time)
crc16 := Can_Crc16BtmReq(timeArr)
f.Crc16CheckOk = f.Crc16 == crc16
if !f.Crc16CheckOk {
slog.Debug("解码AtpRequestFrameCRC16校验未通过")
}
return true
}
func (f *AtpRequestFrame) Decode(cf *CanetFrame) bool { func (f *AtpRequestFrame) Decode(cf *CanetFrame) bool {
f.FId = cf.CanId f.FId = cf.CanId
// //
@ -146,7 +180,7 @@ func (f *AtpRequestFrame) Decode(cf *CanetFrame) bool {
} else { } else {
return false return false
} }
crc16 := Can_Crc16(timeArr) crc16 := Can_Crc16BtmReq(timeArr)
t1 := uint32(timeArr[0]) t1 := uint32(timeArr[0])
t2 := uint32(timeArr[1]) t2 := uint32(timeArr[1])
t3 := uint32(timeArr[2]) t3 := uint32(timeArr[2])
@ -179,7 +213,7 @@ func (f *AtpRequestFrame) Decode(cf *CanetFrame) bool {
} }
func (f *AtpRequestFrame) Encode() *CanetFrame { func (f *AtpRequestFrame) Encode() *CanetFrame {
cf := &CanetFrame{} cf := &CanetFrame{}
cf.IsTrainPcSim = f.IsTrainPcSim
cf.CanId = f.FId cf.CanId = f.FId
cf.CanLen = 8 cf.CanLen = 8
cf.FF = true cf.FF = true

View File

@ -8,30 +8,28 @@ type BtmDataMessageFrame struct {
//帧ID //帧ID
FId CanFrameId FId CanFrameId
//8字节,应答器报文片段 //8字节,应答器报文片段
Message []byte Message []byte
IsTrainPcSim bool
} }
func NewBtmDataMessageFrame(sn byte, offset byte, isTrainPcSim bool) *BtmDataMessageFrame { func NewBtmDataMessageFrame(sn byte, offset byte) *BtmDataMessageFrame {
return &BtmDataMessageFrame{ return &BtmDataMessageFrame{
FId: *NewCanFrameId(CAN_ADDR_RSP_ATP, CAN_ADDR_RSP_BTM, 0x80+offset, sn), FId: *NewCanFrameId(CAN_ADDR_RSP_ATP, CAN_ADDR_RSP_BTM, 0x80+offset, sn),
IsTrainPcSim: isTrainPcSim,
} }
} }
func (f *BtmDataMessageFrame) Encode() *CanetFrame { func (f *BtmDataMessageFrame) Encode() *CanetFrame {
cf := &CanetFrame{} cf := &CanetFrame{}
cf.IsTrainPcSim = f.IsTrainPcSim
cf.CanId = f.FId cf.CanId = f.FId
cf.CanLen = 8 cf.CanLen = 8
cf.FF = true cf.FF = true
cf.RTR = false cf.RTR = false
// //
writer := NewCanBitsWriter(8) writer := NewCanBitsWriter(8)
//
for _, data := range f.Message { for _, data := range f.Message {
writer.AddByte(data) writer.AddByte(data)
} }
cf.CanData = writer.(CanBusData).GetData() cf.CanData = writer.(CanBusData).GetData()
// //
return cf return cf
} }
@ -62,46 +60,39 @@ type BtmDataMessageTimeAFrame struct {
//时间戳A //时间戳A
TimeA uint32 TimeA uint32
//CRC //CRC
Crc32A uint32 Crc32A uint32
IsTrainPcSim bool
} }
func NewBtmDataMessageTimeAFrame2(sn byte, isTrainPcSim bool) *BtmDataMessageTimeAFrame { func NewBtmDataMessageTimeAFrame(sn byte) *BtmDataMessageTimeAFrame {
return &BtmDataMessageTimeAFrame{ return &BtmDataMessageTimeAFrame{
FId: *NewCanFrameId(CAN_ADDR_RSP_ATP, CAN_ADDR_RSP_BTM, 0x80+0x0e, sn), FId: *NewCanFrameId(CAN_ADDR_RSP_ATP, CAN_ADDR_RSP_BTM, 0x80+0x0d, sn),
IsTrainPcSim: isTrainPcSim,
}
}
func NewBtmDataMessageTimeAFrame(sn byte, isTrainPcSim bool) *BtmDataMessageTimeAFrame {
return &BtmDataMessageTimeAFrame{
FId: *NewCanFrameId(CAN_ADDR_RSP_ATP, CAN_ADDR_RSP_BTM, 0x80+0x0d, sn),
IsTrainPcSim: isTrainPcSim,
} }
} }
func (f *BtmDataMessageTimeAFrame) Encode() *CanetFrame { func (f *BtmDataMessageTimeAFrame) Encode() *CanetFrame {
cf := &CanetFrame{} cf := &CanetFrame{}
cf.IsTrainPcSim = f.IsTrainPcSim
cf.CanId = f.FId cf.CanId = f.FId
cf.CanLen = 8 cf.CanLen = 8
cf.FF = true cf.FF = true
cf.RTR = false cf.RTR = false
//
writer := NewCanBitsWriter(8) writer := NewCanBitsWriter(8)
//
byteMsk := uint32(0x00_00_00_ff) byteMsk := uint32(0x00_00_00_ff)
//
writer.AddByte(byte((f.TimeA >> 24) & byteMsk)) writer.AddByte(byte((f.TimeA >> 24) & byteMsk))
writer.AddByte(byte((f.TimeA >> 16) & byteMsk)) writer.AddByte(byte((f.TimeA >> 16) & byteMsk))
writer.AddByte(byte((f.TimeA >> 8) & byteMsk)) writer.AddByte(byte((f.TimeA >> 8) & byteMsk))
writer.AddByte(byte(f.TimeA & byteMsk)) writer.AddByte(byte(f.TimeA & byteMsk))
//
writer.AddByte(byte((f.Crc32A >> 24) & byteMsk)) writer.AddByte(byte((f.Crc32A >> 24) & byteMsk))
writer.AddByte(byte((f.Crc32A >> 16) & byteMsk)) writer.AddByte(byte((f.Crc32A >> 16) & byteMsk))
writer.AddByte(byte((f.Crc32A >> 8) & byteMsk)) writer.AddByte(byte((f.Crc32A >> 8) & byteMsk))
writer.AddByte(byte(f.Crc32A & byteMsk)) writer.AddByte(byte(f.Crc32A & byteMsk))
//
cf.CanData = writer.(CanBusData).GetData() cf.CanData = writer.(CanBusData).GetData()
//
return cf return cf
} }
@ -173,40 +164,37 @@ type BtmDataMessageTimeBFrame struct {
//时间戳B //时间戳B
TimeB uint32 TimeB uint32
//CRC //CRC
Crc32B uint32 Crc32B uint32
IsTrainPcSim bool
} }
func NewBtmDataMessageTimeBFrame(sn byte, isTrainPcSim bool) *BtmDataMessageTimeBFrame { func NewBtmDataMessageTimeBFrame(sn byte) *BtmDataMessageTimeBFrame {
return &BtmDataMessageTimeBFrame{ return &BtmDataMessageTimeBFrame{
FId: *NewCanFrameId(CAN_ADDR_RSP_ATP, CAN_ADDR_RSP_BTM, 0x80+0x0e, sn), FId: *NewCanFrameId(CAN_ADDR_RSP_ATP, CAN_ADDR_RSP_BTM, 0x80+0x0e, sn),
IsTrainPcSim: isTrainPcSim,
} }
} }
func (f *BtmDataMessageTimeBFrame) Encode() *CanetFrame { func (f *BtmDataMessageTimeBFrame) Encode() *CanetFrame {
cf := &CanetFrame{} cf := &CanetFrame{}
cf.IsTrainPcSim = f.IsTrainPcSim
cf.CanId = f.FId cf.CanId = f.FId
cf.CanLen = 8 cf.CanLen = 8
cf.FF = true cf.FF = true
cf.RTR = false cf.RTR = false
// //
writer := NewCanBitsWriter(8) writer := NewCanBitsWriter(8)
//
byteMsk := uint32(0x00_00_00_ff) byteMsk := uint32(0x00_00_00_ff)
//
writer.AddByte(byte((f.TimeB >> 24) & byteMsk)) writer.AddByte(byte((f.TimeB >> 24) & byteMsk))
writer.AddByte(byte((f.TimeB >> 16) & byteMsk)) writer.AddByte(byte((f.TimeB >> 16) & byteMsk))
writer.AddByte(byte((f.TimeB >> 8) & byteMsk)) writer.AddByte(byte((f.TimeB >> 8) & byteMsk))
writer.AddByte(byte(f.TimeB & byteMsk)) writer.AddByte(byte(f.TimeB & byteMsk))
//
writer.AddByte(byte((f.Crc32B >> 24) & byteMsk)) writer.AddByte(byte((f.Crc32B >> 24) & byteMsk))
writer.AddByte(byte((f.Crc32B >> 16) & byteMsk)) writer.AddByte(byte((f.Crc32B >> 16) & byteMsk))
writer.AddByte(byte((f.Crc32B >> 8) & byteMsk)) writer.AddByte(byte((f.Crc32B >> 8) & byteMsk))
writer.AddByte(byte(f.Crc32B & byteMsk)) writer.AddByte(byte(f.Crc32B & byteMsk))
//
cf.CanData = writer.(CanBusData).GetData() cf.CanData = writer.(CanBusData).GetData()
//
return cf return cf
} }
func (f *BtmDataMessageTimeBFrame) Decode(cf *CanetFrame) bool { func (f *BtmDataMessageTimeBFrame) Decode(cf *CanetFrame) bool {
@ -278,25 +266,18 @@ type BtmDataMessageEndFrame struct {
TkB uint32 TkB uint32
//CRC32C校验包含对状态应答帧与数据帧的总校验总共为8×17-4=132字节4-即Crc32C //CRC32C校验包含对状态应答帧与数据帧的总校验总共为8×17-4=132字节4-即Crc32C
//1个状态应答帧 + 13个BtmDataMessageFrame + 1个BtmDataMessageTimeAFrame + 1个BtmDataMessageTimeBFrame + 1个BtmDataMessageEndFrame //1个状态应答帧 + 13个BtmDataMessageFrame + 1个BtmDataMessageTimeAFrame + 1个BtmDataMessageTimeBFrame + 1个BtmDataMessageEndFrame
Crc32C uint32 Crc32C uint32
IsTrainPcSim bool
} }
func NewBtmDataMessageEndFrame2(sn byte, isTrainPcSim bool) *BtmDataMessageEndFrame { func NewBtmDataMessageEndFrame(sn byte) *BtmDataMessageEndFrame {
return &BtmDataMessageEndFrame{ return &BtmDataMessageEndFrame{
FId: *NewCanFrameId(CAN_ADDR_RSP_ATP, CAN_ADDR_RSP_BTM, 0xff, sn), FId: *NewCanFrameId(CAN_ADDR_RSP_ATP, CAN_ADDR_RSP_BTM, 0x80+0x7f, sn),
IsTrainPcSim: isTrainPcSim,
}
}
func NewBtmDataMessageEndFrame(sn byte, isTrainPcSim bool) *BtmDataMessageEndFrame {
return &BtmDataMessageEndFrame{
FId: *NewCanFrameId(CAN_ADDR_RSP_ATP, CAN_ADDR_RSP_BTM, 0x80+0x7f, sn),
IsTrainPcSim: isTrainPcSim,
} }
} }
func (f *BtmDataMessageEndFrame) Encode() *CanetFrame { func (f *BtmDataMessageEndFrame) Encode() *CanetFrame {
cf := &CanetFrame{} cf := &CanetFrame{}
cf.IsTrainPcSim = f.IsTrainPcSim
cf.CanId = f.FId cf.CanId = f.FId
cf.CanLen = 8 cf.CanLen = 8
cf.FF = true cf.FF = true

View File

@ -1,18 +1,19 @@
package message package message
import "log/slog" import (
"encoding/binary"
"fmt"
"log/slog"
)
func CreateBtmRspFramesData2(statusRsp *BtmStatusRspFrame, msg []byte, msgPackError bool, msgTimeA uint32, msgTimeB uint32, tkTimeB uint32, isTrainPcSim bool) ([]byte, bool) { // 返回应答器数据帧(数据帧 + timeA+timeB+结束帧)
/* if len(msg) > 104 { //数据帧最多存储13*8个字节 func CreateBtmAtpDataRspFramesData(statusRsp *BtmHeadFrame, msg []byte, msgPackError bool, msgTimeA uint32, msgTimeB uint32, tkTimeB uint32) ([]byte, bool) {
return nil, false sn := statusRsp.CanId.ID4
}*/ //应答器整个是16个数据帧其中报文占13帧timeA,timeB 占2帧最后是结束帧
//最近一次ATP查询请求序列号
sn := statusRsp.FId.ID4
//13个BtmDataMessageFrame [0x00,0x0c]
//数据 //数据
dms := make([]*BtmDataMessageFrame, 13) dms := make([]*BtmDataMessageAtpFrame, 13)
for mr := 0x00; mr <= 0x0c; mr++ { for mr := 0x00; mr <= 0x0c; mr++ {
dms[mr] = NewBtmDataMessageFrame(sn, byte(mr), isTrainPcSim) dms[mr] = CreateBtmDataMessageDataAtpFrame(sn, byte(mr))
dms[mr].Message = make([]byte, 8) //8字节数组默认值0 dms[mr].Message = make([]byte, 8) //8字节数组默认值0
// //
if !msgPackError { if !msgPackError {
@ -32,70 +33,62 @@ func CreateBtmRspFramesData2(statusRsp *BtmStatusRspFrame, msg []byte, msgPackEr
} }
} }
} }
// dtA := createTimeA(sn, DATA_TIME_A_OFFSET, msgTimeA, msgPackError, msg)
dtA := NewBtmDataMessageTimeAFrame(sn, isTrainPcSim) dtB := createTimeA(sn, DATA_TIME_B_OFFSET, msgTimeB, msgPackError, msg)
dtA.TimeA = msgTimeA
if !msgPackError {
var crc32AData []byte
crc32AData = append(crc32AData, msg...)
crc32AData = append(crc32AData, canTimeToBytes(dtA.TimeA)...)
dtA.Crc32A = Can_Crc32(crc32AData) //CRC32A的校验范围是报文+时间戳A
} else { //BTM解包发生错误则数据帧及CRC32A/B全填“0xFF”
dtA.Crc32A = 0xff_ff_ff_ff
}
//
dtB := NewBtmDataMessageTimeBFrame(sn, isTrainPcSim)
dtB.TimeB = msgTimeB
if !msgPackError {
var crc32BData []byte
crc32BData = append(crc32BData, msg...)
crc32BData = append(crc32BData, canTimeToBytes(dtB.TimeB)...)
dtB.Crc32B = Can_Crc32(crc32BData) //CRC32B的校验范围是报文+时间戳B
} else { //BTM解包发生错误则数据帧及CRC32A/B全填“0xFF”
dtB.Crc32B = 0xff_ff_ff_ff
}
//
end := NewBtmDataMessageEndFrame(sn, isTrainPcSim)
end.TkB = tkTimeB
//
statusCf := statusRsp.Encode()
dmsCfs := make([]*CanetFrame, 0, 13)
for _, dm := range dms {
dmsCfs = append(dmsCfs, dm.Encode())
}
dtACf := dtA.Encode() dtACf := dtA.Encode()
dtBCf := dtB.Encode() dtBCf := dtB.Encode()
//
crc32cData := make([]byte, 0, 132)
crc32cData = append(crc32cData, statusCf.CanData...)
for _, dmCf := range dmsCfs {
crc32cData = append(crc32cData, dmCf.CanData...)
}
crc32cData = append(crc32cData, dtACf.CanData...)
crc32cData = append(crc32cData, dtBCf.CanData...)
crc32cData = append(crc32cData, canTimeToBytes(end.TkB)...)
//
end.Crc32C = Can_Crc32(crc32cData)
//
endCf := end.Encode()
//
rt := make([]byte, 0, 221) //17*13
rt = append(rt, statusCf.Encode2()...)
for _, dmCf := range dmsCfs {
rt = append(rt, dmCf.Encode2()...)
}
rt = append(rt, dtACf.Encode2()...)
rt = append(rt, dtBCf.Encode2()...)
rt = append(rt, endCf.Encode2()...)
if isTrainPcSim && len(rt) != 221 {
} else if len(rt) != 221 { //结束帧
slog.Warn("len(rt)!=221")
end := createDataAtpEnd(sn, tkTimeB, statusRsp.CanData, msg, dtACf.CanData, dtBCf.CanData)
endCf := end.Encode()
rt := make([]byte, 0) //17*12
for _, dmCf := range dms {
rt = append(rt, dmCf.Encode().Encode()...)
}
rt = append(rt, dtACf.Encode()...)
rt = append(rt, dtBCf.Encode()...)
rt = append(rt, endCf.Encode()...)
if len(rt) != 192 {
slog.Warn(fmt.Sprintf("len(rt)!=192 实际数据长度:%v", len(rt)))
return nil, false return nil, false
} }
return rt, true return rt, true
} }
func createDataAtpEnd(sn byte, time uint32, statusData, msg, dtAData, dtBData []byte) *BtmDataMessageAtpTimeAndEndFrame {
end := BtmDataMessageEndAtpFrame(sn)
end.Time = time
crc32cData := make([]byte, 0)
crc32cData = append(crc32cData, statusData...)
crc32cData = append(crc32cData, msg...)
crc32cData = append(crc32cData, dtAData...)
crc32cData = append(crc32cData, dtBData...)
crc32cData = binary.BigEndian.AppendUint32(crc32cData, end.Time)
end.Crc32 = Can_Crc32(crc32cData)
return end
}
func createTimeA(sn, offset byte, time uint32, msgPackError bool, msg []byte) *BtmDataMessageAtpTimeAndEndFrame {
tf := CreateBtmDataMessageTimeAtpFrame(sn, offset)
tf.Time = time
if !msgPackError {
var crcData []byte
crcData = append(crcData, msg...)
crcData = binary.BigEndian.AppendUint32(crcData, time)
if offset == DATA_TIME_A_OFFSET {
tf.Crc32 = Can_Crc32A(crcData) //CRC32A的校验范围是报文+时间戳B
} else {
tf.Crc32 = Can_Crc32B(crcData) //CRC32B的校验范围是报文+时间戳B
}
} else { //BTM解包发生错误则数据帧及CRC32A/B全填“0xFF”
tf.Crc32 = 0xff_ff_ff_ff
}
return tf
}
// CreateBtmRspFramesData BTM与ATP之间为双向通信ATP定时发送请求帧BTM在未接收到应答器报文时回复状态应答器帧和时间同步帧在接收到应答器报文时回复所有帧 // CreateBtmRspFramesData BTM与ATP之间为双向通信ATP定时发送请求帧BTM在未接收到应答器报文时回复状态应答器帧和时间同步帧在接收到应答器报文时回复所有帧
// //
@ -104,7 +97,7 @@ func CreateBtmRspFramesData2(statusRsp *BtmStatusRspFrame, msg []byte, msgPackEr
// 共17帧17X12个字节每个帧12字节 // 共17帧17X12个字节每个帧12字节
// msg - 应答器报文 // msg - 应答器报文
// msgPackError - true BTM解包发生错误则数据帧及CRC32A/B全填“0xFF” // msgPackError - true BTM解包发生错误则数据帧及CRC32A/B全填“0xFF”
func CreateBtmRspFramesData(statusRsp *BtmStatusRspFrame, msg []byte, msgPackError bool, msgTimeA uint32, msgTimeB uint32, tkTimeB uint32, isTrainPcSim bool) ([]byte, bool) { func CreateBtmRspFramesData(statusRsp *BtmStatusRspFrame, msg []byte, msgPackError bool, msgTimeA uint32, msgTimeB uint32, tkTimeB uint32) ([]byte, bool) {
/* if len(msg) > 104 { //数据帧最多存储13*8个字节 /* if len(msg) > 104 { //数据帧最多存储13*8个字节
return nil, false return nil, false
}*/ }*/
@ -114,7 +107,7 @@ func CreateBtmRspFramesData(statusRsp *BtmStatusRspFrame, msg []byte, msgPackErr
//数据 //数据
dms := make([]*BtmDataMessageFrame, 13) dms := make([]*BtmDataMessageFrame, 13)
for mr := 0x00; mr <= 0x0c; mr++ { for mr := 0x00; mr <= 0x0c; mr++ {
dms[mr] = NewBtmDataMessageFrame(sn, byte(mr), isTrainPcSim) dms[mr] = NewBtmDataMessageFrame(sn, byte(mr))
dms[mr].Message = make([]byte, 8) //8字节数组默认值0 dms[mr].Message = make([]byte, 8) //8字节数组默认值0
// //
if !msgPackError { if !msgPackError {
@ -135,7 +128,7 @@ func CreateBtmRspFramesData(statusRsp *BtmStatusRspFrame, msg []byte, msgPackErr
} }
} }
// //
dtA := NewBtmDataMessageTimeAFrame(sn, isTrainPcSim) dtA := NewBtmDataMessageTimeAFrame(sn)
dtA.TimeA = msgTimeA dtA.TimeA = msgTimeA
if !msgPackError { if !msgPackError {
var crc32AData []byte var crc32AData []byte
@ -146,7 +139,7 @@ func CreateBtmRspFramesData(statusRsp *BtmStatusRspFrame, msg []byte, msgPackErr
dtA.Crc32A = 0xff_ff_ff_ff dtA.Crc32A = 0xff_ff_ff_ff
} }
// //
dtB := NewBtmDataMessageTimeBFrame(sn, isTrainPcSim) dtB := NewBtmDataMessageTimeBFrame(sn)
dtB.TimeB = msgTimeB dtB.TimeB = msgTimeB
if !msgPackError { if !msgPackError {
var crc32BData []byte var crc32BData []byte
@ -157,102 +150,7 @@ func CreateBtmRspFramesData(statusRsp *BtmStatusRspFrame, msg []byte, msgPackErr
dtB.Crc32B = 0xff_ff_ff_ff dtB.Crc32B = 0xff_ff_ff_ff
} }
// //
end := NewBtmDataMessageEndFrame(sn, isTrainPcSim) end := NewBtmDataMessageEndFrame(sn)
end.TkB = tkTimeB
//
statusCf := statusRsp.Encode()
dmsCfs := make([]*CanetFrame, 0, 13)
for _, dm := range dms {
dmsCfs = append(dmsCfs, dm.Encode())
}
dtACf := dtA.Encode()
dtBCf := dtB.Encode()
//
crc32cData := make([]byte, 0, 132)
crc32cData = append(crc32cData, statusCf.CanData...)
for _, dmCf := range dmsCfs {
crc32cData = append(crc32cData, dmCf.CanData...)
}
crc32cData = append(crc32cData, dtACf.CanData...)
crc32cData = append(crc32cData, dtBCf.CanData...)
crc32cData = append(crc32cData, canTimeToBytes(end.TkB)...)
//
end.Crc32C = Can_Crc32(crc32cData)
//
endCf := end.Encode()
//
rt := make([]byte, 0, 221) //17*13
rt = append(rt, statusCf.Encode()...)
for _, dmCf := range dmsCfs {
rt = append(rt, dmCf.Encode()...)
}
rt = append(rt, dtACf.Encode()...)
rt = append(rt, dtBCf.Encode()...)
rt = append(rt, endCf.Encode()...)
if isTrainPcSim && len(rt) != 221 {
} else if len(rt) != 221 {
slog.Warn("len(rt)!=221")
return nil, false
}
return rt, true
}
func CreateBtmRspFramesDataForPcSim(statusRsp *BtmStatusRspFrame, msg []byte, msgPackError bool, msgTimeA uint32, msgTimeB uint32, tkTimeB uint32, isTrainPcSim bool) ([]byte, bool) {
if len(msg) > 128 { //数据帧最多存储13*8个字节
return nil, false
}
//最近一次ATP查询请求序列号
sn := statusRsp.FId.ID4
//13个BtmDataMessageFrame [0x00,0x0c]
//数据
dms := make([]*BtmDataMessageFrame, 14)
for mr := 0x00; mr <= 0x0E; mr++ {
dms[mr] = NewBtmDataMessageFrame(sn, byte(mr), isTrainPcSim)
dms[mr].Message = make([]byte, 8) //8字节数组默认值0
//
if !msgPackError {
mi := mr * 8
if mi < len(msg) { //数据帧中有<=8个字节数据
if mi+7 < len(msg) {
dms[mr].Message = msg[mi : mi+8]
} else {
for i, d := range msg[mi:] {
dms[mr].Message[i] = d
}
}
}
} else { //BTM解包发生错误则数据帧及CRC32A/B全填“0xFF”
for c := 0; c < 8; c++ {
dms[mr].Message[c] = 0xff
}
}
}
//
dtA := NewBtmDataMessageTimeAFrame(sn, isTrainPcSim)
//dtA.TimeA = msgTimeA
//if !msgPackError {
// var crc32AData []byte
// crc32AData = append(crc32AData, msg...)
// crc32AData = append(crc32AData, canTimeToBytes(dtA.TimeA)...)
// dtA.Crc32A = Can_Crc32(crc32AData) //CRC32A的校验范围是报文+时间戳A
//} else { //BTM解包发生错误则数据帧及CRC32A/B全填“0xFF”
// dtA.Crc32A = 0xff_ff_ff_ff
//}
//
dtB := NewBtmDataMessageTimeBFrame(sn, isTrainPcSim)
dtB.TimeB = msgTimeB
if !msgPackError {
var crc32BData []byte
crc32BData = append(crc32BData, msg...)
crc32BData = append(crc32BData, canTimeToBytes(dtB.TimeB)...)
dtB.Crc32B = Can_Crc32(crc32BData) //CRC32B的校验范围是报文+时间戳B
} else { //BTM解包发生错误则数据帧及CRC32A/B全填“0xFF”
dtB.Crc32B = 0xff_ff_ff_ff
}
//
end := NewBtmDataMessageEndFrame(sn, isTrainPcSim)
end.TkB = tkTimeB end.TkB = tkTimeB
// //
statusCf := statusRsp.Encode() statusCf := statusRsp.Encode()
@ -288,5 +186,6 @@ func CreateBtmRspFramesDataForPcSim(statusRsp *BtmStatusRspFrame, msg []byte, ms
slog.Warn("len(rt)!=221") slog.Warn("len(rt)!=221")
return nil, false return nil, false
} }
return rt, true return rt, true
} }

View File

@ -1,6 +1,7 @@
package message package message
import ( import (
"encoding/binary"
"fmt" "fmt"
"strings" "strings"
) )
@ -26,15 +27,14 @@ type BtmStatusRspFrame struct {
//BTM detailed code //BTM detailed code
DetailedCode byte DetailedCode byte
//有具体报文内容时TK A时刻填充为CD信号上升沿时刻报文全零时TK A时刻填充为CD信号下降沿时刻。 //有具体报文内容时TK A时刻填充为CD信号上升沿时刻报文全零时TK A时刻填充为CD信号下降沿时刻。
TkTimeA uint32 TkTimeA uint32
IsTrainPcSim bool
} }
func NewBtmStatusRspFrame(sn byte, isTrainPcSim bool) *BtmStatusRspFrame { func NewBtmStatusRspFrame(sn byte) *BtmStatusRspFrame {
return &BtmStatusRspFrame{ return &BtmStatusRspFrame{
FId: *NewCanFrameId(CAN_ADDR_RSP_ATP, CAN_ADDR_RSP_BTM, CAN_FRAME_STATUS_RSP, sn), FId: *NewCanFrameId(CAN_ADDR_RSP_ATP, CAN_ADDR_RSP_BTM, CAN_FRAME_STATUS_RSP, sn),
//FId: *NewCanFrameId(0x00, 0x00, 0x05, sn), //FId: *NewCanFrameId(0x00, 0x00, 0x05, sn),
IsTrainPcSim: isTrainPcSim,
} }
} }
func (f *BtmStatusRspFrame) Decode(cf *CanetFrame) bool { func (f *BtmStatusRspFrame) Decode(cf *CanetFrame) bool {
@ -114,9 +114,35 @@ func (f *BtmStatusRspFrame) Decode(cf *CanetFrame) bool {
// //
return true return true
} }
func (f *BtmStatusRspFrame) EncodeBtmAtp() *BtmHeadFrame {
cf := &BtmHeadFrame{}
cf.CanId = f.FId
cf.CanLen = 8
data := make([]byte, 0)
data = append(data, f.Dsn)
data = append(data, f.BaliseCounter)
data = append(data, f.MessageCounter)
var state byte = 0
if f.PowerAmplifierOn {
state = setBit(state, 7, 1)
}
if f.AtpReqCrcCheckWrong {
state = setBit(state, 6, 1)
}
if f.PowerAmplifierFailure {
state = setBit(state, 5, 1)
}
if f.AntennaFault {
state = setBit(state, 4, 1)
}
data = append(data, state)
data = binary.BigEndian.AppendUint32(data, f.TkTimeA)
cf.CanData = data
return cf
}
func (f *BtmStatusRspFrame) Encode() *CanetFrame { func (f *BtmStatusRspFrame) Encode() *CanetFrame {
cf := &CanetFrame{} cf := &CanetFrame{}
cf.IsTrainPcSim = f.IsTrainPcSim
cf.CanId = f.FId cf.CanId = f.FId
cf.CanLen = 8 cf.CanLen = 8
cf.FF = true cf.FF = true
@ -126,6 +152,7 @@ func (f *BtmStatusRspFrame) Encode() *CanetFrame {
writer.AddByte(f.Dsn) writer.AddByte(f.Dsn)
writer.AddByte(f.BaliseCounter) writer.AddByte(f.BaliseCounter)
writer.AddByte(f.MessageCounter) writer.AddByte(f.MessageCounter)
// //
if f.PowerAmplifierOn { if f.PowerAmplifierOn {
writer.AddBits(1, 1) writer.AddBits(1, 1)

View File

@ -1,6 +1,7 @@
package message package message
import ( import (
"encoding/binary"
"fmt" "fmt"
"strings" "strings"
) )
@ -14,15 +15,14 @@ type BtmTimeSyncCheckFrame struct {
T2 uint32 T2 uint32
//T3时刻 //T3时刻
//BTM将在T3时刻发送回复帧给ATP并保持流水号与ATP查询帧一致。 //BTM将在T3时刻发送回复帧给ATP并保持流水号与ATP查询帧一致。
T3 uint32 T3 uint32
IsTrainPcSim bool
} }
func NewBtmTimeSyncCheckFrame(sn byte, isTrainPcSim bool) *BtmTimeSyncCheckFrame { func NewBtmTimeSyncCheckFrame(sn byte) *BtmTimeSyncCheckFrame {
return &BtmTimeSyncCheckFrame{ return &BtmTimeSyncCheckFrame{
FId: *NewCanFrameId(CAN_ADDR_RSP_ATP, CAN_ADDR_RSP_BTM, CAN_FRAME_TIME_SYNC_RSP, sn), FId: *NewCanFrameId(CAN_ADDR_RSP_ATP, CAN_ADDR_RSP_BTM, CAN_FRAME_TIME_SYNC_RSP, sn),
//FId: *NewCanFrameId(0x00, 0x00, 0x35, sn), //FId: *NewCanFrameId(0x00, 0x00, 0x35, sn),
IsTrainPcSim: isTrainPcSim,
} }
} }
@ -77,9 +77,21 @@ func (f *BtmTimeSyncCheckFrame) Decode(cf *CanetFrame) bool {
// //
return true return true
} }
func (f *BtmTimeSyncCheckFrame) EncodeBtmAtp() *BtmHeadFrame {
cf := &BtmHeadFrame{}
cf.CanId = f.FId
cf.CanLen = 8
data := make([]byte, 0)
data = binary.BigEndian.AppendUint32(data, f.T2)
data = binary.BigEndian.AppendUint32(data, f.T3)
cf.CanData = data
return cf
}
func (f *BtmTimeSyncCheckFrame) Encode() *CanetFrame { func (f *BtmTimeSyncCheckFrame) Encode() *CanetFrame {
cf := &CanetFrame{} cf := &CanetFrame{}
cf.IsTrainPcSim = f.IsTrainPcSim
cf.CanId = f.FId cf.CanId = f.FId
cf.CanLen = 8 cf.CanLen = 8
cf.FF = true cf.FF = true

View File

@ -1,6 +1,8 @@
package message package message
import "github.com/snksoft/crc" import (
"github.com/snksoft/crc"
)
/////////////////////CAN串行总线 bit 流处理 //////////////////////// /////////////////////CAN串行总线 bit 流处理 ////////////////////////
@ -199,47 +201,53 @@ const (
CAN_BITS_LEN8 = byte(0b1111_1111) CAN_BITS_LEN8 = byte(0b1111_1111)
) )
///////////////////// CRC ////////////////////////
// const (
// CAN_CRC16_ATPREQ = 0x11021
// CAN_CRC32 = 0x04C11DB7
// )
var ( var (
CAN_CRC16 = crc.CCITT CAN_CRC16 = crc.CCITT
CAN_CRC32 = &crc.Parameters{Width: 32, Polynomial: 0x4A503DF1, Init: 0x00FF0000, ReflectIn: true, ReflectOut: true, FinalXor: 0xFFFFFFFF} CAN_CRC32 = &crc.Parameters{Width: 32, Polynomial: 0x4A503DF1, Init: 0x00FF0000, ReflectIn: false, ReflectOut: false, FinalXor: 0x000000}
ATP_TIMEA = crc.CRC32
ATP_TIMEB = crc.Castagnoli
ATP_REQ = crc.XMODEM
) )
func Can_Crc16(data []byte) uint16 { func Can_Crc16(data []byte) uint16 {
return uint16(crc.CalculateCRC(CAN_CRC16, data)) return uint16(crc.CalculateCRC(CAN_CRC16, data))
} }
func Can_Crc16BtmReq(data []byte) uint16 {
return uint16(crc.CalculateCRC(ATP_REQ, data))
}
func Can_Crc32(data []byte) uint32 { func Can_Crc32(data []byte) uint32 {
return uint32(crc.CalculateCRC(CAN_CRC32, data)) return uint32(crc.CalculateCRC(CAN_CRC32, data))
} }
func Can_Crc32A(data []byte) uint32 {
return uint32(crc.CalculateCRC(ATP_TIMEA, data))
}
func Can_Crc32B(data []byte) uint32 {
return uint32(crc.CalculateCRC(ATP_TIMEB, data))
}
// var ( //var (
// crc16AtpReqTable []uint32 = nil // crc16AtpReqTable []uint32 = nil
// crc32CanTable []uint32 = nil // crc32CanTable []uint32 = nil
// ) //)
// func CreateCanCrcTable() { // func CreateCanCrcTable() {
// if crc16AtpReqTable == nil { // if crc16AtpReqTable == nil {
// crc16AtpReqTable = CreateCrcTable(CAN_CRC16_ATPREQ, 16, false) // crc16AtpReqTable = CreateCrcTable(CAN_CRC16_ATPREQ, 16, false)
// } // }
// if crc32CanTable == nil { // if crc32CanTable == nil {
// crc32CanTable = CreateCrcTable(CAN_CRC32, 32, false) // crc32CanTable = CreateCrcTable(CAN_CRC32, 32, false)
// } // }
// } // }
// func calculateAtpReqCrc16(data []byte) uint16 { //
// crc := CrcTableBased(data, 16, 0, false, false, 0, crc16AtpReqTable) // func calculateAtpReqCrc16(data []byte) uint16 {
// return uint16(crc) // crc := CrcTableBased(data, 16, 0, false, false, 0, crc16AtpReqTable)
// } // return uint16(crc)
// func calculateCanCrc32(data []byte) uint32 { // }
// crc := CrcTableBased(data, 32, 0xFF_FF_FF_FF, false, false, 0, crc32CanTable) //func calculateCanCrc32(data []byte) uint32 {
// return crc // crc := CrcTableBased(data, 32, 0xFF_FF_FF_FF, false, false, 0, crc32CanTable)
// } // return crc
//}
// // CRC32A的校验范围是报文+时间戳A // // CRC32A的校验范围是报文+时间戳A
// func calculateDataRspCrc32A(data []byte) uint32 { // func calculateDataRspCrc32A(data []byte) uint32 {

View File

@ -1,8 +1,6 @@
package message package message
import ( import (
"bytes"
"encoding/binary"
"fmt" "fmt"
"log/slog" "log/slog"
"strings" "strings"
@ -10,62 +8,37 @@ import (
// CanetFrame USR-CANET200_V1.0.7 设备 以太网-CAN 透传协议帧(13字节) // CanetFrame USR-CANET200_V1.0.7 设备 以太网-CAN 透传协议帧(13字节)
type CanetFrame struct { type CanetFrame struct {
FF bool //true-1扩展帧 FF bool //true-1扩展帧
RTR bool //true-1远程帧 RTR bool //true-1远程帧
CanLen byte //CAN帧数据长度[0,8]CanData中有效数据字节数 CanLen byte //CAN帧数据长度[0,8]CanData中有效数据字节数
CanId CanFrameId //CAN帧ID CanId CanFrameId //CAN帧ID
CanData []byte //CAN帧数据8字节 CanData []byte //CAN帧数据8字节
IsTrainPcSim bool //是否列车pc仿真
} }
func NewCanetFrame(buf []byte, isTrainPcSim bool) *CanetFrame { func NewCanetFrame(buf []byte) *CanetFrame {
cf := &CanetFrame{IsTrainPcSim: isTrainPcSim} cf := &CanetFrame{}
cf.Decode(buf) cf.Decode(buf)
return cf return cf
} }
func NewCanetFrame2(buf []byte, isTrainPcSim bool) *CanetFrame {
cf := &CanetFrame{IsTrainPcSim: isTrainPcSim}
cf.Decode2(buf)
return cf
}
func (p *CanetFrame) Encode2() []byte {
buf := make([]byte, 0)
//CAN 帧ID
frameId := uint32(p.CanId.ID1)<<21 | uint32(p.CanId.ID2)<<13 | uint32(p.CanId.ID3)<<5 | uint32(p.CanId.ID4)
buf = binary.BigEndian.AppendUint32(buf, frameId)
//CAN 帧数据
if len(p.CanData) != 8 {
panic("len(p.CanData)!=8")
}
buf = append(buf, p.CanData...)
return buf
}
func (p *CanetFrame) Encode() []byte { func (p *CanetFrame) Encode() []byte {
buf := make([]byte, 0) buf := make([]byte, 0)
if !p.IsTrainPcSim { //canet200帧信息
//canet200帧信息 b1 := byte(0x00)
b1 := byte(0x00) if p.FF {
if p.FF { b1 |= 0x80 //bit7
b1 |= 0x80 //bit7
}
if p.RTR {
b1 |= 0x40 //bit6
}
b1 |= p.CanLen & 0x0f
buf = append(buf, b1)
} }
if p.RTR {
b1 |= 0x40 //bit6
}
b1 |= p.CanLen & 0x0f
buf = append(buf, b1)
//CAN 帧ID //CAN 帧ID
buf = append(buf, p.CanId.ID1) buf = append(buf, p.CanId.ID1)
buf = append(buf, p.CanId.ID2) buf = append(buf, p.CanId.ID2)
buf = append(buf, p.CanId.ID3) buf = append(buf, p.CanId.ID3)
if p.IsTrainPcSim { buf = append(buf, p.CanId.ID4<<3)
buf = append(buf, p.CanId.ID4)
} else {
buf = append(buf, p.CanId.ID4<<3)
}
//CAN 帧数据 //CAN 帧数据
if len(p.CanData) != 8 { if len(p.CanData) != 8 {
@ -74,28 +47,7 @@ func (p *CanetFrame) Encode() []byte {
buf = append(buf, p.CanData...) buf = append(buf, p.CanData...)
return buf return buf
} }
func (p *CanetFrame) Decode2(buf []byte) {
bb := bytes.NewBuffer(buf)
var idSource uint32
binary.Read(bb, binary.BigEndian, &idSource)
data := make([]byte, bb.Len())
_, err := bb.Read(data)
if err != nil {
fmt.Println(err)
return
}
b1 := byte(idSource >> 21)
b2 := byte((idSource << 7) >> 13)
b3 := byte((idSource << 15) >> 20)
b4 := byte(idSource & 0x1f)
p.CanId.ID1 = b1
p.CanId.ID2 = b2
p.CanId.ID3 = b3
p.CanId.ID4 = b4
p.CanData = data
}
func (p *CanetFrame) Decode(buf []byte) { func (p *CanetFrame) Decode(buf []byte) {
if len(buf) != 13 { if len(buf) != 13 {
panic("len(buf)!=13") panic("len(buf)!=13")
@ -113,8 +65,8 @@ func (p *CanetFrame) Decode(buf []byte) {
} }
func (p *CanetFrame) String() string { func (p *CanetFrame) String() string {
sb := strings.Builder{} sb := strings.Builder{}
sb.WriteString(fmt.Sprintf("CanetFrame FF = %t, RTR = %t, CanLen = %d, ID1 = 0x%0x, ID2 = 0x%0x, ID3 = 0x%0x, ID4 = 0x%0x, isTrainPcSim=%v", p.FF, p.RTR, p.CanLen, sb.WriteString(fmt.Sprintf("CanetFrame FF = %t, RTR = %t, CanLen = %d, ID1 = 0x%0x, ID2 = 0x%0x, ID3 = 0x%0x, ID4 = 0x%0x", p.FF, p.RTR, p.CanLen,
p.CanId.ID1, p.CanId.ID2, p.CanId.ID3, p.CanId.ID4, p.IsTrainPcSim)) p.CanId.ID1, p.CanId.ID2, p.CanId.ID3, p.CanId.ID4))
sb.WriteString("CanData = ") sb.WriteString("CanData = ")
for _, d := range p.CanData { for _, d := range p.CanData {
sb.WriteString(fmt.Sprintf(" 0x%0x ", d)) sb.WriteString(fmt.Sprintf(" 0x%0x ", d))

View File

@ -93,16 +93,6 @@ func (m *InterlockSendMsgPkg) Encode() []byte {
} }
} }
data = append(data, infoBytes...) data = append(data, infoBytes...)
//for index, length, cycles := 0, len(m.info), len(m.info)/boolsToByteArrLen; index < cycles; index++ {
// startIndex := index * boolsToByteArrLen
// toByteArr := [8]bool{}
// for i := 0; i < boolsToByteArrLen && startIndex < length; i++ {
// startIndex = startIndex + i
// toByteArr[i] = m.info[startIndex+i]
// }
// data = append(data, boolsToByte(toByteArr))
//}
data = append(data, m.tail.encode()...) data = append(data, m.tail.encode()...)
return data return data
} }

View File

@ -8,9 +8,9 @@ var (
// crc16多项式为G(x)=X16+X11+X4+1 // crc16多项式为G(x)=X16+X11+X4+1
RSSP_I_CRC16 = crc.NewHash(&crc.Parameters{Width: 16, Polynomial: 0x0811, Init: 0x0, ReflectIn: true, ReflectOut: true, FinalXor: 0x0}) RSSP_I_CRC16 = crc.NewHash(&crc.Parameters{Width: 16, Polynomial: 0x0811, Init: 0x0, ReflectIn: true, ReflectOut: true, FinalXor: 0x0})
// 通道1 crc32多项式为0x100d4e63 // 通道1 crc32多项式为0x100d4e63
RSSP_I_C1_CRC32 = crc.NewHash(&crc.Parameters{Width: 32, Polynomial: 0x100d4e63, Init: 0x0, ReflectIn: true, ReflectOut: true, FinalXor: 0x0}) RSSP_I_C1_CRC32 = crc.NewHash(&crc.Parameters{Width: 32, Polynomial: 0x100d4e63, Init: 0x0, ReflectIn: false, ReflectOut: true, FinalXor: 0x0})
// 通道2 crc32多项式为0x8ce56011 // 通道2 crc32多项式为0x8ce56011
RSSP_I_C2_CRC32 = crc.NewHash(&crc.Parameters{Width: 32, Polynomial: 0x8ce56011, Init: 0x0, ReflectIn: true, ReflectOut: true, FinalXor: 0x0}) RSSP_I_C2_CRC32 = crc.NewHash(&crc.Parameters{Width: 32, Polynomial: 0x8ce56011, Init: 0x0, ReflectIn: false, ReflectOut: true, FinalXor: 0x0})
) )
// Rssp_I_Crc16计算 // Rssp_I_Crc16计算
@ -20,27 +20,27 @@ func Rssp_I_Crc16(data []byte) uint16 {
// 通道1的crc32 // 通道1的crc32
func Rssp_I_Crc32C1(data []byte) uint32 { func Rssp_I_Crc32C1(data []byte) uint32 {
newData := reverseBitsInByte(data) //newData := reverseBitsInByte(data)
return uint32(RSSP_I_C1_CRC32.CalculateCRC(newData)) return uint32(RSSP_I_C1_CRC32.CalculateCRC(data))
} }
// 通道2的crc32 // 通道2的crc32
func Rssp_I_Crc32C2(data []byte) uint32 { func Rssp_I_Crc32C2(data []byte) uint32 {
newData := reverseBitsInByte(data) //newData := reverseBitsInByte(data)
return uint32(RSSP_I_C2_CRC32.CalculateCRC(newData)) return uint32(RSSP_I_C2_CRC32.CalculateCRC(data))
} }
func reverseBitsInByte(data []byte) []byte { //func reverseBitsInByte(data []byte) []byte {
var result byte // var result byte
newData := make([]byte, len(data)) // newData := make([]byte, len(data))
for i, b := range data { // for i, b := range data {
result = 0 // result = 0
for i := 0; i < 8; i++ { // for i := 0; i < 8; i++ {
result <<= 1 // result <<= 1
result |= b & 1 // result |= b & 1
b >>= 1 // b >>= 1
} // }
newData[i] = result // newData[i] = result
} // }
return newData // return newData
} //}

View File

@ -50,6 +50,7 @@ type TrainPcSim interface {
TrainPluseCount(sta *state_proto.TrainState, h1, h2, t1, t2 float32) TrainPluseCount(sta *state_proto.TrainState, h1, h2, t1, t2 float32)
ResetPluseCount(sta *state_proto.TrainState) ResetPluseCount(sta *state_proto.TrainState)
//FindAllThirdPartState() []tpapi.ThirdPartyApiService //FindAllThirdPartState() []tpapi.ThirdPartyApiService
DsnAddAndReturn() byte
} }
type TrainPcSimManage interface { type TrainPcSimManage interface {
@ -75,9 +76,8 @@ type trainPcSimService struct {
newPcSimclientMap map[string]*TrainPcReciverData newPcSimclientMap map[string]*TrainPcReciverData
cancleContext context.CancelFunc cancleContext context.CancelFunc
trainPcSimManage TrainPcSimManage trainPcSimManage TrainPcSimManage
//speedPlace *message.TrainSpeedPlaceReportMsg configs []config.VehiclePCSimConfig
//trainSpeedPlace map[string]*message.TrainSpeedPlaceReportMsg btmDsn uint8
configs []config.VehiclePCSimConfig
} }
var ( var (
@ -111,6 +111,14 @@ func (d *trainPcSimService) TrueService() bool {
func (d *trainPcSimService) ServiceDesc() string { func (d *trainPcSimService) ServiceDesc() string {
return Name return Name
} }
func (d *trainPcSimService) DsnAddAndReturn() byte {
defer initLock.Unlock()
initLock.Lock()
returnVal := d.btmDsn
d.btmDsn = returnVal + 1
return returnVal
}
func FindTrainPcSimClientKey2(t *state_proto.TrainState) string { func FindTrainPcSimClientKey2(t *state_proto.TrainState) string {
return t.ConnState.TypeName return t.ConnState.TypeName
} }
@ -196,40 +204,6 @@ func (d *trainPcSimService) findConfig(configName string) (*config.VehiclePCSimC
return nil, fmt.Errorf("未找到对应的车载pc连接配置") return nil, fmt.Errorf("未找到对应的车载pc连接配置")
} }
/*func (d *trainPcSimService) connTrainPcSim(ctx context.Context) {
go func() {
for {
select {
case <-ctx.Done():
d.newCloseAllConn()
return
default:
}
trains := d.trainPcSimManage.GetConnTrain2()
if len(trains) > 0 {
for _, t := range trains {
clientKey := FindTrainPcSimClientKey(t)
if clientKey == "" {
slog.Error("未找到对应的pc仿真连接,trainId:", t.Id, "删除对应客户端")
d.newCloseConn(clientKey)
continue
}
rd := d.newPcSimclientMap[clientKey]
if rd == nil {
d.newPcSimclientMap[clientKey] = &TrainPcReciverData{pcSimManage: d.trainPcSimManage, clientKey: clientKey, tcpClient: &tcp.TcpClient{}}
}
if !rd.tcpClient.IsConning() {
d.newCloseConn(clientKey)
d.initConn(clientKey)
}
}
}
time.Sleep(time.Second)
}
}()
}*/
func (d *trainPcSimService) initConn(clientKey string) error { func (d *trainPcSimService) initConn(clientKey string) error {
rd := d.newPcSimclientMap[clientKey] rd := d.newPcSimclientMap[clientKey]
@ -239,11 +213,10 @@ func (d *trainPcSimService) initConn(clientKey string) error {
rd.trainInit = false rd.trainInit = false
rd.tcpClient = nil rd.tcpClient = nil
} }
cfg, cfgErr := d.findConfig(clientKey) cfg, cfgErr := d.findConfig(clientKey)
if cfgErr != nil { if cfgErr != nil {
errMsg := fmt.Sprintf("没找到对应的配置信息 key:%v", clientKey) errMsg := fmt.Sprintf("没找到对应的配置信息 key:%v", clientKey)
slog.Error(errMsg, cfgErr.Error()) //slog.Error(errMsg, cfgErr.Error())
rd.updateState(tpapi.ThirdPartyState_Broken) rd.updateState(tpapi.ThirdPartyState_Broken)
return sys_error.New(errMsg, cfgErr) return sys_error.New(errMsg, cfgErr)
} }
@ -251,7 +224,7 @@ func (d *trainPcSimService) initConn(clientKey string) error {
client2, err := tcp.StartTcpClient(addr, rd.receiverDataHandle, rd.readError) client2, err := tcp.StartTcpClient(addr, rd.receiverDataHandle, rd.readError)
if err != nil { if err != nil {
connErrMsg := fmt.Sprintf("车载pc连接失败 clientKey:%v", clientKey) connErrMsg := fmt.Sprintf("车载pc连接失败 clientKey:%v", clientKey)
slog.Error(connErrMsg, err.Error()) //slog.Error(connErrMsg, err.Error())
rd.updateState(tpapi.ThirdPartyState_Broken) rd.updateState(tpapi.ThirdPartyState_Broken)
return sys_error.New(connErrMsg, err) return sys_error.New(connErrMsg, err)
} else { } else {
@ -283,7 +256,7 @@ func (d *trainPcSimService) Start(pcSimManage TrainPcSimManage) {
slog.Error("车载pc仿真配置未开启") slog.Error("车载pc仿真配置未开启")
return return
} }
//third_party.AppendService(d.findAllThirdPartState())
d.configs = configs d.configs = configs
ctx, ctxFun := context.WithCancel(context.Background()) ctx, ctxFun := context.WithCancel(context.Background())
d.cancleContext = ctxFun d.cancleContext = ctxFun
@ -303,17 +276,6 @@ func (d *trainPcSimService) Stop() {
d.newCloseAllConn() d.newCloseAllConn()
} }
/*
func (d *trainPcSimService) CreateOrRemoveSpeedPLace(train *state_proto.TrainState) {
if train.ConnState.Conn && (train.ConnState.ConnType == state_proto.TrainConnState_PC_SIM_A || train.ConnState.ConnType == state_proto.TrainConnState_PC_SIM_B) {
train.PluseCount = &state_proto.SensorSpeedPulseCount{}
d.speedPlace = &message.TrainSpeedPlaceReportMsg{TrainId: train.Id}
} else {
train.PluseCount = nil
d.speedPlace = nil
}
}
*/
func (d *trainPcSimService) CreateOrRemoveTrain(train *state_proto.TrainState, isCreate bool) error { func (d *trainPcSimService) CreateOrRemoveTrain(train *state_proto.TrainState, isCreate bool) error {
clientKey := FindTrainPcSimClientKey2(train) clientKey := FindTrainPcSimClientKey2(train)
err := d.initConn(clientKey) err := d.initConn(clientKey)
@ -402,13 +364,12 @@ func (d *trainPcSimService) sendTrainLocationAndSpeedTask(ctx context.Context) {
bm := &message.TrainPcSimBaseMessage{Type: message.SENDER_TRAIN_LOCATION_INFO, Data: data} bm := &message.TrainPcSimBaseMessage{Type: message.SENDER_TRAIN_LOCATION_INFO, Data: data}
d.TrainPluseCountReset(train) d.TrainPluseCountReset(train)
dataCode := bm.Encode() dataCode := bm.Encode()
slog.Info(fmt.Sprintf("发送列车速度位置,列车:%v,s1: %v,s2: %v,c2: %v,c2: %v,发送数据:%v", train.Id, s1, s2, trainClient.speedPlace.PulseCount1, trainClient.speedPlace.PulseCount2, hex.EncodeToString(dataCode))) //slog.Info(fmt.Sprintf("发送列车速度位置,列车:%v,s1: %v,s2: %v,c2: %v,c2: %v,发送数据:%v", train.Id, s1, s2, trainClient.speedPlace.PulseCount1, trainClient.speedPlace.PulseCount2, hex.EncodeToString(dataCode)))
err := trainClient.tcpClient.Send(dataCode) err := trainClient.tcpClient.Send(dataCode)
if err != nil { if err != nil {
slog.Error(fmt.Sprintf("发送列车速度位置失败,列车:%v,发送数据:%v", train.Id, hex.EncodeToString(dataCode))) slog.Error(fmt.Sprintf("发送列车速度位置失败,列车:%v,发送数据:%v", train.Id, hex.EncodeToString(dataCode)))
} }
} }
} }
time.Sleep(time.Millisecond * 80) time.Sleep(time.Millisecond * 80)
@ -450,7 +411,7 @@ func (d *trainPcSimService) SendDriverActive(train *state_proto.TrainState) {
} }
msgs = append(msgs, msg.Encode()...) msgs = append(msgs, msg.Encode()...)
hexData := hex.EncodeToString(msgs) hexData := hex.EncodeToString(msgs)
slog.Info(fmt.Sprintf("发送驾驶激活列车id:%v,数据:%v", train.Id, hexData)) //slog.Info(fmt.Sprintf("发送驾驶激活列车id:%v,数据:%v", train.Id, hexData))
err := trainClient.tcpClient.Send(msgs) err := trainClient.tcpClient.Send(msgs)
if err != nil { if err != nil {
@ -493,7 +454,7 @@ func (d *trainPcSimService) SendHandleSwitch(oldTraction, oldBrakeForce int64, t
msg.Type = message.RECIVE_TRAIN_HAND_KEY_BACKWARD msg.Type = message.RECIVE_TRAIN_HAND_KEY_BACKWARD
} }
da := msg.Encode() da := msg.Encode()
slog.Info("发送列车手柄消息", "msg", hex.EncodeToString(da)) //slog.Info("发送列车手柄消息", "msg", hex.EncodeToString(da))
err := trainClient.tcpClient.Send(da) err := trainClient.tcpClient.Send(da)
//err := client.Send(da) //err := client.Send(da)
if err != nil { if err != nil {
@ -519,7 +480,7 @@ func (d *trainPcSimService) SendTrainDirection(train *state_proto.TrainState, tr
for _, msg := range baseMsgs { for _, msg := range baseMsgs {
da := msg.Encode() da := msg.Encode()
slog.Info(fmt.Sprintf("发送列车方向列车:%v ,数据:%v", train.Id, hex.EncodeToString(da))) //slog.Info(fmt.Sprintf("发送列车方向列车:%v ,数据:%v", train.Id, hex.EncodeToString(da)))
err := trainClient.tcpClient.Send(da) err := trainClient.tcpClient.Send(da)
if err != nil { if err != nil {
@ -539,7 +500,7 @@ func (d *trainPcSimService) SendBaliseData2(train *state_proto.TrainState, msgTy
msg := &message.TrainPcSimBaseMessage{Type: msgType, Data: dd} msg := &message.TrainPcSimBaseMessage{Type: msgType, Data: dd}
da := msg.Encode() da := msg.Encode()
//slog.Info(fmt.Sprintf("发送列车PC仿真应答器信息,数据类型:0x%X,数据:%v", msgType, hex.EncodeToString(da))) slog.Info(fmt.Sprintf("发送列车PC仿真应答器信息,数据类型:0x%X,数据:%v", msgType, hex.EncodeToString(da)))
err := trainClient.tcpClient.Send(da) err := trainClient.tcpClient.Send(da)
if err != nil { if err != nil {
slog.Info(fmt.Sprintf("发送列车PC仿真应答器信息失败,数据:%v", hex.EncodeToString(da))) slog.Info(fmt.Sprintf("发送列车PC仿真应答器信息失败,数据:%v", hex.EncodeToString(da)))
@ -558,37 +519,13 @@ func (d *trainPcSimService) SendBaliseData(train *state_proto.TrainState, msgTyp
msg.Data = data msg.Data = data
da := msg.Encode() da := msg.Encode()
//slog.Info(fmt.Sprintf("发送列车PC仿真应答器信息,无应答器:%v,数据:%v", msgType == message.RECIVE_TRAIN_BTM_NOT_DATA, hex.EncodeToString(da))) slog.Info(fmt.Sprintf("发送列车PC仿真应答器信息,数据类型:0x%x源数据长度:%v,数据:%v", msgType, len(data), hex.EncodeToString(da)))
err := trainClient.tcpClient.Send(da) err := trainClient.tcpClient.Send(da)
if err != nil { if err != nil {
slog.Info(fmt.Sprintf("发送列车PC仿真应答器信息失败,数据:%v", hex.EncodeToString(da))) slog.Info(fmt.Sprintf("发送列车PC仿真应答器信息失败,数据:%v", hex.EncodeToString(da)))
} }
} }
/*func (d *trainPcSimService) PublishTrainControlEvent(train *state_proto.TrainState, events []TrainControlEvent) {
if len(events) <= 0 {
return
}
trainClient, trainDataErr := d.findTrainConn(train)
if trainDataErr != nil {
slog.Error("")
return
}
msgs := make([]byte, 0)
for _, event := range events {
msg := &message.TrainPcSimBaseMessage{Type: event.Type, Data: event.Data}
code := msg.Encode()
msgs = append(msgs, code...)
}
hexCode := hex.EncodeToString(msgs)
slog.Info(fmt.Sprintf("列车数字量信息发送数据:%v", hexCode))
err := trainClient.tcpClient.Send(msgs)
if err != nil {
slog.Error(fmt.Sprintf("列车数字量信息发送失败,数据:%v", hexCode))
}
}*/
func (d *trainPcSimService) SendTrainControlMsg(train *state_proto.TrainState, baseMessage []message.TrainPcSimBaseMessage) { func (d *trainPcSimService) SendTrainControlMsg(train *state_proto.TrainState, baseMessage []message.TrainPcSimBaseMessage) {
if len(baseMessage) <= 0 { if len(baseMessage) <= 0 {
return return
@ -601,7 +538,6 @@ func (d *trainPcSimService) SendTrainControlMsg(train *state_proto.TrainState, b
for _, msg := range baseMessage { for _, msg := range baseMessage {
d.sendData(trainClient.tcpClient, msg.Encode()) d.sendData(trainClient.tcpClient, msg.Encode())
} }
} }
func (d *trainPcSimService) sendData(client *tcp.TcpClient, data []byte) { func (d *trainPcSimService) sendData(client *tcp.TcpClient, data []byte) {

View File

@ -2,6 +2,7 @@ package memory
import ( import (
"fmt" "fmt"
"joylink.club/bj-rtsts-server/sys_error"
"unsafe" "unsafe"
"joylink.club/bj-rtsts-server/dto/data_proto" "joylink.club/bj-rtsts-server/dto/data_proto"
@ -19,20 +20,27 @@ func HandleSectionOperation(simulation *VerifySimulation, req *request_proto.Sec
case request_proto.Section_SetFaultOcc: case request_proto.Section_SetFaultOcc:
return fi.AxleSectionFaultOccDrive(simulation.World, uid, true) return fi.AxleSectionFaultOccDrive(simulation.World, uid, true)
case request_proto.Section_SetParams: case request_proto.Section_SetParams:
var err error err := setSectionParam(simulation.World, uid, req.Param)
setSectionParam(simulation.World, uid, req.Param)
if req.Param.MockDrst {
err = fi.AxleSectionDrstDrive(simulation.World, uid, true)
} else {
err = fi.AxleSectionDrstDrive(simulation.World, uid, false)
}
if err != nil { if err != nil {
return err return err
} }
if req.Param.MockDrst {
state, err := fi.AxleSectionDrstDrive(simulation.World, uid)
if err != nil {
return err
}
if state.Rjo {
return sys_error.New("运营原因拒绝复位")
}
}
if req.Param.MockPdrst { if req.Param.MockPdrst {
err = fi.AxleSectionPdrstDrive(simulation.World, uid, true) state, err := fi.AxleSectionPdrstDrive(simulation.World, uid)
} else { if err != nil {
err = fi.AxleSectionPdrstDrive(simulation.World, uid, false) return err
}
if state.Rjo {
return sys_error.New("运营原因拒绝预复位")
}
} }
return err return err
default: default:

View File

@ -5,6 +5,7 @@ import (
"fmt" "fmt"
"joylink.club/bj-rtsts-server/const/balise_const" "joylink.club/bj-rtsts-server/const/balise_const"
"joylink.club/ecs" "joylink.club/ecs"
"joylink.club/rtsssimulation/fi"
"strings" "strings"
"joylink.club/bj-rtsts-server/dto" "joylink.club/bj-rtsts-server/dto"
@ -39,7 +40,8 @@ func BalisePositionModify(simulation *VerifySimulation, req *dto.BaliseMoveReqDt
panic(fmt.Sprintf("未知的公里标方向[%d]", req.Km.Direction)) panic(fmt.Sprintf("未知的公里标方向[%d]", req.Km.Direction))
} }
//将应答器所在Link的两端公里标转为请求参数中公里标的坐标系 //将应答器所在Link的两端公里标转为请求参数中公里标的坐标系
link := transponder.LinkPosition().Link() linkPosition := transponder.LinkPosition()
link := linkPosition.Link()
akm, err := repository.ConvertKilometer(simulation.Repo, link.AKm(), km.CoordinateSystem) akm, err := repository.ConvertKilometer(simulation.Repo, link.AKm(), km.CoordinateSystem)
if err != nil { if err != nil {
panic(sys_error.New("应答器所在Link的起点公里标转换失败")) panic(sys_error.New("应答器所在Link的起点公里标转换失败"))
@ -194,8 +196,8 @@ func BaliseTelegramSend(simulation *VerifySimulation, req *dto.BaliseReqDto) *sy
return baliseTelegramSend(simulation, balise) return baliseTelegramSend(simulation, balise)
} }
// BaliseReset 重置应答器所有状态 // AllBaliseTelegramReset 重置应答器所有状态
func BaliseReset(simulation *VerifySimulation) *sys_error.BusinessError { func AllBaliseTelegramReset(simulation *VerifySimulation) *sys_error.BusinessError {
var errs []error var errs []error
for _, balise := range simulation.Repo.ResponderList() { for _, balise := range simulation.Repo.ResponderList() {
err := baliseTelegramReset(simulation, balise) err := baliseTelegramReset(simulation, balise)
@ -235,25 +237,28 @@ func baliseTelegramSend(simulation *VerifySimulation, balise *repository.Transpo
func balisePositionReset(simulation *VerifySimulation, balise *repository.Transponder) *sys_error.BusinessError { func balisePositionReset(simulation *VerifySimulation, balise *repository.Transponder) *sys_error.BusinessError {
entry, _ := entity.GetEntityByUid(simulation.World, balise.Id()) entry, _ := entity.GetEntityByUid(simulation.World, balise.Id())
component.KmType.Set(entry, balise.Km()) component.KmType.Set(entry, balise.Km())
linkPosition := balise.LinkPosition()
component.LinkPositionType.SetValue(entry, component_data.LinkPosition{ component.LinkPositionType.SetValue(entry, component_data.LinkPosition{
LinkId: balise.LinkPosition().Link().Id(), LinkId: linkPosition.Link().Id(),
Offset: balise.LinkPosition().Offset(), Offset: linkPosition.Offset(),
}) })
return nil return nil
} }
func baliseTelegramReset(simulation *VerifySimulation, balise *repository.Transponder) *sys_error.BusinessError { func baliseTelegramReset(simulation *VerifySimulation, balise *repository.Transponder) *sys_error.BusinessError {
entry, _ := entity.GetEntityByUid(simulation.World, balise.Id()) err := fi.BaliseUpdateFixedTelegram(simulation.World, balise.Id(), balise.FixedTelegram(), balise.FixedUserTelegram())
return sendEcsRequest(simulation.World, func() error { if err != nil {
component.BaliseFixedTelegramType.SetValue(entry, component.BaliseTelegram{ return sys_error.New("重置应答器报文失败", err)
Telegram: balise.FixedTelegram(), }
UserTelegram: balise.FixedUserTelegram(), err = fi.BaliseCancelForceVariableTelegram(simulation.World, balise.Id())
}) if err != nil {
if entry.HasComponent(component.BaliseVariableTelegramType) { return sys_error.New("重置应答器报文失败", err)
component.BaliseVariableTelegramType.SetValue(entry, component.BaliseTelegram{}) }
} err = fi.BaliseUpdateVariableTelegram(simulation.World, balise.Id(), []byte{}, false)
return nil if err != nil {
}) return sys_error.New("重置应答器报文失败", err)
}
return nil
} }
func sendEcsRequest(w ecs.World, request func() error) *sys_error.BusinessError { func sendEcsRequest(w ecs.World, request func() error) *sys_error.BusinessError {

View File

@ -271,38 +271,6 @@ func (s *VerifySimulation) CollectDynamicsTurnoutInfo() *message.DynamicsTurnout
return turnoutState return turnoutState
} }
// HandleSectionCmdMsg 计轴设备接收到联锁发送来的控制命令
func (s *VerifySimulation) HandleSectionCmdMsg(city string, lineId string, centralizedStation string, msg *message.SectionCmdMsgPack) {
stationUid := GenerateElementUid(city, lineId, nil, centralizedStation)
ref := s.Repo.GetCentralizedStationRef(stationUid)
if ref == nil {
slog.Warn(fmt.Sprintf("没有找到GetCentralizedStationRef [%s]", stationUid))
return
}
//
codePoints := ref.SectionCodePoints
if len(codePoints) != len(msg.Scs) {
slog.Warn(fmt.Sprintf("本地配置区段码表个数[%d] != 联锁发送集中站[%s]的区段命令个数[%d]", len(codePoints), stationUid, len(msg.Scs)))
return
}
//
var cpSectionMap = make(map[int]*proto.CiSectionCodePoint)
for _, cp := range codePoints {
cpSectionMap[int(cp.Row)] = cp
}
//
var cmds []*fi.AxleSectionCmd
for index, cmdMsg := range msg.Scs {
cp := cpSectionMap[index]
cmd := &fi.AxleSectionCmd{}
cmd.SectionId = cp.SectionId
cmd.Drst = cmdMsg.Drst
cmd.Pdrst = cmdMsg.Pdrst
cmds = append(cmds, cmd)
}
fi.AxleSectionRstDrive(s.World, cmds)
}
// 处理动力学列车速度消息 // 处理动力学列车速度消息
func (s *VerifySimulation) HandleDynamicsTrainInfo(info *message.DynamicsTrainInfo) { func (s *VerifySimulation) HandleDynamicsTrainInfo(info *message.DynamicsTrainInfo) {
trainId := strconv.Itoa(int(info.Number)) trainId := strconv.Itoa(int(info.Number))
@ -465,7 +433,6 @@ func (s *VerifySimulation) GetInterlockCodes() []*config.InterlockConfig {
configs = append(configs, &config.InterlockConfig{ configs = append(configs, &config.InterlockConfig{
Code: stationMap[c.Code], Code: stationMap[c.Code],
Ip: c.Ip, Ip: c.Ip,
LocalPort: c.LocalPort,
RemotePort: c.RemotePort, RemotePort: c.RemotePort,
Open: c.Open, Open: c.Open,
Line: c.Line, Line: c.Line,
@ -475,24 +442,31 @@ func (s *VerifySimulation) GetInterlockCodes() []*config.InterlockConfig {
} }
// 处理接到的联锁消息 // 处理接到的联锁消息
func (s *VerifySimulation) HandleInterlockDriverInfo(code string, b []byte) { func (s *VerifySimulation) HandleInterlockDriverInfo(code string, driveBytes []byte) {
wd := entity.GetWorldData(s.World)
for _, m := range s.Repo.CiQcList() { // 获取继电器地图信息 for _, m := range s.Repo.CiQcList() { // 获取继电器地图信息
if m.StationId != code { if m.StationId != code {
continue continue
} }
driverMsg := message.NewInterlockReceiveMsgPkg(0, len(m.QdList), len(m.TransponderId)) var driveInfo []bool
err := driverMsg.Decode(b) for _, b := range driveBytes {
if err != nil { for bit := 0; bit < 8; bit++ {
slog.Error(fmt.Sprintf("联锁驱动数据解析失败:%s", err)) driveInfo = append(driveInfo, (b&(1<<bit)) != 0)
} }
driveState := driverMsg.DriveInfo }
for i, r := range m.QdList { slog.Info(fmt.Sprintf("12号线驱动数据解析结果%v", driveInfo))
ds := driveState[i] for i, b := range driveInfo {
for _, b := range r.RefRelays { qdData := m.QdList[i]
slog.Debug("继电器位【%s】获取到驱动状态【%v】", b, ds) for _, relayId := range qdData.RefRelays {
if b {
}
err := wd.SetQdBit(relayId, b)
if err != nil {
slog.Error("联锁驱动数据设置出错", "error", err)
}
} }
} }
return
} }
} }
@ -1265,6 +1239,8 @@ func fillProtoRepository(repo *proto.Repository, storage *data_proto.RtssGraphic
FixedTelegram: fixedTelegram, FixedTelegram: fixedTelegram,
Type: convertToProtoBaliseType(data.Type), Type: convertToProtoBaliseType(data.Type),
FixedUserTelegram: fixedUserTelegram, FixedUserTelegram: fixedUserTelegram,
LeuIndex: data.LeuIndex,
IndexInLeu: data.LeuInsideIndex,
} }
switch data.TransponderRef.DeviceType { switch data.TransponderRef.DeviceType {
case data_proto.RelatedRef_Section: case data_proto.RelatedRef_Section:

View File

@ -516,6 +516,7 @@ func (s *VerifySimulation) reportTrainMockInitMsg(train *state_proto.TrainState,
if message.GetBit(data3, 3) == 0 { if message.GetBit(data3, 3) == 0 {
tce = append(tce, message.TrainPcSimBaseMessage{Type: message.SENDER_TRAIN_OUTR_INFO, Data: []byte{message.DRIVER_ACTIVE_REPORT, 1}}) tce = append(tce, message.TrainPcSimBaseMessage{Type: message.SENDER_TRAIN_OUTR_INFO, Data: []byte{message.DRIVER_ACTIVE_REPORT, 1}})
} }
tce = append(tce, message.TrainPcSimBaseMessage{Type: message.SENDER_TRAIN_OUTR_INFO, Data: []byte{message.TRAIN_INTEGRITY, 1}})
} }
train_pc_sim.Default().SendTrainControlMsg(train, tce) train_pc_sim.Default().SendTrainControlMsg(train, tce)
return initResult return initResult
@ -675,73 +676,67 @@ func (s *VerifySimulation) TrainPcSimMockInfo(train *state_proto.TrainState, dat
// 4.4.4. 车载输出BTM查询同步帧报文内容0x04 // 4.4.4. 车载输出BTM查询同步帧报文内容0x04
func (s *VerifySimulation) TrainBtmQuery(train *state_proto.TrainState, data []byte) { func (s *VerifySimulation) TrainBtmQuery(train *state_proto.TrainState, data []byte) {
//slog.Info(fmt.Sprintf("收到车载输出BTM查询同步帧报文内容:%v", hex.EncodeToString(data))) //time.Sleep(time.Millisecond * 50)
slog.Info(fmt.Sprintf("收到车载输出BTM查询同步帧报文内容:%v", hex.EncodeToString(data)))
if len(data) < 12 { if len(data) < 12 {
slog.Error("列车btm查询报文长度错误:", len(data)) slog.Error("列车btm查询报文长度错误:", len(data))
return return
} }
//train := s.FindConnTrain(connType)
if train.BtmState == nil {
slog.Warn("列车暂时未获取到应答器信息")
return
}
/*if train == nil {
slog.Error("车载输出btm查询,未找到连接车载pc仿真的列车")
return
}
if !train.ConnState.Conn {
slog.Error("车载输出btm查询,列车未连接车载pc仿真")
return
}*/
trainAtm := message.NewCanetFrame2(data, true) if train.BtmState == nil {
atpReq := &message.AtpRequestFrame{IsTrainPcSim: true} slog.Warn(fmt.Sprintf("列车暂时未获取到应答器信息,无法进行btm查询列车id:%v", train.Id))
if !atpReq.Decode(trainAtm) { return
}
trainAtm := message.NewBtmHeadFrame(data)
atpReq := &message.AtpRequestFrame{}
if !atpReq.Decode2(trainAtm) {
slog.Warn("列车pc驾驶模拟-CanetFrame解码成AtpRequestFrame失败", "CanetFrame", trainAtm.String()) slog.Warn("列车pc驾驶模拟-CanetFrame解码成AtpRequestFrame失败", "CanetFrame", trainAtm.String())
return return
} }
cl := clock(atpReq) cl := clock(atpReq)
btmRepFrame := createBtmStatus(trainAtm.CanId.ID4, train.BtmState, atpReq, cl) dsn := train_pc_sim.Default().DsnAddAndReturn()
btmRepFrame := createBtmStatus(trainAtm.CanId.ID4, train.BtmState, atpReq, cl, dsn)
//slog.Info(fmt.Sprintf("id1:%x,id2:%x,id3:%x,id4:%x,resendRequest:%v,reqTime:%v,dsn:%v", trainAtm.CanId.ID1, trainAtm.CanId.ID2, trainAtm.CanId.ID3, trainAtm.CanId.ID4, atpReq.ResendRequest, atpReq.Time, dsn))
if atpReq.ResendRequest == 2 { if atpReq.ResendRequest == 2 {
//重新发送 //重新发送
if len(train.BtmState.BaliseTelegramForPcSimResend) > 0 { if len(train.BtmState.BaliseTelegramForPcSimResend) > 0 {
dd, _ := hex.DecodeString(train.BtmState.BaliseTelegramForPcSimResend) dd, _ := hex.DecodeString(train.BtmState.BaliseTelegramForPcSimResend)
train_pc_sim.Default().SendBaliseData(train, message.RECIVE_TRAIN_BTM_HAS_DATA, dd) train_pc_sim.Default().SendBaliseData(train, message.RECIVE_TRAIN_BTM_HAS_DATA, dd)
} else {
timeSyncF := message.NewBtmTimeSyncCheckFrame(trainAtm.CanId.ID4)
timeSyncF.T2 = cl.BtmTk
timeSyncF.T3 = cl.TkNow()
queryData := make([]byte, 0)
queryData = append(queryData, btmRepFrame.EncodeBtmAtp().Encode()...)
queryData = append(queryData, timeSyncF.Encode().Encode()...)
train_pc_sim.Default().SendBaliseData(train, message.RECIVE_TRAIN_BTM_NOT_DATA, queryData)
} }
} else { } else {
timeSyncF := message.NewBtmTimeSyncCheckFrame(trainAtm.CanId.ID4, true) timeSyncF := message.NewBtmTimeSyncCheckFrame(trainAtm.CanId.ID4)
timeSyncF.T2 = cl.BtmTk timeSyncF.T2 = cl.BtmTk
timeSyncF.T3 = cl.TkNow() timeSyncF.T3 = cl.TkNow()
telCount := strings.Count(train.BtmState.Telegram, "00") telCount := strings.Count(train.BtmState.Telegram, "00")
if telCount >= balise_const.UserTelegramByteLen { if telCount >= balise_const.UserTelegramByteLen {
//无数据 queryData := make([]byte, 0)
queryDataStr := make([]string, 0) queryData = append(queryData, btmRepFrame.EncodeBtmAtp().Encode()...)
queryDataStr = append(queryDataStr, hex.EncodeToString(btmRepFrame.Encode().Encode2())) queryData = append(queryData, timeSyncF.EncodeBtmAtp().Encode()...)
queryDataStr = append(queryDataStr, hex.EncodeToString(timeSyncF.Encode().Encode2())) train_pc_sim.Default().SendBaliseData(train, message.RECIVE_TRAIN_BTM_NOT_DATA, queryData)
train_pc_sim.Default().SendBaliseData2(train, message.RECIVE_TRAIN_BTM_NOT_DATA, queryDataStr)
/* queryData := make([]byte, 0)
queryData = append(queryData, btmRepFrame.Encode().Encode()...)
queryData = append(queryData, timeSyncF.Encode().Encode()...)
train_pc_sim.Default().SendBaliseData(train, message.RECIVE_TRAIN_BTM_NOT_DATA, queryData)*/
} else { } else {
//有数据 //有数据
aliseData, _ := hex.DecodeString(train.BtmState.Telegram) aliseData, _ := hex.DecodeString(train.BtmState.Telegram)
statusDataCf, statusDataCfOk := message.CreateBtmRspFramesData2(btmRepFrame, aliseData, false, cl.TkNow(), cl.TkNow(), cl.TkNow(), true) stateRepFrame := btmRepFrame.EncodeBtmAtp()
statusDataCf, statusDataCfOk := message.CreateBtmAtpDataRspFramesData(stateRepFrame, aliseData, false, cl.BtmTk, cl.BtmTk, cl.BtmTk)
if statusDataCfOk { if statusDataCfOk {
/* queryData := make([]byte, 0) timeSyncF.T2 = cl.BtmTk
queryData = append(queryData, btmRepFrame.Encode().Encode2()...) timeSyncF.T3 = cl.TkNow()
queryData = append(queryData, timeSyncF.Encode().Encode2()...) queryData := make([]byte, 0)
queryData = append(queryData, statusDataCf...) //数据帧包含结束帧 queryData = append(queryData, stateRepFrame.Encode()...)
train.BtmState.BaliseTelegramForPcSimResend = fmt.Sprintf("%X", statusDataCf) queryData = append(queryData, timeSyncF.EncodeBtmAtp().Encode()...)
train_pc_sim.Default().SendBaliseData(train, message.RECIVE_TRAIN_BTM_HAS_DATA, queryData)*/ queryData = append(queryData, statusDataCf...) //数据帧包含结束帧
queryDataStr := make([]string, 0)
queryDataStr = append(queryDataStr, hex.EncodeToString(btmRepFrame.Encode().Encode2()))
queryDataStr = append(queryDataStr, hex.EncodeToString(timeSyncF.Encode().Encode2()))
queryDataStr = append(queryDataStr, hex.EncodeToString(statusDataCf)) //数据帧包含结束帧
train.BtmState.BaliseTelegramForPcSimResend = fmt.Sprintf("%X", statusDataCf) train.BtmState.BaliseTelegramForPcSimResend = fmt.Sprintf("%X", statusDataCf)
train_pc_sim.Default().SendBaliseData2(train, message.RECIVE_TRAIN_BTM_HAS_DATA, queryDataStr) train_pc_sim.Default().SendBaliseData(train, message.RECIVE_TRAIN_BTM_HAS_DATA, queryData)
} else { } else {
slog.Error("列车pc仿真 BtmCanetClient应答帧、数据帧编码失败") slog.Error("列车pc仿真 BtmCanetClient应答帧、数据帧编码失败")
} }
@ -749,22 +744,21 @@ func (s *VerifySimulation) TrainBtmQuery(train *state_proto.TrainState, data []b
} }
} }
func createBtmStatus(canIdSn byte, btmState *state_proto.BTMState, atpReq *message.AtpRequestFrame, cl can_btm.BtmClock) *message.BtmStatusRspFrame { func createBtmStatus(canIdSn byte, btmState *state_proto.BTMState, atpReq *message.AtpRequestFrame, cl can_btm.BtmClock, dsn byte) *message.BtmStatusRspFrame {
statusF := message.NewBtmStatusRspFrame(canIdSn, atpReq.IsTrainPcSim) statusF := message.NewBtmStatusRspFrame(canIdSn)
//btmStatus := aa(train, atpReq)
statusF.PowerAmplifierOn = true statusF.PowerAmplifierOn = true
statusF.PowerAmplifierFailure = false statusF.PowerAmplifierFailure = false
statusF.AtpReqCrcCheckWrong = !atpReq.Crc16CheckOk statusF.AtpReqCrcCheckWrong = !atpReq.Crc16CheckOk
statusF.AntennaFault = false statusF.AntennaFault = false
statusF.BaliseCounter = byte(btmState.BaliseCount) statusF.BaliseCounter = byte(btmState.BaliseCount)
statusF.MessageCounter = byte(btmState.MessageCounter) statusF.MessageCounter = byte(btmState.MessageCounter)
statusF.TkTimeA = cl.TkNow() //statusF.TkTimeA = cl.TkNow()
statusF.TkTimeA = cl.BtmTk
statusF.DetailedCode = 0 statusF.DetailedCode = 0
if btmState.AboveBalise { if btmState.AboveBalise {
statusF.DetailedCode = 0x07 statusF.DetailedCode = 0x07
} }
dsn := byte(btmState.DataSerialNumber) + 1
btmState.DataSerialNumber = uint32(dsn) btmState.DataSerialNumber = uint32(dsn)
statusF.Dsn = dsn statusF.Dsn = dsn
return statusF return statusF

View File

@ -126,7 +126,7 @@ func runThirdParty(s *memory.VerifySimulation) error {
case "11": case "11":
beijing11.Start(c, s) beijing11.Start(c, s)
default: default:
beijing12.Start(c, s) beijing12.Start(c, s, s.Repo.TransponderList())
} }
} }
// 计轴RSSP启动 // 计轴RSSP启动

38
util/myreader/reader.go Normal file
View File

@ -0,0 +1,38 @@
package myreader
import "bytes"
type Reader struct {
r *bytes.Reader
Err error
}
func NewReader(b []byte) *Reader {
return &Reader{r: bytes.NewReader(b)}
}
func (r *Reader) ReadByte() byte {
if r.Err != nil {
return 0
}
b, err := r.r.ReadByte()
r.Err = err
return b
}
func (r *Reader) Read(b []byte) (n int) {
if r.Err != nil {
return 0
}
n, r.Err = r.r.Read(b)
return n
}
func (r *Reader) ReadBytes(n int) []byte {
if r.Err != nil {
return nil
}
b := make([]byte, n)
r.Read(b)
return b
}