Implement end-to-end app payload encryption.

This implements end-to-end encryption between the end-device and
end-application. The encrypted AppSKey or SessionKeyID is forwarded to
the end-application which should be able to decrypt or request the
AppSKey to decrypt the uplink payload. As well the end-application will
be able to enqueue encrypted application payloads.

Using this mechanism, ChirpStack will never have access to the uplink
and downlink application-payloads.
This commit is contained in:
Orne Brocaar 2023-10-05 13:05:53 +01:00
parent 503beaa2fd
commit 41d00cb651
49 changed files with 4859 additions and 783 deletions

View File

@ -101,67 +101,73 @@ namespace Chirpstack.Api {
"CzIOLmNvbW1vbi5NZXRyaWMSHgoGZ3dfc25yGAMgASgLMg4uY29tbW9uLk1l",
"dHJpYxIrChNyeF9wYWNrZXRzX3Blcl9mcmVxGAQgASgLMg4uY29tbW9uLk1l",
"dHJpYxIpChFyeF9wYWNrZXRzX3Blcl9kchgFIAEoCzIOLmNvbW1vbi5NZXRy",
"aWMSHgoGZXJyb3JzGAYgASgLMg4uY29tbW9uLk1ldHJpYyKwAQoPRGV2aWNl",
"aWMSHgoGZXJyb3JzGAYgASgLMg4uY29tbW9uLk1ldHJpYyLGAQoPRGV2aWNl",
"UXVldWVJdGVtEgoKAmlkGAEgASgJEg8KB2Rldl9ldWkYAiABKAkSEQoJY29u",
"ZmlybWVkGAMgASgIEg4KBmZfcG9ydBgEIAEoDRIMCgRkYXRhGAUgASgMEicK",
"Bm9iamVjdBgGIAEoCzIXLmdvb2dsZS5wcm90b2J1Zi5TdHJ1Y3QSEgoKaXNf",
"cGVuZGluZxgHIAEoCBISCgpmX2NudF9kb3duGAggASgNIkkKHUVucXVldWVE",
"ZXZpY2VRdWV1ZUl0ZW1SZXF1ZXN0EigKCnF1ZXVlX2l0ZW0YASABKAsyFC5h",
"cGkuRGV2aWNlUXVldWVJdGVtIiwKHkVucXVldWVEZXZpY2VRdWV1ZUl0ZW1S",
"ZXNwb25zZRIKCgJpZBgBIAEoCSIqChdGbHVzaERldmljZVF1ZXVlUmVxdWVz",
"dBIPCgdkZXZfZXVpGAEgASgJIkEKGkdldERldmljZVF1ZXVlSXRlbXNSZXF1",
"ZXN0Eg8KB2Rldl9ldWkYASABKAkSEgoKY291bnRfb25seRgCIAEoCCJYChtH",
"ZXREZXZpY2VRdWV1ZUl0ZW1zUmVzcG9uc2USEwoLdG90YWxfY291bnQYASAB",
"KA0SJAoGcmVzdWx0GAIgAygLMhQuYXBpLkRldmljZVF1ZXVlSXRlbSIoChVG",
"bHVzaERldk5vbmNlc1JlcXVlc3QSDwoHZGV2X2V1aRgBIAEoCTLQEAoNRGV2",
"aWNlU2VydmljZRJTCgZDcmVhdGUSGC5hcGkuQ3JlYXRlRGV2aWNlUmVxdWVz",
"dBoWLmdvb2dsZS5wcm90b2J1Zi5FbXB0eSIXgtPkkwIRIgwvYXBpL2Rldmlj",
"ZXM6ASoSVAoDR2V0EhUuYXBpLkdldERldmljZVJlcXVlc3QaFi5hcGkuR2V0",
"RGV2aWNlUmVzcG9uc2UiHoLT5JMCGBIWL2FwaS9kZXZpY2VzL3tkZXZfZXVp",
"fRJkCgZVcGRhdGUSGC5hcGkuVXBkYXRlRGV2aWNlUmVxdWVzdBoWLmdvb2ds",
"ZS5wcm90b2J1Zi5FbXB0eSIogtPkkwIiGh0vYXBpL2RldmljZXMve2Rldmlj",
"ZS5kZXZfZXVpfToBKhJaCgZEZWxldGUSGC5hcGkuRGVsZXRlRGV2aWNlUmVx",
"dWVzdBoWLmdvb2dsZS5wcm90b2J1Zi5FbXB0eSIegtPkkwIYKhYvYXBpL2Rl",
"dmljZXMve2Rldl9ldWl9Ek8KBExpc3QSFy5hcGkuTGlzdERldmljZXNSZXF1",
"ZXN0GhguYXBpLkxpc3REZXZpY2VzUmVzcG9uc2UiFILT5JMCDhIML2FwaS9k",
"ZXZpY2VzEnYKCkNyZWF0ZUtleXMSHC5hcGkuQ3JlYXRlRGV2aWNlS2V5c1Jl",
"cXVlc3QaFi5nb29nbGUucHJvdG9idWYuRW1wdHkiMoLT5JMCLCInL2FwaS9k",
"ZXZpY2VzL3tkZXZpY2Vfa2V5cy5kZXZfZXVpfS9rZXlzOgEqEmUKB0dldEtl",
"eXMSGS5hcGkuR2V0RGV2aWNlS2V5c1JlcXVlc3QaGi5hcGkuR2V0RGV2aWNl",
"S2V5c1Jlc3BvbnNlIiOC0+STAh0SGy9hcGkvZGV2aWNlcy97ZGV2X2V1aX0v",
"a2V5cxJ2CgpVcGRhdGVLZXlzEhwuYXBpLlVwZGF0ZURldmljZUtleXNSZXF1",
"ZXN0GhYuZ29vZ2xlLnByb3RvYnVmLkVtcHR5IjKC0+STAiwaJy9hcGkvZGV2",
"aWNlcy97ZGV2aWNlX2tleXMuZGV2X2V1aX0va2V5czoBKhJnCgpEZWxldGVL",
"ZXlzEhwuYXBpLkRlbGV0ZURldmljZUtleXNSZXF1ZXN0GhYuZ29vZ2xlLnBy",
"b3RvYnVmLkVtcHR5IiOC0+STAh0qGy9hcGkvZGV2aWNlcy97ZGV2X2V1aX0v",
"a2V5cxJvCg5GbHVzaERldk5vbmNlcxIaLmFwaS5GbHVzaERldk5vbmNlc1Jl",
"cXVlc3QaFi5nb29nbGUucHJvdG9idWYuRW1wdHkiKYLT5JMCIyohL2FwaS9k",
"ZXZpY2VzL3tkZXZfZXVpfS9kZXYtbm9uY2VzEnwKCEFjdGl2YXRlEhouYXBp",
"LkFjdGl2YXRlRGV2aWNlUmVxdWVzdBoWLmdvb2dsZS5wcm90b2J1Zi5FbXB0",
"eSI8gtPkkwI2IjEvYXBpL2RldmljZXMve2RldmljZV9hY3RpdmF0aW9uLmRl",
"dl9ldWl9L2FjdGl2YXRlOgEqEm0KCkRlYWN0aXZhdGUSHC5hcGkuRGVhY3Rp",
"dmF0ZURldmljZVJlcXVlc3QaFi5nb29nbGUucHJvdG9idWYuRW1wdHkiKYLT",
"5JMCIyohL2FwaS9kZXZpY2VzL3tkZXZfZXVpfS9hY3RpdmF0aW9uEn0KDUdl",
"dEFjdGl2YXRpb24SHy5hcGkuR2V0RGV2aWNlQWN0aXZhdGlvblJlcXVlc3Qa",
"IC5hcGkuR2V0RGV2aWNlQWN0aXZhdGlvblJlc3BvbnNlIimC0+STAiMSIS9h",
"cGkvZGV2aWNlcy97ZGV2X2V1aX0vYWN0aXZhdGlvbhKDAQoQR2V0UmFuZG9t",
"RGV2QWRkchIcLmFwaS5HZXRSYW5kb21EZXZBZGRyUmVxdWVzdBodLmFwaS5H",
"ZXRSYW5kb21EZXZBZGRyUmVzcG9uc2UiMoLT5JMCLCIqL2FwaS9kZXZpY2Vz",
"L3tkZXZfZXVpfS9nZXQtcmFuZG9tLWRldi1hZGRyEnEKCkdldE1ldHJpY3MS",
"HC5hcGkuR2V0RGV2aWNlTWV0cmljc1JlcXVlc3QaHS5hcGkuR2V0RGV2aWNl",
"TWV0cmljc1Jlc3BvbnNlIiaC0+STAiASHi9hcGkvZGV2aWNlcy97ZGV2X2V1",
"aX0vbWV0cmljcxKCAQoOR2V0TGlua01ldHJpY3MSIC5hcGkuR2V0RGV2aWNl",
"TGlua01ldHJpY3NSZXF1ZXN0GiEuYXBpLkdldERldmljZUxpbmtNZXRyaWNz",
"UmVzcG9uc2UiK4LT5JMCJRIjL2FwaS9kZXZpY2VzL3tkZXZfZXVpfS9saW5r",
"LW1ldHJpY3MShgEKB0VucXVldWUSIi5hcGkuRW5xdWV1ZURldmljZVF1ZXVl",
"SXRlbVJlcXVlc3QaIy5hcGkuRW5xdWV1ZURldmljZVF1ZXVlSXRlbVJlc3Bv",
"bnNlIjKC0+STAiwiJy9hcGkvZGV2aWNlcy97cXVldWVfaXRlbS5kZXZfZXVp",
"fS9xdWV1ZToBKhJoCgpGbHVzaFF1ZXVlEhwuYXBpLkZsdXNoRGV2aWNlUXVl",
"dWVSZXF1ZXN0GhYuZ29vZ2xlLnByb3RvYnVmLkVtcHR5IiSC0+STAh4qHC9h",
"cGkvZGV2aWNlcy97ZGV2X2V1aX0vcXVldWUScwoIR2V0UXVldWUSHy5hcGku",
"R2V0RGV2aWNlUXVldWVJdGVtc1JlcXVlc3QaIC5hcGkuR2V0RGV2aWNlUXVl",
"dWVJdGVtc1Jlc3BvbnNlIiSC0+STAh4SHC9hcGkvZGV2aWNlcy97ZGV2X2V1",
"aX0vcXVldWVCYwoRaW8uY2hpcnBzdGFjay5hcGlCC0RldmljZVByb3RvUAFa",
"cGVuZGluZxgHIAEoCBISCgpmX2NudF9kb3duGAggASgNEhQKDGlzX2VuY3J5",
"cHRlZBgJIAEoCCJJCh1FbnF1ZXVlRGV2aWNlUXVldWVJdGVtUmVxdWVzdBIo",
"CgpxdWV1ZV9pdGVtGAEgASgLMhQuYXBpLkRldmljZVF1ZXVlSXRlbSIsCh5F",
"bnF1ZXVlRGV2aWNlUXVldWVJdGVtUmVzcG9uc2USCgoCaWQYASABKAkiKgoX",
"Rmx1c2hEZXZpY2VRdWV1ZVJlcXVlc3QSDwoHZGV2X2V1aRgBIAEoCSJBChpH",
"ZXREZXZpY2VRdWV1ZUl0ZW1zUmVxdWVzdBIPCgdkZXZfZXVpGAEgASgJEhIK",
"CmNvdW50X29ubHkYAiABKAgiWAobR2V0RGV2aWNlUXVldWVJdGVtc1Jlc3Bv",
"bnNlEhMKC3RvdGFsX2NvdW50GAEgASgNEiQKBnJlc3VsdBgCIAMoCzIULmFw",
"aS5EZXZpY2VRdWV1ZUl0ZW0iKAoVRmx1c2hEZXZOb25jZXNSZXF1ZXN0Eg8K",
"B2Rldl9ldWkYASABKAkiLwocR2V0RGV2aWNlTmV4dEZDbnREb3duUmVxdWVz",
"dBIPCgdkZXZfZXVpGAEgASgJIjMKHUdldERldmljZU5leHRGQ250RG93blJl",
"c3BvbnNlEhIKCmZfY250X2Rvd24YASABKA0y4hEKDURldmljZVNlcnZpY2US",
"UwoGQ3JlYXRlEhguYXBpLkNyZWF0ZURldmljZVJlcXVlc3QaFi5nb29nbGUu",
"cHJvdG9idWYuRW1wdHkiF4LT5JMCESIML2FwaS9kZXZpY2VzOgEqElQKA0dl",
"dBIVLmFwaS5HZXREZXZpY2VSZXF1ZXN0GhYuYXBpLkdldERldmljZVJlc3Bv",
"bnNlIh6C0+STAhgSFi9hcGkvZGV2aWNlcy97ZGV2X2V1aX0SZAoGVXBkYXRl",
"EhguYXBpLlVwZGF0ZURldmljZVJlcXVlc3QaFi5nb29nbGUucHJvdG9idWYu",
"RW1wdHkiKILT5JMCIhodL2FwaS9kZXZpY2VzL3tkZXZpY2UuZGV2X2V1aX06",
"ASoSWgoGRGVsZXRlEhguYXBpLkRlbGV0ZURldmljZVJlcXVlc3QaFi5nb29n",
"bGUucHJvdG9idWYuRW1wdHkiHoLT5JMCGCoWL2FwaS9kZXZpY2VzL3tkZXZf",
"ZXVpfRJPCgRMaXN0EhcuYXBpLkxpc3REZXZpY2VzUmVxdWVzdBoYLmFwaS5M",
"aXN0RGV2aWNlc1Jlc3BvbnNlIhSC0+STAg4SDC9hcGkvZGV2aWNlcxJ2CgpD",
"cmVhdGVLZXlzEhwuYXBpLkNyZWF0ZURldmljZUtleXNSZXF1ZXN0GhYuZ29v",
"Z2xlLnByb3RvYnVmLkVtcHR5IjKC0+STAiwiJy9hcGkvZGV2aWNlcy97ZGV2",
"aWNlX2tleXMuZGV2X2V1aX0va2V5czoBKhJlCgdHZXRLZXlzEhkuYXBpLkdl",
"dERldmljZUtleXNSZXF1ZXN0GhouYXBpLkdldERldmljZUtleXNSZXNwb25z",
"ZSIjgtPkkwIdEhsvYXBpL2RldmljZXMve2Rldl9ldWl9L2tleXMSdgoKVXBk",
"YXRlS2V5cxIcLmFwaS5VcGRhdGVEZXZpY2VLZXlzUmVxdWVzdBoWLmdvb2ds",
"ZS5wcm90b2J1Zi5FbXB0eSIygtPkkwIsGicvYXBpL2RldmljZXMve2Rldmlj",
"ZV9rZXlzLmRldl9ldWl9L2tleXM6ASoSZwoKRGVsZXRlS2V5cxIcLmFwaS5E",
"ZWxldGVEZXZpY2VLZXlzUmVxdWVzdBoWLmdvb2dsZS5wcm90b2J1Zi5FbXB0",
"eSIjgtPkkwIdKhsvYXBpL2RldmljZXMve2Rldl9ldWl9L2tleXMSbwoORmx1",
"c2hEZXZOb25jZXMSGi5hcGkuRmx1c2hEZXZOb25jZXNSZXF1ZXN0GhYuZ29v",
"Z2xlLnByb3RvYnVmLkVtcHR5IimC0+STAiMqIS9hcGkvZGV2aWNlcy97ZGV2",
"X2V1aX0vZGV2LW5vbmNlcxJ8CghBY3RpdmF0ZRIaLmFwaS5BY3RpdmF0ZURl",
"dmljZVJlcXVlc3QaFi5nb29nbGUucHJvdG9idWYuRW1wdHkiPILT5JMCNiIx",
"L2FwaS9kZXZpY2VzL3tkZXZpY2VfYWN0aXZhdGlvbi5kZXZfZXVpfS9hY3Rp",
"dmF0ZToBKhJtCgpEZWFjdGl2YXRlEhwuYXBpLkRlYWN0aXZhdGVEZXZpY2VS",
"ZXF1ZXN0GhYuZ29vZ2xlLnByb3RvYnVmLkVtcHR5IimC0+STAiMqIS9hcGkv",
"ZGV2aWNlcy97ZGV2X2V1aX0vYWN0aXZhdGlvbhJ9Cg1HZXRBY3RpdmF0aW9u",
"Eh8uYXBpLkdldERldmljZUFjdGl2YXRpb25SZXF1ZXN0GiAuYXBpLkdldERl",
"dmljZUFjdGl2YXRpb25SZXNwb25zZSIpgtPkkwIjEiEvYXBpL2RldmljZXMv",
"e2Rldl9ldWl9L2FjdGl2YXRpb24SgwEKEEdldFJhbmRvbURldkFkZHISHC5h",
"cGkuR2V0UmFuZG9tRGV2QWRkclJlcXVlc3QaHS5hcGkuR2V0UmFuZG9tRGV2",
"QWRkclJlc3BvbnNlIjKC0+STAiwiKi9hcGkvZGV2aWNlcy97ZGV2X2V1aX0v",
"Z2V0LXJhbmRvbS1kZXYtYWRkchJxCgpHZXRNZXRyaWNzEhwuYXBpLkdldERl",
"dmljZU1ldHJpY3NSZXF1ZXN0Gh0uYXBpLkdldERldmljZU1ldHJpY3NSZXNw",
"b25zZSImgtPkkwIgEh4vYXBpL2RldmljZXMve2Rldl9ldWl9L21ldHJpY3MS",
"ggEKDkdldExpbmtNZXRyaWNzEiAuYXBpLkdldERldmljZUxpbmtNZXRyaWNz",
"UmVxdWVzdBohLmFwaS5HZXREZXZpY2VMaW5rTWV0cmljc1Jlc3BvbnNlIiuC",
"0+STAiUSIy9hcGkvZGV2aWNlcy97ZGV2X2V1aX0vbGluay1tZXRyaWNzEoYB",
"CgdFbnF1ZXVlEiIuYXBpLkVucXVldWVEZXZpY2VRdWV1ZUl0ZW1SZXF1ZXN0",
"GiMuYXBpLkVucXVldWVEZXZpY2VRdWV1ZUl0ZW1SZXNwb25zZSIygtPkkwIs",
"IicvYXBpL2RldmljZXMve3F1ZXVlX2l0ZW0uZGV2X2V1aX0vcXVldWU6ASoS",
"aAoKRmx1c2hRdWV1ZRIcLmFwaS5GbHVzaERldmljZVF1ZXVlUmVxdWVzdBoW",
"Lmdvb2dsZS5wcm90b2J1Zi5FbXB0eSIkgtPkkwIeKhwvYXBpL2RldmljZXMv",
"e2Rldl9ldWl9L3F1ZXVlEnMKCEdldFF1ZXVlEh8uYXBpLkdldERldmljZVF1",
"ZXVlSXRlbXNSZXF1ZXN0GiAuYXBpLkdldERldmljZVF1ZXVlSXRlbXNSZXNw",
"b25zZSIkgtPkkwIeEhwvYXBpL2RldmljZXMve2Rldl9ldWl9L3F1ZXVlEo8B",
"Cg9HZXROZXh0RkNudERvd24SIS5hcGkuR2V0RGV2aWNlTmV4dEZDbnREb3du",
"UmVxdWVzdBoiLmFwaS5HZXREZXZpY2VOZXh0RkNudERvd25SZXNwb25zZSI1",
"gtPkkwIvIiovYXBpL2RldmljZXMve2Rldl9ldWl9L2dldC1uZXh0LWYtY250",
"LWRvd246ASpCYwoRaW8uY2hpcnBzdGFjay5hcGlCC0RldmljZVByb3RvUAFa",
"LmdpdGh1Yi5jb20vY2hpcnBzdGFjay9jaGlycHN0YWNrL2FwaS9nby92NC9h",
"cGmqAg5DaGlycHN0YWNrLkFwaWIGcHJvdG8z"));
descriptor = pbr::FileDescriptor.FromGeneratedCode(descriptorData,
@ -195,13 +201,15 @@ namespace Chirpstack.Api {
new pbr::GeneratedClrTypeInfo(typeof(global::Chirpstack.Api.DeviceState), global::Chirpstack.Api.DeviceState.Parser, new[]{ "Name", "Value" }, null, null, null, null),
new pbr::GeneratedClrTypeInfo(typeof(global::Chirpstack.Api.GetDeviceLinkMetricsRequest), global::Chirpstack.Api.GetDeviceLinkMetricsRequest.Parser, new[]{ "DevEui", "Start", "End", "Aggregation" }, null, null, null, null),
new pbr::GeneratedClrTypeInfo(typeof(global::Chirpstack.Api.GetDeviceLinkMetricsResponse), global::Chirpstack.Api.GetDeviceLinkMetricsResponse.Parser, new[]{ "RxPackets", "GwRssi", "GwSnr", "RxPacketsPerFreq", "RxPacketsPerDr", "Errors" }, null, null, null, null),
new pbr::GeneratedClrTypeInfo(typeof(global::Chirpstack.Api.DeviceQueueItem), global::Chirpstack.Api.DeviceQueueItem.Parser, new[]{ "Id", "DevEui", "Confirmed", "FPort", "Data", "Object", "IsPending", "FCntDown" }, null, null, null, null),
new pbr::GeneratedClrTypeInfo(typeof(global::Chirpstack.Api.DeviceQueueItem), global::Chirpstack.Api.DeviceQueueItem.Parser, new[]{ "Id", "DevEui", "Confirmed", "FPort", "Data", "Object", "IsPending", "FCntDown", "IsEncrypted" }, null, null, null, null),
new pbr::GeneratedClrTypeInfo(typeof(global::Chirpstack.Api.EnqueueDeviceQueueItemRequest), global::Chirpstack.Api.EnqueueDeviceQueueItemRequest.Parser, new[]{ "QueueItem" }, null, null, null, null),
new pbr::GeneratedClrTypeInfo(typeof(global::Chirpstack.Api.EnqueueDeviceQueueItemResponse), global::Chirpstack.Api.EnqueueDeviceQueueItemResponse.Parser, new[]{ "Id" }, null, null, null, null),
new pbr::GeneratedClrTypeInfo(typeof(global::Chirpstack.Api.FlushDeviceQueueRequest), global::Chirpstack.Api.FlushDeviceQueueRequest.Parser, new[]{ "DevEui" }, null, null, null, null),
new pbr::GeneratedClrTypeInfo(typeof(global::Chirpstack.Api.GetDeviceQueueItemsRequest), global::Chirpstack.Api.GetDeviceQueueItemsRequest.Parser, new[]{ "DevEui", "CountOnly" }, null, null, null, null),
new pbr::GeneratedClrTypeInfo(typeof(global::Chirpstack.Api.GetDeviceQueueItemsResponse), global::Chirpstack.Api.GetDeviceQueueItemsResponse.Parser, new[]{ "TotalCount", "Result" }, null, null, null, null),
new pbr::GeneratedClrTypeInfo(typeof(global::Chirpstack.Api.FlushDevNoncesRequest), global::Chirpstack.Api.FlushDevNoncesRequest.Parser, new[]{ "DevEui" }, null, null, null, null)
new pbr::GeneratedClrTypeInfo(typeof(global::Chirpstack.Api.FlushDevNoncesRequest), global::Chirpstack.Api.FlushDevNoncesRequest.Parser, new[]{ "DevEui" }, null, null, null, null),
new pbr::GeneratedClrTypeInfo(typeof(global::Chirpstack.Api.GetDeviceNextFCntDownRequest), global::Chirpstack.Api.GetDeviceNextFCntDownRequest.Parser, new[]{ "DevEui" }, null, null, null, null),
new pbr::GeneratedClrTypeInfo(typeof(global::Chirpstack.Api.GetDeviceNextFCntDownResponse), global::Chirpstack.Api.GetDeviceNextFCntDownResponse.Parser, new[]{ "FCntDown" }, null, null, null, null)
}));
}
#endregion
@ -7991,6 +7999,7 @@ namespace Chirpstack.Api {
object_ = other.object_ != null ? other.object_.Clone() : null;
isPending_ = other.isPending_;
fCntDown_ = other.fCntDown_;
isEncrypted_ = other.isEncrypted_;
_unknownFields = pb::UnknownFieldSet.Clone(other._unknownFields);
}
@ -8098,7 +8107,8 @@ namespace Chirpstack.Api {
private bool isPending_;
/// <summary>
/// Is pending.
/// This is set to true when the downlink is pending.
/// This is set by ChirpStack to true when the downlink is pending (e.g. it
/// has been sent, but a confirmation is still pending).
/// </summary>
[global::System.Diagnostics.DebuggerNonUserCodeAttribute]
[global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
@ -8114,7 +8124,8 @@ namespace Chirpstack.Api {
private uint fCntDown_;
/// <summary>
/// Downlink frame-counter.
/// This is set when the payload has been sent as downlink.
/// Do not set this for plain-text data payloads. It will be automatically set
/// by ChirpStack when the payload has been sent as downlink.
/// </summary>
[global::System.Diagnostics.DebuggerNonUserCodeAttribute]
[global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
@ -8125,6 +8136,24 @@ namespace Chirpstack.Api {
}
}
/// <summary>Field number for the "is_encrypted" field.</summary>
public const int IsEncryptedFieldNumber = 9;
private bool isEncrypted_;
/// <summary>
/// Is encrypted.
/// This must be set to true if the end-application has already encrypted
/// the data payload. In this case, the f_cnt_down field must be set to
/// the corresponding frame-counter which has been used during the encryption.
/// </summary>
[global::System.Diagnostics.DebuggerNonUserCodeAttribute]
[global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
public bool IsEncrypted {
get { return isEncrypted_; }
set {
isEncrypted_ = value;
}
}
[global::System.Diagnostics.DebuggerNonUserCodeAttribute]
[global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
public override bool Equals(object other) {
@ -8148,6 +8177,7 @@ namespace Chirpstack.Api {
if (!object.Equals(Object, other.Object)) return false;
if (IsPending != other.IsPending) return false;
if (FCntDown != other.FCntDown) return false;
if (IsEncrypted != other.IsEncrypted) return false;
return Equals(_unknownFields, other._unknownFields);
}
@ -8163,6 +8193,7 @@ namespace Chirpstack.Api {
if (object_ != null) hash ^= Object.GetHashCode();
if (IsPending != false) hash ^= IsPending.GetHashCode();
if (FCntDown != 0) hash ^= FCntDown.GetHashCode();
if (IsEncrypted != false) hash ^= IsEncrypted.GetHashCode();
if (_unknownFields != null) {
hash ^= _unknownFields.GetHashCode();
}
@ -8213,6 +8244,10 @@ namespace Chirpstack.Api {
output.WriteRawTag(64);
output.WriteUInt32(FCntDown);
}
if (IsEncrypted != false) {
output.WriteRawTag(72);
output.WriteBool(IsEncrypted);
}
if (_unknownFields != null) {
_unknownFields.WriteTo(output);
}
@ -8255,6 +8290,10 @@ namespace Chirpstack.Api {
output.WriteRawTag(64);
output.WriteUInt32(FCntDown);
}
if (IsEncrypted != false) {
output.WriteRawTag(72);
output.WriteBool(IsEncrypted);
}
if (_unknownFields != null) {
_unknownFields.WriteTo(ref output);
}
@ -8289,6 +8328,9 @@ namespace Chirpstack.Api {
if (FCntDown != 0) {
size += 1 + pb::CodedOutputStream.ComputeUInt32Size(FCntDown);
}
if (IsEncrypted != false) {
size += 1 + 1;
}
if (_unknownFields != null) {
size += _unknownFields.CalculateSize();
}
@ -8328,6 +8370,9 @@ namespace Chirpstack.Api {
if (other.FCntDown != 0) {
FCntDown = other.FCntDown;
}
if (other.IsEncrypted != false) {
IsEncrypted = other.IsEncrypted;
}
_unknownFields = pb::UnknownFieldSet.MergeFrom(_unknownFields, other._unknownFields);
}
@ -8378,6 +8423,10 @@ namespace Chirpstack.Api {
FCntDown = input.ReadUInt32();
break;
}
case 72: {
IsEncrypted = input.ReadBool();
break;
}
}
}
#endif
@ -8428,6 +8477,10 @@ namespace Chirpstack.Api {
FCntDown = input.ReadUInt32();
break;
}
case 72: {
IsEncrypted = input.ReadBool();
break;
}
}
}
}
@ -9662,6 +9715,390 @@ namespace Chirpstack.Api {
}
public sealed partial class GetDeviceNextFCntDownRequest : pb::IMessage<GetDeviceNextFCntDownRequest>
#if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE
, pb::IBufferMessage
#endif
{
private static readonly pb::MessageParser<GetDeviceNextFCntDownRequest> _parser = new pb::MessageParser<GetDeviceNextFCntDownRequest>(() => new GetDeviceNextFCntDownRequest());
private pb::UnknownFieldSet _unknownFields;
[global::System.Diagnostics.DebuggerNonUserCodeAttribute]
[global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
public static pb::MessageParser<GetDeviceNextFCntDownRequest> Parser { get { return _parser; } }
[global::System.Diagnostics.DebuggerNonUserCodeAttribute]
[global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
public static pbr::MessageDescriptor Descriptor {
get { return global::Chirpstack.Api.DeviceReflection.Descriptor.MessageTypes[35]; }
}
[global::System.Diagnostics.DebuggerNonUserCodeAttribute]
[global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
pbr::MessageDescriptor pb::IMessage.Descriptor {
get { return Descriptor; }
}
[global::System.Diagnostics.DebuggerNonUserCodeAttribute]
[global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
public GetDeviceNextFCntDownRequest() {
OnConstruction();
}
partial void OnConstruction();
[global::System.Diagnostics.DebuggerNonUserCodeAttribute]
[global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
public GetDeviceNextFCntDownRequest(GetDeviceNextFCntDownRequest other) : this() {
devEui_ = other.devEui_;
_unknownFields = pb::UnknownFieldSet.Clone(other._unknownFields);
}
[global::System.Diagnostics.DebuggerNonUserCodeAttribute]
[global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
public GetDeviceNextFCntDownRequest Clone() {
return new GetDeviceNextFCntDownRequest(this);
}
/// <summary>Field number for the "dev_eui" field.</summary>
public const int DevEuiFieldNumber = 1;
private string devEui_ = "";
/// <summary>
/// Device EUI (EUI64).
/// </summary>
[global::System.Diagnostics.DebuggerNonUserCodeAttribute]
[global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
public string DevEui {
get { return devEui_; }
set {
devEui_ = pb::ProtoPreconditions.CheckNotNull(value, "value");
}
}
[global::System.Diagnostics.DebuggerNonUserCodeAttribute]
[global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
public override bool Equals(object other) {
return Equals(other as GetDeviceNextFCntDownRequest);
}
[global::System.Diagnostics.DebuggerNonUserCodeAttribute]
[global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
public bool Equals(GetDeviceNextFCntDownRequest other) {
if (ReferenceEquals(other, null)) {
return false;
}
if (ReferenceEquals(other, this)) {
return true;
}
if (DevEui != other.DevEui) return false;
return Equals(_unknownFields, other._unknownFields);
}
[global::System.Diagnostics.DebuggerNonUserCodeAttribute]
[global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
public override int GetHashCode() {
int hash = 1;
if (DevEui.Length != 0) hash ^= DevEui.GetHashCode();
if (_unknownFields != null) {
hash ^= _unknownFields.GetHashCode();
}
return hash;
}
[global::System.Diagnostics.DebuggerNonUserCodeAttribute]
[global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
public override string ToString() {
return pb::JsonFormatter.ToDiagnosticString(this);
}
[global::System.Diagnostics.DebuggerNonUserCodeAttribute]
[global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
public void WriteTo(pb::CodedOutputStream output) {
#if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE
output.WriteRawMessage(this);
#else
if (DevEui.Length != 0) {
output.WriteRawTag(10);
output.WriteString(DevEui);
}
if (_unknownFields != null) {
_unknownFields.WriteTo(output);
}
#endif
}
#if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE
[global::System.Diagnostics.DebuggerNonUserCodeAttribute]
[global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
void pb::IBufferMessage.InternalWriteTo(ref pb::WriteContext output) {
if (DevEui.Length != 0) {
output.WriteRawTag(10);
output.WriteString(DevEui);
}
if (_unknownFields != null) {
_unknownFields.WriteTo(ref output);
}
}
#endif
[global::System.Diagnostics.DebuggerNonUserCodeAttribute]
[global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
public int CalculateSize() {
int size = 0;
if (DevEui.Length != 0) {
size += 1 + pb::CodedOutputStream.ComputeStringSize(DevEui);
}
if (_unknownFields != null) {
size += _unknownFields.CalculateSize();
}
return size;
}
[global::System.Diagnostics.DebuggerNonUserCodeAttribute]
[global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
public void MergeFrom(GetDeviceNextFCntDownRequest other) {
if (other == null) {
return;
}
if (other.DevEui.Length != 0) {
DevEui = other.DevEui;
}
_unknownFields = pb::UnknownFieldSet.MergeFrom(_unknownFields, other._unknownFields);
}
[global::System.Diagnostics.DebuggerNonUserCodeAttribute]
[global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
public void MergeFrom(pb::CodedInputStream input) {
#if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE
input.ReadRawMessage(this);
#else
uint tag;
while ((tag = input.ReadTag()) != 0) {
switch(tag) {
default:
_unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, input);
break;
case 10: {
DevEui = input.ReadString();
break;
}
}
}
#endif
}
#if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE
[global::System.Diagnostics.DebuggerNonUserCodeAttribute]
[global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
void pb::IBufferMessage.InternalMergeFrom(ref pb::ParseContext input) {
uint tag;
while ((tag = input.ReadTag()) != 0) {
switch(tag) {
default:
_unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, ref input);
break;
case 10: {
DevEui = input.ReadString();
break;
}
}
}
}
#endif
}
public sealed partial class GetDeviceNextFCntDownResponse : pb::IMessage<GetDeviceNextFCntDownResponse>
#if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE
, pb::IBufferMessage
#endif
{
private static readonly pb::MessageParser<GetDeviceNextFCntDownResponse> _parser = new pb::MessageParser<GetDeviceNextFCntDownResponse>(() => new GetDeviceNextFCntDownResponse());
private pb::UnknownFieldSet _unknownFields;
[global::System.Diagnostics.DebuggerNonUserCodeAttribute]
[global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
public static pb::MessageParser<GetDeviceNextFCntDownResponse> Parser { get { return _parser; } }
[global::System.Diagnostics.DebuggerNonUserCodeAttribute]
[global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
public static pbr::MessageDescriptor Descriptor {
get { return global::Chirpstack.Api.DeviceReflection.Descriptor.MessageTypes[36]; }
}
[global::System.Diagnostics.DebuggerNonUserCodeAttribute]
[global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
pbr::MessageDescriptor pb::IMessage.Descriptor {
get { return Descriptor; }
}
[global::System.Diagnostics.DebuggerNonUserCodeAttribute]
[global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
public GetDeviceNextFCntDownResponse() {
OnConstruction();
}
partial void OnConstruction();
[global::System.Diagnostics.DebuggerNonUserCodeAttribute]
[global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
public GetDeviceNextFCntDownResponse(GetDeviceNextFCntDownResponse other) : this() {
fCntDown_ = other.fCntDown_;
_unknownFields = pb::UnknownFieldSet.Clone(other._unknownFields);
}
[global::System.Diagnostics.DebuggerNonUserCodeAttribute]
[global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
public GetDeviceNextFCntDownResponse Clone() {
return new GetDeviceNextFCntDownResponse(this);
}
/// <summary>Field number for the "f_cnt_down" field.</summary>
public const int FCntDownFieldNumber = 1;
private uint fCntDown_;
/// <summary>
/// FCntDown.
/// </summary>
[global::System.Diagnostics.DebuggerNonUserCodeAttribute]
[global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
public uint FCntDown {
get { return fCntDown_; }
set {
fCntDown_ = value;
}
}
[global::System.Diagnostics.DebuggerNonUserCodeAttribute]
[global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
public override bool Equals(object other) {
return Equals(other as GetDeviceNextFCntDownResponse);
}
[global::System.Diagnostics.DebuggerNonUserCodeAttribute]
[global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
public bool Equals(GetDeviceNextFCntDownResponse other) {
if (ReferenceEquals(other, null)) {
return false;
}
if (ReferenceEquals(other, this)) {
return true;
}
if (FCntDown != other.FCntDown) return false;
return Equals(_unknownFields, other._unknownFields);
}
[global::System.Diagnostics.DebuggerNonUserCodeAttribute]
[global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
public override int GetHashCode() {
int hash = 1;
if (FCntDown != 0) hash ^= FCntDown.GetHashCode();
if (_unknownFields != null) {
hash ^= _unknownFields.GetHashCode();
}
return hash;
}
[global::System.Diagnostics.DebuggerNonUserCodeAttribute]
[global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
public override string ToString() {
return pb::JsonFormatter.ToDiagnosticString(this);
}
[global::System.Diagnostics.DebuggerNonUserCodeAttribute]
[global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
public void WriteTo(pb::CodedOutputStream output) {
#if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE
output.WriteRawMessage(this);
#else
if (FCntDown != 0) {
output.WriteRawTag(8);
output.WriteUInt32(FCntDown);
}
if (_unknownFields != null) {
_unknownFields.WriteTo(output);
}
#endif
}
#if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE
[global::System.Diagnostics.DebuggerNonUserCodeAttribute]
[global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
void pb::IBufferMessage.InternalWriteTo(ref pb::WriteContext output) {
if (FCntDown != 0) {
output.WriteRawTag(8);
output.WriteUInt32(FCntDown);
}
if (_unknownFields != null) {
_unknownFields.WriteTo(ref output);
}
}
#endif
[global::System.Diagnostics.DebuggerNonUserCodeAttribute]
[global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
public int CalculateSize() {
int size = 0;
if (FCntDown != 0) {
size += 1 + pb::CodedOutputStream.ComputeUInt32Size(FCntDown);
}
if (_unknownFields != null) {
size += _unknownFields.CalculateSize();
}
return size;
}
[global::System.Diagnostics.DebuggerNonUserCodeAttribute]
[global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
public void MergeFrom(GetDeviceNextFCntDownResponse other) {
if (other == null) {
return;
}
if (other.FCntDown != 0) {
FCntDown = other.FCntDown;
}
_unknownFields = pb::UnknownFieldSet.MergeFrom(_unknownFields, other._unknownFields);
}
[global::System.Diagnostics.DebuggerNonUserCodeAttribute]
[global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
public void MergeFrom(pb::CodedInputStream input) {
#if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE
input.ReadRawMessage(this);
#else
uint tag;
while ((tag = input.ReadTag()) != 0) {
switch(tag) {
default:
_unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, input);
break;
case 8: {
FCntDown = input.ReadUInt32();
break;
}
}
}
#endif
}
#if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE
[global::System.Diagnostics.DebuggerNonUserCodeAttribute]
[global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
void pb::IBufferMessage.InternalMergeFrom(ref pb::ParseContext input) {
uint tag;
while ((tag = input.ReadTag()) != 0) {
switch(tag) {
default:
_unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, ref input);
break;
case 8: {
FCntDown = input.ReadUInt32();
break;
}
}
}
}
#endif
}
#endregion
}

View File

@ -106,6 +106,10 @@ namespace Chirpstack.Api {
static readonly grpc::Marshaller<global::Chirpstack.Api.GetDeviceQueueItemsRequest> __Marshaller_api_GetDeviceQueueItemsRequest = grpc::Marshallers.Create(__Helper_SerializeMessage, context => __Helper_DeserializeMessage(context, global::Chirpstack.Api.GetDeviceQueueItemsRequest.Parser));
[global::System.CodeDom.Compiler.GeneratedCode("grpc_csharp_plugin", null)]
static readonly grpc::Marshaller<global::Chirpstack.Api.GetDeviceQueueItemsResponse> __Marshaller_api_GetDeviceQueueItemsResponse = grpc::Marshallers.Create(__Helper_SerializeMessage, context => __Helper_DeserializeMessage(context, global::Chirpstack.Api.GetDeviceQueueItemsResponse.Parser));
[global::System.CodeDom.Compiler.GeneratedCode("grpc_csharp_plugin", null)]
static readonly grpc::Marshaller<global::Chirpstack.Api.GetDeviceNextFCntDownRequest> __Marshaller_api_GetDeviceNextFCntDownRequest = grpc::Marshallers.Create(__Helper_SerializeMessage, context => __Helper_DeserializeMessage(context, global::Chirpstack.Api.GetDeviceNextFCntDownRequest.Parser));
[global::System.CodeDom.Compiler.GeneratedCode("grpc_csharp_plugin", null)]
static readonly grpc::Marshaller<global::Chirpstack.Api.GetDeviceNextFCntDownResponse> __Marshaller_api_GetDeviceNextFCntDownResponse = grpc::Marshallers.Create(__Helper_SerializeMessage, context => __Helper_DeserializeMessage(context, global::Chirpstack.Api.GetDeviceNextFCntDownResponse.Parser));
[global::System.CodeDom.Compiler.GeneratedCode("grpc_csharp_plugin", null)]
static readonly grpc::Method<global::Chirpstack.Api.CreateDeviceRequest, global::Google.Protobuf.WellKnownTypes.Empty> __Method_Create = new grpc::Method<global::Chirpstack.Api.CreateDeviceRequest, global::Google.Protobuf.WellKnownTypes.Empty>(
@ -259,6 +263,14 @@ namespace Chirpstack.Api {
__Marshaller_api_GetDeviceQueueItemsRequest,
__Marshaller_api_GetDeviceQueueItemsResponse);
[global::System.CodeDom.Compiler.GeneratedCode("grpc_csharp_plugin", null)]
static readonly grpc::Method<global::Chirpstack.Api.GetDeviceNextFCntDownRequest, global::Chirpstack.Api.GetDeviceNextFCntDownResponse> __Method_GetNextFCntDown = new grpc::Method<global::Chirpstack.Api.GetDeviceNextFCntDownRequest, global::Chirpstack.Api.GetDeviceNextFCntDownResponse>(
grpc::MethodType.Unary,
__ServiceName,
"GetNextFCntDown",
__Marshaller_api_GetDeviceNextFCntDownRequest,
__Marshaller_api_GetDeviceNextFCntDownResponse);
/// <summary>Service descriptor</summary>
public static global::Google.Protobuf.Reflection.ServiceDescriptor Descriptor
{
@ -503,6 +515,20 @@ namespace Chirpstack.Api {
throw new grpc::RpcException(new grpc::Status(grpc::StatusCode.Unimplemented, ""));
}
/// <summary>
/// GetNextFCntDown returns the next FCntDown to use for enqueing encrypted
/// downlinks. The difference with the DeviceActivation f_cont_down is that
/// this method takes potential existing queue-items into account.
/// </summary>
/// <param name="request">The request received from the client.</param>
/// <param name="context">The context of the server-side call handler being invoked.</param>
/// <returns>The response to send back to the client (wrapped by a task).</returns>
[global::System.CodeDom.Compiler.GeneratedCode("grpc_csharp_plugin", null)]
public virtual global::System.Threading.Tasks.Task<global::Chirpstack.Api.GetDeviceNextFCntDownResponse> GetNextFCntDown(global::Chirpstack.Api.GetDeviceNextFCntDownRequest request, grpc::ServerCallContext context)
{
throw new grpc::RpcException(new grpc::Status(grpc::StatusCode.Unimplemented, ""));
}
}
/// <summary>Client for DeviceService</summary>
@ -1468,6 +1494,62 @@ namespace Chirpstack.Api {
{
return CallInvoker.AsyncUnaryCall(__Method_GetQueue, null, options, request);
}
/// <summary>
/// GetNextFCntDown returns the next FCntDown to use for enqueing encrypted
/// downlinks. The difference with the DeviceActivation f_cont_down is that
/// this method takes potential existing queue-items into account.
/// </summary>
/// <param name="request">The request to send to the server.</param>
/// <param name="headers">The initial metadata to send with the call. This parameter is optional.</param>
/// <param name="deadline">An optional deadline for the call. The call will be cancelled if deadline is hit.</param>
/// <param name="cancellationToken">An optional token for canceling the call.</param>
/// <returns>The response received from the server.</returns>
[global::System.CodeDom.Compiler.GeneratedCode("grpc_csharp_plugin", null)]
public virtual global::Chirpstack.Api.GetDeviceNextFCntDownResponse GetNextFCntDown(global::Chirpstack.Api.GetDeviceNextFCntDownRequest request, grpc::Metadata headers = null, global::System.DateTime? deadline = null, global::System.Threading.CancellationToken cancellationToken = default(global::System.Threading.CancellationToken))
{
return GetNextFCntDown(request, new grpc::CallOptions(headers, deadline, cancellationToken));
}
/// <summary>
/// GetNextFCntDown returns the next FCntDown to use for enqueing encrypted
/// downlinks. The difference with the DeviceActivation f_cont_down is that
/// this method takes potential existing queue-items into account.
/// </summary>
/// <param name="request">The request to send to the server.</param>
/// <param name="options">The options for the call.</param>
/// <returns>The response received from the server.</returns>
[global::System.CodeDom.Compiler.GeneratedCode("grpc_csharp_plugin", null)]
public virtual global::Chirpstack.Api.GetDeviceNextFCntDownResponse GetNextFCntDown(global::Chirpstack.Api.GetDeviceNextFCntDownRequest request, grpc::CallOptions options)
{
return CallInvoker.BlockingUnaryCall(__Method_GetNextFCntDown, null, options, request);
}
/// <summary>
/// GetNextFCntDown returns the next FCntDown to use for enqueing encrypted
/// downlinks. The difference with the DeviceActivation f_cont_down is that
/// this method takes potential existing queue-items into account.
/// </summary>
/// <param name="request">The request to send to the server.</param>
/// <param name="headers">The initial metadata to send with the call. This parameter is optional.</param>
/// <param name="deadline">An optional deadline for the call. The call will be cancelled if deadline is hit.</param>
/// <param name="cancellationToken">An optional token for canceling the call.</param>
/// <returns>The call object.</returns>
[global::System.CodeDom.Compiler.GeneratedCode("grpc_csharp_plugin", null)]
public virtual grpc::AsyncUnaryCall<global::Chirpstack.Api.GetDeviceNextFCntDownResponse> GetNextFCntDownAsync(global::Chirpstack.Api.GetDeviceNextFCntDownRequest request, grpc::Metadata headers = null, global::System.DateTime? deadline = null, global::System.Threading.CancellationToken cancellationToken = default(global::System.Threading.CancellationToken))
{
return GetNextFCntDownAsync(request, new grpc::CallOptions(headers, deadline, cancellationToken));
}
/// <summary>
/// GetNextFCntDown returns the next FCntDown to use for enqueing encrypted
/// downlinks. The difference with the DeviceActivation f_cont_down is that
/// this method takes potential existing queue-items into account.
/// </summary>
/// <param name="request">The request to send to the server.</param>
/// <param name="options">The options for the call.</param>
/// <returns>The call object.</returns>
[global::System.CodeDom.Compiler.GeneratedCode("grpc_csharp_plugin", null)]
public virtual grpc::AsyncUnaryCall<global::Chirpstack.Api.GetDeviceNextFCntDownResponse> GetNextFCntDownAsync(global::Chirpstack.Api.GetDeviceNextFCntDownRequest request, grpc::CallOptions options)
{
return CallInvoker.AsyncUnaryCall(__Method_GetNextFCntDown, null, options, request);
}
/// <summary>Creates a new instance of client from given <c>ClientBaseConfiguration</c>.</summary>
[global::System.CodeDom.Compiler.GeneratedCode("grpc_csharp_plugin", null)]
protected override DeviceServiceClient NewInstance(ClientBaseConfiguration configuration)
@ -1500,7 +1582,8 @@ namespace Chirpstack.Api {
.AddMethod(__Method_GetLinkMetrics, serviceImpl.GetLinkMetrics)
.AddMethod(__Method_Enqueue, serviceImpl.Enqueue)
.AddMethod(__Method_FlushQueue, serviceImpl.FlushQueue)
.AddMethod(__Method_GetQueue, serviceImpl.GetQueue).Build();
.AddMethod(__Method_GetQueue, serviceImpl.GetQueue)
.AddMethod(__Method_GetNextFCntDown, serviceImpl.GetNextFCntDown).Build();
}
/// <summary>Register service method with a service binder with or without implementation. Useful when customizing the service binding logic.
@ -1529,6 +1612,7 @@ namespace Chirpstack.Api {
serviceBinder.AddMethod(__Method_Enqueue, serviceImpl == null ? null : new grpc::UnaryServerMethod<global::Chirpstack.Api.EnqueueDeviceQueueItemRequest, global::Chirpstack.Api.EnqueueDeviceQueueItemResponse>(serviceImpl.Enqueue));
serviceBinder.AddMethod(__Method_FlushQueue, serviceImpl == null ? null : new grpc::UnaryServerMethod<global::Chirpstack.Api.FlushDeviceQueueRequest, global::Google.Protobuf.WellKnownTypes.Empty>(serviceImpl.FlushQueue));
serviceBinder.AddMethod(__Method_GetQueue, serviceImpl == null ? null : new grpc::UnaryServerMethod<global::Chirpstack.Api.GetDeviceQueueItemsRequest, global::Chirpstack.Api.GetDeviceQueueItemsResponse>(serviceImpl.GetQueue));
serviceBinder.AddMethod(__Method_GetNextFCntDown, serviceImpl == null ? null : new grpc::UnaryServerMethod<global::Chirpstack.Api.GetDeviceNextFCntDownRequest, global::Chirpstack.Api.GetDeviceNextFCntDownResponse>(serviceImpl.GetNextFCntDown));
}
}

View File

@ -37,69 +37,75 @@ namespace Chirpstack.Integration {
"dHJ5EgsKA2tleRgBIAEoCRINCgV2YWx1ZRgCIAEoCToCOAEicwoRVXBsaW5r",
"UmVsYXlSeEluZm8SDwoHZGV2X2V1aRgBIAEoCRIRCglmcmVxdWVuY3kYAiAB",
"KA0SCgoCZHIYAyABKA0SCwoDc25yGAQgASgFEgwKBHJzc2kYBSABKAUSEwoL",
"d29yX2NoYW5uZWwYBiABKA0ikAMKC1VwbGlua0V2ZW50EhgKEGRlZHVwbGlj",
"YXRpb25faWQYASABKAkSKAoEdGltZRgCIAEoCzIaLmdvb2dsZS5wcm90b2J1",
"Zi5UaW1lc3RhbXASLAoLZGV2aWNlX2luZm8YAyABKAsyFy5pbnRlZ3JhdGlv",
"bi5EZXZpY2VJbmZvEhAKCGRldl9hZGRyGAQgASgJEgsKA2FkchgFIAEoCBIK",
"CgJkchgGIAEoDRINCgVmX2NudBgHIAEoDRIOCgZmX3BvcnQYCCABKA0SEQoJ",
"Y29uZmlybWVkGAkgASgIEgwKBGRhdGEYCiABKAwSJwoGb2JqZWN0GAsgASgL",
"MhcuZ29vZ2xlLnByb3RvYnVmLlN0cnVjdBIhCgdyeF9pbmZvGAwgAygLMhAu",
"Z3cuVXBsaW5rUnhJbmZvEiEKB3R4X2luZm8YDSABKAsyEC5ndy5VcGxpbmtU",
"eEluZm8SNQoNcmVsYXlfcnhfaW5mbxgOIAEoCzIeLmludGVncmF0aW9uLlVw",
"bGlua1JlbGF5UnhJbmZvIsYBCglKb2luRXZlbnQSGAoQZGVkdXBsaWNhdGlv",
"bl9pZBgBIAEoCRIoCgR0aW1lGAIgASgLMhouZ29vZ2xlLnByb3RvYnVmLlRp",
"bWVzdGFtcBIsCgtkZXZpY2VfaW5mbxgDIAEoCzIXLmludGVncmF0aW9uLkRl",
"dmljZUluZm8SEAoIZGV2X2FkZHIYBCABKAkSNQoNcmVsYXlfcnhfaW5mbxgF",
"IAEoCzIeLmludGVncmF0aW9uLlVwbGlua1JlbGF5UnhJbmZvIr0BCghBY2tF",
"dmVudBIYChBkZWR1cGxpY2F0aW9uX2lkGAEgASgJEigKBHRpbWUYAiABKAsy",
"Gi5nb29nbGUucHJvdG9idWYuVGltZXN0YW1wEiwKC2RldmljZV9pbmZvGAMg",
"ASgLMhcuaW50ZWdyYXRpb24uRGV2aWNlSW5mbxIVCg1xdWV1ZV9pdGVtX2lk",
"GAQgASgJEhQKDGFja25vd2xlZGdlZBgFIAEoCBISCgpmX2NudF9kb3duGAYg",
"ASgNIt0BCgpUeEFja0V2ZW50EhMKC2Rvd25saW5rX2lkGAEgASgNEigKBHRp",
"bWUYAiABKAsyGi5nb29nbGUucHJvdG9idWYuVGltZXN0YW1wEiwKC2Rldmlj",
"ZV9pbmZvGAMgASgLMhcuaW50ZWdyYXRpb24uRGV2aWNlSW5mbxIVCg1xdWV1",
"ZV9pdGVtX2lkGAQgASgJEhIKCmZfY250X2Rvd24YBSABKA0SEgoKZ2F0ZXdh",
"eV9pZBgGIAEoCRIjCgd0eF9pbmZvGAcgASgLMhIuZ3cuRG93bmxpbmtUeElu",
"Zm8ipgIKCExvZ0V2ZW50EigKBHRpbWUYASABKAsyGi5nb29nbGUucHJvdG9i",
"dWYuVGltZXN0YW1wEiwKC2RldmljZV9pbmZvGAIgASgLMhcuaW50ZWdyYXRp",
"b24uRGV2aWNlSW5mbxIkCgVsZXZlbBgDIAEoDjIVLmludGVncmF0aW9uLkxv",
"Z0xldmVsEiIKBGNvZGUYBCABKA4yFC5pbnRlZ3JhdGlvbi5Mb2dDb2RlEhMK",
"C2Rlc2NyaXB0aW9uGAUgASgJEjMKB2NvbnRleHQYBiADKAsyIi5pbnRlZ3Jh",
"dGlvbi5Mb2dFdmVudC5Db250ZXh0RW50cnkaLgoMQ29udGV4dEVudHJ5EgsK",
"A2tleRgBIAEoCRINCgV2YWx1ZRgCIAEoCToCOAEi6AEKC1N0YXR1c0V2ZW50",
"EhgKEGRlZHVwbGljYXRpb25faWQYASABKAkSKAoEdGltZRgCIAEoCzIaLmdv",
"b2dsZS5wcm90b2J1Zi5UaW1lc3RhbXASLAoLZGV2aWNlX2luZm8YAyABKAsy",
"Fy5pbnRlZ3JhdGlvbi5EZXZpY2VJbmZvEg4KBm1hcmdpbhgFIAEoBRIdChVl",
"eHRlcm5hbF9wb3dlcl9zb3VyY2UYBiABKAgSIQoZYmF0dGVyeV9sZXZlbF91",
"bmF2YWlsYWJsZRgHIAEoCBIVCg1iYXR0ZXJ5X2xldmVsGAggASgCIqUBCg1M",
"b2NhdGlvbkV2ZW50EhgKEGRlZHVwbGljYXRpb25faWQYASABKAkSKAoEdGlt",
"ZRgCIAEoCzIaLmdvb2dsZS5wcm90b2J1Zi5UaW1lc3RhbXASLAoLZGV2aWNl",
"X2luZm8YAyABKAsyFy5pbnRlZ3JhdGlvbi5EZXZpY2VJbmZvEiIKCGxvY2F0",
"aW9uGAQgASgLMhAuY29tbW9uLkxvY2F0aW9uItsBChBJbnRlZ3JhdGlvbkV2",
"ZW50EhgKEGRlZHVwbGljYXRpb25faWQYASABKAkSKAoEdGltZRgCIAEoCzIa",
"Lmdvb2dsZS5wcm90b2J1Zi5UaW1lc3RhbXASLAoLZGV2aWNlX2luZm8YAyAB",
"KAsyFy5pbnRlZ3JhdGlvbi5EZXZpY2VJbmZvEhgKEGludGVncmF0aW9uX25h",
"bWUYBCABKAkSEgoKZXZlbnRfdHlwZRgFIAEoCRInCgZvYmplY3QYBiABKAsy",
"Fy5nb29nbGUucHJvdG9idWYuU3RydWN0IogBCg9Eb3dubGlua0NvbW1hbmQS",
"CgoCaWQYASABKAkSDwoHZGV2X2V1aRgCIAEoCRIRCgljb25maXJtZWQYAyAB",
"KAgSDgoGZl9wb3J0GAQgASgNEgwKBGRhdGEYBSABKAwSJwoGb2JqZWN0GAYg",
"ASgLMhcuZ29vZ2xlLnByb3RvYnVmLlN0cnVjdCosCghMb2dMZXZlbBIICgRJ",
"TkZPEAASCwoHV0FSTklORxABEgkKBUVSUk9SEAIq2gEKB0xvZ0NvZGUSCwoH",
"VU5LTk9XThAAEhkKFURPV05MSU5LX1BBWUxPQURfU0laRRABEhAKDFVQTElO",
"S19DT0RFQxACEhIKDkRPV05MSU5LX0NPREVDEAMSCAoET1RBQRAEEhYKElVQ",
"TElOS19GX0NOVF9SRVNFVBAFEg4KClVQTElOS19NSUMQBhIfChtVUExJTktf",
"Rl9DTlRfUkVUUkFOU01JU1NJT04QBxIUChBET1dOTElOS19HQVRFV0FZEAgS",
"GAoUUkVMQVlfTkVXX0VORF9ERVZJQ0UQCUKBAQodaW8uY2hpcnBzdGFjay5h",
"cGkuaW50ZWdyYXRpb25CEEludGVncmF0aW9uUHJvdG9QAVozZ2l0aHViLmNv",
"bS9icm9jYWFyL2NoaXJwc3RhY2svYXBpL2dvL3Y0L2ludGVncmF0aW9uqgIW",
"Q2hpcnBzdGFjay5JbnRlZ3JhdGlvbmIGcHJvdG8z"));
"d29yX2NoYW5uZWwYBiABKA0iUwoRSm9pblNlcnZlckNvbnRleHQSFgoOc2Vz",
"c2lvbl9rZXlfaWQYASABKAkSJgoJYXBwX3Nfa2V5GAIgASgLMhMuY29tbW9u",
"LktleUVudmVsb3BlIs0DCgtVcGxpbmtFdmVudBIYChBkZWR1cGxpY2F0aW9u",
"X2lkGAEgASgJEigKBHRpbWUYAiABKAsyGi5nb29nbGUucHJvdG9idWYuVGlt",
"ZXN0YW1wEiwKC2RldmljZV9pbmZvGAMgASgLMhcuaW50ZWdyYXRpb24uRGV2",
"aWNlSW5mbxIQCghkZXZfYWRkchgEIAEoCRILCgNhZHIYBSABKAgSCgoCZHIY",
"BiABKA0SDQoFZl9jbnQYByABKA0SDgoGZl9wb3J0GAggASgNEhEKCWNvbmZp",
"cm1lZBgJIAEoCBIMCgRkYXRhGAogASgMEicKBm9iamVjdBgLIAEoCzIXLmdv",
"b2dsZS5wcm90b2J1Zi5TdHJ1Y3QSIQoHcnhfaW5mbxgMIAMoCzIQLmd3LlVw",
"bGlua1J4SW5mbxIhCgd0eF9pbmZvGA0gASgLMhAuZ3cuVXBsaW5rVHhJbmZv",
"EjUKDXJlbGF5X3J4X2luZm8YDiABKAsyHi5pbnRlZ3JhdGlvbi5VcGxpbmtS",
"ZWxheVJ4SW5mbxI7ChNqb2luX3NlcnZlcl9jb250ZXh0GA8gASgLMh4uaW50",
"ZWdyYXRpb24uSm9pblNlcnZlckNvbnRleHQigwIKCUpvaW5FdmVudBIYChBk",
"ZWR1cGxpY2F0aW9uX2lkGAEgASgJEigKBHRpbWUYAiABKAsyGi5nb29nbGUu",
"cHJvdG9idWYuVGltZXN0YW1wEiwKC2RldmljZV9pbmZvGAMgASgLMhcuaW50",
"ZWdyYXRpb24uRGV2aWNlSW5mbxIQCghkZXZfYWRkchgEIAEoCRI1Cg1yZWxh",
"eV9yeF9pbmZvGAUgASgLMh4uaW50ZWdyYXRpb24uVXBsaW5rUmVsYXlSeElu",
"Zm8SOwoTam9pbl9zZXJ2ZXJfY29udGV4dBgGIAEoCzIeLmludGVncmF0aW9u",
"LkpvaW5TZXJ2ZXJDb250ZXh0Ir0BCghBY2tFdmVudBIYChBkZWR1cGxpY2F0",
"aW9uX2lkGAEgASgJEigKBHRpbWUYAiABKAsyGi5nb29nbGUucHJvdG9idWYu",
"VGltZXN0YW1wEiwKC2RldmljZV9pbmZvGAMgASgLMhcuaW50ZWdyYXRpb24u",
"RGV2aWNlSW5mbxIVCg1xdWV1ZV9pdGVtX2lkGAQgASgJEhQKDGFja25vd2xl",
"ZGdlZBgFIAEoCBISCgpmX2NudF9kb3duGAYgASgNIt0BCgpUeEFja0V2ZW50",
"EhMKC2Rvd25saW5rX2lkGAEgASgNEigKBHRpbWUYAiABKAsyGi5nb29nbGUu",
"cHJvdG9idWYuVGltZXN0YW1wEiwKC2RldmljZV9pbmZvGAMgASgLMhcuaW50",
"ZWdyYXRpb24uRGV2aWNlSW5mbxIVCg1xdWV1ZV9pdGVtX2lkGAQgASgJEhIK",
"CmZfY250X2Rvd24YBSABKA0SEgoKZ2F0ZXdheV9pZBgGIAEoCRIjCgd0eF9p",
"bmZvGAcgASgLMhIuZ3cuRG93bmxpbmtUeEluZm8ipgIKCExvZ0V2ZW50EigK",
"BHRpbWUYASABKAsyGi5nb29nbGUucHJvdG9idWYuVGltZXN0YW1wEiwKC2Rl",
"dmljZV9pbmZvGAIgASgLMhcuaW50ZWdyYXRpb24uRGV2aWNlSW5mbxIkCgVs",
"ZXZlbBgDIAEoDjIVLmludGVncmF0aW9uLkxvZ0xldmVsEiIKBGNvZGUYBCAB",
"KA4yFC5pbnRlZ3JhdGlvbi5Mb2dDb2RlEhMKC2Rlc2NyaXB0aW9uGAUgASgJ",
"EjMKB2NvbnRleHQYBiADKAsyIi5pbnRlZ3JhdGlvbi5Mb2dFdmVudC5Db250",
"ZXh0RW50cnkaLgoMQ29udGV4dEVudHJ5EgsKA2tleRgBIAEoCRINCgV2YWx1",
"ZRgCIAEoCToCOAEi6AEKC1N0YXR1c0V2ZW50EhgKEGRlZHVwbGljYXRpb25f",
"aWQYASABKAkSKAoEdGltZRgCIAEoCzIaLmdvb2dsZS5wcm90b2J1Zi5UaW1l",
"c3RhbXASLAoLZGV2aWNlX2luZm8YAyABKAsyFy5pbnRlZ3JhdGlvbi5EZXZp",
"Y2VJbmZvEg4KBm1hcmdpbhgFIAEoBRIdChVleHRlcm5hbF9wb3dlcl9zb3Vy",
"Y2UYBiABKAgSIQoZYmF0dGVyeV9sZXZlbF91bmF2YWlsYWJsZRgHIAEoCBIV",
"Cg1iYXR0ZXJ5X2xldmVsGAggASgCIqUBCg1Mb2NhdGlvbkV2ZW50EhgKEGRl",
"ZHVwbGljYXRpb25faWQYASABKAkSKAoEdGltZRgCIAEoCzIaLmdvb2dsZS5w",
"cm90b2J1Zi5UaW1lc3RhbXASLAoLZGV2aWNlX2luZm8YAyABKAsyFy5pbnRl",
"Z3JhdGlvbi5EZXZpY2VJbmZvEiIKCGxvY2F0aW9uGAQgASgLMhAuY29tbW9u",
"LkxvY2F0aW9uItsBChBJbnRlZ3JhdGlvbkV2ZW50EhgKEGRlZHVwbGljYXRp",
"b25faWQYASABKAkSKAoEdGltZRgCIAEoCzIaLmdvb2dsZS5wcm90b2J1Zi5U",
"aW1lc3RhbXASLAoLZGV2aWNlX2luZm8YAyABKAsyFy5pbnRlZ3JhdGlvbi5E",
"ZXZpY2VJbmZvEhgKEGludGVncmF0aW9uX25hbWUYBCABKAkSEgoKZXZlbnRf",
"dHlwZRgFIAEoCRInCgZvYmplY3QYBiABKAsyFy5nb29nbGUucHJvdG9idWYu",
"U3RydWN0IogBCg9Eb3dubGlua0NvbW1hbmQSCgoCaWQYASABKAkSDwoHZGV2",
"X2V1aRgCIAEoCRIRCgljb25maXJtZWQYAyABKAgSDgoGZl9wb3J0GAQgASgN",
"EgwKBGRhdGEYBSABKAwSJwoGb2JqZWN0GAYgASgLMhcuZ29vZ2xlLnByb3Rv",
"YnVmLlN0cnVjdCosCghMb2dMZXZlbBIICgRJTkZPEAASCwoHV0FSTklORxAB",
"EgkKBUVSUk9SEAIq6gEKB0xvZ0NvZGUSCwoHVU5LTk9XThAAEhkKFURPV05M",
"SU5LX1BBWUxPQURfU0laRRABEhAKDFVQTElOS19DT0RFQxACEhIKDkRPV05M",
"SU5LX0NPREVDEAMSCAoET1RBQRAEEhYKElVQTElOS19GX0NOVF9SRVNFVBAF",
"Eg4KClVQTElOS19NSUMQBhIfChtVUExJTktfRl9DTlRfUkVUUkFOU01JU1NJ",
"T04QBxIUChBET1dOTElOS19HQVRFV0FZEAgSGAoUUkVMQVlfTkVXX0VORF9E",
"RVZJQ0UQCRIOCgpGX0NOVF9ET1dOEApCgQEKHWlvLmNoaXJwc3RhY2suYXBp",
"LmludGVncmF0aW9uQhBJbnRlZ3JhdGlvblByb3RvUAFaM2dpdGh1Yi5jb20v",
"YnJvY2Fhci9jaGlycHN0YWNrL2FwaS9nby92NC9pbnRlZ3JhdGlvbqoCFkNo",
"aXJwc3RhY2suSW50ZWdyYXRpb25iBnByb3RvMw=="));
descriptor = pbr::FileDescriptor.FromGeneratedCode(descriptorData,
new pbr::FileDescriptor[] { global::Chirpstack.Common.CommonReflection.Descriptor, global::Chirpstack.Gateway.GwReflection.Descriptor, global::Google.Protobuf.WellKnownTypes.TimestampReflection.Descriptor, global::Google.Protobuf.WellKnownTypes.StructReflection.Descriptor, },
new pbr::GeneratedClrTypeInfo(new[] {typeof(global::Chirpstack.Integration.LogLevel), typeof(global::Chirpstack.Integration.LogCode), }, null, new pbr::GeneratedClrTypeInfo[] {
new pbr::GeneratedClrTypeInfo(typeof(global::Chirpstack.Integration.DeviceInfo), global::Chirpstack.Integration.DeviceInfo.Parser, new[]{ "TenantId", "TenantName", "ApplicationId", "ApplicationName", "DeviceProfileId", "DeviceProfileName", "DeviceName", "DevEui", "DeviceClassEnabled", "Tags" }, null, null, null, new pbr::GeneratedClrTypeInfo[] { null, }),
new pbr::GeneratedClrTypeInfo(typeof(global::Chirpstack.Integration.UplinkRelayRxInfo), global::Chirpstack.Integration.UplinkRelayRxInfo.Parser, new[]{ "DevEui", "Frequency", "Dr", "Snr", "Rssi", "WorChannel" }, null, null, null, null),
new pbr::GeneratedClrTypeInfo(typeof(global::Chirpstack.Integration.UplinkEvent), global::Chirpstack.Integration.UplinkEvent.Parser, new[]{ "DeduplicationId", "Time", "DeviceInfo", "DevAddr", "Adr", "Dr", "FCnt", "FPort", "Confirmed", "Data", "Object", "RxInfo", "TxInfo", "RelayRxInfo" }, null, null, null, null),
new pbr::GeneratedClrTypeInfo(typeof(global::Chirpstack.Integration.JoinEvent), global::Chirpstack.Integration.JoinEvent.Parser, new[]{ "DeduplicationId", "Time", "DeviceInfo", "DevAddr", "RelayRxInfo" }, null, null, null, null),
new pbr::GeneratedClrTypeInfo(typeof(global::Chirpstack.Integration.JoinServerContext), global::Chirpstack.Integration.JoinServerContext.Parser, new[]{ "SessionKeyId", "AppSKey" }, null, null, null, null),
new pbr::GeneratedClrTypeInfo(typeof(global::Chirpstack.Integration.UplinkEvent), global::Chirpstack.Integration.UplinkEvent.Parser, new[]{ "DeduplicationId", "Time", "DeviceInfo", "DevAddr", "Adr", "Dr", "FCnt", "FPort", "Confirmed", "Data", "Object", "RxInfo", "TxInfo", "RelayRxInfo", "JoinServerContext" }, null, null, null, null),
new pbr::GeneratedClrTypeInfo(typeof(global::Chirpstack.Integration.JoinEvent), global::Chirpstack.Integration.JoinEvent.Parser, new[]{ "DeduplicationId", "Time", "DeviceInfo", "DevAddr", "RelayRxInfo", "JoinServerContext" }, null, null, null, null),
new pbr::GeneratedClrTypeInfo(typeof(global::Chirpstack.Integration.AckEvent), global::Chirpstack.Integration.AckEvent.Parser, new[]{ "DeduplicationId", "Time", "DeviceInfo", "QueueItemId", "Acknowledged", "FCntDown" }, null, null, null, null),
new pbr::GeneratedClrTypeInfo(typeof(global::Chirpstack.Integration.TxAckEvent), global::Chirpstack.Integration.TxAckEvent.Parser, new[]{ "DownlinkId", "Time", "DeviceInfo", "QueueItemId", "FCntDown", "GatewayId", "TxInfo" }, null, null, null, null),
new pbr::GeneratedClrTypeInfo(typeof(global::Chirpstack.Integration.LogEvent), global::Chirpstack.Integration.LogEvent.Parser, new[]{ "Time", "DeviceInfo", "Level", "Code", "Description", "Context" }, null, null, null, new pbr::GeneratedClrTypeInfo[] { null, }),
@ -170,6 +176,10 @@ namespace Chirpstack.Integration {
/// Relay new end-device.
/// </summary>
[pbr::OriginalName("RELAY_NEW_END_DEVICE")] RelayNewEndDevice = 9,
/// <summary>
/// Downlink frame-counter.
/// </summary>
[pbr::OriginalName("F_CNT_DOWN")] FCntDown = 10,
}
#endregion
@ -1114,6 +1124,250 @@ namespace Chirpstack.Integration {
}
/// <summary>
/// Join-Server context.
/// </summary>
public sealed partial class JoinServerContext : pb::IMessage<JoinServerContext>
#if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE
, pb::IBufferMessage
#endif
{
private static readonly pb::MessageParser<JoinServerContext> _parser = new pb::MessageParser<JoinServerContext>(() => new JoinServerContext());
private pb::UnknownFieldSet _unknownFields;
[global::System.Diagnostics.DebuggerNonUserCodeAttribute]
[global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
public static pb::MessageParser<JoinServerContext> Parser { get { return _parser; } }
[global::System.Diagnostics.DebuggerNonUserCodeAttribute]
[global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
public static pbr::MessageDescriptor Descriptor {
get { return global::Chirpstack.Integration.IntegrationReflection.Descriptor.MessageTypes[2]; }
}
[global::System.Diagnostics.DebuggerNonUserCodeAttribute]
[global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
pbr::MessageDescriptor pb::IMessage.Descriptor {
get { return Descriptor; }
}
[global::System.Diagnostics.DebuggerNonUserCodeAttribute]
[global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
public JoinServerContext() {
OnConstruction();
}
partial void OnConstruction();
[global::System.Diagnostics.DebuggerNonUserCodeAttribute]
[global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
public JoinServerContext(JoinServerContext other) : this() {
sessionKeyId_ = other.sessionKeyId_;
appSKey_ = other.appSKey_ != null ? other.appSKey_.Clone() : null;
_unknownFields = pb::UnknownFieldSet.Clone(other._unknownFields);
}
[global::System.Diagnostics.DebuggerNonUserCodeAttribute]
[global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
public JoinServerContext Clone() {
return new JoinServerContext(this);
}
/// <summary>Field number for the "session_key_id" field.</summary>
public const int SessionKeyIdFieldNumber = 1;
private string sessionKeyId_ = "";
/// <summary>
/// Session-key ID.
/// </summary>
[global::System.Diagnostics.DebuggerNonUserCodeAttribute]
[global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
public string SessionKeyId {
get { return sessionKeyId_; }
set {
sessionKeyId_ = pb::ProtoPreconditions.CheckNotNull(value, "value");
}
}
/// <summary>Field number for the "app_s_key" field.</summary>
public const int AppSKeyFieldNumber = 2;
private global::Chirpstack.Common.KeyEnvelope appSKey_;
/// <summary>
/// AppSKey envelope.
/// </summary>
[global::System.Diagnostics.DebuggerNonUserCodeAttribute]
[global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
public global::Chirpstack.Common.KeyEnvelope AppSKey {
get { return appSKey_; }
set {
appSKey_ = value;
}
}
[global::System.Diagnostics.DebuggerNonUserCodeAttribute]
[global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
public override bool Equals(object other) {
return Equals(other as JoinServerContext);
}
[global::System.Diagnostics.DebuggerNonUserCodeAttribute]
[global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
public bool Equals(JoinServerContext other) {
if (ReferenceEquals(other, null)) {
return false;
}
if (ReferenceEquals(other, this)) {
return true;
}
if (SessionKeyId != other.SessionKeyId) return false;
if (!object.Equals(AppSKey, other.AppSKey)) return false;
return Equals(_unknownFields, other._unknownFields);
}
[global::System.Diagnostics.DebuggerNonUserCodeAttribute]
[global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
public override int GetHashCode() {
int hash = 1;
if (SessionKeyId.Length != 0) hash ^= SessionKeyId.GetHashCode();
if (appSKey_ != null) hash ^= AppSKey.GetHashCode();
if (_unknownFields != null) {
hash ^= _unknownFields.GetHashCode();
}
return hash;
}
[global::System.Diagnostics.DebuggerNonUserCodeAttribute]
[global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
public override string ToString() {
return pb::JsonFormatter.ToDiagnosticString(this);
}
[global::System.Diagnostics.DebuggerNonUserCodeAttribute]
[global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
public void WriteTo(pb::CodedOutputStream output) {
#if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE
output.WriteRawMessage(this);
#else
if (SessionKeyId.Length != 0) {
output.WriteRawTag(10);
output.WriteString(SessionKeyId);
}
if (appSKey_ != null) {
output.WriteRawTag(18);
output.WriteMessage(AppSKey);
}
if (_unknownFields != null) {
_unknownFields.WriteTo(output);
}
#endif
}
#if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE
[global::System.Diagnostics.DebuggerNonUserCodeAttribute]
[global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
void pb::IBufferMessage.InternalWriteTo(ref pb::WriteContext output) {
if (SessionKeyId.Length != 0) {
output.WriteRawTag(10);
output.WriteString(SessionKeyId);
}
if (appSKey_ != null) {
output.WriteRawTag(18);
output.WriteMessage(AppSKey);
}
if (_unknownFields != null) {
_unknownFields.WriteTo(ref output);
}
}
#endif
[global::System.Diagnostics.DebuggerNonUserCodeAttribute]
[global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
public int CalculateSize() {
int size = 0;
if (SessionKeyId.Length != 0) {
size += 1 + pb::CodedOutputStream.ComputeStringSize(SessionKeyId);
}
if (appSKey_ != null) {
size += 1 + pb::CodedOutputStream.ComputeMessageSize(AppSKey);
}
if (_unknownFields != null) {
size += _unknownFields.CalculateSize();
}
return size;
}
[global::System.Diagnostics.DebuggerNonUserCodeAttribute]
[global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
public void MergeFrom(JoinServerContext other) {
if (other == null) {
return;
}
if (other.SessionKeyId.Length != 0) {
SessionKeyId = other.SessionKeyId;
}
if (other.appSKey_ != null) {
if (appSKey_ == null) {
AppSKey = new global::Chirpstack.Common.KeyEnvelope();
}
AppSKey.MergeFrom(other.AppSKey);
}
_unknownFields = pb::UnknownFieldSet.MergeFrom(_unknownFields, other._unknownFields);
}
[global::System.Diagnostics.DebuggerNonUserCodeAttribute]
[global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
public void MergeFrom(pb::CodedInputStream input) {
#if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE
input.ReadRawMessage(this);
#else
uint tag;
while ((tag = input.ReadTag()) != 0) {
switch(tag) {
default:
_unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, input);
break;
case 10: {
SessionKeyId = input.ReadString();
break;
}
case 18: {
if (appSKey_ == null) {
AppSKey = new global::Chirpstack.Common.KeyEnvelope();
}
input.ReadMessage(AppSKey);
break;
}
}
}
#endif
}
#if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE
[global::System.Diagnostics.DebuggerNonUserCodeAttribute]
[global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
void pb::IBufferMessage.InternalMergeFrom(ref pb::ParseContext input) {
uint tag;
while ((tag = input.ReadTag()) != 0) {
switch(tag) {
default:
_unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, ref input);
break;
case 10: {
SessionKeyId = input.ReadString();
break;
}
case 18: {
if (appSKey_ == null) {
AppSKey = new global::Chirpstack.Common.KeyEnvelope();
}
input.ReadMessage(AppSKey);
break;
}
}
}
}
#endif
}
/// <summary>
/// UplinkEvent is the message sent when an uplink payload has been received.
/// </summary>
@ -1131,7 +1385,7 @@ namespace Chirpstack.Integration {
[global::System.Diagnostics.DebuggerNonUserCodeAttribute]
[global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
public static pbr::MessageDescriptor Descriptor {
get { return global::Chirpstack.Integration.IntegrationReflection.Descriptor.MessageTypes[2]; }
get { return global::Chirpstack.Integration.IntegrationReflection.Descriptor.MessageTypes[3]; }
}
[global::System.Diagnostics.DebuggerNonUserCodeAttribute]
@ -1165,6 +1419,7 @@ namespace Chirpstack.Integration {
rxInfo_ = other.rxInfo_.Clone();
txInfo_ = other.txInfo_ != null ? other.txInfo_.Clone() : null;
relayRxInfo_ = other.relayRxInfo_ != null ? other.relayRxInfo_.Clone() : null;
joinServerContext_ = other.joinServerContext_ != null ? other.joinServerContext_.Clone() : null;
_unknownFields = pb::UnknownFieldSet.Clone(other._unknownFields);
}
@ -1384,6 +1639,24 @@ namespace Chirpstack.Integration {
}
}
/// <summary>Field number for the "join_server_context" field.</summary>
public const int JoinServerContextFieldNumber = 15;
private global::Chirpstack.Integration.JoinServerContext joinServerContext_;
/// <summary>
/// Join-Server context.
/// A non-empty value indicatest that ChirpStack does not have access to
/// the AppSKey and that the encryption / decryption of the payloads is
/// the responsibility of the end-application.
/// </summary>
[global::System.Diagnostics.DebuggerNonUserCodeAttribute]
[global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
public global::Chirpstack.Integration.JoinServerContext JoinServerContext {
get { return joinServerContext_; }
set {
joinServerContext_ = value;
}
}
[global::System.Diagnostics.DebuggerNonUserCodeAttribute]
[global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
public override bool Equals(object other) {
@ -1413,6 +1686,7 @@ namespace Chirpstack.Integration {
if(!rxInfo_.Equals(other.rxInfo_)) return false;
if (!object.Equals(TxInfo, other.TxInfo)) return false;
if (!object.Equals(RelayRxInfo, other.RelayRxInfo)) return false;
if (!object.Equals(JoinServerContext, other.JoinServerContext)) return false;
return Equals(_unknownFields, other._unknownFields);
}
@ -1434,6 +1708,7 @@ namespace Chirpstack.Integration {
hash ^= rxInfo_.GetHashCode();
if (txInfo_ != null) hash ^= TxInfo.GetHashCode();
if (relayRxInfo_ != null) hash ^= RelayRxInfo.GetHashCode();
if (joinServerContext_ != null) hash ^= JoinServerContext.GetHashCode();
if (_unknownFields != null) {
hash ^= _unknownFields.GetHashCode();
}
@ -1505,6 +1780,10 @@ namespace Chirpstack.Integration {
output.WriteRawTag(114);
output.WriteMessage(RelayRxInfo);
}
if (joinServerContext_ != null) {
output.WriteRawTag(122);
output.WriteMessage(JoinServerContext);
}
if (_unknownFields != null) {
_unknownFields.WriteTo(output);
}
@ -1568,6 +1847,10 @@ namespace Chirpstack.Integration {
output.WriteRawTag(114);
output.WriteMessage(RelayRxInfo);
}
if (joinServerContext_ != null) {
output.WriteRawTag(122);
output.WriteMessage(JoinServerContext);
}
if (_unknownFields != null) {
_unknownFields.WriteTo(ref output);
}
@ -1618,6 +1901,9 @@ namespace Chirpstack.Integration {
if (relayRxInfo_ != null) {
size += 1 + pb::CodedOutputStream.ComputeMessageSize(RelayRxInfo);
}
if (joinServerContext_ != null) {
size += 1 + pb::CodedOutputStream.ComputeMessageSize(JoinServerContext);
}
if (_unknownFields != null) {
size += _unknownFields.CalculateSize();
}
@ -1685,6 +1971,12 @@ namespace Chirpstack.Integration {
}
RelayRxInfo.MergeFrom(other.RelayRxInfo);
}
if (other.joinServerContext_ != null) {
if (joinServerContext_ == null) {
JoinServerContext = new global::Chirpstack.Integration.JoinServerContext();
}
JoinServerContext.MergeFrom(other.JoinServerContext);
}
_unknownFields = pb::UnknownFieldSet.MergeFrom(_unknownFields, other._unknownFields);
}
@ -1771,6 +2063,13 @@ namespace Chirpstack.Integration {
input.ReadMessage(RelayRxInfo);
break;
}
case 122: {
if (joinServerContext_ == null) {
JoinServerContext = new global::Chirpstack.Integration.JoinServerContext();
}
input.ReadMessage(JoinServerContext);
break;
}
}
}
#endif
@ -1857,6 +2156,13 @@ namespace Chirpstack.Integration {
input.ReadMessage(RelayRxInfo);
break;
}
case 122: {
if (joinServerContext_ == null) {
JoinServerContext = new global::Chirpstack.Integration.JoinServerContext();
}
input.ReadMessage(JoinServerContext);
break;
}
}
}
}
@ -1882,7 +2188,7 @@ namespace Chirpstack.Integration {
[global::System.Diagnostics.DebuggerNonUserCodeAttribute]
[global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
public static pbr::MessageDescriptor Descriptor {
get { return global::Chirpstack.Integration.IntegrationReflection.Descriptor.MessageTypes[3]; }
get { return global::Chirpstack.Integration.IntegrationReflection.Descriptor.MessageTypes[4]; }
}
[global::System.Diagnostics.DebuggerNonUserCodeAttribute]
@ -1907,6 +2213,7 @@ namespace Chirpstack.Integration {
deviceInfo_ = other.deviceInfo_ != null ? other.deviceInfo_.Clone() : null;
devAddr_ = other.devAddr_;
relayRxInfo_ = other.relayRxInfo_ != null ? other.relayRxInfo_.Clone() : null;
joinServerContext_ = other.joinServerContext_ != null ? other.joinServerContext_.Clone() : null;
_unknownFields = pb::UnknownFieldSet.Clone(other._unknownFields);
}
@ -1991,6 +2298,24 @@ namespace Chirpstack.Integration {
}
}
/// <summary>Field number for the "join_server_context" field.</summary>
public const int JoinServerContextFieldNumber = 6;
private global::Chirpstack.Integration.JoinServerContext joinServerContext_;
/// <summary>
/// Join-Server context.
/// A non-empty value indicatest that ChirpStack does not have access to
/// the AppSKey and that the encryption / decryption of the payloads is
/// the responsibility of the end-application.
/// </summary>
[global::System.Diagnostics.DebuggerNonUserCodeAttribute]
[global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
public global::Chirpstack.Integration.JoinServerContext JoinServerContext {
get { return joinServerContext_; }
set {
joinServerContext_ = value;
}
}
[global::System.Diagnostics.DebuggerNonUserCodeAttribute]
[global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
public override bool Equals(object other) {
@ -2011,6 +2336,7 @@ namespace Chirpstack.Integration {
if (!object.Equals(DeviceInfo, other.DeviceInfo)) return false;
if (DevAddr != other.DevAddr) return false;
if (!object.Equals(RelayRxInfo, other.RelayRxInfo)) return false;
if (!object.Equals(JoinServerContext, other.JoinServerContext)) return false;
return Equals(_unknownFields, other._unknownFields);
}
@ -2023,6 +2349,7 @@ namespace Chirpstack.Integration {
if (deviceInfo_ != null) hash ^= DeviceInfo.GetHashCode();
if (DevAddr.Length != 0) hash ^= DevAddr.GetHashCode();
if (relayRxInfo_ != null) hash ^= RelayRxInfo.GetHashCode();
if (joinServerContext_ != null) hash ^= JoinServerContext.GetHashCode();
if (_unknownFields != null) {
hash ^= _unknownFields.GetHashCode();
}
@ -2061,6 +2388,10 @@ namespace Chirpstack.Integration {
output.WriteRawTag(42);
output.WriteMessage(RelayRxInfo);
}
if (joinServerContext_ != null) {
output.WriteRawTag(50);
output.WriteMessage(JoinServerContext);
}
if (_unknownFields != null) {
_unknownFields.WriteTo(output);
}
@ -2091,6 +2422,10 @@ namespace Chirpstack.Integration {
output.WriteRawTag(42);
output.WriteMessage(RelayRxInfo);
}
if (joinServerContext_ != null) {
output.WriteRawTag(50);
output.WriteMessage(JoinServerContext);
}
if (_unknownFields != null) {
_unknownFields.WriteTo(ref output);
}
@ -2116,6 +2451,9 @@ namespace Chirpstack.Integration {
if (relayRxInfo_ != null) {
size += 1 + pb::CodedOutputStream.ComputeMessageSize(RelayRxInfo);
}
if (joinServerContext_ != null) {
size += 1 + pb::CodedOutputStream.ComputeMessageSize(JoinServerContext);
}
if (_unknownFields != null) {
size += _unknownFields.CalculateSize();
}
@ -2152,6 +2490,12 @@ namespace Chirpstack.Integration {
}
RelayRxInfo.MergeFrom(other.RelayRxInfo);
}
if (other.joinServerContext_ != null) {
if (joinServerContext_ == null) {
JoinServerContext = new global::Chirpstack.Integration.JoinServerContext();
}
JoinServerContext.MergeFrom(other.JoinServerContext);
}
_unknownFields = pb::UnknownFieldSet.MergeFrom(_unknownFields, other._unknownFields);
}
@ -2196,6 +2540,13 @@ namespace Chirpstack.Integration {
input.ReadMessage(RelayRxInfo);
break;
}
case 50: {
if (joinServerContext_ == null) {
JoinServerContext = new global::Chirpstack.Integration.JoinServerContext();
}
input.ReadMessage(JoinServerContext);
break;
}
}
}
#endif
@ -2240,6 +2591,13 @@ namespace Chirpstack.Integration {
input.ReadMessage(RelayRxInfo);
break;
}
case 50: {
if (joinServerContext_ == null) {
JoinServerContext = new global::Chirpstack.Integration.JoinServerContext();
}
input.ReadMessage(JoinServerContext);
break;
}
}
}
}
@ -2265,7 +2623,7 @@ namespace Chirpstack.Integration {
[global::System.Diagnostics.DebuggerNonUserCodeAttribute]
[global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
public static pbr::MessageDescriptor Descriptor {
get { return global::Chirpstack.Integration.IntegrationReflection.Descriptor.MessageTypes[4]; }
get { return global::Chirpstack.Integration.IntegrationReflection.Descriptor.MessageTypes[5]; }
}
[global::System.Diagnostics.DebuggerNonUserCodeAttribute]
@ -2680,7 +3038,7 @@ namespace Chirpstack.Integration {
[global::System.Diagnostics.DebuggerNonUserCodeAttribute]
[global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
public static pbr::MessageDescriptor Descriptor {
get { return global::Chirpstack.Integration.IntegrationReflection.Descriptor.MessageTypes[5]; }
get { return global::Chirpstack.Integration.IntegrationReflection.Descriptor.MessageTypes[6]; }
}
[global::System.Diagnostics.DebuggerNonUserCodeAttribute]
@ -3142,7 +3500,7 @@ namespace Chirpstack.Integration {
[global::System.Diagnostics.DebuggerNonUserCodeAttribute]
[global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
public static pbr::MessageDescriptor Descriptor {
get { return global::Chirpstack.Integration.IntegrationReflection.Descriptor.MessageTypes[6]; }
get { return global::Chirpstack.Integration.IntegrationReflection.Descriptor.MessageTypes[7]; }
}
[global::System.Diagnostics.DebuggerNonUserCodeAttribute]
@ -3545,7 +3903,7 @@ namespace Chirpstack.Integration {
[global::System.Diagnostics.DebuggerNonUserCodeAttribute]
[global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
public static pbr::MessageDescriptor Descriptor {
get { return global::Chirpstack.Integration.IntegrationReflection.Descriptor.MessageTypes[7]; }
get { return global::Chirpstack.Integration.IntegrationReflection.Descriptor.MessageTypes[8]; }
}
[global::System.Diagnostics.DebuggerNonUserCodeAttribute]
@ -3999,7 +4357,7 @@ namespace Chirpstack.Integration {
[global::System.Diagnostics.DebuggerNonUserCodeAttribute]
[global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
public static pbr::MessageDescriptor Descriptor {
get { return global::Chirpstack.Integration.IntegrationReflection.Descriptor.MessageTypes[8]; }
get { return global::Chirpstack.Integration.IntegrationReflection.Descriptor.MessageTypes[9]; }
}
[global::System.Diagnostics.DebuggerNonUserCodeAttribute]
@ -4343,7 +4701,7 @@ namespace Chirpstack.Integration {
[global::System.Diagnostics.DebuggerNonUserCodeAttribute]
[global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
public static pbr::MessageDescriptor Descriptor {
get { return global::Chirpstack.Integration.IntegrationReflection.Descriptor.MessageTypes[9]; }
get { return global::Chirpstack.Integration.IntegrationReflection.Descriptor.MessageTypes[10]; }
}
[global::System.Diagnostics.DebuggerNonUserCodeAttribute]
@ -4766,7 +5124,7 @@ namespace Chirpstack.Integration {
[global::System.Diagnostics.DebuggerNonUserCodeAttribute]
[global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
public static pbr::MessageDescriptor Descriptor {
get { return global::Chirpstack.Integration.IntegrationReflection.Descriptor.MessageTypes[10]; }
get { return global::Chirpstack.Integration.IntegrationReflection.Descriptor.MessageTypes[11]; }
}
[global::System.Diagnostics.DebuggerNonUserCodeAttribute]

View File

@ -1888,11 +1888,18 @@ type DeviceQueueItem struct {
// object to bytes.
Object *structpb.Struct `protobuf:"bytes,6,opt,name=object,proto3" json:"object,omitempty"`
// Is pending.
// This is set to true when the downlink is pending.
// This is set by ChirpStack to true when the downlink is pending (e.g. it
// has been sent, but a confirmation is still pending).
IsPending bool `protobuf:"varint,7,opt,name=is_pending,json=isPending,proto3" json:"is_pending,omitempty"`
// Downlink frame-counter.
// This is set when the payload has been sent as downlink.
// Do not set this for plain-text data payloads. It will be automatically set
// by ChirpStack when the payload has been sent as downlink.
FCntDown uint32 `protobuf:"varint,8,opt,name=f_cnt_down,json=fCntDown,proto3" json:"f_cnt_down,omitempty"`
// Is encrypted.
// This must be set to true if the end-application has already encrypted
// the data payload. In this case, the f_cnt_down field must be set to
// the corresponding frame-counter which has been used during the encryption.
IsEncrypted bool `protobuf:"varint,9,opt,name=is_encrypted,json=isEncrypted,proto3" json:"is_encrypted,omitempty"`
}
func (x *DeviceQueueItem) Reset() {
@ -1983,6 +1990,13 @@ func (x *DeviceQueueItem) GetFCntDown() uint32 {
return 0
}
func (x *DeviceQueueItem) GetIsEncrypted() bool {
if x != nil {
return x.IsEncrypted
}
return false
}
type EnqueueDeviceQueueItemRequest struct {
state protoimpl.MessageState
sizeCache protoimpl.SizeCache
@ -2288,6 +2302,102 @@ func (x *FlushDevNoncesRequest) GetDevEui() string {
return ""
}
type GetDeviceNextFCntDownRequest struct {
state protoimpl.MessageState
sizeCache protoimpl.SizeCache
unknownFields protoimpl.UnknownFields
// Device EUI (EUI64).
DevEui string `protobuf:"bytes,1,opt,name=dev_eui,json=devEui,proto3" json:"dev_eui,omitempty"`
}
func (x *GetDeviceNextFCntDownRequest) Reset() {
*x = GetDeviceNextFCntDownRequest{}
if protoimpl.UnsafeEnabled {
mi := &file_api_device_proto_msgTypes[35]
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms.StoreMessageInfo(mi)
}
}
func (x *GetDeviceNextFCntDownRequest) String() string {
return protoimpl.X.MessageStringOf(x)
}
func (*GetDeviceNextFCntDownRequest) ProtoMessage() {}
func (x *GetDeviceNextFCntDownRequest) ProtoReflect() protoreflect.Message {
mi := &file_api_device_proto_msgTypes[35]
if protoimpl.UnsafeEnabled && x != nil {
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
if ms.LoadMessageInfo() == nil {
ms.StoreMessageInfo(mi)
}
return ms
}
return mi.MessageOf(x)
}
// Deprecated: Use GetDeviceNextFCntDownRequest.ProtoReflect.Descriptor instead.
func (*GetDeviceNextFCntDownRequest) Descriptor() ([]byte, []int) {
return file_api_device_proto_rawDescGZIP(), []int{35}
}
func (x *GetDeviceNextFCntDownRequest) GetDevEui() string {
if x != nil {
return x.DevEui
}
return ""
}
type GetDeviceNextFCntDownResponse struct {
state protoimpl.MessageState
sizeCache protoimpl.SizeCache
unknownFields protoimpl.UnknownFields
// FCntDown.
FCntDown uint32 `protobuf:"varint,1,opt,name=f_cnt_down,json=fCntDown,proto3" json:"f_cnt_down,omitempty"`
}
func (x *GetDeviceNextFCntDownResponse) Reset() {
*x = GetDeviceNextFCntDownResponse{}
if protoimpl.UnsafeEnabled {
mi := &file_api_device_proto_msgTypes[36]
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms.StoreMessageInfo(mi)
}
}
func (x *GetDeviceNextFCntDownResponse) String() string {
return protoimpl.X.MessageStringOf(x)
}
func (*GetDeviceNextFCntDownResponse) ProtoMessage() {}
func (x *GetDeviceNextFCntDownResponse) ProtoReflect() protoreflect.Message {
mi := &file_api_device_proto_msgTypes[36]
if protoimpl.UnsafeEnabled && x != nil {
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
if ms.LoadMessageInfo() == nil {
ms.StoreMessageInfo(mi)
}
return ms
}
return mi.MessageOf(x)
}
// Deprecated: Use GetDeviceNextFCntDownResponse.ProtoReflect.Descriptor instead.
func (*GetDeviceNextFCntDownResponse) Descriptor() ([]byte, []int) {
return file_api_device_proto_rawDescGZIP(), []int{36}
}
func (x *GetDeviceNextFCntDownResponse) GetFCntDown() uint32 {
if x != nil {
return x.FCntDown
}
return 0
}
var File_api_device_proto protoreflect.FileDescriptor
var file_api_device_proto_rawDesc = []byte{
@ -2567,7 +2677,7 @@ var file_api_device_proto_rawDesc = []byte{
0x6b, 0x65, 0x74, 0x73, 0x50, 0x65, 0x72, 0x44, 0x72, 0x12, 0x26, 0x0a, 0x06, 0x65, 0x72, 0x72,
0x6f, 0x72, 0x73, 0x18, 0x06, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x0e, 0x2e, 0x63, 0x6f, 0x6d, 0x6d,
0x6f, 0x6e, 0x2e, 0x4d, 0x65, 0x74, 0x72, 0x69, 0x63, 0x52, 0x06, 0x65, 0x72, 0x72, 0x6f, 0x72,
0x73, 0x22, 0xf1, 0x01, 0x0a, 0x0f, 0x44, 0x65, 0x76, 0x69, 0x63, 0x65, 0x51, 0x75, 0x65, 0x75,
0x73, 0x22, 0x94, 0x02, 0x0a, 0x0f, 0x44, 0x65, 0x76, 0x69, 0x63, 0x65, 0x51, 0x75, 0x65, 0x75,
0x65, 0x49, 0x74, 0x65, 0x6d, 0x12, 0x0e, 0x0a, 0x02, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28,
0x09, 0x52, 0x02, 0x69, 0x64, 0x12, 0x17, 0x0a, 0x07, 0x64, 0x65, 0x76, 0x5f, 0x65, 0x75, 0x69,
0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x06, 0x64, 0x65, 0x76, 0x45, 0x75, 0x69, 0x12, 0x1c,
@ -2582,174 +2692,193 @@ var file_api_device_proto_rawDesc = []byte{
0x65, 0x6e, 0x64, 0x69, 0x6e, 0x67, 0x18, 0x07, 0x20, 0x01, 0x28, 0x08, 0x52, 0x09, 0x69, 0x73,
0x50, 0x65, 0x6e, 0x64, 0x69, 0x6e, 0x67, 0x12, 0x1c, 0x0a, 0x0a, 0x66, 0x5f, 0x63, 0x6e, 0x74,
0x5f, 0x64, 0x6f, 0x77, 0x6e, 0x18, 0x08, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x08, 0x66, 0x43, 0x6e,
0x74, 0x44, 0x6f, 0x77, 0x6e, 0x22, 0x54, 0x0a, 0x1d, 0x45, 0x6e, 0x71, 0x75, 0x65, 0x75, 0x65,
0x44, 0x65, 0x76, 0x69, 0x63, 0x65, 0x51, 0x75, 0x65, 0x75, 0x65, 0x49, 0x74, 0x65, 0x6d, 0x52,
0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x33, 0x0a, 0x0a, 0x71, 0x75, 0x65, 0x75, 0x65, 0x5f,
0x69, 0x74, 0x65, 0x6d, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x14, 0x2e, 0x61, 0x70, 0x69,
0x74, 0x44, 0x6f, 0x77, 0x6e, 0x12, 0x21, 0x0a, 0x0c, 0x69, 0x73, 0x5f, 0x65, 0x6e, 0x63, 0x72,
0x79, 0x70, 0x74, 0x65, 0x64, 0x18, 0x09, 0x20, 0x01, 0x28, 0x08, 0x52, 0x0b, 0x69, 0x73, 0x45,
0x6e, 0x63, 0x72, 0x79, 0x70, 0x74, 0x65, 0x64, 0x22, 0x54, 0x0a, 0x1d, 0x45, 0x6e, 0x71, 0x75,
0x65, 0x75, 0x65, 0x44, 0x65, 0x76, 0x69, 0x63, 0x65, 0x51, 0x75, 0x65, 0x75, 0x65, 0x49, 0x74,
0x65, 0x6d, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x33, 0x0a, 0x0a, 0x71, 0x75, 0x65,
0x75, 0x65, 0x5f, 0x69, 0x74, 0x65, 0x6d, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x14, 0x2e,
0x61, 0x70, 0x69, 0x2e, 0x44, 0x65, 0x76, 0x69, 0x63, 0x65, 0x51, 0x75, 0x65, 0x75, 0x65, 0x49,
0x74, 0x65, 0x6d, 0x52, 0x09, 0x71, 0x75, 0x65, 0x75, 0x65, 0x49, 0x74, 0x65, 0x6d, 0x22, 0x30,
0x0a, 0x1e, 0x45, 0x6e, 0x71, 0x75, 0x65, 0x75, 0x65, 0x44, 0x65, 0x76, 0x69, 0x63, 0x65, 0x51,
0x75, 0x65, 0x75, 0x65, 0x49, 0x74, 0x65, 0x6d, 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, 0x32, 0x0a, 0x17, 0x46, 0x6c, 0x75, 0x73, 0x68, 0x44, 0x65, 0x76, 0x69, 0x63, 0x65, 0x51,
0x75, 0x65, 0x75, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x17, 0x0a, 0x07, 0x64,
0x65, 0x76, 0x5f, 0x65, 0x75, 0x69, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x06, 0x64, 0x65,
0x76, 0x45, 0x75, 0x69, 0x22, 0x54, 0x0a, 0x1a, 0x47, 0x65, 0x74, 0x44, 0x65, 0x76, 0x69, 0x63,
0x65, 0x51, 0x75, 0x65, 0x75, 0x65, 0x49, 0x74, 0x65, 0x6d, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65,
0x73, 0x74, 0x12, 0x17, 0x0a, 0x07, 0x64, 0x65, 0x76, 0x5f, 0x65, 0x75, 0x69, 0x18, 0x01, 0x20,
0x01, 0x28, 0x09, 0x52, 0x06, 0x64, 0x65, 0x76, 0x45, 0x75, 0x69, 0x12, 0x1d, 0x0a, 0x0a, 0x63,
0x6f, 0x75, 0x6e, 0x74, 0x5f, 0x6f, 0x6e, 0x6c, 0x79, 0x18, 0x02, 0x20, 0x01, 0x28, 0x08, 0x52,
0x09, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x4f, 0x6e, 0x6c, 0x79, 0x22, 0x6c, 0x0a, 0x1b, 0x47, 0x65,
0x74, 0x44, 0x65, 0x76, 0x69, 0x63, 0x65, 0x51, 0x75, 0x65, 0x75, 0x65, 0x49, 0x74, 0x65, 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, 0x2c, 0x0a, 0x06, 0x72, 0x65,
0x73, 0x75, 0x6c, 0x74, 0x18, 0x02, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x14, 0x2e, 0x61, 0x70, 0x69,
0x2e, 0x44, 0x65, 0x76, 0x69, 0x63, 0x65, 0x51, 0x75, 0x65, 0x75, 0x65, 0x49, 0x74, 0x65, 0x6d,
0x52, 0x09, 0x71, 0x75, 0x65, 0x75, 0x65, 0x49, 0x74, 0x65, 0x6d, 0x22, 0x30, 0x0a, 0x1e, 0x45,
0x6e, 0x71, 0x75, 0x65, 0x75, 0x65, 0x44, 0x65, 0x76, 0x69, 0x63, 0x65, 0x51, 0x75, 0x65, 0x75,
0x65, 0x49, 0x74, 0x65, 0x6d, 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, 0x32, 0x0a,
0x17, 0x46, 0x6c, 0x75, 0x73, 0x68, 0x44, 0x65, 0x76, 0x69, 0x63, 0x65, 0x51, 0x75, 0x65, 0x75,
0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x17, 0x0a, 0x07, 0x64, 0x65, 0x76, 0x5f,
0x65, 0x75, 0x69, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x06, 0x64, 0x65, 0x76, 0x45, 0x75,
0x69, 0x22, 0x54, 0x0a, 0x1a, 0x47, 0x65, 0x74, 0x44, 0x65, 0x76, 0x69, 0x63, 0x65, 0x51, 0x75,
0x65, 0x75, 0x65, 0x49, 0x74, 0x65, 0x6d, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12,
0x17, 0x0a, 0x07, 0x64, 0x65, 0x76, 0x5f, 0x65, 0x75, 0x69, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09,
0x52, 0x06, 0x64, 0x65, 0x76, 0x45, 0x75, 0x69, 0x12, 0x1d, 0x0a, 0x0a, 0x63, 0x6f, 0x75, 0x6e,
0x74, 0x5f, 0x6f, 0x6e, 0x6c, 0x79, 0x18, 0x02, 0x20, 0x01, 0x28, 0x08, 0x52, 0x09, 0x63, 0x6f,
0x75, 0x6e, 0x74, 0x4f, 0x6e, 0x6c, 0x79, 0x22, 0x6c, 0x0a, 0x1b, 0x47, 0x65, 0x74, 0x44, 0x65,
0x76, 0x69, 0x63, 0x65, 0x51, 0x75, 0x65, 0x75, 0x65, 0x49, 0x74, 0x65, 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, 0x2c, 0x0a, 0x06, 0x72, 0x65, 0x73, 0x75, 0x6c,
0x74, 0x18, 0x02, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x14, 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x44, 0x65,
0x76, 0x69, 0x63, 0x65, 0x51, 0x75, 0x65, 0x75, 0x65, 0x49, 0x74, 0x65, 0x6d, 0x52, 0x06, 0x72,
0x65, 0x73, 0x75, 0x6c, 0x74, 0x22, 0x30, 0x0a, 0x15, 0x46, 0x6c, 0x75, 0x73, 0x68, 0x44, 0x65,
0x76, 0x4e, 0x6f, 0x6e, 0x63, 0x65, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x17,
0x0a, 0x07, 0x64, 0x65, 0x76, 0x5f, 0x65, 0x75, 0x69, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52,
0x06, 0x64, 0x65, 0x76, 0x45, 0x75, 0x69, 0x32, 0xd0, 0x10, 0x0a, 0x0d, 0x44, 0x65, 0x76, 0x69,
0x63, 0x65, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x12, 0x53, 0x0a, 0x06, 0x43, 0x72, 0x65,
0x61, 0x74, 0x65, 0x12, 0x18, 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65,
0x44, 0x65, 0x76, 0x69, 0x63, 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, 0x17, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x11, 0x3a, 0x01, 0x2a,
0x22, 0x0c, 0x2f, 0x61, 0x70, 0x69, 0x2f, 0x64, 0x65, 0x76, 0x69, 0x63, 0x65, 0x73, 0x12, 0x54,
0x0a, 0x03, 0x47, 0x65, 0x74, 0x12, 0x15, 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x47, 0x65, 0x74, 0x44,
0x65, 0x76, 0x69, 0x63, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x16, 0x2e, 0x61,
0x70, 0x69, 0x2e, 0x47, 0x65, 0x74, 0x44, 0x65, 0x76, 0x69, 0x63, 0x65, 0x52, 0x65, 0x73, 0x70,
0x6f, 0x6e, 0x73, 0x65, 0x22, 0x1e, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x18, 0x12, 0x16, 0x2f, 0x61,
0x70, 0x69, 0x2f, 0x64, 0x65, 0x76, 0x69, 0x63, 0x65, 0x73, 0x2f, 0x7b, 0x64, 0x65, 0x76, 0x5f,
0x65, 0x75, 0x69, 0x7d, 0x12, 0x64, 0x0a, 0x06, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x12, 0x18,
0x2e, 0x61, 0x70, 0x69, 0x2e, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x44, 0x65, 0x76, 0x69, 0x63,
0x52, 0x06, 0x72, 0x65, 0x73, 0x75, 0x6c, 0x74, 0x22, 0x30, 0x0a, 0x15, 0x46, 0x6c, 0x75, 0x73,
0x68, 0x44, 0x65, 0x76, 0x4e, 0x6f, 0x6e, 0x63, 0x65, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73,
0x74, 0x12, 0x17, 0x0a, 0x07, 0x64, 0x65, 0x76, 0x5f, 0x65, 0x75, 0x69, 0x18, 0x01, 0x20, 0x01,
0x28, 0x09, 0x52, 0x06, 0x64, 0x65, 0x76, 0x45, 0x75, 0x69, 0x22, 0x37, 0x0a, 0x1c, 0x47, 0x65,
0x74, 0x44, 0x65, 0x76, 0x69, 0x63, 0x65, 0x4e, 0x65, 0x78, 0x74, 0x46, 0x43, 0x6e, 0x74, 0x44,
0x6f, 0x77, 0x6e, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x17, 0x0a, 0x07, 0x64, 0x65,
0x76, 0x5f, 0x65, 0x75, 0x69, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x06, 0x64, 0x65, 0x76,
0x45, 0x75, 0x69, 0x22, 0x3d, 0x0a, 0x1d, 0x47, 0x65, 0x74, 0x44, 0x65, 0x76, 0x69, 0x63, 0x65,
0x4e, 0x65, 0x78, 0x74, 0x46, 0x43, 0x6e, 0x74, 0x44, 0x6f, 0x77, 0x6e, 0x52, 0x65, 0x73, 0x70,
0x6f, 0x6e, 0x73, 0x65, 0x12, 0x1c, 0x0a, 0x0a, 0x66, 0x5f, 0x63, 0x6e, 0x74, 0x5f, 0x64, 0x6f,
0x77, 0x6e, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x08, 0x66, 0x43, 0x6e, 0x74, 0x44, 0x6f,
0x77, 0x6e, 0x32, 0xe2, 0x11, 0x0a, 0x0d, 0x44, 0x65, 0x76, 0x69, 0x63, 0x65, 0x53, 0x65, 0x72,
0x76, 0x69, 0x63, 0x65, 0x12, 0x53, 0x0a, 0x06, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x12, 0x18,
0x2e, 0x61, 0x70, 0x69, 0x2e, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x44, 0x65, 0x76, 0x69, 0x63,
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, 0x28, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x22, 0x3a, 0x01, 0x2a, 0x1a, 0x1d, 0x2f, 0x61, 0x70,
0x69, 0x2f, 0x64, 0x65, 0x76, 0x69, 0x63, 0x65, 0x73, 0x2f, 0x7b, 0x64, 0x65, 0x76, 0x69, 0x63,
0x65, 0x2e, 0x64, 0x65, 0x76, 0x5f, 0x65, 0x75, 0x69, 0x7d, 0x12, 0x5a, 0x0a, 0x06, 0x44, 0x65,
0x6c, 0x65, 0x74, 0x65, 0x12, 0x18, 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x44, 0x65, 0x6c, 0x65, 0x74,
0x65, 0x44, 0x65, 0x76, 0x69, 0x63, 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, 0x1e, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x18, 0x2a, 0x16,
0x2f, 0x61, 0x70, 0x69, 0x2f, 0x64, 0x65, 0x76, 0x69, 0x63, 0x65, 0x73, 0x2f, 0x7b, 0x64, 0x65,
0x76, 0x5f, 0x65, 0x75, 0x69, 0x7d, 0x12, 0x4f, 0x0a, 0x04, 0x4c, 0x69, 0x73, 0x74, 0x12, 0x17,
0x2e, 0x61, 0x70, 0x69, 0x2e, 0x4c, 0x69, 0x73, 0x74, 0x44, 0x65, 0x76, 0x69, 0x63, 0x65, 0x73,
0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x18, 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x4c, 0x69,
0x73, 0x74, 0x44, 0x65, 0x76, 0x69, 0x63, 0x65, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73,
0x65, 0x22, 0x14, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x0e, 0x12, 0x0c, 0x2f, 0x61, 0x70, 0x69, 0x2f,
0x64, 0x65, 0x76, 0x69, 0x63, 0x65, 0x73, 0x12, 0x76, 0x0a, 0x0a, 0x43, 0x72, 0x65, 0x61, 0x74,
0x65, 0x4b, 0x65, 0x79, 0x73, 0x12, 0x1c, 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x43, 0x72, 0x65, 0x61,
0x74, 0x65, 0x44, 0x65, 0x76, 0x69, 0x63, 0x65, 0x4b, 0x65, 0x79, 0x73, 0x52, 0x65, 0x71, 0x75,
0x22, 0x17, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x11, 0x3a, 0x01, 0x2a, 0x22, 0x0c, 0x2f, 0x61, 0x70,
0x69, 0x2f, 0x64, 0x65, 0x76, 0x69, 0x63, 0x65, 0x73, 0x12, 0x54, 0x0a, 0x03, 0x47, 0x65, 0x74,
0x12, 0x15, 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x47, 0x65, 0x74, 0x44, 0x65, 0x76, 0x69, 0x63, 0x65,
0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x16, 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x47, 0x65,
0x74, 0x44, 0x65, 0x76, 0x69, 0x63, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22,
0x1e, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x18, 0x12, 0x16, 0x2f, 0x61, 0x70, 0x69, 0x2f, 0x64, 0x65,
0x76, 0x69, 0x63, 0x65, 0x73, 0x2f, 0x7b, 0x64, 0x65, 0x76, 0x5f, 0x65, 0x75, 0x69, 0x7d, 0x12,
0x64, 0x0a, 0x06, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x12, 0x18, 0x2e, 0x61, 0x70, 0x69, 0x2e,
0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x44, 0x65, 0x76, 0x69, 0x63, 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, 0x32, 0x82, 0xd3, 0xe4,
0x93, 0x02, 0x2c, 0x3a, 0x01, 0x2a, 0x22, 0x27, 0x2f, 0x61, 0x70, 0x69, 0x2f, 0x64, 0x65, 0x76,
0x69, 0x63, 0x65, 0x73, 0x2f, 0x7b, 0x64, 0x65, 0x76, 0x69, 0x63, 0x65, 0x5f, 0x6b, 0x65, 0x79,
0x73, 0x2e, 0x64, 0x65, 0x76, 0x5f, 0x65, 0x75, 0x69, 0x7d, 0x2f, 0x6b, 0x65, 0x79, 0x73, 0x12,
0x65, 0x0a, 0x07, 0x47, 0x65, 0x74, 0x4b, 0x65, 0x79, 0x73, 0x12, 0x19, 0x2e, 0x61, 0x70, 0x69,
0x2e, 0x47, 0x65, 0x74, 0x44, 0x65, 0x76, 0x69, 0x63, 0x65, 0x4b, 0x65, 0x79, 0x73, 0x52, 0x65,
0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x1a, 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x47, 0x65, 0x74, 0x44,
0x65, 0x76, 0x69, 0x63, 0x65, 0x4b, 0x65, 0x79, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73,
0x65, 0x22, 0x23, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x1d, 0x12, 0x1b, 0x2f, 0x61, 0x70, 0x69, 0x2f,
0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x45, 0x6d, 0x70, 0x74, 0x79, 0x22, 0x28, 0x82, 0xd3, 0xe4,
0x93, 0x02, 0x22, 0x3a, 0x01, 0x2a, 0x1a, 0x1d, 0x2f, 0x61, 0x70, 0x69, 0x2f, 0x64, 0x65, 0x76,
0x69, 0x63, 0x65, 0x73, 0x2f, 0x7b, 0x64, 0x65, 0x76, 0x69, 0x63, 0x65, 0x2e, 0x64, 0x65, 0x76,
0x5f, 0x65, 0x75, 0x69, 0x7d, 0x12, 0x5a, 0x0a, 0x06, 0x44, 0x65, 0x6c, 0x65, 0x74, 0x65, 0x12,
0x18, 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x44, 0x65, 0x6c, 0x65, 0x74, 0x65, 0x44, 0x65, 0x76, 0x69,
0x63, 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, 0x1e, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x18, 0x2a, 0x16, 0x2f, 0x61, 0x70, 0x69, 0x2f,
0x64, 0x65, 0x76, 0x69, 0x63, 0x65, 0x73, 0x2f, 0x7b, 0x64, 0x65, 0x76, 0x5f, 0x65, 0x75, 0x69,
0x7d, 0x2f, 0x6b, 0x65, 0x79, 0x73, 0x12, 0x76, 0x0a, 0x0a, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65,
0x4b, 0x65, 0x79, 0x73, 0x12, 0x1c, 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x55, 0x70, 0x64, 0x61, 0x74,
0x65, 0x44, 0x65, 0x76, 0x69, 0x63, 0x65, 0x4b, 0x65, 0x79, 0x73, 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, 0x32, 0x82, 0xd3, 0xe4, 0x93,
0x02, 0x2c, 0x3a, 0x01, 0x2a, 0x1a, 0x27, 0x2f, 0x61, 0x70, 0x69, 0x2f, 0x64, 0x65, 0x76, 0x69,
0x63, 0x65, 0x73, 0x2f, 0x7b, 0x64, 0x65, 0x76, 0x69, 0x63, 0x65, 0x5f, 0x6b, 0x65, 0x79, 0x73,
0x2e, 0x64, 0x65, 0x76, 0x5f, 0x65, 0x75, 0x69, 0x7d, 0x2f, 0x6b, 0x65, 0x79, 0x73, 0x12, 0x67,
0x0a, 0x0a, 0x44, 0x65, 0x6c, 0x65, 0x74, 0x65, 0x4b, 0x65, 0x79, 0x73, 0x12, 0x1c, 0x2e, 0x61,
0x70, 0x69, 0x2e, 0x44, 0x65, 0x6c, 0x65, 0x74, 0x65, 0x44, 0x65, 0x76, 0x69, 0x63, 0x65, 0x4b,
0x65, 0x79, 0x73, 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, 0x23, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x1d, 0x2a, 0x1b, 0x2f, 0x61, 0x70, 0x69,
0x2f, 0x64, 0x65, 0x76, 0x69, 0x63, 0x65, 0x73, 0x2f, 0x7b, 0x64, 0x65, 0x76, 0x5f, 0x65, 0x75,
0x69, 0x7d, 0x2f, 0x6b, 0x65, 0x79, 0x73, 0x12, 0x6f, 0x0a, 0x0e, 0x46, 0x6c, 0x75, 0x73, 0x68,
0x44, 0x65, 0x76, 0x4e, 0x6f, 0x6e, 0x63, 0x65, 0x73, 0x12, 0x1a, 0x2e, 0x61, 0x70, 0x69, 0x2e,
0x46, 0x6c, 0x75, 0x73, 0x68, 0x44, 0x65, 0x76, 0x4e, 0x6f, 0x6e, 0x63, 0x65, 0x73, 0x52, 0x65,
0x7d, 0x12, 0x4f, 0x0a, 0x04, 0x4c, 0x69, 0x73, 0x74, 0x12, 0x17, 0x2e, 0x61, 0x70, 0x69, 0x2e,
0x4c, 0x69, 0x73, 0x74, 0x44, 0x65, 0x76, 0x69, 0x63, 0x65, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65,
0x73, 0x74, 0x1a, 0x18, 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x4c, 0x69, 0x73, 0x74, 0x44, 0x65, 0x76,
0x69, 0x63, 0x65, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x14, 0x82, 0xd3,
0xe4, 0x93, 0x02, 0x0e, 0x12, 0x0c, 0x2f, 0x61, 0x70, 0x69, 0x2f, 0x64, 0x65, 0x76, 0x69, 0x63,
0x65, 0x73, 0x12, 0x76, 0x0a, 0x0a, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x4b, 0x65, 0x79, 0x73,
0x12, 0x1c, 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x44, 0x65, 0x76,
0x69, 0x63, 0x65, 0x4b, 0x65, 0x79, 0x73, 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, 0x32, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x2c, 0x3a, 0x01,
0x2a, 0x22, 0x27, 0x2f, 0x61, 0x70, 0x69, 0x2f, 0x64, 0x65, 0x76, 0x69, 0x63, 0x65, 0x73, 0x2f,
0x7b, 0x64, 0x65, 0x76, 0x69, 0x63, 0x65, 0x5f, 0x6b, 0x65, 0x79, 0x73, 0x2e, 0x64, 0x65, 0x76,
0x5f, 0x65, 0x75, 0x69, 0x7d, 0x2f, 0x6b, 0x65, 0x79, 0x73, 0x12, 0x65, 0x0a, 0x07, 0x47, 0x65,
0x74, 0x4b, 0x65, 0x79, 0x73, 0x12, 0x19, 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x47, 0x65, 0x74, 0x44,
0x65, 0x76, 0x69, 0x63, 0x65, 0x4b, 0x65, 0x79, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74,
0x1a, 0x1a, 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x47, 0x65, 0x74, 0x44, 0x65, 0x76, 0x69, 0x63, 0x65,
0x4b, 0x65, 0x79, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x23, 0x82, 0xd3,
0xe4, 0x93, 0x02, 0x1d, 0x12, 0x1b, 0x2f, 0x61, 0x70, 0x69, 0x2f, 0x64, 0x65, 0x76, 0x69, 0x63,
0x65, 0x73, 0x2f, 0x7b, 0x64, 0x65, 0x76, 0x5f, 0x65, 0x75, 0x69, 0x7d, 0x2f, 0x6b, 0x65, 0x79,
0x73, 0x12, 0x76, 0x0a, 0x0a, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x4b, 0x65, 0x79, 0x73, 0x12,
0x1c, 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x44, 0x65, 0x76, 0x69,
0x63, 0x65, 0x4b, 0x65, 0x79, 0x73, 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, 0x32, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x2c, 0x3a, 0x01, 0x2a,
0x1a, 0x27, 0x2f, 0x61, 0x70, 0x69, 0x2f, 0x64, 0x65, 0x76, 0x69, 0x63, 0x65, 0x73, 0x2f, 0x7b,
0x64, 0x65, 0x76, 0x69, 0x63, 0x65, 0x5f, 0x6b, 0x65, 0x79, 0x73, 0x2e, 0x64, 0x65, 0x76, 0x5f,
0x65, 0x75, 0x69, 0x7d, 0x2f, 0x6b, 0x65, 0x79, 0x73, 0x12, 0x67, 0x0a, 0x0a, 0x44, 0x65, 0x6c,
0x65, 0x74, 0x65, 0x4b, 0x65, 0x79, 0x73, 0x12, 0x1c, 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x44, 0x65,
0x6c, 0x65, 0x74, 0x65, 0x44, 0x65, 0x76, 0x69, 0x63, 0x65, 0x4b, 0x65, 0x79, 0x73, 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, 0x29, 0x82,
0xd3, 0xe4, 0x93, 0x02, 0x23, 0x2a, 0x21, 0x2f, 0x61, 0x70, 0x69, 0x2f, 0x64, 0x65, 0x76, 0x69,
0x63, 0x65, 0x73, 0x2f, 0x7b, 0x64, 0x65, 0x76, 0x5f, 0x65, 0x75, 0x69, 0x7d, 0x2f, 0x64, 0x65,
0x76, 0x2d, 0x6e, 0x6f, 0x6e, 0x63, 0x65, 0x73, 0x12, 0x7c, 0x0a, 0x08, 0x41, 0x63, 0x74, 0x69,
0x76, 0x61, 0x74, 0x65, 0x12, 0x1a, 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x41, 0x63, 0x74, 0x69, 0x76,
0x61, 0x74, 0x65, 0x44, 0x65, 0x76, 0x69, 0x63, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74,
0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x45, 0x6d, 0x70, 0x74, 0x79, 0x22, 0x23, 0x82,
0xd3, 0xe4, 0x93, 0x02, 0x1d, 0x2a, 0x1b, 0x2f, 0x61, 0x70, 0x69, 0x2f, 0x64, 0x65, 0x76, 0x69,
0x63, 0x65, 0x73, 0x2f, 0x7b, 0x64, 0x65, 0x76, 0x5f, 0x65, 0x75, 0x69, 0x7d, 0x2f, 0x6b, 0x65,
0x79, 0x73, 0x12, 0x6f, 0x0a, 0x0e, 0x46, 0x6c, 0x75, 0x73, 0x68, 0x44, 0x65, 0x76, 0x4e, 0x6f,
0x6e, 0x63, 0x65, 0x73, 0x12, 0x1a, 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x46, 0x6c, 0x75, 0x73, 0x68,
0x44, 0x65, 0x76, 0x4e, 0x6f, 0x6e, 0x63, 0x65, 0x73, 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, 0x3c, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x36,
0x3a, 0x01, 0x2a, 0x22, 0x31, 0x2f, 0x61, 0x70, 0x69, 0x2f, 0x64, 0x65, 0x76, 0x69, 0x63, 0x65,
0x73, 0x2f, 0x7b, 0x64, 0x65, 0x76, 0x69, 0x63, 0x65, 0x5f, 0x61, 0x63, 0x74, 0x69, 0x76, 0x61,
0x74, 0x69, 0x6f, 0x6e, 0x2e, 0x64, 0x65, 0x76, 0x5f, 0x65, 0x75, 0x69, 0x7d, 0x2f, 0x61, 0x63,
0x74, 0x69, 0x76, 0x61, 0x74, 0x65, 0x12, 0x6d, 0x0a, 0x0a, 0x44, 0x65, 0x61, 0x63, 0x74, 0x69,
0x76, 0x61, 0x74, 0x65, 0x12, 0x1c, 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x44, 0x65, 0x61, 0x63, 0x74,
0x69, 0x76, 0x61, 0x74, 0x65, 0x44, 0x65, 0x76, 0x69, 0x63, 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, 0x29, 0x82, 0xd3, 0xe4, 0x93,
0x02, 0x23, 0x2a, 0x21, 0x2f, 0x61, 0x70, 0x69, 0x2f, 0x64, 0x65, 0x76, 0x69, 0x63, 0x65, 0x73,
0x2f, 0x7b, 0x64, 0x65, 0x76, 0x5f, 0x65, 0x75, 0x69, 0x7d, 0x2f, 0x61, 0x63, 0x74, 0x69, 0x76,
0x61, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x7d, 0x0a, 0x0d, 0x47, 0x65, 0x74, 0x41, 0x63, 0x74, 0x69,
0x76, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x1f, 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x47, 0x65, 0x74,
0x44, 0x65, 0x76, 0x69, 0x63, 0x65, 0x41, 0x63, 0x74, 0x69, 0x76, 0x61, 0x74, 0x69, 0x6f, 0x6e,
0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x20, 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x47, 0x65,
0x74, 0x44, 0x65, 0x76, 0x69, 0x63, 0x65, 0x41, 0x63, 0x74, 0x69, 0x76, 0x61, 0x74, 0x69, 0x6f,
0x6e, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x29, 0x82, 0xd3, 0xe4, 0x93, 0x02,
0x23, 0x12, 0x21, 0x2f, 0x61, 0x70, 0x69, 0x2f, 0x64, 0x65, 0x76, 0x69, 0x63, 0x65, 0x73, 0x2f,
0x7b, 0x64, 0x65, 0x76, 0x5f, 0x65, 0x75, 0x69, 0x7d, 0x2f, 0x61, 0x63, 0x74, 0x69, 0x76, 0x61,
0x74, 0x69, 0x6f, 0x6e, 0x12, 0x83, 0x01, 0x0a, 0x10, 0x47, 0x65, 0x74, 0x52, 0x61, 0x6e, 0x64,
0x6f, 0x6d, 0x44, 0x65, 0x76, 0x41, 0x64, 0x64, 0x72, 0x12, 0x1c, 0x2e, 0x61, 0x70, 0x69, 0x2e,
0x47, 0x65, 0x74, 0x52, 0x61, 0x6e, 0x64, 0x6f, 0x6d, 0x44, 0x65, 0x76, 0x41, 0x64, 0x64, 0x72,
0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x1d, 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x47, 0x65,
0x74, 0x52, 0x61, 0x6e, 0x64, 0x6f, 0x6d, 0x44, 0x65, 0x76, 0x41, 0x64, 0x64, 0x72, 0x52, 0x65,
0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x32, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x2c, 0x22, 0x2a,
0x75, 0x66, 0x2e, 0x45, 0x6d, 0x70, 0x74, 0x79, 0x22, 0x29, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x23,
0x2a, 0x21, 0x2f, 0x61, 0x70, 0x69, 0x2f, 0x64, 0x65, 0x76, 0x69, 0x63, 0x65, 0x73, 0x2f, 0x7b,
0x64, 0x65, 0x76, 0x5f, 0x65, 0x75, 0x69, 0x7d, 0x2f, 0x64, 0x65, 0x76, 0x2d, 0x6e, 0x6f, 0x6e,
0x63, 0x65, 0x73, 0x12, 0x7c, 0x0a, 0x08, 0x41, 0x63, 0x74, 0x69, 0x76, 0x61, 0x74, 0x65, 0x12,
0x1a, 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x41, 0x63, 0x74, 0x69, 0x76, 0x61, 0x74, 0x65, 0x44, 0x65,
0x76, 0x69, 0x63, 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, 0x3c, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x36, 0x3a, 0x01, 0x2a, 0x22, 0x31,
0x2f, 0x61, 0x70, 0x69, 0x2f, 0x64, 0x65, 0x76, 0x69, 0x63, 0x65, 0x73, 0x2f, 0x7b, 0x64, 0x65,
0x76, 0x5f, 0x65, 0x75, 0x69, 0x7d, 0x2f, 0x67, 0x65, 0x74, 0x2d, 0x72, 0x61, 0x6e, 0x64, 0x6f,
0x6d, 0x2d, 0x64, 0x65, 0x76, 0x2d, 0x61, 0x64, 0x64, 0x72, 0x12, 0x71, 0x0a, 0x0a, 0x47, 0x65,
0x74, 0x4d, 0x65, 0x74, 0x72, 0x69, 0x63, 0x73, 0x12, 0x1c, 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x47,
0x65, 0x74, 0x44, 0x65, 0x76, 0x69, 0x63, 0x65, 0x4d, 0x65, 0x74, 0x72, 0x69, 0x63, 0x73, 0x52,
0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x1d, 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x47, 0x65, 0x74,
0x44, 0x65, 0x76, 0x69, 0x63, 0x65, 0x4d, 0x65, 0x74, 0x72, 0x69, 0x63, 0x73, 0x52, 0x65, 0x73,
0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x26, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x20, 0x12, 0x1e, 0x2f,
0x76, 0x69, 0x63, 0x65, 0x5f, 0x61, 0x63, 0x74, 0x69, 0x76, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2e,
0x64, 0x65, 0x76, 0x5f, 0x65, 0x75, 0x69, 0x7d, 0x2f, 0x61, 0x63, 0x74, 0x69, 0x76, 0x61, 0x74,
0x65, 0x12, 0x6d, 0x0a, 0x0a, 0x44, 0x65, 0x61, 0x63, 0x74, 0x69, 0x76, 0x61, 0x74, 0x65, 0x12,
0x1c, 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x44, 0x65, 0x61, 0x63, 0x74, 0x69, 0x76, 0x61, 0x74, 0x65,
0x44, 0x65, 0x76, 0x69, 0x63, 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, 0x29, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x23, 0x2a, 0x21, 0x2f,
0x61, 0x70, 0x69, 0x2f, 0x64, 0x65, 0x76, 0x69, 0x63, 0x65, 0x73, 0x2f, 0x7b, 0x64, 0x65, 0x76,
0x5f, 0x65, 0x75, 0x69, 0x7d, 0x2f, 0x6d, 0x65, 0x74, 0x72, 0x69, 0x63, 0x73, 0x12, 0x82, 0x01,
0x0a, 0x0e, 0x47, 0x65, 0x74, 0x4c, 0x69, 0x6e, 0x6b, 0x4d, 0x65, 0x74, 0x72, 0x69, 0x63, 0x73,
0x12, 0x20, 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x47, 0x65, 0x74, 0x44, 0x65, 0x76, 0x69, 0x63, 0x65,
0x4c, 0x69, 0x6e, 0x6b, 0x4d, 0x65, 0x74, 0x72, 0x69, 0x63, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65,
0x73, 0x74, 0x1a, 0x21, 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x47, 0x65, 0x74, 0x44, 0x65, 0x76, 0x69,
0x63, 0x65, 0x4c, 0x69, 0x6e, 0x6b, 0x4d, 0x65, 0x74, 0x72, 0x69, 0x63, 0x73, 0x52, 0x65, 0x73,
0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x2b, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x25, 0x12, 0x23, 0x2f,
0x61, 0x70, 0x69, 0x2f, 0x64, 0x65, 0x76, 0x69, 0x63, 0x65, 0x73, 0x2f, 0x7b, 0x64, 0x65, 0x76,
0x5f, 0x65, 0x75, 0x69, 0x7d, 0x2f, 0x6c, 0x69, 0x6e, 0x6b, 0x2d, 0x6d, 0x65, 0x74, 0x72, 0x69,
0x63, 0x73, 0x12, 0x86, 0x01, 0x0a, 0x07, 0x45, 0x6e, 0x71, 0x75, 0x65, 0x75, 0x65, 0x12, 0x22,
0x2e, 0x61, 0x70, 0x69, 0x2e, 0x45, 0x6e, 0x71, 0x75, 0x65, 0x75, 0x65, 0x44, 0x65, 0x76, 0x69,
0x63, 0x65, 0x51, 0x75, 0x65, 0x75, 0x65, 0x49, 0x74, 0x65, 0x6d, 0x52, 0x65, 0x71, 0x75, 0x65,
0x73, 0x74, 0x1a, 0x23, 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x45, 0x6e, 0x71, 0x75, 0x65, 0x75, 0x65,
0x44, 0x65, 0x76, 0x69, 0x63, 0x65, 0x51, 0x75, 0x65, 0x75, 0x65, 0x49, 0x74, 0x65, 0x6d, 0x52,
0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x32, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x2c, 0x3a,
0x01, 0x2a, 0x22, 0x27, 0x2f, 0x61, 0x70, 0x69, 0x2f, 0x64, 0x65, 0x76, 0x69, 0x63, 0x65, 0x73,
0x2f, 0x7b, 0x71, 0x75, 0x65, 0x75, 0x65, 0x5f, 0x69, 0x74, 0x65, 0x6d, 0x2e, 0x64, 0x65, 0x76,
0x5f, 0x65, 0x75, 0x69, 0x7d, 0x2f, 0x71, 0x75, 0x65, 0x75, 0x65, 0x12, 0x68, 0x0a, 0x0a, 0x46,
0x6c, 0x75, 0x73, 0x68, 0x51, 0x75, 0x65, 0x75, 0x65, 0x12, 0x1c, 0x2e, 0x61, 0x70, 0x69, 0x2e,
0x46, 0x6c, 0x75, 0x73, 0x68, 0x44, 0x65, 0x76, 0x69, 0x63, 0x65, 0x51, 0x75, 0x65, 0x75, 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,
0x24, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x1e, 0x2a, 0x1c, 0x2f, 0x61, 0x70, 0x69, 0x2f, 0x64, 0x65,
0x76, 0x69, 0x63, 0x65, 0x73, 0x2f, 0x7b, 0x64, 0x65, 0x76, 0x5f, 0x65, 0x75, 0x69, 0x7d, 0x2f,
0x71, 0x75, 0x65, 0x75, 0x65, 0x12, 0x73, 0x0a, 0x08, 0x47, 0x65, 0x74, 0x51, 0x75, 0x65, 0x75,
0x65, 0x12, 0x1f, 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x47, 0x65, 0x74, 0x44, 0x65, 0x76, 0x69, 0x63,
0x65, 0x51, 0x75, 0x65, 0x75, 0x65, 0x49, 0x74, 0x65, 0x6d, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65,
0x5f, 0x65, 0x75, 0x69, 0x7d, 0x2f, 0x61, 0x63, 0x74, 0x69, 0x76, 0x61, 0x74, 0x69, 0x6f, 0x6e,
0x12, 0x7d, 0x0a, 0x0d, 0x47, 0x65, 0x74, 0x41, 0x63, 0x74, 0x69, 0x76, 0x61, 0x74, 0x69, 0x6f,
0x6e, 0x12, 0x1f, 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x47, 0x65, 0x74, 0x44, 0x65, 0x76, 0x69, 0x63,
0x65, 0x41, 0x63, 0x74, 0x69, 0x76, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x65, 0x71, 0x75, 0x65,
0x73, 0x74, 0x1a, 0x20, 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x47, 0x65, 0x74, 0x44, 0x65, 0x76, 0x69,
0x63, 0x65, 0x51, 0x75, 0x65, 0x75, 0x65, 0x49, 0x74, 0x65, 0x6d, 0x73, 0x52, 0x65, 0x73, 0x70,
0x6f, 0x6e, 0x73, 0x65, 0x22, 0x24, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x1e, 0x12, 0x1c, 0x2f, 0x61,
0x63, 0x65, 0x41, 0x63, 0x74, 0x69, 0x76, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x65, 0x73, 0x70,
0x6f, 0x6e, 0x73, 0x65, 0x22, 0x29, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x23, 0x12, 0x21, 0x2f, 0x61,
0x70, 0x69, 0x2f, 0x64, 0x65, 0x76, 0x69, 0x63, 0x65, 0x73, 0x2f, 0x7b, 0x64, 0x65, 0x76, 0x5f,
0x65, 0x75, 0x69, 0x7d, 0x2f, 0x71, 0x75, 0x65, 0x75, 0x65, 0x42, 0x63, 0x0a, 0x11, 0x69, 0x6f,
0x2e, 0x63, 0x68, 0x69, 0x72, 0x70, 0x73, 0x74, 0x61, 0x63, 0x6b, 0x2e, 0x61, 0x70, 0x69, 0x42,
0x0b, 0x44, 0x65, 0x76, 0x69, 0x63, 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,
0x65, 0x75, 0x69, 0x7d, 0x2f, 0x61, 0x63, 0x74, 0x69, 0x76, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x12,
0x83, 0x01, 0x0a, 0x10, 0x47, 0x65, 0x74, 0x52, 0x61, 0x6e, 0x64, 0x6f, 0x6d, 0x44, 0x65, 0x76,
0x41, 0x64, 0x64, 0x72, 0x12, 0x1c, 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x47, 0x65, 0x74, 0x52, 0x61,
0x6e, 0x64, 0x6f, 0x6d, 0x44, 0x65, 0x76, 0x41, 0x64, 0x64, 0x72, 0x52, 0x65, 0x71, 0x75, 0x65,
0x73, 0x74, 0x1a, 0x1d, 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x47, 0x65, 0x74, 0x52, 0x61, 0x6e, 0x64,
0x6f, 0x6d, 0x44, 0x65, 0x76, 0x41, 0x64, 0x64, 0x72, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73,
0x65, 0x22, 0x32, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x2c, 0x22, 0x2a, 0x2f, 0x61, 0x70, 0x69, 0x2f,
0x64, 0x65, 0x76, 0x69, 0x63, 0x65, 0x73, 0x2f, 0x7b, 0x64, 0x65, 0x76, 0x5f, 0x65, 0x75, 0x69,
0x7d, 0x2f, 0x67, 0x65, 0x74, 0x2d, 0x72, 0x61, 0x6e, 0x64, 0x6f, 0x6d, 0x2d, 0x64, 0x65, 0x76,
0x2d, 0x61, 0x64, 0x64, 0x72, 0x12, 0x71, 0x0a, 0x0a, 0x47, 0x65, 0x74, 0x4d, 0x65, 0x74, 0x72,
0x69, 0x63, 0x73, 0x12, 0x1c, 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x47, 0x65, 0x74, 0x44, 0x65, 0x76,
0x69, 0x63, 0x65, 0x4d, 0x65, 0x74, 0x72, 0x69, 0x63, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73,
0x74, 0x1a, 0x1d, 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x47, 0x65, 0x74, 0x44, 0x65, 0x76, 0x69, 0x63,
0x65, 0x4d, 0x65, 0x74, 0x72, 0x69, 0x63, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65,
0x22, 0x26, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x20, 0x12, 0x1e, 0x2f, 0x61, 0x70, 0x69, 0x2f, 0x64,
0x65, 0x76, 0x69, 0x63, 0x65, 0x73, 0x2f, 0x7b, 0x64, 0x65, 0x76, 0x5f, 0x65, 0x75, 0x69, 0x7d,
0x2f, 0x6d, 0x65, 0x74, 0x72, 0x69, 0x63, 0x73, 0x12, 0x82, 0x01, 0x0a, 0x0e, 0x47, 0x65, 0x74,
0x4c, 0x69, 0x6e, 0x6b, 0x4d, 0x65, 0x74, 0x72, 0x69, 0x63, 0x73, 0x12, 0x20, 0x2e, 0x61, 0x70,
0x69, 0x2e, 0x47, 0x65, 0x74, 0x44, 0x65, 0x76, 0x69, 0x63, 0x65, 0x4c, 0x69, 0x6e, 0x6b, 0x4d,
0x65, 0x74, 0x72, 0x69, 0x63, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x21, 0x2e,
0x61, 0x70, 0x69, 0x2e, 0x47, 0x65, 0x74, 0x44, 0x65, 0x76, 0x69, 0x63, 0x65, 0x4c, 0x69, 0x6e,
0x6b, 0x4d, 0x65, 0x74, 0x72, 0x69, 0x63, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65,
0x22, 0x2b, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x25, 0x12, 0x23, 0x2f, 0x61, 0x70, 0x69, 0x2f, 0x64,
0x65, 0x76, 0x69, 0x63, 0x65, 0x73, 0x2f, 0x7b, 0x64, 0x65, 0x76, 0x5f, 0x65, 0x75, 0x69, 0x7d,
0x2f, 0x6c, 0x69, 0x6e, 0x6b, 0x2d, 0x6d, 0x65, 0x74, 0x72, 0x69, 0x63, 0x73, 0x12, 0x86, 0x01,
0x0a, 0x07, 0x45, 0x6e, 0x71, 0x75, 0x65, 0x75, 0x65, 0x12, 0x22, 0x2e, 0x61, 0x70, 0x69, 0x2e,
0x45, 0x6e, 0x71, 0x75, 0x65, 0x75, 0x65, 0x44, 0x65, 0x76, 0x69, 0x63, 0x65, 0x51, 0x75, 0x65,
0x75, 0x65, 0x49, 0x74, 0x65, 0x6d, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x23, 0x2e,
0x61, 0x70, 0x69, 0x2e, 0x45, 0x6e, 0x71, 0x75, 0x65, 0x75, 0x65, 0x44, 0x65, 0x76, 0x69, 0x63,
0x65, 0x51, 0x75, 0x65, 0x75, 0x65, 0x49, 0x74, 0x65, 0x6d, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e,
0x73, 0x65, 0x22, 0x32, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x2c, 0x3a, 0x01, 0x2a, 0x22, 0x27, 0x2f,
0x61, 0x70, 0x69, 0x2f, 0x64, 0x65, 0x76, 0x69, 0x63, 0x65, 0x73, 0x2f, 0x7b, 0x71, 0x75, 0x65,
0x75, 0x65, 0x5f, 0x69, 0x74, 0x65, 0x6d, 0x2e, 0x64, 0x65, 0x76, 0x5f, 0x65, 0x75, 0x69, 0x7d,
0x2f, 0x71, 0x75, 0x65, 0x75, 0x65, 0x12, 0x68, 0x0a, 0x0a, 0x46, 0x6c, 0x75, 0x73, 0x68, 0x51,
0x75, 0x65, 0x75, 0x65, 0x12, 0x1c, 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x46, 0x6c, 0x75, 0x73, 0x68,
0x44, 0x65, 0x76, 0x69, 0x63, 0x65, 0x51, 0x75, 0x65, 0x75, 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, 0x24, 0x82, 0xd3, 0xe4, 0x93,
0x02, 0x1e, 0x2a, 0x1c, 0x2f, 0x61, 0x70, 0x69, 0x2f, 0x64, 0x65, 0x76, 0x69, 0x63, 0x65, 0x73,
0x2f, 0x7b, 0x64, 0x65, 0x76, 0x5f, 0x65, 0x75, 0x69, 0x7d, 0x2f, 0x71, 0x75, 0x65, 0x75, 0x65,
0x12, 0x73, 0x0a, 0x08, 0x47, 0x65, 0x74, 0x51, 0x75, 0x65, 0x75, 0x65, 0x12, 0x1f, 0x2e, 0x61,
0x70, 0x69, 0x2e, 0x47, 0x65, 0x74, 0x44, 0x65, 0x76, 0x69, 0x63, 0x65, 0x51, 0x75, 0x65, 0x75,
0x65, 0x49, 0x74, 0x65, 0x6d, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x20, 0x2e,
0x61, 0x70, 0x69, 0x2e, 0x47, 0x65, 0x74, 0x44, 0x65, 0x76, 0x69, 0x63, 0x65, 0x51, 0x75, 0x65,
0x75, 0x65, 0x49, 0x74, 0x65, 0x6d, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22,
0x24, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x1e, 0x12, 0x1c, 0x2f, 0x61, 0x70, 0x69, 0x2f, 0x64, 0x65,
0x76, 0x69, 0x63, 0x65, 0x73, 0x2f, 0x7b, 0x64, 0x65, 0x76, 0x5f, 0x65, 0x75, 0x69, 0x7d, 0x2f,
0x71, 0x75, 0x65, 0x75, 0x65, 0x12, 0x8f, 0x01, 0x0a, 0x0f, 0x47, 0x65, 0x74, 0x4e, 0x65, 0x78,
0x74, 0x46, 0x43, 0x6e, 0x74, 0x44, 0x6f, 0x77, 0x6e, 0x12, 0x21, 0x2e, 0x61, 0x70, 0x69, 0x2e,
0x47, 0x65, 0x74, 0x44, 0x65, 0x76, 0x69, 0x63, 0x65, 0x4e, 0x65, 0x78, 0x74, 0x46, 0x43, 0x6e,
0x74, 0x44, 0x6f, 0x77, 0x6e, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x22, 0x2e, 0x61,
0x70, 0x69, 0x2e, 0x47, 0x65, 0x74, 0x44, 0x65, 0x76, 0x69, 0x63, 0x65, 0x4e, 0x65, 0x78, 0x74,
0x46, 0x43, 0x6e, 0x74, 0x44, 0x6f, 0x77, 0x6e, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65,
0x22, 0x35, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x2f, 0x3a, 0x01, 0x2a, 0x22, 0x2a, 0x2f, 0x61, 0x70,
0x69, 0x2f, 0x64, 0x65, 0x76, 0x69, 0x63, 0x65, 0x73, 0x2f, 0x7b, 0x64, 0x65, 0x76, 0x5f, 0x65,
0x75, 0x69, 0x7d, 0x2f, 0x67, 0x65, 0x74, 0x2d, 0x6e, 0x65, 0x78, 0x74, 0x2d, 0x66, 0x2d, 0x63,
0x6e, 0x74, 0x2d, 0x64, 0x6f, 0x77, 0x6e, 0x42, 0x63, 0x0a, 0x11, 0x69, 0x6f, 0x2e, 0x63, 0x68,
0x69, 0x72, 0x70, 0x73, 0x74, 0x61, 0x63, 0x6b, 0x2e, 0x61, 0x70, 0x69, 0x42, 0x0b, 0x44, 0x65,
0x76, 0x69, 0x63, 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 (
@ -2764,7 +2893,7 @@ func file_api_device_proto_rawDescGZIP() []byte {
return file_api_device_proto_rawDescData
}
var file_api_device_proto_msgTypes = make([]protoimpl.MessageInfo, 39)
var file_api_device_proto_msgTypes = make([]protoimpl.MessageInfo, 41)
var file_api_device_proto_goTypes = []interface{}{
(*Device)(nil), // 0: api.Device
(*DeviceStatus)(nil), // 1: api.DeviceStatus
@ -2801,58 +2930,60 @@ var file_api_device_proto_goTypes = []interface{}{
(*GetDeviceQueueItemsRequest)(nil), // 32: api.GetDeviceQueueItemsRequest
(*GetDeviceQueueItemsResponse)(nil), // 33: api.GetDeviceQueueItemsResponse
(*FlushDevNoncesRequest)(nil), // 34: api.FlushDevNoncesRequest
nil, // 35: api.Device.VariablesEntry
nil, // 36: api.Device.TagsEntry
nil, // 37: api.GetDeviceMetricsResponse.MetricsEntry
nil, // 38: api.GetDeviceMetricsResponse.StatesEntry
(*timestamppb.Timestamp)(nil), // 39: google.protobuf.Timestamp
(common.DeviceClass)(0), // 40: common.DeviceClass
(common.Aggregation)(0), // 41: common.Aggregation
(*common.Metric)(nil), // 42: common.Metric
(*structpb.Struct)(nil), // 43: google.protobuf.Struct
(*emptypb.Empty)(nil), // 44: google.protobuf.Empty
(*GetDeviceNextFCntDownRequest)(nil), // 35: api.GetDeviceNextFCntDownRequest
(*GetDeviceNextFCntDownResponse)(nil), // 36: api.GetDeviceNextFCntDownResponse
nil, // 37: api.Device.VariablesEntry
nil, // 38: api.Device.TagsEntry
nil, // 39: api.GetDeviceMetricsResponse.MetricsEntry
nil, // 40: api.GetDeviceMetricsResponse.StatesEntry
(*timestamppb.Timestamp)(nil), // 41: google.protobuf.Timestamp
(common.DeviceClass)(0), // 42: common.DeviceClass
(common.Aggregation)(0), // 43: common.Aggregation
(*common.Metric)(nil), // 44: common.Metric
(*structpb.Struct)(nil), // 45: google.protobuf.Struct
(*emptypb.Empty)(nil), // 46: google.protobuf.Empty
}
var file_api_device_proto_depIdxs = []int32{
35, // 0: api.Device.variables:type_name -> api.Device.VariablesEntry
36, // 1: api.Device.tags:type_name -> api.Device.TagsEntry
39, // 2: api.DeviceListItem.created_at:type_name -> google.protobuf.Timestamp
39, // 3: api.DeviceListItem.updated_at:type_name -> google.protobuf.Timestamp
39, // 4: api.DeviceListItem.last_seen_at:type_name -> google.protobuf.Timestamp
37, // 0: api.Device.variables:type_name -> api.Device.VariablesEntry
38, // 1: api.Device.tags:type_name -> api.Device.TagsEntry
41, // 2: api.DeviceListItem.created_at:type_name -> google.protobuf.Timestamp
41, // 3: api.DeviceListItem.updated_at:type_name -> google.protobuf.Timestamp
41, // 4: api.DeviceListItem.last_seen_at:type_name -> google.protobuf.Timestamp
1, // 5: api.DeviceListItem.device_status:type_name -> api.DeviceStatus
0, // 6: api.CreateDeviceRequest.device:type_name -> api.Device
0, // 7: api.GetDeviceResponse.device:type_name -> api.Device
39, // 8: api.GetDeviceResponse.created_at:type_name -> google.protobuf.Timestamp
39, // 9: api.GetDeviceResponse.updated_at:type_name -> google.protobuf.Timestamp
39, // 10: api.GetDeviceResponse.last_seen_at:type_name -> google.protobuf.Timestamp
41, // 8: api.GetDeviceResponse.created_at:type_name -> google.protobuf.Timestamp
41, // 9: api.GetDeviceResponse.updated_at:type_name -> google.protobuf.Timestamp
41, // 10: api.GetDeviceResponse.last_seen_at:type_name -> google.protobuf.Timestamp
1, // 11: api.GetDeviceResponse.device_status:type_name -> api.DeviceStatus
40, // 12: api.GetDeviceResponse.class_enabled:type_name -> common.DeviceClass
42, // 12: api.GetDeviceResponse.class_enabled:type_name -> common.DeviceClass
0, // 13: api.UpdateDeviceRequest.device:type_name -> api.Device
2, // 14: api.ListDevicesResponse.result:type_name -> api.DeviceListItem
3, // 15: api.CreateDeviceKeysRequest.device_keys:type_name -> api.DeviceKeys
3, // 16: api.GetDeviceKeysResponse.device_keys:type_name -> api.DeviceKeys
39, // 17: api.GetDeviceKeysResponse.created_at:type_name -> google.protobuf.Timestamp
39, // 18: api.GetDeviceKeysResponse.updated_at:type_name -> google.protobuf.Timestamp
41, // 17: api.GetDeviceKeysResponse.created_at:type_name -> google.protobuf.Timestamp
41, // 18: api.GetDeviceKeysResponse.updated_at:type_name -> google.protobuf.Timestamp
3, // 19: api.UpdateDeviceKeysRequest.device_keys:type_name -> api.DeviceKeys
16, // 20: api.ActivateDeviceRequest.device_activation:type_name -> api.DeviceActivation
16, // 21: api.GetDeviceActivationResponse.device_activation:type_name -> api.DeviceActivation
39, // 22: api.GetDeviceMetricsRequest.start:type_name -> google.protobuf.Timestamp
39, // 23: api.GetDeviceMetricsRequest.end:type_name -> google.protobuf.Timestamp
41, // 24: api.GetDeviceMetricsRequest.aggregation:type_name -> common.Aggregation
37, // 25: api.GetDeviceMetricsResponse.metrics:type_name -> api.GetDeviceMetricsResponse.MetricsEntry
38, // 26: api.GetDeviceMetricsResponse.states:type_name -> api.GetDeviceMetricsResponse.StatesEntry
39, // 27: api.GetDeviceLinkMetricsRequest.start:type_name -> google.protobuf.Timestamp
39, // 28: api.GetDeviceLinkMetricsRequest.end:type_name -> google.protobuf.Timestamp
41, // 29: api.GetDeviceLinkMetricsRequest.aggregation:type_name -> common.Aggregation
42, // 30: api.GetDeviceLinkMetricsResponse.rx_packets:type_name -> common.Metric
42, // 31: api.GetDeviceLinkMetricsResponse.gw_rssi:type_name -> common.Metric
42, // 32: api.GetDeviceLinkMetricsResponse.gw_snr:type_name -> common.Metric
42, // 33: api.GetDeviceLinkMetricsResponse.rx_packets_per_freq:type_name -> common.Metric
42, // 34: api.GetDeviceLinkMetricsResponse.rx_packets_per_dr:type_name -> common.Metric
42, // 35: api.GetDeviceLinkMetricsResponse.errors:type_name -> common.Metric
43, // 36: api.DeviceQueueItem.object:type_name -> google.protobuf.Struct
41, // 22: api.GetDeviceMetricsRequest.start:type_name -> google.protobuf.Timestamp
41, // 23: api.GetDeviceMetricsRequest.end:type_name -> google.protobuf.Timestamp
43, // 24: api.GetDeviceMetricsRequest.aggregation:type_name -> common.Aggregation
39, // 25: api.GetDeviceMetricsResponse.metrics:type_name -> api.GetDeviceMetricsResponse.MetricsEntry
40, // 26: api.GetDeviceMetricsResponse.states:type_name -> api.GetDeviceMetricsResponse.StatesEntry
41, // 27: api.GetDeviceLinkMetricsRequest.start:type_name -> google.protobuf.Timestamp
41, // 28: api.GetDeviceLinkMetricsRequest.end:type_name -> google.protobuf.Timestamp
43, // 29: api.GetDeviceLinkMetricsRequest.aggregation:type_name -> common.Aggregation
44, // 30: api.GetDeviceLinkMetricsResponse.rx_packets:type_name -> common.Metric
44, // 31: api.GetDeviceLinkMetricsResponse.gw_rssi:type_name -> common.Metric
44, // 32: api.GetDeviceLinkMetricsResponse.gw_snr:type_name -> common.Metric
44, // 33: api.GetDeviceLinkMetricsResponse.rx_packets_per_freq:type_name -> common.Metric
44, // 34: api.GetDeviceLinkMetricsResponse.rx_packets_per_dr:type_name -> common.Metric
44, // 35: api.GetDeviceLinkMetricsResponse.errors:type_name -> common.Metric
45, // 36: api.DeviceQueueItem.object:type_name -> google.protobuf.Struct
28, // 37: api.EnqueueDeviceQueueItemRequest.queue_item:type_name -> api.DeviceQueueItem
28, // 38: api.GetDeviceQueueItemsResponse.result:type_name -> api.DeviceQueueItem
42, // 39: api.GetDeviceMetricsResponse.MetricsEntry.value:type_name -> common.Metric
44, // 39: api.GetDeviceMetricsResponse.MetricsEntry.value:type_name -> common.Metric
25, // 40: api.GetDeviceMetricsResponse.StatesEntry.value:type_name -> api.DeviceState
4, // 41: api.DeviceService.Create:input_type -> api.CreateDeviceRequest
5, // 42: api.DeviceService.Get:input_type -> api.GetDeviceRequest
@ -2873,27 +3004,29 @@ var file_api_device_proto_depIdxs = []int32{
29, // 57: api.DeviceService.Enqueue:input_type -> api.EnqueueDeviceQueueItemRequest
31, // 58: api.DeviceService.FlushQueue:input_type -> api.FlushDeviceQueueRequest
32, // 59: api.DeviceService.GetQueue:input_type -> api.GetDeviceQueueItemsRequest
44, // 60: api.DeviceService.Create:output_type -> google.protobuf.Empty
6, // 61: api.DeviceService.Get:output_type -> api.GetDeviceResponse
44, // 62: api.DeviceService.Update:output_type -> google.protobuf.Empty
44, // 63: api.DeviceService.Delete:output_type -> google.protobuf.Empty
10, // 64: api.DeviceService.List:output_type -> api.ListDevicesResponse
44, // 65: api.DeviceService.CreateKeys:output_type -> google.protobuf.Empty
13, // 66: api.DeviceService.GetKeys:output_type -> api.GetDeviceKeysResponse
44, // 67: api.DeviceService.UpdateKeys:output_type -> google.protobuf.Empty
44, // 68: api.DeviceService.DeleteKeys:output_type -> google.protobuf.Empty
44, // 69: api.DeviceService.FlushDevNonces:output_type -> google.protobuf.Empty
44, // 70: api.DeviceService.Activate:output_type -> google.protobuf.Empty
44, // 71: api.DeviceService.Deactivate:output_type -> google.protobuf.Empty
20, // 72: api.DeviceService.GetActivation:output_type -> api.GetDeviceActivationResponse
22, // 73: api.DeviceService.GetRandomDevAddr:output_type -> api.GetRandomDevAddrResponse
24, // 74: api.DeviceService.GetMetrics:output_type -> api.GetDeviceMetricsResponse
27, // 75: api.DeviceService.GetLinkMetrics:output_type -> api.GetDeviceLinkMetricsResponse
30, // 76: api.DeviceService.Enqueue:output_type -> api.EnqueueDeviceQueueItemResponse
44, // 77: api.DeviceService.FlushQueue:output_type -> google.protobuf.Empty
33, // 78: api.DeviceService.GetQueue:output_type -> api.GetDeviceQueueItemsResponse
60, // [60:79] is the sub-list for method output_type
41, // [41:60] is the sub-list for method input_type
35, // 60: api.DeviceService.GetNextFCntDown:input_type -> api.GetDeviceNextFCntDownRequest
46, // 61: api.DeviceService.Create:output_type -> google.protobuf.Empty
6, // 62: api.DeviceService.Get:output_type -> api.GetDeviceResponse
46, // 63: api.DeviceService.Update:output_type -> google.protobuf.Empty
46, // 64: api.DeviceService.Delete:output_type -> google.protobuf.Empty
10, // 65: api.DeviceService.List:output_type -> api.ListDevicesResponse
46, // 66: api.DeviceService.CreateKeys:output_type -> google.protobuf.Empty
13, // 67: api.DeviceService.GetKeys:output_type -> api.GetDeviceKeysResponse
46, // 68: api.DeviceService.UpdateKeys:output_type -> google.protobuf.Empty
46, // 69: api.DeviceService.DeleteKeys:output_type -> google.protobuf.Empty
46, // 70: api.DeviceService.FlushDevNonces:output_type -> google.protobuf.Empty
46, // 71: api.DeviceService.Activate:output_type -> google.protobuf.Empty
46, // 72: api.DeviceService.Deactivate:output_type -> google.protobuf.Empty
20, // 73: api.DeviceService.GetActivation:output_type -> api.GetDeviceActivationResponse
22, // 74: api.DeviceService.GetRandomDevAddr:output_type -> api.GetRandomDevAddrResponse
24, // 75: api.DeviceService.GetMetrics:output_type -> api.GetDeviceMetricsResponse
27, // 76: api.DeviceService.GetLinkMetrics:output_type -> api.GetDeviceLinkMetricsResponse
30, // 77: api.DeviceService.Enqueue:output_type -> api.EnqueueDeviceQueueItemResponse
46, // 78: api.DeviceService.FlushQueue:output_type -> google.protobuf.Empty
33, // 79: api.DeviceService.GetQueue:output_type -> api.GetDeviceQueueItemsResponse
36, // 80: api.DeviceService.GetNextFCntDown:output_type -> api.GetDeviceNextFCntDownResponse
61, // [61:81] is the sub-list for method output_type
41, // [41:61] is the sub-list for method input_type
41, // [41:41] is the sub-list for extension type_name
41, // [41:41] is the sub-list for extension extendee
0, // [0:41] is the sub-list for field type_name
@ -3325,6 +3458,30 @@ func file_api_device_proto_init() {
return nil
}
}
file_api_device_proto_msgTypes[35].Exporter = func(v interface{}, i int) interface{} {
switch v := v.(*GetDeviceNextFCntDownRequest); i {
case 0:
return &v.state
case 1:
return &v.sizeCache
case 2:
return &v.unknownFields
default:
return nil
}
}
file_api_device_proto_msgTypes[36].Exporter = func(v interface{}, i int) interface{} {
switch v := v.(*GetDeviceNextFCntDownResponse); i {
case 0:
return &v.state
case 1:
return &v.sizeCache
case 2:
return &v.unknownFields
default:
return nil
}
}
}
type x struct{}
out := protoimpl.TypeBuilder{
@ -3332,7 +3489,7 @@ func file_api_device_proto_init() {
GoPackagePath: reflect.TypeOf(x{}).PkgPath(),
RawDescriptor: file_api_device_proto_rawDesc,
NumEnums: 0,
NumMessages: 39,
NumMessages: 41,
NumExtensions: 0,
NumServices: 1,
},

View File

@ -39,6 +39,7 @@ const (
DeviceService_Enqueue_FullMethodName = "/api.DeviceService/Enqueue"
DeviceService_FlushQueue_FullMethodName = "/api.DeviceService/FlushQueue"
DeviceService_GetQueue_FullMethodName = "/api.DeviceService/GetQueue"
DeviceService_GetNextFCntDown_FullMethodName = "/api.DeviceService/GetNextFCntDown"
)
// DeviceServiceClient is the client API for DeviceService service.
@ -89,6 +90,10 @@ type DeviceServiceClient interface {
FlushQueue(ctx context.Context, in *FlushDeviceQueueRequest, opts ...grpc.CallOption) (*emptypb.Empty, error)
// GetQueue returns the downlink device-queue.
GetQueue(ctx context.Context, in *GetDeviceQueueItemsRequest, opts ...grpc.CallOption) (*GetDeviceQueueItemsResponse, error)
// GetNextFCntDown returns the next FCntDown to use for enqueing encrypted
// downlinks. The difference with the DeviceActivation f_cont_down is that
// this method takes potential existing queue-items into account.
GetNextFCntDown(ctx context.Context, in *GetDeviceNextFCntDownRequest, opts ...grpc.CallOption) (*GetDeviceNextFCntDownResponse, error)
}
type deviceServiceClient struct {
@ -270,6 +275,15 @@ func (c *deviceServiceClient) GetQueue(ctx context.Context, in *GetDeviceQueueIt
return out, nil
}
func (c *deviceServiceClient) GetNextFCntDown(ctx context.Context, in *GetDeviceNextFCntDownRequest, opts ...grpc.CallOption) (*GetDeviceNextFCntDownResponse, error) {
out := new(GetDeviceNextFCntDownResponse)
err := c.cc.Invoke(ctx, DeviceService_GetNextFCntDown_FullMethodName, in, out, opts...)
if err != nil {
return nil, err
}
return out, nil
}
// DeviceServiceServer is the server API for DeviceService service.
// All implementations must embed UnimplementedDeviceServiceServer
// for forward compatibility
@ -318,6 +332,10 @@ type DeviceServiceServer interface {
FlushQueue(context.Context, *FlushDeviceQueueRequest) (*emptypb.Empty, error)
// GetQueue returns the downlink device-queue.
GetQueue(context.Context, *GetDeviceQueueItemsRequest) (*GetDeviceQueueItemsResponse, error)
// GetNextFCntDown returns the next FCntDown to use for enqueing encrypted
// downlinks. The difference with the DeviceActivation f_cont_down is that
// this method takes potential existing queue-items into account.
GetNextFCntDown(context.Context, *GetDeviceNextFCntDownRequest) (*GetDeviceNextFCntDownResponse, error)
mustEmbedUnimplementedDeviceServiceServer()
}
@ -382,6 +400,9 @@ func (UnimplementedDeviceServiceServer) FlushQueue(context.Context, *FlushDevice
func (UnimplementedDeviceServiceServer) GetQueue(context.Context, *GetDeviceQueueItemsRequest) (*GetDeviceQueueItemsResponse, error) {
return nil, status.Errorf(codes.Unimplemented, "method GetQueue not implemented")
}
func (UnimplementedDeviceServiceServer) GetNextFCntDown(context.Context, *GetDeviceNextFCntDownRequest) (*GetDeviceNextFCntDownResponse, error) {
return nil, status.Errorf(codes.Unimplemented, "method GetNextFCntDown not implemented")
}
func (UnimplementedDeviceServiceServer) mustEmbedUnimplementedDeviceServiceServer() {}
// UnsafeDeviceServiceServer may be embedded to opt out of forward compatibility for this service.
@ -737,6 +758,24 @@ func _DeviceService_GetQueue_Handler(srv interface{}, ctx context.Context, dec f
return interceptor(ctx, in, info, handler)
}
func _DeviceService_GetNextFCntDown_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) {
in := new(GetDeviceNextFCntDownRequest)
if err := dec(in); err != nil {
return nil, err
}
if interceptor == nil {
return srv.(DeviceServiceServer).GetNextFCntDown(ctx, in)
}
info := &grpc.UnaryServerInfo{
Server: srv,
FullMethod: DeviceService_GetNextFCntDown_FullMethodName,
}
handler := func(ctx context.Context, req interface{}) (interface{}, error) {
return srv.(DeviceServiceServer).GetNextFCntDown(ctx, req.(*GetDeviceNextFCntDownRequest))
}
return interceptor(ctx, in, info, handler)
}
// DeviceService_ServiceDesc is the grpc.ServiceDesc for DeviceService service.
// It's only intended for direct use with grpc.RegisterService,
// and not to be introspected or modified (even as a copy)
@ -820,6 +859,10 @@ var DeviceService_ServiceDesc = grpc.ServiceDesc{
MethodName: "GetQueue",
Handler: _DeviceService_GetQueue_Handler,
},
{
MethodName: "GetNextFCntDown",
Handler: _DeviceService_GetNextFCntDown_Handler,
},
},
Streams: []grpc.StreamDesc{},
Metadata: "api/device.proto",

View File

@ -100,21 +100,24 @@ const (
LogCode_DOWNLINK_GATEWAY LogCode = 8
// Relay new end-device.
LogCode_RELAY_NEW_END_DEVICE LogCode = 9
// Downlink frame-counter.
LogCode_F_CNT_DOWN LogCode = 10
)
// Enum value maps for LogCode.
var (
LogCode_name = map[int32]string{
0: "UNKNOWN",
1: "DOWNLINK_PAYLOAD_SIZE",
2: "UPLINK_CODEC",
3: "DOWNLINK_CODEC",
4: "OTAA",
5: "UPLINK_F_CNT_RESET",
6: "UPLINK_MIC",
7: "UPLINK_F_CNT_RETRANSMISSION",
8: "DOWNLINK_GATEWAY",
9: "RELAY_NEW_END_DEVICE",
0: "UNKNOWN",
1: "DOWNLINK_PAYLOAD_SIZE",
2: "UPLINK_CODEC",
3: "DOWNLINK_CODEC",
4: "OTAA",
5: "UPLINK_F_CNT_RESET",
6: "UPLINK_MIC",
7: "UPLINK_F_CNT_RETRANSMISSION",
8: "DOWNLINK_GATEWAY",
9: "RELAY_NEW_END_DEVICE",
10: "F_CNT_DOWN",
}
LogCode_value = map[string]int32{
"UNKNOWN": 0,
@ -127,6 +130,7 @@ var (
"UPLINK_F_CNT_RETRANSMISSION": 7,
"DOWNLINK_GATEWAY": 8,
"RELAY_NEW_END_DEVICE": 9,
"F_CNT_DOWN": 10,
}
)
@ -381,6 +385,64 @@ func (x *UplinkRelayRxInfo) GetWorChannel() uint32 {
return 0
}
// Join-Server context.
type JoinServerContext struct {
state protoimpl.MessageState
sizeCache protoimpl.SizeCache
unknownFields protoimpl.UnknownFields
// Session-key ID.
SessionKeyId string `protobuf:"bytes,1,opt,name=session_key_id,json=sessionKeyId,proto3" json:"session_key_id,omitempty"`
// AppSKey envelope.
AppSKey *common.KeyEnvelope `protobuf:"bytes,2,opt,name=app_s_key,json=appSKey,proto3" json:"app_s_key,omitempty"`
}
func (x *JoinServerContext) Reset() {
*x = JoinServerContext{}
if protoimpl.UnsafeEnabled {
mi := &file_integration_integration_proto_msgTypes[2]
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms.StoreMessageInfo(mi)
}
}
func (x *JoinServerContext) String() string {
return protoimpl.X.MessageStringOf(x)
}
func (*JoinServerContext) ProtoMessage() {}
func (x *JoinServerContext) ProtoReflect() protoreflect.Message {
mi := &file_integration_integration_proto_msgTypes[2]
if protoimpl.UnsafeEnabled && x != nil {
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
if ms.LoadMessageInfo() == nil {
ms.StoreMessageInfo(mi)
}
return ms
}
return mi.MessageOf(x)
}
// Deprecated: Use JoinServerContext.ProtoReflect.Descriptor instead.
func (*JoinServerContext) Descriptor() ([]byte, []int) {
return file_integration_integration_proto_rawDescGZIP(), []int{2}
}
func (x *JoinServerContext) GetSessionKeyId() string {
if x != nil {
return x.SessionKeyId
}
return ""
}
func (x *JoinServerContext) GetAppSKey() *common.KeyEnvelope {
if x != nil {
return x.AppSKey
}
return nil
}
// UplinkEvent is the message sent when an uplink payload has been received.
type UplinkEvent struct {
state protoimpl.MessageState
@ -416,12 +478,17 @@ type UplinkEvent struct {
TxInfo *gw.UplinkTxInfo `protobuf:"bytes,13,opt,name=tx_info,json=txInfo,proto3" json:"tx_info,omitempty"`
// Relay info.
RelayRxInfo *UplinkRelayRxInfo `protobuf:"bytes,14,opt,name=relay_rx_info,json=relayRxInfo,proto3" json:"relay_rx_info,omitempty"`
// Join-Server context.
// A non-empty value indicatest that ChirpStack does not have access to
// the AppSKey and that the encryption / decryption of the payloads is
// the responsibility of the end-application.
JoinServerContext *JoinServerContext `protobuf:"bytes,15,opt,name=join_server_context,json=joinServerContext,proto3" json:"join_server_context,omitempty"`
}
func (x *UplinkEvent) Reset() {
*x = UplinkEvent{}
if protoimpl.UnsafeEnabled {
mi := &file_integration_integration_proto_msgTypes[2]
mi := &file_integration_integration_proto_msgTypes[3]
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms.StoreMessageInfo(mi)
}
@ -434,7 +501,7 @@ func (x *UplinkEvent) String() string {
func (*UplinkEvent) ProtoMessage() {}
func (x *UplinkEvent) ProtoReflect() protoreflect.Message {
mi := &file_integration_integration_proto_msgTypes[2]
mi := &file_integration_integration_proto_msgTypes[3]
if protoimpl.UnsafeEnabled && x != nil {
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
if ms.LoadMessageInfo() == nil {
@ -447,7 +514,7 @@ func (x *UplinkEvent) ProtoReflect() protoreflect.Message {
// Deprecated: Use UplinkEvent.ProtoReflect.Descriptor instead.
func (*UplinkEvent) Descriptor() ([]byte, []int) {
return file_integration_integration_proto_rawDescGZIP(), []int{2}
return file_integration_integration_proto_rawDescGZIP(), []int{3}
}
func (x *UplinkEvent) GetDeduplicationId() string {
@ -548,6 +615,13 @@ func (x *UplinkEvent) GetRelayRxInfo() *UplinkRelayRxInfo {
return nil
}
func (x *UplinkEvent) GetJoinServerContext() *JoinServerContext {
if x != nil {
return x.JoinServerContext
}
return nil
}
// JoinEvent is the message sent when a device joined the network.
// Note: this event is sent at the first uplink after OTAA.
type JoinEvent struct {
@ -565,12 +639,17 @@ type JoinEvent struct {
DevAddr string `protobuf:"bytes,4,opt,name=dev_addr,json=devAddr,proto3" json:"dev_addr,omitempty"`
// Relay info.
RelayRxInfo *UplinkRelayRxInfo `protobuf:"bytes,5,opt,name=relay_rx_info,json=relayRxInfo,proto3" json:"relay_rx_info,omitempty"`
// Join-Server context.
// A non-empty value indicatest that ChirpStack does not have access to
// the AppSKey and that the encryption / decryption of the payloads is
// the responsibility of the end-application.
JoinServerContext *JoinServerContext `protobuf:"bytes,6,opt,name=join_server_context,json=joinServerContext,proto3" json:"join_server_context,omitempty"`
}
func (x *JoinEvent) Reset() {
*x = JoinEvent{}
if protoimpl.UnsafeEnabled {
mi := &file_integration_integration_proto_msgTypes[3]
mi := &file_integration_integration_proto_msgTypes[4]
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms.StoreMessageInfo(mi)
}
@ -583,7 +662,7 @@ func (x *JoinEvent) String() string {
func (*JoinEvent) ProtoMessage() {}
func (x *JoinEvent) ProtoReflect() protoreflect.Message {
mi := &file_integration_integration_proto_msgTypes[3]
mi := &file_integration_integration_proto_msgTypes[4]
if protoimpl.UnsafeEnabled && x != nil {
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
if ms.LoadMessageInfo() == nil {
@ -596,7 +675,7 @@ func (x *JoinEvent) ProtoReflect() protoreflect.Message {
// Deprecated: Use JoinEvent.ProtoReflect.Descriptor instead.
func (*JoinEvent) Descriptor() ([]byte, []int) {
return file_integration_integration_proto_rawDescGZIP(), []int{3}
return file_integration_integration_proto_rawDescGZIP(), []int{4}
}
func (x *JoinEvent) GetDeduplicationId() string {
@ -634,6 +713,13 @@ func (x *JoinEvent) GetRelayRxInfo() *UplinkRelayRxInfo {
return nil
}
func (x *JoinEvent) GetJoinServerContext() *JoinServerContext {
if x != nil {
return x.JoinServerContext
}
return nil
}
// AckEvent is the message sent when a confirmation on a confirmed downlink
// has been received -or- when the downlink timed out.
type AckEvent struct {
@ -658,7 +744,7 @@ type AckEvent struct {
func (x *AckEvent) Reset() {
*x = AckEvent{}
if protoimpl.UnsafeEnabled {
mi := &file_integration_integration_proto_msgTypes[4]
mi := &file_integration_integration_proto_msgTypes[5]
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms.StoreMessageInfo(mi)
}
@ -671,7 +757,7 @@ func (x *AckEvent) String() string {
func (*AckEvent) ProtoMessage() {}
func (x *AckEvent) ProtoReflect() protoreflect.Message {
mi := &file_integration_integration_proto_msgTypes[4]
mi := &file_integration_integration_proto_msgTypes[5]
if protoimpl.UnsafeEnabled && x != nil {
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
if ms.LoadMessageInfo() == nil {
@ -684,7 +770,7 @@ func (x *AckEvent) ProtoReflect() protoreflect.Message {
// Deprecated: Use AckEvent.ProtoReflect.Descriptor instead.
func (*AckEvent) Descriptor() ([]byte, []int) {
return file_integration_integration_proto_rawDescGZIP(), []int{4}
return file_integration_integration_proto_rawDescGZIP(), []int{5}
}
func (x *AckEvent) GetDeduplicationId() string {
@ -756,7 +842,7 @@ type TxAckEvent struct {
func (x *TxAckEvent) Reset() {
*x = TxAckEvent{}
if protoimpl.UnsafeEnabled {
mi := &file_integration_integration_proto_msgTypes[5]
mi := &file_integration_integration_proto_msgTypes[6]
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms.StoreMessageInfo(mi)
}
@ -769,7 +855,7 @@ func (x *TxAckEvent) String() string {
func (*TxAckEvent) ProtoMessage() {}
func (x *TxAckEvent) ProtoReflect() protoreflect.Message {
mi := &file_integration_integration_proto_msgTypes[5]
mi := &file_integration_integration_proto_msgTypes[6]
if protoimpl.UnsafeEnabled && x != nil {
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
if ms.LoadMessageInfo() == nil {
@ -782,7 +868,7 @@ func (x *TxAckEvent) ProtoReflect() protoreflect.Message {
// Deprecated: Use TxAckEvent.ProtoReflect.Descriptor instead.
func (*TxAckEvent) Descriptor() ([]byte, []int) {
return file_integration_integration_proto_rawDescGZIP(), []int{5}
return file_integration_integration_proto_rawDescGZIP(), []int{6}
}
func (x *TxAckEvent) GetDownlinkId() uint32 {
@ -857,7 +943,7 @@ type LogEvent struct {
func (x *LogEvent) Reset() {
*x = LogEvent{}
if protoimpl.UnsafeEnabled {
mi := &file_integration_integration_proto_msgTypes[6]
mi := &file_integration_integration_proto_msgTypes[7]
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms.StoreMessageInfo(mi)
}
@ -870,7 +956,7 @@ func (x *LogEvent) String() string {
func (*LogEvent) ProtoMessage() {}
func (x *LogEvent) ProtoReflect() protoreflect.Message {
mi := &file_integration_integration_proto_msgTypes[6]
mi := &file_integration_integration_proto_msgTypes[7]
if protoimpl.UnsafeEnabled && x != nil {
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
if ms.LoadMessageInfo() == nil {
@ -883,7 +969,7 @@ func (x *LogEvent) ProtoReflect() protoreflect.Message {
// Deprecated: Use LogEvent.ProtoReflect.Descriptor instead.
func (*LogEvent) Descriptor() ([]byte, []int) {
return file_integration_integration_proto_rawDescGZIP(), []int{6}
return file_integration_integration_proto_rawDescGZIP(), []int{7}
}
func (x *LogEvent) GetTime() *timestamppb.Timestamp {
@ -955,7 +1041,7 @@ type StatusEvent struct {
func (x *StatusEvent) Reset() {
*x = StatusEvent{}
if protoimpl.UnsafeEnabled {
mi := &file_integration_integration_proto_msgTypes[7]
mi := &file_integration_integration_proto_msgTypes[8]
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms.StoreMessageInfo(mi)
}
@ -968,7 +1054,7 @@ func (x *StatusEvent) String() string {
func (*StatusEvent) ProtoMessage() {}
func (x *StatusEvent) ProtoReflect() protoreflect.Message {
mi := &file_integration_integration_proto_msgTypes[7]
mi := &file_integration_integration_proto_msgTypes[8]
if protoimpl.UnsafeEnabled && x != nil {
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
if ms.LoadMessageInfo() == nil {
@ -981,7 +1067,7 @@ func (x *StatusEvent) ProtoReflect() protoreflect.Message {
// Deprecated: Use StatusEvent.ProtoReflect.Descriptor instead.
func (*StatusEvent) Descriptor() ([]byte, []int) {
return file_integration_integration_proto_rawDescGZIP(), []int{7}
return file_integration_integration_proto_rawDescGZIP(), []int{8}
}
func (x *StatusEvent) GetDeduplicationId() string {
@ -1052,7 +1138,7 @@ type LocationEvent struct {
func (x *LocationEvent) Reset() {
*x = LocationEvent{}
if protoimpl.UnsafeEnabled {
mi := &file_integration_integration_proto_msgTypes[8]
mi := &file_integration_integration_proto_msgTypes[9]
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms.StoreMessageInfo(mi)
}
@ -1065,7 +1151,7 @@ func (x *LocationEvent) String() string {
func (*LocationEvent) ProtoMessage() {}
func (x *LocationEvent) ProtoReflect() protoreflect.Message {
mi := &file_integration_integration_proto_msgTypes[8]
mi := &file_integration_integration_proto_msgTypes[9]
if protoimpl.UnsafeEnabled && x != nil {
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
if ms.LoadMessageInfo() == nil {
@ -1078,7 +1164,7 @@ func (x *LocationEvent) ProtoReflect() protoreflect.Message {
// Deprecated: Use LocationEvent.ProtoReflect.Descriptor instead.
func (*LocationEvent) Descriptor() ([]byte, []int) {
return file_integration_integration_proto_rawDescGZIP(), []int{8}
return file_integration_integration_proto_rawDescGZIP(), []int{9}
}
func (x *LocationEvent) GetDeduplicationId() string {
@ -1134,7 +1220,7 @@ type IntegrationEvent struct {
func (x *IntegrationEvent) Reset() {
*x = IntegrationEvent{}
if protoimpl.UnsafeEnabled {
mi := &file_integration_integration_proto_msgTypes[9]
mi := &file_integration_integration_proto_msgTypes[10]
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms.StoreMessageInfo(mi)
}
@ -1147,7 +1233,7 @@ func (x *IntegrationEvent) String() string {
func (*IntegrationEvent) ProtoMessage() {}
func (x *IntegrationEvent) ProtoReflect() protoreflect.Message {
mi := &file_integration_integration_proto_msgTypes[9]
mi := &file_integration_integration_proto_msgTypes[10]
if protoimpl.UnsafeEnabled && x != nil {
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
if ms.LoadMessageInfo() == nil {
@ -1160,7 +1246,7 @@ func (x *IntegrationEvent) ProtoReflect() protoreflect.Message {
// Deprecated: Use IntegrationEvent.ProtoReflect.Descriptor instead.
func (*IntegrationEvent) Descriptor() ([]byte, []int) {
return file_integration_integration_proto_rawDescGZIP(), []int{9}
return file_integration_integration_proto_rawDescGZIP(), []int{10}
}
func (x *IntegrationEvent) GetDeduplicationId() string {
@ -1232,7 +1318,7 @@ type DownlinkCommand struct {
func (x *DownlinkCommand) Reset() {
*x = DownlinkCommand{}
if protoimpl.UnsafeEnabled {
mi := &file_integration_integration_proto_msgTypes[10]
mi := &file_integration_integration_proto_msgTypes[11]
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms.StoreMessageInfo(mi)
}
@ -1245,7 +1331,7 @@ func (x *DownlinkCommand) String() string {
func (*DownlinkCommand) ProtoMessage() {}
func (x *DownlinkCommand) ProtoReflect() protoreflect.Message {
mi := &file_integration_integration_proto_msgTypes[10]
mi := &file_integration_integration_proto_msgTypes[11]
if protoimpl.UnsafeEnabled && x != nil {
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
if ms.LoadMessageInfo() == nil {
@ -1258,7 +1344,7 @@ func (x *DownlinkCommand) ProtoReflect() protoreflect.Message {
// Deprecated: Use DownlinkCommand.ProtoReflect.Descriptor instead.
func (*DownlinkCommand) Descriptor() ([]byte, []int) {
return file_integration_integration_proto_rawDescGZIP(), []int{10}
return file_integration_integration_proto_rawDescGZIP(), []int{11}
}
func (x *DownlinkCommand) GetId() string {
@ -1355,149 +1441,131 @@ var file_integration_integration_proto_rawDesc = []byte{
0x01, 0x28, 0x05, 0x52, 0x03, 0x73, 0x6e, 0x72, 0x12, 0x12, 0x0a, 0x04, 0x72, 0x73, 0x73, 0x69,
0x18, 0x05, 0x20, 0x01, 0x28, 0x05, 0x52, 0x04, 0x72, 0x73, 0x73, 0x69, 0x12, 0x1f, 0x0a, 0x0b,
0x77, 0x6f, 0x72, 0x5f, 0x63, 0x68, 0x61, 0x6e, 0x6e, 0x65, 0x6c, 0x18, 0x06, 0x20, 0x01, 0x28,
0x0d, 0x52, 0x0a, 0x77, 0x6f, 0x72, 0x43, 0x68, 0x61, 0x6e, 0x6e, 0x65, 0x6c, 0x22, 0x88, 0x04,
0x0a, 0x0b, 0x55, 0x70, 0x6c, 0x69, 0x6e, 0x6b, 0x45, 0x76, 0x65, 0x6e, 0x74, 0x12, 0x29, 0x0a,
0x10, 0x64, 0x65, 0x64, 0x75, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x5f, 0x69,
0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0f, 0x64, 0x65, 0x64, 0x75, 0x70, 0x6c, 0x69,
0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x49, 0x64, 0x12, 0x2e, 0x0a, 0x04, 0x74, 0x69, 0x6d, 0x65,
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, 0x04, 0x74, 0x69, 0x6d, 0x65, 0x12, 0x38, 0x0a, 0x0b, 0x64, 0x65, 0x76, 0x69,
0x63, 0x65, 0x5f, 0x69, 0x6e, 0x66, 0x6f, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x17, 0x2e,
0x69, 0x6e, 0x74, 0x65, 0x67, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2e, 0x44, 0x65, 0x76, 0x69,
0x63, 0x65, 0x49, 0x6e, 0x66, 0x6f, 0x52, 0x0a, 0x64, 0x65, 0x76, 0x69, 0x63, 0x65, 0x49, 0x6e,
0x66, 0x6f, 0x12, 0x19, 0x0a, 0x08, 0x64, 0x65, 0x76, 0x5f, 0x61, 0x64, 0x64, 0x72, 0x18, 0x04,
0x20, 0x01, 0x28, 0x09, 0x52, 0x07, 0x64, 0x65, 0x76, 0x41, 0x64, 0x64, 0x72, 0x12, 0x10, 0x0a,
0x03, 0x61, 0x64, 0x72, 0x18, 0x05, 0x20, 0x01, 0x28, 0x08, 0x52, 0x03, 0x61, 0x64, 0x72, 0x12,
0x0e, 0x0a, 0x02, 0x64, 0x72, 0x18, 0x06, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x02, 0x64, 0x72, 0x12,
0x13, 0x0a, 0x05, 0x66, 0x5f, 0x63, 0x6e, 0x74, 0x18, 0x07, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x04,
0x66, 0x43, 0x6e, 0x74, 0x12, 0x15, 0x0a, 0x06, 0x66, 0x5f, 0x70, 0x6f, 0x72, 0x74, 0x18, 0x08,
0x20, 0x01, 0x28, 0x0d, 0x52, 0x05, 0x66, 0x50, 0x6f, 0x72, 0x74, 0x12, 0x1c, 0x0a, 0x09, 0x63,
0x6f, 0x6e, 0x66, 0x69, 0x72, 0x6d, 0x65, 0x64, 0x18, 0x09, 0x20, 0x01, 0x28, 0x08, 0x52, 0x09,
0x63, 0x6f, 0x6e, 0x66, 0x69, 0x72, 0x6d, 0x65, 0x64, 0x12, 0x12, 0x0a, 0x04, 0x64, 0x61, 0x74,
0x61, 0x18, 0x0a, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x04, 0x64, 0x61, 0x74, 0x61, 0x12, 0x2f, 0x0a,
0x06, 0x6f, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x18, 0x0b, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x17, 0x2e,
0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e,
0x53, 0x74, 0x72, 0x75, 0x63, 0x74, 0x52, 0x06, 0x6f, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x12, 0x29,
0x0a, 0x07, 0x72, 0x78, 0x5f, 0x69, 0x6e, 0x66, 0x6f, 0x18, 0x0c, 0x20, 0x03, 0x28, 0x0b, 0x32,
0x10, 0x2e, 0x67, 0x77, 0x2e, 0x55, 0x70, 0x6c, 0x69, 0x6e, 0x6b, 0x52, 0x78, 0x49, 0x6e, 0x66,
0x6f, 0x52, 0x06, 0x72, 0x78, 0x49, 0x6e, 0x66, 0x6f, 0x12, 0x29, 0x0a, 0x07, 0x74, 0x78, 0x5f,
0x69, 0x6e, 0x66, 0x6f, 0x18, 0x0d, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x10, 0x2e, 0x67, 0x77, 0x2e,
0x55, 0x70, 0x6c, 0x69, 0x6e, 0x6b, 0x54, 0x78, 0x49, 0x6e, 0x66, 0x6f, 0x52, 0x06, 0x74, 0x78,
0x49, 0x6e, 0x66, 0x6f, 0x12, 0x42, 0x0a, 0x0d, 0x72, 0x65, 0x6c, 0x61, 0x79, 0x5f, 0x72, 0x78,
0x5f, 0x69, 0x6e, 0x66, 0x6f, 0x18, 0x0e, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1e, 0x2e, 0x69, 0x6e,
0x74, 0x65, 0x67, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2e, 0x55, 0x70, 0x6c, 0x69, 0x6e, 0x6b,
0x52, 0x65, 0x6c, 0x61, 0x79, 0x52, 0x78, 0x49, 0x6e, 0x66, 0x6f, 0x52, 0x0b, 0x72, 0x65, 0x6c,
0x61, 0x79, 0x52, 0x78, 0x49, 0x6e, 0x66, 0x6f, 0x22, 0xff, 0x01, 0x0a, 0x09, 0x4a, 0x6f, 0x69,
0x6e, 0x45, 0x76, 0x65, 0x6e, 0x74, 0x12, 0x29, 0x0a, 0x10, 0x64, 0x65, 0x64, 0x75, 0x70, 0x6c,
0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x5f, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09,
0x52, 0x0f, 0x64, 0x65, 0x64, 0x75, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x49,
0x64, 0x12, 0x2e, 0x0a, 0x04, 0x74, 0x69, 0x6d, 0x65, 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, 0x04, 0x74, 0x69, 0x6d,
0x65, 0x12, 0x38, 0x0a, 0x0b, 0x64, 0x65, 0x76, 0x69, 0x63, 0x65, 0x5f, 0x69, 0x6e, 0x66, 0x6f,
0x18, 0x03, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x17, 0x2e, 0x69, 0x6e, 0x74, 0x65, 0x67, 0x72, 0x61,
0x74, 0x69, 0x6f, 0x6e, 0x2e, 0x44, 0x65, 0x76, 0x69, 0x63, 0x65, 0x49, 0x6e, 0x66, 0x6f, 0x52,
0x0a, 0x64, 0x65, 0x76, 0x69, 0x63, 0x65, 0x49, 0x6e, 0x66, 0x6f, 0x12, 0x19, 0x0a, 0x08, 0x64,
0x65, 0x76, 0x5f, 0x61, 0x64, 0x64, 0x72, 0x18, 0x04, 0x20, 0x01, 0x28, 0x09, 0x52, 0x07, 0x64,
0x65, 0x76, 0x41, 0x64, 0x64, 0x72, 0x12, 0x42, 0x0a, 0x0d, 0x72, 0x65, 0x6c, 0x61, 0x79, 0x5f,
0x72, 0x78, 0x5f, 0x69, 0x6e, 0x66, 0x6f, 0x18, 0x05, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1e, 0x2e,
0x69, 0x6e, 0x74, 0x65, 0x67, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2e, 0x55, 0x70, 0x6c, 0x69,
0x6e, 0x6b, 0x52, 0x65, 0x6c, 0x61, 0x79, 0x52, 0x78, 0x49, 0x6e, 0x66, 0x6f, 0x52, 0x0b, 0x72,
0x65, 0x6c, 0x61, 0x79, 0x52, 0x78, 0x49, 0x6e, 0x66, 0x6f, 0x22, 0x85, 0x02, 0x0a, 0x08, 0x41,
0x63, 0x6b, 0x45, 0x76, 0x65, 0x6e, 0x74, 0x12, 0x29, 0x0a, 0x10, 0x64, 0x65, 0x64, 0x75, 0x70,
0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x5f, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28,
0x09, 0x52, 0x0f, 0x64, 0x65, 0x64, 0x75, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e,
0x49, 0x64, 0x12, 0x2e, 0x0a, 0x04, 0x74, 0x69, 0x6d, 0x65, 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, 0x04, 0x74, 0x69,
0x6d, 0x65, 0x12, 0x38, 0x0a, 0x0b, 0x64, 0x65, 0x76, 0x69, 0x63, 0x65, 0x5f, 0x69, 0x6e, 0x66,
0x6f, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x17, 0x2e, 0x69, 0x6e, 0x74, 0x65, 0x67, 0x72,
0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2e, 0x44, 0x65, 0x76, 0x69, 0x63, 0x65, 0x49, 0x6e, 0x66, 0x6f,
0x52, 0x0a, 0x64, 0x65, 0x76, 0x69, 0x63, 0x65, 0x49, 0x6e, 0x66, 0x6f, 0x12, 0x22, 0x0a, 0x0d,
0x71, 0x75, 0x65, 0x75, 0x65, 0x5f, 0x69, 0x74, 0x65, 0x6d, 0x5f, 0x69, 0x64, 0x18, 0x04, 0x20,
0x01, 0x28, 0x09, 0x52, 0x0b, 0x71, 0x75, 0x65, 0x75, 0x65, 0x49, 0x74, 0x65, 0x6d, 0x49, 0x64,
0x12, 0x22, 0x0a, 0x0c, 0x61, 0x63, 0x6b, 0x6e, 0x6f, 0x77, 0x6c, 0x65, 0x64, 0x67, 0x65, 0x64,
0x18, 0x05, 0x20, 0x01, 0x28, 0x08, 0x52, 0x0c, 0x61, 0x63, 0x6b, 0x6e, 0x6f, 0x77, 0x6c, 0x65,
0x64, 0x67, 0x65, 0x64, 0x12, 0x1c, 0x0a, 0x0a, 0x66, 0x5f, 0x63, 0x6e, 0x74, 0x5f, 0x64, 0x6f,
0x77, 0x6e, 0x18, 0x06, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x08, 0x66, 0x43, 0x6e, 0x74, 0x44, 0x6f,
0x77, 0x6e, 0x22, 0xa5, 0x02, 0x0a, 0x0a, 0x54, 0x78, 0x41, 0x63, 0x6b, 0x45, 0x76, 0x65, 0x6e,
0x74, 0x12, 0x1f, 0x0a, 0x0b, 0x64, 0x6f, 0x77, 0x6e, 0x6c, 0x69, 0x6e, 0x6b, 0x5f, 0x69, 0x64,
0x18, 0x01, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x0a, 0x64, 0x6f, 0x77, 0x6e, 0x6c, 0x69, 0x6e, 0x6b,
0x49, 0x64, 0x12, 0x2e, 0x0a, 0x04, 0x74, 0x69, 0x6d, 0x65, 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, 0x04, 0x74, 0x69,
0x6d, 0x65, 0x12, 0x38, 0x0a, 0x0b, 0x64, 0x65, 0x76, 0x69, 0x63, 0x65, 0x5f, 0x69, 0x6e, 0x66,
0x6f, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x17, 0x2e, 0x69, 0x6e, 0x74, 0x65, 0x67, 0x72,
0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2e, 0x44, 0x65, 0x76, 0x69, 0x63, 0x65, 0x49, 0x6e, 0x66, 0x6f,
0x52, 0x0a, 0x64, 0x65, 0x76, 0x69, 0x63, 0x65, 0x49, 0x6e, 0x66, 0x6f, 0x12, 0x22, 0x0a, 0x0d,
0x71, 0x75, 0x65, 0x75, 0x65, 0x5f, 0x69, 0x74, 0x65, 0x6d, 0x5f, 0x69, 0x64, 0x18, 0x04, 0x20,
0x01, 0x28, 0x09, 0x52, 0x0b, 0x71, 0x75, 0x65, 0x75, 0x65, 0x49, 0x74, 0x65, 0x6d, 0x49, 0x64,
0x12, 0x1c, 0x0a, 0x0a, 0x66, 0x5f, 0x63, 0x6e, 0x74, 0x5f, 0x64, 0x6f, 0x77, 0x6e, 0x18, 0x05,
0x20, 0x01, 0x28, 0x0d, 0x52, 0x08, 0x66, 0x43, 0x6e, 0x74, 0x44, 0x6f, 0x77, 0x6e, 0x12, 0x1d,
0x0a, 0x0a, 0x67, 0x61, 0x74, 0x65, 0x77, 0x61, 0x79, 0x5f, 0x69, 0x64, 0x18, 0x06, 0x20, 0x01,
0x28, 0x09, 0x52, 0x09, 0x67, 0x61, 0x74, 0x65, 0x77, 0x61, 0x79, 0x49, 0x64, 0x12, 0x2b, 0x0a,
0x07, 0x74, 0x78, 0x5f, 0x69, 0x6e, 0x66, 0x6f, 0x18, 0x07, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x12,
0x2e, 0x67, 0x77, 0x2e, 0x44, 0x6f, 0x77, 0x6e, 0x6c, 0x69, 0x6e, 0x6b, 0x54, 0x78, 0x49, 0x6e,
0x66, 0x6f, 0x52, 0x06, 0x74, 0x78, 0x49, 0x6e, 0x66, 0x6f, 0x22, 0xe7, 0x02, 0x0a, 0x08, 0x4c,
0x6f, 0x67, 0x45, 0x76, 0x65, 0x6e, 0x74, 0x12, 0x2e, 0x0a, 0x04, 0x74, 0x69, 0x6d, 0x65, 0x18,
0x01, 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, 0x04, 0x74, 0x69, 0x6d, 0x65, 0x12, 0x38, 0x0a, 0x0b, 0x64, 0x65, 0x76, 0x69, 0x63,
0x65, 0x5f, 0x69, 0x6e, 0x66, 0x6f, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x17, 0x2e, 0x69,
0x6e, 0x74, 0x65, 0x67, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2e, 0x44, 0x65, 0x76, 0x69, 0x63,
0x65, 0x49, 0x6e, 0x66, 0x6f, 0x52, 0x0a, 0x64, 0x65, 0x76, 0x69, 0x63, 0x65, 0x49, 0x6e, 0x66,
0x6f, 0x12, 0x2b, 0x0a, 0x05, 0x6c, 0x65, 0x76, 0x65, 0x6c, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0e,
0x32, 0x15, 0x2e, 0x69, 0x6e, 0x74, 0x65, 0x67, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2e, 0x4c,
0x6f, 0x67, 0x4c, 0x65, 0x76, 0x65, 0x6c, 0x52, 0x05, 0x6c, 0x65, 0x76, 0x65, 0x6c, 0x12, 0x28,
0x0a, 0x04, 0x63, 0x6f, 0x64, 0x65, 0x18, 0x04, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x14, 0x2e, 0x69,
0x6e, 0x74, 0x65, 0x67, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2e, 0x4c, 0x6f, 0x67, 0x43, 0x6f,
0x64, 0x65, 0x52, 0x04, 0x63, 0x6f, 0x64, 0x65, 0x12, 0x20, 0x0a, 0x0b, 0x64, 0x65, 0x73, 0x63,
0x72, 0x69, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x18, 0x05, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0b, 0x64,
0x65, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x3c, 0x0a, 0x07, 0x63, 0x6f,
0x6e, 0x74, 0x65, 0x78, 0x74, 0x18, 0x06, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x22, 0x2e, 0x69, 0x6e,
0x74, 0x65, 0x67, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2e, 0x4c, 0x6f, 0x67, 0x45, 0x76, 0x65,
0x6e, 0x74, 0x2e, 0x43, 0x6f, 0x6e, 0x74, 0x65, 0x78, 0x74, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x52,
0x07, 0x63, 0x6f, 0x6e, 0x74, 0x65, 0x78, 0x74, 0x1a, 0x3a, 0x0a, 0x0c, 0x43, 0x6f, 0x6e, 0x74,
0x65, 0x78, 0x74, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x12, 0x10, 0x0a, 0x03, 0x6b, 0x65, 0x79, 0x18,
0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x03, 0x6b, 0x65, 0x79, 0x12, 0x14, 0x0a, 0x05, 0x76, 0x61,
0x6c, 0x75, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65,
0x3a, 0x02, 0x38, 0x01, 0x22, 0xcf, 0x02, 0x0a, 0x0b, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x45,
0x76, 0x65, 0x6e, 0x74, 0x12, 0x29, 0x0a, 0x10, 0x64, 0x65, 0x64, 0x75, 0x70, 0x6c, 0x69, 0x63,
0x61, 0x74, 0x69, 0x6f, 0x6e, 0x5f, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0f,
0x64, 0x65, 0x64, 0x75, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x49, 0x64, 0x12,
0x2e, 0x0a, 0x04, 0x74, 0x69, 0x6d, 0x65, 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, 0x04, 0x74, 0x69, 0x6d, 0x65, 0x12,
0x38, 0x0a, 0x0b, 0x64, 0x65, 0x76, 0x69, 0x63, 0x65, 0x5f, 0x69, 0x6e, 0x66, 0x6f, 0x18, 0x03,
0x20, 0x01, 0x28, 0x0b, 0x32, 0x17, 0x2e, 0x69, 0x6e, 0x74, 0x65, 0x67, 0x72, 0x61, 0x74, 0x69,
0x6f, 0x6e, 0x2e, 0x44, 0x65, 0x76, 0x69, 0x63, 0x65, 0x49, 0x6e, 0x66, 0x6f, 0x52, 0x0a, 0x64,
0x65, 0x76, 0x69, 0x63, 0x65, 0x49, 0x6e, 0x66, 0x6f, 0x12, 0x16, 0x0a, 0x06, 0x6d, 0x61, 0x72,
0x67, 0x69, 0x6e, 0x18, 0x05, 0x20, 0x01, 0x28, 0x05, 0x52, 0x06, 0x6d, 0x61, 0x72, 0x67, 0x69,
0x6e, 0x12, 0x32, 0x0a, 0x15, 0x65, 0x78, 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x5f, 0x70, 0x6f,
0x77, 0x65, 0x72, 0x5f, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x18, 0x06, 0x20, 0x01, 0x28, 0x08,
0x52, 0x13, 0x65, 0x78, 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x50, 0x6f, 0x77, 0x65, 0x72, 0x53,
0x6f, 0x75, 0x72, 0x63, 0x65, 0x12, 0x3a, 0x0a, 0x19, 0x62, 0x61, 0x74, 0x74, 0x65, 0x72, 0x79,
0x5f, 0x6c, 0x65, 0x76, 0x65, 0x6c, 0x5f, 0x75, 0x6e, 0x61, 0x76, 0x61, 0x69, 0x6c, 0x61, 0x62,
0x6c, 0x65, 0x18, 0x07, 0x20, 0x01, 0x28, 0x08, 0x52, 0x17, 0x62, 0x61, 0x74, 0x74, 0x65, 0x72,
0x79, 0x4c, 0x65, 0x76, 0x65, 0x6c, 0x55, 0x6e, 0x61, 0x76, 0x61, 0x69, 0x6c, 0x61, 0x62, 0x6c,
0x65, 0x12, 0x23, 0x0a, 0x0d, 0x62, 0x61, 0x74, 0x74, 0x65, 0x72, 0x79, 0x5f, 0x6c, 0x65, 0x76,
0x65, 0x6c, 0x18, 0x08, 0x20, 0x01, 0x28, 0x02, 0x52, 0x0c, 0x62, 0x61, 0x74, 0x74, 0x65, 0x72,
0x79, 0x4c, 0x65, 0x76, 0x65, 0x6c, 0x22, 0xd2, 0x01, 0x0a, 0x0d, 0x4c, 0x6f, 0x63, 0x61, 0x74,
0x69, 0x6f, 0x6e, 0x45, 0x76, 0x65, 0x6e, 0x74, 0x12, 0x29, 0x0a, 0x10, 0x64, 0x65, 0x64, 0x75,
0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x5f, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01,
0x28, 0x09, 0x52, 0x0f, 0x64, 0x65, 0x64, 0x75, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f,
0x6e, 0x49, 0x64, 0x12, 0x2e, 0x0a, 0x04, 0x74, 0x69, 0x6d, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28,
0x0d, 0x52, 0x0a, 0x77, 0x6f, 0x72, 0x43, 0x68, 0x61, 0x6e, 0x6e, 0x65, 0x6c, 0x22, 0x6a, 0x0a,
0x11, 0x4a, 0x6f, 0x69, 0x6e, 0x53, 0x65, 0x72, 0x76, 0x65, 0x72, 0x43, 0x6f, 0x6e, 0x74, 0x65,
0x78, 0x74, 0x12, 0x24, 0x0a, 0x0e, 0x73, 0x65, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x5f, 0x6b, 0x65,
0x79, 0x5f, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0c, 0x73, 0x65, 0x73, 0x73,
0x69, 0x6f, 0x6e, 0x4b, 0x65, 0x79, 0x49, 0x64, 0x12, 0x2f, 0x0a, 0x09, 0x61, 0x70, 0x70, 0x5f,
0x73, 0x5f, 0x6b, 0x65, 0x79, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x13, 0x2e, 0x63, 0x6f,
0x6d, 0x6d, 0x6f, 0x6e, 0x2e, 0x4b, 0x65, 0x79, 0x45, 0x6e, 0x76, 0x65, 0x6c, 0x6f, 0x70, 0x65,
0x52, 0x07, 0x61, 0x70, 0x70, 0x53, 0x4b, 0x65, 0x79, 0x22, 0xd8, 0x04, 0x0a, 0x0b, 0x55, 0x70,
0x6c, 0x69, 0x6e, 0x6b, 0x45, 0x76, 0x65, 0x6e, 0x74, 0x12, 0x29, 0x0a, 0x10, 0x64, 0x65, 0x64,
0x75, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x5f, 0x69, 0x64, 0x18, 0x01, 0x20,
0x01, 0x28, 0x09, 0x52, 0x0f, 0x64, 0x65, 0x64, 0x75, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69,
0x6f, 0x6e, 0x49, 0x64, 0x12, 0x2e, 0x0a, 0x04, 0x74, 0x69, 0x6d, 0x65, 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, 0x04,
0x74, 0x69, 0x6d, 0x65, 0x12, 0x38, 0x0a, 0x0b, 0x64, 0x65, 0x76, 0x69, 0x63, 0x65, 0x5f, 0x69,
0x6e, 0x66, 0x6f, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x17, 0x2e, 0x69, 0x6e, 0x74, 0x65,
0x67, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2e, 0x44, 0x65, 0x76, 0x69, 0x63, 0x65, 0x49, 0x6e,
0x66, 0x6f, 0x52, 0x0a, 0x64, 0x65, 0x76, 0x69, 0x63, 0x65, 0x49, 0x6e, 0x66, 0x6f, 0x12, 0x19,
0x0a, 0x08, 0x64, 0x65, 0x76, 0x5f, 0x61, 0x64, 0x64, 0x72, 0x18, 0x04, 0x20, 0x01, 0x28, 0x09,
0x52, 0x07, 0x64, 0x65, 0x76, 0x41, 0x64, 0x64, 0x72, 0x12, 0x10, 0x0a, 0x03, 0x61, 0x64, 0x72,
0x18, 0x05, 0x20, 0x01, 0x28, 0x08, 0x52, 0x03, 0x61, 0x64, 0x72, 0x12, 0x0e, 0x0a, 0x02, 0x64,
0x72, 0x18, 0x06, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x02, 0x64, 0x72, 0x12, 0x13, 0x0a, 0x05, 0x66,
0x5f, 0x63, 0x6e, 0x74, 0x18, 0x07, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x04, 0x66, 0x43, 0x6e, 0x74,
0x12, 0x15, 0x0a, 0x06, 0x66, 0x5f, 0x70, 0x6f, 0x72, 0x74, 0x18, 0x08, 0x20, 0x01, 0x28, 0x0d,
0x52, 0x05, 0x66, 0x50, 0x6f, 0x72, 0x74, 0x12, 0x1c, 0x0a, 0x09, 0x63, 0x6f, 0x6e, 0x66, 0x69,
0x72, 0x6d, 0x65, 0x64, 0x18, 0x09, 0x20, 0x01, 0x28, 0x08, 0x52, 0x09, 0x63, 0x6f, 0x6e, 0x66,
0x69, 0x72, 0x6d, 0x65, 0x64, 0x12, 0x12, 0x0a, 0x04, 0x64, 0x61, 0x74, 0x61, 0x18, 0x0a, 0x20,
0x01, 0x28, 0x0c, 0x52, 0x04, 0x64, 0x61, 0x74, 0x61, 0x12, 0x2f, 0x0a, 0x06, 0x6f, 0x62, 0x6a,
0x65, 0x63, 0x74, 0x18, 0x0b, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x17, 0x2e, 0x67, 0x6f, 0x6f, 0x67,
0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x53, 0x74, 0x72, 0x75,
0x63, 0x74, 0x52, 0x06, 0x6f, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x12, 0x29, 0x0a, 0x07, 0x72, 0x78,
0x5f, 0x69, 0x6e, 0x66, 0x6f, 0x18, 0x0c, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x10, 0x2e, 0x67, 0x77,
0x2e, 0x55, 0x70, 0x6c, 0x69, 0x6e, 0x6b, 0x52, 0x78, 0x49, 0x6e, 0x66, 0x6f, 0x52, 0x06, 0x72,
0x78, 0x49, 0x6e, 0x66, 0x6f, 0x12, 0x29, 0x0a, 0x07, 0x74, 0x78, 0x5f, 0x69, 0x6e, 0x66, 0x6f,
0x18, 0x0d, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x10, 0x2e, 0x67, 0x77, 0x2e, 0x55, 0x70, 0x6c, 0x69,
0x6e, 0x6b, 0x54, 0x78, 0x49, 0x6e, 0x66, 0x6f, 0x52, 0x06, 0x74, 0x78, 0x49, 0x6e, 0x66, 0x6f,
0x12, 0x42, 0x0a, 0x0d, 0x72, 0x65, 0x6c, 0x61, 0x79, 0x5f, 0x72, 0x78, 0x5f, 0x69, 0x6e, 0x66,
0x6f, 0x18, 0x0e, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1e, 0x2e, 0x69, 0x6e, 0x74, 0x65, 0x67, 0x72,
0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2e, 0x55, 0x70, 0x6c, 0x69, 0x6e, 0x6b, 0x52, 0x65, 0x6c, 0x61,
0x79, 0x52, 0x78, 0x49, 0x6e, 0x66, 0x6f, 0x52, 0x0b, 0x72, 0x65, 0x6c, 0x61, 0x79, 0x52, 0x78,
0x49, 0x6e, 0x66, 0x6f, 0x12, 0x4e, 0x0a, 0x13, 0x6a, 0x6f, 0x69, 0x6e, 0x5f, 0x73, 0x65, 0x72,
0x76, 0x65, 0x72, 0x5f, 0x63, 0x6f, 0x6e, 0x74, 0x65, 0x78, 0x74, 0x18, 0x0f, 0x20, 0x01, 0x28,
0x0b, 0x32, 0x1e, 0x2e, 0x69, 0x6e, 0x74, 0x65, 0x67, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2e,
0x4a, 0x6f, 0x69, 0x6e, 0x53, 0x65, 0x72, 0x76, 0x65, 0x72, 0x43, 0x6f, 0x6e, 0x74, 0x65, 0x78,
0x74, 0x52, 0x11, 0x6a, 0x6f, 0x69, 0x6e, 0x53, 0x65, 0x72, 0x76, 0x65, 0x72, 0x43, 0x6f, 0x6e,
0x74, 0x65, 0x78, 0x74, 0x22, 0xcf, 0x02, 0x0a, 0x09, 0x4a, 0x6f, 0x69, 0x6e, 0x45, 0x76, 0x65,
0x6e, 0x74, 0x12, 0x29, 0x0a, 0x10, 0x64, 0x65, 0x64, 0x75, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74,
0x69, 0x6f, 0x6e, 0x5f, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0f, 0x64, 0x65,
0x64, 0x75, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x49, 0x64, 0x12, 0x2e, 0x0a,
0x04, 0x74, 0x69, 0x6d, 0x65, 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, 0x04, 0x74, 0x69, 0x6d, 0x65, 0x12, 0x38, 0x0a,
0x0b, 0x64, 0x65, 0x76, 0x69, 0x63, 0x65, 0x5f, 0x69, 0x6e, 0x66, 0x6f, 0x18, 0x03, 0x20, 0x01,
0x28, 0x0b, 0x32, 0x17, 0x2e, 0x69, 0x6e, 0x74, 0x65, 0x67, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e,
0x2e, 0x44, 0x65, 0x76, 0x69, 0x63, 0x65, 0x49, 0x6e, 0x66, 0x6f, 0x52, 0x0a, 0x64, 0x65, 0x76,
0x69, 0x63, 0x65, 0x49, 0x6e, 0x66, 0x6f, 0x12, 0x19, 0x0a, 0x08, 0x64, 0x65, 0x76, 0x5f, 0x61,
0x64, 0x64, 0x72, 0x18, 0x04, 0x20, 0x01, 0x28, 0x09, 0x52, 0x07, 0x64, 0x65, 0x76, 0x41, 0x64,
0x64, 0x72, 0x12, 0x42, 0x0a, 0x0d, 0x72, 0x65, 0x6c, 0x61, 0x79, 0x5f, 0x72, 0x78, 0x5f, 0x69,
0x6e, 0x66, 0x6f, 0x18, 0x05, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1e, 0x2e, 0x69, 0x6e, 0x74, 0x65,
0x67, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2e, 0x55, 0x70, 0x6c, 0x69, 0x6e, 0x6b, 0x52, 0x65,
0x6c, 0x61, 0x79, 0x52, 0x78, 0x49, 0x6e, 0x66, 0x6f, 0x52, 0x0b, 0x72, 0x65, 0x6c, 0x61, 0x79,
0x52, 0x78, 0x49, 0x6e, 0x66, 0x6f, 0x12, 0x4e, 0x0a, 0x13, 0x6a, 0x6f, 0x69, 0x6e, 0x5f, 0x73,
0x65, 0x72, 0x76, 0x65, 0x72, 0x5f, 0x63, 0x6f, 0x6e, 0x74, 0x65, 0x78, 0x74, 0x18, 0x06, 0x20,
0x01, 0x28, 0x0b, 0x32, 0x1e, 0x2e, 0x69, 0x6e, 0x74, 0x65, 0x67, 0x72, 0x61, 0x74, 0x69, 0x6f,
0x6e, 0x2e, 0x4a, 0x6f, 0x69, 0x6e, 0x53, 0x65, 0x72, 0x76, 0x65, 0x72, 0x43, 0x6f, 0x6e, 0x74,
0x65, 0x78, 0x74, 0x52, 0x11, 0x6a, 0x6f, 0x69, 0x6e, 0x53, 0x65, 0x72, 0x76, 0x65, 0x72, 0x43,
0x6f, 0x6e, 0x74, 0x65, 0x78, 0x74, 0x22, 0x85, 0x02, 0x0a, 0x08, 0x41, 0x63, 0x6b, 0x45, 0x76,
0x65, 0x6e, 0x74, 0x12, 0x29, 0x0a, 0x10, 0x64, 0x65, 0x64, 0x75, 0x70, 0x6c, 0x69, 0x63, 0x61,
0x74, 0x69, 0x6f, 0x6e, 0x5f, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0f, 0x64,
0x65, 0x64, 0x75, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x49, 0x64, 0x12, 0x2e,
0x0a, 0x04, 0x74, 0x69, 0x6d, 0x65, 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, 0x04, 0x74, 0x69, 0x6d, 0x65, 0x12, 0x38,
0x0a, 0x0b, 0x64, 0x65, 0x76, 0x69, 0x63, 0x65, 0x5f, 0x69, 0x6e, 0x66, 0x6f, 0x18, 0x03, 0x20,
0x01, 0x28, 0x0b, 0x32, 0x17, 0x2e, 0x69, 0x6e, 0x74, 0x65, 0x67, 0x72, 0x61, 0x74, 0x69, 0x6f,
0x6e, 0x2e, 0x44, 0x65, 0x76, 0x69, 0x63, 0x65, 0x49, 0x6e, 0x66, 0x6f, 0x52, 0x0a, 0x64, 0x65,
0x76, 0x69, 0x63, 0x65, 0x49, 0x6e, 0x66, 0x6f, 0x12, 0x22, 0x0a, 0x0d, 0x71, 0x75, 0x65, 0x75,
0x65, 0x5f, 0x69, 0x74, 0x65, 0x6d, 0x5f, 0x69, 0x64, 0x18, 0x04, 0x20, 0x01, 0x28, 0x09, 0x52,
0x0b, 0x71, 0x75, 0x65, 0x75, 0x65, 0x49, 0x74, 0x65, 0x6d, 0x49, 0x64, 0x12, 0x22, 0x0a, 0x0c,
0x61, 0x63, 0x6b, 0x6e, 0x6f, 0x77, 0x6c, 0x65, 0x64, 0x67, 0x65, 0x64, 0x18, 0x05, 0x20, 0x01,
0x28, 0x08, 0x52, 0x0c, 0x61, 0x63, 0x6b, 0x6e, 0x6f, 0x77, 0x6c, 0x65, 0x64, 0x67, 0x65, 0x64,
0x12, 0x1c, 0x0a, 0x0a, 0x66, 0x5f, 0x63, 0x6e, 0x74, 0x5f, 0x64, 0x6f, 0x77, 0x6e, 0x18, 0x06,
0x20, 0x01, 0x28, 0x0d, 0x52, 0x08, 0x66, 0x43, 0x6e, 0x74, 0x44, 0x6f, 0x77, 0x6e, 0x22, 0xa5,
0x02, 0x0a, 0x0a, 0x54, 0x78, 0x41, 0x63, 0x6b, 0x45, 0x76, 0x65, 0x6e, 0x74, 0x12, 0x1f, 0x0a,
0x0b, 0x64, 0x6f, 0x77, 0x6e, 0x6c, 0x69, 0x6e, 0x6b, 0x5f, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01,
0x28, 0x0d, 0x52, 0x0a, 0x64, 0x6f, 0x77, 0x6e, 0x6c, 0x69, 0x6e, 0x6b, 0x49, 0x64, 0x12, 0x2e,
0x0a, 0x04, 0x74, 0x69, 0x6d, 0x65, 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, 0x04, 0x74, 0x69, 0x6d, 0x65, 0x12, 0x38,
0x0a, 0x0b, 0x64, 0x65, 0x76, 0x69, 0x63, 0x65, 0x5f, 0x69, 0x6e, 0x66, 0x6f, 0x18, 0x03, 0x20,
0x01, 0x28, 0x0b, 0x32, 0x17, 0x2e, 0x69, 0x6e, 0x74, 0x65, 0x67, 0x72, 0x61, 0x74, 0x69, 0x6f,
0x6e, 0x2e, 0x44, 0x65, 0x76, 0x69, 0x63, 0x65, 0x49, 0x6e, 0x66, 0x6f, 0x52, 0x0a, 0x64, 0x65,
0x76, 0x69, 0x63, 0x65, 0x49, 0x6e, 0x66, 0x6f, 0x12, 0x22, 0x0a, 0x0d, 0x71, 0x75, 0x65, 0x75,
0x65, 0x5f, 0x69, 0x74, 0x65, 0x6d, 0x5f, 0x69, 0x64, 0x18, 0x04, 0x20, 0x01, 0x28, 0x09, 0x52,
0x0b, 0x71, 0x75, 0x65, 0x75, 0x65, 0x49, 0x74, 0x65, 0x6d, 0x49, 0x64, 0x12, 0x1c, 0x0a, 0x0a,
0x66, 0x5f, 0x63, 0x6e, 0x74, 0x5f, 0x64, 0x6f, 0x77, 0x6e, 0x18, 0x05, 0x20, 0x01, 0x28, 0x0d,
0x52, 0x08, 0x66, 0x43, 0x6e, 0x74, 0x44, 0x6f, 0x77, 0x6e, 0x12, 0x1d, 0x0a, 0x0a, 0x67, 0x61,
0x74, 0x65, 0x77, 0x61, 0x79, 0x5f, 0x69, 0x64, 0x18, 0x06, 0x20, 0x01, 0x28, 0x09, 0x52, 0x09,
0x67, 0x61, 0x74, 0x65, 0x77, 0x61, 0x79, 0x49, 0x64, 0x12, 0x2b, 0x0a, 0x07, 0x74, 0x78, 0x5f,
0x69, 0x6e, 0x66, 0x6f, 0x18, 0x07, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x12, 0x2e, 0x67, 0x77, 0x2e,
0x44, 0x6f, 0x77, 0x6e, 0x6c, 0x69, 0x6e, 0x6b, 0x54, 0x78, 0x49, 0x6e, 0x66, 0x6f, 0x52, 0x06,
0x74, 0x78, 0x49, 0x6e, 0x66, 0x6f, 0x22, 0xe7, 0x02, 0x0a, 0x08, 0x4c, 0x6f, 0x67, 0x45, 0x76,
0x65, 0x6e, 0x74, 0x12, 0x2e, 0x0a, 0x04, 0x74, 0x69, 0x6d, 0x65, 0x18, 0x01, 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, 0x04, 0x74,
0x69, 0x6d, 0x65, 0x12, 0x38, 0x0a, 0x0b, 0x64, 0x65, 0x76, 0x69, 0x63, 0x65, 0x5f, 0x69, 0x6e,
0x66, 0x6f, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x17, 0x2e, 0x69, 0x6e, 0x74, 0x65, 0x67,
0x66, 0x6f, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x17, 0x2e, 0x69, 0x6e, 0x74, 0x65, 0x67,
0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2e, 0x44, 0x65, 0x76, 0x69, 0x63, 0x65, 0x49, 0x6e, 0x66,
0x6f, 0x52, 0x0a, 0x64, 0x65, 0x76, 0x69, 0x63, 0x65, 0x49, 0x6e, 0x66, 0x6f, 0x12, 0x2c, 0x0a,
0x08, 0x6c, 0x6f, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x18, 0x04, 0x20, 0x01, 0x28, 0x0b, 0x32,
0x10, 0x2e, 0x63, 0x6f, 0x6d, 0x6d, 0x6f, 0x6e, 0x2e, 0x4c, 0x6f, 0x63, 0x61, 0x74, 0x69, 0x6f,
0x6e, 0x52, 0x08, 0x6c, 0x6f, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x22, 0xa2, 0x02, 0x0a, 0x10,
0x49, 0x6e, 0x74, 0x65, 0x67, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x45, 0x76, 0x65, 0x6e, 0x74,
0x6f, 0x52, 0x0a, 0x64, 0x65, 0x76, 0x69, 0x63, 0x65, 0x49, 0x6e, 0x66, 0x6f, 0x12, 0x2b, 0x0a,
0x05, 0x6c, 0x65, 0x76, 0x65, 0x6c, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x15, 0x2e, 0x69,
0x6e, 0x74, 0x65, 0x67, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2e, 0x4c, 0x6f, 0x67, 0x4c, 0x65,
0x76, 0x65, 0x6c, 0x52, 0x05, 0x6c, 0x65, 0x76, 0x65, 0x6c, 0x12, 0x28, 0x0a, 0x04, 0x63, 0x6f,
0x64, 0x65, 0x18, 0x04, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x14, 0x2e, 0x69, 0x6e, 0x74, 0x65, 0x67,
0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2e, 0x4c, 0x6f, 0x67, 0x43, 0x6f, 0x64, 0x65, 0x52, 0x04,
0x63, 0x6f, 0x64, 0x65, 0x12, 0x20, 0x0a, 0x0b, 0x64, 0x65, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74,
0x69, 0x6f, 0x6e, 0x18, 0x05, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0b, 0x64, 0x65, 0x73, 0x63, 0x72,
0x69, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x3c, 0x0a, 0x07, 0x63, 0x6f, 0x6e, 0x74, 0x65, 0x78,
0x74, 0x18, 0x06, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x22, 0x2e, 0x69, 0x6e, 0x74, 0x65, 0x67, 0x72,
0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2e, 0x4c, 0x6f, 0x67, 0x45, 0x76, 0x65, 0x6e, 0x74, 0x2e, 0x43,
0x6f, 0x6e, 0x74, 0x65, 0x78, 0x74, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x52, 0x07, 0x63, 0x6f, 0x6e,
0x74, 0x65, 0x78, 0x74, 0x1a, 0x3a, 0x0a, 0x0c, 0x43, 0x6f, 0x6e, 0x74, 0x65, 0x78, 0x74, 0x45,
0x6e, 0x74, 0x72, 0x79, 0x12, 0x10, 0x0a, 0x03, 0x6b, 0x65, 0x79, 0x18, 0x01, 0x20, 0x01, 0x28,
0x09, 0x52, 0x03, 0x6b, 0x65, 0x79, 0x12, 0x14, 0x0a, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18,
0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x3a, 0x02, 0x38, 0x01,
0x22, 0xcf, 0x02, 0x0a, 0x0b, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x45, 0x76, 0x65, 0x6e, 0x74,
0x12, 0x29, 0x0a, 0x10, 0x64, 0x65, 0x64, 0x75, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f,
0x6e, 0x5f, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0f, 0x64, 0x65, 0x64, 0x75,
0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x49, 0x64, 0x12, 0x2e, 0x0a, 0x04, 0x74,
@ -1507,51 +1575,87 @@ var file_integration_integration_proto_rawDesc = []byte{
0x65, 0x76, 0x69, 0x63, 0x65, 0x5f, 0x69, 0x6e, 0x66, 0x6f, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0b,
0x32, 0x17, 0x2e, 0x69, 0x6e, 0x74, 0x65, 0x67, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2e, 0x44,
0x65, 0x76, 0x69, 0x63, 0x65, 0x49, 0x6e, 0x66, 0x6f, 0x52, 0x0a, 0x64, 0x65, 0x76, 0x69, 0x63,
0x65, 0x49, 0x6e, 0x66, 0x6f, 0x12, 0x29, 0x0a, 0x10, 0x69, 0x6e, 0x74, 0x65, 0x67, 0x72, 0x61,
0x74, 0x69, 0x6f, 0x6e, 0x5f, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x04, 0x20, 0x01, 0x28, 0x09, 0x52,
0x0f, 0x69, 0x6e, 0x74, 0x65, 0x67, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x4e, 0x61, 0x6d, 0x65,
0x12, 0x1d, 0x0a, 0x0a, 0x65, 0x76, 0x65, 0x6e, 0x74, 0x5f, 0x74, 0x79, 0x70, 0x65, 0x18, 0x05,
0x20, 0x01, 0x28, 0x09, 0x52, 0x09, 0x65, 0x76, 0x65, 0x6e, 0x74, 0x54, 0x79, 0x70, 0x65, 0x12,
0x2f, 0x0a, 0x06, 0x6f, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x18, 0x06, 0x20, 0x01, 0x28, 0x0b, 0x32,
0x17, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75,
0x66, 0x2e, 0x53, 0x74, 0x72, 0x75, 0x63, 0x74, 0x52, 0x06, 0x6f, 0x62, 0x6a, 0x65, 0x63, 0x74,
0x22, 0xb4, 0x01, 0x0a, 0x0f, 0x44, 0x6f, 0x77, 0x6e, 0x6c, 0x69, 0x6e, 0x6b, 0x43, 0x6f, 0x6d,
0x6d, 0x61, 0x6e, 0x64, 0x12, 0x0e, 0x0a, 0x02, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09,
0x52, 0x02, 0x69, 0x64, 0x12, 0x17, 0x0a, 0x07, 0x64, 0x65, 0x76, 0x5f, 0x65, 0x75, 0x69, 0x18,
0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x06, 0x64, 0x65, 0x76, 0x45, 0x75, 0x69, 0x12, 0x1c, 0x0a,
0x09, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x72, 0x6d, 0x65, 0x64, 0x18, 0x03, 0x20, 0x01, 0x28, 0x08,
0x52, 0x09, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x72, 0x6d, 0x65, 0x64, 0x12, 0x15, 0x0a, 0x06, 0x66,
0x5f, 0x70, 0x6f, 0x72, 0x74, 0x18, 0x04, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x05, 0x66, 0x50, 0x6f,
0x72, 0x74, 0x12, 0x12, 0x0a, 0x04, 0x64, 0x61, 0x74, 0x61, 0x18, 0x05, 0x20, 0x01, 0x28, 0x0c,
0x52, 0x04, 0x64, 0x61, 0x74, 0x61, 0x12, 0x2f, 0x0a, 0x06, 0x6f, 0x62, 0x6a, 0x65, 0x63, 0x74,
0x18, 0x06, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x17, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e,
0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x53, 0x74, 0x72, 0x75, 0x63, 0x74, 0x52,
0x06, 0x6f, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x2a, 0x2c, 0x0a, 0x08, 0x4c, 0x6f, 0x67, 0x4c, 0x65,
0x76, 0x65, 0x6c, 0x12, 0x08, 0x0a, 0x04, 0x49, 0x4e, 0x46, 0x4f, 0x10, 0x00, 0x12, 0x0b, 0x0a,
0x07, 0x57, 0x41, 0x52, 0x4e, 0x49, 0x4e, 0x47, 0x10, 0x01, 0x12, 0x09, 0x0a, 0x05, 0x45, 0x52,
0x52, 0x4f, 0x52, 0x10, 0x02, 0x2a, 0xda, 0x01, 0x0a, 0x07, 0x4c, 0x6f, 0x67, 0x43, 0x6f, 0x64,
0x65, 0x12, 0x0b, 0x0a, 0x07, 0x55, 0x4e, 0x4b, 0x4e, 0x4f, 0x57, 0x4e, 0x10, 0x00, 0x12, 0x19,
0x0a, 0x15, 0x44, 0x4f, 0x57, 0x4e, 0x4c, 0x49, 0x4e, 0x4b, 0x5f, 0x50, 0x41, 0x59, 0x4c, 0x4f,
0x41, 0x44, 0x5f, 0x53, 0x49, 0x5a, 0x45, 0x10, 0x01, 0x12, 0x10, 0x0a, 0x0c, 0x55, 0x50, 0x4c,
0x49, 0x4e, 0x4b, 0x5f, 0x43, 0x4f, 0x44, 0x45, 0x43, 0x10, 0x02, 0x12, 0x12, 0x0a, 0x0e, 0x44,
0x4f, 0x57, 0x4e, 0x4c, 0x49, 0x4e, 0x4b, 0x5f, 0x43, 0x4f, 0x44, 0x45, 0x43, 0x10, 0x03, 0x12,
0x08, 0x0a, 0x04, 0x4f, 0x54, 0x41, 0x41, 0x10, 0x04, 0x12, 0x16, 0x0a, 0x12, 0x55, 0x50, 0x4c,
0x49, 0x4e, 0x4b, 0x5f, 0x46, 0x5f, 0x43, 0x4e, 0x54, 0x5f, 0x52, 0x45, 0x53, 0x45, 0x54, 0x10,
0x05, 0x12, 0x0e, 0x0a, 0x0a, 0x55, 0x50, 0x4c, 0x49, 0x4e, 0x4b, 0x5f, 0x4d, 0x49, 0x43, 0x10,
0x06, 0x12, 0x1f, 0x0a, 0x1b, 0x55, 0x50, 0x4c, 0x49, 0x4e, 0x4b, 0x5f, 0x46, 0x5f, 0x43, 0x4e,
0x54, 0x5f, 0x52, 0x45, 0x54, 0x52, 0x41, 0x4e, 0x53, 0x4d, 0x49, 0x53, 0x53, 0x49, 0x4f, 0x4e,
0x10, 0x07, 0x12, 0x14, 0x0a, 0x10, 0x44, 0x4f, 0x57, 0x4e, 0x4c, 0x49, 0x4e, 0x4b, 0x5f, 0x47,
0x41, 0x54, 0x45, 0x57, 0x41, 0x59, 0x10, 0x08, 0x12, 0x18, 0x0a, 0x14, 0x52, 0x45, 0x4c, 0x41,
0x59, 0x5f, 0x4e, 0x45, 0x57, 0x5f, 0x45, 0x4e, 0x44, 0x5f, 0x44, 0x45, 0x56, 0x49, 0x43, 0x45,
0x10, 0x09, 0x42, 0x81, 0x01, 0x0a, 0x1d, 0x69, 0x6f, 0x2e, 0x63, 0x68, 0x69, 0x72, 0x70, 0x73,
0x74, 0x61, 0x63, 0x6b, 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x69, 0x6e, 0x74, 0x65, 0x67, 0x72, 0x61,
0x74, 0x69, 0x6f, 0x6e, 0x42, 0x10, 0x49, 0x6e, 0x74, 0x65, 0x67, 0x72, 0x61, 0x74, 0x69, 0x6f,
0x6e, 0x50, 0x72, 0x6f, 0x74, 0x6f, 0x50, 0x01, 0x5a, 0x33, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62,
0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x62, 0x72, 0x6f, 0x63, 0x61, 0x61, 0x72, 0x2f, 0x63, 0x68, 0x69,
0x72, 0x70, 0x73, 0x74, 0x61, 0x63, 0x6b, 0x2f, 0x61, 0x70, 0x69, 0x2f, 0x67, 0x6f, 0x2f, 0x76,
0x34, 0x2f, 0x69, 0x6e, 0x74, 0x65, 0x67, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0xaa, 0x02, 0x16,
0x43, 0x68, 0x69, 0x72, 0x70, 0x73, 0x74, 0x61, 0x63, 0x6b, 0x2e, 0x49, 0x6e, 0x74, 0x65, 0x67,
0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33,
0x65, 0x49, 0x6e, 0x66, 0x6f, 0x12, 0x16, 0x0a, 0x06, 0x6d, 0x61, 0x72, 0x67, 0x69, 0x6e, 0x18,
0x05, 0x20, 0x01, 0x28, 0x05, 0x52, 0x06, 0x6d, 0x61, 0x72, 0x67, 0x69, 0x6e, 0x12, 0x32, 0x0a,
0x15, 0x65, 0x78, 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x5f, 0x70, 0x6f, 0x77, 0x65, 0x72, 0x5f,
0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x18, 0x06, 0x20, 0x01, 0x28, 0x08, 0x52, 0x13, 0x65, 0x78,
0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x50, 0x6f, 0x77, 0x65, 0x72, 0x53, 0x6f, 0x75, 0x72, 0x63,
0x65, 0x12, 0x3a, 0x0a, 0x19, 0x62, 0x61, 0x74, 0x74, 0x65, 0x72, 0x79, 0x5f, 0x6c, 0x65, 0x76,
0x65, 0x6c, 0x5f, 0x75, 0x6e, 0x61, 0x76, 0x61, 0x69, 0x6c, 0x61, 0x62, 0x6c, 0x65, 0x18, 0x07,
0x20, 0x01, 0x28, 0x08, 0x52, 0x17, 0x62, 0x61, 0x74, 0x74, 0x65, 0x72, 0x79, 0x4c, 0x65, 0x76,
0x65, 0x6c, 0x55, 0x6e, 0x61, 0x76, 0x61, 0x69, 0x6c, 0x61, 0x62, 0x6c, 0x65, 0x12, 0x23, 0x0a,
0x0d, 0x62, 0x61, 0x74, 0x74, 0x65, 0x72, 0x79, 0x5f, 0x6c, 0x65, 0x76, 0x65, 0x6c, 0x18, 0x08,
0x20, 0x01, 0x28, 0x02, 0x52, 0x0c, 0x62, 0x61, 0x74, 0x74, 0x65, 0x72, 0x79, 0x4c, 0x65, 0x76,
0x65, 0x6c, 0x22, 0xd2, 0x01, 0x0a, 0x0d, 0x4c, 0x6f, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x45,
0x76, 0x65, 0x6e, 0x74, 0x12, 0x29, 0x0a, 0x10, 0x64, 0x65, 0x64, 0x75, 0x70, 0x6c, 0x69, 0x63,
0x61, 0x74, 0x69, 0x6f, 0x6e, 0x5f, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0f,
0x64, 0x65, 0x64, 0x75, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x49, 0x64, 0x12,
0x2e, 0x0a, 0x04, 0x74, 0x69, 0x6d, 0x65, 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, 0x04, 0x74, 0x69, 0x6d, 0x65, 0x12,
0x38, 0x0a, 0x0b, 0x64, 0x65, 0x76, 0x69, 0x63, 0x65, 0x5f, 0x69, 0x6e, 0x66, 0x6f, 0x18, 0x03,
0x20, 0x01, 0x28, 0x0b, 0x32, 0x17, 0x2e, 0x69, 0x6e, 0x74, 0x65, 0x67, 0x72, 0x61, 0x74, 0x69,
0x6f, 0x6e, 0x2e, 0x44, 0x65, 0x76, 0x69, 0x63, 0x65, 0x49, 0x6e, 0x66, 0x6f, 0x52, 0x0a, 0x64,
0x65, 0x76, 0x69, 0x63, 0x65, 0x49, 0x6e, 0x66, 0x6f, 0x12, 0x2c, 0x0a, 0x08, 0x6c, 0x6f, 0x63,
0x61, 0x74, 0x69, 0x6f, 0x6e, 0x18, 0x04, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x10, 0x2e, 0x63, 0x6f,
0x6d, 0x6d, 0x6f, 0x6e, 0x2e, 0x4c, 0x6f, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x08, 0x6c,
0x6f, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x22, 0xa2, 0x02, 0x0a, 0x10, 0x49, 0x6e, 0x74, 0x65,
0x67, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x45, 0x76, 0x65, 0x6e, 0x74, 0x12, 0x29, 0x0a, 0x10,
0x64, 0x65, 0x64, 0x75, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x5f, 0x69, 0x64,
0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0f, 0x64, 0x65, 0x64, 0x75, 0x70, 0x6c, 0x69, 0x63,
0x61, 0x74, 0x69, 0x6f, 0x6e, 0x49, 0x64, 0x12, 0x2e, 0x0a, 0x04, 0x74, 0x69, 0x6d, 0x65, 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, 0x04, 0x74, 0x69, 0x6d, 0x65, 0x12, 0x38, 0x0a, 0x0b, 0x64, 0x65, 0x76, 0x69, 0x63,
0x65, 0x5f, 0x69, 0x6e, 0x66, 0x6f, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x17, 0x2e, 0x69,
0x6e, 0x74, 0x65, 0x67, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2e, 0x44, 0x65, 0x76, 0x69, 0x63,
0x65, 0x49, 0x6e, 0x66, 0x6f, 0x52, 0x0a, 0x64, 0x65, 0x76, 0x69, 0x63, 0x65, 0x49, 0x6e, 0x66,
0x6f, 0x12, 0x29, 0x0a, 0x10, 0x69, 0x6e, 0x74, 0x65, 0x67, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e,
0x5f, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x04, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0f, 0x69, 0x6e, 0x74,
0x65, 0x67, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x4e, 0x61, 0x6d, 0x65, 0x12, 0x1d, 0x0a, 0x0a,
0x65, 0x76, 0x65, 0x6e, 0x74, 0x5f, 0x74, 0x79, 0x70, 0x65, 0x18, 0x05, 0x20, 0x01, 0x28, 0x09,
0x52, 0x09, 0x65, 0x76, 0x65, 0x6e, 0x74, 0x54, 0x79, 0x70, 0x65, 0x12, 0x2f, 0x0a, 0x06, 0x6f,
0x62, 0x6a, 0x65, 0x63, 0x74, 0x18, 0x06, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x17, 0x2e, 0x67, 0x6f,
0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x53, 0x74,
0x72, 0x75, 0x63, 0x74, 0x52, 0x06, 0x6f, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x22, 0xb4, 0x01, 0x0a,
0x0f, 0x44, 0x6f, 0x77, 0x6e, 0x6c, 0x69, 0x6e, 0x6b, 0x43, 0x6f, 0x6d, 0x6d, 0x61, 0x6e, 0x64,
0x12, 0x0e, 0x0a, 0x02, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x02, 0x69, 0x64,
0x12, 0x17, 0x0a, 0x07, 0x64, 0x65, 0x76, 0x5f, 0x65, 0x75, 0x69, 0x18, 0x02, 0x20, 0x01, 0x28,
0x09, 0x52, 0x06, 0x64, 0x65, 0x76, 0x45, 0x75, 0x69, 0x12, 0x1c, 0x0a, 0x09, 0x63, 0x6f, 0x6e,
0x66, 0x69, 0x72, 0x6d, 0x65, 0x64, 0x18, 0x03, 0x20, 0x01, 0x28, 0x08, 0x52, 0x09, 0x63, 0x6f,
0x6e, 0x66, 0x69, 0x72, 0x6d, 0x65, 0x64, 0x12, 0x15, 0x0a, 0x06, 0x66, 0x5f, 0x70, 0x6f, 0x72,
0x74, 0x18, 0x04, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x05, 0x66, 0x50, 0x6f, 0x72, 0x74, 0x12, 0x12,
0x0a, 0x04, 0x64, 0x61, 0x74, 0x61, 0x18, 0x05, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x04, 0x64, 0x61,
0x74, 0x61, 0x12, 0x2f, 0x0a, 0x06, 0x6f, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x18, 0x06, 0x20, 0x01,
0x28, 0x0b, 0x32, 0x17, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74,
0x6f, 0x62, 0x75, 0x66, 0x2e, 0x53, 0x74, 0x72, 0x75, 0x63, 0x74, 0x52, 0x06, 0x6f, 0x62, 0x6a,
0x65, 0x63, 0x74, 0x2a, 0x2c, 0x0a, 0x08, 0x4c, 0x6f, 0x67, 0x4c, 0x65, 0x76, 0x65, 0x6c, 0x12,
0x08, 0x0a, 0x04, 0x49, 0x4e, 0x46, 0x4f, 0x10, 0x00, 0x12, 0x0b, 0x0a, 0x07, 0x57, 0x41, 0x52,
0x4e, 0x49, 0x4e, 0x47, 0x10, 0x01, 0x12, 0x09, 0x0a, 0x05, 0x45, 0x52, 0x52, 0x4f, 0x52, 0x10,
0x02, 0x2a, 0xea, 0x01, 0x0a, 0x07, 0x4c, 0x6f, 0x67, 0x43, 0x6f, 0x64, 0x65, 0x12, 0x0b, 0x0a,
0x07, 0x55, 0x4e, 0x4b, 0x4e, 0x4f, 0x57, 0x4e, 0x10, 0x00, 0x12, 0x19, 0x0a, 0x15, 0x44, 0x4f,
0x57, 0x4e, 0x4c, 0x49, 0x4e, 0x4b, 0x5f, 0x50, 0x41, 0x59, 0x4c, 0x4f, 0x41, 0x44, 0x5f, 0x53,
0x49, 0x5a, 0x45, 0x10, 0x01, 0x12, 0x10, 0x0a, 0x0c, 0x55, 0x50, 0x4c, 0x49, 0x4e, 0x4b, 0x5f,
0x43, 0x4f, 0x44, 0x45, 0x43, 0x10, 0x02, 0x12, 0x12, 0x0a, 0x0e, 0x44, 0x4f, 0x57, 0x4e, 0x4c,
0x49, 0x4e, 0x4b, 0x5f, 0x43, 0x4f, 0x44, 0x45, 0x43, 0x10, 0x03, 0x12, 0x08, 0x0a, 0x04, 0x4f,
0x54, 0x41, 0x41, 0x10, 0x04, 0x12, 0x16, 0x0a, 0x12, 0x55, 0x50, 0x4c, 0x49, 0x4e, 0x4b, 0x5f,
0x46, 0x5f, 0x43, 0x4e, 0x54, 0x5f, 0x52, 0x45, 0x53, 0x45, 0x54, 0x10, 0x05, 0x12, 0x0e, 0x0a,
0x0a, 0x55, 0x50, 0x4c, 0x49, 0x4e, 0x4b, 0x5f, 0x4d, 0x49, 0x43, 0x10, 0x06, 0x12, 0x1f, 0x0a,
0x1b, 0x55, 0x50, 0x4c, 0x49, 0x4e, 0x4b, 0x5f, 0x46, 0x5f, 0x43, 0x4e, 0x54, 0x5f, 0x52, 0x45,
0x54, 0x52, 0x41, 0x4e, 0x53, 0x4d, 0x49, 0x53, 0x53, 0x49, 0x4f, 0x4e, 0x10, 0x07, 0x12, 0x14,
0x0a, 0x10, 0x44, 0x4f, 0x57, 0x4e, 0x4c, 0x49, 0x4e, 0x4b, 0x5f, 0x47, 0x41, 0x54, 0x45, 0x57,
0x41, 0x59, 0x10, 0x08, 0x12, 0x18, 0x0a, 0x14, 0x52, 0x45, 0x4c, 0x41, 0x59, 0x5f, 0x4e, 0x45,
0x57, 0x5f, 0x45, 0x4e, 0x44, 0x5f, 0x44, 0x45, 0x56, 0x49, 0x43, 0x45, 0x10, 0x09, 0x12, 0x0e,
0x0a, 0x0a, 0x46, 0x5f, 0x43, 0x4e, 0x54, 0x5f, 0x44, 0x4f, 0x57, 0x4e, 0x10, 0x0a, 0x42, 0x81,
0x01, 0x0a, 0x1d, 0x69, 0x6f, 0x2e, 0x63, 0x68, 0x69, 0x72, 0x70, 0x73, 0x74, 0x61, 0x63, 0x6b,
0x2e, 0x61, 0x70, 0x69, 0x2e, 0x69, 0x6e, 0x74, 0x65, 0x67, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e,
0x42, 0x10, 0x49, 0x6e, 0x74, 0x65, 0x67, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x50, 0x72, 0x6f,
0x74, 0x6f, 0x50, 0x01, 0x5a, 0x33, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d,
0x2f, 0x62, 0x72, 0x6f, 0x63, 0x61, 0x61, 0x72, 0x2f, 0x63, 0x68, 0x69, 0x72, 0x70, 0x73, 0x74,
0x61, 0x63, 0x6b, 0x2f, 0x61, 0x70, 0x69, 0x2f, 0x67, 0x6f, 0x2f, 0x76, 0x34, 0x2f, 0x69, 0x6e,
0x74, 0x65, 0x67, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0xaa, 0x02, 0x16, 0x43, 0x68, 0x69, 0x72,
0x70, 0x73, 0x74, 0x61, 0x63, 0x6b, 0x2e, 0x49, 0x6e, 0x74, 0x65, 0x67, 0x72, 0x61, 0x74, 0x69,
0x6f, 0x6e, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33,
}
var (
@ -1567,67 +1671,72 @@ func file_integration_integration_proto_rawDescGZIP() []byte {
}
var file_integration_integration_proto_enumTypes = make([]protoimpl.EnumInfo, 2)
var file_integration_integration_proto_msgTypes = make([]protoimpl.MessageInfo, 13)
var file_integration_integration_proto_msgTypes = make([]protoimpl.MessageInfo, 14)
var file_integration_integration_proto_goTypes = []interface{}{
(LogLevel)(0), // 0: integration.LogLevel
(LogCode)(0), // 1: integration.LogCode
(*DeviceInfo)(nil), // 2: integration.DeviceInfo
(*UplinkRelayRxInfo)(nil), // 3: integration.UplinkRelayRxInfo
(*UplinkEvent)(nil), // 4: integration.UplinkEvent
(*JoinEvent)(nil), // 5: integration.JoinEvent
(*AckEvent)(nil), // 6: integration.AckEvent
(*TxAckEvent)(nil), // 7: integration.TxAckEvent
(*LogEvent)(nil), // 8: integration.LogEvent
(*StatusEvent)(nil), // 9: integration.StatusEvent
(*LocationEvent)(nil), // 10: integration.LocationEvent
(*IntegrationEvent)(nil), // 11: integration.IntegrationEvent
(*DownlinkCommand)(nil), // 12: integration.DownlinkCommand
nil, // 13: integration.DeviceInfo.TagsEntry
nil, // 14: integration.LogEvent.ContextEntry
(common.DeviceClass)(0), // 15: common.DeviceClass
(*timestamppb.Timestamp)(nil), // 16: google.protobuf.Timestamp
(*structpb.Struct)(nil), // 17: google.protobuf.Struct
(*gw.UplinkRxInfo)(nil), // 18: gw.UplinkRxInfo
(*gw.UplinkTxInfo)(nil), // 19: gw.UplinkTxInfo
(*gw.DownlinkTxInfo)(nil), // 20: gw.DownlinkTxInfo
(*common.Location)(nil), // 21: common.Location
(*JoinServerContext)(nil), // 4: integration.JoinServerContext
(*UplinkEvent)(nil), // 5: integration.UplinkEvent
(*JoinEvent)(nil), // 6: integration.JoinEvent
(*AckEvent)(nil), // 7: integration.AckEvent
(*TxAckEvent)(nil), // 8: integration.TxAckEvent
(*LogEvent)(nil), // 9: integration.LogEvent
(*StatusEvent)(nil), // 10: integration.StatusEvent
(*LocationEvent)(nil), // 11: integration.LocationEvent
(*IntegrationEvent)(nil), // 12: integration.IntegrationEvent
(*DownlinkCommand)(nil), // 13: integration.DownlinkCommand
nil, // 14: integration.DeviceInfo.TagsEntry
nil, // 15: integration.LogEvent.ContextEntry
(common.DeviceClass)(0), // 16: common.DeviceClass
(*common.KeyEnvelope)(nil), // 17: common.KeyEnvelope
(*timestamppb.Timestamp)(nil), // 18: google.protobuf.Timestamp
(*structpb.Struct)(nil), // 19: google.protobuf.Struct
(*gw.UplinkRxInfo)(nil), // 20: gw.UplinkRxInfo
(*gw.UplinkTxInfo)(nil), // 21: gw.UplinkTxInfo
(*gw.DownlinkTxInfo)(nil), // 22: gw.DownlinkTxInfo
(*common.Location)(nil), // 23: common.Location
}
var file_integration_integration_proto_depIdxs = []int32{
15, // 0: integration.DeviceInfo.device_class_enabled:type_name -> common.DeviceClass
13, // 1: integration.DeviceInfo.tags:type_name -> integration.DeviceInfo.TagsEntry
16, // 2: integration.UplinkEvent.time:type_name -> google.protobuf.Timestamp
2, // 3: integration.UplinkEvent.device_info:type_name -> integration.DeviceInfo
17, // 4: integration.UplinkEvent.object:type_name -> google.protobuf.Struct
18, // 5: integration.UplinkEvent.rx_info:type_name -> gw.UplinkRxInfo
19, // 6: integration.UplinkEvent.tx_info:type_name -> gw.UplinkTxInfo
3, // 7: integration.UplinkEvent.relay_rx_info:type_name -> integration.UplinkRelayRxInfo
16, // 8: integration.JoinEvent.time:type_name -> google.protobuf.Timestamp
2, // 9: integration.JoinEvent.device_info:type_name -> integration.DeviceInfo
3, // 10: integration.JoinEvent.relay_rx_info:type_name -> integration.UplinkRelayRxInfo
16, // 11: integration.AckEvent.time:type_name -> google.protobuf.Timestamp
2, // 12: integration.AckEvent.device_info:type_name -> integration.DeviceInfo
16, // 13: integration.TxAckEvent.time:type_name -> google.protobuf.Timestamp
2, // 14: integration.TxAckEvent.device_info:type_name -> integration.DeviceInfo
20, // 15: integration.TxAckEvent.tx_info:type_name -> gw.DownlinkTxInfo
16, // 16: integration.LogEvent.time:type_name -> google.protobuf.Timestamp
2, // 17: integration.LogEvent.device_info:type_name -> integration.DeviceInfo
0, // 18: integration.LogEvent.level:type_name -> integration.LogLevel
1, // 19: integration.LogEvent.code:type_name -> integration.LogCode
14, // 20: integration.LogEvent.context:type_name -> integration.LogEvent.ContextEntry
16, // 21: integration.StatusEvent.time:type_name -> google.protobuf.Timestamp
2, // 22: integration.StatusEvent.device_info:type_name -> integration.DeviceInfo
16, // 23: integration.LocationEvent.time:type_name -> google.protobuf.Timestamp
2, // 24: integration.LocationEvent.device_info:type_name -> integration.DeviceInfo
21, // 25: integration.LocationEvent.location:type_name -> common.Location
16, // 26: integration.IntegrationEvent.time:type_name -> google.protobuf.Timestamp
2, // 27: integration.IntegrationEvent.device_info:type_name -> integration.DeviceInfo
17, // 28: integration.IntegrationEvent.object:type_name -> google.protobuf.Struct
17, // 29: integration.DownlinkCommand.object:type_name -> google.protobuf.Struct
30, // [30:30] is the sub-list for method output_type
30, // [30:30] is the sub-list for method input_type
30, // [30:30] is the sub-list for extension type_name
30, // [30:30] is the sub-list for extension extendee
0, // [0:30] is the sub-list for field type_name
16, // 0: integration.DeviceInfo.device_class_enabled:type_name -> common.DeviceClass
14, // 1: integration.DeviceInfo.tags:type_name -> integration.DeviceInfo.TagsEntry
17, // 2: integration.JoinServerContext.app_s_key:type_name -> common.KeyEnvelope
18, // 3: integration.UplinkEvent.time:type_name -> google.protobuf.Timestamp
2, // 4: integration.UplinkEvent.device_info:type_name -> integration.DeviceInfo
19, // 5: integration.UplinkEvent.object:type_name -> google.protobuf.Struct
20, // 6: integration.UplinkEvent.rx_info:type_name -> gw.UplinkRxInfo
21, // 7: integration.UplinkEvent.tx_info:type_name -> gw.UplinkTxInfo
3, // 8: integration.UplinkEvent.relay_rx_info:type_name -> integration.UplinkRelayRxInfo
4, // 9: integration.UplinkEvent.join_server_context:type_name -> integration.JoinServerContext
18, // 10: integration.JoinEvent.time:type_name -> google.protobuf.Timestamp
2, // 11: integration.JoinEvent.device_info:type_name -> integration.DeviceInfo
3, // 12: integration.JoinEvent.relay_rx_info:type_name -> integration.UplinkRelayRxInfo
4, // 13: integration.JoinEvent.join_server_context:type_name -> integration.JoinServerContext
18, // 14: integration.AckEvent.time:type_name -> google.protobuf.Timestamp
2, // 15: integration.AckEvent.device_info:type_name -> integration.DeviceInfo
18, // 16: integration.TxAckEvent.time:type_name -> google.protobuf.Timestamp
2, // 17: integration.TxAckEvent.device_info:type_name -> integration.DeviceInfo
22, // 18: integration.TxAckEvent.tx_info:type_name -> gw.DownlinkTxInfo
18, // 19: integration.LogEvent.time:type_name -> google.protobuf.Timestamp
2, // 20: integration.LogEvent.device_info:type_name -> integration.DeviceInfo
0, // 21: integration.LogEvent.level:type_name -> integration.LogLevel
1, // 22: integration.LogEvent.code:type_name -> integration.LogCode
15, // 23: integration.LogEvent.context:type_name -> integration.LogEvent.ContextEntry
18, // 24: integration.StatusEvent.time:type_name -> google.protobuf.Timestamp
2, // 25: integration.StatusEvent.device_info:type_name -> integration.DeviceInfo
18, // 26: integration.LocationEvent.time:type_name -> google.protobuf.Timestamp
2, // 27: integration.LocationEvent.device_info:type_name -> integration.DeviceInfo
23, // 28: integration.LocationEvent.location:type_name -> common.Location
18, // 29: integration.IntegrationEvent.time:type_name -> google.protobuf.Timestamp
2, // 30: integration.IntegrationEvent.device_info:type_name -> integration.DeviceInfo
19, // 31: integration.IntegrationEvent.object:type_name -> google.protobuf.Struct
19, // 32: integration.DownlinkCommand.object:type_name -> google.protobuf.Struct
33, // [33:33] is the sub-list for method output_type
33, // [33:33] is the sub-list for method input_type
33, // [33:33] is the sub-list for extension type_name
33, // [33:33] is the sub-list for extension extendee
0, // [0:33] is the sub-list for field type_name
}
func init() { file_integration_integration_proto_init() }
@ -1661,7 +1770,7 @@ func file_integration_integration_proto_init() {
}
}
file_integration_integration_proto_msgTypes[2].Exporter = func(v interface{}, i int) interface{} {
switch v := v.(*UplinkEvent); i {
switch v := v.(*JoinServerContext); i {
case 0:
return &v.state
case 1:
@ -1673,7 +1782,7 @@ func file_integration_integration_proto_init() {
}
}
file_integration_integration_proto_msgTypes[3].Exporter = func(v interface{}, i int) interface{} {
switch v := v.(*JoinEvent); i {
switch v := v.(*UplinkEvent); i {
case 0:
return &v.state
case 1:
@ -1685,7 +1794,7 @@ func file_integration_integration_proto_init() {
}
}
file_integration_integration_proto_msgTypes[4].Exporter = func(v interface{}, i int) interface{} {
switch v := v.(*AckEvent); i {
switch v := v.(*JoinEvent); i {
case 0:
return &v.state
case 1:
@ -1697,7 +1806,7 @@ func file_integration_integration_proto_init() {
}
}
file_integration_integration_proto_msgTypes[5].Exporter = func(v interface{}, i int) interface{} {
switch v := v.(*TxAckEvent); i {
switch v := v.(*AckEvent); i {
case 0:
return &v.state
case 1:
@ -1709,7 +1818,7 @@ func file_integration_integration_proto_init() {
}
}
file_integration_integration_proto_msgTypes[6].Exporter = func(v interface{}, i int) interface{} {
switch v := v.(*LogEvent); i {
switch v := v.(*TxAckEvent); i {
case 0:
return &v.state
case 1:
@ -1721,7 +1830,7 @@ func file_integration_integration_proto_init() {
}
}
file_integration_integration_proto_msgTypes[7].Exporter = func(v interface{}, i int) interface{} {
switch v := v.(*StatusEvent); i {
switch v := v.(*LogEvent); i {
case 0:
return &v.state
case 1:
@ -1733,7 +1842,7 @@ func file_integration_integration_proto_init() {
}
}
file_integration_integration_proto_msgTypes[8].Exporter = func(v interface{}, i int) interface{} {
switch v := v.(*LocationEvent); i {
switch v := v.(*StatusEvent); i {
case 0:
return &v.state
case 1:
@ -1745,7 +1854,7 @@ func file_integration_integration_proto_init() {
}
}
file_integration_integration_proto_msgTypes[9].Exporter = func(v interface{}, i int) interface{} {
switch v := v.(*IntegrationEvent); i {
switch v := v.(*LocationEvent); i {
case 0:
return &v.state
case 1:
@ -1757,6 +1866,18 @@ func file_integration_integration_proto_init() {
}
}
file_integration_integration_proto_msgTypes[10].Exporter = func(v interface{}, i int) interface{} {
switch v := v.(*IntegrationEvent); i {
case 0:
return &v.state
case 1:
return &v.sizeCache
case 2:
return &v.unknownFields
default:
return nil
}
}
file_integration_integration_proto_msgTypes[11].Exporter = func(v interface{}, i int) interface{} {
switch v := v.(*DownlinkCommand); i {
case 0:
return &v.state
@ -1775,7 +1896,7 @@ func file_integration_integration_proto_init() {
GoPackagePath: reflect.TypeOf(x{}).PkgPath(),
RawDescriptor: file_integration_integration_proto_rawDesc,
NumEnums: 2,
NumMessages: 13,
NumMessages: 14,
NumExtensions: 0,
NumServices: 0,
},

View File

@ -142,6 +142,13 @@ export class DeviceServiceClient {
response: api_device_pb.GetDeviceQueueItemsResponse) => void
): grpcWeb.ClientReadableStream<api_device_pb.GetDeviceQueueItemsResponse>;
getNextFCntDown(
request: api_device_pb.GetDeviceNextFCntDownRequest,
metadata: grpcWeb.Metadata | undefined,
callback: (err: grpcWeb.RpcError,
response: api_device_pb.GetDeviceNextFCntDownResponse) => void
): grpcWeb.ClientReadableStream<api_device_pb.GetDeviceNextFCntDownResponse>;
}
export class DeviceServicePromiseClient {
@ -244,5 +251,10 @@ export class DeviceServicePromiseClient {
metadata?: grpcWeb.Metadata
): Promise<api_device_pb.GetDeviceQueueItemsResponse>;
getNextFCntDown(
request: api_device_pb.GetDeviceNextFCntDownRequest,
metadata?: grpcWeb.Metadata
): Promise<api_device_pb.GetDeviceNextFCntDownResponse>;
}

View File

@ -1243,5 +1243,66 @@ proto.api.DeviceServicePromiseClient.prototype.getQueue =
};
/**
* @const
* @type {!grpc.web.MethodDescriptor<
* !proto.api.GetDeviceNextFCntDownRequest,
* !proto.api.GetDeviceNextFCntDownResponse>}
*/
const methodDescriptor_DeviceService_GetNextFCntDown = new grpc.web.MethodDescriptor(
'/api.DeviceService/GetNextFCntDown',
grpc.web.MethodType.UNARY,
proto.api.GetDeviceNextFCntDownRequest,
proto.api.GetDeviceNextFCntDownResponse,
/**
* @param {!proto.api.GetDeviceNextFCntDownRequest} request
* @return {!Uint8Array}
*/
function(request) {
return request.serializeBinary();
},
proto.api.GetDeviceNextFCntDownResponse.deserializeBinary
);
/**
* @param {!proto.api.GetDeviceNextFCntDownRequest} request The
* request proto
* @param {?Object<string, string>} metadata User defined
* call metadata
* @param {function(?grpc.web.RpcError, ?proto.api.GetDeviceNextFCntDownResponse)}
* callback The callback function(error, response)
* @return {!grpc.web.ClientReadableStream<!proto.api.GetDeviceNextFCntDownResponse>|undefined}
* The XHR Node Readable Stream
*/
proto.api.DeviceServiceClient.prototype.getNextFCntDown =
function(request, metadata, callback) {
return this.client_.rpcCall(this.hostname_ +
'/api.DeviceService/GetNextFCntDown',
request,
metadata || {},
methodDescriptor_DeviceService_GetNextFCntDown,
callback);
};
/**
* @param {!proto.api.GetDeviceNextFCntDownRequest} request The
* request proto
* @param {?Object<string, string>=} metadata User defined
* call metadata
* @return {!Promise<!proto.api.GetDeviceNextFCntDownResponse>}
* Promise that resolves to the response
*/
proto.api.DeviceServicePromiseClient.prototype.getNextFCntDown =
function(request, metadata) {
return this.client_.unaryCall(this.hostname_ +
'/api.DeviceService/GetNextFCntDown',
request,
metadata || {},
methodDescriptor_DeviceService_GetNextFCntDown);
};
module.exports = proto.api;

View File

@ -814,6 +814,9 @@ export class DeviceQueueItem extends jspb.Message {
getFCntDown(): number;
setFCntDown(value: number): DeviceQueueItem;
getIsEncrypted(): boolean;
setIsEncrypted(value: boolean): DeviceQueueItem;
serializeBinary(): Uint8Array;
toObject(includeInstance?: boolean): DeviceQueueItem.AsObject;
static toObject(includeInstance: boolean, msg: DeviceQueueItem): DeviceQueueItem.AsObject;
@ -832,6 +835,7 @@ export namespace DeviceQueueItem {
object?: google_protobuf_struct_pb.Struct.AsObject,
isPending: boolean,
fCntDown: number,
isEncrypted: boolean,
}
}
@ -955,3 +959,39 @@ export namespace FlushDevNoncesRequest {
}
}
export class GetDeviceNextFCntDownRequest extends jspb.Message {
getDevEui(): string;
setDevEui(value: string): GetDeviceNextFCntDownRequest;
serializeBinary(): Uint8Array;
toObject(includeInstance?: boolean): GetDeviceNextFCntDownRequest.AsObject;
static toObject(includeInstance: boolean, msg: GetDeviceNextFCntDownRequest): GetDeviceNextFCntDownRequest.AsObject;
static serializeBinaryToWriter(message: GetDeviceNextFCntDownRequest, writer: jspb.BinaryWriter): void;
static deserializeBinary(bytes: Uint8Array): GetDeviceNextFCntDownRequest;
static deserializeBinaryFromReader(message: GetDeviceNextFCntDownRequest, reader: jspb.BinaryReader): GetDeviceNextFCntDownRequest;
}
export namespace GetDeviceNextFCntDownRequest {
export type AsObject = {
devEui: string,
}
}
export class GetDeviceNextFCntDownResponse extends jspb.Message {
getFCntDown(): number;
setFCntDown(value: number): GetDeviceNextFCntDownResponse;
serializeBinary(): Uint8Array;
toObject(includeInstance?: boolean): GetDeviceNextFCntDownResponse.AsObject;
static toObject(includeInstance: boolean, msg: GetDeviceNextFCntDownResponse): GetDeviceNextFCntDownResponse.AsObject;
static serializeBinaryToWriter(message: GetDeviceNextFCntDownResponse, writer: jspb.BinaryWriter): void;
static deserializeBinary(bytes: Uint8Array): GetDeviceNextFCntDownResponse;
static deserializeBinaryFromReader(message: GetDeviceNextFCntDownResponse, reader: jspb.BinaryReader): GetDeviceNextFCntDownResponse;
}
export namespace GetDeviceNextFCntDownResponse {
export type AsObject = {
fCntDown: number,
}
}

View File

@ -47,6 +47,8 @@ goog.exportSymbol('proto.api.GetDeviceLinkMetricsRequest', null, global);
goog.exportSymbol('proto.api.GetDeviceLinkMetricsResponse', null, global);
goog.exportSymbol('proto.api.GetDeviceMetricsRequest', null, global);
goog.exportSymbol('proto.api.GetDeviceMetricsResponse', null, global);
goog.exportSymbol('proto.api.GetDeviceNextFCntDownRequest', null, global);
goog.exportSymbol('proto.api.GetDeviceNextFCntDownResponse', null, global);
goog.exportSymbol('proto.api.GetDeviceQueueItemsRequest', null, global);
goog.exportSymbol('proto.api.GetDeviceQueueItemsResponse', null, global);
goog.exportSymbol('proto.api.GetDeviceRequest', null, global);
@ -792,6 +794,48 @@ if (goog.DEBUG && !COMPILED) {
*/
proto.api.FlushDevNoncesRequest.displayName = 'proto.api.FlushDevNoncesRequest';
}
/**
* Generated by JsPbCodeGenerator.
* @param {Array=} opt_data Optional initial data array, typically from a
* server response, or constructed directly in Javascript. The array is used
* in place and becomes part of the constructed object. It is not cloned.
* If no data is provided, the constructed object will be empty, but still
* valid.
* @extends {jspb.Message}
* @constructor
*/
proto.api.GetDeviceNextFCntDownRequest = function(opt_data) {
jspb.Message.initialize(this, opt_data, 0, -1, null, null);
};
goog.inherits(proto.api.GetDeviceNextFCntDownRequest, jspb.Message);
if (goog.DEBUG && !COMPILED) {
/**
* @public
* @override
*/
proto.api.GetDeviceNextFCntDownRequest.displayName = 'proto.api.GetDeviceNextFCntDownRequest';
}
/**
* Generated by JsPbCodeGenerator.
* @param {Array=} opt_data Optional initial data array, typically from a
* server response, or constructed directly in Javascript. The array is used
* in place and becomes part of the constructed object. It is not cloned.
* If no data is provided, the constructed object will be empty, but still
* valid.
* @extends {jspb.Message}
* @constructor
*/
proto.api.GetDeviceNextFCntDownResponse = function(opt_data) {
jspb.Message.initialize(this, opt_data, 0, -1, null, null);
};
goog.inherits(proto.api.GetDeviceNextFCntDownResponse, jspb.Message);
if (goog.DEBUG && !COMPILED) {
/**
* @public
* @override
*/
proto.api.GetDeviceNextFCntDownResponse.displayName = 'proto.api.GetDeviceNextFCntDownResponse';
}
@ -6721,7 +6765,8 @@ proto.api.DeviceQueueItem.toObject = function(includeInstance, msg) {
data: msg.getData_asB64(),
object: (f = msg.getObject()) && google_protobuf_struct_pb.Struct.toObject(includeInstance, f),
isPending: jspb.Message.getBooleanFieldWithDefault(msg, 7, false),
fCntDown: jspb.Message.getFieldWithDefault(msg, 8, 0)
fCntDown: jspb.Message.getFieldWithDefault(msg, 8, 0),
isEncrypted: jspb.Message.getBooleanFieldWithDefault(msg, 9, false)
};
if (includeInstance) {
@ -6791,6 +6836,10 @@ proto.api.DeviceQueueItem.deserializeBinaryFromReader = function(msg, reader) {
var value = /** @type {number} */ (reader.readUint32());
msg.setFCntDown(value);
break;
case 9:
var value = /** @type {boolean} */ (reader.readBool());
msg.setIsEncrypted(value);
break;
default:
reader.skipField();
break;
@ -6877,6 +6926,13 @@ proto.api.DeviceQueueItem.serializeBinaryToWriter = function(message, writer) {
f
);
}
f = message.getIsEncrypted();
if (f) {
writer.writeBool(
9,
f
);
}
};
@ -7067,6 +7123,24 @@ proto.api.DeviceQueueItem.prototype.setFCntDown = function(value) {
};
/**
* optional bool is_encrypted = 9;
* @return {boolean}
*/
proto.api.DeviceQueueItem.prototype.getIsEncrypted = function() {
return /** @type {boolean} */ (jspb.Message.getBooleanFieldWithDefault(this, 9, false));
};
/**
* @param {boolean} value
* @return {!proto.api.DeviceQueueItem} returns this
*/
proto.api.DeviceQueueItem.prototype.setIsEncrypted = function(value) {
return jspb.Message.setProto3BooleanField(this, 9, value);
};
@ -7958,4 +8032,264 @@ proto.api.FlushDevNoncesRequest.prototype.setDevEui = function(value) {
};
if (jspb.Message.GENERATE_TO_OBJECT) {
/**
* Creates an object representation of this proto.
* Field names that are reserved in JavaScript and will be renamed to pb_name.
* Optional fields that are not set will be set to undefined.
* To access a reserved field use, foo.pb_<name>, eg, foo.pb_default.
* For the list of reserved names please see:
* net/proto2/compiler/js/internal/generator.cc#kKeyword.
* @param {boolean=} opt_includeInstance Deprecated. whether to include the
* JSPB instance for transitional soy proto support:
* http://goto/soy-param-migration
* @return {!Object}
*/
proto.api.GetDeviceNextFCntDownRequest.prototype.toObject = function(opt_includeInstance) {
return proto.api.GetDeviceNextFCntDownRequest.toObject(opt_includeInstance, this);
};
/**
* Static version of the {@see toObject} method.
* @param {boolean|undefined} includeInstance Deprecated. Whether to include
* the JSPB instance for transitional soy proto support:
* http://goto/soy-param-migration
* @param {!proto.api.GetDeviceNextFCntDownRequest} msg The msg instance to transform.
* @return {!Object}
* @suppress {unusedLocalVariables} f is only used for nested messages
*/
proto.api.GetDeviceNextFCntDownRequest.toObject = function(includeInstance, msg) {
var f, obj = {
devEui: jspb.Message.getFieldWithDefault(msg, 1, "")
};
if (includeInstance) {
obj.$jspbMessageInstance = msg;
}
return obj;
};
}
/**
* Deserializes binary data (in protobuf wire format).
* @param {jspb.ByteSource} bytes The bytes to deserialize.
* @return {!proto.api.GetDeviceNextFCntDownRequest}
*/
proto.api.GetDeviceNextFCntDownRequest.deserializeBinary = function(bytes) {
var reader = new jspb.BinaryReader(bytes);
var msg = new proto.api.GetDeviceNextFCntDownRequest;
return proto.api.GetDeviceNextFCntDownRequest.deserializeBinaryFromReader(msg, reader);
};
/**
* Deserializes binary data (in protobuf wire format) from the
* given reader into the given message object.
* @param {!proto.api.GetDeviceNextFCntDownRequest} msg The message object to deserialize into.
* @param {!jspb.BinaryReader} reader The BinaryReader to use.
* @return {!proto.api.GetDeviceNextFCntDownRequest}
*/
proto.api.GetDeviceNextFCntDownRequest.deserializeBinaryFromReader = function(msg, reader) {
while (reader.nextField()) {
if (reader.isEndGroup()) {
break;
}
var field = reader.getFieldNumber();
switch (field) {
case 1:
var value = /** @type {string} */ (reader.readString());
msg.setDevEui(value);
break;
default:
reader.skipField();
break;
}
}
return msg;
};
/**
* Serializes the message to binary data (in protobuf wire format).
* @return {!Uint8Array}
*/
proto.api.GetDeviceNextFCntDownRequest.prototype.serializeBinary = function() {
var writer = new jspb.BinaryWriter();
proto.api.GetDeviceNextFCntDownRequest.serializeBinaryToWriter(this, writer);
return writer.getResultBuffer();
};
/**
* Serializes the given message to binary data (in protobuf wire
* format), writing to the given BinaryWriter.
* @param {!proto.api.GetDeviceNextFCntDownRequest} message
* @param {!jspb.BinaryWriter} writer
* @suppress {unusedLocalVariables} f is only used for nested messages
*/
proto.api.GetDeviceNextFCntDownRequest.serializeBinaryToWriter = function(message, writer) {
var f = undefined;
f = message.getDevEui();
if (f.length > 0) {
writer.writeString(
1,
f
);
}
};
/**
* optional string dev_eui = 1;
* @return {string}
*/
proto.api.GetDeviceNextFCntDownRequest.prototype.getDevEui = function() {
return /** @type {string} */ (jspb.Message.getFieldWithDefault(this, 1, ""));
};
/**
* @param {string} value
* @return {!proto.api.GetDeviceNextFCntDownRequest} returns this
*/
proto.api.GetDeviceNextFCntDownRequest.prototype.setDevEui = function(value) {
return jspb.Message.setProto3StringField(this, 1, value);
};
if (jspb.Message.GENERATE_TO_OBJECT) {
/**
* Creates an object representation of this proto.
* Field names that are reserved in JavaScript and will be renamed to pb_name.
* Optional fields that are not set will be set to undefined.
* To access a reserved field use, foo.pb_<name>, eg, foo.pb_default.
* For the list of reserved names please see:
* net/proto2/compiler/js/internal/generator.cc#kKeyword.
* @param {boolean=} opt_includeInstance Deprecated. whether to include the
* JSPB instance for transitional soy proto support:
* http://goto/soy-param-migration
* @return {!Object}
*/
proto.api.GetDeviceNextFCntDownResponse.prototype.toObject = function(opt_includeInstance) {
return proto.api.GetDeviceNextFCntDownResponse.toObject(opt_includeInstance, this);
};
/**
* Static version of the {@see toObject} method.
* @param {boolean|undefined} includeInstance Deprecated. Whether to include
* the JSPB instance for transitional soy proto support:
* http://goto/soy-param-migration
* @param {!proto.api.GetDeviceNextFCntDownResponse} msg The msg instance to transform.
* @return {!Object}
* @suppress {unusedLocalVariables} f is only used for nested messages
*/
proto.api.GetDeviceNextFCntDownResponse.toObject = function(includeInstance, msg) {
var f, obj = {
fCntDown: jspb.Message.getFieldWithDefault(msg, 1, 0)
};
if (includeInstance) {
obj.$jspbMessageInstance = msg;
}
return obj;
};
}
/**
* Deserializes binary data (in protobuf wire format).
* @param {jspb.ByteSource} bytes The bytes to deserialize.
* @return {!proto.api.GetDeviceNextFCntDownResponse}
*/
proto.api.GetDeviceNextFCntDownResponse.deserializeBinary = function(bytes) {
var reader = new jspb.BinaryReader(bytes);
var msg = new proto.api.GetDeviceNextFCntDownResponse;
return proto.api.GetDeviceNextFCntDownResponse.deserializeBinaryFromReader(msg, reader);
};
/**
* Deserializes binary data (in protobuf wire format) from the
* given reader into the given message object.
* @param {!proto.api.GetDeviceNextFCntDownResponse} msg The message object to deserialize into.
* @param {!jspb.BinaryReader} reader The BinaryReader to use.
* @return {!proto.api.GetDeviceNextFCntDownResponse}
*/
proto.api.GetDeviceNextFCntDownResponse.deserializeBinaryFromReader = function(msg, reader) {
while (reader.nextField()) {
if (reader.isEndGroup()) {
break;
}
var field = reader.getFieldNumber();
switch (field) {
case 1:
var value = /** @type {number} */ (reader.readUint32());
msg.setFCntDown(value);
break;
default:
reader.skipField();
break;
}
}
return msg;
};
/**
* Serializes the message to binary data (in protobuf wire format).
* @return {!Uint8Array}
*/
proto.api.GetDeviceNextFCntDownResponse.prototype.serializeBinary = function() {
var writer = new jspb.BinaryWriter();
proto.api.GetDeviceNextFCntDownResponse.serializeBinaryToWriter(this, writer);
return writer.getResultBuffer();
};
/**
* Serializes the given message to binary data (in protobuf wire
* format), writing to the given BinaryWriter.
* @param {!proto.api.GetDeviceNextFCntDownResponse} message
* @param {!jspb.BinaryWriter} writer
* @suppress {unusedLocalVariables} f is only used for nested messages
*/
proto.api.GetDeviceNextFCntDownResponse.serializeBinaryToWriter = function(message, writer) {
var f = undefined;
f = message.getFCntDown();
if (f !== 0) {
writer.writeUint32(
1,
f
);
}
};
/**
* optional uint32 f_cnt_down = 1;
* @return {number}
*/
proto.api.GetDeviceNextFCntDownResponse.prototype.getFCntDown = function() {
return /** @type {number} */ (jspb.Message.getFieldWithDefault(this, 1, 0));
};
/**
* @param {number} value
* @return {!proto.api.GetDeviceNextFCntDownResponse} returns this
*/
proto.api.GetDeviceNextFCntDownResponse.prototype.setFCntDown = function(value) {
return jspb.Message.setProto3IntField(this, 1, value);
};
goog.object.extend(exports, proto.api);

View File

@ -27,6 +27,7 @@ interface IDeviceServiceService extends grpc.ServiceDefinition<grpc.UntypedServi
enqueue: grpc.MethodDefinition<api_device_pb.EnqueueDeviceQueueItemRequest, api_device_pb.EnqueueDeviceQueueItemResponse>;
flushQueue: grpc.MethodDefinition<api_device_pb.FlushDeviceQueueRequest, google_protobuf_empty_pb.Empty>;
getQueue: grpc.MethodDefinition<api_device_pb.GetDeviceQueueItemsRequest, api_device_pb.GetDeviceQueueItemsResponse>;
getNextFCntDown: grpc.MethodDefinition<api_device_pb.GetDeviceNextFCntDownRequest, api_device_pb.GetDeviceNextFCntDownResponse>;
}
export const DeviceServiceService: IDeviceServiceService;
@ -51,6 +52,7 @@ export interface IDeviceServiceServer extends grpc.UntypedServiceImplementation
enqueue: grpc.handleUnaryCall<api_device_pb.EnqueueDeviceQueueItemRequest, api_device_pb.EnqueueDeviceQueueItemResponse>;
flushQueue: grpc.handleUnaryCall<api_device_pb.FlushDeviceQueueRequest, google_protobuf_empty_pb.Empty>;
getQueue: grpc.handleUnaryCall<api_device_pb.GetDeviceQueueItemsRequest, api_device_pb.GetDeviceQueueItemsResponse>;
getNextFCntDown: grpc.handleUnaryCall<api_device_pb.GetDeviceNextFCntDownRequest, api_device_pb.GetDeviceNextFCntDownResponse>;
}
export class DeviceServiceClient extends grpc.Client {
@ -112,4 +114,7 @@ export class DeviceServiceClient extends grpc.Client {
getQueue(argument: api_device_pb.GetDeviceQueueItemsRequest, callback: grpc.requestCallback<api_device_pb.GetDeviceQueueItemsResponse>): grpc.ClientUnaryCall;
getQueue(argument: api_device_pb.GetDeviceQueueItemsRequest, metadataOrOptions: grpc.Metadata | grpc.CallOptions | null, callback: grpc.requestCallback<api_device_pb.GetDeviceQueueItemsResponse>): grpc.ClientUnaryCall;
getQueue(argument: api_device_pb.GetDeviceQueueItemsRequest, metadata: grpc.Metadata | null, options: grpc.CallOptions | null, callback: grpc.requestCallback<api_device_pb.GetDeviceQueueItemsResponse>): grpc.ClientUnaryCall;
getNextFCntDown(argument: api_device_pb.GetDeviceNextFCntDownRequest, callback: grpc.requestCallback<api_device_pb.GetDeviceNextFCntDownResponse>): grpc.ClientUnaryCall;
getNextFCntDown(argument: api_device_pb.GetDeviceNextFCntDownRequest, metadataOrOptions: grpc.Metadata | grpc.CallOptions | null, callback: grpc.requestCallback<api_device_pb.GetDeviceNextFCntDownResponse>): grpc.ClientUnaryCall;
getNextFCntDown(argument: api_device_pb.GetDeviceNextFCntDownRequest, metadata: grpc.Metadata | null, options: grpc.CallOptions | null, callback: grpc.requestCallback<api_device_pb.GetDeviceNextFCntDownResponse>): grpc.ClientUnaryCall;
}

View File

@ -207,6 +207,28 @@ function deserialize_api_GetDeviceMetricsResponse(buffer_arg) {
return api_device_pb.GetDeviceMetricsResponse.deserializeBinary(new Uint8Array(buffer_arg));
}
function serialize_api_GetDeviceNextFCntDownRequest(arg) {
if (!(arg instanceof api_device_pb.GetDeviceNextFCntDownRequest)) {
throw new Error('Expected argument of type api.GetDeviceNextFCntDownRequest');
}
return Buffer.from(arg.serializeBinary());
}
function deserialize_api_GetDeviceNextFCntDownRequest(buffer_arg) {
return api_device_pb.GetDeviceNextFCntDownRequest.deserializeBinary(new Uint8Array(buffer_arg));
}
function serialize_api_GetDeviceNextFCntDownResponse(arg) {
if (!(arg instanceof api_device_pb.GetDeviceNextFCntDownResponse)) {
throw new Error('Expected argument of type api.GetDeviceNextFCntDownResponse');
}
return Buffer.from(arg.serializeBinary());
}
function deserialize_api_GetDeviceNextFCntDownResponse(buffer_arg) {
return api_device_pb.GetDeviceNextFCntDownResponse.deserializeBinary(new Uint8Array(buffer_arg));
}
function serialize_api_GetDeviceQueueItemsRequest(arg) {
if (!(arg instanceof api_device_pb.GetDeviceQueueItemsRequest)) {
throw new Error('Expected argument of type api.GetDeviceQueueItemsRequest');
@ -565,6 +587,20 @@ getQueue: {
responseSerialize: serialize_api_GetDeviceQueueItemsResponse,
responseDeserialize: deserialize_api_GetDeviceQueueItemsResponse,
},
// GetNextFCntDown returns the next FCntDown to use for enqueing encrypted
// downlinks. The difference with the DeviceActivation f_cont_down is that
// this method takes potential existing queue-items into account.
getNextFCntDown: {
path: '/api.DeviceService/GetNextFCntDown',
requestStream: false,
responseStream: false,
requestType: api_device_pb.GetDeviceNextFCntDownRequest,
responseType: api_device_pb.GetDeviceNextFCntDownResponse,
requestSerialize: serialize_api_GetDeviceNextFCntDownRequest,
requestDeserialize: deserialize_api_GetDeviceNextFCntDownRequest,
responseSerialize: serialize_api_GetDeviceNextFCntDownResponse,
responseDeserialize: deserialize_api_GetDeviceNextFCntDownResponse,
},
};
exports.DeviceServiceClient = grpc.makeGenericClientConstructor(DeviceServiceService);

View File

@ -867,6 +867,9 @@ export class DeviceQueueItem extends jspb.Message {
getFCntDown(): number;
setFCntDown(value: number): void;
getIsEncrypted(): boolean;
setIsEncrypted(value: boolean): void;
serializeBinary(): Uint8Array;
toObject(includeInstance?: boolean): DeviceQueueItem.AsObject;
static toObject(includeInstance: boolean, msg: DeviceQueueItem): DeviceQueueItem.AsObject;
@ -887,6 +890,7 @@ export namespace DeviceQueueItem {
object?: google_protobuf_struct_pb.Struct.AsObject,
isPending: boolean,
fCntDown: number,
isEncrypted: boolean,
}
}
@ -1022,3 +1026,43 @@ export namespace FlushDevNoncesRequest {
}
}
export class GetDeviceNextFCntDownRequest extends jspb.Message {
getDevEui(): string;
setDevEui(value: string): void;
serializeBinary(): Uint8Array;
toObject(includeInstance?: boolean): GetDeviceNextFCntDownRequest.AsObject;
static toObject(includeInstance: boolean, msg: GetDeviceNextFCntDownRequest): GetDeviceNextFCntDownRequest.AsObject;
static extensions: {[key: number]: jspb.ExtensionFieldInfo<jspb.Message>};
static extensionsBinary: {[key: number]: jspb.ExtensionFieldBinaryInfo<jspb.Message>};
static serializeBinaryToWriter(message: GetDeviceNextFCntDownRequest, writer: jspb.BinaryWriter): void;
static deserializeBinary(bytes: Uint8Array): GetDeviceNextFCntDownRequest;
static deserializeBinaryFromReader(message: GetDeviceNextFCntDownRequest, reader: jspb.BinaryReader): GetDeviceNextFCntDownRequest;
}
export namespace GetDeviceNextFCntDownRequest {
export type AsObject = {
devEui: string,
}
}
export class GetDeviceNextFCntDownResponse extends jspb.Message {
getFCntDown(): number;
setFCntDown(value: number): void;
serializeBinary(): Uint8Array;
toObject(includeInstance?: boolean): GetDeviceNextFCntDownResponse.AsObject;
static toObject(includeInstance: boolean, msg: GetDeviceNextFCntDownResponse): GetDeviceNextFCntDownResponse.AsObject;
static extensions: {[key: number]: jspb.ExtensionFieldInfo<jspb.Message>};
static extensionsBinary: {[key: number]: jspb.ExtensionFieldBinaryInfo<jspb.Message>};
static serializeBinaryToWriter(message: GetDeviceNextFCntDownResponse, writer: jspb.BinaryWriter): void;
static deserializeBinary(bytes: Uint8Array): GetDeviceNextFCntDownResponse;
static deserializeBinaryFromReader(message: GetDeviceNextFCntDownResponse, reader: jspb.BinaryReader): GetDeviceNextFCntDownResponse;
}
export namespace GetDeviceNextFCntDownResponse {
export type AsObject = {
fCntDown: number,
}
}

View File

@ -47,6 +47,8 @@ goog.exportSymbol('proto.api.GetDeviceLinkMetricsRequest', null, global);
goog.exportSymbol('proto.api.GetDeviceLinkMetricsResponse', null, global);
goog.exportSymbol('proto.api.GetDeviceMetricsRequest', null, global);
goog.exportSymbol('proto.api.GetDeviceMetricsResponse', null, global);
goog.exportSymbol('proto.api.GetDeviceNextFCntDownRequest', null, global);
goog.exportSymbol('proto.api.GetDeviceNextFCntDownResponse', null, global);
goog.exportSymbol('proto.api.GetDeviceQueueItemsRequest', null, global);
goog.exportSymbol('proto.api.GetDeviceQueueItemsResponse', null, global);
goog.exportSymbol('proto.api.GetDeviceRequest', null, global);
@ -792,6 +794,48 @@ if (goog.DEBUG && !COMPILED) {
*/
proto.api.FlushDevNoncesRequest.displayName = 'proto.api.FlushDevNoncesRequest';
}
/**
* Generated by JsPbCodeGenerator.
* @param {Array=} opt_data Optional initial data array, typically from a
* server response, or constructed directly in Javascript. The array is used
* in place and becomes part of the constructed object. It is not cloned.
* If no data is provided, the constructed object will be empty, but still
* valid.
* @extends {jspb.Message}
* @constructor
*/
proto.api.GetDeviceNextFCntDownRequest = function(opt_data) {
jspb.Message.initialize(this, opt_data, 0, -1, null, null);
};
goog.inherits(proto.api.GetDeviceNextFCntDownRequest, jspb.Message);
if (goog.DEBUG && !COMPILED) {
/**
* @public
* @override
*/
proto.api.GetDeviceNextFCntDownRequest.displayName = 'proto.api.GetDeviceNextFCntDownRequest';
}
/**
* Generated by JsPbCodeGenerator.
* @param {Array=} opt_data Optional initial data array, typically from a
* server response, or constructed directly in Javascript. The array is used
* in place and becomes part of the constructed object. It is not cloned.
* If no data is provided, the constructed object will be empty, but still
* valid.
* @extends {jspb.Message}
* @constructor
*/
proto.api.GetDeviceNextFCntDownResponse = function(opt_data) {
jspb.Message.initialize(this, opt_data, 0, -1, null, null);
};
goog.inherits(proto.api.GetDeviceNextFCntDownResponse, jspb.Message);
if (goog.DEBUG && !COMPILED) {
/**
* @public
* @override
*/
proto.api.GetDeviceNextFCntDownResponse.displayName = 'proto.api.GetDeviceNextFCntDownResponse';
}
@ -6721,7 +6765,8 @@ proto.api.DeviceQueueItem.toObject = function(includeInstance, msg) {
data: msg.getData_asB64(),
object: (f = msg.getObject()) && google_protobuf_struct_pb.Struct.toObject(includeInstance, f),
isPending: jspb.Message.getBooleanFieldWithDefault(msg, 7, false),
fCntDown: jspb.Message.getFieldWithDefault(msg, 8, 0)
fCntDown: jspb.Message.getFieldWithDefault(msg, 8, 0),
isEncrypted: jspb.Message.getBooleanFieldWithDefault(msg, 9, false)
};
if (includeInstance) {
@ -6791,6 +6836,10 @@ proto.api.DeviceQueueItem.deserializeBinaryFromReader = function(msg, reader) {
var value = /** @type {number} */ (reader.readUint32());
msg.setFCntDown(value);
break;
case 9:
var value = /** @type {boolean} */ (reader.readBool());
msg.setIsEncrypted(value);
break;
default:
reader.skipField();
break;
@ -6877,6 +6926,13 @@ proto.api.DeviceQueueItem.serializeBinaryToWriter = function(message, writer) {
f
);
}
f = message.getIsEncrypted();
if (f) {
writer.writeBool(
9,
f
);
}
};
@ -7067,6 +7123,24 @@ proto.api.DeviceQueueItem.prototype.setFCntDown = function(value) {
};
/**
* optional bool is_encrypted = 9;
* @return {boolean}
*/
proto.api.DeviceQueueItem.prototype.getIsEncrypted = function() {
return /** @type {boolean} */ (jspb.Message.getBooleanFieldWithDefault(this, 9, false));
};
/**
* @param {boolean} value
* @return {!proto.api.DeviceQueueItem} returns this
*/
proto.api.DeviceQueueItem.prototype.setIsEncrypted = function(value) {
return jspb.Message.setProto3BooleanField(this, 9, value);
};
@ -7958,4 +8032,264 @@ proto.api.FlushDevNoncesRequest.prototype.setDevEui = function(value) {
};
if (jspb.Message.GENERATE_TO_OBJECT) {
/**
* Creates an object representation of this proto.
* Field names that are reserved in JavaScript and will be renamed to pb_name.
* Optional fields that are not set will be set to undefined.
* To access a reserved field use, foo.pb_<name>, eg, foo.pb_default.
* For the list of reserved names please see:
* net/proto2/compiler/js/internal/generator.cc#kKeyword.
* @param {boolean=} opt_includeInstance Deprecated. whether to include the
* JSPB instance for transitional soy proto support:
* http://goto/soy-param-migration
* @return {!Object}
*/
proto.api.GetDeviceNextFCntDownRequest.prototype.toObject = function(opt_includeInstance) {
return proto.api.GetDeviceNextFCntDownRequest.toObject(opt_includeInstance, this);
};
/**
* Static version of the {@see toObject} method.
* @param {boolean|undefined} includeInstance Deprecated. Whether to include
* the JSPB instance for transitional soy proto support:
* http://goto/soy-param-migration
* @param {!proto.api.GetDeviceNextFCntDownRequest} msg The msg instance to transform.
* @return {!Object}
* @suppress {unusedLocalVariables} f is only used for nested messages
*/
proto.api.GetDeviceNextFCntDownRequest.toObject = function(includeInstance, msg) {
var f, obj = {
devEui: jspb.Message.getFieldWithDefault(msg, 1, "")
};
if (includeInstance) {
obj.$jspbMessageInstance = msg;
}
return obj;
};
}
/**
* Deserializes binary data (in protobuf wire format).
* @param {jspb.ByteSource} bytes The bytes to deserialize.
* @return {!proto.api.GetDeviceNextFCntDownRequest}
*/
proto.api.GetDeviceNextFCntDownRequest.deserializeBinary = function(bytes) {
var reader = new jspb.BinaryReader(bytes);
var msg = new proto.api.GetDeviceNextFCntDownRequest;
return proto.api.GetDeviceNextFCntDownRequest.deserializeBinaryFromReader(msg, reader);
};
/**
* Deserializes binary data (in protobuf wire format) from the
* given reader into the given message object.
* @param {!proto.api.GetDeviceNextFCntDownRequest} msg The message object to deserialize into.
* @param {!jspb.BinaryReader} reader The BinaryReader to use.
* @return {!proto.api.GetDeviceNextFCntDownRequest}
*/
proto.api.GetDeviceNextFCntDownRequest.deserializeBinaryFromReader = function(msg, reader) {
while (reader.nextField()) {
if (reader.isEndGroup()) {
break;
}
var field = reader.getFieldNumber();
switch (field) {
case 1:
var value = /** @type {string} */ (reader.readString());
msg.setDevEui(value);
break;
default:
reader.skipField();
break;
}
}
return msg;
};
/**
* Serializes the message to binary data (in protobuf wire format).
* @return {!Uint8Array}
*/
proto.api.GetDeviceNextFCntDownRequest.prototype.serializeBinary = function() {
var writer = new jspb.BinaryWriter();
proto.api.GetDeviceNextFCntDownRequest.serializeBinaryToWriter(this, writer);
return writer.getResultBuffer();
};
/**
* Serializes the given message to binary data (in protobuf wire
* format), writing to the given BinaryWriter.
* @param {!proto.api.GetDeviceNextFCntDownRequest} message
* @param {!jspb.BinaryWriter} writer
* @suppress {unusedLocalVariables} f is only used for nested messages
*/
proto.api.GetDeviceNextFCntDownRequest.serializeBinaryToWriter = function(message, writer) {
var f = undefined;
f = message.getDevEui();
if (f.length > 0) {
writer.writeString(
1,
f
);
}
};
/**
* optional string dev_eui = 1;
* @return {string}
*/
proto.api.GetDeviceNextFCntDownRequest.prototype.getDevEui = function() {
return /** @type {string} */ (jspb.Message.getFieldWithDefault(this, 1, ""));
};
/**
* @param {string} value
* @return {!proto.api.GetDeviceNextFCntDownRequest} returns this
*/
proto.api.GetDeviceNextFCntDownRequest.prototype.setDevEui = function(value) {
return jspb.Message.setProto3StringField(this, 1, value);
};
if (jspb.Message.GENERATE_TO_OBJECT) {
/**
* Creates an object representation of this proto.
* Field names that are reserved in JavaScript and will be renamed to pb_name.
* Optional fields that are not set will be set to undefined.
* To access a reserved field use, foo.pb_<name>, eg, foo.pb_default.
* For the list of reserved names please see:
* net/proto2/compiler/js/internal/generator.cc#kKeyword.
* @param {boolean=} opt_includeInstance Deprecated. whether to include the
* JSPB instance for transitional soy proto support:
* http://goto/soy-param-migration
* @return {!Object}
*/
proto.api.GetDeviceNextFCntDownResponse.prototype.toObject = function(opt_includeInstance) {
return proto.api.GetDeviceNextFCntDownResponse.toObject(opt_includeInstance, this);
};
/**
* Static version of the {@see toObject} method.
* @param {boolean|undefined} includeInstance Deprecated. Whether to include
* the JSPB instance for transitional soy proto support:
* http://goto/soy-param-migration
* @param {!proto.api.GetDeviceNextFCntDownResponse} msg The msg instance to transform.
* @return {!Object}
* @suppress {unusedLocalVariables} f is only used for nested messages
*/
proto.api.GetDeviceNextFCntDownResponse.toObject = function(includeInstance, msg) {
var f, obj = {
fCntDown: jspb.Message.getFieldWithDefault(msg, 1, 0)
};
if (includeInstance) {
obj.$jspbMessageInstance = msg;
}
return obj;
};
}
/**
* Deserializes binary data (in protobuf wire format).
* @param {jspb.ByteSource} bytes The bytes to deserialize.
* @return {!proto.api.GetDeviceNextFCntDownResponse}
*/
proto.api.GetDeviceNextFCntDownResponse.deserializeBinary = function(bytes) {
var reader = new jspb.BinaryReader(bytes);
var msg = new proto.api.GetDeviceNextFCntDownResponse;
return proto.api.GetDeviceNextFCntDownResponse.deserializeBinaryFromReader(msg, reader);
};
/**
* Deserializes binary data (in protobuf wire format) from the
* given reader into the given message object.
* @param {!proto.api.GetDeviceNextFCntDownResponse} msg The message object to deserialize into.
* @param {!jspb.BinaryReader} reader The BinaryReader to use.
* @return {!proto.api.GetDeviceNextFCntDownResponse}
*/
proto.api.GetDeviceNextFCntDownResponse.deserializeBinaryFromReader = function(msg, reader) {
while (reader.nextField()) {
if (reader.isEndGroup()) {
break;
}
var field = reader.getFieldNumber();
switch (field) {
case 1:
var value = /** @type {number} */ (reader.readUint32());
msg.setFCntDown(value);
break;
default:
reader.skipField();
break;
}
}
return msg;
};
/**
* Serializes the message to binary data (in protobuf wire format).
* @return {!Uint8Array}
*/
proto.api.GetDeviceNextFCntDownResponse.prototype.serializeBinary = function() {
var writer = new jspb.BinaryWriter();
proto.api.GetDeviceNextFCntDownResponse.serializeBinaryToWriter(this, writer);
return writer.getResultBuffer();
};
/**
* Serializes the given message to binary data (in protobuf wire
* format), writing to the given BinaryWriter.
* @param {!proto.api.GetDeviceNextFCntDownResponse} message
* @param {!jspb.BinaryWriter} writer
* @suppress {unusedLocalVariables} f is only used for nested messages
*/
proto.api.GetDeviceNextFCntDownResponse.serializeBinaryToWriter = function(message, writer) {
var f = undefined;
f = message.getFCntDown();
if (f !== 0) {
writer.writeUint32(
1,
f
);
}
};
/**
* optional uint32 f_cnt_down = 1;
* @return {number}
*/
proto.api.GetDeviceNextFCntDownResponse.prototype.getFCntDown = function() {
return /** @type {number} */ (jspb.Message.getFieldWithDefault(this, 1, 0));
};
/**
* @param {number} value
* @return {!proto.api.GetDeviceNextFCntDownResponse} returns this
*/
proto.api.GetDeviceNextFCntDownResponse.prototype.setFCntDown = function(value) {
return jspb.Message.setProto3IntField(this, 1, value);
};
goog.object.extend(exports, proto.api);

View File

@ -102,6 +102,32 @@ export namespace UplinkRelayRxInfo {
}
}
export class JoinServerContext extends jspb.Message {
getSessionKeyId(): string;
setSessionKeyId(value: string): void;
hasAppSKey(): boolean;
clearAppSKey(): void;
getAppSKey(): common_common_pb.KeyEnvelope | undefined;
setAppSKey(value?: common_common_pb.KeyEnvelope): void;
serializeBinary(): Uint8Array;
toObject(includeInstance?: boolean): JoinServerContext.AsObject;
static toObject(includeInstance: boolean, msg: JoinServerContext): JoinServerContext.AsObject;
static extensions: {[key: number]: jspb.ExtensionFieldInfo<jspb.Message>};
static extensionsBinary: {[key: number]: jspb.ExtensionFieldBinaryInfo<jspb.Message>};
static serializeBinaryToWriter(message: JoinServerContext, writer: jspb.BinaryWriter): void;
static deserializeBinary(bytes: Uint8Array): JoinServerContext;
static deserializeBinaryFromReader(message: JoinServerContext, reader: jspb.BinaryReader): JoinServerContext;
}
export namespace JoinServerContext {
export type AsObject = {
sessionKeyId: string,
appSKey?: common_common_pb.KeyEnvelope.AsObject,
}
}
export class UplinkEvent extends jspb.Message {
getDeduplicationId(): string;
setDeduplicationId(value: string): void;
@ -159,6 +185,11 @@ export class UplinkEvent extends jspb.Message {
getRelayRxInfo(): UplinkRelayRxInfo | undefined;
setRelayRxInfo(value?: UplinkRelayRxInfo): void;
hasJoinServerContext(): boolean;
clearJoinServerContext(): void;
getJoinServerContext(): JoinServerContext | undefined;
setJoinServerContext(value?: JoinServerContext): void;
serializeBinary(): Uint8Array;
toObject(includeInstance?: boolean): UplinkEvent.AsObject;
static toObject(includeInstance: boolean, msg: UplinkEvent): UplinkEvent.AsObject;
@ -185,6 +216,7 @@ export namespace UplinkEvent {
rxInfoList: Array<gw_gw_pb.UplinkRxInfo.AsObject>,
txInfo?: gw_gw_pb.UplinkTxInfo.AsObject,
relayRxInfo?: UplinkRelayRxInfo.AsObject,
joinServerContext?: JoinServerContext.AsObject,
}
}
@ -210,6 +242,11 @@ export class JoinEvent extends jspb.Message {
getRelayRxInfo(): UplinkRelayRxInfo | undefined;
setRelayRxInfo(value?: UplinkRelayRxInfo): void;
hasJoinServerContext(): boolean;
clearJoinServerContext(): void;
getJoinServerContext(): JoinServerContext | undefined;
setJoinServerContext(value?: JoinServerContext): void;
serializeBinary(): Uint8Array;
toObject(includeInstance?: boolean): JoinEvent.AsObject;
static toObject(includeInstance: boolean, msg: JoinEvent): JoinEvent.AsObject;
@ -227,6 +264,7 @@ export namespace JoinEvent {
deviceInfo?: DeviceInfo.AsObject,
devAddr: string,
relayRxInfo?: UplinkRelayRxInfo.AsObject,
joinServerContext?: JoinServerContext.AsObject,
}
}
@ -562,6 +600,7 @@ export interface LogCodeMap {
UPLINK_F_CNT_RETRANSMISSION: 7;
DOWNLINK_GATEWAY: 8;
RELAY_NEW_END_DEVICE: 9;
F_CNT_DOWN: 10;
}
export const LogCode: LogCodeMap;

View File

@ -25,6 +25,7 @@ goog.exportSymbol('proto.integration.DeviceInfo', null, global);
goog.exportSymbol('proto.integration.DownlinkCommand', null, global);
goog.exportSymbol('proto.integration.IntegrationEvent', null, global);
goog.exportSymbol('proto.integration.JoinEvent', null, global);
goog.exportSymbol('proto.integration.JoinServerContext', null, global);
goog.exportSymbol('proto.integration.LocationEvent', null, global);
goog.exportSymbol('proto.integration.LogCode', null, global);
goog.exportSymbol('proto.integration.LogEvent', null, global);
@ -75,6 +76,27 @@ if (goog.DEBUG && !COMPILED) {
*/
proto.integration.UplinkRelayRxInfo.displayName = 'proto.integration.UplinkRelayRxInfo';
}
/**
* Generated by JsPbCodeGenerator.
* @param {Array=} opt_data Optional initial data array, typically from a
* server response, or constructed directly in Javascript. The array is used
* in place and becomes part of the constructed object. It is not cloned.
* If no data is provided, the constructed object will be empty, but still
* valid.
* @extends {jspb.Message}
* @constructor
*/
proto.integration.JoinServerContext = function(opt_data) {
jspb.Message.initialize(this, opt_data, 0, -1, null, null);
};
goog.inherits(proto.integration.JoinServerContext, jspb.Message);
if (goog.DEBUG && !COMPILED) {
/**
* @public
* @override
*/
proto.integration.JoinServerContext.displayName = 'proto.integration.JoinServerContext';
}
/**
* Generated by JsPbCodeGenerator.
* @param {Array=} opt_data Optional initial data array, typically from a
@ -948,6 +970,187 @@ proto.integration.UplinkRelayRxInfo.prototype.setWorChannel = function(value) {
if (jspb.Message.GENERATE_TO_OBJECT) {
/**
* Creates an object representation of this proto.
* Field names that are reserved in JavaScript and will be renamed to pb_name.
* Optional fields that are not set will be set to undefined.
* To access a reserved field use, foo.pb_<name>, eg, foo.pb_default.
* For the list of reserved names please see:
* net/proto2/compiler/js/internal/generator.cc#kKeyword.
* @param {boolean=} opt_includeInstance Deprecated. whether to include the
* JSPB instance for transitional soy proto support:
* http://goto/soy-param-migration
* @return {!Object}
*/
proto.integration.JoinServerContext.prototype.toObject = function(opt_includeInstance) {
return proto.integration.JoinServerContext.toObject(opt_includeInstance, this);
};
/**
* Static version of the {@see toObject} method.
* @param {boolean|undefined} includeInstance Deprecated. Whether to include
* the JSPB instance for transitional soy proto support:
* http://goto/soy-param-migration
* @param {!proto.integration.JoinServerContext} msg The msg instance to transform.
* @return {!Object}
* @suppress {unusedLocalVariables} f is only used for nested messages
*/
proto.integration.JoinServerContext.toObject = function(includeInstance, msg) {
var f, obj = {
sessionKeyId: jspb.Message.getFieldWithDefault(msg, 1, ""),
appSKey: (f = msg.getAppSKey()) && common_common_pb.KeyEnvelope.toObject(includeInstance, f)
};
if (includeInstance) {
obj.$jspbMessageInstance = msg;
}
return obj;
};
}
/**
* Deserializes binary data (in protobuf wire format).
* @param {jspb.ByteSource} bytes The bytes to deserialize.
* @return {!proto.integration.JoinServerContext}
*/
proto.integration.JoinServerContext.deserializeBinary = function(bytes) {
var reader = new jspb.BinaryReader(bytes);
var msg = new proto.integration.JoinServerContext;
return proto.integration.JoinServerContext.deserializeBinaryFromReader(msg, reader);
};
/**
* Deserializes binary data (in protobuf wire format) from the
* given reader into the given message object.
* @param {!proto.integration.JoinServerContext} msg The message object to deserialize into.
* @param {!jspb.BinaryReader} reader The BinaryReader to use.
* @return {!proto.integration.JoinServerContext}
*/
proto.integration.JoinServerContext.deserializeBinaryFromReader = function(msg, reader) {
while (reader.nextField()) {
if (reader.isEndGroup()) {
break;
}
var field = reader.getFieldNumber();
switch (field) {
case 1:
var value = /** @type {string} */ (reader.readString());
msg.setSessionKeyId(value);
break;
case 2:
var value = new common_common_pb.KeyEnvelope;
reader.readMessage(value,common_common_pb.KeyEnvelope.deserializeBinaryFromReader);
msg.setAppSKey(value);
break;
default:
reader.skipField();
break;
}
}
return msg;
};
/**
* Serializes the message to binary data (in protobuf wire format).
* @return {!Uint8Array}
*/
proto.integration.JoinServerContext.prototype.serializeBinary = function() {
var writer = new jspb.BinaryWriter();
proto.integration.JoinServerContext.serializeBinaryToWriter(this, writer);
return writer.getResultBuffer();
};
/**
* Serializes the given message to binary data (in protobuf wire
* format), writing to the given BinaryWriter.
* @param {!proto.integration.JoinServerContext} message
* @param {!jspb.BinaryWriter} writer
* @suppress {unusedLocalVariables} f is only used for nested messages
*/
proto.integration.JoinServerContext.serializeBinaryToWriter = function(message, writer) {
var f = undefined;
f = message.getSessionKeyId();
if (f.length > 0) {
writer.writeString(
1,
f
);
}
f = message.getAppSKey();
if (f != null) {
writer.writeMessage(
2,
f,
common_common_pb.KeyEnvelope.serializeBinaryToWriter
);
}
};
/**
* optional string session_key_id = 1;
* @return {string}
*/
proto.integration.JoinServerContext.prototype.getSessionKeyId = function() {
return /** @type {string} */ (jspb.Message.getFieldWithDefault(this, 1, ""));
};
/**
* @param {string} value
* @return {!proto.integration.JoinServerContext} returns this
*/
proto.integration.JoinServerContext.prototype.setSessionKeyId = function(value) {
return jspb.Message.setProto3StringField(this, 1, value);
};
/**
* optional common.KeyEnvelope app_s_key = 2;
* @return {?proto.common.KeyEnvelope}
*/
proto.integration.JoinServerContext.prototype.getAppSKey = function() {
return /** @type{?proto.common.KeyEnvelope} */ (
jspb.Message.getWrapperField(this, common_common_pb.KeyEnvelope, 2));
};
/**
* @param {?proto.common.KeyEnvelope|undefined} value
* @return {!proto.integration.JoinServerContext} returns this
*/
proto.integration.JoinServerContext.prototype.setAppSKey = function(value) {
return jspb.Message.setWrapperField(this, 2, value);
};
/**
* Clears the message field making it undefined.
* @return {!proto.integration.JoinServerContext} returns this
*/
proto.integration.JoinServerContext.prototype.clearAppSKey = function() {
return this.setAppSKey(undefined);
};
/**
* Returns whether this field is set.
* @return {boolean}
*/
proto.integration.JoinServerContext.prototype.hasAppSKey = function() {
return jspb.Message.getField(this, 2) != null;
};
/**
* List of repeated fields within this message type.
* @private {!Array<number>}
@ -1000,7 +1203,8 @@ proto.integration.UplinkEvent.toObject = function(includeInstance, msg) {
rxInfoList: jspb.Message.toObjectList(msg.getRxInfoList(),
gw_gw_pb.UplinkRxInfo.toObject, includeInstance),
txInfo: (f = msg.getTxInfo()) && gw_gw_pb.UplinkTxInfo.toObject(includeInstance, f),
relayRxInfo: (f = msg.getRelayRxInfo()) && proto.integration.UplinkRelayRxInfo.toObject(includeInstance, f)
relayRxInfo: (f = msg.getRelayRxInfo()) && proto.integration.UplinkRelayRxInfo.toObject(includeInstance, f),
joinServerContext: (f = msg.getJoinServerContext()) && proto.integration.JoinServerContext.toObject(includeInstance, f)
};
if (includeInstance) {
@ -1099,6 +1303,11 @@ proto.integration.UplinkEvent.deserializeBinaryFromReader = function(msg, reader
reader.readMessage(value,proto.integration.UplinkRelayRxInfo.deserializeBinaryFromReader);
msg.setRelayRxInfo(value);
break;
case 15:
var value = new proto.integration.JoinServerContext;
reader.readMessage(value,proto.integration.JoinServerContext.deserializeBinaryFromReader);
msg.setJoinServerContext(value);
break;
default:
reader.skipField();
break;
@ -1232,6 +1441,14 @@ proto.integration.UplinkEvent.serializeBinaryToWriter = function(message, writer
proto.integration.UplinkRelayRxInfo.serializeBinaryToWriter
);
}
f = message.getJoinServerContext();
if (f != null) {
writer.writeMessage(
15,
f,
proto.integration.JoinServerContext.serializeBinaryToWriter
);
}
};
@ -1626,6 +1843,43 @@ proto.integration.UplinkEvent.prototype.hasRelayRxInfo = function() {
};
/**
* optional JoinServerContext join_server_context = 15;
* @return {?proto.integration.JoinServerContext}
*/
proto.integration.UplinkEvent.prototype.getJoinServerContext = function() {
return /** @type{?proto.integration.JoinServerContext} */ (
jspb.Message.getWrapperField(this, proto.integration.JoinServerContext, 15));
};
/**
* @param {?proto.integration.JoinServerContext|undefined} value
* @return {!proto.integration.UplinkEvent} returns this
*/
proto.integration.UplinkEvent.prototype.setJoinServerContext = function(value) {
return jspb.Message.setWrapperField(this, 15, value);
};
/**
* Clears the message field making it undefined.
* @return {!proto.integration.UplinkEvent} returns this
*/
proto.integration.UplinkEvent.prototype.clearJoinServerContext = function() {
return this.setJoinServerContext(undefined);
};
/**
* Returns whether this field is set.
* @return {boolean}
*/
proto.integration.UplinkEvent.prototype.hasJoinServerContext = function() {
return jspb.Message.getField(this, 15) != null;
};
@ -1662,7 +1916,8 @@ proto.integration.JoinEvent.toObject = function(includeInstance, msg) {
time: (f = msg.getTime()) && google_protobuf_timestamp_pb.Timestamp.toObject(includeInstance, f),
deviceInfo: (f = msg.getDeviceInfo()) && proto.integration.DeviceInfo.toObject(includeInstance, f),
devAddr: jspb.Message.getFieldWithDefault(msg, 4, ""),
relayRxInfo: (f = msg.getRelayRxInfo()) && proto.integration.UplinkRelayRxInfo.toObject(includeInstance, f)
relayRxInfo: (f = msg.getRelayRxInfo()) && proto.integration.UplinkRelayRxInfo.toObject(includeInstance, f),
joinServerContext: (f = msg.getJoinServerContext()) && proto.integration.JoinServerContext.toObject(includeInstance, f)
};
if (includeInstance) {
@ -1722,6 +1977,11 @@ proto.integration.JoinEvent.deserializeBinaryFromReader = function(msg, reader)
reader.readMessage(value,proto.integration.UplinkRelayRxInfo.deserializeBinaryFromReader);
msg.setRelayRxInfo(value);
break;
case 6:
var value = new proto.integration.JoinServerContext;
reader.readMessage(value,proto.integration.JoinServerContext.deserializeBinaryFromReader);
msg.setJoinServerContext(value);
break;
default:
reader.skipField();
break;
@ -1789,6 +2049,14 @@ proto.integration.JoinEvent.serializeBinaryToWriter = function(message, writer)
proto.integration.UplinkRelayRxInfo.serializeBinaryToWriter
);
}
f = message.getJoinServerContext();
if (f != null) {
writer.writeMessage(
6,
f,
proto.integration.JoinServerContext.serializeBinaryToWriter
);
}
};
@ -1939,6 +2207,43 @@ proto.integration.JoinEvent.prototype.hasRelayRxInfo = function() {
};
/**
* optional JoinServerContext join_server_context = 6;
* @return {?proto.integration.JoinServerContext}
*/
proto.integration.JoinEvent.prototype.getJoinServerContext = function() {
return /** @type{?proto.integration.JoinServerContext} */ (
jspb.Message.getWrapperField(this, proto.integration.JoinServerContext, 6));
};
/**
* @param {?proto.integration.JoinServerContext|undefined} value
* @return {!proto.integration.JoinEvent} returns this
*/
proto.integration.JoinEvent.prototype.setJoinServerContext = function(value) {
return jspb.Message.setWrapperField(this, 6, value);
};
/**
* Clears the message field making it undefined.
* @return {!proto.integration.JoinEvent} returns this
*/
proto.integration.JoinEvent.prototype.clearJoinServerContext = function() {
return this.setJoinServerContext(undefined);
};
/**
* Returns whether this field is set.
* @return {boolean}
*/
proto.integration.JoinEvent.prototype.hasJoinServerContext = function() {
return jspb.Message.getField(this, 6) != null;
};
@ -4284,7 +4589,8 @@ proto.integration.LogCode = {
UPLINK_MIC: 6,
UPLINK_F_CNT_RETRANSMISSION: 7,
DOWNLINK_GATEWAY: 8,
RELAY_NEW_END_DEVICE: 9
RELAY_NEW_END_DEVICE: 9,
F_CNT_DOWN: 10
};
goog.object.extend(exports, proto.integration);

38
api/md/api/api.md vendored
View File

@ -119,6 +119,8 @@
- [GetDeviceMetricsResponse](#api-GetDeviceMetricsResponse)
- [GetDeviceMetricsResponse.MetricsEntry](#api-GetDeviceMetricsResponse-MetricsEntry)
- [GetDeviceMetricsResponse.StatesEntry](#api-GetDeviceMetricsResponse-StatesEntry)
- [GetDeviceNextFCntDownRequest](#api-GetDeviceNextFCntDownRequest)
- [GetDeviceNextFCntDownResponse](#api-GetDeviceNextFCntDownResponse)
- [GetDeviceQueueItemsRequest](#api-GetDeviceQueueItemsRequest)
- [GetDeviceQueueItemsResponse](#api-GetDeviceQueueItemsResponse)
- [GetDeviceRequest](#api-GetDeviceRequest)
@ -1841,8 +1843,9 @@ applications.
| f_port | [uint32](#uint32) | | FPort (must be &gt; 0). |
| data | [bytes](#bytes) | | Data. Or use the json_object field when a codec has been configured. |
| object | [google.protobuf.Struct](#google-protobuf-Struct) | | Only use this when a codec has been configured that can encode this object to bytes. |
| is_pending | [bool](#bool) | | Is pending. This is set to true when the downlink is pending. |
| f_cnt_down | [uint32](#uint32) | | Downlink frame-counter. This is set when the payload has been sent as downlink. |
| is_pending | [bool](#bool) | | Is pending. This is set by ChirpStack to true when the downlink is pending (e.g. it has been sent, but a confirmation is still pending). |
| f_cnt_down | [uint32](#uint32) | | Downlink frame-counter. Do not set this for plain-text data payloads. It will be automatically set by ChirpStack when the payload has been sent as downlink. |
| is_encrypted | [bool](#bool) | | Is encrypted. This must be set to true if the end-application has already encrypted the data payload. In this case, the f_cnt_down field must be set to the corresponding frame-counter which has been used during the encryption. |
@ -2108,6 +2111,36 @@ applications.
<a name="api-GetDeviceNextFCntDownRequest"></a>
### GetDeviceNextFCntDownRequest
| Field | Type | Label | Description |
| ----- | ---- | ----- | ----------- |
| dev_eui | [string](#string) | | Device EUI (EUI64). |
<a name="api-GetDeviceNextFCntDownResponse"></a>
### GetDeviceNextFCntDownResponse
| Field | Type | Label | Description |
| ----- | ---- | ----- | ----------- |
| f_cnt_down | [uint32](#uint32) | | FCntDown. |
<a name="api-GetDeviceQueueItemsRequest"></a>
### GetDeviceQueueItemsRequest
@ -2302,6 +2335,7 @@ DeviceService is the service providing API methods for managing devices.
| Enqueue | [EnqueueDeviceQueueItemRequest](#api-EnqueueDeviceQueueItemRequest) | [EnqueueDeviceQueueItemResponse](#api-EnqueueDeviceQueueItemResponse) | Enqueue adds the given item to the downlink queue. |
| FlushQueue | [FlushDeviceQueueRequest](#api-FlushDeviceQueueRequest) | [.google.protobuf.Empty](#google-protobuf-Empty) | FlushQueue flushes the downlink device-queue. |
| GetQueue | [GetDeviceQueueItemsRequest](#api-GetDeviceQueueItemsRequest) | [GetDeviceQueueItemsResponse](#api-GetDeviceQueueItemsResponse) | GetQueue returns the downlink device-queue. |
| GetNextFCntDown | [GetDeviceNextFCntDownRequest](#api-GetDeviceNextFCntDownRequest) | [GetDeviceNextFCntDownResponse](#api-GetDeviceNextFCntDownResponse) | GetNextFCntDown returns the next FCntDown to use for enqueing encrypted downlinks. The difference with the DeviceActivation f_cont_down is that this method takes potential existing queue-items into account. |

View File

@ -165,6 +165,17 @@ service DeviceService {
get : "/api/devices/{dev_eui}/queue"
};
}
// GetNextFCntDown returns the next FCntDown to use for enqueing encrypted
// downlinks. The difference with the DeviceActivation f_cont_down is that
// this method takes potential existing queue-items into account.
rpc GetNextFCntDown(GetDeviceNextFCntDownRequest)
returns (GetDeviceNextFCntDownResponse) {
option (google.api.http) = {
post : "/api/devices/{dev_eui}/get-next-f-cnt-down"
body : "*"
};
}
}
message Device {
@ -504,12 +515,20 @@ message DeviceQueueItem {
google.protobuf.Struct object = 6;
// Is pending.
// This is set to true when the downlink is pending.
// This is set by ChirpStack to true when the downlink is pending (e.g. it
// has been sent, but a confirmation is still pending).
bool is_pending = 7;
// Downlink frame-counter.
// This is set when the payload has been sent as downlink.
// Do not set this for plain-text data payloads. It will be automatically set
// by ChirpStack when the payload has been sent as downlink.
uint32 f_cnt_down = 8;
// Is encrypted.
// This must be set to true if the end-application has already encrypted
// the data payload. In this case, the f_cnt_down field must be set to
// the corresponding frame-counter which has been used during the encryption.
bool is_encrypted = 9;
}
message EnqueueDeviceQueueItemRequest { DeviceQueueItem queue_item = 1; }
@ -544,3 +563,13 @@ message FlushDevNoncesRequest {
// Device EUI (EUI64).
string dev_eui = 1;
}
message GetDeviceNextFCntDownRequest {
// Device EUI (EUI64).
string dev_eui = 1;
}
message GetDeviceNextFCntDownResponse {
// FCntDown.
uint32 f_cnt_down = 1;
}

View File

@ -55,6 +55,9 @@ enum LogCode {
// Relay new end-device.
RELAY_NEW_END_DEVICE = 9;
// Downlink frame-counter.
F_CNT_DOWN = 10;
}
// Device information.
@ -111,6 +114,15 @@ message UplinkRelayRxInfo {
uint32 wor_channel = 6;
}
// Join-Server context.
message JoinServerContext {
// Session-key ID.
string session_key_id = 1;
// AppSKey envelope.
common.KeyEnvelope app_s_key = 2;
}
// UplinkEvent is the message sent when an uplink payload has been received.
message UplinkEvent {
// Deduplication ID (UUID).
@ -155,6 +167,12 @@ message UplinkEvent {
// Relay info.
UplinkRelayRxInfo relay_rx_info = 14;
// Join-Server context.
// A non-empty value indicatest that ChirpStack does not have access to
// the AppSKey and that the encryption / decryption of the payloads is
// the responsibility of the end-application.
JoinServerContext join_server_context = 15;
}
// JoinEvent is the message sent when a device joined the network.
@ -174,6 +192,12 @@ message JoinEvent {
// Relay info.
UplinkRelayRxInfo relay_rx_info = 5;
// Join-Server context.
// A non-empty value indicatest that ChirpStack does not have access to
// the AppSKey and that the encryption / decryption of the payloads is
// the responsibility of the end-application.
JoinServerContext join_server_context = 6;
}
// AckEvent is the message sent when a confirmation on a confirmed downlink

View File

@ -31,6 +31,9 @@ message DeviceSession {
// AppSKey envelope.
common.KeyEnvelope app_s_key = 8;
// JS Session Key ID.
bytes js_session_key_id = 42;
// Uplink frame-counter.
uint32 f_cnt_up = 9;

View File

@ -165,6 +165,17 @@ service DeviceService {
get : "/api/devices/{dev_eui}/queue"
};
}
// GetNextFCntDown returns the next FCntDown to use for enqueing encrypted
// downlinks. The difference with the DeviceActivation f_cont_down is that
// this method takes potential existing queue-items into account.
rpc GetNextFCntDown(GetDeviceNextFCntDownRequest)
returns (GetDeviceNextFCntDownResponse) {
option (google.api.http) = {
post : "/api/devices/{dev_eui}/get-next-f-cnt-down"
body : "*"
};
}
}
message Device {
@ -504,12 +515,20 @@ message DeviceQueueItem {
google.protobuf.Struct object = 6;
// Is pending.
// This is set to true when the downlink is pending.
// This is set by ChirpStack to true when the downlink is pending (e.g. it
// has been sent, but a confirmation is still pending).
bool is_pending = 7;
// Downlink frame-counter.
// This is set when the payload has been sent as downlink.
// Do not set this for plain-text data payloads. It will be automatically set
// by ChirpStack when the payload has been sent as downlink.
uint32 f_cnt_down = 8;
// Is encrypted.
// This must be set to true if the end-application has already encrypted
// the data payload. In this case, the f_cnt_down field must be set to
// the corresponding frame-counter which has been used during the encryption.
bool is_encrypted = 9;
}
message EnqueueDeviceQueueItemRequest { DeviceQueueItem queue_item = 1; }
@ -544,3 +563,13 @@ message FlushDevNoncesRequest {
// Device EUI (EUI64).
string dev_eui = 1;
}
message GetDeviceNextFCntDownRequest {
// Device EUI (EUI64).
string dev_eui = 1;
}
message GetDeviceNextFCntDownResponse {
// FCntDown.
uint32 f_cnt_down = 1;
}

View File

@ -55,6 +55,9 @@ enum LogCode {
// Relay new end-device.
RELAY_NEW_END_DEVICE = 9;
// Downlink frame-counter.
F_CNT_DOWN = 10;
}
// Device information.
@ -111,6 +114,15 @@ message UplinkRelayRxInfo {
uint32 wor_channel = 6;
}
// Join-Server context.
message JoinServerContext {
// Session-key ID.
string session_key_id = 1;
// AppSKey envelope.
common.KeyEnvelope app_s_key = 2;
}
// UplinkEvent is the message sent when an uplink payload has been received.
message UplinkEvent {
// Deduplication ID (UUID).
@ -155,6 +167,12 @@ message UplinkEvent {
// Relay info.
UplinkRelayRxInfo relay_rx_info = 14;
// Join-Server context.
// A non-empty value indicatest that ChirpStack does not have access to
// the AppSKey and that the encryption / decryption of the payloads is
// the responsibility of the end-application.
JoinServerContext join_server_context = 15;
}
// JoinEvent is the message sent when a device joined the network.
@ -174,6 +192,12 @@ message JoinEvent {
// Relay info.
UplinkRelayRxInfo relay_rx_info = 5;
// Join-Server context.
// A non-empty value indicatest that ChirpStack does not have access to
// the AppSKey and that the encryption / decryption of the payloads is
// the responsibility of the end-application.
JoinServerContext join_server_context = 6;
}
// AckEvent is the message sent when a confirmation on a confirmed downlink

View File

@ -31,6 +31,9 @@ message DeviceSession {
// AppSKey envelope.
common.KeyEnvelope app_s_key = 8;
// JS Session Key ID.
bytes js_session_key_id = 42;
// Uplink frame-counter.
uint32 f_cnt_up = 9;

File diff suppressed because one or more lines are too long

View File

@ -315,7 +315,7 @@ class GetDeviceLinkMetricsResponse(_message.Message):
def __init__(self, rx_packets: _Optional[_Union[_common_pb2.Metric, _Mapping]] = ..., gw_rssi: _Optional[_Union[_common_pb2.Metric, _Mapping]] = ..., gw_snr: _Optional[_Union[_common_pb2.Metric, _Mapping]] = ..., rx_packets_per_freq: _Optional[_Union[_common_pb2.Metric, _Mapping]] = ..., rx_packets_per_dr: _Optional[_Union[_common_pb2.Metric, _Mapping]] = ..., errors: _Optional[_Union[_common_pb2.Metric, _Mapping]] = ...) -> None: ...
class DeviceQueueItem(_message.Message):
__slots__ = ["id", "dev_eui", "confirmed", "f_port", "data", "object", "is_pending", "f_cnt_down"]
__slots__ = ["id", "dev_eui", "confirmed", "f_port", "data", "object", "is_pending", "f_cnt_down", "is_encrypted"]
ID_FIELD_NUMBER: _ClassVar[int]
DEV_EUI_FIELD_NUMBER: _ClassVar[int]
CONFIRMED_FIELD_NUMBER: _ClassVar[int]
@ -324,6 +324,7 @@ class DeviceQueueItem(_message.Message):
OBJECT_FIELD_NUMBER: _ClassVar[int]
IS_PENDING_FIELD_NUMBER: _ClassVar[int]
F_CNT_DOWN_FIELD_NUMBER: _ClassVar[int]
IS_ENCRYPTED_FIELD_NUMBER: _ClassVar[int]
id: str
dev_eui: str
confirmed: bool
@ -332,7 +333,8 @@ class DeviceQueueItem(_message.Message):
object: _struct_pb2.Struct
is_pending: bool
f_cnt_down: int
def __init__(self, id: _Optional[str] = ..., dev_eui: _Optional[str] = ..., confirmed: bool = ..., f_port: _Optional[int] = ..., data: _Optional[bytes] = ..., object: _Optional[_Union[_struct_pb2.Struct, _Mapping]] = ..., is_pending: bool = ..., f_cnt_down: _Optional[int] = ...) -> None: ...
is_encrypted: bool
def __init__(self, id: _Optional[str] = ..., dev_eui: _Optional[str] = ..., confirmed: bool = ..., f_port: _Optional[int] = ..., data: _Optional[bytes] = ..., object: _Optional[_Union[_struct_pb2.Struct, _Mapping]] = ..., is_pending: bool = ..., f_cnt_down: _Optional[int] = ..., is_encrypted: bool = ...) -> None: ...
class EnqueueDeviceQueueItemRequest(_message.Message):
__slots__ = ["queue_item"]
@ -373,3 +375,15 @@ class FlushDevNoncesRequest(_message.Message):
DEV_EUI_FIELD_NUMBER: _ClassVar[int]
dev_eui: str
def __init__(self, dev_eui: _Optional[str] = ...) -> None: ...
class GetDeviceNextFCntDownRequest(_message.Message):
__slots__ = ["dev_eui"]
DEV_EUI_FIELD_NUMBER: _ClassVar[int]
dev_eui: str
def __init__(self, dev_eui: _Optional[str] = ...) -> None: ...
class GetDeviceNextFCntDownResponse(_message.Message):
__slots__ = ["f_cnt_down"]
F_CNT_DOWN_FIELD_NUMBER: _ClassVar[int]
f_cnt_down: int
def __init__(self, f_cnt_down: _Optional[int] = ...) -> None: ...

View File

@ -111,6 +111,11 @@ class DeviceServiceStub(object):
request_serializer=chirpstack__api_dot_api_dot_device__pb2.GetDeviceQueueItemsRequest.SerializeToString,
response_deserializer=chirpstack__api_dot_api_dot_device__pb2.GetDeviceQueueItemsResponse.FromString,
)
self.GetNextFCntDown = channel.unary_unary(
'/api.DeviceService/GetNextFCntDown',
request_serializer=chirpstack__api_dot_api_dot_device__pb2.GetDeviceNextFCntDownRequest.SerializeToString,
response_deserializer=chirpstack__api_dot_api_dot_device__pb2.GetDeviceNextFCntDownResponse.FromString,
)
class DeviceServiceServicer(object):
@ -256,6 +261,15 @@ class DeviceServiceServicer(object):
context.set_details('Method not implemented!')
raise NotImplementedError('Method not implemented!')
def GetNextFCntDown(self, request, context):
"""GetNextFCntDown returns the next FCntDown to use for enqueing encrypted
downlinks. The difference with the DeviceActivation f_cont_down is that
this method takes potential existing queue-items into account.
"""
context.set_code(grpc.StatusCode.UNIMPLEMENTED)
context.set_details('Method not implemented!')
raise NotImplementedError('Method not implemented!')
def add_DeviceServiceServicer_to_server(servicer, server):
rpc_method_handlers = {
@ -354,6 +368,11 @@ def add_DeviceServiceServicer_to_server(servicer, server):
request_deserializer=chirpstack__api_dot_api_dot_device__pb2.GetDeviceQueueItemsRequest.FromString,
response_serializer=chirpstack__api_dot_api_dot_device__pb2.GetDeviceQueueItemsResponse.SerializeToString,
),
'GetNextFCntDown': grpc.unary_unary_rpc_method_handler(
servicer.GetNextFCntDown,
request_deserializer=chirpstack__api_dot_api_dot_device__pb2.GetDeviceNextFCntDownRequest.FromString,
response_serializer=chirpstack__api_dot_api_dot_device__pb2.GetDeviceNextFCntDownResponse.SerializeToString,
),
}
generic_handler = grpc.method_handlers_generic_handler(
'api.DeviceService', rpc_method_handlers)
@ -687,3 +706,20 @@ class DeviceService(object):
chirpstack__api_dot_api_dot_device__pb2.GetDeviceQueueItemsResponse.FromString,
options, channel_credentials,
insecure, call_credentials, compression, wait_for_ready, timeout, metadata)
@staticmethod
def GetNextFCntDown(request,
target,
options=(),
channel_credentials=None,
call_credentials=None,
insecure=False,
compression=None,
wait_for_ready=None,
timeout=None,
metadata=None):
return grpc.experimental.unary_unary(request, target, '/api.DeviceService/GetNextFCntDown',
chirpstack__api_dot_api_dot_device__pb2.GetDeviceNextFCntDownRequest.SerializeToString,
chirpstack__api_dot_api_dot_device__pb2.GetDeviceNextFCntDownResponse.FromString,
options, channel_credentials,
insecure, call_credentials, compression, wait_for_ready, timeout, metadata)

File diff suppressed because one or more lines are too long

View File

@ -28,6 +28,7 @@ class LogCode(int, metaclass=_enum_type_wrapper.EnumTypeWrapper):
UPLINK_F_CNT_RETRANSMISSION: _ClassVar[LogCode]
DOWNLINK_GATEWAY: _ClassVar[LogCode]
RELAY_NEW_END_DEVICE: _ClassVar[LogCode]
F_CNT_DOWN: _ClassVar[LogCode]
INFO: LogLevel
WARNING: LogLevel
ERROR: LogLevel
@ -41,6 +42,7 @@ UPLINK_MIC: LogCode
UPLINK_F_CNT_RETRANSMISSION: LogCode
DOWNLINK_GATEWAY: LogCode
RELAY_NEW_END_DEVICE: LogCode
F_CNT_DOWN: LogCode
class DeviceInfo(_message.Message):
__slots__ = ["tenant_id", "tenant_name", "application_id", "application_name", "device_profile_id", "device_profile_name", "device_name", "dev_eui", "device_class_enabled", "tags"]
@ -89,8 +91,16 @@ class UplinkRelayRxInfo(_message.Message):
wor_channel: int
def __init__(self, dev_eui: _Optional[str] = ..., frequency: _Optional[int] = ..., dr: _Optional[int] = ..., snr: _Optional[int] = ..., rssi: _Optional[int] = ..., wor_channel: _Optional[int] = ...) -> None: ...
class JoinServerContext(_message.Message):
__slots__ = ["session_key_id", "app_s_key"]
SESSION_KEY_ID_FIELD_NUMBER: _ClassVar[int]
APP_S_KEY_FIELD_NUMBER: _ClassVar[int]
session_key_id: str
app_s_key: _common_pb2.KeyEnvelope
def __init__(self, session_key_id: _Optional[str] = ..., app_s_key: _Optional[_Union[_common_pb2.KeyEnvelope, _Mapping]] = ...) -> None: ...
class UplinkEvent(_message.Message):
__slots__ = ["deduplication_id", "time", "device_info", "dev_addr", "adr", "dr", "f_cnt", "f_port", "confirmed", "data", "object", "rx_info", "tx_info", "relay_rx_info"]
__slots__ = ["deduplication_id", "time", "device_info", "dev_addr", "adr", "dr", "f_cnt", "f_port", "confirmed", "data", "object", "rx_info", "tx_info", "relay_rx_info", "join_server_context"]
DEDUPLICATION_ID_FIELD_NUMBER: _ClassVar[int]
TIME_FIELD_NUMBER: _ClassVar[int]
DEVICE_INFO_FIELD_NUMBER: _ClassVar[int]
@ -105,6 +115,7 @@ class UplinkEvent(_message.Message):
RX_INFO_FIELD_NUMBER: _ClassVar[int]
TX_INFO_FIELD_NUMBER: _ClassVar[int]
RELAY_RX_INFO_FIELD_NUMBER: _ClassVar[int]
JOIN_SERVER_CONTEXT_FIELD_NUMBER: _ClassVar[int]
deduplication_id: str
time: _timestamp_pb2.Timestamp
device_info: DeviceInfo
@ -119,21 +130,24 @@ class UplinkEvent(_message.Message):
rx_info: _containers.RepeatedCompositeFieldContainer[_gw_pb2.UplinkRxInfo]
tx_info: _gw_pb2.UplinkTxInfo
relay_rx_info: UplinkRelayRxInfo
def __init__(self, deduplication_id: _Optional[str] = ..., time: _Optional[_Union[_timestamp_pb2.Timestamp, _Mapping]] = ..., device_info: _Optional[_Union[DeviceInfo, _Mapping]] = ..., dev_addr: _Optional[str] = ..., adr: bool = ..., dr: _Optional[int] = ..., f_cnt: _Optional[int] = ..., f_port: _Optional[int] = ..., confirmed: bool = ..., data: _Optional[bytes] = ..., object: _Optional[_Union[_struct_pb2.Struct, _Mapping]] = ..., rx_info: _Optional[_Iterable[_Union[_gw_pb2.UplinkRxInfo, _Mapping]]] = ..., tx_info: _Optional[_Union[_gw_pb2.UplinkTxInfo, _Mapping]] = ..., relay_rx_info: _Optional[_Union[UplinkRelayRxInfo, _Mapping]] = ...) -> None: ...
join_server_context: JoinServerContext
def __init__(self, deduplication_id: _Optional[str] = ..., time: _Optional[_Union[_timestamp_pb2.Timestamp, _Mapping]] = ..., device_info: _Optional[_Union[DeviceInfo, _Mapping]] = ..., dev_addr: _Optional[str] = ..., adr: bool = ..., dr: _Optional[int] = ..., f_cnt: _Optional[int] = ..., f_port: _Optional[int] = ..., confirmed: bool = ..., data: _Optional[bytes] = ..., object: _Optional[_Union[_struct_pb2.Struct, _Mapping]] = ..., rx_info: _Optional[_Iterable[_Union[_gw_pb2.UplinkRxInfo, _Mapping]]] = ..., tx_info: _Optional[_Union[_gw_pb2.UplinkTxInfo, _Mapping]] = ..., relay_rx_info: _Optional[_Union[UplinkRelayRxInfo, _Mapping]] = ..., join_server_context: _Optional[_Union[JoinServerContext, _Mapping]] = ...) -> None: ...
class JoinEvent(_message.Message):
__slots__ = ["deduplication_id", "time", "device_info", "dev_addr", "relay_rx_info"]
__slots__ = ["deduplication_id", "time", "device_info", "dev_addr", "relay_rx_info", "join_server_context"]
DEDUPLICATION_ID_FIELD_NUMBER: _ClassVar[int]
TIME_FIELD_NUMBER: _ClassVar[int]
DEVICE_INFO_FIELD_NUMBER: _ClassVar[int]
DEV_ADDR_FIELD_NUMBER: _ClassVar[int]
RELAY_RX_INFO_FIELD_NUMBER: _ClassVar[int]
JOIN_SERVER_CONTEXT_FIELD_NUMBER: _ClassVar[int]
deduplication_id: str
time: _timestamp_pb2.Timestamp
device_info: DeviceInfo
dev_addr: str
relay_rx_info: UplinkRelayRxInfo
def __init__(self, deduplication_id: _Optional[str] = ..., time: _Optional[_Union[_timestamp_pb2.Timestamp, _Mapping]] = ..., device_info: _Optional[_Union[DeviceInfo, _Mapping]] = ..., dev_addr: _Optional[str] = ..., relay_rx_info: _Optional[_Union[UplinkRelayRxInfo, _Mapping]] = ...) -> None: ...
join_server_context: JoinServerContext
def __init__(self, deduplication_id: _Optional[str] = ..., time: _Optional[_Union[_timestamp_pb2.Timestamp, _Mapping]] = ..., device_info: _Optional[_Union[DeviceInfo, _Mapping]] = ..., dev_addr: _Optional[str] = ..., relay_rx_info: _Optional[_Union[UplinkRelayRxInfo, _Mapping]] = ..., join_server_context: _Optional[_Union[JoinServerContext, _Mapping]] = ...) -> None: ...
class AckEvent(_message.Message):
__slots__ = ["deduplication_id", "time", "device_info", "queue_item_id", "acknowledged", "f_cnt_down"]

View File

@ -165,6 +165,17 @@ service DeviceService {
get : "/api/devices/{dev_eui}/queue"
};
}
// GetNextFCntDown returns the next FCntDown to use for enqueing encrypted
// downlinks. The difference with the DeviceActivation f_cont_down is that
// this method takes potential existing queue-items into account.
rpc GetNextFCntDown(GetDeviceNextFCntDownRequest)
returns (GetDeviceNextFCntDownResponse) {
option (google.api.http) = {
post : "/api/devices/{dev_eui}/get-next-f-cnt-down"
body : "*"
};
}
}
message Device {
@ -504,12 +515,20 @@ message DeviceQueueItem {
google.protobuf.Struct object = 6;
// Is pending.
// This is set to true when the downlink is pending.
// This is set by ChirpStack to true when the downlink is pending (e.g. it
// has been sent, but a confirmation is still pending).
bool is_pending = 7;
// Downlink frame-counter.
// This is set when the payload has been sent as downlink.
// Do not set this for plain-text data payloads. It will be automatically set
// by ChirpStack when the payload has been sent as downlink.
uint32 f_cnt_down = 8;
// Is encrypted.
// This must be set to true if the end-application has already encrypted
// the data payload. In this case, the f_cnt_down field must be set to
// the corresponding frame-counter which has been used during the encryption.
bool is_encrypted = 9;
}
message EnqueueDeviceQueueItemRequest { DeviceQueueItem queue_item = 1; }
@ -544,3 +563,13 @@ message FlushDevNoncesRequest {
// Device EUI (EUI64).
string dev_eui = 1;
}
message GetDeviceNextFCntDownRequest {
// Device EUI (EUI64).
string dev_eui = 1;
}
message GetDeviceNextFCntDownResponse {
// FCntDown.
uint32 f_cnt_down = 1;
}

View File

@ -55,6 +55,9 @@ enum LogCode {
// Relay new end-device.
RELAY_NEW_END_DEVICE = 9;
// Downlink frame-counter.
F_CNT_DOWN = 10;
}
// Device information.
@ -111,6 +114,15 @@ message UplinkRelayRxInfo {
uint32 wor_channel = 6;
}
// Join-Server context.
message JoinServerContext {
// Session-key ID.
string session_key_id = 1;
// AppSKey envelope.
common.KeyEnvelope app_s_key = 2;
}
// UplinkEvent is the message sent when an uplink payload has been received.
message UplinkEvent {
// Deduplication ID (UUID).
@ -155,6 +167,12 @@ message UplinkEvent {
// Relay info.
UplinkRelayRxInfo relay_rx_info = 14;
// Join-Server context.
// A non-empty value indicatest that ChirpStack does not have access to
// the AppSKey and that the encryption / decryption of the payloads is
// the responsibility of the end-application.
JoinServerContext join_server_context = 15;
}
// JoinEvent is the message sent when a device joined the network.
@ -174,6 +192,12 @@ message JoinEvent {
// Relay info.
UplinkRelayRxInfo relay_rx_info = 5;
// Join-Server context.
// A non-empty value indicatest that ChirpStack does not have access to
// the AppSKey and that the encryption / decryption of the payloads is
// the responsibility of the end-application.
JoinServerContext join_server_context = 6;
}
// AckEvent is the message sent when a confirmation on a confirmed downlink

View File

@ -31,6 +31,9 @@ message DeviceSession {
// AppSKey envelope.
common.KeyEnvelope app_s_key = 8;
// JS Session Key ID.
bytes js_session_key_id = 42;
// Uplink frame-counter.
uint32 f_cnt_up = 9;

View File

@ -31,6 +31,7 @@ impl Into<String> for LogCode {
LogCode::UplinkFCntRetransmission => "UPLINK_F_CNT_RETRANSMISSION",
LogCode::DownlinkGateway => "DOWNLINK_GATEWAY",
LogCode::RelayNewEndDevice => "RELAY_NEW_END_DEVICE",
LogCode::FCntDown => "F_CNT_DOWN",
}
.to_string()
}

View File

@ -0,0 +1,2 @@
alter table device_queue_item
drop column is_encrypted;

View File

@ -0,0 +1,5 @@
alter table device_queue_item
add column is_encrypted boolean default false not null;
alter table device_queue_item
alter column is_encrypted drop default;

View File

@ -1,3 +1,4 @@
use std::cmp;
use std::collections::HashSet;
use std::str::FromStr;
use std::time::SystemTime;
@ -1040,6 +1041,12 @@ impl DeviceService for Device {
dev_eui,
f_port: req_qi.f_port as i16,
confirmed: req_qi.confirmed,
is_encrypted: req_qi.is_encrypted,
f_cnt_down: if req_qi.is_encrypted {
Some(req_qi.f_cnt_down.into())
} else {
None
},
data,
..Default::default()
};
@ -1112,10 +1119,8 @@ impl DeviceService for Device {
data: qi.data.clone(),
object: None,
is_pending: qi.is_pending,
f_cnt_down: match qi.f_cnt_down {
None => 0,
Some(v) => v as u32,
},
f_cnt_down: qi.f_cnt_down.unwrap_or(0) as u32,
is_encrypted: qi.is_encrypted,
})
.collect(),
});
@ -1124,6 +1129,36 @@ impl DeviceService for Device {
Ok(resp)
}
async fn get_next_f_cnt_down(
&self,
request: Request<api::GetDeviceNextFCntDownRequest>,
) -> Result<Response<api::GetDeviceNextFCntDownResponse>, Status> {
let req = request.get_ref();
let dev_eui = EUI64::from_str(&req.dev_eui).map_err(|e| e.status())?;
self.validator
.validate(
request.extensions(),
validator::ValidateDeviceAccess::new(validator::Flag::Read, dev_eui),
)
.await?;
let ds = device_session::get(&dev_eui).await.unwrap_or_default();
let max_f_cnt_down_queue = device_queue::get_max_f_cnt_down(dev_eui)
.await
.map_err(|e| e.status())?
.unwrap_or_default() as u32;
let mut resp = Response::new(api::GetDeviceNextFCntDownResponse {
f_cnt_down: cmp::max(ds.get_a_f_cnt_down(), max_f_cnt_down_queue + 1),
});
resp.metadata_mut()
.insert("x-log-dev_eui", req.dev_eui.parse().unwrap());
Ok(resp)
}
}
#[cfg(test)]
@ -1407,6 +1442,19 @@ pub mod test {
get_activation_resp.get_ref().device_activation
);
// get next FCntDown (from device-session)
let get_next_f_cnt_req = get_request(
&u.id,
api::GetDeviceNextFCntDownRequest {
dev_eui: "0102030405060708".into(),
},
);
let get_next_f_cnt_resp = service
.get_next_f_cnt_down(get_next_f_cnt_req)
.await
.unwrap();
assert_eq!(1, get_next_f_cnt_resp.get_ref().f_cnt_down);
// deactivate
let deactivate_req = get_request(
&u.id,
@ -1455,6 +1503,22 @@ pub mod test {
);
let _ = service.enqueue(enqueue_req).await.unwrap();
let enqueue_req = get_request(
&u.id,
api::EnqueueDeviceQueueItemRequest {
queue_item: Some(api::DeviceQueueItem {
dev_eui: "0102030405060708".into(),
confirmed: true,
f_port: 2,
f_cnt_down: 10,
data: vec![1, 2, 3],
is_encrypted: true,
..Default::default()
}),
},
);
let _ = service.enqueue(enqueue_req).await.unwrap();
// get queue
let get_queue_req = get_request(
&u.id,
@ -1465,9 +1529,27 @@ pub mod test {
);
let get_queue_resp = service.get_queue(get_queue_req).await.unwrap();
let get_queue_resp = get_queue_resp.get_ref();
assert_eq!(1, get_queue_resp.total_count);
assert_eq!(1, get_queue_resp.result.len());
assert_eq!(2, get_queue_resp.total_count);
assert_eq!(2, get_queue_resp.result.len());
assert_eq!(vec![3, 2, 1], get_queue_resp.result[0].data);
assert_eq!(false, get_queue_resp.result[0].is_encrypted);
assert_eq!(0, get_queue_resp.result[0].f_cnt_down);
assert_eq!(vec![1, 2, 3], get_queue_resp.result[1].data);
assert_eq!(true, get_queue_resp.result[1].is_encrypted);
assert_eq!(10, get_queue_resp.result[1].f_cnt_down);
// get next FCntDown (from queue)
let get_next_f_cnt_req = get_request(
&u.id,
api::GetDeviceNextFCntDownRequest {
dev_eui: "0102030405060708".into(),
},
);
let get_next_f_cnt_resp = service
.get_next_f_cnt_down(get_next_f_cnt_req)
.await
.unwrap();
assert_eq!(11, get_next_f_cnt_resp.get_ref().f_cnt_down);
// flush queue
let flush_queue_req = get_request(

View File

@ -413,9 +413,16 @@ impl Data {
},
};
// The queue item should fit within the max payload size and should not be pending
// already.
if qi.data.len() <= max_payload_size && !qi.is_pending {
// The queue item:
// * should fit within the max payload size
// * should not be pending
// * in case encrypted, should have a valid FCntDown
if qi.data.len() <= max_payload_size
&& !qi.is_pending
&& !(qi.is_encrypted
&& (qi.f_cnt_down.unwrap_or_default() as u32)
< self.device_session.get_a_f_cnt_down())
{
trace!(id = %qi.id, more_in_queue = more_in_queue, "Found device queue-item for downlink");
self.device_queue_item = Some(qi);
self.more_device_queue_items = more_in_queue;
@ -499,6 +506,44 @@ impl Data {
continue;
}
// Handling encrypted payload with invalid FCntDown
if qi.is_encrypted
&& (qi.f_cnt_down.unwrap_or_default() as u32)
< self.device_session.get_a_f_cnt_down()
{
device_queue::delete_item(&qi.id)
.await
.context("Delete device queue-item")?;
let pl = integration_pb::LogEvent {
time: Some(Utc::now().into()),
device_info: Some(device_info.clone()),
level: integration_pb::LogLevel::Error.into(),
code: integration_pb::LogCode::FCntDown.into(),
description: "Device queue-item discarded because the frame-counter is invalid"
.to_string(),
context: [
(
"device_f_cnt_down".to_string(),
self.device_session.get_a_f_cnt_down().to_string(),
),
(
"queue_item_f_cnt_down".to_string(),
qi.f_cnt_down.unwrap_or_default().to_string(),
),
("queue_item_id".to_string(), qi.id.to_string()),
]
.iter()
.cloned()
.collect(),
};
integration::log_event(self.application.id, &self.device.variables, &pl).await;
warn!(dev_eui = %self.device.dev_eui, device_queue_item_id = %qi.id, "Device queue-item discarded because of invalid frame-counter");
continue;
}
}
}
@ -650,7 +695,10 @@ impl Data {
if qi.data.len() <= item.remaining_payload_size {
// Set the device-queue item.
mac_pl.f_port = Some(qi.f_port as u8);
mac_pl.fhdr.f_cnt = self.device_session.get_a_f_cnt_down();
mac_pl.fhdr.f_cnt = match qi.is_encrypted {
true => qi.f_cnt_down.unwrap_or_default() as u32,
false => self.device_session.get_a_f_cnt_down(),
};
mac_pl.frm_payload = Some(lrwn::FRMPayload::Raw(qi.data.clone()));
if qi.confirmed {
@ -673,13 +721,18 @@ impl Data {
};
// Encrypt FRMPayload.
let qi_encrypted = match &self.device_queue_item {
Some(v) => v.is_encrypted,
None => false,
};
if mac_size > 15 {
// Encrypt mac-commands.
phy.encrypt_frm_payload(&lrwn::AES128Key::from_slice(
&self.device_session.nwk_s_enc_key,
)?)
.context("Encrypt frm_payload mac-commands")?;
} else {
} else if self.device_queue_item.is_some() && !qi_encrypted {
// Encrypt application payload.
if let Some(key_env) = &self.device_session.app_s_key {
let app_s_key = lrwn::AES128Key::from_slice(&key_env.aes_key)?;
@ -781,18 +834,12 @@ impl Data {
// * get_next_device_queue_item is called on next downlink
// * as is_pending was already set to true, a negative ack event is sent
// and item is popped from the queue
qi.f_cnt_down = Some(if self
.device_session
.mac_version()
.to_string()
.starts_with("1.0")
{
self.device_session.n_f_cnt_down
} else {
self.device_session.a_f_cnt_down
} as i64);
*qi = device_queue::update_item(qi.clone()).await?;
// Do not update the frame-counter in case the queue-item is encrypted.
if !qi.is_encrypted {
qi.f_cnt_down = Some(self.device_session.get_a_f_cnt_down() as i64);
*qi = device_queue::update_item(qi.clone()).await?;
}
}
Ok(())
@ -816,7 +863,13 @@ impl Data {
nwk_s_enc_key: self.device_session.nwk_s_enc_key.clone(),
downlink_frame: Some(self.downlink_frame.clone()),
n_f_cnt_down: self.device_session.n_f_cnt_down,
a_f_cnt_down: self.device_session.get_a_f_cnt_down(),
a_f_cnt_down: match &self.device_queue_item {
Some(v) => match v.is_encrypted {
true => v.f_cnt_down.unwrap_or_default() as u32,
false => self.device_session.get_a_f_cnt_down(),
},
None => self.device_session.get_a_f_cnt_down(),
},
..Default::default()
})
.await
@ -2476,6 +2529,261 @@ mod test {
use super::*;
use crate::test;
use lrwn::EUI64;
use tokio::time::sleep;
use uuid::Uuid;
#[tokio::test]
async fn test_get_next_device_queue_item() {
let _guard = test::prepare().await;
let t = tenant::create(tenant::Tenant {
name: "test-tenant".into(),
..Default::default()
})
.await
.unwrap();
let dp = device_profile::create(device_profile::DeviceProfile {
name: "dp".into(),
tenant_id: t.id,
is_relay: true,
..Default::default()
})
.await
.unwrap();
let app = application::create(application::Application {
name: "test-app".into(),
tenant_id: t.id,
..Default::default()
})
.await
.unwrap();
let d = device::create(device::Device {
dev_eui: EUI64::from_be_bytes([1, 1, 1, 1, 1, 1, 1, 1]),
name: "dev".into(),
application_id: app.id,
device_profile_id: dp.id,
..Default::default()
})
.await
.unwrap();
let ds = internal::DeviceSession {
n_f_cnt_down: 10,
a_f_cnt_down: 10,
..Default::default()
};
struct Test {
name: String,
max_payload_size: usize,
queue_items: Vec<device_queue::DeviceQueueItem>,
expected_queue_item: Option<device_queue::DeviceQueueItem>,
expected_ack_event: Option<integration_pb::AckEvent>,
expected_log_event: Option<integration_pb::LogEvent>,
}
let qi_id = Uuid::new_v4();
let tests = vec![
Test {
name: "max payload size error".into(),
max_payload_size: 10,
queue_items: vec![device_queue::DeviceQueueItem {
id: qi_id,
dev_eui: d.dev_eui,
f_port: 1,
data: vec![1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11],
..Default::default()
}],
expected_queue_item: None,
expected_ack_event: None,
expected_log_event: Some(integration_pb::LogEvent {
device_info: Some(integration_pb::DeviceInfo {
tenant_id: t.id.to_string(),
tenant_name: t.name.clone(),
application_id: app.id.to_string(),
application_name: app.name.clone(),
device_profile_id: dp.id.to_string(),
device_profile_name: dp.name.clone(),
device_name: d.name.clone(),
dev_eui: d.dev_eui.to_string(),
..Default::default()
}),
level: integration_pb::LogLevel::Error.into(),
code: integration_pb::LogCode::DownlinkPayloadSize.into(),
description:
"Device queue-item discarded because it exceeds the max. payload size"
.into(),
context: [
("item_size".to_string(), "11".to_string()),
("queue_item_id".to_string(), qi_id.to_string()),
("max_payload_size".to_string(), "10".to_string()),
]
.iter()
.cloned()
.collect(),
..Default::default()
}),
},
Test {
name: "is pending".into(),
max_payload_size: 10,
queue_items: vec![device_queue::DeviceQueueItem {
id: qi_id,
dev_eui: d.dev_eui,
f_port: 1,
f_cnt_down: Some(10),
data: vec![1, 2, 3],
is_pending: true,
..Default::default()
}],
expected_queue_item: None,
expected_log_event: None,
expected_ack_event: Some(integration_pb::AckEvent {
device_info: Some(integration_pb::DeviceInfo {
tenant_id: t.id.to_string(),
tenant_name: t.name.clone(),
application_id: app.id.to_string(),
application_name: app.name.clone(),
device_profile_id: dp.id.to_string(),
device_profile_name: dp.name.clone(),
device_name: d.name.clone(),
dev_eui: d.dev_eui.to_string(),
..Default::default()
}),
queue_item_id: qi_id.to_string(),
acknowledged: false,
f_cnt_down: 10,
..Default::default()
}),
},
Test {
name: "invalid frame-counter".into(),
max_payload_size: 10,
queue_items: vec![device_queue::DeviceQueueItem {
id: qi_id,
dev_eui: d.dev_eui,
f_port: 1,
data: vec![1, 2, 3],
f_cnt_down: Some(5),
is_encrypted: true,
..Default::default()
}],
expected_queue_item: None,
expected_ack_event: None,
expected_log_event: Some(integration_pb::LogEvent {
device_info: Some(integration_pb::DeviceInfo {
tenant_id: t.id.to_string(),
tenant_name: t.name.clone(),
application_id: app.id.to_string(),
application_name: app.name.clone(),
device_profile_id: dp.id.to_string(),
device_profile_name: dp.name.clone(),
device_name: d.name.clone(),
dev_eui: d.dev_eui.to_string(),
..Default::default()
}),
level: integration_pb::LogLevel::Error.into(),
code: integration_pb::LogCode::FCntDown.into(),
description: "Device queue-item discarded because the frame-counter is invalid"
.into(),
context: [
("queue_item_id".to_string(), qi_id.to_string()),
("device_f_cnt_down".to_string(), "10".to_string()),
("queue_item_f_cnt_down".to_string(), "5".to_string()),
]
.iter()
.cloned()
.collect(),
..Default::default()
}),
},
Test {
name: "valid payload".into(),
max_payload_size: 10,
queue_items: vec![device_queue::DeviceQueueItem {
id: qi_id,
dev_eui: d.dev_eui,
f_port: 1,
data: vec![1, 2, 3],
..Default::default()
}],
expected_queue_item: Some(device_queue::DeviceQueueItem {
id: qi_id,
dev_eui: d.dev_eui,
f_port: 1,
data: vec![1, 2, 3],
..Default::default()
}),
expected_log_event: None,
expected_ack_event: None,
},
];
for tst in &tests {
println!("> {}", tst.name);
integration::set_mock().await;
integration::mock::reset().await;
device_queue::flush_for_dev_eui(&d.dev_eui).await.unwrap();
for qi in &tst.queue_items {
device_queue::enqueue_item(qi.clone()).await.unwrap();
}
let mut ctx = Data {
relay_context: None,
uplink_frame_set: None,
tenant: t.clone(),
application: app.clone(),
device_profile: dp.clone(),
device: d.clone(),
device_session: ds.clone(),
network_conf: config::get_region_network("eu868").unwrap(),
region_conf: region::get("eu868").unwrap(),
must_send: false,
must_ack: false,
mac_commands: vec![],
device_gateway_rx_info: None,
downlink_gateway: None,
downlink_frame: Default::default(),
downlink_frame_items: vec![DownlinkFrameItem {
downlink_frame_item: Default::default(),
remaining_payload_size: tst.max_payload_size,
}],
immediately: false,
device_queue_item: None,
more_device_queue_items: false,
};
ctx.get_next_device_queue_item().await.unwrap();
// Integrations are handled async.
sleep(Duration::from_millis(100)).await;
if let Some(log) = &tst.expected_log_event {
let mut event = integration::mock::get_log_event().await.unwrap();
assert_ne!(None, event.time);
event.time = None;
assert_eq!(log, &event);
}
if let Some(ack) = &tst.expected_ack_event {
let mut event = integration::mock::get_ack_event().await.unwrap();
assert_ne!(None, event.time);
event.time = None;
assert_eq!(ack, &event);
}
if let Some(qi) = &tst.expected_queue_item {
assert_ne!(None, ctx.device_queue_item);
assert_eq!(qi.id, ctx.device_queue_item.as_ref().unwrap().id);
}
}
}
#[test]
fn test_filter_mac_commands() {

View File

@ -389,7 +389,7 @@ impl TxAck {
trace!("Incrementing a_f_cnt_down");
let ds = self.device_session.as_mut().unwrap();
ds.set_a_f_cnt_down(ds.get_a_f_cnt_down() + 1);
ds.set_a_f_cnt_down(self.downlink_frame.as_ref().unwrap().a_f_cnt_down + 1);
Ok(())
}

View File

@ -108,6 +108,20 @@ impl IntegrationTrait for Integration {
}
}
pub async fn get_join_event() -> Option<integration::JoinEvent> {
if JOIN_EVENTS.read().await.is_empty() {
return None;
}
JOIN_EVENTS
.write()
.await
.drain(0..1)
.collect::<Vec<integration::JoinEvent>>()
.first()
.cloned()
}
pub async fn get_uplink_event() -> Option<integration::UplinkEvent> {
if UPLINK_EVENTS.read().await.is_empty() {
return None;
@ -122,6 +136,34 @@ pub async fn get_uplink_event() -> Option<integration::UplinkEvent> {
.cloned()
}
pub async fn get_ack_event() -> Option<integration::AckEvent> {
if ACK_EVENTS.read().await.is_empty() {
return None;
}
ACK_EVENTS
.write()
.await
.drain(0..1)
.collect::<Vec<integration::AckEvent>>()
.first()
.cloned()
}
pub async fn get_log_event() -> Option<integration::LogEvent> {
if LOG_EVENTS.read().await.is_empty() {
return None;
}
LOG_EVENTS
.write()
.await
.drain(0..1)
.collect::<Vec<integration::LogEvent>>()
.first()
.cloned()
}
pub async fn get_join_events() -> Vec<integration::JoinEvent> {
JOIN_EVENTS.write().await.drain(..).collect()
}

View File

@ -1,6 +1,6 @@
use anyhow::Result;
use chrono::{DateTime, Utc};
use diesel::prelude::*;
use diesel::{dsl, prelude::*};
use tokio::task;
use tracing::info;
use uuid::Uuid;
@ -22,6 +22,7 @@ pub struct DeviceQueueItem {
pub is_pending: bool,
pub f_cnt_down: Option<i64>,
pub timeout_after: Option<DateTime<Utc>>,
pub is_encrypted: bool,
}
impl DeviceQueueItem {
@ -32,6 +33,12 @@ impl DeviceQueueItem {
));
}
if self.is_encrypted && self.f_cnt_down.is_none() {
return Err(Error::Validation(
"FCntDown must be set for encrypted queue-items".to_string(),
));
}
Ok(())
}
}
@ -50,6 +57,7 @@ impl Default for DeviceQueueItem {
is_pending: false,
f_cnt_down: None,
timeout_after: None,
is_encrypted: false,
}
}
}
@ -211,6 +219,19 @@ pub async fn get_pending_for_dev_eui(dev_eui: &EUI64) -> Result<DeviceQueueItem,
.await?
}
pub async fn get_max_f_cnt_down(dev_eui: EUI64) -> Result<Option<i64>, Error> {
task::spawn_blocking({
move || -> Result<Option<i64>, Error> {
let mut c = get_db_conn()?;
Ok(device_queue_item::dsl::device_queue_item
.select(dsl::max(device_queue_item::f_cnt_down))
.filter(device_queue_item::dsl::dev_eui.eq(dev_eui))
.first(&mut c)?)
}
})
.await?
}
#[cfg(test)]
pub mod test {
use super::*;
@ -302,4 +323,34 @@ pub mod test {
flush_for_dev_eui(&d.dev_eui).await.unwrap();
assert_eq!(true, delete_item(&qi.id).await.is_err());
}
#[tokio::test]
async fn test_get_max_f_cnt_down() {
let _guard = test::prepare().await;
let dp = storage::device_profile::test::create_device_profile(None).await;
let d = storage::device::test::create_device(
EUI64::from_be_bytes([1, 2, 3, 4, 5, 6, 7, 8]),
dp.id,
None,
)
.await;
// create
let mut qi = DeviceQueueItem {
dev_eui: d.dev_eui,
f_port: 10,
data: vec![0x01, 0x02, 0x03],
..Default::default()
};
qi = enqueue_item(qi).await.unwrap();
// No max_f_cnt.
let max_f_cnt = get_max_f_cnt_down(d.dev_eui).await.unwrap();
assert_eq!(None, max_f_cnt);
qi.f_cnt_down = Some(10);
update_item(qi).await.unwrap();
let max_f_cnt = get_max_f_cnt_down(d.dev_eui).await.unwrap();
assert_eq!(Some(10), max_f_cnt);
}
}

View File

@ -4,6 +4,7 @@ diesel::table! {
api_key (id) {
id -> Uuid,
created_at -> Timestamptz,
#[max_length = 100]
name -> Varchar,
is_admin -> Bool,
tenant_id -> Nullable<Uuid>,
@ -16,6 +17,7 @@ diesel::table! {
tenant_id -> Uuid,
created_at -> Timestamptz,
updated_at -> Timestamptz,
#[max_length = 100]
name -> Varchar,
description -> Text,
mqtt_tls_cert -> Nullable<Bytea>,
@ -25,6 +27,7 @@ diesel::table! {
diesel::table! {
application_integration (application_id, kind) {
application_id -> Uuid,
#[max_length = 20]
kind -> Varchar,
created_at -> Timestamptz,
updated_at -> Timestamptz,
@ -41,6 +44,7 @@ diesel::table! {
updated_at -> Timestamptz,
last_seen_at -> Nullable<Timestamptz>,
scheduler_run_after -> Nullable<Timestamptz>,
#[max_length = 100]
name -> Varchar,
description -> Text,
external_power_source -> Bool,
@ -51,6 +55,7 @@ diesel::table! {
longitude -> Nullable<Float8>,
altitude -> Nullable<Float4>,
dev_addr -> Nullable<Bytea>,
#[max_length = 1]
enabled_class -> Bpchar,
skip_fcnt_check -> Bool,
is_disabled -> Bool,
@ -78,11 +83,17 @@ diesel::table! {
tenant_id -> Uuid,
created_at -> Timestamptz,
updated_at -> Timestamptz,
#[max_length = 100]
name -> Varchar,
#[max_length = 10]
region -> Varchar,
#[max_length = 10]
mac_version -> Varchar,
#[max_length = 20]
reg_params_revision -> Varchar,
#[max_length = 100]
adr_algorithm_id -> Varchar,
#[max_length = 20]
payload_codec_runtime -> Varchar,
uplink_interval -> Int4,
device_status_req_interval -> Int4,
@ -104,6 +115,7 @@ diesel::table! {
description -> Text,
measurements -> Jsonb,
auto_detect_measurements -> Bool,
#[max_length = 100]
region_config_id -> Nullable<Varchar>,
is_relay -> Bool,
is_relay_ed -> Bool,
@ -135,14 +147,22 @@ diesel::table! {
id -> Text,
created_at -> Timestamptz,
updated_at -> Timestamptz,
#[max_length = 100]
name -> Varchar,
description -> Text,
#[max_length = 100]
vendor -> Varchar,
#[max_length = 100]
firmware -> Varchar,
#[max_length = 10]
region -> Varchar,
#[max_length = 10]
mac_version -> Varchar,
#[max_length = 20]
reg_params_revision -> Varchar,
#[max_length = 100]
adr_algorithm_id -> Varchar,
#[max_length = 20]
payload_codec_runtime -> Varchar,
payload_codec_script -> Text,
uplink_interval -> Int4,
@ -177,6 +197,7 @@ diesel::table! {
is_pending -> Bool,
f_cnt_down -> Nullable<Int8>,
timeout_after -> Nullable<Timestamptz>,
is_encrypted -> Bool,
}
}
@ -187,6 +208,7 @@ diesel::table! {
created_at -> Timestamptz,
updated_at -> Timestamptz,
last_seen_at -> Nullable<Timestamptz>,
#[max_length = 100]
name -> Varchar,
description -> Text,
latitude -> Float8,
@ -205,16 +227,20 @@ diesel::table! {
application_id -> Uuid,
created_at -> Timestamptz,
updated_at -> Timestamptz,
#[max_length = 100]
name -> Varchar,
#[max_length = 10]
region -> Varchar,
mc_addr -> Bytea,
mc_nwk_s_key -> Bytea,
mc_app_s_key -> Bytea,
f_cnt -> Int8,
#[max_length = 1]
group_type -> Bpchar,
dr -> Int2,
frequency -> Int8,
class_b_ping_slot_period -> Int4,
#[max_length = 20]
class_c_scheduling_type -> Varchar,
}
}
@ -262,6 +288,7 @@ diesel::table! {
id -> Uuid,
created_at -> Timestamptz,
updated_at -> Timestamptz,
#[max_length = 100]
name -> Varchar,
description -> Text,
can_have_gateways -> Bool,
@ -294,6 +321,7 @@ diesel::table! {
is_active -> Bool,
email -> Text,
email_verified -> Bool,
#[max_length = 200]
password_hash -> Varchar,
note -> Text,
}

View File

@ -149,6 +149,25 @@ pub fn no_uplink_event() -> Validator {
})
}
pub fn join_event(join: integration_pb::JoinEvent) -> Validator {
Box::new(move || {
let join = join.clone();
Box::pin(async move {
// Integration events are handled async.
sleep(Duration::from_millis(100)).await;
let mut event = mock::get_join_event().await.unwrap();
assert_ne!("", event.deduplication_id);
assert_ne!(None, event.time);
event.deduplication_id = "".into();
event.time = None;
assert_eq!(join, event);
})
})
}
pub fn uplink_event(up: integration_pb::UplinkEvent) -> Validator {
Box::new(move || {
let up = up.clone();

View File

@ -1653,6 +1653,334 @@ async fn test_lorawan_10_uplink() {
}
}
#[tokio::test]
async fn test_lorawan_10_end_to_end_enc() {
let _guard = test::prepare().await;
let t = tenant::create(tenant::Tenant {
name: "tenant".into(),
can_have_gateways: true,
..Default::default()
})
.await
.unwrap();
let gw = gateway::create(gateway::Gateway {
name: "gateway".into(),
tenant_id: t.id.clone(),
gateway_id: EUI64::from_be_bytes([1, 2, 3, 4, 5, 6, 7, 8]),
..Default::default()
})
.await
.unwrap();
let app = application::create(application::Application {
name: "app".into(),
tenant_id: t.id.clone(),
..Default::default()
})
.await
.unwrap();
let dp = device_profile::create(device_profile::DeviceProfile {
name: "dp".into(),
tenant_id: t.id.clone(),
region: lrwn::region::CommonName::EU868,
mac_version: lrwn::region::MacVersion::LORAWAN_1_0_4,
reg_params_revision: lrwn::region::Revision::RP002_1_0_3,
supports_otaa: true,
..Default::default()
})
.await
.unwrap();
let dev = device::create(device::Device {
name: "device".into(),
application_id: app.id.clone(),
device_profile_id: dp.id.clone(),
dev_eui: EUI64::from_be_bytes([2, 2, 3, 4, 5, 6, 7, 8]),
enabled_class: DeviceClass::A,
..Default::default()
})
.await
.unwrap();
let mut rx_info = gw::UplinkRxInfo {
gateway_id: gw.gateway_id.to_string(),
location: Some(Default::default()),
..Default::default()
};
rx_info
.metadata
.insert("region_config_id".to_string(), "eu868".to_string());
rx_info
.metadata
.insert("region_common_name".to_string(), "EU868".to_string());
let mut tx_info = gw::UplinkTxInfo {
frequency: 868100000,
..Default::default()
};
uplink::helpers::set_uplink_modulation(&"eu868", &mut tx_info, 0).unwrap();
let ds_sess_key_id = internal::DeviceSession {
dev_eui: vec![2, 2, 3, 4, 5, 6, 7, 8],
mac_version: common::MacVersion::Lorawan104.into(),
join_eui: vec![8, 7, 6, 5, 4, 3, 2, 1],
dev_addr: vec![1, 2, 3, 4],
f_nwk_s_int_key: vec![1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16],
s_nwk_s_int_key: vec![1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16],
nwk_s_enc_key: vec![1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16],
app_s_key: None,
js_session_key_id: vec![1, 2, 3],
f_cnt_up: 8,
n_f_cnt_down: 5,
enabled_uplink_channel_indices: vec![0, 1, 2],
rx1_delay: 1,
rx2_frequency: 869525000,
region_config_id: "eu868".into(),
..Default::default()
};
let ds_app_s_key = internal::DeviceSession {
dev_eui: vec![2, 2, 3, 4, 5, 6, 7, 8],
mac_version: common::MacVersion::Lorawan104.into(),
join_eui: vec![8, 7, 6, 5, 4, 3, 2, 1],
dev_addr: vec![1, 2, 3, 4],
f_nwk_s_int_key: vec![1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16],
s_nwk_s_int_key: vec![1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16],
nwk_s_enc_key: vec![1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16],
app_s_key: Some(common::KeyEnvelope {
kek_label: "kek-label".into(),
aes_key: vec![1, 2, 3],
}),
f_cnt_up: 8,
n_f_cnt_down: 5,
enabled_uplink_channel_indices: vec![0, 1, 2],
rx1_delay: 1,
rx2_frequency: 869525000,
region_config_id: "eu868".into(),
..Default::default()
};
let tests = vec![
Test {
name: "end-to-end encryption with session key id".into(),
device_queue_items: vec![],
before_func: None,
after_func: None,
device_session: Some(ds_sess_key_id.clone()),
tx_info: tx_info.clone(),
rx_info: rx_info.clone(),
phy_payload: lrwn::PhyPayload {
mhdr: lrwn::MHDR {
m_type: lrwn::MType::UnconfirmedDataUp,
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: Some(lrwn::FRMPayload::Raw(vec![1, 2, 3, 4])),
}),
mic: Some([104, 147, 35, 121]),
},
assert: vec![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,
dr: 0,
data: vec![1, 2, 3, 4],
join_server_context: Some(integration_pb::JoinServerContext {
session_key_id: "010203".into(),
..Default::default()
}),
..Default::default()
})],
},
Test {
name: "end-to-end encryption with AppSKey".into(),
device_queue_items: vec![],
before_func: None,
after_func: None,
device_session: Some(ds_app_s_key.clone()),
tx_info: tx_info.clone(),
rx_info: rx_info.clone(),
phy_payload: lrwn::PhyPayload {
mhdr: lrwn::MHDR {
m_type: lrwn::MType::UnconfirmedDataUp,
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: Some(lrwn::FRMPayload::Raw(vec![1, 2, 3, 4])),
}),
mic: Some([104, 147, 35, 121]),
},
assert: vec![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,
dr: 0,
data: vec![1, 2, 3, 4],
join_server_context: Some(integration_pb::JoinServerContext {
app_s_key: Some(common::KeyEnvelope {
kek_label: "kek-label".into(),
aes_key: vec![1, 2, 3],
}),
..Default::default()
}),
..Default::default()
})],
},
Test {
name: "end-to-end encryption using AppSkey + encrypted downlink".into(),
device_queue_items: vec![device_queue::DeviceQueueItem {
id: Uuid::nil(),
dev_eui: dev.dev_eui.clone(),
f_port: 1,
data: vec![1, 2, 3, 4],
f_cnt_down: Some(10),
is_encrypted: true,
..Default::default()
}],
before_func: None,
after_func: None,
device_session: Some(ds_app_s_key.clone()),
tx_info: tx_info.clone(),
rx_info: rx_info.clone(),
phy_payload: lrwn::PhyPayload {
mhdr: lrwn::MHDR {
m_type: lrwn::MType::UnconfirmedDataUp,
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: Some(lrwn::FRMPayload::Raw(vec![1, 2, 3, 4])),
}),
mic: Some([104, 147, 35, 121]),
},
assert: vec![
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,
dr: 0,
data: vec![1, 2, 3, 4],
join_server_context: Some(integration_pb::JoinServerContext {
app_s_key: Some(common::KeyEnvelope {
kek_label: "kek-label".into(),
aes_key: vec![1, 2, 3],
}),
..Default::default()
}),
..Default::default()
}),
assert::f_cnt_up(dev.dev_eui.clone(), 11),
assert::n_f_cnt_down(dev.dev_eui.clone(), 5),
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: 10,
f_ctrl: lrwn::FCtrl {
adr: true,
..Default::default()
},
..Default::default()
},
f_port: Some(1),
frm_payload: Some(lrwn::FRMPayload::Raw(vec![1, 2, 3, 4])),
}),
mic: Some([8, 125, 131, 36]),
},
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: 10,
f_ctrl: lrwn::FCtrl {
adr: true,
..Default::default()
},
..Default::default()
},
f_port: Some(1),
frm_payload: Some(lrwn::FRMPayload::Raw(vec![1, 2, 3, 4])),
}),
mic: Some([8, 125, 131, 36]),
},
]),
],
},
];
for tst in &tests {
run_test(tst).await;
}
}
#[tokio::test]
async fn test_lorawan_11_uplink() {
let _guard = test::prepare().await;

View File

@ -9,6 +9,7 @@ mod class_a_test;
mod class_b_test;
mod class_c_test;
mod multicast_test;
mod otaa_js_test;
mod otaa_pr_test;
mod otaa_test;
mod relay_class_a_test;

View File

@ -0,0 +1,396 @@
use httpmock::prelude::*;
use uuid::Uuid;
use super::assert;
use crate::storage::{application, device, device_profile, gateway, reset_redis, tenant};
use crate::{
backend::joinserver, config, gateway::backend as gateway_backend, integration, region, test,
uplink,
};
use chirpstack_api::{common, gw, integration as integration_pb, internal};
use lrwn::{DevAddr, EUI64};
struct Test {
name: String,
tx_info: gw::UplinkTxInfo,
rx_info: gw::UplinkRxInfo,
phy_payload: lrwn::PhyPayload,
js_response: backend::JoinAnsPayload,
assert: Vec<assert::Validator>,
}
#[tokio::test]
async fn test_js() {
let _guard = test::prepare().await;
let t = tenant::create(tenant::Tenant {
name: "tenant".into(),
can_have_gateways: true,
..Default::default()
})
.await
.unwrap();
let gw = gateway::create(gateway::Gateway {
name: "gw".into(),
tenant_id: t.id.clone(),
gateway_id: EUI64::from_be_bytes([1, 2, 3, 4, 5, 6, 7, 8]),
..Default::default()
})
.await
.unwrap();
let dp = device_profile::create(device_profile::DeviceProfile {
name: "dp".into(),
tenant_id: t.id.clone(),
region: lrwn::region::CommonName::EU868,
mac_version: lrwn::region::MacVersion::LORAWAN_1_0_3,
reg_params_revision: lrwn::region::Revision::A,
supports_otaa: true,
..Default::default()
})
.await
.unwrap();
let app = application::create(application::Application {
name: "app".into(),
tenant_id: t.id.clone(),
..Default::default()
})
.await
.unwrap();
let dev = device::create(device::Device {
name: "dev".into(),
application_id: app.id.clone(),
device_profile_id: dp.id.clone(),
dev_eui: EUI64::from_be_bytes([1, 2, 3, 4, 5, 6, 7, 8]),
..Default::default()
})
.await
.unwrap();
let mut tx_info = gw::UplinkTxInfo {
frequency: 868100000,
..Default::default()
};
uplink::helpers::set_uplink_modulation(&"eu868", &mut tx_info, 0).unwrap();
let mut rx_info = gw::UplinkRxInfo {
gateway_id: gw.gateway_id.to_string(),
location: Some(Default::default()),
..Default::default()
};
rx_info
.metadata
.insert("region_config_id".to_string(), "eu868".to_string());
rx_info
.metadata
.insert("region_common_name".to_string(), "EU868".to_string());
let phy = lrwn::PhyPayload {
mhdr: lrwn::MHDR {
m_type: lrwn::MType::JoinRequest,
major: lrwn::Major::LoRaWANR1,
},
payload: lrwn::Payload::JoinRequest(lrwn::JoinRequestPayload {
join_eui: EUI64::from_be_bytes([1, 2, 3, 4, 5, 6, 7, 8]),
dev_eui: dev.dev_eui.clone(),
dev_nonce: 1,
}),
mic: Some([1, 2, 3, 4]),
};
let phy_ja = lrwn::PhyPayload {
mhdr: lrwn::MHDR {
m_type: lrwn::MType::JoinAccept,
major: lrwn::Major::LoRaWANR1,
},
payload: lrwn::Payload::JoinAccept(lrwn::JoinAcceptPayload {
join_nonce: 1,
home_netid: lrwn::NetID::from_be_bytes([0, 0, 0]),
devaddr: DevAddr::from_be_bytes([1, 2, 3, 4]),
dl_settings: lrwn::DLSettings {
opt_neg: false,
rx2_dr: 0,
rx1_dr_offset: 0,
},
rx_delay: 1,
cflist: None,
}),
mic: Some([1, 2, 3, 4]),
};
let tests = vec![
Test {
name: "test plain-text app_s_key".into(),
rx_info: rx_info.clone(),
tx_info: tx_info.clone(),
phy_payload: phy.clone(),
js_response: backend::JoinAnsPayload {
base: backend::BasePayloadResult {
base: backend::BasePayload {
sender_id: vec![1, 2, 3, 4, 5, 6, 7, 8],
receiver_id: vec![0, 0, 0],
message_type: backend::MessageType::JoinAns,
..Default::default()
},
result: backend::ResultPayload {
result_code: backend::ResultCode::Success,
..Default::default()
},
},
phy_payload: phy_ja.to_vec().unwrap(),
app_s_key: Some(backend::KeyEnvelope {
kek_label: "".into(),
aes_key: vec![1, 2, 3, 4, 5, 6, 7, 8, 1, 2, 3, 4, 5, 6, 7, 8],
}),
nwk_s_key: Some(backend::KeyEnvelope {
kek_label: "".into(),
aes_key: vec![1, 2, 3, 4, 5, 6, 7, 8, 1, 2, 3, 4, 5, 6, 7, 8],
}),
..Default::default()
},
assert: vec![
assert::device_session(
dev.dev_eui.clone(),
internal::DeviceSession {
dev_addr: vec![1, 2, 3, 4],
dev_eui: vec![1, 2, 3, 4, 5, 6, 7, 8],
join_eui: vec![1, 2, 3, 4, 5, 6, 7, 8],
mac_version: common::MacVersion::Lorawan103.into(),
f_nwk_s_int_key: vec![1, 2, 3, 4, 5, 6, 7, 8, 1, 2, 3, 4, 5, 6, 7, 8],
s_nwk_s_int_key: vec![1, 2, 3, 4, 5, 6, 7, 8, 1, 2, 3, 4, 5, 6, 7, 8],
nwk_s_enc_key: vec![1, 2, 3, 4, 5, 6, 7, 8, 1, 2, 3, 4, 5, 6, 7, 8],
app_s_key: Some(common::KeyEnvelope {
kek_label: "".into(),
aes_key: vec![1, 2, 3, 4, 5, 6, 7, 8, 1, 2, 3, 4, 5, 6, 7, 8],
}),
rx1_delay: 1,
rx2_frequency: 869525000,
enabled_uplink_channel_indices: vec![0, 1, 2],
nb_trans: 1,
region_config_id: "eu868".to_string(),
class_b_ping_slot_nb: 1,
..Default::default()
},
),
assert::join_event(integration_pb::JoinEvent {
device_info: Some(integration_pb::DeviceInfo {
tenant_id: t.id.to_string(),
tenant_name: t.name.clone(),
application_id: app.id.to_string(),
application_name: app.name.clone(),
device_profile_id: dp.id.to_string(),
device_profile_name: dp.name.clone(),
device_name: dev.name.clone(),
dev_eui: dev.dev_eui.to_string(),
device_class_enabled: common::DeviceClass::ClassA.into(),
..Default::default()
}),
dev_addr: "01020304".into(),
join_server_context: None,
..Default::default()
}),
],
},
Test {
name: "test session_key_id".into(),
rx_info: rx_info.clone(),
tx_info: tx_info.clone(),
phy_payload: phy.clone(),
js_response: backend::JoinAnsPayload {
base: backend::BasePayloadResult {
base: backend::BasePayload {
sender_id: vec![1, 2, 3, 4, 5, 6, 7, 8],
receiver_id: vec![0, 0, 0],
message_type: backend::MessageType::JoinAns,
..Default::default()
},
result: backend::ResultPayload {
result_code: backend::ResultCode::Success,
..Default::default()
},
},
phy_payload: phy_ja.to_vec().unwrap(),
session_key_id: vec![1, 2, 3, 4],
nwk_s_key: Some(backend::KeyEnvelope {
kek_label: "".into(),
aes_key: vec![1, 2, 3, 4, 5, 6, 7, 8, 1, 2, 3, 4, 5, 6, 7, 8],
}),
..Default::default()
},
assert: vec![
assert::device_session(
dev.dev_eui.clone(),
internal::DeviceSession {
dev_addr: vec![1, 2, 3, 4],
dev_eui: vec![1, 2, 3, 4, 5, 6, 7, 8],
join_eui: vec![1, 2, 3, 4, 5, 6, 7, 8],
mac_version: common::MacVersion::Lorawan103.into(),
f_nwk_s_int_key: vec![1, 2, 3, 4, 5, 6, 7, 8, 1, 2, 3, 4, 5, 6, 7, 8],
s_nwk_s_int_key: vec![1, 2, 3, 4, 5, 6, 7, 8, 1, 2, 3, 4, 5, 6, 7, 8],
nwk_s_enc_key: vec![1, 2, 3, 4, 5, 6, 7, 8, 1, 2, 3, 4, 5, 6, 7, 8],
js_session_key_id: vec![1, 2, 3, 4],
rx1_delay: 1,
rx2_frequency: 869525000,
enabled_uplink_channel_indices: vec![0, 1, 2],
nb_trans: 1,
region_config_id: "eu868".to_string(),
class_b_ping_slot_nb: 1,
..Default::default()
},
),
assert::join_event(integration_pb::JoinEvent {
device_info: Some(integration_pb::DeviceInfo {
tenant_id: t.id.to_string(),
tenant_name: t.name.clone(),
application_id: app.id.to_string(),
application_name: app.name.clone(),
device_profile_id: dp.id.to_string(),
device_profile_name: dp.name.clone(),
device_name: dev.name.clone(),
dev_eui: dev.dev_eui.to_string(),
device_class_enabled: common::DeviceClass::ClassA.into(),
..Default::default()
}),
dev_addr: "01020304".into(),
join_server_context: Some(integration_pb::JoinServerContext {
session_key_id: "01020304".into(),
..Default::default()
}),
..Default::default()
}),
],
},
Test {
name: "test encrypted app_s_key".into(),
rx_info: rx_info.clone(),
tx_info: tx_info.clone(),
phy_payload: phy.clone(),
js_response: backend::JoinAnsPayload {
base: backend::BasePayloadResult {
base: backend::BasePayload {
sender_id: vec![1, 2, 3, 4, 5, 6, 7, 8],
receiver_id: vec![0, 0, 0],
message_type: backend::MessageType::JoinAns,
..Default::default()
},
result: backend::ResultPayload {
result_code: backend::ResultCode::Success,
..Default::default()
},
},
phy_payload: phy_ja.to_vec().unwrap(),
app_s_key: Some(backend::KeyEnvelope {
kek_label: "kek-label".into(),
aes_key: vec![1, 2, 3, 4, 5, 6, 7, 8, 1, 2, 3, 4, 5, 6, 7, 8],
}),
nwk_s_key: Some(backend::KeyEnvelope {
kek_label: "".into(),
aes_key: vec![1, 2, 3, 4, 5, 6, 7, 8, 1, 2, 3, 4, 5, 6, 7, 8],
}),
..Default::default()
},
assert: vec![
assert::device_session(
dev.dev_eui.clone(),
internal::DeviceSession {
dev_addr: vec![1, 2, 3, 4],
dev_eui: vec![1, 2, 3, 4, 5, 6, 7, 8],
join_eui: vec![1, 2, 3, 4, 5, 6, 7, 8],
mac_version: common::MacVersion::Lorawan103.into(),
f_nwk_s_int_key: vec![1, 2, 3, 4, 5, 6, 7, 8, 1, 2, 3, 4, 5, 6, 7, 8],
s_nwk_s_int_key: vec![1, 2, 3, 4, 5, 6, 7, 8, 1, 2, 3, 4, 5, 6, 7, 8],
nwk_s_enc_key: vec![1, 2, 3, 4, 5, 6, 7, 8, 1, 2, 3, 4, 5, 6, 7, 8],
app_s_key: Some(common::KeyEnvelope {
kek_label: "kek-label".into(),
aes_key: vec![1, 2, 3, 4, 5, 6, 7, 8, 1, 2, 3, 4, 5, 6, 7, 8],
}),
rx1_delay: 1,
rx2_frequency: 869525000,
enabled_uplink_channel_indices: vec![0, 1, 2],
nb_trans: 1,
region_config_id: "eu868".to_string(),
class_b_ping_slot_nb: 1,
..Default::default()
},
),
assert::join_event(integration_pb::JoinEvent {
device_info: Some(integration_pb::DeviceInfo {
tenant_id: t.id.to_string(),
tenant_name: t.name.clone(),
application_id: app.id.to_string(),
application_name: app.name.clone(),
device_profile_id: dp.id.to_string(),
device_profile_name: dp.name.clone(),
device_name: dev.name.clone(),
dev_eui: dev.dev_eui.to_string(),
device_class_enabled: common::DeviceClass::ClassA.into(),
..Default::default()
}),
dev_addr: "01020304".into(),
join_server_context: Some(integration_pb::JoinServerContext {
app_s_key: Some(common::KeyEnvelope {
kek_label: "kek-label".into(),
aes_key: vec![1, 2, 3, 4, 5, 6, 7, 8, 1, 2, 3, 4, 5, 6, 7, 8],
}),
..Default::default()
}),
..Default::default()
}),
],
},
];
for tst in &tests {
run_test(tst).await;
}
}
async fn run_test(t: &Test) {
println!("> {}", t.name);
reset_redis().await.unwrap();
let server = MockServer::start();
let mut js_mock = server.mock(|when, then| {
when.method(POST).path("/");
then.body(serde_json::to_string(&t.js_response).unwrap());
});
let mut conf: config::Configuration = (*config::get()).clone();
conf.join_server.servers.push(config::JoinServerServer {
join_eui: EUI64::from_be_bytes([1, 2, 3, 4, 5, 6, 7, 8]),
server: server.url("/"),
..Default::default()
});
config::set(conf);
region::setup().unwrap();
joinserver::setup().unwrap();
integration::set_mock().await;
gateway_backend::set_backend(&"eu868", Box::new(gateway_backend::mock::Backend {})).await;
integration::mock::reset().await;
gateway_backend::mock::reset().await;
uplink::handle_uplink(
Uuid::new_v4(),
gw::UplinkFrameSet {
phy_payload: t.phy_payload.to_vec().unwrap(),
tx_info: Some(t.tx_info.clone()),
rx_info: vec![t.rx_info.clone()],
},
)
.await
.unwrap();
js_mock.assert();
js_mock.delete();
for assert in &t.assert {
assert().await;
}
}

View File

@ -190,6 +190,7 @@ async fn test_fns() {
});
gateway_backend::set_backend(&"eu868", Box::new(gateway_backend::mock::Backend {})).await;
gateway_backend::mock::reset().await;
// Simulate uplink
uplink::handle_uplink(

View File

@ -637,10 +637,11 @@ impl Data {
if f_port == 0 || f_port == lrwn::LA_FPORT_RELAY {
let nwk_s_enc_key = AES128Key::from_slice(&ds.nwk_s_enc_key)?;
self.phy_payload.decrypt_frm_payload(&nwk_s_enc_key)?;
} else if ds.app_s_key.is_some() {
let app_s_key = AES128Key::from_slice(&ds.app_s_key.as_ref().unwrap().aes_key)?;
self.phy_payload.decrypt_frm_payload(&app_s_key)?;
} else if !self._is_end_to_end_encrypted() {
if let Some(app_s_key) = &ds.app_s_key {
let app_s_key = AES128Key::from_slice(&app_s_key.aes_key)?;
self.phy_payload.decrypt_frm_payload(&app_s_key)?;
}
}
Ok(())
@ -935,6 +936,7 @@ impl Data {
let app = self.application.as_ref().unwrap();
let dp = self.device_profile.as_ref().unwrap();
let dev = self.device.as_ref().unwrap();
let ds = self.device_session.as_ref().unwrap();
let mac = if let lrwn::Payload::MACPayload(pl) = &self.phy_payload.payload {
pl
} else {
@ -959,39 +961,52 @@ impl Data {
object: None,
rx_info: self.uplink_frame_set.rx_info_set.clone(),
tx_info: Some(self.uplink_frame_set.tx_info.clone()),
join_server_context: if self._is_end_to_end_encrypted() {
Some(integration_pb::JoinServerContext {
session_key_id: hex::encode(&ds.js_session_key_id),
app_s_key: ds.app_s_key.clone(),
})
} else {
None
},
};
pl.object = match codec::binary_to_struct(
dp.payload_codec_runtime,
ts,
mac.f_port.unwrap_or(0),
&dev.variables,
&dp.payload_codec_script,
&pl.data,
)
.await
{
Ok(v) => v,
Err(e) => {
integration::log_event(
app.id,
&dev.variables,
&integration_pb::LogEvent {
time: Some(Utc::now().into()),
device_info: self.device_info.clone(),
level: integration_pb::LogLevel::Error.into(),
code: integration_pb::LogCode::UplinkCodec.into(),
description: format!("{}", e),
context: [("deduplication_id".to_string(), pl.deduplication_id.clone())]
if !self._is_end_to_end_encrypted() {
pl.object = match codec::binary_to_struct(
dp.payload_codec_runtime,
ts,
mac.f_port.unwrap_or(0),
&dev.variables,
&dp.payload_codec_script,
&pl.data,
)
.await
{
Ok(v) => v,
Err(e) => {
integration::log_event(
app.id,
&dev.variables,
&integration_pb::LogEvent {
time: Some(Utc::now().into()),
device_info: self.device_info.clone(),
level: integration_pb::LogLevel::Error.into(),
code: integration_pb::LogCode::UplinkCodec.into(),
description: format!("{}", e),
context: [(
"deduplication_id".to_string(),
pl.deduplication_id.clone(),
)]
.iter()
.cloned()
.collect(),
},
)
.await;
None
}
};
},
)
.await;
None
}
};
}
integration::uplink_event(app.id, &dev.variables, &pl).await;
@ -1356,4 +1371,20 @@ impl Data {
false
}
fn _is_end_to_end_encrypted(&self) -> bool {
let ds = self.device_session.as_ref().unwrap();
if !ds.js_session_key_id.is_empty() {
return true;
}
if let Some(app_s_key) = &ds.app_s_key {
if !app_s_key.kek_label.is_empty() {
return true;
}
}
false
}
}

View File

@ -52,6 +52,7 @@ pub struct JoinRequest {
s_nwk_s_int_key: Option<AES128Key>,
nwk_s_enc_key: Option<AES128Key>,
app_s_key: Option<common::KeyEnvelope>,
js_session_key_id: Vec<u8>,
}
impl JoinRequest {
@ -108,11 +109,12 @@ impl JoinRequest {
s_nwk_s_int_key: None,
nwk_s_enc_key: None,
app_s_key: None,
js_session_key_id: vec![],
};
ctx.get_join_request_payload()?;
ctx.get_device_or_try_pr_roaming().await?;
ctx.get_js_client()?;
ctx.get_device_keys_or_js_client().await?; // used to validate MIC + if we need external JS
ctx.get_application().await?;
ctx.get_tenant().await?;
ctx.get_device_profile().await?;
@ -165,11 +167,12 @@ impl JoinRequest {
s_nwk_s_int_key: None,
nwk_s_enc_key: None,
app_s_key: None,
js_session_key_id: vec![],
};
ctx.get_join_request_payload_relayed()?;
ctx.get_device().await?;
ctx.get_js_client()?;
ctx.get_device_keys_or_js_client().await?;
ctx.get_application().await?;
ctx.get_tenant().await?;
ctx.get_device_profile().await?;
@ -227,20 +230,6 @@ impl JoinRequest {
Ok(())
}
fn get_js_client(&mut self) -> Result<()> {
let jr = self.join_request.as_ref().unwrap();
trace!(join_eui = %jr.join_eui, "Trying to get Join Server client");
if let Ok(v) = joinserver::get(&jr.join_eui) {
trace!("Found Join Server client");
self.js_client = Some(v);
} else {
trace!("Join Server client does not exist");
}
Ok(())
}
async fn get_device(&mut self) -> Result<()> {
trace!("Getting device");
let jr = self.join_request.as_ref().unwrap();
@ -249,6 +238,29 @@ impl JoinRequest {
Ok(())
}
// We need to get either the device-keys or a JS client. In any other case, this must return an error.
async fn get_device_keys_or_js_client(&mut self) -> Result<()> {
trace!("Getting device keys");
let jr = self.join_request.as_ref().unwrap();
self.device_keys = match device_keys::get(&jr.dev_eui).await {
Ok(v) => Some(v),
Err(e) => {
if let StorageError::NotFound(_) = e {
None
} else {
return Err(anyhow::Error::new(e));
}
}
};
if !self.device_keys.is_some() {
trace!(join_eui = %jr.join_eui, "Getting Join Server client");
self.js_client = Some(joinserver::get(&jr.join_eui)?);
}
Ok(())
}
async fn get_device_or_try_pr_roaming(&mut self) -> Result<()> {
trace!("Getting device");
let jr = self.join_request.as_ref().unwrap();
@ -391,8 +403,7 @@ impl JoinRequest {
}
async fn validate_mic(&self) -> Result<()> {
let join_request = self.join_request.as_ref().unwrap();
let device_keys = device_keys::get(&join_request.dev_eui).await?;
let device_keys = self.device_keys.as_ref().unwrap();
if let Some(relay_ctx) = self.relay_context.as_ref() {
if relay_ctx
@ -571,6 +582,7 @@ impl JoinRequest {
aes_key: v.aes_key.clone(),
});
}
self.js_session_key_id = join_ans_pl.session_key_id.clone();
if let Some(v) = &join_ans_pl.nwk_s_key {
let key = keywrap::unwrap(v).context("Unwrap nwk_s_key")?;
@ -776,6 +788,7 @@ impl JoinRequest {
s_nwk_s_int_key: self.s_nwk_s_int_key.as_ref().unwrap().to_vec(),
nwk_s_enc_key: self.nwk_s_enc_key.as_ref().unwrap().to_vec(),
app_s_key: self.app_s_key.clone(),
js_session_key_id: self.js_session_key_id.clone(),
rx1_delay: region_network.rx1_delay.into(),
rx1_dr_offset: region_network.rx1_dr_offset.into(),
rx2_dr: region_network.rx2_dr.into(),
@ -928,6 +941,26 @@ impl JoinRequest {
device_info: self.device_info.clone(),
relay_rx_info: self.relay_rx_info.clone(),
dev_addr: self.dev_addr.as_ref().unwrap().to_string(),
join_server_context: if !self.js_session_key_id.is_empty() {
Some(integration_pb::JoinServerContext {
app_s_key: None,
session_key_id: hex::encode(&self.js_session_key_id),
})
} else if let Some(app_s_key) = &self.app_s_key {
if app_s_key.kek_label.is_empty() {
None
} else {
Some(integration_pb::JoinServerContext {
app_s_key: Some(common::KeyEnvelope {
kek_label: app_s_key.kek_label.clone(),
aes_key: app_s_key.aes_key.clone(),
}),
session_key_id: "".into(),
})
}
} else {
None
},
};
integration::join_event(app.id, &dev.variables, &pl).await;

View File

@ -39,6 +39,7 @@ pub struct JoinRequest {
s_nwk_s_int_key: Option<AES128Key>,
nwk_s_enc_key: Option<AES128Key>,
app_s_key: Option<common::KeyEnvelope>,
js_session_key_id: String,
}
impl JoinRequest {
@ -76,11 +77,12 @@ impl JoinRequest {
s_nwk_s_int_key: None,
nwk_s_enc_key: None,
app_s_key: None,
js_session_key_id: "".to_string(),
};
ctx.get_join_request_payload()?;
ctx.get_device().await?;
ctx.get_js_client()?;
ctx.get_device_keys_or_js_client().await?;
ctx.get_application().await?;
ctx.get_tenant().await?;
ctx.get_device_profile().await?;
@ -128,15 +130,24 @@ impl JoinRequest {
Ok(())
}
fn get_js_client(&mut self) -> Result<()> {
// We need to get either the device-keys or a JS client. In any other case, this must return an error.
async fn get_device_keys_or_js_client(&mut self) -> Result<()> {
trace!("Getting device keys");
let jr = self.join_request.as_ref().unwrap();
self.device_keys = match device_keys::get(&jr.dev_eui).await {
Ok(v) => Some(v),
Err(e) => {
if let StorageError::NotFound(_) = e {
None
} else {
return Err(anyhow::Error::new(e));
}
}
};
trace!(join_eui = %jr.join_eui, "Trying to get Join Server client");
if let Ok(v) = joinserver::get(&jr.join_eui) {
trace!("Found Join Server client");
self.js_client = Some(v);
} else {
trace!("Join Server client does not exist");
if !self.device_keys.is_some() {
trace!(join_eui = %jr.join_eui, "Getting Join Server client");
self.js_client = Some(joinserver::get(&jr.join_eui)?);
}
Ok(())
@ -258,6 +269,7 @@ impl JoinRequest {
aes_key: v.aes_key.clone(),
});
}
self.js_session_key_id = hex::encode(join_ans_pl.session_key_id);
if let Some(v) = &join_ans_pl.nwk_s_key {
let key = keywrap::unwrap(v).context("Unwrap nwk_s_key")?;
@ -289,8 +301,7 @@ impl JoinRequest {
}
async fn validate_mic(&self) -> Result<()> {
let join_request = self.join_request.as_ref().unwrap();
let device_keys = device_keys::get(&join_request.dev_eui).await?;
let device_keys = self.device_keys.as_ref().unwrap();
if self
.uplink_frame_set
@ -678,6 +689,26 @@ impl JoinRequest {
device_info: self.device_info.clone(),
relay_rx_info: None,
dev_addr: self.dev_addr.as_ref().unwrap().to_string(),
join_server_context: if !self.js_session_key_id.is_empty() {
Some(integration_pb::JoinServerContext {
app_s_key: None,
session_key_id: self.js_session_key_id.clone(),
})
} else if let Some(app_s_key) = &self.app_s_key {
if app_s_key.kek_label.is_empty() {
None
} else {
Some(integration_pb::JoinServerContext {
app_s_key: Some(common::KeyEnvelope {
kek_label: app_s_key.kek_label.clone(),
aes_key: app_s_key.aes_key.clone(),
}),
session_key_id: "".to_string(),
})
}
} else {
None
},
};
integration::join_event(app.id, &dev.variables, &pl).await;

View File

@ -2,7 +2,7 @@ import React, { useState } from "react";
import { Struct } from "google-protobuf/google/protobuf/struct_pb";
import { notification } from "antd";
import { Switch, notification } from "antd";
import { Button, Tabs, Space, Card, Row, Form, Input, InputNumber, Checkbox, Popconfirm } from "antd";
import { ColumnsType } from "antd/es/table";
import { RedoOutlined, DeleteOutlined } from "@ant-design/icons";
@ -28,6 +28,7 @@ interface IProps {
function DeviceQueue(props: IProps) {
const [refreshCounter, setRefreshCounter] = useState<number>(0);
const [isEncrypted, setIsEncrypted] = useState<boolean>(false);
const [form] = Form.useForm();
const columns: ColumnsType<DeviceQueueItem.AsObject> = [
@ -38,7 +39,7 @@ function DeviceQueue(props: IProps) {
width: 350,
},
{
title: "Is pending",
title: "Pending",
dataIndex: "isPending",
key: "isPending",
width: 100,
@ -50,13 +51,26 @@ function DeviceQueue(props: IProps) {
}
},
},
{
title: "Encrypted",
dataIndex: "isEncrypted",
key: "isEncrypted",
width: 100,
render: (text, record) => {
if (record.isEncrypted) {
return "yes";
} else {
return "no";
}
},
},
{
title: "Frame-counter",
dataIndex: "fCntDown",
key: "fCntDown",
width: 200,
render: (text, record) => {
if (record.isPending === true) {
if (record.isPending === true || record.isEncrypted === true) {
return record.fCntDown;
} else {
return "";
@ -121,6 +135,8 @@ function DeviceQueue(props: IProps) {
item.setDevEui(props.device.getDevEui());
item.setFPort(values.fPort);
item.setConfirmed(values.confirmed);
item.setIsEncrypted(values.isEncrypted);
item.setFCntDown(values.fCntDown);
if (values.hex !== undefined) {
item.setData(new Uint8Array(Buffer.from(values.hex, "hex")));
@ -151,6 +167,7 @@ function DeviceQueue(props: IProps) {
DeviceStore.enqueue(req, _ => {
form.resetFields();
setIsEncrypted(false);
refreshQueue();
});
};
@ -162,11 +179,26 @@ function DeviceQueue(props: IProps) {
<Row>
<Space direction="horizontal" style={{ width: "100%" }} size="large">
<Form.Item name="confirmed" label="Confirmed" valuePropName="checked">
<Checkbox />
<Switch />
</Form.Item>
<Form.Item name="fPort" label="FPort">
<InputNumber min={1} max={254} />
</Form.Item>
<Form.Item
name="isEncrypted"
label="Is encrypted"
valuePropName="checked"
tooltip="Only enable this in case the payload that you would like to enqueue has already been encrypted. In this case you also must enter the downlink frame-counter which has been used for the encryption."
>
<Switch onChange={setIsEncrypted} />
</Form.Item>
{isEncrypted && (<Form.Item
name="fCntDown"
label="Downlink frame-counter used for encryption"
rules={[{ required: true, message: "Please enter a downlink frame-counter!" }]}
>
<InputNumber min={0} />
</Form.Item>)}
</Space>
</Row>
<Tabs defaultActiveKey="1">