Add option to increase RX1 Delay in device-profile.

In general ChirpStack is configured with a rx1_delay configuration
matching the network latency (e.g. on cellular, one might want to set
this to rx1_delay=3). However, this does not take into account a
possible latency of the end-application. Handling the uplink and
enqueueing a downlink might take more time than the configured rx1_delay
(and get_downlink_data_delay) allows.

This option makes it possible to increase the RX1 Delay in the
device-profile. If the RX1 Delay has between increased relative to
the system default, then the get_downlink_data_delay will be
incremented with the same amount of seconds.
This commit is contained in:
Orne Brocaar 2024-05-02 10:29:10 +01:00
parent a5ff416fa2
commit 487f785302
12 changed files with 655 additions and 329 deletions

View File

@ -544,6 +544,14 @@ type DeviceProfile struct {
// //
// If set to true, it means that the device is allowed to use roaming. // If set to true, it means that the device is allowed to use roaming.
AllowRoaming bool `protobuf:"varint,52,opt,name=allow_roaming,json=allowRoaming,proto3" json:"allow_roaming,omitempty"` AllowRoaming bool `protobuf:"varint,52,opt,name=allow_roaming,json=allowRoaming,proto3" json:"allow_roaming,omitempty"`
// RX1 Delay.
//
// This makes it possible to override the system RX1 Delay. Please note that
// this values only has effect in case it is higher than the system value.
// In other words, it can be used to increase the RX1 Delay but not to decrease
// it.
// Valid options are 1 - 15 (0 = always use system RX1 Delay).
Rx1Delay uint32 `protobuf:"varint,53,opt,name=rx1_delay,json=rx1Delay,proto3" json:"rx1_delay,omitempty"`
} }
func (x *DeviceProfile) Reset() { func (x *DeviceProfile) Reset() {
@ -942,6 +950,13 @@ func (x *DeviceProfile) GetAllowRoaming() bool {
return false return false
} }
func (x *DeviceProfile) GetRx1Delay() uint32 {
if x != nil {
return x.Rx1Delay
}
return 0
}
type Measurement struct { type Measurement struct {
state protoimpl.MessageState state protoimpl.MessageState
sizeCache protoimpl.SizeCache sizeCache protoimpl.SizeCache
@ -1692,7 +1707,7 @@ var file_api_device_profile_proto_rawDesc = []byte{
0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2f, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2f, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2f, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2f,
0x65, 0x6d, 0x70, 0x74, 0x79, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x1a, 0x13, 0x63, 0x6f, 0x6d, 0x65, 0x6d, 0x70, 0x74, 0x79, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x1a, 0x13, 0x63, 0x6f, 0x6d,
0x6d, 0x6f, 0x6e, 0x2f, 0x63, 0x6f, 0x6d, 0x6d, 0x6f, 0x6e, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x6d, 0x6f, 0x6e, 0x2f, 0x63, 0x6f, 0x6d, 0x6d, 0x6f, 0x6e, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f,
0x22, 0xd3, 0x16, 0x0a, 0x0d, 0x44, 0x65, 0x76, 0x69, 0x63, 0x65, 0x50, 0x72, 0x6f, 0x66, 0x69, 0x22, 0xf0, 0x16, 0x0a, 0x0d, 0x44, 0x65, 0x76, 0x69, 0x63, 0x65, 0x50, 0x72, 0x6f, 0x66, 0x69,
0x6c, 0x65, 0x12, 0x0e, 0x0a, 0x02, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x02, 0x6c, 0x65, 0x12, 0x0e, 0x0a, 0x02, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x02,
0x69, 0x64, 0x12, 0x1b, 0x0a, 0x09, 0x74, 0x65, 0x6e, 0x61, 0x6e, 0x74, 0x5f, 0x69, 0x64, 0x18, 0x69, 0x64, 0x12, 0x1b, 0x0a, 0x09, 0x74, 0x65, 0x6e, 0x61, 0x6e, 0x74, 0x5f, 0x69, 0x64, 0x18,
0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x08, 0x74, 0x65, 0x6e, 0x61, 0x6e, 0x74, 0x49, 0x64, 0x12, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x08, 0x74, 0x65, 0x6e, 0x61, 0x6e, 0x74, 0x49, 0x64, 0x12,
@ -1864,187 +1879,189 @@ var file_api_device_profile_proto_rawDesc = []byte{
0x76, 0x65, 0x72, 0x61, 0x6c, 0x6c, 0x4c, 0x69, 0x6d, 0x69, 0x74, 0x42, 0x75, 0x63, 0x6b, 0x65, 0x76, 0x65, 0x72, 0x61, 0x6c, 0x6c, 0x4c, 0x69, 0x6d, 0x69, 0x74, 0x42, 0x75, 0x63, 0x6b, 0x65,
0x74, 0x53, 0x69, 0x7a, 0x65, 0x12, 0x23, 0x0a, 0x0d, 0x61, 0x6c, 0x6c, 0x6f, 0x77, 0x5f, 0x72, 0x74, 0x53, 0x69, 0x7a, 0x65, 0x12, 0x23, 0x0a, 0x0d, 0x61, 0x6c, 0x6c, 0x6f, 0x77, 0x5f, 0x72,
0x6f, 0x61, 0x6d, 0x69, 0x6e, 0x67, 0x18, 0x34, 0x20, 0x01, 0x28, 0x08, 0x52, 0x0c, 0x61, 0x6c, 0x6f, 0x61, 0x6d, 0x69, 0x6e, 0x67, 0x18, 0x34, 0x20, 0x01, 0x28, 0x08, 0x52, 0x0c, 0x61, 0x6c,
0x6c, 0x6f, 0x77, 0x52, 0x6f, 0x61, 0x6d, 0x69, 0x6e, 0x67, 0x1a, 0x37, 0x0a, 0x09, 0x54, 0x61, 0x6c, 0x6f, 0x77, 0x52, 0x6f, 0x61, 0x6d, 0x69, 0x6e, 0x67, 0x12, 0x1b, 0x0a, 0x09, 0x72, 0x78,
0x67, 0x73, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x12, 0x10, 0x0a, 0x03, 0x6b, 0x65, 0x79, 0x18, 0x01, 0x31, 0x5f, 0x64, 0x65, 0x6c, 0x61, 0x79, 0x18, 0x35, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x08, 0x72,
0x20, 0x01, 0x28, 0x09, 0x52, 0x03, 0x6b, 0x65, 0x79, 0x12, 0x14, 0x0a, 0x05, 0x76, 0x61, 0x6c, 0x78, 0x31, 0x44, 0x65, 0x6c, 0x61, 0x79, 0x1a, 0x37, 0x0a, 0x09, 0x54, 0x61, 0x67, 0x73, 0x45,
0x75, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x3a, 0x6e, 0x74, 0x72, 0x79, 0x12, 0x10, 0x0a, 0x03, 0x6b, 0x65, 0x79, 0x18, 0x01, 0x20, 0x01, 0x28,
0x02, 0x38, 0x01, 0x1a, 0x51, 0x0a, 0x11, 0x4d, 0x65, 0x61, 0x73, 0x75, 0x72, 0x65, 0x6d, 0x65, 0x09, 0x52, 0x03, 0x6b, 0x65, 0x79, 0x12, 0x14, 0x0a, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18,
0x6e, 0x74, 0x73, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x12, 0x10, 0x0a, 0x03, 0x6b, 0x65, 0x79, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x3a, 0x02, 0x38, 0x01,
0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x03, 0x6b, 0x65, 0x79, 0x12, 0x26, 0x0a, 0x05, 0x76, 0x61, 0x1a, 0x51, 0x0a, 0x11, 0x4d, 0x65, 0x61, 0x73, 0x75, 0x72, 0x65, 0x6d, 0x65, 0x6e, 0x74, 0x73,
0x6c, 0x75, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x10, 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x12, 0x10, 0x0a, 0x03, 0x6b, 0x65, 0x79, 0x18, 0x01, 0x20, 0x01,
0x4d, 0x65, 0x61, 0x73, 0x75, 0x72, 0x65, 0x6d, 0x65, 0x6e, 0x74, 0x52, 0x05, 0x76, 0x61, 0x6c, 0x28, 0x09, 0x52, 0x03, 0x6b, 0x65, 0x79, 0x12, 0x26, 0x0a, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65,
0x75, 0x65, 0x3a, 0x02, 0x38, 0x01, 0x22, 0x4b, 0x0a, 0x0b, 0x4d, 0x65, 0x61, 0x73, 0x75, 0x72, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x10, 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x4d, 0x65, 0x61,
0x65, 0x6d, 0x65, 0x6e, 0x74, 0x12, 0x12, 0x0a, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x02, 0x20, 0x73, 0x75, 0x72, 0x65, 0x6d, 0x65, 0x6e, 0x74, 0x52, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x3a,
0x01, 0x28, 0x09, 0x52, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x12, 0x28, 0x0a, 0x04, 0x6b, 0x69, 0x6e, 0x02, 0x38, 0x01, 0x22, 0x4b, 0x0a, 0x0b, 0x4d, 0x65, 0x61, 0x73, 0x75, 0x72, 0x65, 0x6d, 0x65,
0x64, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x14, 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x4d, 0x65, 0x6e, 0x74, 0x12, 0x12, 0x0a, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09,
0x61, 0x73, 0x75, 0x72, 0x65, 0x6d, 0x65, 0x6e, 0x74, 0x4b, 0x69, 0x6e, 0x64, 0x52, 0x04, 0x6b, 0x52, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x12, 0x28, 0x0a, 0x04, 0x6b, 0x69, 0x6e, 0x64, 0x18, 0x03,
0x69, 0x6e, 0x64, 0x22, 0xd2, 0x03, 0x0a, 0x15, 0x44, 0x65, 0x76, 0x69, 0x63, 0x65, 0x50, 0x72, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x14, 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x4d, 0x65, 0x61, 0x73, 0x75,
0x6f, 0x66, 0x69, 0x6c, 0x65, 0x4c, 0x69, 0x73, 0x74, 0x49, 0x74, 0x65, 0x6d, 0x12, 0x0e, 0x0a, 0x72, 0x65, 0x6d, 0x65, 0x6e, 0x74, 0x4b, 0x69, 0x6e, 0x64, 0x52, 0x04, 0x6b, 0x69, 0x6e, 0x64,
0x02, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x02, 0x69, 0x64, 0x12, 0x39, 0x0a, 0x22, 0xd2, 0x03, 0x0a, 0x15, 0x44, 0x65, 0x76, 0x69, 0x63, 0x65, 0x50, 0x72, 0x6f, 0x66, 0x69,
0x0a, 0x63, 0x72, 0x65, 0x61, 0x74, 0x65, 0x64, 0x5f, 0x61, 0x74, 0x18, 0x02, 0x20, 0x01, 0x28, 0x6c, 0x65, 0x4c, 0x69, 0x73, 0x74, 0x49, 0x74, 0x65, 0x6d, 0x12, 0x0e, 0x0a, 0x02, 0x69, 0x64,
0x0b, 0x32, 0x1a, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x02, 0x69, 0x64, 0x12, 0x39, 0x0a, 0x0a, 0x63, 0x72,
0x62, 0x75, 0x66, 0x2e, 0x54, 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, 0x52, 0x09, 0x63, 0x65, 0x61, 0x74, 0x65, 0x64, 0x5f, 0x61, 0x74, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1a,
0x72, 0x65, 0x61, 0x74, 0x65, 0x64, 0x41, 0x74, 0x12, 0x39, 0x0a, 0x0a, 0x75, 0x70, 0x64, 0x61, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66,
0x74, 0x65, 0x64, 0x5f, 0x61, 0x74, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1a, 0x2e, 0x67, 0x2e, 0x54, 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, 0x52, 0x09, 0x63, 0x72, 0x65, 0x61,
0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x54, 0x74, 0x65, 0x64, 0x41, 0x74, 0x12, 0x39, 0x0a, 0x0a, 0x75, 0x70, 0x64, 0x61, 0x74, 0x65, 0x64,
0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, 0x52, 0x09, 0x75, 0x70, 0x64, 0x61, 0x74, 0x65, 0x5f, 0x61, 0x74, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1a, 0x2e, 0x67, 0x6f, 0x6f, 0x67,
0x64, 0x41, 0x74, 0x12, 0x12, 0x0a, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x04, 0x20, 0x01, 0x28, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x54, 0x69, 0x6d, 0x65,
0x09, 0x52, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x12, 0x26, 0x0a, 0x06, 0x72, 0x65, 0x67, 0x69, 0x6f, 0x73, 0x74, 0x61, 0x6d, 0x70, 0x52, 0x09, 0x75, 0x70, 0x64, 0x61, 0x74, 0x65, 0x64, 0x41, 0x74,
0x6e, 0x18, 0x05, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x0e, 0x2e, 0x63, 0x6f, 0x6d, 0x6d, 0x6f, 0x6e, 0x12, 0x12, 0x0a, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x04, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04,
0x2e, 0x52, 0x65, 0x67, 0x69, 0x6f, 0x6e, 0x52, 0x06, 0x72, 0x65, 0x67, 0x69, 0x6f, 0x6e, 0x12, 0x6e, 0x61, 0x6d, 0x65, 0x12, 0x26, 0x0a, 0x06, 0x72, 0x65, 0x67, 0x69, 0x6f, 0x6e, 0x18, 0x05,
0x33, 0x0a, 0x0b, 0x6d, 0x61, 0x63, 0x5f, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x18, 0x06, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x0e, 0x2e, 0x63, 0x6f, 0x6d, 0x6d, 0x6f, 0x6e, 0x2e, 0x52, 0x65,
0x20, 0x01, 0x28, 0x0e, 0x32, 0x12, 0x2e, 0x63, 0x6f, 0x6d, 0x6d, 0x6f, 0x6e, 0x2e, 0x4d, 0x61, 0x67, 0x69, 0x6f, 0x6e, 0x52, 0x06, 0x72, 0x65, 0x67, 0x69, 0x6f, 0x6e, 0x12, 0x33, 0x0a, 0x0b,
0x63, 0x56, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x52, 0x0a, 0x6d, 0x61, 0x63, 0x56, 0x65, 0x72, 0x6d, 0x61, 0x63, 0x5f, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x18, 0x06, 0x20, 0x01, 0x28,
0x73, 0x69, 0x6f, 0x6e, 0x12, 0x49, 0x0a, 0x13, 0x72, 0x65, 0x67, 0x5f, 0x70, 0x61, 0x72, 0x61, 0x0e, 0x32, 0x12, 0x2e, 0x63, 0x6f, 0x6d, 0x6d, 0x6f, 0x6e, 0x2e, 0x4d, 0x61, 0x63, 0x56, 0x65,
0x6d, 0x73, 0x5f, 0x72, 0x65, 0x76, 0x69, 0x73, 0x69, 0x6f, 0x6e, 0x18, 0x07, 0x20, 0x01, 0x28, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x52, 0x0a, 0x6d, 0x61, 0x63, 0x56, 0x65, 0x72, 0x73, 0x69, 0x6f,
0x0e, 0x32, 0x19, 0x2e, 0x63, 0x6f, 0x6d, 0x6d, 0x6f, 0x6e, 0x2e, 0x52, 0x65, 0x67, 0x50, 0x61, 0x6e, 0x12, 0x49, 0x0a, 0x13, 0x72, 0x65, 0x67, 0x5f, 0x70, 0x61, 0x72, 0x61, 0x6d, 0x73, 0x5f,
0x72, 0x61, 0x6d, 0x73, 0x52, 0x65, 0x76, 0x69, 0x73, 0x69, 0x6f, 0x6e, 0x52, 0x11, 0x72, 0x65, 0x72, 0x65, 0x76, 0x69, 0x73, 0x69, 0x6f, 0x6e, 0x18, 0x07, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x19,
0x67, 0x50, 0x61, 0x72, 0x61, 0x6d, 0x73, 0x52, 0x65, 0x76, 0x69, 0x73, 0x69, 0x6f, 0x6e, 0x12, 0x2e, 0x63, 0x6f, 0x6d, 0x6d, 0x6f, 0x6e, 0x2e, 0x52, 0x65, 0x67, 0x50, 0x61, 0x72, 0x61, 0x6d,
0x23, 0x0a, 0x0d, 0x73, 0x75, 0x70, 0x70, 0x6f, 0x72, 0x74, 0x73, 0x5f, 0x6f, 0x74, 0x61, 0x61, 0x73, 0x52, 0x65, 0x76, 0x69, 0x73, 0x69, 0x6f, 0x6e, 0x52, 0x11, 0x72, 0x65, 0x67, 0x50, 0x61,
0x18, 0x08, 0x20, 0x01, 0x28, 0x08, 0x52, 0x0c, 0x73, 0x75, 0x70, 0x70, 0x6f, 0x72, 0x74, 0x73, 0x72, 0x61, 0x6d, 0x73, 0x52, 0x65, 0x76, 0x69, 0x73, 0x69, 0x6f, 0x6e, 0x12, 0x23, 0x0a, 0x0d,
0x4f, 0x74, 0x61, 0x61, 0x12, 0x28, 0x0a, 0x10, 0x73, 0x75, 0x70, 0x70, 0x6f, 0x72, 0x74, 0x73, 0x73, 0x75, 0x70, 0x70, 0x6f, 0x72, 0x74, 0x73, 0x5f, 0x6f, 0x74, 0x61, 0x61, 0x18, 0x08, 0x20,
0x5f, 0x63, 0x6c, 0x61, 0x73, 0x73, 0x5f, 0x62, 0x18, 0x09, 0x20, 0x01, 0x28, 0x08, 0x52, 0x0e, 0x01, 0x28, 0x08, 0x52, 0x0c, 0x73, 0x75, 0x70, 0x70, 0x6f, 0x72, 0x74, 0x73, 0x4f, 0x74, 0x61,
0x73, 0x75, 0x70, 0x70, 0x6f, 0x72, 0x74, 0x73, 0x43, 0x6c, 0x61, 0x73, 0x73, 0x42, 0x12, 0x28, 0x61, 0x12, 0x28, 0x0a, 0x10, 0x73, 0x75, 0x70, 0x70, 0x6f, 0x72, 0x74, 0x73, 0x5f, 0x63, 0x6c,
0x0a, 0x10, 0x73, 0x75, 0x70, 0x70, 0x6f, 0x72, 0x74, 0x73, 0x5f, 0x63, 0x6c, 0x61, 0x73, 0x73, 0x61, 0x73, 0x73, 0x5f, 0x62, 0x18, 0x09, 0x20, 0x01, 0x28, 0x08, 0x52, 0x0e, 0x73, 0x75, 0x70,
0x5f, 0x63, 0x18, 0x0a, 0x20, 0x01, 0x28, 0x08, 0x52, 0x0e, 0x73, 0x75, 0x70, 0x70, 0x6f, 0x72, 0x70, 0x6f, 0x72, 0x74, 0x73, 0x43, 0x6c, 0x61, 0x73, 0x73, 0x42, 0x12, 0x28, 0x0a, 0x10, 0x73,
0x74, 0x73, 0x43, 0x6c, 0x61, 0x73, 0x73, 0x43, 0x22, 0x57, 0x0a, 0x1a, 0x43, 0x72, 0x65, 0x61, 0x75, 0x70, 0x70, 0x6f, 0x72, 0x74, 0x73, 0x5f, 0x63, 0x6c, 0x61, 0x73, 0x73, 0x5f, 0x63, 0x18,
0x74, 0x65, 0x44, 0x65, 0x76, 0x69, 0x63, 0x65, 0x50, 0x72, 0x6f, 0x66, 0x69, 0x6c, 0x65, 0x52, 0x0a, 0x20, 0x01, 0x28, 0x08, 0x52, 0x0e, 0x73, 0x75, 0x70, 0x70, 0x6f, 0x72, 0x74, 0x73, 0x43,
0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x39, 0x0a, 0x0e, 0x64, 0x65, 0x76, 0x69, 0x63, 0x65, 0x6c, 0x61, 0x73, 0x73, 0x43, 0x22, 0x57, 0x0a, 0x1a, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x44,
0x5f, 0x70, 0x72, 0x6f, 0x66, 0x69, 0x6c, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x12,
0x2e, 0x61, 0x70, 0x69, 0x2e, 0x44, 0x65, 0x76, 0x69, 0x63, 0x65, 0x50, 0x72, 0x6f, 0x66, 0x69,
0x6c, 0x65, 0x52, 0x0d, 0x64, 0x65, 0x76, 0x69, 0x63, 0x65, 0x50, 0x72, 0x6f, 0x66, 0x69, 0x6c,
0x65, 0x22, 0x2d, 0x0a, 0x1b, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x44, 0x65, 0x76, 0x69, 0x63,
0x65, 0x50, 0x72, 0x6f, 0x66, 0x69, 0x6c, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65,
0x12, 0x0e, 0x0a, 0x02, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x02, 0x69, 0x64,
0x22, 0x29, 0x0a, 0x17, 0x47, 0x65, 0x74, 0x44, 0x65, 0x76, 0x69, 0x63, 0x65, 0x50, 0x72, 0x6f,
0x66, 0x69, 0x6c, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x0e, 0x0a, 0x02, 0x69,
0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x02, 0x69, 0x64, 0x22, 0xcb, 0x01, 0x0a, 0x18,
0x47, 0x65, 0x74, 0x44, 0x65, 0x76, 0x69, 0x63, 0x65, 0x50, 0x72, 0x6f, 0x66, 0x69, 0x6c, 0x65,
0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x39, 0x0a, 0x0e, 0x64, 0x65, 0x76, 0x69,
0x63, 0x65, 0x5f, 0x70, 0x72, 0x6f, 0x66, 0x69, 0x6c, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b,
0x32, 0x12, 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x44, 0x65, 0x76, 0x69, 0x63, 0x65, 0x50, 0x72, 0x6f,
0x66, 0x69, 0x6c, 0x65, 0x52, 0x0d, 0x64, 0x65, 0x76, 0x69, 0x63, 0x65, 0x50, 0x72, 0x6f, 0x66,
0x69, 0x6c, 0x65, 0x12, 0x39, 0x0a, 0x0a, 0x63, 0x72, 0x65, 0x61, 0x74, 0x65, 0x64, 0x5f, 0x61,
0x74, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1a, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65,
0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x54, 0x69, 0x6d, 0x65, 0x73, 0x74,
0x61, 0x6d, 0x70, 0x52, 0x09, 0x63, 0x72, 0x65, 0x61, 0x74, 0x65, 0x64, 0x41, 0x74, 0x12, 0x39,
0x0a, 0x0a, 0x75, 0x70, 0x64, 0x61, 0x74, 0x65, 0x64, 0x5f, 0x61, 0x74, 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, 0x54, 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, 0x52, 0x09,
0x75, 0x70, 0x64, 0x61, 0x74, 0x65, 0x64, 0x41, 0x74, 0x22, 0x57, 0x0a, 0x1a, 0x55, 0x70, 0x64,
0x61, 0x74, 0x65, 0x44, 0x65, 0x76, 0x69, 0x63, 0x65, 0x50, 0x72, 0x6f, 0x66, 0x69, 0x6c, 0x65,
0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x39, 0x0a, 0x0e, 0x64, 0x65, 0x76, 0x69, 0x63,
0x65, 0x5f, 0x70, 0x72, 0x6f, 0x66, 0x69, 0x6c, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32,
0x12, 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x44, 0x65, 0x76, 0x69, 0x63, 0x65, 0x50, 0x72, 0x6f, 0x66,
0x69, 0x6c, 0x65, 0x52, 0x0d, 0x64, 0x65, 0x76, 0x69, 0x63, 0x65, 0x50, 0x72, 0x6f, 0x66, 0x69,
0x6c, 0x65, 0x22, 0x2c, 0x0a, 0x1a, 0x44, 0x65, 0x6c, 0x65, 0x74, 0x65, 0x44, 0x65, 0x76, 0x69,
0x63, 0x65, 0x50, 0x72, 0x6f, 0x66, 0x69, 0x6c, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74,
0x12, 0x0e, 0x0a, 0x02, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x02, 0x69, 0x64,
0x22, 0x7e, 0x0a, 0x19, 0x4c, 0x69, 0x73, 0x74, 0x44, 0x65, 0x76, 0x69, 0x63, 0x65, 0x50, 0x72,
0x6f, 0x66, 0x69, 0x6c, 0x65, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x14, 0x0a,
0x05, 0x6c, 0x69, 0x6d, 0x69, 0x74, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x05, 0x6c, 0x69,
0x6d, 0x69, 0x74, 0x12, 0x16, 0x0a, 0x06, 0x6f, 0x66, 0x66, 0x73, 0x65, 0x74, 0x18, 0x02, 0x20,
0x01, 0x28, 0x0d, 0x52, 0x06, 0x6f, 0x66, 0x66, 0x73, 0x65, 0x74, 0x12, 0x16, 0x0a, 0x06, 0x73,
0x65, 0x61, 0x72, 0x63, 0x68, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x06, 0x73, 0x65, 0x61,
0x72, 0x63, 0x68, 0x12, 0x1b, 0x0a, 0x09, 0x74, 0x65, 0x6e, 0x61, 0x6e, 0x74, 0x5f, 0x69, 0x64,
0x18, 0x04, 0x20, 0x01, 0x28, 0x09, 0x52, 0x08, 0x74, 0x65, 0x6e, 0x61, 0x6e, 0x74, 0x49, 0x64,
0x22, 0x71, 0x0a, 0x1a, 0x4c, 0x69, 0x73, 0x74, 0x44, 0x65, 0x76, 0x69, 0x63, 0x65, 0x50, 0x72,
0x6f, 0x66, 0x69, 0x6c, 0x65, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x1f,
0x0a, 0x0b, 0x74, 0x6f, 0x74, 0x61, 0x6c, 0x5f, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x18, 0x01, 0x20,
0x01, 0x28, 0x0d, 0x52, 0x0a, 0x74, 0x6f, 0x74, 0x61, 0x6c, 0x43, 0x6f, 0x75, 0x6e, 0x74, 0x12,
0x32, 0x0a, 0x06, 0x72, 0x65, 0x73, 0x75, 0x6c, 0x74, 0x18, 0x02, 0x20, 0x03, 0x28, 0x0b, 0x32,
0x1a, 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x44, 0x65, 0x76, 0x69, 0x63, 0x65, 0x50, 0x72, 0x6f, 0x66,
0x69, 0x6c, 0x65, 0x4c, 0x69, 0x73, 0x74, 0x49, 0x74, 0x65, 0x6d, 0x52, 0x06, 0x72, 0x65, 0x73,
0x75, 0x6c, 0x74, 0x22, 0x7c, 0x0a, 0x26, 0x4c, 0x69, 0x73, 0x74, 0x44, 0x65, 0x76, 0x69, 0x63,
0x65, 0x50, 0x72, 0x6f, 0x66, 0x69, 0x6c, 0x65, 0x41, 0x64, 0x72, 0x41, 0x6c, 0x67, 0x6f, 0x72,
0x69, 0x74, 0x68, 0x6d, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x1f, 0x0a,
0x0b, 0x74, 0x6f, 0x74, 0x61, 0x6c, 0x5f, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x18, 0x01, 0x20, 0x01,
0x28, 0x0d, 0x52, 0x0a, 0x74, 0x6f, 0x74, 0x61, 0x6c, 0x43, 0x6f, 0x75, 0x6e, 0x74, 0x12, 0x31,
0x0a, 0x06, 0x72, 0x65, 0x73, 0x75, 0x6c, 0x74, 0x18, 0x02, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x19,
0x2e, 0x61, 0x70, 0x69, 0x2e, 0x41, 0x64, 0x72, 0x41, 0x6c, 0x67, 0x6f, 0x72, 0x69, 0x74, 0x68,
0x6d, 0x4c, 0x69, 0x73, 0x74, 0x49, 0x74, 0x65, 0x6d, 0x52, 0x06, 0x72, 0x65, 0x73, 0x75, 0x6c,
0x74, 0x22, 0x3a, 0x0a, 0x14, 0x41, 0x64, 0x72, 0x41, 0x6c, 0x67, 0x6f, 0x72, 0x69, 0x74, 0x68,
0x6d, 0x4c, 0x69, 0x73, 0x74, 0x49, 0x74, 0x65, 0x6d, 0x12, 0x0e, 0x0a, 0x02, 0x69, 0x64, 0x18,
0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x02, 0x69, 0x64, 0x12, 0x12, 0x0a, 0x04, 0x6e, 0x61, 0x6d,
0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x2a, 0x31, 0x0a,
0x0c, 0x43, 0x6f, 0x64, 0x65, 0x63, 0x52, 0x75, 0x6e, 0x74, 0x69, 0x6d, 0x65, 0x12, 0x08, 0x0a,
0x04, 0x4e, 0x4f, 0x4e, 0x45, 0x10, 0x00, 0x12, 0x0f, 0x0a, 0x0b, 0x43, 0x41, 0x59, 0x45, 0x4e,
0x4e, 0x45, 0x5f, 0x4c, 0x50, 0x50, 0x10, 0x01, 0x12, 0x06, 0x0a, 0x02, 0x4a, 0x53, 0x10, 0x02,
0x2a, 0x50, 0x0a, 0x0f, 0x4d, 0x65, 0x61, 0x73, 0x75, 0x72, 0x65, 0x6d, 0x65, 0x6e, 0x74, 0x4b,
0x69, 0x6e, 0x64, 0x12, 0x0b, 0x0a, 0x07, 0x55, 0x4e, 0x4b, 0x4e, 0x4f, 0x57, 0x4e, 0x10, 0x00,
0x12, 0x0b, 0x0a, 0x07, 0x43, 0x4f, 0x55, 0x4e, 0x54, 0x45, 0x52, 0x10, 0x01, 0x12, 0x0c, 0x0a,
0x08, 0x41, 0x42, 0x53, 0x4f, 0x4c, 0x55, 0x54, 0x45, 0x10, 0x02, 0x12, 0x09, 0x0a, 0x05, 0x47,
0x41, 0x55, 0x47, 0x45, 0x10, 0x03, 0x12, 0x0a, 0x0a, 0x06, 0x53, 0x54, 0x52, 0x49, 0x4e, 0x47,
0x10, 0x04, 0x2a, 0x55, 0x0a, 0x0e, 0x43, 0x61, 0x64, 0x50, 0x65, 0x72, 0x69, 0x6f, 0x64, 0x69,
0x63, 0x69, 0x74, 0x79, 0x12, 0x09, 0x0a, 0x05, 0x53, 0x45, 0x43, 0x5f, 0x31, 0x10, 0x00, 0x12,
0x0a, 0x0a, 0x06, 0x4d, 0x53, 0x5f, 0x35, 0x30, 0x30, 0x10, 0x01, 0x12, 0x0a, 0x0a, 0x06, 0x4d,
0x53, 0x5f, 0x32, 0x35, 0x30, 0x10, 0x02, 0x12, 0x0a, 0x0a, 0x06, 0x4d, 0x53, 0x5f, 0x31, 0x30,
0x30, 0x10, 0x03, 0x12, 0x09, 0x0a, 0x05, 0x4d, 0x53, 0x5f, 0x35, 0x30, 0x10, 0x04, 0x12, 0x09,
0x0a, 0x05, 0x4d, 0x53, 0x5f, 0x32, 0x30, 0x10, 0x05, 0x2a, 0x61, 0x0a, 0x11, 0x53, 0x65, 0x63,
0x6f, 0x6e, 0x64, 0x43, 0x68, 0x41, 0x63, 0x6b, 0x4f, 0x66, 0x66, 0x73, 0x65, 0x74, 0x12, 0x09,
0x0a, 0x05, 0x4b, 0x48, 0x5a, 0x5f, 0x30, 0x10, 0x00, 0x12, 0x0b, 0x0a, 0x07, 0x4b, 0x48, 0x5a,
0x5f, 0x32, 0x30, 0x30, 0x10, 0x01, 0x12, 0x0b, 0x0a, 0x07, 0x4b, 0x48, 0x5a, 0x5f, 0x34, 0x30,
0x30, 0x10, 0x02, 0x12, 0x0b, 0x0a, 0x07, 0x4b, 0x48, 0x5a, 0x5f, 0x38, 0x30, 0x30, 0x10, 0x03,
0x12, 0x0c, 0x0a, 0x08, 0x4b, 0x48, 0x5a, 0x5f, 0x31, 0x36, 0x30, 0x30, 0x10, 0x04, 0x12, 0x0c,
0x0a, 0x08, 0x4b, 0x48, 0x5a, 0x5f, 0x33, 0x32, 0x30, 0x30, 0x10, 0x05, 0x2a, 0x6c, 0x0a, 0x13,
0x52, 0x65, 0x6c, 0x61, 0x79, 0x4d, 0x6f, 0x64, 0x65, 0x41, 0x63, 0x74, 0x69, 0x76, 0x61, 0x74,
0x69, 0x6f, 0x6e, 0x12, 0x16, 0x0a, 0x12, 0x44, 0x49, 0x53, 0x41, 0x42, 0x4c, 0x45, 0x5f, 0x52,
0x45, 0x4c, 0x41, 0x59, 0x5f, 0x4d, 0x4f, 0x44, 0x45, 0x10, 0x00, 0x12, 0x15, 0x0a, 0x11, 0x45,
0x4e, 0x41, 0x42, 0x4c, 0x45, 0x5f, 0x52, 0x45, 0x4c, 0x41, 0x59, 0x5f, 0x4d, 0x4f, 0x44, 0x45,
0x10, 0x01, 0x12, 0x0b, 0x0a, 0x07, 0x44, 0x59, 0x4e, 0x41, 0x4d, 0x49, 0x43, 0x10, 0x02, 0x12,
0x19, 0x0a, 0x15, 0x45, 0x4e, 0x44, 0x5f, 0x44, 0x45, 0x56, 0x49, 0x43, 0x45, 0x5f, 0x43, 0x4f,
0x4e, 0x54, 0x52, 0x4f, 0x4c, 0x4c, 0x45, 0x44, 0x10, 0x03, 0x32, 0xb8, 0x05, 0x0a, 0x14, 0x44,
0x65, 0x76, 0x69, 0x63, 0x65, 0x50, 0x72, 0x6f, 0x66, 0x69, 0x6c, 0x65, 0x53, 0x65, 0x72, 0x76,
0x69, 0x63, 0x65, 0x12, 0x6c, 0x0a, 0x06, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x12, 0x1f, 0x2e,
0x61, 0x70, 0x69, 0x2e, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x44, 0x65, 0x76, 0x69, 0x63, 0x65,
0x50, 0x72, 0x6f, 0x66, 0x69, 0x6c, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x20,
0x2e, 0x61, 0x70, 0x69, 0x2e, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x44, 0x65, 0x76, 0x69, 0x63,
0x65, 0x50, 0x72, 0x6f, 0x66, 0x69, 0x6c, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65,
0x22, 0x1f, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x19, 0x3a, 0x01, 0x2a, 0x22, 0x14, 0x2f, 0x61, 0x70,
0x69, 0x2f, 0x64, 0x65, 0x76, 0x69, 0x63, 0x65, 0x2d, 0x70, 0x72, 0x6f, 0x66, 0x69, 0x6c, 0x65,
0x73, 0x12, 0x65, 0x0a, 0x03, 0x47, 0x65, 0x74, 0x12, 0x1c, 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x47,
0x65, 0x74, 0x44, 0x65, 0x76, 0x69, 0x63, 0x65, 0x50, 0x72, 0x6f, 0x66, 0x69, 0x6c, 0x65, 0x52,
0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x1d, 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x47, 0x65, 0x74,
0x44, 0x65, 0x76, 0x69, 0x63, 0x65, 0x50, 0x72, 0x6f, 0x66, 0x69, 0x6c, 0x65, 0x52, 0x65, 0x73,
0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x21, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x1b, 0x12, 0x19, 0x2f,
0x61, 0x70, 0x69, 0x2f, 0x64, 0x65, 0x76, 0x69, 0x63, 0x65, 0x2d, 0x70, 0x72, 0x6f, 0x66, 0x69,
0x6c, 0x65, 0x73, 0x2f, 0x7b, 0x69, 0x64, 0x7d, 0x12, 0x76, 0x0a, 0x06, 0x55, 0x70, 0x64, 0x61,
0x74, 0x65, 0x12, 0x1f, 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x44,
0x65, 0x76, 0x69, 0x63, 0x65, 0x50, 0x72, 0x6f, 0x66, 0x69, 0x6c, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x76, 0x69, 0x63, 0x65, 0x50, 0x72, 0x6f, 0x66, 0x69, 0x6c, 0x65, 0x52, 0x65, 0x71, 0x75,
0x65, 0x73, 0x74, 0x1a, 0x16, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x65, 0x73, 0x74, 0x12, 0x39, 0x0a, 0x0e, 0x64, 0x65, 0x76, 0x69, 0x63, 0x65, 0x5f, 0x70, 0x72,
0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x45, 0x6d, 0x70, 0x74, 0x79, 0x22, 0x33, 0x82, 0xd3, 0xe4, 0x6f, 0x66, 0x69, 0x6c, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x12, 0x2e, 0x61, 0x70,
0x93, 0x02, 0x2d, 0x3a, 0x01, 0x2a, 0x1a, 0x28, 0x2f, 0x61, 0x70, 0x69, 0x2f, 0x64, 0x65, 0x76, 0x69, 0x2e, 0x44, 0x65, 0x76, 0x69, 0x63, 0x65, 0x50, 0x72, 0x6f, 0x66, 0x69, 0x6c, 0x65, 0x52,
0x69, 0x63, 0x65, 0x2d, 0x70, 0x72, 0x6f, 0x66, 0x69, 0x6c, 0x65, 0x73, 0x2f, 0x7b, 0x64, 0x65, 0x0d, 0x64, 0x65, 0x76, 0x69, 0x63, 0x65, 0x50, 0x72, 0x6f, 0x66, 0x69, 0x6c, 0x65, 0x22, 0x2d,
0x76, 0x69, 0x63, 0x65, 0x5f, 0x70, 0x72, 0x6f, 0x66, 0x69, 0x6c, 0x65, 0x2e, 0x69, 0x64, 0x7d, 0x0a, 0x1b, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x44, 0x65, 0x76, 0x69, 0x63, 0x65, 0x50, 0x72,
0x12, 0x64, 0x0a, 0x06, 0x44, 0x65, 0x6c, 0x65, 0x74, 0x65, 0x12, 0x1f, 0x2e, 0x61, 0x70, 0x69, 0x6f, 0x66, 0x69, 0x6c, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x0e, 0x0a,
0x2e, 0x44, 0x65, 0x6c, 0x65, 0x74, 0x65, 0x44, 0x65, 0x76, 0x69, 0x63, 0x65, 0x50, 0x72, 0x6f, 0x02, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x02, 0x69, 0x64, 0x22, 0x29, 0x0a,
0x66, 0x69, 0x6c, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x16, 0x2e, 0x67, 0x6f, 0x17, 0x47, 0x65, 0x74, 0x44, 0x65, 0x76, 0x69, 0x63, 0x65, 0x50, 0x72, 0x6f, 0x66, 0x69, 0x6c,
0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x45, 0x6d, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x0e, 0x0a, 0x02, 0x69, 0x64, 0x18, 0x01,
0x70, 0x74, 0x79, 0x22, 0x21, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x1b, 0x2a, 0x19, 0x2f, 0x61, 0x70, 0x20, 0x01, 0x28, 0x09, 0x52, 0x02, 0x69, 0x64, 0x22, 0xcb, 0x01, 0x0a, 0x18, 0x47, 0x65, 0x74,
0x69, 0x2f, 0x64, 0x65, 0x76, 0x69, 0x63, 0x65, 0x2d, 0x70, 0x72, 0x6f, 0x66, 0x69, 0x6c, 0x65, 0x44, 0x65, 0x76, 0x69, 0x63, 0x65, 0x50, 0x72, 0x6f, 0x66, 0x69, 0x6c, 0x65, 0x52, 0x65, 0x73,
0x73, 0x2f, 0x7b, 0x69, 0x64, 0x7d, 0x12, 0x65, 0x0a, 0x04, 0x4c, 0x69, 0x73, 0x74, 0x12, 0x1e, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x39, 0x0a, 0x0e, 0x64, 0x65, 0x76, 0x69, 0x63, 0x65, 0x5f,
0x2e, 0x61, 0x70, 0x69, 0x2e, 0x4c, 0x69, 0x73, 0x74, 0x44, 0x65, 0x76, 0x69, 0x63, 0x65, 0x50, 0x70, 0x72, 0x6f, 0x66, 0x69, 0x6c, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x12, 0x2e,
0x72, 0x6f, 0x66, 0x69, 0x6c, 0x65, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x1f, 0x61, 0x70, 0x69, 0x2e, 0x44, 0x65, 0x76, 0x69, 0x63, 0x65, 0x50, 0x72, 0x6f, 0x66, 0x69, 0x6c,
0x2e, 0x61, 0x70, 0x69, 0x2e, 0x4c, 0x69, 0x73, 0x74, 0x44, 0x65, 0x76, 0x69, 0x63, 0x65, 0x50, 0x65, 0x52, 0x0d, 0x64, 0x65, 0x76, 0x69, 0x63, 0x65, 0x50, 0x72, 0x6f, 0x66, 0x69, 0x6c, 0x65,
0x72, 0x6f, 0x66, 0x69, 0x6c, 0x65, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x12, 0x39, 0x0a, 0x0a, 0x63, 0x72, 0x65, 0x61, 0x74, 0x65, 0x64, 0x5f, 0x61, 0x74, 0x18, 0x02,
0x1c, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x16, 0x12, 0x14, 0x2f, 0x61, 0x70, 0x69, 0x2f, 0x64, 0x65, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1a, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72,
0x76, 0x69, 0x63, 0x65, 0x2d, 0x70, 0x72, 0x6f, 0x66, 0x69, 0x6c, 0x65, 0x73, 0x12, 0x85, 0x01, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x54, 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70,
0x0a, 0x11, 0x4c, 0x69, 0x73, 0x74, 0x41, 0x64, 0x72, 0x41, 0x6c, 0x67, 0x6f, 0x72, 0x69, 0x74, 0x52, 0x09, 0x63, 0x72, 0x65, 0x61, 0x74, 0x65, 0x64, 0x41, 0x74, 0x12, 0x39, 0x0a, 0x0a, 0x75,
0x68, 0x6d, 0x73, 0x12, 0x16, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x70, 0x64, 0x61, 0x74, 0x65, 0x64, 0x5f, 0x61, 0x74, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0b, 0x32,
0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x45, 0x6d, 0x70, 0x74, 0x79, 0x1a, 0x2b, 0x2e, 0x61, 0x70, 0x1a, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75,
0x66, 0x2e, 0x54, 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, 0x52, 0x09, 0x75, 0x70, 0x64,
0x61, 0x74, 0x65, 0x64, 0x41, 0x74, 0x22, 0x57, 0x0a, 0x1a, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65,
0x44, 0x65, 0x76, 0x69, 0x63, 0x65, 0x50, 0x72, 0x6f, 0x66, 0x69, 0x6c, 0x65, 0x52, 0x65, 0x71,
0x75, 0x65, 0x73, 0x74, 0x12, 0x39, 0x0a, 0x0e, 0x64, 0x65, 0x76, 0x69, 0x63, 0x65, 0x5f, 0x70,
0x72, 0x6f, 0x66, 0x69, 0x6c, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x12, 0x2e, 0x61,
0x70, 0x69, 0x2e, 0x44, 0x65, 0x76, 0x69, 0x63, 0x65, 0x50, 0x72, 0x6f, 0x66, 0x69, 0x6c, 0x65,
0x52, 0x0d, 0x64, 0x65, 0x76, 0x69, 0x63, 0x65, 0x50, 0x72, 0x6f, 0x66, 0x69, 0x6c, 0x65, 0x22,
0x2c, 0x0a, 0x1a, 0x44, 0x65, 0x6c, 0x65, 0x74, 0x65, 0x44, 0x65, 0x76, 0x69, 0x63, 0x65, 0x50,
0x72, 0x6f, 0x66, 0x69, 0x6c, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x0e, 0x0a,
0x02, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x02, 0x69, 0x64, 0x22, 0x7e, 0x0a,
0x19, 0x4c, 0x69, 0x73, 0x74, 0x44, 0x65, 0x76, 0x69, 0x63, 0x65, 0x50, 0x72, 0x6f, 0x66, 0x69,
0x6c, 0x65, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x14, 0x0a, 0x05, 0x6c, 0x69,
0x6d, 0x69, 0x74, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x05, 0x6c, 0x69, 0x6d, 0x69, 0x74,
0x12, 0x16, 0x0a, 0x06, 0x6f, 0x66, 0x66, 0x73, 0x65, 0x74, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0d,
0x52, 0x06, 0x6f, 0x66, 0x66, 0x73, 0x65, 0x74, 0x12, 0x16, 0x0a, 0x06, 0x73, 0x65, 0x61, 0x72,
0x63, 0x68, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x06, 0x73, 0x65, 0x61, 0x72, 0x63, 0x68,
0x12, 0x1b, 0x0a, 0x09, 0x74, 0x65, 0x6e, 0x61, 0x6e, 0x74, 0x5f, 0x69, 0x64, 0x18, 0x04, 0x20,
0x01, 0x28, 0x09, 0x52, 0x08, 0x74, 0x65, 0x6e, 0x61, 0x6e, 0x74, 0x49, 0x64, 0x22, 0x71, 0x0a,
0x1a, 0x4c, 0x69, 0x73, 0x74, 0x44, 0x65, 0x76, 0x69, 0x63, 0x65, 0x50, 0x72, 0x6f, 0x66, 0x69,
0x6c, 0x65, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x1f, 0x0a, 0x0b, 0x74,
0x6f, 0x74, 0x61, 0x6c, 0x5f, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0d,
0x52, 0x0a, 0x74, 0x6f, 0x74, 0x61, 0x6c, 0x43, 0x6f, 0x75, 0x6e, 0x74, 0x12, 0x32, 0x0a, 0x06,
0x72, 0x65, 0x73, 0x75, 0x6c, 0x74, 0x18, 0x02, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x1a, 0x2e, 0x61,
0x70, 0x69, 0x2e, 0x44, 0x65, 0x76, 0x69, 0x63, 0x65, 0x50, 0x72, 0x6f, 0x66, 0x69, 0x6c, 0x65,
0x4c, 0x69, 0x73, 0x74, 0x49, 0x74, 0x65, 0x6d, 0x52, 0x06, 0x72, 0x65, 0x73, 0x75, 0x6c, 0x74,
0x22, 0x7c, 0x0a, 0x26, 0x4c, 0x69, 0x73, 0x74, 0x44, 0x65, 0x76, 0x69, 0x63, 0x65, 0x50, 0x72,
0x6f, 0x66, 0x69, 0x6c, 0x65, 0x41, 0x64, 0x72, 0x41, 0x6c, 0x67, 0x6f, 0x72, 0x69, 0x74, 0x68,
0x6d, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x1f, 0x0a, 0x0b, 0x74, 0x6f,
0x74, 0x61, 0x6c, 0x5f, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0d, 0x52,
0x0a, 0x74, 0x6f, 0x74, 0x61, 0x6c, 0x43, 0x6f, 0x75, 0x6e, 0x74, 0x12, 0x31, 0x0a, 0x06, 0x72,
0x65, 0x73, 0x75, 0x6c, 0x74, 0x18, 0x02, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x19, 0x2e, 0x61, 0x70,
0x69, 0x2e, 0x41, 0x64, 0x72, 0x41, 0x6c, 0x67, 0x6f, 0x72, 0x69, 0x74, 0x68, 0x6d, 0x4c, 0x69,
0x73, 0x74, 0x49, 0x74, 0x65, 0x6d, 0x52, 0x06, 0x72, 0x65, 0x73, 0x75, 0x6c, 0x74, 0x22, 0x3a,
0x0a, 0x14, 0x41, 0x64, 0x72, 0x41, 0x6c, 0x67, 0x6f, 0x72, 0x69, 0x74, 0x68, 0x6d, 0x4c, 0x69,
0x73, 0x74, 0x49, 0x74, 0x65, 0x6d, 0x12, 0x0e, 0x0a, 0x02, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01,
0x28, 0x09, 0x52, 0x02, 0x69, 0x64, 0x12, 0x12, 0x0a, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x02,
0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x2a, 0x31, 0x0a, 0x0c, 0x43, 0x6f,
0x64, 0x65, 0x63, 0x52, 0x75, 0x6e, 0x74, 0x69, 0x6d, 0x65, 0x12, 0x08, 0x0a, 0x04, 0x4e, 0x4f,
0x4e, 0x45, 0x10, 0x00, 0x12, 0x0f, 0x0a, 0x0b, 0x43, 0x41, 0x59, 0x45, 0x4e, 0x4e, 0x45, 0x5f,
0x4c, 0x50, 0x50, 0x10, 0x01, 0x12, 0x06, 0x0a, 0x02, 0x4a, 0x53, 0x10, 0x02, 0x2a, 0x50, 0x0a,
0x0f, 0x4d, 0x65, 0x61, 0x73, 0x75, 0x72, 0x65, 0x6d, 0x65, 0x6e, 0x74, 0x4b, 0x69, 0x6e, 0x64,
0x12, 0x0b, 0x0a, 0x07, 0x55, 0x4e, 0x4b, 0x4e, 0x4f, 0x57, 0x4e, 0x10, 0x00, 0x12, 0x0b, 0x0a,
0x07, 0x43, 0x4f, 0x55, 0x4e, 0x54, 0x45, 0x52, 0x10, 0x01, 0x12, 0x0c, 0x0a, 0x08, 0x41, 0x42,
0x53, 0x4f, 0x4c, 0x55, 0x54, 0x45, 0x10, 0x02, 0x12, 0x09, 0x0a, 0x05, 0x47, 0x41, 0x55, 0x47,
0x45, 0x10, 0x03, 0x12, 0x0a, 0x0a, 0x06, 0x53, 0x54, 0x52, 0x49, 0x4e, 0x47, 0x10, 0x04, 0x2a,
0x55, 0x0a, 0x0e, 0x43, 0x61, 0x64, 0x50, 0x65, 0x72, 0x69, 0x6f, 0x64, 0x69, 0x63, 0x69, 0x74,
0x79, 0x12, 0x09, 0x0a, 0x05, 0x53, 0x45, 0x43, 0x5f, 0x31, 0x10, 0x00, 0x12, 0x0a, 0x0a, 0x06,
0x4d, 0x53, 0x5f, 0x35, 0x30, 0x30, 0x10, 0x01, 0x12, 0x0a, 0x0a, 0x06, 0x4d, 0x53, 0x5f, 0x32,
0x35, 0x30, 0x10, 0x02, 0x12, 0x0a, 0x0a, 0x06, 0x4d, 0x53, 0x5f, 0x31, 0x30, 0x30, 0x10, 0x03,
0x12, 0x09, 0x0a, 0x05, 0x4d, 0x53, 0x5f, 0x35, 0x30, 0x10, 0x04, 0x12, 0x09, 0x0a, 0x05, 0x4d,
0x53, 0x5f, 0x32, 0x30, 0x10, 0x05, 0x2a, 0x61, 0x0a, 0x11, 0x53, 0x65, 0x63, 0x6f, 0x6e, 0x64,
0x43, 0x68, 0x41, 0x63, 0x6b, 0x4f, 0x66, 0x66, 0x73, 0x65, 0x74, 0x12, 0x09, 0x0a, 0x05, 0x4b,
0x48, 0x5a, 0x5f, 0x30, 0x10, 0x00, 0x12, 0x0b, 0x0a, 0x07, 0x4b, 0x48, 0x5a, 0x5f, 0x32, 0x30,
0x30, 0x10, 0x01, 0x12, 0x0b, 0x0a, 0x07, 0x4b, 0x48, 0x5a, 0x5f, 0x34, 0x30, 0x30, 0x10, 0x02,
0x12, 0x0b, 0x0a, 0x07, 0x4b, 0x48, 0x5a, 0x5f, 0x38, 0x30, 0x30, 0x10, 0x03, 0x12, 0x0c, 0x0a,
0x08, 0x4b, 0x48, 0x5a, 0x5f, 0x31, 0x36, 0x30, 0x30, 0x10, 0x04, 0x12, 0x0c, 0x0a, 0x08, 0x4b,
0x48, 0x5a, 0x5f, 0x33, 0x32, 0x30, 0x30, 0x10, 0x05, 0x2a, 0x6c, 0x0a, 0x13, 0x52, 0x65, 0x6c,
0x61, 0x79, 0x4d, 0x6f, 0x64, 0x65, 0x41, 0x63, 0x74, 0x69, 0x76, 0x61, 0x74, 0x69, 0x6f, 0x6e,
0x12, 0x16, 0x0a, 0x12, 0x44, 0x49, 0x53, 0x41, 0x42, 0x4c, 0x45, 0x5f, 0x52, 0x45, 0x4c, 0x41,
0x59, 0x5f, 0x4d, 0x4f, 0x44, 0x45, 0x10, 0x00, 0x12, 0x15, 0x0a, 0x11, 0x45, 0x4e, 0x41, 0x42,
0x4c, 0x45, 0x5f, 0x52, 0x45, 0x4c, 0x41, 0x59, 0x5f, 0x4d, 0x4f, 0x44, 0x45, 0x10, 0x01, 0x12,
0x0b, 0x0a, 0x07, 0x44, 0x59, 0x4e, 0x41, 0x4d, 0x49, 0x43, 0x10, 0x02, 0x12, 0x19, 0x0a, 0x15,
0x45, 0x4e, 0x44, 0x5f, 0x44, 0x45, 0x56, 0x49, 0x43, 0x45, 0x5f, 0x43, 0x4f, 0x4e, 0x54, 0x52,
0x4f, 0x4c, 0x4c, 0x45, 0x44, 0x10, 0x03, 0x32, 0xb8, 0x05, 0x0a, 0x14, 0x44, 0x65, 0x76, 0x69,
0x63, 0x65, 0x50, 0x72, 0x6f, 0x66, 0x69, 0x6c, 0x65, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65,
0x12, 0x6c, 0x0a, 0x06, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x12, 0x1f, 0x2e, 0x61, 0x70, 0x69,
0x2e, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x44, 0x65, 0x76, 0x69, 0x63, 0x65, 0x50, 0x72, 0x6f,
0x66, 0x69, 0x6c, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x20, 0x2e, 0x61, 0x70,
0x69, 0x2e, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x44, 0x65, 0x76, 0x69, 0x63, 0x65, 0x50, 0x72,
0x6f, 0x66, 0x69, 0x6c, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x1f, 0x82,
0xd3, 0xe4, 0x93, 0x02, 0x19, 0x3a, 0x01, 0x2a, 0x22, 0x14, 0x2f, 0x61, 0x70, 0x69, 0x2f, 0x64,
0x65, 0x76, 0x69, 0x63, 0x65, 0x2d, 0x70, 0x72, 0x6f, 0x66, 0x69, 0x6c, 0x65, 0x73, 0x12, 0x65,
0x0a, 0x03, 0x47, 0x65, 0x74, 0x12, 0x1c, 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x47, 0x65, 0x74, 0x44,
0x65, 0x76, 0x69, 0x63, 0x65, 0x50, 0x72, 0x6f, 0x66, 0x69, 0x6c, 0x65, 0x52, 0x65, 0x71, 0x75,
0x65, 0x73, 0x74, 0x1a, 0x1d, 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x47, 0x65, 0x74, 0x44, 0x65, 0x76,
0x69, 0x63, 0x65, 0x50, 0x72, 0x6f, 0x66, 0x69, 0x6c, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e,
0x73, 0x65, 0x22, 0x21, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x1b, 0x12, 0x19, 0x2f, 0x61, 0x70, 0x69,
0x2f, 0x64, 0x65, 0x76, 0x69, 0x63, 0x65, 0x2d, 0x70, 0x72, 0x6f, 0x66, 0x69, 0x6c, 0x65, 0x73,
0x2f, 0x7b, 0x69, 0x64, 0x7d, 0x12, 0x76, 0x0a, 0x06, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x12,
0x1f, 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x44, 0x65, 0x76, 0x69,
0x63, 0x65, 0x50, 0x72, 0x6f, 0x66, 0x69, 0x6c, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74,
0x1a, 0x16, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62,
0x75, 0x66, 0x2e, 0x45, 0x6d, 0x70, 0x74, 0x79, 0x22, 0x33, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x2d,
0x3a, 0x01, 0x2a, 0x1a, 0x28, 0x2f, 0x61, 0x70, 0x69, 0x2f, 0x64, 0x65, 0x76, 0x69, 0x63, 0x65,
0x2d, 0x70, 0x72, 0x6f, 0x66, 0x69, 0x6c, 0x65, 0x73, 0x2f, 0x7b, 0x64, 0x65, 0x76, 0x69, 0x63,
0x65, 0x5f, 0x70, 0x72, 0x6f, 0x66, 0x69, 0x6c, 0x65, 0x2e, 0x69, 0x64, 0x7d, 0x12, 0x64, 0x0a,
0x06, 0x44, 0x65, 0x6c, 0x65, 0x74, 0x65, 0x12, 0x1f, 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x44, 0x65,
0x6c, 0x65, 0x74, 0x65, 0x44, 0x65, 0x76, 0x69, 0x63, 0x65, 0x50, 0x72, 0x6f, 0x66, 0x69, 0x6c,
0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x16, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c,
0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x45, 0x6d, 0x70, 0x74, 0x79,
0x22, 0x21, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x1b, 0x2a, 0x19, 0x2f, 0x61, 0x70, 0x69, 0x2f, 0x64,
0x65, 0x76, 0x69, 0x63, 0x65, 0x2d, 0x70, 0x72, 0x6f, 0x66, 0x69, 0x6c, 0x65, 0x73, 0x2f, 0x7b,
0x69, 0x64, 0x7d, 0x12, 0x65, 0x0a, 0x04, 0x4c, 0x69, 0x73, 0x74, 0x12, 0x1e, 0x2e, 0x61, 0x70,
0x69, 0x2e, 0x4c, 0x69, 0x73, 0x74, 0x44, 0x65, 0x76, 0x69, 0x63, 0x65, 0x50, 0x72, 0x6f, 0x66, 0x69, 0x2e, 0x4c, 0x69, 0x73, 0x74, 0x44, 0x65, 0x76, 0x69, 0x63, 0x65, 0x50, 0x72, 0x6f, 0x66,
0x69, 0x6c, 0x65, 0x41, 0x64, 0x72, 0x41, 0x6c, 0x67, 0x6f, 0x72, 0x69, 0x74, 0x68, 0x6d, 0x73, 0x69, 0x6c, 0x65, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x1f, 0x2e, 0x61, 0x70,
0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x2b, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x25, 0x69, 0x2e, 0x4c, 0x69, 0x73, 0x74, 0x44, 0x65, 0x76, 0x69, 0x63, 0x65, 0x50, 0x72, 0x6f, 0x66,
0x12, 0x23, 0x2f, 0x61, 0x70, 0x69, 0x2f, 0x64, 0x65, 0x76, 0x69, 0x63, 0x65, 0x2d, 0x70, 0x72, 0x69, 0x6c, 0x65, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x1c, 0x82, 0xd3,
0x6f, 0x66, 0x69, 0x6c, 0x65, 0x73, 0x2f, 0x61, 0x64, 0x72, 0x2d, 0x61, 0x6c, 0x67, 0x6f, 0x72, 0xe4, 0x93, 0x02, 0x16, 0x12, 0x14, 0x2f, 0x61, 0x70, 0x69, 0x2f, 0x64, 0x65, 0x76, 0x69, 0x63,
0x69, 0x74, 0x68, 0x6d, 0x73, 0x42, 0x6a, 0x0a, 0x11, 0x69, 0x6f, 0x2e, 0x63, 0x68, 0x69, 0x72, 0x65, 0x2d, 0x70, 0x72, 0x6f, 0x66, 0x69, 0x6c, 0x65, 0x73, 0x12, 0x85, 0x01, 0x0a, 0x11, 0x4c,
0x70, 0x73, 0x74, 0x61, 0x63, 0x6b, 0x2e, 0x61, 0x70, 0x69, 0x42, 0x12, 0x44, 0x65, 0x76, 0x69, 0x69, 0x73, 0x74, 0x41, 0x64, 0x72, 0x41, 0x6c, 0x67, 0x6f, 0x72, 0x69, 0x74, 0x68, 0x6d, 0x73,
0x63, 0x65, 0x50, 0x72, 0x6f, 0x66, 0x69, 0x6c, 0x65, 0x50, 0x72, 0x6f, 0x74, 0x6f, 0x50, 0x01, 0x12, 0x16, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62,
0x5a, 0x2e, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x63, 0x68, 0x69, 0x75, 0x66, 0x2e, 0x45, 0x6d, 0x70, 0x74, 0x79, 0x1a, 0x2b, 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x4c,
0x72, 0x70, 0x73, 0x74, 0x61, 0x63, 0x6b, 0x2f, 0x63, 0x68, 0x69, 0x72, 0x70, 0x73, 0x74, 0x61, 0x69, 0x73, 0x74, 0x44, 0x65, 0x76, 0x69, 0x63, 0x65, 0x50, 0x72, 0x6f, 0x66, 0x69, 0x6c, 0x65,
0x63, 0x6b, 0x2f, 0x61, 0x70, 0x69, 0x2f, 0x67, 0x6f, 0x2f, 0x76, 0x34, 0x2f, 0x61, 0x70, 0x69, 0x41, 0x64, 0x72, 0x41, 0x6c, 0x67, 0x6f, 0x72, 0x69, 0x74, 0x68, 0x6d, 0x73, 0x52, 0x65, 0x73,
0xaa, 0x02, 0x0e, 0x43, 0x68, 0x69, 0x72, 0x70, 0x73, 0x74, 0x61, 0x63, 0x6b, 0x2e, 0x41, 0x70, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x2b, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x25, 0x12, 0x23, 0x2f,
0x69, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33, 0x61, 0x70, 0x69, 0x2f, 0x64, 0x65, 0x76, 0x69, 0x63, 0x65, 0x2d, 0x70, 0x72, 0x6f, 0x66, 0x69,
0x6c, 0x65, 0x73, 0x2f, 0x61, 0x64, 0x72, 0x2d, 0x61, 0x6c, 0x67, 0x6f, 0x72, 0x69, 0x74, 0x68,
0x6d, 0x73, 0x42, 0x6a, 0x0a, 0x11, 0x69, 0x6f, 0x2e, 0x63, 0x68, 0x69, 0x72, 0x70, 0x73, 0x74,
0x61, 0x63, 0x6b, 0x2e, 0x61, 0x70, 0x69, 0x42, 0x12, 0x44, 0x65, 0x76, 0x69, 0x63, 0x65, 0x50,
0x72, 0x6f, 0x66, 0x69, 0x6c, 0x65, 0x50, 0x72, 0x6f, 0x74, 0x6f, 0x50, 0x01, 0x5a, 0x2e, 0x67,
0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x63, 0x68, 0x69, 0x72, 0x70, 0x73,
0x74, 0x61, 0x63, 0x6b, 0x2f, 0x63, 0x68, 0x69, 0x72, 0x70, 0x73, 0x74, 0x61, 0x63, 0x6b, 0x2f,
0x61, 0x70, 0x69, 0x2f, 0x67, 0x6f, 0x2f, 0x76, 0x34, 0x2f, 0x61, 0x70, 0x69, 0xaa, 0x02, 0x0e,
0x43, 0x68, 0x69, 0x72, 0x70, 0x73, 0x74, 0x61, 0x63, 0x6b, 0x2e, 0x41, 0x70, 0x69, 0x62, 0x06,
0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33,
} }
var ( var (

View File

@ -410,6 +410,15 @@ message DeviceProfile {
// //
// If set to true, it means that the device is allowed to use roaming. // If set to true, it means that the device is allowed to use roaming.
bool allow_roaming = 52; bool allow_roaming = 52;
// RX1 Delay.
//
// This makes it possible to override the system RX1 Delay. Please note that
// this values only has effect in case it is higher than the system value.
// In other words, it can be used to increase the RX1 Delay but not to decrease
// it.
// Valid options are 1 - 15 (0 = always use system RX1 Delay).
uint32 rx1_delay = 53;
} }
message Measurement { message Measurement {

View File

@ -410,6 +410,15 @@ message DeviceProfile {
// //
// If set to true, it means that the device is allowed to use roaming. // If set to true, it means that the device is allowed to use roaming.
bool allow_roaming = 52; bool allow_roaming = 52;
// RX1 Delay.
//
// This makes it possible to override the system RX1 Delay. Please note that
// this values only has effect in case it is higher than the system value.
// In other words, it can be used to increase the RX1 Delay but not to decrease
// it.
// Valid options are 1 - 15 (0 = always use system RX1 Delay).
uint32 rx1_delay = 53;
} }
message Measurement { message Measurement {

View File

@ -0,0 +1,2 @@
alter table device_profile
drop column rx1_delay;

View File

@ -0,0 +1,5 @@
alter table device_profile
add column rx1_delay smallint not null default 0;
alter table device_profile
alter column rx1_delay drop default;

View File

@ -113,6 +113,7 @@ impl DeviceProfileService for DeviceProfile {
as i16, as i16,
relay_overall_limit_bucket_size: req_dp.relay_overall_limit_bucket_size as i16, relay_overall_limit_bucket_size: req_dp.relay_overall_limit_bucket_size as i16,
allow_roaming: req_dp.allow_roaming, allow_roaming: req_dp.allow_roaming,
rx1_delay: req_dp.rx1_delay as i16,
..Default::default() ..Default::default()
}; };
@ -214,6 +215,7 @@ impl DeviceProfileService for DeviceProfile {
as u32, as u32,
relay_overall_limit_bucket_size: dp.relay_overall_limit_bucket_size as u32, relay_overall_limit_bucket_size: dp.relay_overall_limit_bucket_size as u32,
allow_roaming: dp.allow_roaming, allow_roaming: dp.allow_roaming,
rx1_delay: dp.rx1_delay as u32,
}), }),
created_at: Some(helpers::datetime_to_prost_timestamp(&dp.created_at)), created_at: Some(helpers::datetime_to_prost_timestamp(&dp.created_at)),
updated_at: Some(helpers::datetime_to_prost_timestamp(&dp.updated_at)), updated_at: Some(helpers::datetime_to_prost_timestamp(&dp.updated_at)),
@ -313,6 +315,7 @@ impl DeviceProfileService for DeviceProfile {
as i16, as i16,
relay_overall_limit_bucket_size: req_dp.relay_overall_limit_bucket_size as i16, relay_overall_limit_bucket_size: req_dp.relay_overall_limit_bucket_size as i16,
allow_roaming: req_dp.allow_roaming, allow_roaming: req_dp.allow_roaming,
rx1_delay: req_dp.rx1_delay as i16,
..Default::default() ..Default::default()
}) })
.await .await

View File

@ -1,3 +1,4 @@
use std::cmp;
use std::collections::HashMap; use std::collections::HashMap;
use std::sync::Arc; use std::sync::Arc;
use std::time::Duration; use std::time::Duration;
@ -1437,9 +1438,14 @@ impl Data {
self.mac_commands.push(set); self.mac_commands.push(set);
} }
let rx1_delay = ds.rx1_delay as u8; let dev_rx1_delay = ds.rx1_delay as u8;
if rx1_delay != self.network_conf.rx1_delay { let req_rx1_delay = cmp::max(
let set = maccommand::rx_timing_setup::request(self.network_conf.rx1_delay); self.network_conf.rx1_delay,
self.device_profile.rx1_delay as u8,
);
if dev_rx1_delay != req_rx1_delay {
let set = maccommand::rx_timing_setup::request(req_rx1_delay);
mac_command::set_pending(&self.device.dev_eui, lrwn::CID::RxTimingSetupReq, &set) mac_command::set_pending(&self.device.dev_eui, lrwn::CID::RxTimingSetupReq, &set)
.await?; .await?;
self.mac_commands.push(set); self.mac_commands.push(set);

View File

@ -73,6 +73,7 @@ pub struct DeviceProfile {
pub relay_global_uplink_limit_bucket_size: i16, pub relay_global_uplink_limit_bucket_size: i16,
pub relay_overall_limit_bucket_size: i16, pub relay_overall_limit_bucket_size: i16,
pub allow_roaming: bool, pub allow_roaming: bool,
pub rx1_delay: i16,
} }
impl DeviceProfile { impl DeviceProfile {
@ -80,6 +81,11 @@ impl DeviceProfile {
if self.name.is_empty() { if self.name.is_empty() {
return Err(Error::Validation("name is not set".into())); return Err(Error::Validation("name is not set".into()));
} }
if self.rx1_delay < 0 || self.rx1_delay > 15 {
return Err(Error::Validation("RX1 Delay must be between 0 - 15".into()));
}
Ok(()) Ok(())
} }
} }
@ -143,6 +149,7 @@ impl Default for DeviceProfile {
relay_global_uplink_limit_bucket_size: 0, relay_global_uplink_limit_bucket_size: 0,
relay_overall_limit_bucket_size: 0, relay_overall_limit_bucket_size: 0,
allow_roaming: false, allow_roaming: false,
rx1_delay: 0,
} }
} }
} }
@ -279,6 +286,7 @@ pub async fn update(dp: DeviceProfile) -> Result<DeviceProfile, Error> {
.eq(&dp.relay_global_uplink_limit_bucket_size), .eq(&dp.relay_global_uplink_limit_bucket_size),
device_profile::relay_overall_limit_bucket_size.eq(&dp.relay_overall_limit_bucket_size), device_profile::relay_overall_limit_bucket_size.eq(&dp.relay_overall_limit_bucket_size),
device_profile::allow_roaming.eq(&dp.allow_roaming), device_profile::allow_roaming.eq(&dp.allow_roaming),
device_profile::rx1_delay.eq(&dp.rx1_delay),
)) ))
.get_result(&mut get_async_db_conn().await?) .get_result(&mut get_async_db_conn().await?)
.await .await

View File

@ -143,6 +143,7 @@ diesel::table! {
relay_global_uplink_limit_bucket_size -> Int2, relay_global_uplink_limit_bucket_size -> Int2,
relay_overall_limit_bucket_size -> Int2, relay_overall_limit_bucket_size -> Int2,
allow_roaming -> Bool, allow_roaming -> Bool,
rx1_delay -> Int2,
} }
} }

View File

@ -172,7 +172,7 @@ async fn test_gateway_filtering() {
}), }),
mic: Some([48, 94, 26, 239]), mic: Some([48, 94, 26, 239]),
}, },
assert: vec![assert::f_cnt_up(dev.dev_eui.clone(), 8)], assert: vec![assert::f_cnt_up(dev.dev_eui, 8)],
}, },
Test { Test {
name: "private gateway other tenant".into(), name: "private gateway other tenant".into(),
@ -337,7 +337,7 @@ async fn test_region_config_id_filtering() {
}), }),
mic: Some([48, 94, 26, 239]), mic: Some([48, 94, 26, 239]),
}, },
assert: vec![assert::f_cnt_up(dev.dev_eui.clone(), 8)], assert: vec![assert::f_cnt_up(dev.dev_eui, 8)],
}, },
Test { Test {
name: "non-matching configuration id".into(), name: "non-matching configuration id".into(),
@ -364,7 +364,7 @@ async fn test_region_config_id_filtering() {
}), }),
mic: Some([48, 94, 26, 239]), mic: Some([48, 94, 26, 239]),
}, },
assert: vec![assert::f_cnt_up(dev.dev_eui.clone(), 7)], assert: vec![assert::f_cnt_up(dev.dev_eui, 7)],
}, },
]; ];
@ -858,8 +858,8 @@ async fn test_lorawan_10_skip_f_cnt() {
f_port: 1, f_port: 1,
..Default::default() ..Default::default()
}), }),
assert::f_cnt_up(dev.dev_eui.clone(), 8), assert::f_cnt_up(dev.dev_eui, 8),
assert::n_f_cnt_down(dev.dev_eui.clone(), 5), assert::n_f_cnt_down(dev.dev_eui, 5),
], ],
}, },
Test { Test {
@ -907,8 +907,8 @@ async fn test_lorawan_10_skip_f_cnt() {
f_port: 1, f_port: 1,
..Default::default() ..Default::default()
}), }),
assert::f_cnt_up(dev.dev_eui.clone(), 1), assert::f_cnt_up(dev.dev_eui, 1),
assert::n_f_cnt_down(dev.dev_eui.clone(), 5), assert::n_f_cnt_down(dev.dev_eui, 5),
], ],
}, },
]; ];
@ -1032,8 +1032,8 @@ async fn test_lorawan_10_device_disabled() {
}, },
assert: vec![ assert: vec![
assert::no_uplink_event(), assert::no_uplink_event(),
assert::f_cnt_up(dev.dev_eui.clone(), 7), assert::f_cnt_up(dev.dev_eui, 7),
assert::n_f_cnt_down(dev.dev_eui.clone(), 5), assert::n_f_cnt_down(dev.dev_eui, 5),
], ],
}]; }];
@ -1165,8 +1165,8 @@ async fn test_lorawan_10_uplink() {
mic: Some([104, 147, 35, 121]), mic: Some([104, 147, 35, 121]),
}, },
assert: vec![ assert: vec![
assert::f_cnt_up(dev.dev_eui.clone(), 11), assert::f_cnt_up(dev.dev_eui, 11),
assert::n_f_cnt_down(dev.dev_eui.clone(), 5), assert::n_f_cnt_down(dev.dev_eui, 5),
assert::uplink_event(integration_pb::UplinkEvent { assert::uplink_event(integration_pb::UplinkEvent {
device_info: Some(integration_pb::DeviceInfo { device_info: Some(integration_pb::DeviceInfo {
tenant_name: t.name.clone(), tenant_name: t.name.clone(),
@ -1237,8 +1237,8 @@ async fn test_lorawan_10_uplink() {
mic: Some([104, 147, 35, 121]), mic: Some([104, 147, 35, 121]),
}, },
assert: vec![ assert: vec![
assert::f_cnt_up(dev.dev_eui.clone(), 11), assert::f_cnt_up(dev.dev_eui, 11),
assert::n_f_cnt_down(dev.dev_eui.clone(), 5), assert::n_f_cnt_down(dev.dev_eui, 5),
assert::uplink_event(integration_pb::UplinkEvent { assert::uplink_event(integration_pb::UplinkEvent {
device_info: Some(integration_pb::DeviceInfo { device_info: Some(integration_pb::DeviceInfo {
tenant_name: t.name.clone(), tenant_name: t.name.clone(),
@ -1267,7 +1267,7 @@ async fn test_lorawan_10_uplink() {
dev_eui: dev.dev_eui, dev_eui: dev.dev_eui,
device_queue_items: vec![device_queue::DeviceQueueItem { device_queue_items: vec![device_queue::DeviceQueueItem {
id: Uuid::nil(), id: Uuid::nil(),
dev_eui: dev.dev_eui.clone(), dev_eui: dev.dev_eui,
f_port: 1, f_port: 1,
f_cnt_down: Some(4), f_cnt_down: Some(4),
is_pending: true, is_pending: true,
@ -1299,8 +1299,8 @@ async fn test_lorawan_10_uplink() {
mic: Some([132, 250, 228, 10]), mic: Some([132, 250, 228, 10]),
}, },
assert: vec![ assert: vec![
assert::f_cnt_up(dev.dev_eui.clone(), 11), assert::f_cnt_up(dev.dev_eui, 11),
assert::n_f_cnt_down(dev.dev_eui.clone(), 5), assert::n_f_cnt_down(dev.dev_eui, 5),
assert::ack_event(integration_pb::AckEvent { assert::ack_event(integration_pb::AckEvent {
device_info: Some(integration_pb::DeviceInfo { device_info: Some(integration_pb::DeviceInfo {
tenant_name: t.name.clone(), tenant_name: t.name.clone(),
@ -1367,8 +1367,8 @@ async fn test_lorawan_10_uplink() {
mic: Some([160, 195, 68, 8]), mic: Some([160, 195, 68, 8]),
}, },
assert: vec![ assert: vec![
assert::f_cnt_up(dev.dev_eui.clone(), 11), assert::f_cnt_up(dev.dev_eui, 11),
assert::n_f_cnt_down(dev.dev_eui.clone(), 5), assert::n_f_cnt_down(dev.dev_eui, 5),
assert::uplink_event(integration_pb::UplinkEvent { assert::uplink_event(integration_pb::UplinkEvent {
device_info: Some(integration_pb::DeviceInfo { device_info: Some(integration_pb::DeviceInfo {
tenant_name: t.name.clone(), tenant_name: t.name.clone(),
@ -1418,8 +1418,8 @@ async fn test_lorawan_10_uplink() {
mic: Some([69, 90, 200, 95]), mic: Some([69, 90, 200, 95]),
}, },
assert: vec![ assert: vec![
assert::f_cnt_up(dev.dev_eui.clone(), 11), assert::f_cnt_up(dev.dev_eui, 11),
assert::n_f_cnt_down(dev.dev_eui.clone(), 5), assert::n_f_cnt_down(dev.dev_eui, 5),
assert::uplink_event(integration_pb::UplinkEvent { assert::uplink_event(integration_pb::UplinkEvent {
device_info: Some(integration_pb::DeviceInfo { device_info: Some(integration_pb::DeviceInfo {
tenant_name: t.name.clone(), tenant_name: t.name.clone(),
@ -1530,8 +1530,8 @@ async fn test_lorawan_10_uplink() {
mic: Some([210, 52, 52, 94]), mic: Some([210, 52, 52, 94]),
}, },
assert: vec![ assert: vec![
assert::f_cnt_up(dev.dev_eui.clone(), 11), assert::f_cnt_up(dev.dev_eui, 11),
assert::n_f_cnt_down(dev.dev_eui.clone(), 5), assert::n_f_cnt_down(dev.dev_eui, 5),
assert::uplink_event(integration_pb::UplinkEvent { assert::uplink_event(integration_pb::UplinkEvent {
device_info: Some(integration_pb::DeviceInfo { device_info: Some(integration_pb::DeviceInfo {
tenant_name: t.name.clone(), tenant_name: t.name.clone(),
@ -1667,9 +1667,9 @@ async fn test_lorawan_10_uplink() {
mic: Some([104, 147, 35, 121]), mic: Some([104, 147, 35, 121]),
}, },
assert: vec![ assert: vec![
assert::f_cnt_up(dev.dev_eui.clone(), 11), assert::f_cnt_up(dev.dev_eui, 11),
assert::n_f_cnt_down(dev.dev_eui.clone(), 5), assert::n_f_cnt_down(dev.dev_eui, 5),
assert::scheduler_run_after_set(dev.dev_eui.clone()), assert::scheduler_run_after_set(dev.dev_eui),
], ],
}, },
]; ];
@ -1897,7 +1897,7 @@ async fn test_lorawan_10_end_to_end_enc() {
dev_eui: dev.dev_eui, dev_eui: dev.dev_eui,
device_queue_items: vec![device_queue::DeviceQueueItem { device_queue_items: vec![device_queue::DeviceQueueItem {
id: Uuid::nil(), id: Uuid::nil(),
dev_eui: dev.dev_eui.clone(), dev_eui: dev.dev_eui,
f_port: 1, f_port: 1,
data: vec![1, 2, 3, 4], data: vec![1, 2, 3, 4],
f_cnt_down: Some(10), f_cnt_down: Some(10),
@ -1954,8 +1954,8 @@ async fn test_lorawan_10_end_to_end_enc() {
}), }),
..Default::default() ..Default::default()
}), }),
assert::f_cnt_up(dev.dev_eui.clone(), 11), assert::f_cnt_up(dev.dev_eui, 11),
assert::n_f_cnt_down(dev.dev_eui.clone(), 5), assert::n_f_cnt_down(dev.dev_eui, 5),
assert::downlink_phy_payloads(vec![ assert::downlink_phy_payloads(vec![
lrwn::PhyPayload { lrwn::PhyPayload {
mhdr: lrwn::MHDR { mhdr: lrwn::MHDR {
@ -2131,8 +2131,8 @@ async fn test_lorawan_11_uplink() {
mic: Some([104, 147, 104, 147]), mic: Some([104, 147, 104, 147]),
}, },
assert: vec![ assert: vec![
assert::f_cnt_up(dev.dev_eui.clone(), 11), assert::f_cnt_up(dev.dev_eui, 11),
assert::n_f_cnt_down(dev.dev_eui.clone(), 5), assert::n_f_cnt_down(dev.dev_eui, 5),
assert::uplink_event(integration_pb::UplinkEvent { assert::uplink_event(integration_pb::UplinkEvent {
device_info: Some(integration_pb::DeviceInfo { device_info: Some(integration_pb::DeviceInfo {
tenant_name: t.name.clone(), tenant_name: t.name.clone(),
@ -2161,7 +2161,7 @@ async fn test_lorawan_11_uplink() {
dev_eui: dev.dev_eui, dev_eui: dev.dev_eui,
device_queue_items: vec![device_queue::DeviceQueueItem { device_queue_items: vec![device_queue::DeviceQueueItem {
id: Uuid::nil(), id: Uuid::nil(),
dev_eui: dev.dev_eui.clone(), dev_eui: dev.dev_eui,
f_port: 1, f_port: 1,
f_cnt_down: Some(4), f_cnt_down: Some(4),
is_pending: true, is_pending: true,
@ -2193,8 +2193,8 @@ async fn test_lorawan_11_uplink() {
mic: Some([76, 46, 132, 250]), mic: Some([76, 46, 132, 250]),
}, },
assert: vec![ assert: vec![
assert::f_cnt_up(dev.dev_eui.clone(), 11), assert::f_cnt_up(dev.dev_eui, 11),
assert::n_f_cnt_down(dev.dev_eui.clone(), 5), assert::n_f_cnt_down(dev.dev_eui, 5),
assert::ack_event(integration_pb::AckEvent { assert::ack_event(integration_pb::AckEvent {
device_info: Some(integration_pb::DeviceInfo { device_info: Some(integration_pb::DeviceInfo {
tenant_name: t.name.clone(), tenant_name: t.name.clone(),
@ -2275,7 +2275,7 @@ async fn test_lorawan_10_rx_delay() {
.await .await
.unwrap(); .unwrap();
let dp = device_profile::create(device_profile::DeviceProfile { let mut dp = device_profile::create(device_profile::DeviceProfile {
name: "dp".into(), name: "dp".into(),
tenant_id: t.id.clone(), tenant_id: t.id.clone(),
region: lrwn::region::CommonName::EU868, region: lrwn::region::CommonName::EU868,
@ -2368,8 +2368,8 @@ async fn test_lorawan_10_rx_delay() {
mic: Some([210, 52, 52, 94]), mic: Some([210, 52, 52, 94]),
}, },
assert: vec![ assert: vec![
assert::f_cnt_up(dev.dev_eui.clone(), 11), assert::f_cnt_up(dev.dev_eui, 11),
assert::n_f_cnt_down(dev.dev_eui.clone(), 5), assert::n_f_cnt_down(dev.dev_eui, 5),
assert::uplink_event(integration_pb::UplinkEvent { assert::uplink_event(integration_pb::UplinkEvent {
device_info: Some(integration_pb::DeviceInfo { device_info: Some(integration_pb::DeviceInfo {
tenant_name: t.name.clone(), tenant_name: t.name.clone(),
@ -2457,6 +2457,238 @@ async fn test_lorawan_10_rx_delay() {
for tst in &tests { for tst in &tests {
run_test(tst).await; run_test(tst).await;
} }
// Test with RX1 Delay decreased in device-profile.
// This should make any difference as we only accept users to increase the RX1 Delay.
dp.rx1_delay = 2;
let mut dp = device_profile::update(dp).await.unwrap();
let tests = vec![Test {
name: "confirmed uplink without payload (dp.rx1_delay=2, used rx_delay = 3)".into(),
dev_eui: dev.dev_eui,
device_queue_items: vec![],
before_func: None,
after_func: None,
device_session: Some(ds.clone()),
tx_info: tx_info.clone(),
rx_info: rx_info.clone(),
phy_payload: lrwn::PhyPayload {
mhdr: lrwn::MHDR {
m_type: lrwn::MType::ConfirmedDataUp,
major: lrwn::Major::LoRaWANR1,
},
payload: lrwn::Payload::MACPayload(lrwn::MACPayload {
fhdr: lrwn::FHDR {
devaddr: lrwn::DevAddr::from_be_bytes([1, 2, 3, 4]),
f_cnt: 10,
..Default::default()
},
f_port: Some(1),
frm_payload: None,
}),
mic: Some([210, 52, 52, 94]),
},
assert: vec![
assert::f_cnt_up(dev.dev_eui, 11),
assert::n_f_cnt_down(dev.dev_eui, 5),
assert::uplink_event(integration_pb::UplinkEvent {
device_info: Some(integration_pb::DeviceInfo {
tenant_name: t.name.clone(),
tenant_id: t.id.to_string(),
application_name: app.name.clone(),
application_id: app.id.to_string(),
device_profile_name: dp.name.clone(),
device_profile_id: dp.id.to_string(),
device_name: dev.name.clone(),
dev_eui: dev.dev_eui.to_string(),
..Default::default()
}),
dev_addr: "01020304".into(),
tx_info: Some(tx_info.clone()),
rx_info: vec![rx_info.clone()],
f_cnt: 10,
f_port: 1,
confirmed: true,
dr: 0,
..Default::default()
}),
assert::downlink_frame(gw::DownlinkFrame {
gateway_id: "0102030405060708".into(),
items: vec![
gw::DownlinkFrameItem {
phy_payload: vec![96, 4, 3, 2, 1, 160, 5, 0, 161, 179, 218, 104],
tx_info_legacy: None,
tx_info: Some(gw::DownlinkTxInfo {
frequency: 868100000,
power: 16,
modulation: Some(gw::Modulation {
parameters: Some(gw::modulation::Parameters::Lora(
gw::LoraModulationInfo {
bandwidth: 125000,
spreading_factor: 12,
code_rate: gw::CodeRate::Cr45.into(),
polarization_inversion: true,
..Default::default()
},
)),
}),
timing: Some(gw::Timing {
parameters: Some(gw::timing::Parameters::Delay(
gw::DelayTimingInfo {
delay: Some(Duration::from_secs(3).into()),
},
)),
}),
..Default::default()
}),
},
gw::DownlinkFrameItem {
phy_payload: vec![96, 4, 3, 2, 1, 160, 5, 0, 161, 179, 218, 104],
tx_info_legacy: None,
tx_info: Some(gw::DownlinkTxInfo {
frequency: 869525000,
power: 29,
modulation: Some(gw::Modulation {
parameters: Some(gw::modulation::Parameters::Lora(
gw::LoraModulationInfo {
bandwidth: 125000,
spreading_factor: 12,
code_rate: gw::CodeRate::Cr45.into(),
polarization_inversion: true,
..Default::default()
},
)),
}),
timing: Some(gw::Timing {
parameters: Some(gw::timing::Parameters::Delay(
gw::DelayTimingInfo {
delay: Some(Duration::from_secs(4).into()),
},
)),
}),
..Default::default()
}),
},
],
..Default::default()
}),
],
}];
for tst in &tests {
run_test(tst).await;
}
// Test with RX1 Delay increased in device-profile.
// This should trigger a mac-command.
dp.rx1_delay = 5;
let dp = device_profile::update(dp).await.unwrap();
let tests = vec![Test {
name: "confirmed uplink without payload (dp.rx1_delay=5, expects mac-command)".into(),
dev_eui: dev.dev_eui,
device_queue_items: vec![],
before_func: None,
after_func: None,
device_session: Some(ds.clone()),
tx_info: tx_info.clone(),
rx_info: rx_info.clone(),
phy_payload: lrwn::PhyPayload {
mhdr: lrwn::MHDR {
m_type: lrwn::MType::ConfirmedDataUp,
major: lrwn::Major::LoRaWANR1,
},
payload: lrwn::Payload::MACPayload(lrwn::MACPayload {
fhdr: lrwn::FHDR {
devaddr: lrwn::DevAddr::from_be_bytes([1, 2, 3, 4]),
f_cnt: 10,
..Default::default()
},
f_port: Some(1),
frm_payload: None,
}),
mic: Some([210, 52, 52, 94]),
},
assert: vec![
assert::f_cnt_up(dev.dev_eui, 11),
assert::n_f_cnt_down(dev.dev_eui, 5),
assert::uplink_event(integration_pb::UplinkEvent {
device_info: Some(integration_pb::DeviceInfo {
tenant_name: t.name.clone(),
tenant_id: t.id.to_string(),
application_name: app.name.clone(),
application_id: app.id.to_string(),
device_profile_name: dp.name.clone(),
device_profile_id: dp.id.to_string(),
device_name: dev.name.clone(),
dev_eui: dev.dev_eui.to_string(),
..Default::default()
}),
dev_addr: "01020304".into(),
tx_info: Some(tx_info.clone()),
rx_info: vec![rx_info.clone()],
f_cnt: 10,
f_port: 1,
confirmed: true,
dr: 0,
..Default::default()
}),
assert::downlink_phy_payloads(vec![
lrwn::PhyPayload {
mhdr: lrwn::MHDR {
m_type: lrwn::MType::UnconfirmedDataDown,
major: lrwn::Major::LoRaWANR1,
},
payload: lrwn::Payload::MACPayload(lrwn::MACPayload {
fhdr: lrwn::FHDR {
devaddr: lrwn::DevAddr::from_be_bytes([1, 2, 3, 4]),
f_cnt: 5,
f_ctrl: lrwn::FCtrl {
adr: true,
ack: true,
f_opts_len: 2,
..Default::default()
},
f_opts: lrwn::MACCommandSet::new(vec![lrwn::MACCommand::Raw(vec![
8, 5,
])]),
},
f_port: None,
frm_payload: None,
}),
mic: Some([37, 72, 226, 133]),
},
lrwn::PhyPayload {
mhdr: lrwn::MHDR {
m_type: lrwn::MType::UnconfirmedDataDown,
major: lrwn::Major::LoRaWANR1,
},
payload: lrwn::Payload::MACPayload(lrwn::MACPayload {
fhdr: lrwn::FHDR {
devaddr: lrwn::DevAddr::from_be_bytes([1, 2, 3, 4]),
f_cnt: 5,
f_ctrl: lrwn::FCtrl {
adr: true,
ack: true,
f_opts_len: 2,
..Default::default()
},
f_opts: lrwn::MACCommandSet::new(vec![lrwn::MACCommand::Raw(vec![
8, 5,
])]),
},
f_port: None,
frm_payload: None,
}),
mic: Some([37, 72, 226, 133]),
},
]),
],
}];
for tst in &tests {
run_test(tst).await;
}
} }
#[tokio::test] #[tokio::test]
@ -2596,8 +2828,8 @@ async fn test_lorawan_10_mac_commands() {
mic: Some([122, 152, 152, 220]), mic: Some([122, 152, 152, 220]),
}, },
assert: vec![ assert: vec![
assert::f_cnt_up(dev.dev_eui.clone(), 11), assert::f_cnt_up(dev.dev_eui, 11),
assert::n_f_cnt_down(dev.dev_eui.clone(), 5), assert::n_f_cnt_down(dev.dev_eui, 5),
assert::downlink_phy_payloads(vec![ assert::downlink_phy_payloads(vec![
lrwn::PhyPayload { lrwn::PhyPayload {
mhdr: lrwn::MHDR { mhdr: lrwn::MHDR {
@ -2654,7 +2886,7 @@ async fn test_lorawan_10_mac_commands() {
dev_eui: dev.dev_eui, dev_eui: dev.dev_eui,
device_queue_items: vec![device_queue::DeviceQueueItem { device_queue_items: vec![device_queue::DeviceQueueItem {
id: Uuid::nil(), id: Uuid::nil(),
dev_eui: dev.dev_eui.clone(), dev_eui: dev.dev_eui,
f_port: 1, f_port: 1,
data: vec![1, 2, 3, 4], data: vec![1, 2, 3, 4],
..Default::default() ..Default::default()
@ -2695,8 +2927,8 @@ async fn test_lorawan_10_mac_commands() {
mic: Some([122, 152, 152, 220]), mic: Some([122, 152, 152, 220]),
}, },
assert: vec![ assert: vec![
assert::f_cnt_up(dev.dev_eui.clone(), 11), assert::f_cnt_up(dev.dev_eui, 11),
assert::n_f_cnt_down(dev.dev_eui.clone(), 5), assert::n_f_cnt_down(dev.dev_eui, 5),
assert::downlink_phy_payloads(vec![ assert::downlink_phy_payloads(vec![
lrwn::PhyPayload { lrwn::PhyPayload {
mhdr: lrwn::MHDR { mhdr: lrwn::MHDR {
@ -2778,7 +3010,7 @@ async fn test_lorawan_10_mac_commands() {
mic: Some([0xb6, 0x20, 0xd2, 0x14]), mic: Some([0xb6, 0x20, 0xd2, 0x14]),
}, },
assert: vec![ assert: vec![
assert::f_cnt_up(dev.dev_eui.clone(), 11), assert::f_cnt_up(dev.dev_eui, 11),
assert::downlink_phy_payloads(vec![ assert::downlink_phy_payloads(vec![
lrwn::PhyPayload { lrwn::PhyPayload {
mhdr: lrwn::MHDR { mhdr: lrwn::MHDR {
@ -2965,7 +3197,7 @@ async fn test_lorawan_11_mac_commands() {
rx_info: rx_info.clone(), rx_info: rx_info.clone(),
phy_payload: phy, phy_payload: phy,
assert: vec![ assert: vec![
assert::f_cnt_up(dev.dev_eui.clone(), 11), assert::f_cnt_up(dev.dev_eui, 11),
assert::downlink_phy_payloads(vec![ assert::downlink_phy_payloads(vec![
lrwn::PhyPayload { lrwn::PhyPayload {
mhdr: lrwn::MHDR { mhdr: lrwn::MHDR {
@ -3120,7 +3352,7 @@ async fn test_lorawan_10_device_queue() {
dev_eui: dev.dev_eui, dev_eui: dev.dev_eui,
device_queue_items: vec![device_queue::DeviceQueueItem { device_queue_items: vec![device_queue::DeviceQueueItem {
id: Uuid::nil(), id: Uuid::nil(),
dev_eui: dev.dev_eui.clone(), dev_eui: dev.dev_eui,
f_port: 10, f_port: 10,
data: vec![1, 2, 3, 4], data: vec![1, 2, 3, 4],
..Default::default() ..Default::default()
@ -3147,8 +3379,8 @@ async fn test_lorawan_10_device_queue() {
mic: Some([160, 195, 68, 8]), mic: Some([160, 195, 68, 8]),
}, },
assert: vec![ assert: vec![
assert::f_cnt_up(dev.dev_eui.clone(), 11), assert::f_cnt_up(dev.dev_eui, 11),
assert::n_f_cnt_down(dev.dev_eui.clone(), 5), assert::n_f_cnt_down(dev.dev_eui, 5),
assert::downlink_phy_payloads(vec![ assert::downlink_phy_payloads(vec![
lrwn::PhyPayload { lrwn::PhyPayload {
mhdr: lrwn::MHDR { mhdr: lrwn::MHDR {
@ -3199,14 +3431,14 @@ async fn test_lorawan_10_device_queue() {
device_queue_items: vec![ device_queue_items: vec![
device_queue::DeviceQueueItem { device_queue::DeviceQueueItem {
id: Uuid::new_v4(), id: Uuid::new_v4(),
dev_eui: dev.dev_eui.clone(), dev_eui: dev.dev_eui,
f_port: 10, f_port: 10,
data: vec![1, 2, 3, 4], data: vec![1, 2, 3, 4],
..Default::default() ..Default::default()
}, },
device_queue::DeviceQueueItem { device_queue::DeviceQueueItem {
id: Uuid::new_v4(), id: Uuid::new_v4(),
dev_eui: dev.dev_eui.clone(), dev_eui: dev.dev_eui,
f_port: 10, f_port: 10,
data: vec![2, 2, 3, 4], data: vec![2, 2, 3, 4],
..Default::default() ..Default::default()
@ -3234,8 +3466,8 @@ async fn test_lorawan_10_device_queue() {
mic: Some([160, 195, 68, 8]), mic: Some([160, 195, 68, 8]),
}, },
assert: vec![ assert: vec![
assert::f_cnt_up(dev.dev_eui.clone(), 11), assert::f_cnt_up(dev.dev_eui, 11),
assert::n_f_cnt_down(dev.dev_eui.clone(), 5), assert::n_f_cnt_down(dev.dev_eui, 5),
assert::downlink_phy_payloads(vec![ assert::downlink_phy_payloads(vec![
lrwn::PhyPayload { lrwn::PhyPayload {
mhdr: lrwn::MHDR { mhdr: lrwn::MHDR {
@ -3289,7 +3521,7 @@ async fn test_lorawan_10_device_queue() {
dev_eui: dev.dev_eui, dev_eui: dev.dev_eui,
device_queue_items: vec![device_queue::DeviceQueueItem { device_queue_items: vec![device_queue::DeviceQueueItem {
id: Uuid::nil(), id: Uuid::nil(),
dev_eui: dev.dev_eui.clone(), dev_eui: dev.dev_eui,
f_port: 10, f_port: 10,
data: vec![1, 2, 3, 4], data: vec![1, 2, 3, 4],
confirmed: true, confirmed: true,
@ -3317,8 +3549,8 @@ async fn test_lorawan_10_device_queue() {
mic: Some([160, 195, 68, 8]), mic: Some([160, 195, 68, 8]),
}, },
assert: vec![ assert: vec![
assert::f_cnt_up(dev.dev_eui.clone(), 11), assert::f_cnt_up(dev.dev_eui, 11),
assert::n_f_cnt_down(dev.dev_eui.clone(), 5), assert::n_f_cnt_down(dev.dev_eui, 5),
assert::downlink_phy_payloads(vec![ assert::downlink_phy_payloads(vec![
lrwn::PhyPayload { lrwn::PhyPayload {
mhdr: lrwn::MHDR { mhdr: lrwn::MHDR {
@ -3368,7 +3600,7 @@ async fn test_lorawan_10_device_queue() {
dev_eui: dev.dev_eui, dev_eui: dev.dev_eui,
device_queue_items: vec![device_queue::DeviceQueueItem { device_queue_items: vec![device_queue::DeviceQueueItem {
id: Uuid::nil(), id: Uuid::nil(),
dev_eui: dev.dev_eui.clone(), dev_eui: dev.dev_eui,
f_port: 10, f_port: 10,
data: vec![0; 52], data: vec![0; 52],
..Default::default() ..Default::default()
@ -3395,7 +3627,7 @@ async fn test_lorawan_10_device_queue() {
mic: Some([160, 195, 68, 8]), mic: Some([160, 195, 68, 8]),
}, },
assert: vec![ assert: vec![
assert::f_cnt_up(dev.dev_eui.clone(), 11), assert::f_cnt_up(dev.dev_eui, 11),
assert::no_downlink_frame(), assert::no_downlink_frame(),
assert::integration_log(vec!["Device queue-item discarded because it exceeds the max. payload size".into()]), assert::integration_log(vec!["Device queue-item discarded because it exceeds the max. payload size".into()]),
], ],
@ -3405,7 +3637,7 @@ async fn test_lorawan_10_device_queue() {
dev_eui: dev.dev_eui, dev_eui: dev.dev_eui,
device_queue_items: vec![device_queue::DeviceQueueItem { device_queue_items: vec![device_queue::DeviceQueueItem {
id: Uuid::nil(), id: Uuid::nil(),
dev_eui: dev.dev_eui.clone(), dev_eui: dev.dev_eui,
f_port: 10, f_port: 10,
data: vec![0; 51], data: vec![0; 51],
..Default::default() ..Default::default()
@ -3437,7 +3669,7 @@ async fn test_lorawan_10_device_queue() {
mic: Some([106, 14, 124, 212]), mic: Some([106, 14, 124, 212]),
}, },
assert: vec![ assert: vec![
assert::f_cnt_up(dev.dev_eui.clone(), 11), assert::f_cnt_up(dev.dev_eui, 11),
assert::downlink_phy_payloads(vec![ assert::downlink_phy_payloads(vec![
lrwn::PhyPayload { lrwn::PhyPayload {
mhdr: lrwn::MHDR { mhdr: lrwn::MHDR {
@ -3598,7 +3830,7 @@ async fn test_lorawan_11_device_queue() {
dev_eui: dev.dev_eui, dev_eui: dev.dev_eui,
device_queue_items: vec![device_queue::DeviceQueueItem { device_queue_items: vec![device_queue::DeviceQueueItem {
id: Uuid::nil(), id: Uuid::nil(),
dev_eui: dev.dev_eui.clone(), dev_eui: dev.dev_eui,
f_port: 10, f_port: 10,
data: vec![1, 2, 3, 4], data: vec![1, 2, 3, 4],
..Default::default() ..Default::default()
@ -3625,8 +3857,8 @@ async fn test_lorawan_11_device_queue() {
mic: Some([160, 195, 160, 195]), mic: Some([160, 195, 160, 195]),
}, },
assert: vec![ assert: vec![
assert::f_cnt_up(dev.dev_eui.clone(), 11), assert::f_cnt_up(dev.dev_eui, 11),
assert::n_f_cnt_down(dev.dev_eui.clone(), 5), assert::n_f_cnt_down(dev.dev_eui, 5),
assert::downlink_phy_payloads(vec![ assert::downlink_phy_payloads(vec![
lrwn::PhyPayload { lrwn::PhyPayload {
mhdr: lrwn::MHDR { mhdr: lrwn::MHDR {
@ -3677,14 +3909,14 @@ async fn test_lorawan_11_device_queue() {
device_queue_items: vec![ device_queue_items: vec![
device_queue::DeviceQueueItem { device_queue::DeviceQueueItem {
id: Uuid::new_v4(), id: Uuid::new_v4(),
dev_eui: dev.dev_eui.clone(), dev_eui: dev.dev_eui,
f_port: 10, f_port: 10,
data: vec![1, 2, 3, 4], data: vec![1, 2, 3, 4],
..Default::default() ..Default::default()
}, },
device_queue::DeviceQueueItem { device_queue::DeviceQueueItem {
id: Uuid::new_v4(), id: Uuid::new_v4(),
dev_eui: dev.dev_eui.clone(), dev_eui: dev.dev_eui,
f_port: 10, f_port: 10,
data: vec![2, 2, 3, 4], data: vec![2, 2, 3, 4],
..Default::default() ..Default::default()
@ -3712,8 +3944,8 @@ async fn test_lorawan_11_device_queue() {
mic: Some([160, 195, 160, 195]), mic: Some([160, 195, 160, 195]),
}, },
assert: vec![ assert: vec![
assert::f_cnt_up(dev.dev_eui.clone(), 11), assert::f_cnt_up(dev.dev_eui, 11),
assert::n_f_cnt_down(dev.dev_eui.clone(), 5), assert::n_f_cnt_down(dev.dev_eui, 5),
assert::downlink_phy_payloads(vec![ assert::downlink_phy_payloads(vec![
lrwn::PhyPayload { lrwn::PhyPayload {
mhdr: lrwn::MHDR { mhdr: lrwn::MHDR {
@ -3767,7 +3999,7 @@ async fn test_lorawan_11_device_queue() {
dev_eui: dev.dev_eui, dev_eui: dev.dev_eui,
device_queue_items: vec![device_queue::DeviceQueueItem { device_queue_items: vec![device_queue::DeviceQueueItem {
id: Uuid::nil(), id: Uuid::nil(),
dev_eui: dev.dev_eui.clone(), dev_eui: dev.dev_eui,
f_port: 10, f_port: 10,
data: vec![1, 2, 3, 4], data: vec![1, 2, 3, 4],
confirmed: true, confirmed: true,
@ -3795,8 +4027,8 @@ async fn test_lorawan_11_device_queue() {
mic: Some([160, 195, 160, 195]), mic: Some([160, 195, 160, 195]),
}, },
assert: vec![ assert: vec![
assert::f_cnt_up(dev.dev_eui.clone(), 11), assert::f_cnt_up(dev.dev_eui, 11),
assert::n_f_cnt_down(dev.dev_eui.clone(), 5), assert::n_f_cnt_down(dev.dev_eui, 5),
assert::downlink_phy_payloads(vec![ assert::downlink_phy_payloads(vec![
lrwn::PhyPayload { lrwn::PhyPayload {
mhdr: lrwn::MHDR { mhdr: lrwn::MHDR {
@ -3846,7 +4078,7 @@ async fn test_lorawan_11_device_queue() {
dev_eui: dev.dev_eui, dev_eui: dev.dev_eui,
device_queue_items: vec![device_queue::DeviceQueueItem { device_queue_items: vec![device_queue::DeviceQueueItem {
id: Uuid::nil(), id: Uuid::nil(),
dev_eui: dev.dev_eui.clone(), dev_eui: dev.dev_eui,
f_port: 10, f_port: 10,
data: vec![0; 52], data: vec![0; 52],
..Default::default() ..Default::default()
@ -3873,7 +4105,7 @@ async fn test_lorawan_11_device_queue() {
mic: Some([160, 195, 160, 195]), mic: Some([160, 195, 160, 195]),
}, },
assert: vec![ assert: vec![
assert::f_cnt_up(dev.dev_eui.clone(), 11), assert::f_cnt_up(dev.dev_eui, 11),
assert::no_downlink_frame(), assert::no_downlink_frame(),
assert::integration_log(vec!["Device queue-item discarded because it exceeds the max. payload size".into()]), assert::integration_log(vec!["Device queue-item discarded because it exceeds the max. payload size".into()]),
], ],
@ -3883,7 +4115,7 @@ async fn test_lorawan_11_device_queue() {
dev_eui: dev.dev_eui, dev_eui: dev.dev_eui,
device_queue_items: vec![device_queue::DeviceQueueItem { device_queue_items: vec![device_queue::DeviceQueueItem {
id: Uuid::nil(), id: Uuid::nil(),
dev_eui: dev.dev_eui.clone(), dev_eui: dev.dev_eui,
f_port: 10, f_port: 10,
data: vec![0; 51], data: vec![0; 51],
..Default::default() ..Default::default()
@ -3917,7 +4149,7 @@ async fn test_lorawan_11_device_queue() {
mic: Some([204, 225, 204, 225]), mic: Some([204, 225, 204, 225]),
}, },
assert: vec![ assert: vec![
assert::f_cnt_up(dev.dev_eui.clone(), 11), assert::f_cnt_up(dev.dev_eui, 11),
assert::downlink_phy_payloads(vec![ assert::downlink_phy_payloads(vec![
lrwn::PhyPayload { lrwn::PhyPayload {
mhdr: lrwn::MHDR { mhdr: lrwn::MHDR {
@ -4121,8 +4353,8 @@ async fn test_lorawan_10_adr() {
mic: Some([187, 243, 244, 117]), mic: Some([187, 243, 244, 117]),
}, },
assert: vec![ assert: vec![
assert::f_cnt_up(dev.dev_eui.clone(), 11), assert::f_cnt_up(dev.dev_eui, 11),
assert::n_f_cnt_down(dev.dev_eui.clone(), 5), assert::n_f_cnt_down(dev.dev_eui, 5),
assert::downlink_phy_payloads_decoded_f_opts(vec![ assert::downlink_phy_payloads_decoded_f_opts(vec![
lrwn::PhyPayload { lrwn::PhyPayload {
mhdr: lrwn::MHDR { mhdr: lrwn::MHDR {
@ -4225,7 +4457,7 @@ async fn test_lorawan_10_adr() {
mic: Some([122, 152, 152, 220]), mic: Some([122, 152, 152, 220]),
}, },
assert: vec![ assert: vec![
assert::f_cnt_up(dev.dev_eui.clone(), 11), assert::f_cnt_up(dev.dev_eui, 11),
assert::no_downlink_frame(), assert::no_downlink_frame(),
], ],
}, },
@ -4234,7 +4466,7 @@ async fn test_lorawan_10_adr() {
dev_eui: dev.dev_eui, dev_eui: dev.dev_eui,
device_queue_items: vec![], device_queue_items: vec![],
before_func: Some(Box::new(move || { before_func: Some(Box::new(move || {
let dev_eui = dev.dev_eui.clone(); let dev_eui = dev.dev_eui;
Box::pin(async move { Box::pin(async move {
mac_command::set_pending( mac_command::set_pending(
&dev_eui, &dev_eui,
@ -4289,12 +4521,12 @@ async fn test_lorawan_10_adr() {
mic: Some([235, 224, 96, 3]), mic: Some([235, 224, 96, 3]),
}, },
assert: vec![ assert: vec![
assert::f_cnt_up(dev.dev_eui.clone(), 11), assert::f_cnt_up(dev.dev_eui, 11),
assert::n_f_cnt_down(dev.dev_eui.clone(), 5), assert::n_f_cnt_down(dev.dev_eui, 5),
assert::tx_power_index(dev.dev_eui.clone(), 3), assert::tx_power_index(dev.dev_eui, 3),
assert::dr(dev.dev_eui.clone(), 0), assert::dr(dev.dev_eui, 0),
assert::nb_trans(dev.dev_eui.clone(), 1), assert::nb_trans(dev.dev_eui, 1),
assert::enabled_uplink_channel_indices(dev.dev_eui.clone(), vec![0, 1, 2]), assert::enabled_uplink_channel_indices(dev.dev_eui, vec![0, 1, 2]),
], ],
}, },
Test { Test {
@ -4302,7 +4534,7 @@ async fn test_lorawan_10_adr() {
dev_eui: dev.dev_eui, dev_eui: dev.dev_eui,
device_queue_items: vec![], device_queue_items: vec![],
before_func: Some(Box::new(move || { before_func: Some(Box::new(move || {
let dev_eui = dev.dev_eui.clone(); let dev_eui = dev.dev_eui;
Box::pin(async move { Box::pin(async move {
mac_command::set_pending( mac_command::set_pending(
&dev_eui, &dev_eui,
@ -4357,12 +4589,12 @@ async fn test_lorawan_10_adr() {
mic: Some([252, 17, 226, 74]), mic: Some([252, 17, 226, 74]),
}, },
assert: vec![ assert: vec![
assert::f_cnt_up(dev.dev_eui.clone(), 11), assert::f_cnt_up(dev.dev_eui, 11),
assert::n_f_cnt_down(dev.dev_eui.clone(), 5), assert::n_f_cnt_down(dev.dev_eui, 5),
assert::tx_power_index(dev.dev_eui.clone(), 0), assert::tx_power_index(dev.dev_eui, 0),
assert::dr(dev.dev_eui.clone(), 0), assert::dr(dev.dev_eui, 0),
assert::nb_trans(dev.dev_eui.clone(), 0), assert::nb_trans(dev.dev_eui, 0),
assert::enabled_uplink_channel_indices(dev.dev_eui.clone(), vec![0, 1, 2]), assert::enabled_uplink_channel_indices(dev.dev_eui, vec![0, 1, 2]),
], ],
}, },
Test { Test {
@ -4395,9 +4627,9 @@ async fn test_lorawan_10_adr() {
mic: Some([73, 26, 32, 42]), mic: Some([73, 26, 32, 42]),
}, },
assert: vec![ assert: vec![
assert::f_cnt_up(dev.dev_eui.clone(), 11), assert::f_cnt_up(dev.dev_eui, 11),
assert::n_f_cnt_down(dev.dev_eui.clone(), 5), assert::n_f_cnt_down(dev.dev_eui, 5),
assert::enabled_uplink_channel_indices(dev.dev_eui.clone(), vec![0, 1, 2]), assert::enabled_uplink_channel_indices(dev.dev_eui, vec![0, 1, 2]),
assert::downlink_phy_payloads(vec![ assert::downlink_phy_payloads(vec![
lrwn::PhyPayload { lrwn::PhyPayload {
mhdr: lrwn::MHDR { mhdr: lrwn::MHDR {
@ -4468,8 +4700,8 @@ async fn test_lorawan_10_adr() {
mic: Some([122, 152, 152, 220]), mic: Some([122, 152, 152, 220]),
}, },
assert: vec![ assert: vec![
assert::f_cnt_up(dev.dev_eui.clone(), 11), assert::f_cnt_up(dev.dev_eui, 11),
assert::n_f_cnt_down(dev.dev_eui.clone(), 5), assert::n_f_cnt_down(dev.dev_eui, 5),
assert::downlink_phy_payloads_decoded_f_opts(vec![ assert::downlink_phy_payloads_decoded_f_opts(vec![
lrwn::PhyPayload { lrwn::PhyPayload {
mhdr: lrwn::MHDR { mhdr: lrwn::MHDR {
@ -4536,10 +4768,7 @@ async fn test_lorawan_10_adr() {
mic: Some([0x8, 0xee, 0xdd, 0x34]), mic: Some([0x8, 0xee, 0xdd, 0x34]),
}, },
]), ]),
assert::enabled_uplink_channel_indices( assert::enabled_uplink_channel_indices(dev.dev_eui, vec![0, 1, 2, 3, 4, 5, 6, 7]),
dev.dev_eui.clone(),
vec![0, 1, 2, 3, 4, 5, 6, 7],
),
], ],
}, },
Test { Test {
@ -4547,7 +4776,7 @@ async fn test_lorawan_10_adr() {
dev_eui: dev.dev_eui, dev_eui: dev.dev_eui,
device_queue_items: vec![], device_queue_items: vec![],
before_func: Some(Box::new(move || { before_func: Some(Box::new(move || {
let dev_eui = dev.dev_eui.clone(); let dev_eui = dev.dev_eui;
Box::pin(async move { Box::pin(async move {
mac_command::set_pending( mac_command::set_pending(
&dev_eui, &dev_eui,
@ -4602,10 +4831,10 @@ async fn test_lorawan_10_adr() {
mic: Some([235, 224, 96, 3]), mic: Some([235, 224, 96, 3]),
}, },
assert: vec![ assert: vec![
assert::f_cnt_up(dev.dev_eui.clone(), 11), assert::f_cnt_up(dev.dev_eui, 11),
assert::n_f_cnt_down(dev.dev_eui.clone(), 5), assert::n_f_cnt_down(dev.dev_eui, 5),
assert::no_downlink_frame(), assert::no_downlink_frame(),
assert::enabled_uplink_channel_indices(dev.dev_eui.clone(), vec![0, 1, 2]), assert::enabled_uplink_channel_indices(dev.dev_eui, vec![0, 1, 2]),
], ],
}, },
Test { Test {
@ -4613,7 +4842,7 @@ async fn test_lorawan_10_adr() {
dev_eui: dev.dev_eui, dev_eui: dev.dev_eui,
device_queue_items: vec![], device_queue_items: vec![],
before_func: Some(Box::new(move || { before_func: Some(Box::new(move || {
let dev_eui = dev.dev_eui.clone(); let dev_eui = dev.dev_eui;
Box::pin(async move { Box::pin(async move {
mac_command::set_pending( mac_command::set_pending(
&dev_eui, &dev_eui,
@ -4668,12 +4897,9 @@ async fn test_lorawan_10_adr() {
mic: Some([252, 17, 226, 74]), mic: Some([252, 17, 226, 74]),
}, },
assert: vec![ assert: vec![
assert::f_cnt_up(dev.dev_eui.clone(), 11), assert::f_cnt_up(dev.dev_eui, 11),
assert::enabled_uplink_channel_indices( assert::enabled_uplink_channel_indices(dev.dev_eui, vec![0, 1, 2, 3, 4, 5, 6, 7]),
dev.dev_eui.clone(), assert::mac_command_error_count(dev.dev_eui, lrwn::CID::LinkADRReq, 1),
vec![0, 1, 2, 3, 4, 5, 6, 7],
),
assert::mac_command_error_count(dev.dev_eui.clone(), lrwn::CID::LinkADRReq, 1),
], ],
}, },
Test { Test {
@ -4706,12 +4932,9 @@ async fn test_lorawan_10_adr() {
mic: Some([187, 243, 244, 117]), mic: Some([187, 243, 244, 117]),
}, },
assert: vec![ assert: vec![
assert::f_cnt_up(dev.dev_eui.clone(), 11), assert::f_cnt_up(dev.dev_eui, 11),
assert::n_f_cnt_down(dev.dev_eui.clone(), 5), assert::n_f_cnt_down(dev.dev_eui, 5),
assert::enabled_uplink_channel_indices( assert::enabled_uplink_channel_indices(dev.dev_eui, vec![0, 1, 2, 3, 4, 5, 6, 7]),
dev.dev_eui.clone(),
vec![0, 1, 2, 3, 4, 5, 6, 7],
),
assert::downlink_phy_payloads_decoded_f_opts(vec![ assert::downlink_phy_payloads_decoded_f_opts(vec![
lrwn::PhyPayload { lrwn::PhyPayload {
mhdr: lrwn::MHDR { mhdr: lrwn::MHDR {
@ -4811,11 +5034,11 @@ async fn test_lorawan_10_adr() {
mic: Some([187, 243, 244, 117]), mic: Some([187, 243, 244, 117]),
}, },
assert: vec![ assert: vec![
assert::f_cnt_up(dev.dev_eui.clone(), 11), assert::f_cnt_up(dev.dev_eui, 11),
assert::dr(dev.dev_eui.clone(), 0), assert::dr(dev.dev_eui, 0),
assert::tx_power_index(dev.dev_eui.clone(), 0), assert::tx_power_index(dev.dev_eui, 0),
assert::uplink_adr_history( assert::uplink_adr_history(
dev.dev_eui.clone(), dev.dev_eui,
vec![internal::UplinkAdrHistory { vec![internal::UplinkAdrHistory {
f_cnt: 10, f_cnt: 10,
max_snr: 0.0, max_snr: 0.0,
@ -4956,7 +5179,7 @@ async fn test_lorawan_10_device_status_request() {
mic: Some([122, 152, 152, 220]), mic: Some([122, 152, 152, 220]),
}, },
assert: vec![ assert: vec![
assert::f_cnt_up(dev.dev_eui.clone(), 11), assert::f_cnt_up(dev.dev_eui, 11),
assert::downlink_phy_payloads_decoded_f_opts(vec![ assert::downlink_phy_payloads_decoded_f_opts(vec![
lrwn::PhyPayload { lrwn::PhyPayload {
mhdr: lrwn::MHDR { mhdr: lrwn::MHDR {
@ -5033,7 +5256,7 @@ async fn test_lorawan_10_device_status_request() {
mic: Some([122, 152, 152, 220]), mic: Some([122, 152, 152, 220]),
}, },
assert: vec![ assert: vec![
assert::f_cnt_up(dev.dev_eui.clone(), 11), assert::f_cnt_up(dev.dev_eui, 11),
assert::no_downlink_frame(), assert::no_downlink_frame(),
], ],
}, },
@ -5073,7 +5296,7 @@ async fn test_lorawan_10_device_status_request() {
mic: Some([29, 141, 54, 155]), mic: Some([29, 141, 54, 155]),
}, },
assert: vec![ assert: vec![
assert::f_cnt_up(dev.dev_eui.clone(), 11), assert::f_cnt_up(dev.dev_eui, 11),
assert::status_event(integration_pb::StatusEvent { assert::status_event(integration_pb::StatusEvent {
device_info: Some(integration_pb::DeviceInfo { device_info: Some(integration_pb::DeviceInfo {
tenant_name: t.name.clone(), tenant_name: t.name.clone(),
@ -5205,7 +5428,7 @@ async fn test_lorawan_11_receive_window_selection() {
dev_eui: dev.dev_eui, dev_eui: dev.dev_eui,
device_queue_items: vec![device_queue::DeviceQueueItem { device_queue_items: vec![device_queue::DeviceQueueItem {
id: Uuid::nil(), id: Uuid::nil(),
dev_eui: dev.dev_eui.clone(), dev_eui: dev.dev_eui,
f_port: 1, f_port: 1,
data: vec![1], data: vec![1],
..Default::default() ..Default::default()
@ -5232,7 +5455,7 @@ async fn test_lorawan_11_receive_window_selection() {
mic: Some([104, 147, 104, 147]), mic: Some([104, 147, 104, 147]),
}, },
assert: vec![ assert: vec![
assert::f_cnt_up(dev.dev_eui.clone(), 11), assert::f_cnt_up(dev.dev_eui, 11),
assert::downlink_frame(gw::DownlinkFrame { assert::downlink_frame(gw::DownlinkFrame {
gateway_id: "0102030405060708".into(), gateway_id: "0102030405060708".into(),
items: vec![gw::DownlinkFrameItem { items: vec![gw::DownlinkFrameItem {
@ -5275,7 +5498,7 @@ async fn test_lorawan_11_receive_window_selection() {
dev_eui: dev.dev_eui, dev_eui: dev.dev_eui,
device_queue_items: vec![device_queue::DeviceQueueItem { device_queue_items: vec![device_queue::DeviceQueueItem {
id: Uuid::nil(), id: Uuid::nil(),
dev_eui: dev.dev_eui.clone(), dev_eui: dev.dev_eui,
f_port: 1, f_port: 1,
data: vec![1], data: vec![1],
..Default::default() ..Default::default()
@ -5302,7 +5525,7 @@ async fn test_lorawan_11_receive_window_selection() {
mic: Some([104, 147, 104, 147]), mic: Some([104, 147, 104, 147]),
}, },
assert: vec![ assert: vec![
assert::f_cnt_up(dev.dev_eui.clone(), 11), assert::f_cnt_up(dev.dev_eui, 11),
assert::downlink_frame(gw::DownlinkFrame { assert::downlink_frame(gw::DownlinkFrame {
gateway_id: "0102030405060708".into(), gateway_id: "0102030405060708".into(),
items: vec![gw::DownlinkFrameItem { items: vec![gw::DownlinkFrameItem {
@ -5345,7 +5568,7 @@ async fn test_lorawan_11_receive_window_selection() {
dev_eui: dev.dev_eui, dev_eui: dev.dev_eui,
device_queue_items: vec![device_queue::DeviceQueueItem { device_queue_items: vec![device_queue::DeviceQueueItem {
id: Uuid::nil(), id: Uuid::nil(),
dev_eui: dev.dev_eui.clone(), dev_eui: dev.dev_eui,
f_port: 1, f_port: 1,
data: vec![1], data: vec![1],
..Default::default() ..Default::default()
@ -5372,7 +5595,7 @@ async fn test_lorawan_11_receive_window_selection() {
mic: Some([104, 147, 104, 147]), mic: Some([104, 147, 104, 147]),
}, },
assert: vec![ assert: vec![
assert::f_cnt_up(dev.dev_eui.clone(), 11), assert::f_cnt_up(dev.dev_eui, 11),
assert::downlink_frame(gw::DownlinkFrame { assert::downlink_frame(gw::DownlinkFrame {
gateway_id: "0102030405060708".into(), gateway_id: "0102030405060708".into(),
items: vec![ items: vec![
@ -5444,7 +5667,7 @@ async fn test_lorawan_11_receive_window_selection() {
dev_eui: dev.dev_eui, dev_eui: dev.dev_eui,
device_queue_items: vec![device_queue::DeviceQueueItem { device_queue_items: vec![device_queue::DeviceQueueItem {
id: Uuid::nil(), id: Uuid::nil(),
dev_eui: dev.dev_eui.clone(), dev_eui: dev.dev_eui,
f_port: 1, f_port: 1,
data: vec![0; 100], data: vec![0; 100],
..Default::default() ..Default::default()
@ -5471,7 +5694,7 @@ async fn test_lorawan_11_receive_window_selection() {
mic: Some([0xd4, 0x59, 0x68, 0x93]), mic: Some([0xd4, 0x59, 0x68, 0x93]),
}, },
assert: vec![ assert: vec![
assert::f_cnt_up(dev.dev_eui.clone(), 11), assert::f_cnt_up(dev.dev_eui, 11),
assert::downlink_frame(gw::DownlinkFrame { assert::downlink_frame(gw::DownlinkFrame {
gateway_id: "0102030405060708".into(), gateway_id: "0102030405060708".into(),
items: vec![ items: vec![

View File

@ -1269,8 +1269,23 @@ impl Data {
async fn start_downlink_data_flow(&mut self) -> Result<()> { async fn start_downlink_data_flow(&mut self) -> Result<()> {
trace!("Starting downlink data flow"); trace!("Starting downlink data flow");
// We sleep get_downlink_data_delay to give the end-user application some time
// to enqueue data before the downlink flow starts. In case the user has increased
// the RX1 Delay relative to the system RX1 Delay, then we add the additional
// seconds to this wait.
{
let conf = config::get(); let conf = config::get();
tokio::time::sleep(conf.network.get_downlink_data_delay).await; let ds = self.device.as_ref().unwrap().get_device_session()?;
let network_conf = config::get_region_network(&ds.region_config_id)?;
let dev_rx1_delay = ds.rx1_delay as u8;
let sys_rx1_delay = network_conf.rx1_delay;
let rx1_delay_increase = dev_rx1_delay.checked_sub(sys_rx1_delay).unwrap_or_default();
let rx1_delay_increase = std::time::Duration::from_secs(rx1_delay_increase.into());
tokio::time::sleep(conf.network.get_downlink_data_delay + rx1_delay_increase).await;
}
if let lrwn::Payload::MACPayload(pl) = &self.phy_payload.payload { if let lrwn::Payload::MACPayload(pl) = &self.phy_payload.payload {
downlink::data::Data::handle_response( downlink::data::Data::handle_response(
@ -1293,8 +1308,26 @@ impl Data {
async fn start_downlink_data_flow_relayed(&mut self) -> Result<()> { async fn start_downlink_data_flow_relayed(&mut self) -> Result<()> {
trace!("Starting relayed downlink data flow"); trace!("Starting relayed downlink data flow");
// We sleep get_downlink_data_delay to give the end-user application some time
// to enqueue data before the downlink flow starts. In case the user has increased
// the RX1 Delay relative to the system RX1 Delay, then we add the additional
// seconds to this wait.
// Note: In this case we use the RX1 Delay from the Relay device-session.
{
let conf = config::get(); let conf = config::get();
tokio::time::sleep(conf.network.get_downlink_data_delay).await; let relay_ctx = self.relay_context.as_ref().unwrap();
let ds = relay_ctx.device.get_device_session()?;
let network_conf = config::get_region_network(&ds.region_config_id)?;
let dev_rx1_delay = ds.rx1_delay as u8;
let sys_rx1_delay = network_conf.rx1_delay;
let rx1_delay_increase = dev_rx1_delay.checked_sub(sys_rx1_delay).unwrap_or_default();
let rx1_delay_increase = std::time::Duration::from_secs(rx1_delay_increase.into());
tokio::time::sleep(conf.network.get_downlink_data_delay + rx1_delay_increase).await;
}
if let lrwn::Payload::MACPayload(pl) = &self.phy_payload.payload { if let lrwn::Payload::MACPayload(pl) = &self.phy_payload.payload {
downlink::data::Data::handle_response_relayed( downlink::data::Data::handle_response_relayed(

View File

@ -241,6 +241,7 @@ function DeviceProfileForm(props: IProps) {
dp.setFlushQueueOnActivate(v.flushQueueOnActivate); dp.setFlushQueueOnActivate(v.flushQueueOnActivate);
dp.setUplinkInterval(v.uplinkInterval); dp.setUplinkInterval(v.uplinkInterval);
dp.setDeviceStatusReqInterval(v.deviceStatusReqInterval); dp.setDeviceStatusReqInterval(v.deviceStatusReqInterval);
dp.setRx1Delay(v.rx1Delay);
// join otaa /abp // join otaa /abp
dp.setSupportsOtaa(v.supportsOtaa); dp.setSupportsOtaa(v.supportsOtaa);
@ -501,6 +502,18 @@ function DeviceProfileForm(props: IProps) {
</Form.Item> </Form.Item>
</Col> </Col>
<Col span={12}> <Col span={12}>
<Form.Item
label="Allow roaming"
name="allowRoaming"
valuePropName="checked"
tooltip="If enabled (and if roaming is configured on the server), this allows the device to use roaming."
>
<Switch />
</Form.Item>
</Col>
</Row>
<Row>
<Col span={8}>
<Form.Item <Form.Item
label="Expected uplink interval (secs)" label="Expected uplink interval (secs)"
tooltip="The expected interval in seconds in which the device sends uplink messages. This is used to determine if a device is active or inactive." tooltip="The expected interval in seconds in which the device sends uplink messages. This is used to determine if a device is active or inactive."
@ -515,19 +528,7 @@ function DeviceProfileForm(props: IProps) {
<InputNumber min={0} disabled={props.disabled} /> <InputNumber min={0} disabled={props.disabled} />
</Form.Item> </Form.Item>
</Col> </Col>
</Row> <Col span={8}>
<Row>
<Col span={12}>
<Form.Item
label="Allow roaming"
name="allowRoaming"
valuePropName="checked"
tooltip="If enabled (and if roaming is configured on the server), this allows the device to use roaming."
>
<Switch />
</Form.Item>
</Col>
<Col span={12}>
<Form.Item <Form.Item
label="Device-status request frequency (req/day)" label="Device-status request frequency (req/day)"
tooltip="Frequency to initiate an End-Device status request (request/day). Set to 0 to disable." tooltip="Frequency to initiate an End-Device status request (request/day). Set to 0 to disable."
@ -536,6 +537,15 @@ function DeviceProfileForm(props: IProps) {
<InputNumber min={0} disabled={props.disabled} /> <InputNumber min={0} disabled={props.disabled} />
</Form.Item> </Form.Item>
</Col> </Col>
<Col span={8}>
<Form.Item
label="RX1 Delay (0 = use system default)"
tooltip="This option makes it possible to set a higher RX1 Delay for devices using this device-profile. Note that a lower value than the system default will be ignored. If configured and incremented, then ChirpStack will increase the downlink data delay with the same increment."
name="rx1Delay"
>
<InputNumber min={0} max={15} disabled={props.disabled} />
</Form.Item>
</Col>
</Row> </Row>
</Tabs.TabPane> </Tabs.TabPane>
<Tabs.TabPane tab="Join (OTAA / ABP)" key="2" forceRender> <Tabs.TabPane tab="Join (OTAA / ABP)" key="2" forceRender>