From ad6dbcb940f3aa157dc2237e7e37e7bd2496035b Mon Sep 17 00:00:00 2001 From: Vlad Vitan Date: Mon, 9 Sep 2024 13:56:40 +0200 Subject: [PATCH] qrg: Update parse gateway qr response --- api/ttn/lorawan/v3/api.md | 10 +- api/ttn/lorawan/v3/api.swagger.json | 9 +- api/ttn/lorawan/v3/qrcodegenerator.proto | 19 +- pkg/qrcodegenerator/grpc_gateways.go | 12 +- pkg/qrcodegenerator/grpc_gateways_test.go | 2 + pkg/ttnpb/qrcodegenerator.pb.go | 361 +++++++++++---------- pkg/ttnpb/qrcodegenerator.pb.paths.fm.go | 31 +- pkg/ttnpb/qrcodegenerator.pb.setters.fm.go | 38 +-- pkg/ttnpb/qrcodegenerator.pb.validate.go | 24 +- pkg/ttnpb/qrcodegenerator_json.pb.go | 25 +- sdk/js/generated/api.json | 38 ++- 11 files changed, 313 insertions(+), 256 deletions(-) diff --git a/api/ttn/lorawan/v3/api.md b/api/ttn/lorawan/v3/api.md index 181ad113a1c..6ac6ab67570 100644 --- a/api/ttn/lorawan/v3/api.md +++ b/api/ttn/lorawan/v3/api.md @@ -10563,7 +10563,15 @@ The Pba service allows clients to manage peering through Packet Broker. | Field | Type | Label | Description | | ----- | ---- | ----- | ----------- | | `format_id` | [`string`](#string) | | Identifier of the format used to successfully parse the QR code data. | -| `claim_gateway_request` | [`ClaimGatewayRequest`](#ttn.lorawan.v3.ClaimGatewayRequest) | | | +| `gateway_eui` | [`bytes`](#bytes) | | | +| `owner_token` | [`string`](#string) | | | + +#### Field Rules + +| Field | Validations | +| ----- | ----------- | +| `gateway_eui` |

`bytes.len`: `8`

| +| `owner_token` |

`string.pattern`: `^[A-Z0-9]{1,32}$`

| ### Message `QRCodeFormat` diff --git a/api/ttn/lorawan/v3/api.swagger.json b/api/ttn/lorawan/v3/api.swagger.json index 14f5e8b3db8..7139915ce9e 100644 --- a/api/ttn/lorawan/v3/api.swagger.json +++ b/api/ttn/lorawan/v3/api.swagger.json @@ -28052,8 +28052,13 @@ "type": "string", "description": "Identifier of the format used to successfully parse the QR code data." }, - "claim_gateway_request": { - "$ref": "#/definitions/v3ClaimGatewayRequest" + "gateway_eui": { + "type": "string", + "format": "string", + "example": "70B3D57ED000ABCD" + }, + "owner_token": { + "type": "string" } } }, diff --git a/api/ttn/lorawan/v3/qrcodegenerator.proto b/api/ttn/lorawan/v3/qrcodegenerator.proto index 97d7dce97b2..48d52b2aaf6 100644 --- a/api/ttn/lorawan/v3/qrcodegenerator.proto +++ b/api/ttn/lorawan/v3/qrcodegenerator.proto @@ -20,7 +20,7 @@ import "google/api/annotations.proto"; import "google/protobuf/empty.proto"; import "google/protobuf/field_mask.proto"; import "protoc-gen-openapiv2/options/annotations.proto"; -import "ttn/lorawan/v3/deviceclaimingserver.proto"; +import "thethings/json/annotations.proto"; import "ttn/lorawan/v3/end_device.proto"; import "ttn/lorawan/v3/picture.proto"; import "validate/validate.proto"; @@ -149,7 +149,22 @@ message ParseGatewayQRCodeRequest { message ParseGatewayQRCodeResponse { // Identifier of the format used to successfully parse the QR code data. string format_id = 1; - ClaimGatewayRequest claim_gateway_request = 2; + bytes gateway_eui = 2 [ + (validate.rules).bytes = { + len: 8, + ignore_empty: true + }, + (thethings.json.field) = { + marshaler_func: "go.thethings.network/lorawan-stack/v3/pkg/types.MarshalHEXBytes", + unmarshaler_func: "go.thethings.network/lorawan-stack/v3/pkg/types.Unmarshal8Bytes" + }, + (grpc.gateway.protoc_gen_openapiv2.options.openapiv2_field) = { + type: STRING, + format: "string", + example: "\"70B3D57ED000ABCD\"" + } + ]; + string owner_token = 3 [(validate.rules).string.pattern = "^[A-Z0-9]{1,32}$"]; } // The GatewayQRCodeGenerator service provides functionality to generate and parse QR codes for gateways. diff --git a/pkg/qrcodegenerator/grpc_gateways.go b/pkg/qrcodegenerator/grpc_gateways.go index 0d71101cf77..4b61de1ea1d 100644 --- a/pkg/qrcodegenerator/grpc_gateways.go +++ b/pkg/qrcodegenerator/grpc_gateways.go @@ -59,14 +59,8 @@ func (s *gatewayQRCodeGeneratorServer) Parse( } return &ttnpb.ParseGatewayQRCodeResponse{ - FormatId: data.FormatID(), - ClaimGatewayRequest: &ttnpb.ClaimGatewayRequest{ - SourceGateway: &ttnpb.ClaimGatewayRequest_AuthenticatedIdentifiers_{ - AuthenticatedIdentifiers: &ttnpb.ClaimGatewayRequest_AuthenticatedIdentifiers{ - GatewayEui: data.GatewayEUI().Bytes(), - AuthenticationCode: []byte(data.OwnerToken()), - }, - }, - }, + FormatId: data.FormatID(), + GatewayEui: data.GatewayEUI().Bytes(), + OwnerToken: data.OwnerToken(), }, nil } diff --git a/pkg/qrcodegenerator/grpc_gateways_test.go b/pkg/qrcodegenerator/grpc_gateways_test.go index a5876a5d471..0c6971fdadc 100644 --- a/pkg/qrcodegenerator/grpc_gateways_test.go +++ b/pkg/qrcodegenerator/grpc_gateways_test.go @@ -117,6 +117,8 @@ func TestGatewayQRCodeParsing(t *testing.T) { return false } a.So(resp.FormatId, should.Equal, ttigpro1.ID()) + a.So(resp.GatewayEui, should.Resemble, []uint8{0xec, 0x65, 0x6e, 0xff, 0xfe, 0x00, 0x01, 0x28}) + a.So(resp.OwnerToken, should.Equal, "abcdef123456") return true }, diff --git a/pkg/ttnpb/qrcodegenerator.pb.go b/pkg/ttnpb/qrcodegenerator.pb.go index c063ccd948c..6bee04fba62 100644 --- a/pkg/ttnpb/qrcodegenerator.pb.go +++ b/pkg/ttnpb/qrcodegenerator.pb.go @@ -21,6 +21,7 @@ package ttnpb import ( + _ "github.com/TheThingsIndustries/protoc-gen-go-json/annotations" _ "github.com/envoyproxy/protoc-gen-validate/validate" _ "github.com/grpc-ecosystem/grpc-gateway/v2/protoc-gen-openapiv2/options" _ "google.golang.org/genproto/googleapis/api/annotations" @@ -501,8 +502,9 @@ type ParseGatewayQRCodeResponse struct { unknownFields protoimpl.UnknownFields // Identifier of the format used to successfully parse the QR code data. - FormatId string `protobuf:"bytes,1,opt,name=format_id,json=formatId,proto3" json:"format_id,omitempty"` - ClaimGatewayRequest *ClaimGatewayRequest `protobuf:"bytes,2,opt,name=claim_gateway_request,json=claimGatewayRequest,proto3" json:"claim_gateway_request,omitempty"` + FormatId string `protobuf:"bytes,1,opt,name=format_id,json=formatId,proto3" json:"format_id,omitempty"` + GatewayEui []byte `protobuf:"bytes,2,opt,name=gateway_eui,json=gatewayEui,proto3" json:"gateway_eui,omitempty"` + OwnerToken string `protobuf:"bytes,3,opt,name=owner_token,json=ownerToken,proto3" json:"owner_token,omitempty"` } func (x *ParseGatewayQRCodeResponse) Reset() { @@ -544,13 +546,20 @@ func (x *ParseGatewayQRCodeResponse) GetFormatId() string { return "" } -func (x *ParseGatewayQRCodeResponse) GetClaimGatewayRequest() *ClaimGatewayRequest { +func (x *ParseGatewayQRCodeResponse) GetGatewayEui() []byte { if x != nil { - return x.ClaimGatewayRequest + return x.GatewayEui } return nil } +func (x *ParseGatewayQRCodeResponse) GetOwnerToken() string { + if x != nil { + return x.OwnerToken + } + return "" +} + type GenerateEndDeviceQRCodeRequest_Image struct { state protoimpl.MessageState sizeCache protoimpl.SizeCache @@ -614,161 +623,172 @@ var file_ttn_lorawan_v3_qrcodegenerator_proto_rawDesc = []byte{ 0x6f, 0x74, 0x6f, 0x1a, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x63, 0x2d, 0x67, 0x65, 0x6e, 0x2d, 0x6f, 0x70, 0x65, 0x6e, 0x61, 0x70, 0x69, 0x76, 0x32, 0x2f, 0x6f, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x2f, 0x61, 0x6e, 0x6e, 0x6f, 0x74, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x2e, 0x70, 0x72, - 0x6f, 0x74, 0x6f, 0x1a, 0x29, 0x74, 0x74, 0x6e, 0x2f, 0x6c, 0x6f, 0x72, 0x61, 0x77, 0x61, 0x6e, - 0x2f, 0x76, 0x33, 0x2f, 0x64, 0x65, 0x76, 0x69, 0x63, 0x65, 0x63, 0x6c, 0x61, 0x69, 0x6d, 0x69, - 0x6e, 0x67, 0x73, 0x65, 0x72, 0x76, 0x65, 0x72, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x1a, 0x1f, - 0x74, 0x74, 0x6e, 0x2f, 0x6c, 0x6f, 0x72, 0x61, 0x77, 0x61, 0x6e, 0x2f, 0x76, 0x33, 0x2f, 0x65, - 0x6e, 0x64, 0x5f, 0x64, 0x65, 0x76, 0x69, 0x63, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x1a, - 0x1c, 0x74, 0x74, 0x6e, 0x2f, 0x6c, 0x6f, 0x72, 0x61, 0x77, 0x61, 0x6e, 0x2f, 0x76, 0x33, 0x2f, - 0x70, 0x69, 0x63, 0x74, 0x75, 0x72, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x1a, 0x17, 0x76, - 0x61, 0x6c, 0x69, 0x64, 0x61, 0x74, 0x65, 0x2f, 0x76, 0x61, 0x6c, 0x69, 0x64, 0x61, 0x74, 0x65, - 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x22, 0x92, 0x01, 0x0a, 0x0c, 0x51, 0x52, 0x43, 0x6f, 0x64, - 0x65, 0x46, 0x6f, 0x72, 0x6d, 0x61, 0x74, 0x12, 0x1b, 0x0a, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x18, - 0x01, 0x20, 0x01, 0x28, 0x09, 0x42, 0x07, 0xfa, 0x42, 0x04, 0x72, 0x02, 0x18, 0x64, 0x52, 0x04, - 0x6e, 0x61, 0x6d, 0x65, 0x12, 0x2a, 0x0a, 0x0b, 0x64, 0x65, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, - 0x69, 0x6f, 0x6e, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x42, 0x08, 0xfa, 0x42, 0x05, 0x72, 0x03, - 0x18, 0xc8, 0x01, 0x52, 0x0b, 0x64, 0x65, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x69, 0x6f, 0x6e, - 0x12, 0x39, 0x0a, 0x0a, 0x66, 0x69, 0x65, 0x6c, 0x64, 0x5f, 0x6d, 0x61, 0x73, 0x6b, 0x18, 0x03, - 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1a, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, - 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x46, 0x69, 0x65, 0x6c, 0x64, 0x4d, 0x61, 0x73, 0x6b, - 0x52, 0x09, 0x66, 0x69, 0x65, 0x6c, 0x64, 0x4d, 0x61, 0x73, 0x6b, 0x22, 0xdd, 0x01, 0x0a, 0x0d, - 0x51, 0x52, 0x43, 0x6f, 0x64, 0x65, 0x46, 0x6f, 0x72, 0x6d, 0x61, 0x74, 0x73, 0x12, 0x72, 0x0a, - 0x07, 0x66, 0x6f, 0x72, 0x6d, 0x61, 0x74, 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x2a, - 0x2e, 0x74, 0x74, 0x6e, 0x2e, 0x6c, 0x6f, 0x72, 0x61, 0x77, 0x61, 0x6e, 0x2e, 0x76, 0x33, 0x2e, - 0x51, 0x52, 0x43, 0x6f, 0x64, 0x65, 0x46, 0x6f, 0x72, 0x6d, 0x61, 0x74, 0x73, 0x2e, 0x46, 0x6f, - 0x72, 0x6d, 0x61, 0x74, 0x73, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x42, 0x2c, 0xfa, 0x42, 0x29, 0x9a, - 0x01, 0x26, 0x22, 0x24, 0x72, 0x22, 0x18, 0x24, 0x32, 0x1e, 0x5e, 0x5b, 0x61, 0x2d, 0x7a, 0x30, + 0x6f, 0x74, 0x6f, 0x1a, 0x20, 0x74, 0x68, 0x65, 0x74, 0x68, 0x69, 0x6e, 0x67, 0x73, 0x2f, 0x6a, + 0x73, 0x6f, 0x6e, 0x2f, 0x61, 0x6e, 0x6e, 0x6f, 0x74, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x2e, + 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x1a, 0x1f, 0x74, 0x74, 0x6e, 0x2f, 0x6c, 0x6f, 0x72, 0x61, 0x77, + 0x61, 0x6e, 0x2f, 0x76, 0x33, 0x2f, 0x65, 0x6e, 0x64, 0x5f, 0x64, 0x65, 0x76, 0x69, 0x63, 0x65, + 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x1a, 0x1c, 0x74, 0x74, 0x6e, 0x2f, 0x6c, 0x6f, 0x72, 0x61, + 0x77, 0x61, 0x6e, 0x2f, 0x76, 0x33, 0x2f, 0x70, 0x69, 0x63, 0x74, 0x75, 0x72, 0x65, 0x2e, 0x70, + 0x72, 0x6f, 0x74, 0x6f, 0x1a, 0x17, 0x76, 0x61, 0x6c, 0x69, 0x64, 0x61, 0x74, 0x65, 0x2f, 0x76, + 0x61, 0x6c, 0x69, 0x64, 0x61, 0x74, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x22, 0x92, 0x01, + 0x0a, 0x0c, 0x51, 0x52, 0x43, 0x6f, 0x64, 0x65, 0x46, 0x6f, 0x72, 0x6d, 0x61, 0x74, 0x12, 0x1b, + 0x0a, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x42, 0x07, 0xfa, 0x42, + 0x04, 0x72, 0x02, 0x18, 0x64, 0x52, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x12, 0x2a, 0x0a, 0x0b, 0x64, + 0x65, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, + 0x42, 0x08, 0xfa, 0x42, 0x05, 0x72, 0x03, 0x18, 0xc8, 0x01, 0x52, 0x0b, 0x64, 0x65, 0x73, 0x63, + 0x72, 0x69, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x39, 0x0a, 0x0a, 0x66, 0x69, 0x65, 0x6c, 0x64, + 0x5f, 0x6d, 0x61, 0x73, 0x6b, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1a, 0x2e, 0x67, 0x6f, + 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x46, 0x69, + 0x65, 0x6c, 0x64, 0x4d, 0x61, 0x73, 0x6b, 0x52, 0x09, 0x66, 0x69, 0x65, 0x6c, 0x64, 0x4d, 0x61, + 0x73, 0x6b, 0x22, 0xdd, 0x01, 0x0a, 0x0d, 0x51, 0x52, 0x43, 0x6f, 0x64, 0x65, 0x46, 0x6f, 0x72, + 0x6d, 0x61, 0x74, 0x73, 0x12, 0x72, 0x0a, 0x07, 0x66, 0x6f, 0x72, 0x6d, 0x61, 0x74, 0x73, 0x18, + 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x2a, 0x2e, 0x74, 0x74, 0x6e, 0x2e, 0x6c, 0x6f, 0x72, 0x61, + 0x77, 0x61, 0x6e, 0x2e, 0x76, 0x33, 0x2e, 0x51, 0x52, 0x43, 0x6f, 0x64, 0x65, 0x46, 0x6f, 0x72, + 0x6d, 0x61, 0x74, 0x73, 0x2e, 0x46, 0x6f, 0x72, 0x6d, 0x61, 0x74, 0x73, 0x45, 0x6e, 0x74, 0x72, + 0x79, 0x42, 0x2c, 0xfa, 0x42, 0x29, 0x9a, 0x01, 0x26, 0x22, 0x24, 0x72, 0x22, 0x18, 0x24, 0x32, + 0x1e, 0x5e, 0x5b, 0x61, 0x2d, 0x7a, 0x30, 0x2d, 0x39, 0x5d, 0x28, 0x3f, 0x3a, 0x5b, 0x2d, 0x5d, + 0x3f, 0x5b, 0x61, 0x2d, 0x7a, 0x30, 0x2d, 0x39, 0x5d, 0x29, 0x7b, 0x32, 0x2c, 0x7d, 0x24, 0x52, + 0x07, 0x66, 0x6f, 0x72, 0x6d, 0x61, 0x74, 0x73, 0x1a, 0x58, 0x0a, 0x0c, 0x46, 0x6f, 0x72, 0x6d, + 0x61, 0x74, 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, 0x32, 0x0a, 0x05, 0x76, 0x61, + 0x6c, 0x75, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1c, 0x2e, 0x74, 0x74, 0x6e, 0x2e, + 0x6c, 0x6f, 0x72, 0x61, 0x77, 0x61, 0x6e, 0x2e, 0x76, 0x33, 0x2e, 0x51, 0x52, 0x43, 0x6f, 0x64, + 0x65, 0x46, 0x6f, 0x72, 0x6d, 0x61, 0x74, 0x52, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x3a, 0x02, + 0x38, 0x01, 0x22, 0x5e, 0x0a, 0x16, 0x47, 0x65, 0x74, 0x51, 0x52, 0x43, 0x6f, 0x64, 0x65, 0x46, + 0x6f, 0x72, 0x6d, 0x61, 0x74, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x44, 0x0a, 0x09, + 0x66, 0x6f, 0x72, 0x6d, 0x61, 0x74, 0x5f, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x42, + 0x27, 0xfa, 0x42, 0x24, 0x72, 0x22, 0x18, 0x24, 0x32, 0x1e, 0x5e, 0x5b, 0x61, 0x2d, 0x7a, 0x30, 0x2d, 0x39, 0x5d, 0x28, 0x3f, 0x3a, 0x5b, 0x2d, 0x5d, 0x3f, 0x5b, 0x61, 0x2d, 0x7a, 0x30, 0x2d, - 0x39, 0x5d, 0x29, 0x7b, 0x32, 0x2c, 0x7d, 0x24, 0x52, 0x07, 0x66, 0x6f, 0x72, 0x6d, 0x61, 0x74, - 0x73, 0x1a, 0x58, 0x0a, 0x0c, 0x46, 0x6f, 0x72, 0x6d, 0x61, 0x74, 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, 0x32, 0x0a, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x02, 0x20, 0x01, - 0x28, 0x0b, 0x32, 0x1c, 0x2e, 0x74, 0x74, 0x6e, 0x2e, 0x6c, 0x6f, 0x72, 0x61, 0x77, 0x61, 0x6e, - 0x2e, 0x76, 0x33, 0x2e, 0x51, 0x52, 0x43, 0x6f, 0x64, 0x65, 0x46, 0x6f, 0x72, 0x6d, 0x61, 0x74, - 0x52, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x3a, 0x02, 0x38, 0x01, 0x22, 0x5e, 0x0a, 0x16, 0x47, - 0x65, 0x74, 0x51, 0x52, 0x43, 0x6f, 0x64, 0x65, 0x46, 0x6f, 0x72, 0x6d, 0x61, 0x74, 0x52, 0x65, + 0x39, 0x5d, 0x29, 0x7b, 0x32, 0x2c, 0x7d, 0x24, 0x52, 0x08, 0x66, 0x6f, 0x72, 0x6d, 0x61, 0x74, + 0x49, 0x64, 0x22, 0xaa, 0x02, 0x0a, 0x1e, 0x47, 0x65, 0x6e, 0x65, 0x72, 0x61, 0x74, 0x65, 0x45, + 0x6e, 0x64, 0x44, 0x65, 0x76, 0x69, 0x63, 0x65, 0x51, 0x52, 0x43, 0x6f, 0x64, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x44, 0x0a, 0x09, 0x66, 0x6f, 0x72, 0x6d, 0x61, 0x74, 0x5f, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x42, 0x27, 0xfa, 0x42, 0x24, 0x72, 0x22, 0x18, 0x24, 0x32, 0x1e, 0x5e, 0x5b, 0x61, 0x2d, 0x7a, 0x30, 0x2d, 0x39, 0x5d, 0x28, 0x3f, 0x3a, 0x5b, 0x2d, 0x5d, 0x3f, 0x5b, 0x61, 0x2d, 0x7a, 0x30, 0x2d, 0x39, 0x5d, 0x29, 0x7b, 0x32, 0x2c, 0x7d, - 0x24, 0x52, 0x08, 0x66, 0x6f, 0x72, 0x6d, 0x61, 0x74, 0x49, 0x64, 0x22, 0xaa, 0x02, 0x0a, 0x1e, - 0x47, 0x65, 0x6e, 0x65, 0x72, 0x61, 0x74, 0x65, 0x45, 0x6e, 0x64, 0x44, 0x65, 0x76, 0x69, 0x63, - 0x65, 0x51, 0x52, 0x43, 0x6f, 0x64, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x44, - 0x0a, 0x09, 0x66, 0x6f, 0x72, 0x6d, 0x61, 0x74, 0x5f, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, - 0x09, 0x42, 0x27, 0xfa, 0x42, 0x24, 0x72, 0x22, 0x18, 0x24, 0x32, 0x1e, 0x5e, 0x5b, 0x61, 0x2d, - 0x7a, 0x30, 0x2d, 0x39, 0x5d, 0x28, 0x3f, 0x3a, 0x5b, 0x2d, 0x5d, 0x3f, 0x5b, 0x61, 0x2d, 0x7a, - 0x30, 0x2d, 0x39, 0x5d, 0x29, 0x7b, 0x32, 0x2c, 0x7d, 0x24, 0x52, 0x08, 0x66, 0x6f, 0x72, 0x6d, - 0x61, 0x74, 0x49, 0x64, 0x12, 0x42, 0x0a, 0x0a, 0x65, 0x6e, 0x64, 0x5f, 0x64, 0x65, 0x76, 0x69, - 0x63, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x19, 0x2e, 0x74, 0x74, 0x6e, 0x2e, 0x6c, - 0x6f, 0x72, 0x61, 0x77, 0x61, 0x6e, 0x2e, 0x76, 0x33, 0x2e, 0x45, 0x6e, 0x64, 0x44, 0x65, 0x76, - 0x69, 0x63, 0x65, 0x42, 0x08, 0xfa, 0x42, 0x05, 0x8a, 0x01, 0x02, 0x10, 0x01, 0x52, 0x09, 0x65, - 0x6e, 0x64, 0x44, 0x65, 0x76, 0x69, 0x63, 0x65, 0x12, 0x4a, 0x0a, 0x05, 0x69, 0x6d, 0x61, 0x67, - 0x65, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x34, 0x2e, 0x74, 0x74, 0x6e, 0x2e, 0x6c, 0x6f, - 0x72, 0x61, 0x77, 0x61, 0x6e, 0x2e, 0x76, 0x33, 0x2e, 0x47, 0x65, 0x6e, 0x65, 0x72, 0x61, 0x74, - 0x65, 0x45, 0x6e, 0x64, 0x44, 0x65, 0x76, 0x69, 0x63, 0x65, 0x51, 0x52, 0x43, 0x6f, 0x64, 0x65, - 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x2e, 0x49, 0x6d, 0x61, 0x67, 0x65, 0x52, 0x05, 0x69, - 0x6d, 0x61, 0x67, 0x65, 0x1a, 0x32, 0x0a, 0x05, 0x49, 0x6d, 0x61, 0x67, 0x65, 0x12, 0x29, 0x0a, - 0x0a, 0x69, 0x6d, 0x61, 0x67, 0x65, 0x5f, 0x73, 0x69, 0x7a, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, - 0x0d, 0x42, 0x0a, 0xfa, 0x42, 0x07, 0x2a, 0x05, 0x18, 0xe8, 0x07, 0x28, 0x0a, 0x52, 0x09, 0x69, - 0x6d, 0x61, 0x67, 0x65, 0x53, 0x69, 0x7a, 0x65, 0x22, 0x5b, 0x0a, 0x16, 0x47, 0x65, 0x6e, 0x65, - 0x72, 0x61, 0x74, 0x65, 0x51, 0x52, 0x43, 0x6f, 0x64, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, - 0x73, 0x65, 0x12, 0x12, 0x0a, 0x04, 0x74, 0x65, 0x78, 0x74, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, - 0x52, 0x04, 0x74, 0x65, 0x78, 0x74, 0x12, 0x2d, 0x0a, 0x05, 0x69, 0x6d, 0x61, 0x67, 0x65, 0x18, - 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x17, 0x2e, 0x74, 0x74, 0x6e, 0x2e, 0x6c, 0x6f, 0x72, 0x61, - 0x77, 0x61, 0x6e, 0x2e, 0x76, 0x33, 0x2e, 0x50, 0x69, 0x63, 0x74, 0x75, 0x72, 0x65, 0x52, 0x05, - 0x69, 0x6d, 0x61, 0x67, 0x65, 0x22, 0x8b, 0x01, 0x0a, 0x1b, 0x50, 0x61, 0x72, 0x73, 0x65, 0x45, - 0x6e, 0x64, 0x44, 0x65, 0x76, 0x69, 0x63, 0x65, 0x51, 0x52, 0x43, 0x6f, 0x64, 0x65, 0x52, 0x65, - 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x47, 0x0a, 0x09, 0x66, 0x6f, 0x72, 0x6d, 0x61, 0x74, 0x5f, - 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x42, 0x2a, 0xfa, 0x42, 0x27, 0x72, 0x25, 0x18, - 0x24, 0x32, 0x21, 0x5e, 0x5b, 0x61, 0x2d, 0x7a, 0x30, 0x2d, 0x39, 0x5d, 0x28, 0x3f, 0x3a, 0x5b, - 0x2d, 0x5d, 0x3f, 0x5b, 0x61, 0x2d, 0x7a, 0x30, 0x2d, 0x39, 0x5d, 0x29, 0x7b, 0x32, 0x2c, 0x7d, - 0x24, 0x7c, 0x5e, 0x24, 0x52, 0x08, 0x66, 0x6f, 0x72, 0x6d, 0x61, 0x74, 0x49, 0x64, 0x12, 0x23, - 0x0a, 0x07, 0x71, 0x72, 0x5f, 0x63, 0x6f, 0x64, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0c, 0x42, - 0x0a, 0xfa, 0x42, 0x07, 0x7a, 0x05, 0x10, 0x0a, 0x18, 0x80, 0x08, 0x52, 0x06, 0x71, 0x72, 0x43, - 0x6f, 0x64, 0x65, 0x22, 0x8e, 0x01, 0x0a, 0x1c, 0x50, 0x61, 0x72, 0x73, 0x65, 0x45, 0x6e, 0x64, - 0x44, 0x65, 0x76, 0x69, 0x63, 0x65, 0x51, 0x52, 0x43, 0x6f, 0x64, 0x65, 0x52, 0x65, 0x73, 0x70, - 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x1b, 0x0a, 0x09, 0x66, 0x6f, 0x72, 0x6d, 0x61, 0x74, 0x5f, 0x69, - 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x08, 0x66, 0x6f, 0x72, 0x6d, 0x61, 0x74, 0x49, - 0x64, 0x12, 0x51, 0x0a, 0x13, 0x65, 0x6e, 0x64, 0x5f, 0x64, 0x65, 0x76, 0x69, 0x63, 0x65, 0x5f, - 0x74, 0x65, 0x6d, 0x70, 0x6c, 0x61, 0x74, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x21, + 0x24, 0x52, 0x08, 0x66, 0x6f, 0x72, 0x6d, 0x61, 0x74, 0x49, 0x64, 0x12, 0x42, 0x0a, 0x0a, 0x65, + 0x6e, 0x64, 0x5f, 0x64, 0x65, 0x76, 0x69, 0x63, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, + 0x19, 0x2e, 0x74, 0x74, 0x6e, 0x2e, 0x6c, 0x6f, 0x72, 0x61, 0x77, 0x61, 0x6e, 0x2e, 0x76, 0x33, + 0x2e, 0x45, 0x6e, 0x64, 0x44, 0x65, 0x76, 0x69, 0x63, 0x65, 0x42, 0x08, 0xfa, 0x42, 0x05, 0x8a, + 0x01, 0x02, 0x10, 0x01, 0x52, 0x09, 0x65, 0x6e, 0x64, 0x44, 0x65, 0x76, 0x69, 0x63, 0x65, 0x12, + 0x4a, 0x0a, 0x05, 0x69, 0x6d, 0x61, 0x67, 0x65, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x34, 0x2e, 0x74, 0x74, 0x6e, 0x2e, 0x6c, 0x6f, 0x72, 0x61, 0x77, 0x61, 0x6e, 0x2e, 0x76, 0x33, 0x2e, - 0x45, 0x6e, 0x64, 0x44, 0x65, 0x76, 0x69, 0x63, 0x65, 0x54, 0x65, 0x6d, 0x70, 0x6c, 0x61, 0x74, - 0x65, 0x52, 0x11, 0x65, 0x6e, 0x64, 0x44, 0x65, 0x76, 0x69, 0x63, 0x65, 0x54, 0x65, 0x6d, 0x70, - 0x6c, 0x61, 0x74, 0x65, 0x22, 0x89, 0x01, 0x0a, 0x19, 0x50, 0x61, 0x72, 0x73, 0x65, 0x47, 0x61, - 0x74, 0x65, 0x77, 0x61, 0x79, 0x51, 0x52, 0x43, 0x6f, 0x64, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, - 0x73, 0x74, 0x12, 0x47, 0x0a, 0x09, 0x66, 0x6f, 0x72, 0x6d, 0x61, 0x74, 0x5f, 0x69, 0x64, 0x18, - 0x01, 0x20, 0x01, 0x28, 0x09, 0x42, 0x2a, 0xfa, 0x42, 0x27, 0x72, 0x25, 0x18, 0x24, 0x32, 0x21, - 0x5e, 0x5b, 0x61, 0x2d, 0x7a, 0x30, 0x2d, 0x39, 0x5d, 0x28, 0x3f, 0x3a, 0x5b, 0x2d, 0x5d, 0x3f, - 0x5b, 0x61, 0x2d, 0x7a, 0x30, 0x2d, 0x39, 0x5d, 0x29, 0x7b, 0x32, 0x2c, 0x7d, 0x24, 0x7c, 0x5e, - 0x24, 0x52, 0x08, 0x66, 0x6f, 0x72, 0x6d, 0x61, 0x74, 0x49, 0x64, 0x12, 0x23, 0x0a, 0x07, 0x71, - 0x72, 0x5f, 0x63, 0x6f, 0x64, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0c, 0x42, 0x0a, 0xfa, 0x42, - 0x07, 0x7a, 0x05, 0x10, 0x0a, 0x18, 0x80, 0x08, 0x52, 0x06, 0x71, 0x72, 0x43, 0x6f, 0x64, 0x65, - 0x22, 0x92, 0x01, 0x0a, 0x1a, 0x50, 0x61, 0x72, 0x73, 0x65, 0x47, 0x61, 0x74, 0x65, 0x77, 0x61, - 0x79, 0x51, 0x52, 0x43, 0x6f, 0x64, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, - 0x1b, 0x0a, 0x09, 0x66, 0x6f, 0x72, 0x6d, 0x61, 0x74, 0x5f, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, - 0x28, 0x09, 0x52, 0x08, 0x66, 0x6f, 0x72, 0x6d, 0x61, 0x74, 0x49, 0x64, 0x12, 0x57, 0x0a, 0x15, - 0x63, 0x6c, 0x61, 0x69, 0x6d, 0x5f, 0x67, 0x61, 0x74, 0x65, 0x77, 0x61, 0x79, 0x5f, 0x72, 0x65, - 0x71, 0x75, 0x65, 0x73, 0x74, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x23, 0x2e, 0x74, 0x74, - 0x6e, 0x2e, 0x6c, 0x6f, 0x72, 0x61, 0x77, 0x61, 0x6e, 0x2e, 0x76, 0x33, 0x2e, 0x43, 0x6c, 0x61, - 0x69, 0x6d, 0x47, 0x61, 0x74, 0x65, 0x77, 0x61, 0x79, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, - 0x52, 0x13, 0x63, 0x6c, 0x61, 0x69, 0x6d, 0x47, 0x61, 0x74, 0x65, 0x77, 0x61, 0x79, 0x52, 0x65, - 0x71, 0x75, 0x65, 0x73, 0x74, 0x32, 0xfe, 0x04, 0x0a, 0x18, 0x45, 0x6e, 0x64, 0x44, 0x65, 0x76, - 0x69, 0x63, 0x65, 0x51, 0x52, 0x43, 0x6f, 0x64, 0x65, 0x47, 0x65, 0x6e, 0x65, 0x72, 0x61, 0x74, - 0x6f, 0x72, 0x12, 0x84, 0x01, 0x0a, 0x09, 0x47, 0x65, 0x74, 0x46, 0x6f, 0x72, 0x6d, 0x61, 0x74, - 0x12, 0x26, 0x2e, 0x74, 0x74, 0x6e, 0x2e, 0x6c, 0x6f, 0x72, 0x61, 0x77, 0x61, 0x6e, 0x2e, 0x76, - 0x33, 0x2e, 0x47, 0x65, 0x74, 0x51, 0x52, 0x43, 0x6f, 0x64, 0x65, 0x46, 0x6f, 0x72, 0x6d, 0x61, - 0x74, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x1c, 0x2e, 0x74, 0x74, 0x6e, 0x2e, 0x6c, - 0x6f, 0x72, 0x61, 0x77, 0x61, 0x6e, 0x2e, 0x76, 0x33, 0x2e, 0x51, 0x52, 0x43, 0x6f, 0x64, 0x65, - 0x46, 0x6f, 0x72, 0x6d, 0x61, 0x74, 0x22, 0x31, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x2b, 0x12, 0x29, - 0x2f, 0x71, 0x72, 0x2d, 0x63, 0x6f, 0x64, 0x65, 0x73, 0x2f, 0x65, 0x6e, 0x64, 0x2d, 0x64, 0x65, - 0x76, 0x69, 0x63, 0x65, 0x73, 0x2f, 0x66, 0x6f, 0x72, 0x6d, 0x61, 0x74, 0x73, 0x2f, 0x7b, 0x66, - 0x6f, 0x72, 0x6d, 0x61, 0x74, 0x5f, 0x69, 0x64, 0x7d, 0x12, 0x6b, 0x0a, 0x0b, 0x4c, 0x69, 0x73, - 0x74, 0x46, 0x6f, 0x72, 0x6d, 0x61, 0x74, 0x73, 0x12, 0x16, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, - 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x45, 0x6d, 0x70, 0x74, 0x79, - 0x1a, 0x1d, 0x2e, 0x74, 0x74, 0x6e, 0x2e, 0x6c, 0x6f, 0x72, 0x61, 0x77, 0x61, 0x6e, 0x2e, 0x76, - 0x33, 0x2e, 0x51, 0x52, 0x43, 0x6f, 0x64, 0x65, 0x46, 0x6f, 0x72, 0x6d, 0x61, 0x74, 0x73, 0x22, - 0x25, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x1f, 0x12, 0x1d, 0x2f, 0x71, 0x72, 0x2d, 0x63, 0x6f, 0x64, - 0x65, 0x73, 0x2f, 0x65, 0x6e, 0x64, 0x2d, 0x64, 0x65, 0x76, 0x69, 0x63, 0x65, 0x73, 0x2f, 0x66, - 0x6f, 0x72, 0x6d, 0x61, 0x74, 0x73, 0x12, 0x84, 0x01, 0x0a, 0x08, 0x47, 0x65, 0x6e, 0x65, 0x72, - 0x61, 0x74, 0x65, 0x12, 0x2e, 0x2e, 0x74, 0x74, 0x6e, 0x2e, 0x6c, 0x6f, 0x72, 0x61, 0x77, 0x61, - 0x6e, 0x2e, 0x76, 0x33, 0x2e, 0x47, 0x65, 0x6e, 0x65, 0x72, 0x61, 0x74, 0x65, 0x45, 0x6e, 0x64, - 0x44, 0x65, 0x76, 0x69, 0x63, 0x65, 0x51, 0x52, 0x43, 0x6f, 0x64, 0x65, 0x52, 0x65, 0x71, 0x75, - 0x65, 0x73, 0x74, 0x1a, 0x26, 0x2e, 0x74, 0x74, 0x6e, 0x2e, 0x6c, 0x6f, 0x72, 0x61, 0x77, 0x61, - 0x6e, 0x2e, 0x76, 0x33, 0x2e, 0x47, 0x65, 0x6e, 0x65, 0x72, 0x61, 0x74, 0x65, 0x51, 0x52, 0x43, - 0x6f, 0x64, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x20, 0x82, 0xd3, 0xe4, - 0x93, 0x02, 0x1a, 0x3a, 0x01, 0x2a, 0x22, 0x15, 0x2f, 0x71, 0x72, 0x2d, 0x63, 0x6f, 0x64, 0x65, - 0x73, 0x2f, 0x65, 0x6e, 0x64, 0x2d, 0x64, 0x65, 0x76, 0x69, 0x63, 0x65, 0x73, 0x12, 0xb8, 0x01, - 0x0a, 0x05, 0x50, 0x61, 0x72, 0x73, 0x65, 0x12, 0x2b, 0x2e, 0x74, 0x74, 0x6e, 0x2e, 0x6c, 0x6f, - 0x72, 0x61, 0x77, 0x61, 0x6e, 0x2e, 0x76, 0x33, 0x2e, 0x50, 0x61, 0x72, 0x73, 0x65, 0x45, 0x6e, + 0x47, 0x65, 0x6e, 0x65, 0x72, 0x61, 0x74, 0x65, 0x45, 0x6e, 0x64, 0x44, 0x65, 0x76, 0x69, 0x63, + 0x65, 0x51, 0x52, 0x43, 0x6f, 0x64, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x2e, 0x49, + 0x6d, 0x61, 0x67, 0x65, 0x52, 0x05, 0x69, 0x6d, 0x61, 0x67, 0x65, 0x1a, 0x32, 0x0a, 0x05, 0x49, + 0x6d, 0x61, 0x67, 0x65, 0x12, 0x29, 0x0a, 0x0a, 0x69, 0x6d, 0x61, 0x67, 0x65, 0x5f, 0x73, 0x69, + 0x7a, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0d, 0x42, 0x0a, 0xfa, 0x42, 0x07, 0x2a, 0x05, 0x18, + 0xe8, 0x07, 0x28, 0x0a, 0x52, 0x09, 0x69, 0x6d, 0x61, 0x67, 0x65, 0x53, 0x69, 0x7a, 0x65, 0x22, + 0x5b, 0x0a, 0x16, 0x47, 0x65, 0x6e, 0x65, 0x72, 0x61, 0x74, 0x65, 0x51, 0x52, 0x43, 0x6f, 0x64, + 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x12, 0x0a, 0x04, 0x74, 0x65, 0x78, + 0x74, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x74, 0x65, 0x78, 0x74, 0x12, 0x2d, 0x0a, + 0x05, 0x69, 0x6d, 0x61, 0x67, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x17, 0x2e, 0x74, + 0x74, 0x6e, 0x2e, 0x6c, 0x6f, 0x72, 0x61, 0x77, 0x61, 0x6e, 0x2e, 0x76, 0x33, 0x2e, 0x50, 0x69, + 0x63, 0x74, 0x75, 0x72, 0x65, 0x52, 0x05, 0x69, 0x6d, 0x61, 0x67, 0x65, 0x22, 0x8b, 0x01, 0x0a, + 0x1b, 0x50, 0x61, 0x72, 0x73, 0x65, 0x45, 0x6e, 0x64, 0x44, 0x65, 0x76, 0x69, 0x63, 0x65, 0x51, + 0x52, 0x43, 0x6f, 0x64, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x47, 0x0a, 0x09, + 0x66, 0x6f, 0x72, 0x6d, 0x61, 0x74, 0x5f, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x42, + 0x2a, 0xfa, 0x42, 0x27, 0x72, 0x25, 0x18, 0x24, 0x32, 0x21, 0x5e, 0x5b, 0x61, 0x2d, 0x7a, 0x30, + 0x2d, 0x39, 0x5d, 0x28, 0x3f, 0x3a, 0x5b, 0x2d, 0x5d, 0x3f, 0x5b, 0x61, 0x2d, 0x7a, 0x30, 0x2d, + 0x39, 0x5d, 0x29, 0x7b, 0x32, 0x2c, 0x7d, 0x24, 0x7c, 0x5e, 0x24, 0x52, 0x08, 0x66, 0x6f, 0x72, + 0x6d, 0x61, 0x74, 0x49, 0x64, 0x12, 0x23, 0x0a, 0x07, 0x71, 0x72, 0x5f, 0x63, 0x6f, 0x64, 0x65, + 0x18, 0x02, 0x20, 0x01, 0x28, 0x0c, 0x42, 0x0a, 0xfa, 0x42, 0x07, 0x7a, 0x05, 0x10, 0x0a, 0x18, + 0x80, 0x08, 0x52, 0x06, 0x71, 0x72, 0x43, 0x6f, 0x64, 0x65, 0x22, 0x8e, 0x01, 0x0a, 0x1c, 0x50, + 0x61, 0x72, 0x73, 0x65, 0x45, 0x6e, 0x64, 0x44, 0x65, 0x76, 0x69, 0x63, 0x65, 0x51, 0x52, 0x43, + 0x6f, 0x64, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x1b, 0x0a, 0x09, 0x66, + 0x6f, 0x72, 0x6d, 0x61, 0x74, 0x5f, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x08, + 0x66, 0x6f, 0x72, 0x6d, 0x61, 0x74, 0x49, 0x64, 0x12, 0x51, 0x0a, 0x13, 0x65, 0x6e, 0x64, 0x5f, + 0x64, 0x65, 0x76, 0x69, 0x63, 0x65, 0x5f, 0x74, 0x65, 0x6d, 0x70, 0x6c, 0x61, 0x74, 0x65, 0x18, + 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x21, 0x2e, 0x74, 0x74, 0x6e, 0x2e, 0x6c, 0x6f, 0x72, 0x61, + 0x77, 0x61, 0x6e, 0x2e, 0x76, 0x33, 0x2e, 0x45, 0x6e, 0x64, 0x44, 0x65, 0x76, 0x69, 0x63, 0x65, + 0x54, 0x65, 0x6d, 0x70, 0x6c, 0x61, 0x74, 0x65, 0x52, 0x11, 0x65, 0x6e, 0x64, 0x44, 0x65, 0x76, + 0x69, 0x63, 0x65, 0x54, 0x65, 0x6d, 0x70, 0x6c, 0x61, 0x74, 0x65, 0x22, 0x89, 0x01, 0x0a, 0x19, + 0x50, 0x61, 0x72, 0x73, 0x65, 0x47, 0x61, 0x74, 0x65, 0x77, 0x61, 0x79, 0x51, 0x52, 0x43, 0x6f, + 0x64, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x47, 0x0a, 0x09, 0x66, 0x6f, 0x72, + 0x6d, 0x61, 0x74, 0x5f, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x42, 0x2a, 0xfa, 0x42, + 0x27, 0x72, 0x25, 0x18, 0x24, 0x32, 0x21, 0x5e, 0x5b, 0x61, 0x2d, 0x7a, 0x30, 0x2d, 0x39, 0x5d, + 0x28, 0x3f, 0x3a, 0x5b, 0x2d, 0x5d, 0x3f, 0x5b, 0x61, 0x2d, 0x7a, 0x30, 0x2d, 0x39, 0x5d, 0x29, + 0x7b, 0x32, 0x2c, 0x7d, 0x24, 0x7c, 0x5e, 0x24, 0x52, 0x08, 0x66, 0x6f, 0x72, 0x6d, 0x61, 0x74, + 0x49, 0x64, 0x12, 0x23, 0x0a, 0x07, 0x71, 0x72, 0x5f, 0x63, 0x6f, 0x64, 0x65, 0x18, 0x02, 0x20, + 0x01, 0x28, 0x0c, 0x42, 0x0a, 0xfa, 0x42, 0x07, 0x7a, 0x05, 0x10, 0x0a, 0x18, 0x80, 0x08, 0x52, + 0x06, 0x71, 0x72, 0x43, 0x6f, 0x64, 0x65, 0x22, 0xcc, 0x02, 0x0a, 0x1a, 0x50, 0x61, 0x72, 0x73, + 0x65, 0x47, 0x61, 0x74, 0x65, 0x77, 0x61, 0x79, 0x51, 0x52, 0x43, 0x6f, 0x64, 0x65, 0x52, 0x65, + 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x1b, 0x0a, 0x09, 0x66, 0x6f, 0x72, 0x6d, 0x61, 0x74, + 0x5f, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x08, 0x66, 0x6f, 0x72, 0x6d, 0x61, + 0x74, 0x49, 0x64, 0x12, 0xd6, 0x01, 0x0a, 0x0b, 0x67, 0x61, 0x74, 0x65, 0x77, 0x61, 0x79, 0x5f, + 0x65, 0x75, 0x69, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0c, 0x42, 0xb4, 0x01, 0x92, 0x41, 0x21, 0x4a, + 0x12, 0x22, 0x37, 0x30, 0x42, 0x33, 0x44, 0x35, 0x37, 0x45, 0x44, 0x30, 0x30, 0x30, 0x41, 0x42, + 0x43, 0x44, 0x22, 0x9a, 0x02, 0x01, 0x07, 0xa2, 0x02, 0x06, 0x73, 0x74, 0x72, 0x69, 0x6e, 0x67, + 0xfa, 0x42, 0x06, 0x7a, 0x04, 0x68, 0x08, 0x70, 0x01, 0xea, 0xaa, 0x19, 0x82, 0x01, 0x0a, 0x3f, + 0x67, 0x6f, 0x2e, 0x74, 0x68, 0x65, 0x74, 0x68, 0x69, 0x6e, 0x67, 0x73, 0x2e, 0x6e, 0x65, 0x74, + 0x77, 0x6f, 0x72, 0x6b, 0x2f, 0x6c, 0x6f, 0x72, 0x61, 0x77, 0x61, 0x6e, 0x2d, 0x73, 0x74, 0x61, + 0x63, 0x6b, 0x2f, 0x76, 0x33, 0x2f, 0x70, 0x6b, 0x67, 0x2f, 0x74, 0x79, 0x70, 0x65, 0x73, 0x2e, + 0x4d, 0x61, 0x72, 0x73, 0x68, 0x61, 0x6c, 0x48, 0x45, 0x58, 0x42, 0x79, 0x74, 0x65, 0x73, 0x12, + 0x3f, 0x67, 0x6f, 0x2e, 0x74, 0x68, 0x65, 0x74, 0x68, 0x69, 0x6e, 0x67, 0x73, 0x2e, 0x6e, 0x65, + 0x74, 0x77, 0x6f, 0x72, 0x6b, 0x2f, 0x6c, 0x6f, 0x72, 0x61, 0x77, 0x61, 0x6e, 0x2d, 0x73, 0x74, + 0x61, 0x63, 0x6b, 0x2f, 0x76, 0x33, 0x2f, 0x70, 0x6b, 0x67, 0x2f, 0x74, 0x79, 0x70, 0x65, 0x73, + 0x2e, 0x55, 0x6e, 0x6d, 0x61, 0x72, 0x73, 0x68, 0x61, 0x6c, 0x38, 0x42, 0x79, 0x74, 0x65, 0x73, + 0x52, 0x0a, 0x67, 0x61, 0x74, 0x65, 0x77, 0x61, 0x79, 0x45, 0x75, 0x69, 0x12, 0x38, 0x0a, 0x0b, + 0x6f, 0x77, 0x6e, 0x65, 0x72, 0x5f, 0x74, 0x6f, 0x6b, 0x65, 0x6e, 0x18, 0x03, 0x20, 0x01, 0x28, + 0x09, 0x42, 0x17, 0xfa, 0x42, 0x14, 0x72, 0x12, 0x32, 0x10, 0x5e, 0x5b, 0x41, 0x2d, 0x5a, 0x30, + 0x2d, 0x39, 0x5d, 0x7b, 0x31, 0x2c, 0x33, 0x32, 0x7d, 0x24, 0x52, 0x0a, 0x6f, 0x77, 0x6e, 0x65, + 0x72, 0x54, 0x6f, 0x6b, 0x65, 0x6e, 0x32, 0xfe, 0x04, 0x0a, 0x18, 0x45, 0x6e, 0x64, 0x44, 0x65, + 0x76, 0x69, 0x63, 0x65, 0x51, 0x52, 0x43, 0x6f, 0x64, 0x65, 0x47, 0x65, 0x6e, 0x65, 0x72, 0x61, + 0x74, 0x6f, 0x72, 0x12, 0x84, 0x01, 0x0a, 0x09, 0x47, 0x65, 0x74, 0x46, 0x6f, 0x72, 0x6d, 0x61, + 0x74, 0x12, 0x26, 0x2e, 0x74, 0x74, 0x6e, 0x2e, 0x6c, 0x6f, 0x72, 0x61, 0x77, 0x61, 0x6e, 0x2e, + 0x76, 0x33, 0x2e, 0x47, 0x65, 0x74, 0x51, 0x52, 0x43, 0x6f, 0x64, 0x65, 0x46, 0x6f, 0x72, 0x6d, + 0x61, 0x74, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x1c, 0x2e, 0x74, 0x74, 0x6e, 0x2e, + 0x6c, 0x6f, 0x72, 0x61, 0x77, 0x61, 0x6e, 0x2e, 0x76, 0x33, 0x2e, 0x51, 0x52, 0x43, 0x6f, 0x64, + 0x65, 0x46, 0x6f, 0x72, 0x6d, 0x61, 0x74, 0x22, 0x31, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x2b, 0x12, + 0x29, 0x2f, 0x71, 0x72, 0x2d, 0x63, 0x6f, 0x64, 0x65, 0x73, 0x2f, 0x65, 0x6e, 0x64, 0x2d, 0x64, + 0x65, 0x76, 0x69, 0x63, 0x65, 0x73, 0x2f, 0x66, 0x6f, 0x72, 0x6d, 0x61, 0x74, 0x73, 0x2f, 0x7b, + 0x66, 0x6f, 0x72, 0x6d, 0x61, 0x74, 0x5f, 0x69, 0x64, 0x7d, 0x12, 0x6b, 0x0a, 0x0b, 0x4c, 0x69, + 0x73, 0x74, 0x46, 0x6f, 0x72, 0x6d, 0x61, 0x74, 0x73, 0x12, 0x16, 0x2e, 0x67, 0x6f, 0x6f, 0x67, + 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x45, 0x6d, 0x70, 0x74, + 0x79, 0x1a, 0x1d, 0x2e, 0x74, 0x74, 0x6e, 0x2e, 0x6c, 0x6f, 0x72, 0x61, 0x77, 0x61, 0x6e, 0x2e, + 0x76, 0x33, 0x2e, 0x51, 0x52, 0x43, 0x6f, 0x64, 0x65, 0x46, 0x6f, 0x72, 0x6d, 0x61, 0x74, 0x73, + 0x22, 0x25, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x1f, 0x12, 0x1d, 0x2f, 0x71, 0x72, 0x2d, 0x63, 0x6f, + 0x64, 0x65, 0x73, 0x2f, 0x65, 0x6e, 0x64, 0x2d, 0x64, 0x65, 0x76, 0x69, 0x63, 0x65, 0x73, 0x2f, + 0x66, 0x6f, 0x72, 0x6d, 0x61, 0x74, 0x73, 0x12, 0x84, 0x01, 0x0a, 0x08, 0x47, 0x65, 0x6e, 0x65, + 0x72, 0x61, 0x74, 0x65, 0x12, 0x2e, 0x2e, 0x74, 0x74, 0x6e, 0x2e, 0x6c, 0x6f, 0x72, 0x61, 0x77, + 0x61, 0x6e, 0x2e, 0x76, 0x33, 0x2e, 0x47, 0x65, 0x6e, 0x65, 0x72, 0x61, 0x74, 0x65, 0x45, 0x6e, 0x64, 0x44, 0x65, 0x76, 0x69, 0x63, 0x65, 0x51, 0x52, 0x43, 0x6f, 0x64, 0x65, 0x52, 0x65, 0x71, - 0x75, 0x65, 0x73, 0x74, 0x1a, 0x2c, 0x2e, 0x74, 0x74, 0x6e, 0x2e, 0x6c, 0x6f, 0x72, 0x61, 0x77, - 0x61, 0x6e, 0x2e, 0x76, 0x33, 0x2e, 0x50, 0x61, 0x72, 0x73, 0x65, 0x45, 0x6e, 0x64, 0x44, 0x65, - 0x76, 0x69, 0x63, 0x65, 0x51, 0x52, 0x43, 0x6f, 0x64, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, - 0x73, 0x65, 0x22, 0x54, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x4e, 0x3a, 0x01, 0x2a, 0x5a, 0x2c, 0x3a, - 0x01, 0x2a, 0x22, 0x27, 0x2f, 0x71, 0x72, 0x2d, 0x63, 0x6f, 0x64, 0x65, 0x73, 0x2f, 0x65, 0x6e, - 0x64, 0x2d, 0x64, 0x65, 0x76, 0x69, 0x63, 0x65, 0x73, 0x2f, 0x7b, 0x66, 0x6f, 0x72, 0x6d, 0x61, - 0x74, 0x5f, 0x69, 0x64, 0x7d, 0x2f, 0x70, 0x61, 0x72, 0x73, 0x65, 0x22, 0x1b, 0x2f, 0x71, 0x72, - 0x2d, 0x63, 0x6f, 0x64, 0x65, 0x73, 0x2f, 0x65, 0x6e, 0x64, 0x2d, 0x64, 0x65, 0x76, 0x69, 0x63, - 0x65, 0x73, 0x2f, 0x70, 0x61, 0x72, 0x73, 0x65, 0x1a, 0x2c, 0x92, 0x41, 0x29, 0x12, 0x27, 0x47, - 0x65, 0x6e, 0x65, 0x72, 0x61, 0x74, 0x65, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x70, 0x61, 0x72, 0x73, - 0x65, 0x20, 0x65, 0x6e, 0x64, 0x20, 0x64, 0x65, 0x76, 0x69, 0x63, 0x65, 0x20, 0x51, 0x52, 0x20, - 0x63, 0x6f, 0x64, 0x65, 0x73, 0x2e, 0x32, 0xc9, 0x01, 0x0a, 0x16, 0x47, 0x61, 0x74, 0x65, 0x77, - 0x61, 0x79, 0x51, 0x52, 0x43, 0x6f, 0x64, 0x65, 0x47, 0x65, 0x6e, 0x65, 0x72, 0x61, 0x74, 0x6f, - 0x72, 0x12, 0xae, 0x01, 0x0a, 0x05, 0x50, 0x61, 0x72, 0x73, 0x65, 0x12, 0x29, 0x2e, 0x74, 0x74, - 0x6e, 0x2e, 0x6c, 0x6f, 0x72, 0x61, 0x77, 0x61, 0x6e, 0x2e, 0x76, 0x33, 0x2e, 0x50, 0x61, 0x72, - 0x73, 0x65, 0x47, 0x61, 0x74, 0x65, 0x77, 0x61, 0x79, 0x51, 0x52, 0x43, 0x6f, 0x64, 0x65, 0x52, - 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x2a, 0x2e, 0x74, 0x74, 0x6e, 0x2e, 0x6c, 0x6f, 0x72, - 0x61, 0x77, 0x61, 0x6e, 0x2e, 0x76, 0x33, 0x2e, 0x50, 0x61, 0x72, 0x73, 0x65, 0x47, 0x61, 0x74, - 0x65, 0x77, 0x61, 0x79, 0x51, 0x52, 0x43, 0x6f, 0x64, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, - 0x73, 0x65, 0x22, 0x4e, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x48, 0x3a, 0x01, 0x2a, 0x5a, 0x29, 0x3a, - 0x01, 0x2a, 0x22, 0x24, 0x2f, 0x71, 0x72, 0x2d, 0x63, 0x6f, 0x64, 0x65, 0x73, 0x2f, 0x67, 0x61, - 0x74, 0x65, 0x77, 0x61, 0x79, 0x73, 0x2f, 0x7b, 0x66, 0x6f, 0x72, 0x6d, 0x61, 0x74, 0x5f, 0x69, - 0x64, 0x7d, 0x2f, 0x70, 0x61, 0x72, 0x73, 0x65, 0x22, 0x18, 0x2f, 0x71, 0x72, 0x2d, 0x63, 0x6f, - 0x64, 0x65, 0x73, 0x2f, 0x67, 0x61, 0x74, 0x65, 0x77, 0x61, 0x79, 0x73, 0x2f, 0x70, 0x61, 0x72, - 0x73, 0x65, 0x42, 0x31, 0x5a, 0x2f, 0x67, 0x6f, 0x2e, 0x74, 0x68, 0x65, 0x74, 0x68, 0x69, 0x6e, - 0x67, 0x73, 0x2e, 0x6e, 0x65, 0x74, 0x77, 0x6f, 0x72, 0x6b, 0x2f, 0x6c, 0x6f, 0x72, 0x61, 0x77, - 0x61, 0x6e, 0x2d, 0x73, 0x74, 0x61, 0x63, 0x6b, 0x2f, 0x76, 0x33, 0x2f, 0x70, 0x6b, 0x67, 0x2f, - 0x74, 0x74, 0x6e, 0x70, 0x62, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33, + 0x75, 0x65, 0x73, 0x74, 0x1a, 0x26, 0x2e, 0x74, 0x74, 0x6e, 0x2e, 0x6c, 0x6f, 0x72, 0x61, 0x77, + 0x61, 0x6e, 0x2e, 0x76, 0x33, 0x2e, 0x47, 0x65, 0x6e, 0x65, 0x72, 0x61, 0x74, 0x65, 0x51, 0x52, + 0x43, 0x6f, 0x64, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x20, 0x82, 0xd3, + 0xe4, 0x93, 0x02, 0x1a, 0x3a, 0x01, 0x2a, 0x22, 0x15, 0x2f, 0x71, 0x72, 0x2d, 0x63, 0x6f, 0x64, + 0x65, 0x73, 0x2f, 0x65, 0x6e, 0x64, 0x2d, 0x64, 0x65, 0x76, 0x69, 0x63, 0x65, 0x73, 0x12, 0xb8, + 0x01, 0x0a, 0x05, 0x50, 0x61, 0x72, 0x73, 0x65, 0x12, 0x2b, 0x2e, 0x74, 0x74, 0x6e, 0x2e, 0x6c, + 0x6f, 0x72, 0x61, 0x77, 0x61, 0x6e, 0x2e, 0x76, 0x33, 0x2e, 0x50, 0x61, 0x72, 0x73, 0x65, 0x45, + 0x6e, 0x64, 0x44, 0x65, 0x76, 0x69, 0x63, 0x65, 0x51, 0x52, 0x43, 0x6f, 0x64, 0x65, 0x52, 0x65, + 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x2c, 0x2e, 0x74, 0x74, 0x6e, 0x2e, 0x6c, 0x6f, 0x72, 0x61, + 0x77, 0x61, 0x6e, 0x2e, 0x76, 0x33, 0x2e, 0x50, 0x61, 0x72, 0x73, 0x65, 0x45, 0x6e, 0x64, 0x44, + 0x65, 0x76, 0x69, 0x63, 0x65, 0x51, 0x52, 0x43, 0x6f, 0x64, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, + 0x6e, 0x73, 0x65, 0x22, 0x54, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x4e, 0x3a, 0x01, 0x2a, 0x5a, 0x2c, + 0x3a, 0x01, 0x2a, 0x22, 0x27, 0x2f, 0x71, 0x72, 0x2d, 0x63, 0x6f, 0x64, 0x65, 0x73, 0x2f, 0x65, + 0x6e, 0x64, 0x2d, 0x64, 0x65, 0x76, 0x69, 0x63, 0x65, 0x73, 0x2f, 0x7b, 0x66, 0x6f, 0x72, 0x6d, + 0x61, 0x74, 0x5f, 0x69, 0x64, 0x7d, 0x2f, 0x70, 0x61, 0x72, 0x73, 0x65, 0x22, 0x1b, 0x2f, 0x71, + 0x72, 0x2d, 0x63, 0x6f, 0x64, 0x65, 0x73, 0x2f, 0x65, 0x6e, 0x64, 0x2d, 0x64, 0x65, 0x76, 0x69, + 0x63, 0x65, 0x73, 0x2f, 0x70, 0x61, 0x72, 0x73, 0x65, 0x1a, 0x2c, 0x92, 0x41, 0x29, 0x12, 0x27, + 0x47, 0x65, 0x6e, 0x65, 0x72, 0x61, 0x74, 0x65, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x70, 0x61, 0x72, + 0x73, 0x65, 0x20, 0x65, 0x6e, 0x64, 0x20, 0x64, 0x65, 0x76, 0x69, 0x63, 0x65, 0x20, 0x51, 0x52, + 0x20, 0x63, 0x6f, 0x64, 0x65, 0x73, 0x2e, 0x32, 0xc9, 0x01, 0x0a, 0x16, 0x47, 0x61, 0x74, 0x65, + 0x77, 0x61, 0x79, 0x51, 0x52, 0x43, 0x6f, 0x64, 0x65, 0x47, 0x65, 0x6e, 0x65, 0x72, 0x61, 0x74, + 0x6f, 0x72, 0x12, 0xae, 0x01, 0x0a, 0x05, 0x50, 0x61, 0x72, 0x73, 0x65, 0x12, 0x29, 0x2e, 0x74, + 0x74, 0x6e, 0x2e, 0x6c, 0x6f, 0x72, 0x61, 0x77, 0x61, 0x6e, 0x2e, 0x76, 0x33, 0x2e, 0x50, 0x61, + 0x72, 0x73, 0x65, 0x47, 0x61, 0x74, 0x65, 0x77, 0x61, 0x79, 0x51, 0x52, 0x43, 0x6f, 0x64, 0x65, + 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x2a, 0x2e, 0x74, 0x74, 0x6e, 0x2e, 0x6c, 0x6f, + 0x72, 0x61, 0x77, 0x61, 0x6e, 0x2e, 0x76, 0x33, 0x2e, 0x50, 0x61, 0x72, 0x73, 0x65, 0x47, 0x61, + 0x74, 0x65, 0x77, 0x61, 0x79, 0x51, 0x52, 0x43, 0x6f, 0x64, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, + 0x6e, 0x73, 0x65, 0x22, 0x4e, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x48, 0x3a, 0x01, 0x2a, 0x5a, 0x29, + 0x3a, 0x01, 0x2a, 0x22, 0x24, 0x2f, 0x71, 0x72, 0x2d, 0x63, 0x6f, 0x64, 0x65, 0x73, 0x2f, 0x67, + 0x61, 0x74, 0x65, 0x77, 0x61, 0x79, 0x73, 0x2f, 0x7b, 0x66, 0x6f, 0x72, 0x6d, 0x61, 0x74, 0x5f, + 0x69, 0x64, 0x7d, 0x2f, 0x70, 0x61, 0x72, 0x73, 0x65, 0x22, 0x18, 0x2f, 0x71, 0x72, 0x2d, 0x63, + 0x6f, 0x64, 0x65, 0x73, 0x2f, 0x67, 0x61, 0x74, 0x65, 0x77, 0x61, 0x79, 0x73, 0x2f, 0x70, 0x61, + 0x72, 0x73, 0x65, 0x42, 0x31, 0x5a, 0x2f, 0x67, 0x6f, 0x2e, 0x74, 0x68, 0x65, 0x74, 0x68, 0x69, + 0x6e, 0x67, 0x73, 0x2e, 0x6e, 0x65, 0x74, 0x77, 0x6f, 0x72, 0x6b, 0x2f, 0x6c, 0x6f, 0x72, 0x61, + 0x77, 0x61, 0x6e, 0x2d, 0x73, 0x74, 0x61, 0x63, 0x6b, 0x2f, 0x76, 0x33, 0x2f, 0x70, 0x6b, 0x67, + 0x2f, 0x74, 0x74, 0x6e, 0x70, 0x62, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33, } var ( @@ -800,8 +820,7 @@ var file_ttn_lorawan_v3_qrcodegenerator_proto_goTypes = []interface{}{ (*EndDevice)(nil), // 12: ttn.lorawan.v3.EndDevice (*Picture)(nil), // 13: ttn.lorawan.v3.Picture (*EndDeviceTemplate)(nil), // 14: ttn.lorawan.v3.EndDeviceTemplate - (*ClaimGatewayRequest)(nil), // 15: ttn.lorawan.v3.ClaimGatewayRequest - (*emptypb.Empty)(nil), // 16: google.protobuf.Empty + (*emptypb.Empty)(nil), // 15: google.protobuf.Empty } var file_ttn_lorawan_v3_qrcodegenerator_proto_depIdxs = []int32{ 11, // 0: ttn.lorawan.v3.QRCodeFormat.field_mask:type_name -> google.protobuf.FieldMask @@ -810,23 +829,22 @@ var file_ttn_lorawan_v3_qrcodegenerator_proto_depIdxs = []int32{ 10, // 3: ttn.lorawan.v3.GenerateEndDeviceQRCodeRequest.image:type_name -> ttn.lorawan.v3.GenerateEndDeviceQRCodeRequest.Image 13, // 4: ttn.lorawan.v3.GenerateQRCodeResponse.image:type_name -> ttn.lorawan.v3.Picture 14, // 5: ttn.lorawan.v3.ParseEndDeviceQRCodeResponse.end_device_template:type_name -> ttn.lorawan.v3.EndDeviceTemplate - 15, // 6: ttn.lorawan.v3.ParseGatewayQRCodeResponse.claim_gateway_request:type_name -> ttn.lorawan.v3.ClaimGatewayRequest - 0, // 7: ttn.lorawan.v3.QRCodeFormats.FormatsEntry.value:type_name -> ttn.lorawan.v3.QRCodeFormat - 2, // 8: ttn.lorawan.v3.EndDeviceQRCodeGenerator.GetFormat:input_type -> ttn.lorawan.v3.GetQRCodeFormatRequest - 16, // 9: ttn.lorawan.v3.EndDeviceQRCodeGenerator.ListFormats:input_type -> google.protobuf.Empty - 3, // 10: ttn.lorawan.v3.EndDeviceQRCodeGenerator.Generate:input_type -> ttn.lorawan.v3.GenerateEndDeviceQRCodeRequest - 5, // 11: ttn.lorawan.v3.EndDeviceQRCodeGenerator.Parse:input_type -> ttn.lorawan.v3.ParseEndDeviceQRCodeRequest - 7, // 12: ttn.lorawan.v3.GatewayQRCodeGenerator.Parse:input_type -> ttn.lorawan.v3.ParseGatewayQRCodeRequest - 0, // 13: ttn.lorawan.v3.EndDeviceQRCodeGenerator.GetFormat:output_type -> ttn.lorawan.v3.QRCodeFormat - 1, // 14: ttn.lorawan.v3.EndDeviceQRCodeGenerator.ListFormats:output_type -> ttn.lorawan.v3.QRCodeFormats - 4, // 15: ttn.lorawan.v3.EndDeviceQRCodeGenerator.Generate:output_type -> ttn.lorawan.v3.GenerateQRCodeResponse - 6, // 16: ttn.lorawan.v3.EndDeviceQRCodeGenerator.Parse:output_type -> ttn.lorawan.v3.ParseEndDeviceQRCodeResponse - 8, // 17: ttn.lorawan.v3.GatewayQRCodeGenerator.Parse:output_type -> ttn.lorawan.v3.ParseGatewayQRCodeResponse - 13, // [13:18] is the sub-list for method output_type - 8, // [8:13] is the sub-list for method input_type - 8, // [8:8] is the sub-list for extension type_name - 8, // [8:8] is the sub-list for extension extendee - 0, // [0:8] is the sub-list for field type_name + 0, // 6: ttn.lorawan.v3.QRCodeFormats.FormatsEntry.value:type_name -> ttn.lorawan.v3.QRCodeFormat + 2, // 7: ttn.lorawan.v3.EndDeviceQRCodeGenerator.GetFormat:input_type -> ttn.lorawan.v3.GetQRCodeFormatRequest + 15, // 8: ttn.lorawan.v3.EndDeviceQRCodeGenerator.ListFormats:input_type -> google.protobuf.Empty + 3, // 9: ttn.lorawan.v3.EndDeviceQRCodeGenerator.Generate:input_type -> ttn.lorawan.v3.GenerateEndDeviceQRCodeRequest + 5, // 10: ttn.lorawan.v3.EndDeviceQRCodeGenerator.Parse:input_type -> ttn.lorawan.v3.ParseEndDeviceQRCodeRequest + 7, // 11: ttn.lorawan.v3.GatewayQRCodeGenerator.Parse:input_type -> ttn.lorawan.v3.ParseGatewayQRCodeRequest + 0, // 12: ttn.lorawan.v3.EndDeviceQRCodeGenerator.GetFormat:output_type -> ttn.lorawan.v3.QRCodeFormat + 1, // 13: ttn.lorawan.v3.EndDeviceQRCodeGenerator.ListFormats:output_type -> ttn.lorawan.v3.QRCodeFormats + 4, // 14: ttn.lorawan.v3.EndDeviceQRCodeGenerator.Generate:output_type -> ttn.lorawan.v3.GenerateQRCodeResponse + 6, // 15: ttn.lorawan.v3.EndDeviceQRCodeGenerator.Parse:output_type -> ttn.lorawan.v3.ParseEndDeviceQRCodeResponse + 8, // 16: ttn.lorawan.v3.GatewayQRCodeGenerator.Parse:output_type -> ttn.lorawan.v3.ParseGatewayQRCodeResponse + 12, // [12:17] is the sub-list for method output_type + 7, // [7:12] is the sub-list for method input_type + 7, // [7:7] is the sub-list for extension type_name + 7, // [7:7] is the sub-list for extension extendee + 0, // [0:7] is the sub-list for field type_name } func init() { file_ttn_lorawan_v3_qrcodegenerator_proto_init() } @@ -834,7 +852,6 @@ func file_ttn_lorawan_v3_qrcodegenerator_proto_init() { if File_ttn_lorawan_v3_qrcodegenerator_proto != nil { return } - file_ttn_lorawan_v3_deviceclaimingserver_proto_init() file_ttn_lorawan_v3_end_device_proto_init() file_ttn_lorawan_v3_picture_proto_init() if !protoimpl.UnsafeEnabled { diff --git a/pkg/ttnpb/qrcodegenerator.pb.paths.fm.go b/pkg/ttnpb/qrcodegenerator.pb.paths.fm.go index a96f377fd21..0c6cc9e100a 100644 --- a/pkg/ttnpb/qrcodegenerator.pb.paths.fm.go +++ b/pkg/ttnpb/qrcodegenerator.pb.paths.fm.go @@ -1589,38 +1589,15 @@ var ParseGatewayQRCodeRequestFieldPathsTopLevel = []string{ "qr_code", } var ParseGatewayQRCodeResponseFieldPathsNested = []string{ - "claim_gateway_request", - "claim_gateway_request.collaborator", - "claim_gateway_request.collaborator.ids", - "claim_gateway_request.collaborator.ids.organization_ids", - "claim_gateway_request.collaborator.ids.organization_ids.organization_id", - "claim_gateway_request.collaborator.ids.user_ids", - "claim_gateway_request.collaborator.ids.user_ids.email", - "claim_gateway_request.collaborator.ids.user_ids.user_id", - "claim_gateway_request.cups_redirection", - "claim_gateway_request.cups_redirection.current_gateway_key", - "claim_gateway_request.cups_redirection.gateway_credentials", - "claim_gateway_request.cups_redirection.gateway_credentials.auth_token", - "claim_gateway_request.cups_redirection.gateway_credentials.client_tls", - "claim_gateway_request.cups_redirection.gateway_credentials.client_tls.cert", - "claim_gateway_request.cups_redirection.gateway_credentials.client_tls.key", - "claim_gateway_request.cups_redirection.target_cups_trust", - "claim_gateway_request.cups_redirection.target_cups_uri", - "claim_gateway_request.source_gateway", - "claim_gateway_request.source_gateway.authenticated_identifiers", - "claim_gateway_request.source_gateway.authenticated_identifiers.authentication_code", - "claim_gateway_request.source_gateway.authenticated_identifiers.gateway_eui", - "claim_gateway_request.source_gateway.qr_code", - "claim_gateway_request.target_frequency_plan_id", - "claim_gateway_request.target_frequency_plan_ids", - "claim_gateway_request.target_gateway_id", - "claim_gateway_request.target_gateway_server_address", "format_id", + "gateway_eui", + "owner_token", } var ParseGatewayQRCodeResponseFieldPathsTopLevel = []string{ - "claim_gateway_request", "format_id", + "gateway_eui", + "owner_token", } var GenerateEndDeviceQRCodeRequest_ImageFieldPathsNested = []string{ "image_size", diff --git a/pkg/ttnpb/qrcodegenerator.pb.setters.fm.go b/pkg/ttnpb/qrcodegenerator.pb.setters.fm.go index 18b7cd41d7d..1e7032e28ee 100644 --- a/pkg/ttnpb/qrcodegenerator.pb.setters.fm.go +++ b/pkg/ttnpb/qrcodegenerator.pb.setters.fm.go @@ -321,30 +321,24 @@ func (dst *ParseGatewayQRCodeResponse) SetFields(src *ParseGatewayQRCodeResponse var zero string dst.FormatId = zero } - case "claim_gateway_request": + case "gateway_eui": if len(subs) > 0 { - var newDst, newSrc *ClaimGatewayRequest - if (src == nil || src.ClaimGatewayRequest == nil) && dst.ClaimGatewayRequest == nil { - continue - } - if src != nil { - newSrc = src.ClaimGatewayRequest - } - if dst.ClaimGatewayRequest != nil { - newDst = dst.ClaimGatewayRequest - } else { - newDst = &ClaimGatewayRequest{} - dst.ClaimGatewayRequest = newDst - } - if err := newDst.SetFields(newSrc, subs...); err != nil { - return err - } + return fmt.Errorf("'gateway_eui' has no subfields, but %s were specified", subs) + } + if src != nil { + dst.GatewayEui = src.GatewayEui } else { - if src != nil { - dst.ClaimGatewayRequest = src.ClaimGatewayRequest - } else { - dst.ClaimGatewayRequest = nil - } + dst.GatewayEui = nil + } + case "owner_token": + if len(subs) > 0 { + return fmt.Errorf("'owner_token' has no subfields, but %s were specified", subs) + } + if src != nil { + dst.OwnerToken = src.OwnerToken + } else { + var zero string + dst.OwnerToken = zero } default: diff --git a/pkg/ttnpb/qrcodegenerator.pb.validate.go b/pkg/ttnpb/qrcodegenerator.pb.validate.go index c1266592053..7961721bedd 100644 --- a/pkg/ttnpb/qrcodegenerator.pb.validate.go +++ b/pkg/ttnpb/qrcodegenerator.pb.validate.go @@ -909,16 +909,26 @@ func (m *ParseGatewayQRCodeResponse) ValidateFields(paths ...string) error { switch name { case "format_id": // no validation rules for FormatId - case "claim_gateway_request": + case "gateway_eui": - if v, ok := interface{}(m.GetClaimGatewayRequest()).(interface{ ValidateFields(...string) error }); ok { - if err := v.ValidateFields(subs...); err != nil { + if len(m.GetGatewayEui()) > 0 { + + if len(m.GetGatewayEui()) != 8 { return ParseGatewayQRCodeResponseValidationError{ - field: "claim_gateway_request", - reason: "embedded message failed validation", - cause: err, + field: "gateway_eui", + reason: "value length must be 8 bytes", } } + + } + + case "owner_token": + + if !_ParseGatewayQRCodeResponse_OwnerToken_Pattern.MatchString(m.GetOwnerToken()) { + return ParseGatewayQRCodeResponseValidationError{ + field: "owner_token", + reason: "value does not match regex pattern \"^[A-Z0-9]{1,32}$\"", + } } default: @@ -988,6 +998,8 @@ var _ interface { ErrorName() string } = ParseGatewayQRCodeResponseValidationError{} +var _ParseGatewayQRCodeResponse_OwnerToken_Pattern = regexp.MustCompile("^[A-Z0-9]{1,32}$") + // ValidateFields checks the field values on // GenerateEndDeviceQRCodeRequest_Image with the rules defined in the proto // definition for this message. If any rules are violated, an error is returned. diff --git a/pkg/ttnpb/qrcodegenerator_json.pb.go b/pkg/ttnpb/qrcodegenerator_json.pb.go index 9aabcda718c..56dd3ecb7c9 100644 --- a/pkg/ttnpb/qrcodegenerator_json.pb.go +++ b/pkg/ttnpb/qrcodegenerator_json.pb.go @@ -9,6 +9,7 @@ package ttnpb import ( golang "github.com/TheThingsIndustries/protoc-gen-go-json/golang" jsonplugin "github.com/TheThingsIndustries/protoc-gen-go-json/jsonplugin" + types "go.thethings.network/lorawan-stack/v3/pkg/types" ) // MarshalProtoJSON marshals the QRCodeFormat message to JSON. @@ -218,10 +219,15 @@ func (x *ParseGatewayQRCodeResponse) MarshalProtoJSON(s *jsonplugin.MarshalState s.WriteObjectField("format_id") s.WriteString(x.FormatId) } - if x.ClaimGatewayRequest != nil || s.HasField("claim_gateway_request") { + if len(x.GatewayEui) > 0 || s.HasField("gateway_eui") { s.WriteMoreIf(&wroteField) - s.WriteObjectField("claim_gateway_request") - x.ClaimGatewayRequest.MarshalProtoJSON(s.WithField("claim_gateway_request")) + s.WriteObjectField("gateway_eui") + types.MarshalHEXBytes(s.WithField("gateway_eui"), x.GatewayEui) + } + if x.OwnerToken != "" || s.HasField("owner_token") { + s.WriteMoreIf(&wroteField) + s.WriteObjectField("owner_token") + s.WriteString(x.OwnerToken) } s.WriteObjectEnd() } @@ -243,13 +249,12 @@ func (x *ParseGatewayQRCodeResponse) UnmarshalProtoJSON(s *jsonplugin.UnmarshalS case "format_id", "formatId": s.AddField("format_id") x.FormatId = s.ReadString() - case "claim_gateway_request", "claimGatewayRequest": - if s.ReadNil() { - x.ClaimGatewayRequest = nil - return - } - x.ClaimGatewayRequest = &ClaimGatewayRequest{} - x.ClaimGatewayRequest.UnmarshalProtoJSON(s.WithField("claim_gateway_request", true)) + case "gateway_eui", "gatewayEui": + s.AddField("gateway_eui") + x.GatewayEui = types.Unmarshal8Bytes(s.WithField("gateway_eui", false)) + case "owner_token", "ownerToken": + s.AddField("owner_token") + x.OwnerToken = s.ReadString() } }) } diff --git a/sdk/js/generated/api.json b/sdk/js/generated/api.json index 27637e36099..f777c02009d 100644 --- a/sdk/js/generated/api.json +++ b/sdk/js/generated/api.json @@ -48325,16 +48325,44 @@ "defaultValue": "" }, { - "name": "claim_gateway_request", + "name": "gateway_eui", "description": "", "label": "", - "type": "ClaimGatewayRequest", - "longType": "ClaimGatewayRequest", - "fullType": "ttn.lorawan.v3.ClaimGatewayRequest", + "type": "bytes", + "longType": "bytes", + "fullType": "bytes", "ismap": false, "isoneof": false, "oneofdecl": "", - "defaultValue": "" + "defaultValue": "", + "options": { + "validate.rules": [ + { + "name": "bytes.len", + "value": 8 + } + ] + } + }, + { + "name": "owner_token", + "description": "", + "label": "", + "type": "string", + "longType": "string", + "fullType": "string", + "ismap": false, + "isoneof": false, + "oneofdecl": "", + "defaultValue": "", + "options": { + "validate.rules": [ + { + "name": "string.pattern", + "value": "^[A-Z0-9]{1,32}$" + } + ] + } } ] },