Skip to content

Commit 202f100

Browse files
committed
is: Add Count RPC to EndDevice registry
1 parent aca2d66 commit 202f100

14 files changed

Lines changed: 1404 additions & 651 deletions

api/ttn/lorawan/v3/api.md

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -249,6 +249,8 @@
249249
- [Message `BatchUpdateEndDeviceLastSeenRequest.EndDeviceLastSeenUpdate`](#ttn.lorawan.v3.BatchUpdateEndDeviceLastSeenRequest.EndDeviceLastSeenUpdate)
250250
- [Message `BoolValue`](#ttn.lorawan.v3.BoolValue)
251251
- [Message `ConvertEndDeviceTemplateRequest`](#ttn.lorawan.v3.ConvertEndDeviceTemplateRequest)
252+
- [Message `CountEndDevicesRequest`](#ttn.lorawan.v3.CountEndDevicesRequest)
253+
- [Message `CountEndDevicesResponse`](#ttn.lorawan.v3.CountEndDevicesResponse)
252254
- [Message `CreateEndDeviceRequest`](#ttn.lorawan.v3.CreateEndDeviceRequest)
253255
- [Message `DevAddrPrefix`](#ttn.lorawan.v3.DevAddrPrefix)
254256
- [Message `EndDevice`](#ttn.lorawan.v3.EndDevice)
@@ -3984,6 +3986,24 @@ Configuration options for static ADR.
39843986
| ----- | ----------- |
39853987
| `format_id` | <p>`string.max_len`: `36`</p><p>`string.pattern`: `^[a-z0-9](?:[-]?[a-z0-9]){2,}$`</p> |
39863988

3989+
### <a name="ttn.lorawan.v3.CountEndDevicesRequest">Message `CountEndDevicesRequest`</a>
3990+
3991+
| Field | Type | Label | Description |
3992+
| ----- | ---- | ----- | ----------- |
3993+
| `application_ids` | [`ApplicationIdentifiers`](#ttn.lorawan.v3.ApplicationIdentifiers) | | |
3994+
3995+
#### Field Rules
3996+
3997+
| Field | Validations |
3998+
| ----- | ----------- |
3999+
| `application_ids` | <p>`message.required`: `true`</p> |
4000+
4001+
### <a name="ttn.lorawan.v3.CountEndDevicesResponse">Message `CountEndDevicesResponse`</a>
4002+
4003+
| Field | Type | Label | Description |
4004+
| ----- | ---- | ----- | ----------- |
4005+
| `count` | [`uint32`](#uint32) | | |
4006+
39874007
### <a name="ttn.lorawan.v3.CreateEndDeviceRequest">Message `CreateEndDeviceRequest`</a>
39884008

39894009
| Field | Type | Label | Description |
@@ -4854,6 +4874,7 @@ NsEndDeviceRegistry, the AsEndDeviceRegistry and the JsEndDeviceRegistry.
48544874
| `Get` | [`GetEndDeviceRequest`](#ttn.lorawan.v3.GetEndDeviceRequest) | [`EndDevice`](#ttn.lorawan.v3.EndDevice) | Get the end device with the given identifiers, selecting the fields specified in the field mask. More or less fields may be returned, depending on the rights of the caller. |
48554875
| `GetIdentifiersForEUIs` | [`GetEndDeviceIdentifiersForEUIsRequest`](#ttn.lorawan.v3.GetEndDeviceIdentifiersForEUIsRequest) | [`EndDeviceIdentifiers`](#ttn.lorawan.v3.EndDeviceIdentifiers) | Get the identifiers of the end device that has the given EUIs registered. |
48564876
| `List` | [`ListEndDevicesRequest`](#ttn.lorawan.v3.ListEndDevicesRequest) | [`EndDevices`](#ttn.lorawan.v3.EndDevices) | List end devices in the given application. Similar to Get, this selects the fields given by the field mask. More or less fields may be returned, depending on the rights of the caller. |
4877+
| `Count` | [`CountEndDevicesRequest`](#ttn.lorawan.v3.CountEndDevicesRequest) | [`CountEndDevicesResponse`](#ttn.lorawan.v3.CountEndDevicesResponse) | Count end devices in the given application. |
48574878
| `Update` | [`UpdateEndDeviceRequest`](#ttn.lorawan.v3.UpdateEndDeviceRequest) | [`EndDevice`](#ttn.lorawan.v3.EndDevice) | Update the end device, changing the fields specified by the field mask to the provided values. |
48584879
| `BatchUpdateLastSeen` | [`BatchUpdateEndDeviceLastSeenRequest`](#ttn.lorawan.v3.BatchUpdateEndDeviceLastSeenRequest) | [`.google.protobuf.Empty`](#google.protobuf.Empty) | Update the last seen timestamp for a batch of end devices. |
48594880
| `Delete` | [`EndDeviceIdentifiers`](#ttn.lorawan.v3.EndDeviceIdentifiers) | [`.google.protobuf.Empty`](#google.protobuf.Empty) | Delete the end device with the given IDs. Before deleting an end device it first needs to be deleted from the NsEndDeviceRegistry, the AsEndDeviceRegistry and the JsEndDeviceRegistry. In addition, if the device claimed on a Join Server, it also needs to be unclaimed via the DeviceClaimingServer so it can be claimed in the future. This is NOT done automatically. |
@@ -4866,6 +4887,7 @@ NsEndDeviceRegistry, the AsEndDeviceRegistry and the JsEndDeviceRegistry.
48664887
| `Get` | `GET` | `/api/v3/applications/{end_device_ids.application_ids.application_id}/devices/{end_device_ids.device_id}` | |
48674888
| `List` | `GET` | `/api/v3/applications/{application_ids.application_id}/devices` | |
48684889
| `List` | `POST` | `/api/v3/applications/{application_ids.application_id}/devices/filter` | `*` |
4890+
| `Count` | `GET` | `/api/v3/applications/{application_ids.application_id}/devices/count` | |
48694891
| `Update` | `PUT` | `/api/v3/applications/{end_device.ids.application_ids.application_id}/devices/{end_device.ids.device_id}` | `*` |
48704892
| `Delete` | `DELETE` | `/api/v3/applications/{application_ids.application_id}/devices/{device_id}` | |
48714893

api/ttn/lorawan/v3/api.swagger.json

Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1185,6 +1185,37 @@
11851185
]
11861186
}
11871187
},
1188+
"/applications/{application_ids.application_id}/devices/count": {
1189+
"get": {
1190+
"summary": "Count end devices in the given application.",
1191+
"operationId": "EndDeviceRegistry_Count",
1192+
"responses": {
1193+
"200": {
1194+
"description": "A successful response.",
1195+
"schema": {
1196+
"$ref": "#/definitions/v3CountEndDevicesResponse"
1197+
}
1198+
},
1199+
"default": {
1200+
"description": "An unexpected error response.",
1201+
"schema": {
1202+
"$ref": "#/definitions/googlerpcStatus"
1203+
}
1204+
}
1205+
},
1206+
"parameters": [
1207+
{
1208+
"name": "application_ids.application_id",
1209+
"in": "path",
1210+
"required": true,
1211+
"type": "string"
1212+
}
1213+
],
1214+
"tags": [
1215+
"EndDeviceRegistry"
1216+
]
1217+
}
1218+
},
11881219
"/applications/{application_ids.application_id}/devices/filter": {
11891220
"post": {
11901221
"summary": "List end devices in the given application.\nSimilar to Get, this selects the fields given by the field mask.\nMore or less fields may be returned, depending on the rights of the caller.",
@@ -22870,6 +22901,15 @@
2287022901
}
2287122902
}
2287222903
},
22904+
"v3CountEndDevicesResponse": {
22905+
"type": "object",
22906+
"properties": {
22907+
"count": {
22908+
"type": "integer",
22909+
"format": "int64"
22910+
}
22911+
}
22912+
},
2287322913
"v3CreateLoginTokenResponse": {
2287422914
"type": "object",
2287522915
"properties": {

api/ttn/lorawan/v3/end_device.proto

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1346,6 +1346,14 @@ message ListEndDevicesRequest {
13461346
repeated Filter filters = 6;
13471347
}
13481348

1349+
message CountEndDevicesRequest {
1350+
ApplicationIdentifiers application_ids = 1 [(validate.rules).message.required = true];
1351+
}
1352+
1353+
message CountEndDevicesResponse {
1354+
uint32 count = 1;
1355+
}
1356+
13491357
message SetEndDeviceRequest {
13501358
EndDevice end_device = 1 [(validate.rules).message.required = true];
13511359
// The names of the end device fields that should be updated.

api/ttn/lorawan/v3/end_device_services.proto

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -72,6 +72,11 @@ service EndDeviceRegistry {
7272
};
7373
}
7474

75+
// Count end devices in the given application.
76+
rpc Count(CountEndDevicesRequest) returns (CountEndDevicesResponse) {
77+
option (google.api.http) = {get: "/applications/{application_ids.application_id}/devices/count"};
78+
}
79+
7580
// Update the end device, changing the fields specified by the field mask to the provided values.
7681
rpc Update(UpdateEndDeviceRequest) returns (EndDevice) {
7782
option (google.api.http) = {

pkg/identityserver/end_device_registry.go

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@ import (
1818
"context"
1919
"encoding/hex"
2020
"fmt"
21+
"math"
2122
"net"
2223
"net/url"
2324
"strings"
@@ -332,6 +333,27 @@ func (is *IdentityServer) listEndDevices(ctx context.Context, req *ttnpb.ListEnd
332333
return devs, nil
333334
}
334335

336+
func (is *IdentityServer) countEndDevices(
337+
ctx context.Context, req *ttnpb.CountEndDevicesRequest,
338+
) (*ttnpb.CountEndDevicesResponse, error) {
339+
if err := rights.RequireApplication(
340+
ctx, req.GetApplicationIds(), ttnpb.Right_RIGHT_APPLICATION_DEVICES_READ,
341+
); err != nil {
342+
return nil, err
343+
}
344+
var count uint64
345+
err := is.store.Transact(ctx, func(ctx context.Context, st store.Store) (err error) {
346+
count, err = st.CountEndDevices(ctx, req.GetApplicationIds())
347+
return err
348+
})
349+
if err != nil {
350+
return nil, err
351+
}
352+
return &ttnpb.CountEndDevicesResponse{
353+
Count: uint32(min(count, math.MaxUint32)), // #nosec G115 -- bounded by min
354+
}, nil
355+
}
356+
335357
func (is *IdentityServer) setFullEndDevicePictureURL(ctx context.Context, dev *ttnpb.EndDevice) {
336358
bucketURL := is.configFromContext(ctx).EndDevicePicture.BucketURL
337359
if bucketURL == "" {
@@ -591,6 +613,12 @@ func (dr *endDeviceRegistry) Delete(ctx context.Context, req *ttnpb.EndDeviceIde
591613
return dr.deleteEndDevice(ctx, req)
592614
}
593615

616+
func (dr *endDeviceRegistry) Count(
617+
ctx context.Context, req *ttnpb.CountEndDevicesRequest,
618+
) (*ttnpb.CountEndDevicesResponse, error) {
619+
return dr.countEndDevices(ctx, req)
620+
}
621+
594622
func (reg *endDeviceBatchRegistry) Delete(
595623
ctx context.Context,
596624
req *ttnpb.BatchDeleteEndDevicesRequest,

0 commit comments

Comments
 (0)